diff --git a/src/attributes.js b/src/attributes.js index c207a001..bc26d735 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -301,10 +301,15 @@ jQuery.extend({ if ( pass && name in jQuery.attrFn ) { 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, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - + // Normalize the name if needed name = notxml && jQuery.attrFix[ name ] || name; @@ -381,7 +386,7 @@ jQuery.extend({ // 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 // This is for element creation - var val = elem.getAttribute("value"); + var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; @@ -404,7 +409,7 @@ jQuery.extend({ } } }, - + propFix: { tabindex: "tabIndex", readonly: "readOnly", @@ -422,32 +427,32 @@ jQuery.extend({ prop: function( elem, name, value ) { var nType = elem.nodeType; - + // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; } - + var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - + // Try to normalize/fix the name name = notxml && jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; - + if ( value !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; - + } else { return (elem[ name ] = value); } - + } else { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { return ret; - + } else { return elem[ name ]; } @@ -485,6 +490,24 @@ 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 if ( !jQuery.support.getSetAttribute ) { @@ -492,7 +515,7 @@ if ( !jQuery.support.getSetAttribute ) { jQuery.attrFix = jQuery.propFix; // 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 ) { var ret; ret = elem.getAttributeNode( name ); diff --git a/test/unit/attributes.js b/test/unit/attributes.js index ce7775d1..d2d43475 100644 --- a/test/unit/attributes.js +++ b/test/unit/attributes.js @@ -117,9 +117,9 @@ if ( !isLocal ) { test("attr(String) in XML Files", function() { expect(2); stop(); - jQuery.get("data/dashboard.xml", function(xml) { - 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" ); + jQuery.get("data/dashboard.xml", function( xml ) { + 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" ); start(); }); }); @@ -144,7 +144,7 @@ test("attr(Hash)", function() { }); test("attr(String, Object)", function() { - expect(59); + expect(66); var div = jQuery("div").attr("foo", "bar"), fail = false; @@ -206,9 +206,6 @@ test("attr(String, Object)", function() { equals( document.getElementById("name").maxLength, 5, "Set maxlength attribute" ); jQuery("#name").attr("maxLength", "10"); 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); if ( "autofocus" in $text[0] ) { @@ -227,12 +224,19 @@ test("attr(String, Object)", function() { var attributeNode = document.createAttribute("irrelevant"), commentNode = document.createComment("some comment"), - textNode = document.createTextNode("some text"); + textNode = document.createTextNode("some text"), + obj = {}; - jQuery.each( [commentNode, textNode, attributeNode], function( i, ele ) { - var $ele = jQuery( ele ); - $ele.attr( "nonexisting", "foo" ); - strictEqual( $ele.attr("nonexisting"), undefined, "attr(name, value) works correctly on comment and text nodes (bug #7500)." ); + jQuery.each( [commentNode, textNode, attributeNode], function( i, elem ) { + var $elem = jQuery( elem ); + $elem.attr( "nonexisting", "foo" ); + 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("cellcellcellcellcell"), @@ -244,7 +248,7 @@ test("attr(String, Object)", function() { table.attr("cellspacing", "2"); 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 jQuery("#name").attr("someAttr", "0"); @@ -350,10 +354,10 @@ if ( !isLocal ) { test("attr(String, Object) - Loaded via XML document", function() { expect(2); stop(); - jQuery.get("data/dashboard.xml", function(xml) { + jQuery.get("data/dashboard.xml", function( xml ) { var titles = []; - jQuery("tab", xml).each(function() { - titles.push(jQuery(this).attr("title")); + jQuery( "tab", xml ).each(function() { + titles.push( jQuery(this).attr("title") ); }); equals( titles[0], "Location", "attr() in XML context: Check first title" ); equals( titles[1], "Users", "attr() in XML context: Check second title" );