From 600d3145386a9dca8143918cc3e339168f886a63 Mon Sep 17 00:00:00 2001 From: jeresig Date: Wed, 6 Jan 2010 15:08:07 -0500 Subject: A first pass at making sure that all the setter function arguments receive the index of the element and a relevant value to work with. Fixes #5763. --- src/attributes.js | 114 ++++++++++++++++++++++++++++------------------------ src/core.js | 2 +- src/manipulation.js | 16 ++++---- 3 files changed, 72 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/attributes.js b/src/attributes.js index a2108feb8..664a02442 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -12,10 +12,27 @@ jQuery.fn.extend({ return access( this, name, value, true, jQuery.attr ); }, + removeAttr: function( name ) { + if ( jQuery.isFunction( name ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeAttr( name.call(this, i, self.attr(name)) ); + }); + } + + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + addClass: function( value ) { if ( jQuery.isFunction(value) ) { - return this.each(function() { - jQuery(this).addClass( value.call(this) ); + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); }); } @@ -46,8 +63,9 @@ jQuery.fn.extend({ removeClass: function( value ) { if ( jQuery.isFunction(value) ) { - return this.each(function() { - jQuery(this).removeClass( value.call(this) ); + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); }); } @@ -75,6 +93,40 @@ jQuery.fn.extend({ return this; }, + toggleClass: function( classNames, state ) { + var type = typeof classNames; + + if ( jQuery.isFunction( classNames ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( classNames.call(this, i, self.attr("class")), state ); + }); + } + + return this.each(function(){ + if ( type === "string" ) { + // toggle individual class names + var isBool = typeof state === "boolean", className, i = 0, + classNames = classNames.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !jQuery(this).hasClass( className ); + jQuery(this)[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery.data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || classNames === false ? "" : jQuery.data( this, "__className__" ) || ""; + } + }); + }, + hasClass: function( selector ) { var className = " " + selector + " "; for ( var i = 0, l = this.length; i < l; i++ ) { @@ -149,9 +201,11 @@ jQuery.fn.extend({ var val = value; - return this.each(function() { + return this.each(function(i) { + var self = jQuery(this); + if ( jQuery.isFunction(value) ) { - val = value.call(this); + val = value.call(this, i, self.val()); // Typecast each time if the value is a Function and the appended // value is therefore different each time. @@ -165,13 +219,13 @@ jQuery.fn.extend({ } if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { - this.checked = jQuery.inArray( jQuery(this).val(), val ) >= 0; + this.checked = jQuery.inArray( self.val(), val ) >= 0; } else if ( jQuery.nodeName( this, "select" ) ) { var values = jQuery.makeArray(val); jQuery( "option", this ).each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + this.selected = jQuery.inArray( self.val(), values ) >= 0; }); if ( !values.length ) { @@ -185,50 +239,6 @@ jQuery.fn.extend({ } }); -jQuery.each({ - removeAttr: function( name ) { - jQuery.attr( this, name, "" ); - if ( this.nodeType === 1 ) { - this.removeAttribute( name ); - } - }, - - toggleClass: function( classNames, state ) { - var type = typeof classNames; - - if ( type === "string" ) { - // toggle individual class names - var isBool = typeof state === "boolean", className, i = 0, - classNames = classNames.split( rspace ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated list - state = isBool ? state : !jQuery(this).hasClass( className ); - jQuery(this)[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery.data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || classNames === false ? "" : jQuery.data( this, "__className__" ) || ""; - } - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( val, state ) { - if ( jQuery.isFunction( val ) ) { - return this.each(function() { - jQuery(this)[ name ]( val.call(this), state ); - }); - } - - return this.each( fn, arguments ); - }; -}); - jQuery.extend({ attrFn: { val: true, diff --git a/src/core.js b/src/core.js index 58cbbc7e5..831570ed3 100644 --- a/src/core.js +++ b/src/core.js @@ -775,7 +775,7 @@ function access( elems, key, value, exec, fn, pass ) { exec = exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i ) : value, pass ); + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; diff --git a/src/manipulation.js b/src/manipulation.js index 2af2d7e7d..730dfca5e 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -33,8 +33,9 @@ if ( !jQuery.support.htmlSerialize ) { jQuery.fn.extend({ text: function( text ) { if ( jQuery.isFunction(text) ) { - return this.each(function() { - return jQuery(this).text( text.call(this) ); + return this.each(function(i) { + var self = jQuery(this); + return self.text( text.call(this, i, self.text()) ); }); } @@ -47,8 +48,8 @@ jQuery.fn.extend({ wrapAll: function( html ) { if ( jQuery.isFunction( html ) ) { - return this.each(function() { - jQuery(this).wrapAll( html.apply(this, arguments) ); + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); }); } @@ -228,9 +229,10 @@ jQuery.fn.extend({ var results, first, value = args[0], scripts = []; if ( jQuery.isFunction(value) ) { - return this.each(function() { - args[0] = value.call(this); - return jQuery(this).domManip( args, table, callback ); + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call(this, i, table ? self.html() : undefined); + return self.domManip( args, table, callback ); }); } -- cgit v1.2.3 From 2526e293538c0959597fee60976b4360390d69e0 Mon Sep 17 00:00:00 2001 From: jeresig Date: Wed, 6 Jan 2010 15:23:30 -0500 Subject: Fixing some bugs in the re-tooling of toggleClass, adding in some performance optimizations. --- src/attributes.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/attributes.js b/src/attributes.js index 664a02442..a5a6662c4 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -93,26 +93,27 @@ jQuery.fn.extend({ return this; }, - toggleClass: function( classNames, state ) { - var type = typeof classNames; + toggleClass: function( value, stateVal ) { + var type = typeof value, isBool = typeof stateVal === "boolean"; - if ( jQuery.isFunction( classNames ) ) { + if ( jQuery.isFunction( value ) ) { return this.each(function(i) { var self = jQuery(this); - self.toggleClass( classNames.call(this, i, self.attr("class")), state ); + self.toggleClass( value.call(this, i, self.attr("class")), stateVal ); }); } - return this.each(function(){ + return this.each(function() { if ( type === "string" ) { // toggle individual class names - var isBool = typeof state === "boolean", className, i = 0, - classNames = classNames.split( rspace ); + var className, i = 0, self = jQuery(this), + state = stateVal, + classNames = value.split( rspace ); while ( (className = classNames[ i++ ]) ) { // check each className given, space seperated list - state = isBool ? state : !jQuery(this).hasClass( className ); - jQuery(this)[ state ? "addClass" : "removeClass" ]( className ); + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { @@ -122,7 +123,7 @@ jQuery.fn.extend({ } // toggle whole className - this.className = this.className || classNames === false ? "" : jQuery.data( this, "__className__" ) || ""; + this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; } }); }, -- cgit v1.2.3 From 4681216c4bdf25b6b146b3f952917f46079c6ef7 Mon Sep 17 00:00:00 2001 From: jeresig Date: Thu, 7 Jan 2010 09:53:16 -0500 Subject: Fixed some bugs relating to the setter arg change in val and html. Also optimized the code in val a bit. --- src/attributes.js | 29 ++++++++++++----------------- src/manipulation.js | 2 +- 2 files changed, 13 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/attributes.js b/src/attributes.js index a5a6662c4..1dd70842c 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -195,28 +195,23 @@ jQuery.fn.extend({ return undefined; } - // Typecast once if the value is a number - if ( typeof value === "number" ) { - value += ""; - } - - var val = value; + var isFunction = jQuery.isFunction(value); return this.each(function(i) { - var self = jQuery(this); + var self = jQuery(this), val = value; - if ( jQuery.isFunction(value) ) { - val = value.call(this, i, self.val()); + if ( this.nodeType !== 1 ) { + return; + } - // Typecast each time if the value is a Function and the appended - // value is therefore different each time. - if ( typeof val === "number" ) { - val += ""; - } + if ( isFunction ) { + val = value.call(this, i, self.val()); } - if ( this.nodeType !== 1 ) { - return; + // Typecast each time if the value is a Function and the appended + // value is therefore different each time. + if ( typeof val === "number" ) { + val += ""; } if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { @@ -226,7 +221,7 @@ jQuery.fn.extend({ var values = jQuery.makeArray(val); jQuery( "option", this ).each(function() { - this.selected = jQuery.inArray( self.val(), values ) >= 0; + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; }); if ( !values.length ) { diff --git a/src/manipulation.js b/src/manipulation.js index 730dfca5e..081bb5481 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -173,7 +173,7 @@ jQuery.fn.extend({ html: function( value ) { if ( value === undefined ) { - return this[0] ? + return this[0] && this[0].nodeType === 1 ? this[0].innerHTML.replace(rinlinejQuery, "") : null; -- cgit v1.2.3 From d36b29fa8e24820e0d1feb6a4ab46c440f54155a Mon Sep 17 00:00:00 2001 From: jeresig Date: Thu, 7 Jan 2010 11:04:21 -0500 Subject: Make sure the state is passed in to the toggleClass attribute function. --- src/attributes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/attributes.js b/src/attributes.js index 1dd70842c..3ae05421b 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -99,7 +99,7 @@ jQuery.fn.extend({ if ( jQuery.isFunction( value ) ) { return this.each(function(i) { var self = jQuery(this); - self.toggleClass( value.call(this, i, self.attr("class")), stateVal ); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); }); } -- cgit v1.2.3 From 21e15219be8e04b3fe25d05a65abfaef96830b9f Mon Sep 17 00:00:00 2001 From: jeresig Date: Thu, 7 Jan 2010 11:14:56 -0500 Subject: Removed .removeAttr(Function), it didn't really make sense. --- src/attributes.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'src') diff --git a/src/attributes.js b/src/attributes.js index 3ae05421b..004c6b30c 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -12,14 +12,7 @@ jQuery.fn.extend({ return access( this, name, value, true, jQuery.attr ); }, - removeAttr: function( name ) { - if ( jQuery.isFunction( name ) ) { - return this.each(function(i) { - var self = jQuery(this); - self.removeAttr( name.call(this, i, self.attr(name)) ); - }); - } - + removeAttr: function( name, fn ) { return this.each(function(){ jQuery.attr( this, name, "" ); if ( this.nodeType === 1 ) { -- cgit v1.2.3 From 8fa9e9d6d0307a5af8d7478d6e030af5afabba9e Mon Sep 17 00:00:00 2001 From: jeresig Date: Thu, 7 Jan 2010 13:33:30 -0500 Subject: Make sure that .html(Function) gets the correct previous value. --- src/manipulation.js | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/manipulation.js b/src/manipulation.js index 081bb5481..9ed22baaf 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -196,6 +196,14 @@ jQuery.fn.extend({ this.empty().append( value ); } + } else if ( jQuery.isFunction( value ) ) { + this.each(function(i){ + var self = jQuery(this), old = self.html(); + self.empty().append(function(){ + return value.call( this, i, old ); + }); + }); + } else { this.empty().append( value ); } -- cgit v1.2.3 From 4fa00369f00b8ee708c8962135b7aa345e3d30d0 Mon Sep 17 00:00:00 2001 From: jeresig Date: Thu, 7 Jan 2010 14:07:21 -0500 Subject: Added in support for .offset(Function). --- src/offset.js | 25 +++++++++++++++---------- test/unit/offset.js | 39 +++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/offset.js b/src/offset.js index d12921dff..7dd71343e 100644 --- a/src/offset.js +++ b/src/offset.js @@ -7,8 +7,8 @@ if ( "getBoundingClientRect" in document.documentElement ) { } if ( options ) { - return this.each(function() { - jQuery.offset.setOffset( this, options ); + return this.each(function( i ) { + jQuery.offset.setOffset( this, i, options ); }); } @@ -33,8 +33,8 @@ if ( "getBoundingClientRect" in document.documentElement ) { } if ( options ) { - return this.each(function() { - jQuery.offset.setOffset( this, options ); + return this.each(function( i ) { + jQuery.offset.setOffset( this, i, options ); }); } @@ -137,7 +137,7 @@ jQuery.offset = { return { top: top, left: left }; }, - setOffset: function( elem, options ) { + setOffset: function( elem, i, options ) { // set position first, in-case top/left are set even on static elem if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) { elem.style.position = "relative"; @@ -145,11 +145,16 @@ jQuery.offset = { var curElem = jQuery( elem ), curOffset = curElem.offset(), curTop = parseInt( jQuery.curCSS( elem, "top", true ), 10 ) || 0, - curLeft = parseInt( jQuery.curCSS( elem, "left", true ), 10) || 0, - props = { - top: (options.top - curOffset.top) + curTop, - left: (options.left - curOffset.left) + curLeft - }; + curLeft = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0; + + if ( jQuery.isFunction( options ) ) { + options = options.call( elem, i, curOffset ); + } + + var props = { + top: (options.top - curOffset.top) + curTop, + left: (options.left - curOffset.left) + curLeft + }; if ( "using" in options ) { options.using.call( elem, props ); diff --git a/test/unit/offset.js b/test/unit/offset.js index 602f5e6ae..dc03bc2e2 100644 --- a/test/unit/offset.js +++ b/test/unit/offset.js @@ -1,6 +1,8 @@ module("offset"); testoffset("absolute", function( jQuery ) { + expect(144); + // get offset tests var tests = [ { id: '#absolute-1', top: 1, left: 1 }, @@ -51,6 +53,16 @@ testoffset("absolute", function( jQuery ) { equals( jQuery( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset({ top: " + this.top + " })" ); equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" ); + var top = this.top, left = this.left; + + jQuery( this.id ).offset(function(i, val){ + equals( val.top, top, "Verify incoming top position." ); + equals( val.left, left, "Verify incoming top position." ); + return { top: top + 1, left: left + 1 }; + }); + equals( jQuery( this.id ).offset().top, this.top + 1, "jQuery('" + this.id + "').offset({ top: " + this.top + " })" ); + equals( jQuery( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" ); + jQuery( this.id ).offset({ top: this.top, left: this.left, using: function( props ) { jQuery( this ).css({ top: props.top + 1, @@ -63,6 +75,8 @@ testoffset("absolute", function( jQuery ) { }); testoffset("relative", function( jQuery ) { + expect(60); + // IE is collapsing the top margin of 1px var ie = jQuery.browser.msie && parseInt( jQuery.browser.version ) < 8; @@ -122,6 +136,8 @@ testoffset("relative", function( jQuery ) { }); testoffset("static", function( jQuery ) { + expect(80); + // IE is collapsing the top margin of 1px var ie = jQuery.browser.msie && parseInt( jQuery.browser.version ) < 8; @@ -187,6 +203,8 @@ testoffset("static", function( jQuery ) { }); testoffset("fixed", function( jQuery ) { + expect(28); + jQuery.offset.initialize(); var tests = [ @@ -238,31 +256,18 @@ testoffset("fixed", function( jQuery ) { }); testoffset("table", function( jQuery ) { - var ie = jQuery.browser.msie; + expect(4); equals( jQuery('#table-1').offset().top, 6, "jQuery('#table-1').offset().top" ); equals( jQuery('#table-1').offset().left, 6, "jQuery('#table-1').offset().left" ); equals( jQuery('#th-1').offset().top, 10, "jQuery('#th-1').offset().top" ); equals( jQuery('#th-1').offset().left, 10, "jQuery('#th-1').offset().left" ); - - // equals( jQuery('#th-2').offset().top, 10, "jQuery('#th-2').offset().top" ); - // equals( jQuery('#th-2').offset().left, 116, "jQuery('#th-2').offset().left" ); - // - // equals( jQuery('#th-3').offset().top, 10, "jQuery('#th-3').offset().top" ); - // equals( jQuery('#th-3').offset().left, 222, "jQuery('#th-3').offset().left" ); - - // equals( jQuery('#td-1').offset().top, ie ? 116 : 112, "jQuery('#td-1').offset().top" ); - // equals( jQuery('#td-1').offset().left, 10, "jQuery('#td-1').offset().left" ); - // - // equals( jQuery('#td-2').offset().top, ie ? 116 : 112, "jQuery('#td-2').offset().top" ); - // equals( jQuery('#td-2').offset().left, 116, "jQuery('#td-2').offset().left" ); - // - // equals( jQuery('#td-3').offset().top, ie ? 116 : 112, "jQuery('#td-3').offset().top" ); - // equals( jQuery('#td-3').offset().left, 222, "jQuery('#td-3').offset().left" ); }); testoffset("scroll", function( jQuery, win ) { + expect(12); + var ie = jQuery.browser.msie && parseInt( jQuery.browser.version ) < 8; // IE is collapsing the top margin of 1px @@ -294,6 +299,8 @@ testoffset("scroll", function( jQuery, win ) { }); testoffset("body", function( jQuery ) { + expect(2); + equals( jQuery('body').offset().top, 1, "jQuery('#body').offset().top" ); equals( jQuery('body').offset().left, 1, "jQuery('#body').offset().left" ); }); -- cgit v1.2.3 From 0e5370b89c0dfe56bf2f02fdd34fd820ecd48254 Mon Sep 17 00:00:00 2001 From: jeresig Date: Thu, 7 Jan 2010 14:08:32 -0500 Subject: Re-ordering the args to setOffset() in case people were relying upon the old order (doubtful). --- src/offset.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/offset.js b/src/offset.js index 7dd71343e..c3183743b 100644 --- a/src/offset.js +++ b/src/offset.js @@ -8,7 +8,7 @@ if ( "getBoundingClientRect" in document.documentElement ) { if ( options ) { return this.each(function( i ) { - jQuery.offset.setOffset( this, i, options ); + jQuery.offset.setOffset( this, options, i ); }); } @@ -34,7 +34,7 @@ if ( "getBoundingClientRect" in document.documentElement ) { if ( options ) { return this.each(function( i ) { - jQuery.offset.setOffset( this, i, options ); + jQuery.offset.setOffset( this, options, i ); }); } @@ -137,7 +137,7 @@ jQuery.offset = { return { top: top, left: left }; }, - setOffset: function( elem, i, options ) { + setOffset: function( elem, options, i ) { // set position first, in-case top/left are set even on static elem if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) { elem.style.position = "relative"; -- cgit v1.2.3