mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
propHooks now an object with props
array and filter
function.
Use the originalEvent to grab properties in filter functions since they often won't have been copied to event. Mark a few current props in the main jQuery.event.props list as deprecated, they aren't supported across all browsers.
This commit is contained in:
parent
ae27424b30
commit
b4120a7430
140
src/event.js
140
src/event.js
@ -7,6 +7,8 @@ var rnamespaces = /\.(.*)$/,
|
|||||||
rescape = /[^\w\s.|`]/g,
|
rescape = /[^\w\s.|`]/g,
|
||||||
rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
|
rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
|
||||||
rhoverHack = /\bhover(\.\S+)?/,
|
rhoverHack = /\bhover(\.\S+)?/,
|
||||||
|
rkeyEvent = /^key/,
|
||||||
|
rmouseEvent = /^(?:mouse|contextmenu)|click/,
|
||||||
rquickIs = /^([\w\-]+)?(?:#([\w\-]+))?(?:\.([\w\-]+))?(?:\[([\w+\-]+)=["']?([\w\-]*)["']?\])?$/,
|
rquickIs = /^([\w\-]+)?(?:#([\w\-]+))?(?:\.([\w\-]+))?(?:\[([\w+\-]+)=["']?([\w\-]*)["']?\])?$/,
|
||||||
quickParse = function( selector ) {
|
quickParse = function( selector ) {
|
||||||
var quick = rquickIs.exec( selector );
|
var quick = rquickIs.exec( selector );
|
||||||
@ -407,12 +409,6 @@ jQuery.event = {
|
|||||||
// Make a writable jQuery.Event from the native event object
|
// Make a writable jQuery.Event from the native event object
|
||||||
event = jQuery.event.fix( event || window.event );
|
event = jQuery.event.fix( event || window.event );
|
||||||
|
|
||||||
var propHook = jQuery.event.propHooks[ event.type ];
|
|
||||||
|
|
||||||
if ( propHook ) {
|
|
||||||
event = propHook( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []),
|
var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []),
|
||||||
delegateCount = handlers.delegateCount,
|
delegateCount = handlers.delegateCount,
|
||||||
args = Array.prototype.slice.call( arguments, 0 ),
|
args = Array.prototype.slice.call( arguments, 0 ),
|
||||||
@ -469,55 +465,89 @@ jQuery.event = {
|
|||||||
return event.result;
|
return event.result;
|
||||||
},
|
},
|
||||||
|
|
||||||
props: "altKey attrName bubbles button cancelable charCode ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view which".split(" "),
|
// Includes some event props shared by KeyEvent and MouseEvent
|
||||||
|
// *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
|
||||||
|
props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp type view which".split(" "),
|
||||||
|
|
||||||
propHooks: {},
|
propHooks: {},
|
||||||
|
|
||||||
|
keyHooks: {
|
||||||
|
props: "char charCode key keyCode".split(" "),
|
||||||
|
filter: function( event, original ) {
|
||||||
|
|
||||||
|
// Add which for key events
|
||||||
|
if ( event.which == null ) {
|
||||||
|
event.which = original.charCode != null ? original.charCode : original.keyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mouseHooks: {
|
||||||
|
props: "button buttons clientX clientY fromElement layerX layerY offsetX offsetY pageX pageY screenX screenY toElement wheelDelta".split(" "),
|
||||||
|
filter: function( event, original ) {
|
||||||
|
var eventDoc, doc, body,
|
||||||
|
button = original.button;
|
||||||
|
|
||||||
|
// Calculate pageX/Y if missing and clientX/Y available
|
||||||
|
if ( event.pageX == null && original.clientX != null ) {
|
||||||
|
eventDoc = event.target.ownerDocument || document;
|
||||||
|
doc = eventDoc.documentElement;
|
||||||
|
body = eventDoc.body;
|
||||||
|
|
||||||
|
event.pageX = original.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
|
||||||
|
event.pageY = original.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add relatedTarget, if necessary
|
||||||
|
if ( !event.relatedTarget && original.fromElement ) {
|
||||||
|
event.relatedTarget = original.fromElement === event.target ? original.toElement : original.fromElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add which for click: 1 === left; 2 === middle; 3 === right
|
||||||
|
// Note: button is not normalized, so don't use it
|
||||||
|
if ( !event.which && button !== undefined ) {
|
||||||
|
event.which = (button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ));
|
||||||
|
}
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
fix: function( event ) {
|
fix: function( event ) {
|
||||||
if ( event[ jQuery.expando ] ) {
|
if ( event[ jQuery.expando ] ) {
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store a copy of the original event object
|
// Create a writable copy of the event object and normalize some properties
|
||||||
// and "clone" to set read-only properties
|
|
||||||
var originalEvent = event,
|
var originalEvent = event,
|
||||||
propHook = jQuery.event.propHooks[ event.type ],
|
propHook = jQuery.event.propHooks[ event.type ] || {},
|
||||||
copy = this.props;
|
copy = propHook.props? this.props.concat( propHook.props ) : this.props;
|
||||||
|
|
||||||
event = jQuery.Event( originalEvent );
|
event = jQuery.Event( originalEvent );
|
||||||
|
|
||||||
if ( propHook ) {
|
|
||||||
copy.push.apply( copy, propHook() || [] );
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( var i = copy.length, prop; i; ) {
|
for ( var i = copy.length, prop; i; ) {
|
||||||
prop = copy[ --i ];
|
prop = copy[ --i ];
|
||||||
event[ prop ] = originalEvent[ prop ];
|
event[ prop ] = originalEvent[ prop ];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix target property, if necessary
|
// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
|
||||||
// Removal will crash IE6,7,8
|
|
||||||
if ( !event.target ) {
|
if ( !event.target ) {
|
||||||
// Fixes #1925 where srcElement might not be defined either
|
event.target = originalEvent.srcElement || document;
|
||||||
event.target = event.srcElement || document;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if target is a textnode (safari)
|
// Target should not be a text node (#504, Safari)
|
||||||
// Removal will crash IE6,7,8
|
|
||||||
if ( event.target.nodeType === 3 ) {
|
if ( event.target.nodeType === 3 ) {
|
||||||
event.target = event.target.parentNode;
|
event.target = event.target.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add relatedTarget, if necessary
|
// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
|
||||||
if ( !event.relatedTarget && event.fromElement ) {
|
if ( event.metaKey === undefined ) {
|
||||||
event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
|
event.metaKey = event.ctrlKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( propHook ) {
|
return propHook.filter? propHook.filter( event, originalEvent ) : event;
|
||||||
event = propHook( event, originalEvent );
|
|
||||||
}
|
|
||||||
|
|
||||||
return event;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Deprecated, use jQuery.guid instead
|
// Deprecated, use jQuery.guid instead
|
||||||
@ -1026,58 +1056,14 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
|
|||||||
jQuery.attrFn[ name ] = true;
|
jQuery.attrFn[ name ] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key Event property hooks
|
|
||||||
if ( rkeyEvent.test( name ) ) {
|
if ( rkeyEvent.test( name ) ) {
|
||||||
jQuery.event.propHooks[ name ] = function( event, original ) {
|
jQuery.event.propHooks[ name ] = jQuery.event.keyHooks;
|
||||||
|
|
||||||
var charCode = event.charCode,
|
|
||||||
keyCode = event.keyCode,
|
|
||||||
ctrlKey = event.ctrlKey;
|
|
||||||
|
|
||||||
// Add which for key events
|
|
||||||
if ( event.which == null && (charCode != null || keyCode != null) ) {
|
|
||||||
event.which = charCode != null ? charCode : keyCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
|
|
||||||
if ( !event.metaKey && ctrlKey ) {
|
|
||||||
event.metaKey = ctrlKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
return event;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mouse Event property hooks
|
|
||||||
if ( rmouseEvent.test( name ) ) {
|
if ( rmouseEvent.test( name ) ) {
|
||||||
jQuery.event.propHooks[ name ] = function( event, original ) {
|
jQuery.event.propHooks[ name ] = jQuery.event.mouseHooks;
|
||||||
|
}
|
||||||
if ( !event ) {
|
});
|
||||||
return mouseProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
var eventDoc, doc, body,
|
|
||||||
button = event.button;
|
|
||||||
|
|
||||||
// Calculate pageX/Y if missing and clientX/Y available
|
|
||||||
if ( event.pageX == null && event.clientX != null ) {
|
|
||||||
eventDoc = event.target.ownerDocument || document;
|
|
||||||
doc = eventDoc.documentElement;
|
|
||||||
body = eventDoc.body;
|
|
||||||
|
|
||||||
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
|
|
||||||
event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add which for click: 1 === left; 2 === middle; 3 === right
|
|
||||||
// Note: button is not normalized, so don't use it
|
|
||||||
if ( !event.which && button !== undefined ) {
|
|
||||||
event.which = (button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ));
|
|
||||||
}
|
|
||||||
|
|
||||||
return event;
|
|
||||||
};
|
|
||||||
}});
|
|
||||||
|
|
||||||
})( jQuery );
|
})( jQuery );
|
||||||
|
|
||||||
|
@ -2383,6 +2383,38 @@ test("delegated events quickIs", function() {
|
|||||||
markup.remove();
|
markup.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("propHooks extensions", function() {
|
||||||
|
expect( 3 );
|
||||||
|
|
||||||
|
jQuery( "<a id='hook-fixture' href=''></a>" ).appendTo( "#qunit-fixture" );
|
||||||
|
|
||||||
|
var $fixture = jQuery( "#hook-fixture" );
|
||||||
|
|
||||||
|
// Ensure the property doesn't exist
|
||||||
|
$fixture.bind( "focus", function( event ) {
|
||||||
|
ok( !("blurrinessLevel" in event), "event.blurrinessLevel does not exist" );
|
||||||
|
})[0].focus();
|
||||||
|
|
||||||
|
// Must blur the link so focus works below
|
||||||
|
$fixture.unbind( "focus" )[0].blur();
|
||||||
|
|
||||||
|
// Define a custom property for "focus" events via the filter function
|
||||||
|
ok( !jQuery.event.propHooks.focus, "We aren't clobbering an existing focus hook" );
|
||||||
|
jQuery.event.propHooks.focus = {
|
||||||
|
filter: function( event, originalEvent ) {
|
||||||
|
event.blurrinessLevel = 42;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Trigger a native focus and ensure the property is set
|
||||||
|
$fixture.bind( "focus", function( event ) {
|
||||||
|
equals( event.blurrinessLevel, 42, "event.blurrinessLevel was set" );
|
||||||
|
})[0].focus();
|
||||||
|
|
||||||
|
delete jQuery.event.propHooks.focus;
|
||||||
|
$fixture.unbind( "focus" ).remove();
|
||||||
|
});
|
||||||
|
|
||||||
(function(){
|
(function(){
|
||||||
// This code must be run before DOM ready!
|
// This code must be run before DOM ready!
|
||||||
@ -2457,72 +2489,4 @@ test("delegated events quickIs", function() {
|
|||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
test("jQuery.event.propHooks", function() {
|
|
||||||
expect( 1 );
|
|
||||||
ok( jQuery.event.propHooks, "jQuery.event.propHooks exists" );
|
|
||||||
});
|
|
||||||
|
|
||||||
test("jQuery.event.propHooks as function", function() {
|
|
||||||
|
|
||||||
expect( 2 );
|
|
||||||
|
|
||||||
jQuery( "<div id='hook-fixture'></div>" ).appendTo( "#qunit-fixture" );
|
|
||||||
|
|
||||||
var $fixture = jQuery( "#hook-fixture" );
|
|
||||||
|
|
||||||
// Does not exist
|
|
||||||
$fixture.bind( "click", function( event ) {
|
|
||||||
ok( !("propC" in event), "event.propC Does not exist" );
|
|
||||||
}).trigger( "click" );
|
|
||||||
|
|
||||||
$fixture.unbind( "click" );
|
|
||||||
|
|
||||||
// Store as function
|
|
||||||
jQuery.event.propHooks[ "custom" ] = function( event ) {
|
|
||||||
// receives the event object for processing
|
|
||||||
event.propC = true;
|
|
||||||
return event;
|
|
||||||
};
|
|
||||||
|
|
||||||
$fixture.bind( "custom", function( event ) {
|
|
||||||
ok( event.propC, "event.propC exists" );
|
|
||||||
}).trigger( "custom" );
|
|
||||||
});
|
|
||||||
|
|
||||||
test("jQuery.event.propHooks usecase", function() {
|
|
||||||
|
|
||||||
expect( 3 );
|
|
||||||
|
|
||||||
jQuery( "<div id='hook-fixture'></div>" ).appendTo( "#qunit-fixture" );
|
|
||||||
|
|
||||||
var $fixture = jQuery( "#hook-fixture" );
|
|
||||||
|
|
||||||
$fixture.bind( "fakedrop", function( event ) {
|
|
||||||
ok( !("dataTransfer" in event), "event.dataTransfer is not available" );
|
|
||||||
}).trigger( "fakedrop" );
|
|
||||||
|
|
||||||
$fixture.unbind( "fakedrop" );
|
|
||||||
|
|
||||||
jQuery.event.propHooks[ "fakedrop" ] = function( event ) {
|
|
||||||
event.dataTransfer = "some val";
|
|
||||||
return event;
|
|
||||||
};
|
|
||||||
|
|
||||||
$fixture.bind( "fakedrop", function( event ) {
|
|
||||||
ok( ("dataTransfer" in event), "event.dataTransfer exists, just copied" );
|
|
||||||
equal( event.dataTransfer, "some val", "event.dataTransfer equal 'some val'" );
|
|
||||||
}).trigger( "fakedrop" );
|
|
||||||
|
|
||||||
$fixture.unbind( "fakedrop" );
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
test("event properties", function() {
|
|
||||||
stop();
|
|
||||||
jQuery("#simon1").click(function(event) {
|
|
||||||
ok( event.timeStamp, "assert event.timeStamp is present" );
|
|
||||||
start();
|
|
||||||
}).click();
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user