Skip to content

Commit 6c2a501

Browse files
gibson042dmethvin
authored andcommitted
Fix jquery#5571. Setters should treat undefined as a no-op and be chainable.
1 parent d511613 commit 6c2a501

14 files changed

+248
-229
lines changed

src/attributes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ var rclass = /[\n\t\r]/g,
1212

1313
jQuery.fn.extend({
1414
attr: function( name, value ) {
15-
return jQuery.access( this, name, value, true, jQuery.attr );
15+
return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
1616
},
1717

1818
removeAttr: function( name ) {
@@ -22,7 +22,7 @@ jQuery.fn.extend({
2222
},
2323

2424
prop: function( name, value ) {
25-
return jQuery.access( this, name, value, true, jQuery.prop );
25+
return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2626
},
2727

2828
removeProp: function( name ) {

src/core.js

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -801,31 +801,55 @@ jQuery.extend({
801801

802802
// Mutifunctional method to get and set values to a collection
803803
// The value/s can optionally be executed if it's a function
804-
access: function( elems, key, value, exec, fn, pass ) {
805-
var length = elems.length;
804+
access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
805+
var exec,
806+
bulk = key == null,
807+
i = 0,
808+
length = elems.length;
806809

807-
// Setting many attributes
808-
if ( typeof key === "object" ) {
809-
for ( var k in key ) {
810-
jQuery.access( elems, k, key[k], exec, fn, value );
810+
// Sets many values
811+
if ( key && typeof key === "object" ) {
812+
for ( i in key ) {
813+
jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
811814
}
812-
return elems;
813-
}
815+
chainable = 1;
814816

815-
// Setting one attribute
816-
if ( value !== undefined ) {
817+
// Sets one value
818+
} else if ( value !== undefined ) {
817819
// Optionally, function values get executed if exec is true
818-
exec = !pass && exec && jQuery.isFunction(value);
820+
exec = pass === undefined && jQuery.isFunction( value );
821+
822+
if ( bulk ) {
823+
// Bulk operations only iterate when executing function values
824+
if ( exec ) {
825+
exec = fn;
826+
fn = function( elem, key, value ) {
827+
return exec.call( jQuery( elem ), value );
828+
};
819829

820-
for ( var i = 0; i < length; i++ ) {
821-
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
830+
// Otherwise they run against the entire set
831+
} else {
832+
fn.call( elems, value );
833+
fn = null;
834+
}
822835
}
823836

824-
return elems;
837+
if ( fn ) {
838+
for (; i < length; i++ ) {
839+
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
840+
}
841+
}
842+
843+
chainable = 1;
825844
}
826845

827-
// Getting an attribute
828-
return length ? fn( elems[0], key ) : undefined;
846+
return chainable ?
847+
elems :
848+
849+
// Gets
850+
bulk ?
851+
fn.call( elems ) :
852+
length ? fn( elems[0], key ) : emptyGet;
829853
},
830854

831855
now: function() {

src/css.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,11 @@ var ralpha = /alpha\([^)]*\)/i,
1717
currentStyle;
1818

1919
jQuery.fn.css = function( name, value ) {
20-
// Setting 'undefined' is a no-op
21-
if ( arguments.length === 2 && value === undefined ) {
22-
return this;
23-
}
24-
25-
return jQuery.access( this, name, value, true, function( elem, name, value ) {
20+
return jQuery.access( this, function( elem, name, value ) {
2621
return value !== undefined ?
2722
jQuery.style( elem, name, value ) :
2823
jQuery.css( elem, name );
29-
});
24+
}, name, value, arguments.length > 1 );
3025
};
3126

3227
jQuery.extend({

src/data.js

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -246,62 +246,69 @@ jQuery.extend({
246246

247247
jQuery.fn.extend({
248248
data: function( key, value ) {
249-
var parts, attr, name,
249+
var parts, part, attr, name, l,
250+
elem = this[0],
251+
i = 0,
250252
data = null;
251253

252-
if ( typeof key === "undefined" ) {
254+
// Gets all values
255+
if ( key === undefined ) {
253256
if ( this.length ) {
254-
data = jQuery.data( this[0] );
257+
data = jQuery.data( elem );
255258

256-
if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
257-
attr = this[0].attributes;
258-
for ( var i = 0, l = attr.length; i < l; i++ ) {
259+
if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
260+
attr = elem.attributes;
261+
for ( l = attr.length; i < l; i++ ) {
259262
name = attr[i].name;
260263

261264
if ( name.indexOf( "data-" ) === 0 ) {
262265
name = jQuery.camelCase( name.substring(5) );
263266

264-
dataAttr( this[0], name, data[ name ] );
267+
dataAttr( elem, name, data[ name ] );
265268
}
266269
}
267-
jQuery._data( this[0], "parsedAttrs", true );
270+
jQuery._data( elem, "parsedAttrs", true );
268271
}
269272
}
270273

271274
return data;
275+
}
272276

273-
} else if ( typeof key === "object" ) {
277+
// Sets multiple values
278+
if ( typeof key === "object" ) {
274279
return this.each(function() {
275280
jQuery.data( this, key );
276281
});
277282
}
278283

279-
parts = key.split(".");
280-
parts[1] = parts[1] ? "." + parts[1] : "";
284+
return jQuery.access( this, function( value ) {
285+
parts = key.split( ".", 2 ),
286+
parts[1] = parts[1] ? "." + parts[1] : "";
287+
part = parts[1] + "!";
281288

282-
if ( value === undefined ) {
283-
data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
289+
if ( value === undefined ) {
290+
data = this.triggerHandler( "getData" + part, [ parts[0] ] );
284291

285-
// Try to fetch any internally stored data first
286-
if ( data === undefined && this.length ) {
287-
data = jQuery.data( this[0], key );
288-
data = dataAttr( this[0], key, data );
289-
}
292+
// Try to fetch any internally stored data first
293+
if ( data === undefined && elem ) {
294+
data = jQuery.data( elem, key );
295+
data = dataAttr( elem, key, data );
296+
}
290297

291-
return data === undefined && parts[1] ?
292-
this.data( parts[0] ) :
293-
data;
298+
return data === undefined && parts[1] ?
299+
this.data( parts[0] ) :
300+
data;
301+
}
294302

295-
} else {
296-
return this.each(function() {
297-
var self = jQuery( this ),
298-
args = [ parts[0], value ];
303+
parts[1] = value;
304+
this.each(function() {
305+
var self = jQuery( this );
299306

300-
self.triggerHandler( "setData" + parts[1] + "!", args );
307+
self.triggerHandler( "setData" + part, parts );
301308
jQuery.data( this, key, value );
302-
self.triggerHandler( "changeData" + parts[1] + "!", args );
309+
self.triggerHandler( "changeData" + part, parts );
303310
});
304-
}
311+
}, null, value, arguments.length > 1, null, false );
305312
},
306313

307314
removeData: function( key ) {

src/dimensions.js

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
(function( jQuery ) {
22

33
// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
4-
jQuery.each([ "Height", "Width" ], function( i, name ) {
5-
6-
var type = name.toLowerCase();
4+
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
5+
var clientProp = "client" + name,
6+
scrollProp = "scroll" + name,
7+
offsetProp = "offset" + name;
78

89
// innerHeight and innerWidth
910
jQuery.fn[ "inner" + name ] = function() {
@@ -25,50 +26,40 @@ jQuery.each([ "Height", "Width" ], function( i, name ) {
2526
null;
2627
};
2728

28-
jQuery.fn[ type ] = function( size ) {
29-
// Get window width or height
30-
var elem = this[0];
31-
if ( !elem ) {
32-
return size == null ? null : this;
33-
}
34-
35-
if ( jQuery.isFunction( size ) ) {
36-
return this.each(function( i ) {
37-
var self = jQuery( this );
38-
self[ type ]( size.call( this, i, self[ type ]() ) );
39-
});
40-
}
29+
jQuery.fn[ type ] = function( value ) {
30+
return jQuery.access( this, function( elem, type, value ) {
31+
var doc, docElemProp, orig, ret;
4132

42-
if ( jQuery.isWindow( elem ) ) {
43-
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
44-
// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
45-
var docElemProp = elem.document.documentElement[ "client" + name ],
46-
body = elem.document.body;
47-
return elem.document.compatMode === "CSS1Compat" && docElemProp ||
48-
body && body[ "client" + name ] || docElemProp;
33+
if ( jQuery.isWindow( elem ) ) {
34+
// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
35+
doc = elem.document;
36+
docElemProp = doc.documentElement[ clientProp ];
37+
return doc.compatMode === "CSS1Compat" && docElemProp ||
38+
doc.body && doc.body[ clientProp ] || docElemProp;
39+
}
4940

50-
// Get document width or height
51-
} else if ( elem.nodeType === 9 ) {
52-
// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
53-
return Math.max(
54-
elem.documentElement["client" + name],
55-
elem.body["scroll" + name], elem.documentElement["scroll" + name],
56-
elem.body["offset" + name], elem.documentElement["offset" + name]
57-
);
41+
// Get document width or height
42+
if ( elem.nodeType === 9 ) {
43+
// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
44+
doc = elem.documentElement;
45+
return Math.max(
46+
doc[ clientProp ],
47+
elem.body[ scrollProp ], doc[ scrollProp ],
48+
elem.body[ offsetProp ], doc[ offsetProp ]
49+
);
50+
}
5851

59-
// Get or set width or height on the element
60-
} else if ( size === undefined ) {
61-
var orig = jQuery.css( elem, type ),
52+
// Get width or height on the element
53+
if ( value === undefined ) {
54+
orig = jQuery.css( elem, type );
6255
ret = parseFloat( orig );
56+
return jQuery.isNumeric( ret ) ? ret : orig;
57+
}
6358

64-
return jQuery.isNumeric( ret ) ? ret : orig;
65-
66-
// Set the width or height on the element (default to pixels if value is unitless)
67-
} else {
68-
return this.css( type, typeof size === "string" ? size : size + "px" );
69-
}
59+
// Set the width or height on the element
60+
jQuery( elem ).css( type, value );
61+
}, type, value, arguments.length, null );
7062
};
71-
7263
});
7364

7465
})( jQuery );

0 commit comments

Comments
 (0)