From 92405d4f5ffe9ec1f26f280303783014948438c5 Mon Sep 17 00:00:00 2001 From: timmywil Date: Mon, 12 Sep 2011 19:40:14 -0400 Subject: [PATCH] Override Sizzle attribute retrieval with jQuery.attr. Fixes #5637, #7128, #9261, #9570, #10178. Bug fixed on the side: $(window).is('a') was throwing an exception. Fixes #10178. --- src/attributes.js | 12 ++-- src/sizzle | 2 +- src/sizzle-jquery.js | 3 + test/data/selector.html | 132 +++++++++++++++++++++++++++++++++++++++ test/data/testinit.js | 3 +- test/index.html | 3 +- test/unit/attributes.js | 15 ++--- test/unit/selector.js | 133 ++++++++++++++++++++++++++++++++++++++++ test/unit/traversing.js | 8 ++- 9 files changed, 294 insertions(+), 17 deletions(-) create mode 100644 test/data/selector.html create mode 100644 test/unit/selector.js diff --git a/src/attributes.js b/src/attributes.js index dd985b494..6380b7d6c 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -7,7 +7,7 @@ var rclass = /[\n\t\r]/g, rfocusable = /^(?:button|input|object|select|textarea)$/i, rclickable = /^a(?:rea)?$/i, rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, - nodeHook, boolHook; + nodeHook, boolHook, fixSpecified; jQuery.fn.extend({ attr: function( name, value ) { @@ -519,15 +519,19 @@ boolHook = { // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !jQuery.support.getSetAttribute ) { - + + fixSpecified = { + name: true, + id: true + }; + // 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 ); - // Return undefined if nodeValue is empty string - return ret && ret.nodeValue !== "" ? + return ret && (fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified) ? ret.nodeValue : undefined; }, diff --git a/src/sizzle b/src/sizzle index 93cc46709..3375f91f7 160000 --- a/src/sizzle +++ b/src/sizzle @@ -1 +1 @@ -Subproject commit 93cc46709e03173288111f8b60d4192fea2ec8d0 +Subproject commit 3375f91f7c0503da1cd34ae9b6bbbd7be07bf64d diff --git a/src/sizzle-jquery.js b/src/sizzle-jquery.js index f15b08252..7090e1c63 100644 --- a/src/sizzle-jquery.js +++ b/src/sizzle-jquery.js @@ -1,3 +1,6 @@ +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; diff --git a/test/data/selector.html b/test/data/selector.html new file mode 100644 index 000000000..b62e1fa4e --- /dev/null +++ b/test/data/selector.html @@ -0,0 +1,132 @@ + + + + + jQuery selector + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+ + + +
+ + + + + +
    + +
    + +
    + + + + + + + + + + + + + + + +
    +
    Term
    This is the first definition in compact format.
    +
    Term
    This is the second definition in compact format.
    +
    + + + + Scrolling text (non-standard) + + diff --git a/test/data/testinit.js b/test/data/testinit.js index c478390d5..c30747d09 100644 --- a/test/data/testinit.js +++ b/test/data/testinit.js @@ -20,8 +20,7 @@ function q() { /** * Asserts that a select matches the given IDs * @example t("Check for something", "//[a]", ["foo", "baar"]); - * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baa -r' + * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baar' */ function t(a,b,c) { var f = jQuery(b).get(), s = ""; diff --git a/test/index.html b/test/index.html index 4bbef54cd..05a444e01 100644 --- a/test/index.html +++ b/test/index.html @@ -41,6 +41,7 @@ + @@ -136,7 +137,7 @@ diff --git a/test/unit/attributes.js b/test/unit/attributes.js index 2af36f1c2..6565d5db8 100644 --- a/test/unit/attributes.js +++ b/test/unit/attributes.js @@ -55,10 +55,10 @@ test("attr(String)", function() { // [7472] & [3113] (form contains an input with name="action" or name="id") var extras = jQuery("").appendTo("#testForm"); - equals( jQuery("#form").attr("action","newformaction").attr("action"), "newformaction", "Check that action attribute was changed" ); - equals( jQuery("#testForm").attr("target"), undefined, "Retrieving target does not equal the input with name=target" ); - equals( jQuery("#testForm").attr("target", "newTarget").attr("target"), "newTarget", "Set target successfully on a form" ); - equals( jQuery("#testForm").removeAttr("id").attr("id"), undefined, "Retrieving id does not equal the input with name=id after id is removed [#7472]" ); + equal( jQuery("#form").attr("action","newformaction").attr("action"), "newformaction", "Check that action attribute was changed" ); + equal( jQuery("#testForm").attr("target"), undefined, "Retrieving target does not equal the input with name=target" ); + equal( jQuery("#testForm").attr("target", "newTarget").attr("target"), "newTarget", "Set target successfully on a form" ); + equal( jQuery("#testForm").removeAttr("id").attr("id"), undefined, "Retrieving id does not equal the input with name=id after id is removed [#7472]" ); // Bug #3685 (form contains input with name="name") equals( jQuery("#testForm").attr("name"), undefined, "Retrieving name does not retrieve input with name=name" ); extras.remove(); @@ -157,7 +157,7 @@ test("attr(Hash)", function() { }); test("attr(String, Object)", function() { - expect(75); + expect(76); var div = jQuery("div").attr("foo", "bar"), fail = false; @@ -177,8 +177,9 @@ test("attr(String, Object)", function() { equals( jQuery("#name").attr("name"), "something", "Set name attribute" ); jQuery("#name").attr("name", null); equals( jQuery("#name").attr("name"), undefined, "Remove name attribute" ); - var $input = jQuery("", { name: "something" }); - equals( $input.attr("name"), "something", "Check element creation gets/sets the name attribute." ); + var $input = jQuery("", { name: "something", id: "specified" }); + equal( $input.attr("name"), "something", "Check element creation gets/sets the name attribute." ); + equal( $input.attr("id"), "specified", "Check element creation gets/sets the id attribute." ); jQuery("#check2").prop("checked", true).prop("checked", false).attr("checked", true); equals( document.getElementById("check2").checked, true, "Set checked attribute" ); diff --git a/test/unit/selector.js b/test/unit/selector.js new file mode 100644 index 000000000..441258008 --- /dev/null +++ b/test/unit/selector.js @@ -0,0 +1,133 @@ +/** + * This test page is for selector tests that address selector issues that have already been addressed in jQuery functions + * and which only work because jQuery has hooked into Sizzle. + * These tests may or may not fail in an independent Sizzle. + */ + +module("selector - jQuery only", { teardown: moduleTeardown }); + +/** + * Loads an iframe for the selector context + * @param {String} fileName - Name of the html file to load + * @param {String} name - Test name + * @param {Function} fn - Test callback containing the tests to run + */ +var testIframe = function( fileName, name, fn ) { + + var loadFixture = function() { + + // Creates iframe with cache disabled + var src = "./data/" + fileName + ".html?" + parseInt( Math.random()*1000, 10 ), + iframe = jQuery("