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,
|
||||
rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
|
||||
rhoverHack = /\bhover(\.\S+)?/,
|
||||
rkeyEvent = /^key/,
|
||||
rmouseEvent = /^(?:mouse|contextmenu)|click/,
|
||||
rquickIs = /^([\w\-]+)?(?:#([\w\-]+))?(?:\.([\w\-]+))?(?:\[([\w+\-]+)=["']?([\w\-]*)["']?\])?$/,
|
||||
quickParse = function( selector ) {
|
||||
var quick = rquickIs.exec( selector );
|
||||
@ -407,12 +409,6 @@ jQuery.event = {
|
||||
// Make a writable jQuery.Event from the native event object
|
||||
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 ] || []),
|
||||
delegateCount = handlers.delegateCount,
|
||||
args = Array.prototype.slice.call( arguments, 0 ),
|
||||
@ -469,55 +465,89 @@ jQuery.event = {
|
||||
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: {},
|
||||
|
||||
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 ) {
|
||||
if ( event[ jQuery.expando ] ) {
|
||||
return event;
|
||||
}
|
||||
|
||||
// store a copy of the original event object
|
||||
// and "clone" to set read-only properties
|
||||
// Create a writable copy of the event object and normalize some properties
|
||||
var originalEvent = event,
|
||||
propHook = jQuery.event.propHooks[ event.type ],
|
||||
copy = this.props;
|
||||
propHook = jQuery.event.propHooks[ event.type ] || {},
|
||||
copy = propHook.props? this.props.concat( propHook.props ) : this.props;
|
||||
|
||||
event = jQuery.Event( originalEvent );
|
||||
|
||||
if ( propHook ) {
|
||||
copy.push.apply( copy, propHook() || [] );
|
||||
}
|
||||
|
||||
for ( var i = copy.length, prop; i; ) {
|
||||
prop = copy[ --i ];
|
||||
event[ prop ] = originalEvent[ prop ];
|
||||
}
|
||||
|
||||
// Fix target property, if necessary
|
||||
// Removal will crash IE6,7,8
|
||||
// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
|
||||
if ( !event.target ) {
|
||||
// Fixes #1925 where srcElement might not be defined either
|
||||
event.target = event.srcElement || document;
|
||||
event.target = originalEvent.srcElement || document;
|
||||
}
|
||||
|
||||
// check if target is a textnode (safari)
|
||||
// Removal will crash IE6,7,8
|
||||
// Target should not be a text node (#504, Safari)
|
||||
if ( event.target.nodeType === 3 ) {
|
||||
event.target = event.target.parentNode;
|
||||
}
|
||||
|
||||
// Add relatedTarget, if necessary
|
||||
if ( !event.relatedTarget && event.fromElement ) {
|
||||
event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
|
||||
// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
|
||||
if ( event.metaKey === undefined ) {
|
||||
event.metaKey = event.ctrlKey;
|
||||
}
|
||||
|
||||
if ( propHook ) {
|
||||
event = propHook( event, originalEvent );
|
||||
}
|
||||
|
||||
return event;
|
||||
return propHook.filter? propHook.filter( event, originalEvent ) : event;
|
||||
},
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Key Event property hooks
|
||||
if ( rkeyEvent.test( name ) ) {
|
||||
jQuery.event.propHooks[ name ] = function( event, original ) {
|
||||
|
||||
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;
|
||||
};
|
||||
jQuery.event.propHooks[ name ] = jQuery.event.keyHooks;
|
||||
}
|
||||
|
||||
// Mouse Event property hooks
|
||||
if ( rmouseEvent.test( name ) ) {
|
||||
jQuery.event.propHooks[ name ] = function( event, original ) {
|
||||
|
||||
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.event.propHooks[ name ] = jQuery.event.mouseHooks;
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery );
|
||||
|
||||
|
@ -2383,6 +2383,38 @@ test("delegated events quickIs", function() {
|
||||
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(){
|
||||
// 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