Skip to content

Commit

Permalink
Add fallback to prop for the window and document. Switch value to use…
Browse files Browse the repository at this point in the history
… the property instead of the attribute for back compat.
  • Loading branch information
timmywil committed May 10, 2011
1 parent 8c13cfa commit 4526c8b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 28 deletions.
47 changes: 35 additions & 12 deletions src/attributes.js
Expand Up @@ -301,10 +301,15 @@ jQuery.extend({
if ( pass && name in jQuery.attrFn ) { if ( pass && name in jQuery.attrFn ) {
return jQuery( elem )[ name ]( value ); return jQuery( elem )[ name ]( value );
} }


// Fallback to prop when attributes are not supported
if ( !("getAttribute" in elem) ) {
return jQuery.prop( elem, name, value );
}

var ret, hooks, var ret, hooks,
notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

// Normalize the name if needed // Normalize the name if needed
name = notxml && jQuery.attrFix[ name ] || name; name = notxml && jQuery.attrFix[ name ] || name;


Expand Down Expand Up @@ -381,7 +386,7 @@ jQuery.extend({
// Setting the type on a radio button after the value resets the value in IE6-9 // Setting the type on a radio button after the value resets the value in IE6-9
// Reset value to it's default in case type is set after value // Reset value to it's default in case type is set after value
// This is for element creation // This is for element creation
var val = elem.getAttribute("value"); var val = elem.value;
elem.setAttribute( "type", value ); elem.setAttribute( "type", value );
if ( val ) { if ( val ) {
elem.value = val; elem.value = val;
Expand All @@ -404,7 +409,7 @@ jQuery.extend({
} }
} }
}, },

propFix: { propFix: {
tabindex: "tabIndex", tabindex: "tabIndex",
readonly: "readOnly", readonly: "readOnly",
Expand All @@ -422,32 +427,32 @@ jQuery.extend({


prop: function( elem, name, value ) { prop: function( elem, name, value ) {
var nType = elem.nodeType; var nType = elem.nodeType;

// don't get/set properties on text, comment and attribute nodes // don't get/set properties on text, comment and attribute nodes
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
return undefined; return undefined;
} }

var ret, hooks, var ret, hooks,
notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

// Try to normalize/fix the name // Try to normalize/fix the name
name = notxml && jQuery.propFix[ name ] || name; name = notxml && jQuery.propFix[ name ] || name;


hooks = jQuery.propHooks[ name ]; hooks = jQuery.propHooks[ name ];

if ( value !== undefined ) { if ( value !== undefined ) {
if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
return ret; return ret;

} else { } else {
return (elem[ name ] = value); return (elem[ name ] = value);
} }

} else { } else {
if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
return ret; return ret;

} else { } else {
return elem[ name ]; return elem[ name ];
} }
Expand Down Expand Up @@ -485,14 +490,32 @@ boolHook = {
} }
}; };


// Use the value property for back compat
// Use the formHook for button elements in IE6/7 (#1954)
jQuery.attrHooks.value = {
get: function( elem, name ) {
if ( formHook && jQuery.nodeName( elem, "button" ) ) {
return formHook.get( elem, name );
}
return elem.value;
},
set: function( elem, value, name ) {
if ( formHook && jQuery.nodeName( elem, "button" ) ) {
return formHook.set( elem, value, name );
}
// Does not return so that setAttribute is also used
elem.value = value;
}
};

// IE6/7 do not support getting/setting some attributes with get/setAttribute // IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !jQuery.support.getSetAttribute ) { if ( !jQuery.support.getSetAttribute ) {


// propFix is more comprehensive and contains all fixes // propFix is more comprehensive and contains all fixes
jQuery.attrFix = jQuery.propFix; jQuery.attrFix = jQuery.propFix;


// Use this for any attribute on a form in IE6/7 // Use this for any attribute on a form in IE6/7
formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = { formHook = jQuery.attrHooks.name = jQuery.valHooks.button = {
get: function( elem, name ) { get: function( elem, name ) {
var ret; var ret;
ret = elem.getAttributeNode( name ); ret = elem.getAttributeNode( name );
Expand Down
36 changes: 20 additions & 16 deletions test/unit/attributes.js
Expand Up @@ -117,9 +117,9 @@ if ( !isLocal ) {
test("attr(String) in XML Files", function() { test("attr(String) in XML Files", function() {
expect(2); expect(2);
stop(); stop();
jQuery.get("data/dashboard.xml", function(xml) { jQuery.get("data/dashboard.xml", function( xml ) {
equals( jQuery("locations", xml).attr("class"), "foo", "Check class attribute in XML document" ); equals( jQuery( "locations", xml ).attr("class"), "foo", "Check class attribute in XML document" );
equals( jQuery("location", xml).attr("for"), "bar", "Check for attribute in XML document" ); equals( jQuery( "location", xml ).attr("for"), "bar", "Check for attribute in XML document" );
start(); start();
}); });
}); });
Expand All @@ -144,7 +144,7 @@ test("attr(Hash)", function() {
}); });


test("attr(String, Object)", function() { test("attr(String, Object)", function() {
expect(59); expect(66);


var div = jQuery("div").attr("foo", "bar"), var div = jQuery("div").attr("foo", "bar"),
fail = false; fail = false;
Expand Down Expand Up @@ -206,9 +206,6 @@ test("attr(String, Object)", function() {
equals( document.getElementById("name").maxLength, 5, "Set maxlength attribute" ); equals( document.getElementById("name").maxLength, 5, "Set maxlength attribute" );
jQuery("#name").attr("maxLength", "10"); jQuery("#name").attr("maxLength", "10");
equals( document.getElementById("name").maxLength, 10, "Set maxlength attribute" ); equals( document.getElementById("name").maxLength, 10, "Set maxlength attribute" );
var $p = jQuery("#firstp").attr("nonexisting", "foo");
equals( $p.attr("nonexisting"), "foo", "attr(name, value) works correctly for non existing attributes (bug #7500).");
$p.removeAttr("nonexisting");


var $text = jQuery("#text1").attr("autofocus", true); var $text = jQuery("#text1").attr("autofocus", true);
if ( "autofocus" in $text[0] ) { if ( "autofocus" in $text[0] ) {
Expand All @@ -227,12 +224,19 @@ test("attr(String, Object)", function() {


var attributeNode = document.createAttribute("irrelevant"), var attributeNode = document.createAttribute("irrelevant"),
commentNode = document.createComment("some comment"), commentNode = document.createComment("some comment"),
textNode = document.createTextNode("some text"); textNode = document.createTextNode("some text"),
obj = {};


jQuery.each( [commentNode, textNode, attributeNode], function( i, ele ) { jQuery.each( [commentNode, textNode, attributeNode], function( i, elem ) {
var $ele = jQuery( ele ); var $elem = jQuery( elem );
$ele.attr( "nonexisting", "foo" ); $elem.attr( "nonexisting", "foo" );
strictEqual( $ele.attr("nonexisting"), undefined, "attr(name, value) works correctly on comment and text nodes (bug #7500)." ); strictEqual( $elem.attr("nonexisting"), undefined, "attr(name, value) works correctly on comment and text nodes (bug #7500)." );
});

jQuery.each( [window, document, obj, "#firstp"], function( i, elem ) {
var $elem = jQuery( elem );
strictEqual( $elem.attr("nonexisting"), undefined, "attr works correctly for non existing attributes (bug #7500)." );
equal( $elem.attr("something", "foo" ).attr("something"), "foo", "attr falls back to prop on unsupported arguments" );
}); });


var table = jQuery("#table").append("<tr><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr>"), var table = jQuery("#table").append("<tr><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr>"),
Expand All @@ -244,7 +248,7 @@ test("attr(String, Object)", function() {
table.attr("cellspacing", "2"); table.attr("cellspacing", "2");
equals( table[0].cellSpacing, "2", "Check cellspacing is correctly set" ); equals( table[0].cellSpacing, "2", "Check cellspacing is correctly set" );


equals( jQuery("#area1").attr("value"), undefined, "Value attribute retrieved correctly on textarea." ); equals( jQuery("#area1").attr("value"), "foobar", "Value attribute retrieves the property for backwards compatibility." );


// for #1070 // for #1070
jQuery("#name").attr("someAttr", "0"); jQuery("#name").attr("someAttr", "0");
Expand Down Expand Up @@ -350,10 +354,10 @@ if ( !isLocal ) {
test("attr(String, Object) - Loaded via XML document", function() { test("attr(String, Object) - Loaded via XML document", function() {
expect(2); expect(2);
stop(); stop();
jQuery.get("data/dashboard.xml", function(xml) { jQuery.get("data/dashboard.xml", function( xml ) {
var titles = []; var titles = [];
jQuery("tab", xml).each(function() { jQuery( "tab", xml ).each(function() {
titles.push(jQuery(this).attr("title")); titles.push( jQuery(this).attr("title") );
}); });
equals( titles[0], "Location", "attr() in XML context: Check first title" ); equals( titles[0], "Location", "attr() in XML context: Check first title" );
equals( titles[1], "Users", "attr() in XML context: Check second title" ); equals( titles[1], "Users", "attr() in XML context: Check second title" );
Expand Down

0 comments on commit 4526c8b

Please sign in to comment.