From 8c2cb49917fc1082abac0a26298b992dcd6a5b6e Mon Sep 17 00:00:00 2001 From: timmywil Date: Thu, 4 Aug 2011 16:34:59 -0400 Subject: [PATCH] Now using getAttributeNode in all attribute cases in IE6/7, which normalizes attribute behaviors across browsers, is less hacky, and shortens the attribute code. Fixes #9980. --- src/attributes.js | 41 +++++++++++++++++-------------------- test/unit/attributes.js | 45 ++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 46 deletions(-) diff --git a/src/attributes.js b/src/attributes.js index df87e23b4..9a35c045b 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -8,7 +8,7 @@ var rclass = /[\n\t\r]/g, rclickable = /^a(?:rea)?$/i, rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, rinvalidChar = /\:|^on/, - formHook, boolHook; + nodeHook, boolHook; jQuery.fn.extend({ attr: function( name, value ) { @@ -326,14 +326,11 @@ jQuery.extend({ if ( !hooks ) { // Use boolHook for boolean attributes if ( rboolean.test( name ) ) { - hooks = boolHook; - // Use formHook for forms and if the name contains certain characters - } else if ( formHook && name !== "className" && - (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { - - hooks = formHook; + // Use nodeHook if available( IE6/7 ) + } else if ( nodeHook ) { + hooks = nodeHook; } } } @@ -406,19 +403,19 @@ jQuery.extend({ } }, // Use the value property for back compat - // Use the formHook for button elements in IE6/7 (#1954) + // Use the nodeHook for button elements in IE6/7 (#1954) value: { get: function( elem, name ) { - if ( formHook && jQuery.nodeName( elem, "button" ) ) { - return formHook.get( elem, name ); + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); } return name in elem ? elem.value : null; }, set: function( elem, value, name ) { - if ( formHook && jQuery.nodeName( elem, "button" ) ) { - return formHook.set( elem, value, name ); + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); } // Does not return so that setAttribute is also used elem.value = value; @@ -481,7 +478,7 @@ jQuery.extend({ get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode("tabIndex"); + var attributeNode = elem.getAttributeNode("tabindex"); return attributeNode && attributeNode.specified ? parseInt( attributeNode.value, 10 ) : @@ -528,12 +525,10 @@ boolHook = { // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !jQuery.support.getSetAttribute ) { - - // propFix is more comprehensive and contains all fixes - jQuery.attrFix = jQuery.propFix; - // Use this for any attribute on a form in IE6/7 - formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = { + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { get: function( elem, name ) { var ret; ret = elem.getAttributeNode( name ); @@ -543,13 +538,13 @@ if ( !jQuery.support.getSetAttribute ) { undefined; }, set: function( elem, value, name ) { - // Check form objects in IE (multiple bugs related) - // Only use nodeValue if the attribute node exists on the form + // Set the existing or create a new attribute node var ret = elem.getAttributeNode( name ); - if ( ret ) { - ret.nodeValue = value; - return value; + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); } + return (ret.nodeValue = value + ""); } }; diff --git a/test/unit/attributes.js b/test/unit/attributes.js index 1a390a4c5..73e7750fc 100644 --- a/test/unit/attributes.js +++ b/test/unit/attributes.js @@ -24,16 +24,11 @@ test("jQuery.attrFix/jQuery.propFix integrity test", function() { usemap: "useMap", frameborder: "frameBorder", contenteditable: "contentEditable" - }, - propsShouldBe; - - if ( !jQuery.support.getSetAttribute ) { - propsShouldBe = props; - } else { - propsShouldBe = { - tabindex: "tabIndex" }; - } + + var propsShouldBe = { + tabindex: "tabIndex" + }; deepEqual(propsShouldBe, jQuery.attrFix, "jQuery.attrFix passes integrity check"); deepEqual(props, jQuery.propFix, "jQuery.propFix passes integrity check"); @@ -162,7 +157,7 @@ test("attr(Hash)", function() { }); test("attr(String, Object)", function() { - expect(73); + expect(75); var div = jQuery("div").attr("foo", "bar"), fail = false; @@ -244,9 +239,13 @@ test("attr(String, Object)", function() { equal( $details.attr("open"), "open", "open attribute presense indicates true" ); equal( $details.attr("open", false).attr("open"), undefined, "Setting open attribute to false removes it" ); - equals( $text.attr("data-something", true).data("something"), true, "Setting data attributes are not affected by boolean settings"); - equals( $text.attr("data-another", false).data("another"), false, "Setting data attributes are not affected by boolean settings" ); - equals( $text.attr("aria-disabled", false).attr("aria-disabled"), "false", "Setting aria attributes are not affected by boolean settings"); + $text.attr("data-something", true); + equal( $text.attr("data-something"), "true", "Set data attributes"); + equal( $text.data("something"), true, "Setting data attributes are not affected by boolean settings"); + $text.attr("data-another", false); + equal( $text.attr("data-another"), "false", "Set data attributes"); + equal( $text.data("another"), false, "Setting data attributes are not affected by boolean settings" ); + equal( $text.attr("aria-disabled", false).attr("aria-disabled"), "false", "Setting aria attributes are not affected by boolean settings"); $text.removeData("something").removeData("another").removeAttr("aria-disabled"); jQuery("#foo").attr("contenteditable", true); @@ -1032,7 +1031,7 @@ test("toggleClass(Fucntion[, boolean]) with incoming value", function() { ok( !e.is(".test"), "Assert class not present" ); e.toggleClass(function(i, val) { - equals( val, old, "Make sure the incoming value is correct." ); + equal( old, val, "Make sure the incoming value is correct." ); return "test"; }); ok( e.is(".test"), "Assert class present" ); @@ -1040,26 +1039,26 @@ test("toggleClass(Fucntion[, boolean]) with incoming value", function() { old = e.attr("class"); e.toggleClass(function(i, val) { - equals( val, old, "Make sure the incoming value is correct." ); + equal( old, val, "Make sure the incoming value is correct." ); return "test"; }); ok( !e.is(".test"), "Assert class not present" ); - old = e.attr("class"); + old = e.attr("class") || ""; // class name with a boolean e.toggleClass(function(i, val, state) { - equals( val, old, "Make sure the incoming value is correct." ); - equals( state, false, "Make sure that the state is passed in." ); + equal( old, val, "Make sure the incoming value is correct." ); + equal( state, false, "Make sure that the state is passed in." ); return "test"; }, false ); ok( !e.is(".test"), "Assert class not present" ); - old = e.attr("class"); + old = e.attr("class") || ""; e.toggleClass(function(i, val, state) { - equals( val, old, "Make sure the incoming value is correct." ); - equals( state, true, "Make sure that the state is passed in." ); + equal( old, val, "Make sure the incoming value is correct." ); + equal( state, true, "Make sure that the state is passed in." ); return "test"; }, true ); ok( e.is(".test"), "Assert class present" ); @@ -1067,8 +1066,8 @@ test("toggleClass(Fucntion[, boolean]) with incoming value", function() { old = e.attr("class"); e.toggleClass(function(i, val, state) { - equals( val, old, "Make sure the incoming value is correct." ); - equals( state, false, "Make sure that the state is passed in." ); + equal( old, val, "Make sure the incoming value is correct." ); + equal( state, false, "Make sure that the state is passed in." ); return "test"; }, false ); ok( !e.is(".test"), "Assert class not present" ); -- 2.39.5