Fixing $.proxy to work like (and use) Function.prototype.bind (ticket #7783)

http://bugs.jquery.com/ticket/7783
This commit is contained in:
Gianni Chiappetta 2010-12-14 21:53:04 -05:00
parent c9c9057c4d
commit 9f8cd6c499
3 changed files with 65 additions and 39 deletions

View file

@ -891,6 +891,8 @@ if ( document.addEventListener ) {
jQuery.each(["bind", "one"], function( i, name ) {
jQuery.fn[ name ] = function( type, data, fn ) {
var handler;
// Handle object literals
if ( typeof type === "object" ) {
for ( var key in type ) {
@ -904,10 +906,15 @@ jQuery.each(["bind", "one"], function( i, name ) {
data = undefined;
}
var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
jQuery( this ).unbind( event, handler );
return fn.apply( this, arguments );
}) : fn;
if ( name === "one" ) {
handler = function( event ) {
jQuery( this ).unbind( event, handler );
return fn.apply( this, arguments );
};
handler.guid = fn.guid || jQuery.guid++;
} else {
handler = fn;
}
if ( type === "unload" && name !== "one" ) {
this.one( type, data, fn );
@ -971,24 +978,27 @@ jQuery.fn.extend({
toggle: function( fn ) {
// Save reference to arguments for access in closure
var args = arguments,
i = 1;
guid = fn.guid || jQuery.guid++,
i = 0,
toggler = function( event ) {
// Figure out which function to execute
var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
// Make sure that clicks stop
event.preventDefault();
// and execute the function
return args[ lastToggle ].apply( this, arguments ) || false;
};
// link all the functions, so any of them can unbind this click handler
toggler.guid = guid;
while ( i < args.length ) {
jQuery.proxy( fn, args[ i++ ] );
args[ i++ ].guid = guid;
}
return this.click( jQuery.proxy( fn, function( event ) {
// Figure out which function to execute
var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
// Make sure that clicks stop
event.preventDefault();
// and execute the function
return args[ lastToggle ].apply( this, arguments ) || false;
}));
return this.click( toggler );
},
hover: function( fnOver, fnOut ) {