From 6dc30ae7f60c44dd83dfb19da61957b20324eb9e Mon Sep 17 00:00:00 2001 From: John Resig Date: Tue, 13 Jan 2009 16:40:19 +0000 Subject: [PATCH] Merged Sizzle changes back into jQuery. --- src/selector.js | 37 ++++++++++++++++++++++++++----------- test/index.html | 1 + test/unit/selector.js | 25 ++++++++++++++++++++----- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/selector.js b/src/selector.js index 085f0b3..56c8a2a 100644 --- a/src/selector.js +++ b/src/selector.js @@ -45,7 +45,7 @@ var Sizzle = function(selector, context, results, seed) { selector = selector.replace( Expr.match.POS, "" ); } - set = Sizzle.filter( later, Sizzle( selector, context ) ); + set = Sizzle.filter( later, Sizzle( /\s$/.test(selector) ? selector + "*" : selector, context ) ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : @@ -259,7 +259,7 @@ var Expr = Sizzle.selectors = { ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, - ATTR: /\[((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, @@ -269,6 +269,11 @@ var Expr = Sizzle.selectors = { "class": "className", "for": "htmlFor" }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, relative: { "+": function(checkSet, part){ for ( var i = 0, l = checkSet.length; i < l; i++ ) { @@ -322,7 +327,7 @@ var Expr = Sizzle.selectors = { checkFn = dirNodeCheck; } - checkFn("parentNode", part, doneName, checkSet, nodeCheck); + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); }, "~": function(checkSet, part, isXML){ var doneName = "done" + (done++), checkFn = dirCheck; @@ -332,7 +337,7 @@ var Expr = Sizzle.selectors = { checkFn = dirNodeCheck; } - checkFn("previousSibling", part, doneName, checkSet, nodeCheck); + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); } }, find: { @@ -580,7 +585,7 @@ var Expr = Sizzle.selectors = { return match.test( elem.className ); }, ATTR: function(elem, match){ - var result = elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4]; + var result = Expr.attrHandle[ match[1] ] ? Expr.attrHandle[ match[1] ]( elem ) : elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4]; return result == null ? false : type === "=" ? @@ -685,9 +690,10 @@ try { root.removeChild( form ); })(); -// Check to see if the browser returns only elements -// when doing getElementsByTagName("*") (function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); @@ -713,6 +719,14 @@ try { return results; }; } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + if ( div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } })(); if ( document.querySelectorAll ) (function(){ @@ -743,7 +757,7 @@ if ( document.documentElement.getElementsByClassName ) { }; } -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck ) { +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { @@ -757,7 +771,7 @@ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck ) { break; } - if ( elem.nodeType === 1 ) + if ( elem.nodeType === 1 && !isXML ) elem[doneName] = i; if ( elem.nodeName === cur ) { @@ -773,7 +787,7 @@ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck ) { } } -function dirCheck( dir, cur, doneName, checkSet, nodeCheck ) { +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { @@ -787,7 +801,8 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck ) { } if ( elem.nodeType === 1 ) { - elem[doneName] = i; + if ( !isXML ) + elem[doneName] = i; if ( typeof cur !== "string" ) { if ( elem === cur ) { diff --git a/test/index.html b/test/index.html index 30e955c..cd5a247 100644 --- a/test/index.html +++ b/test/index.html @@ -54,6 +54,7 @@
    + diff --git a/test/unit/selector.js b/test/unit/selector.js index 183bacb..638f508 100644 --- a/test/unit/selector.js +++ b/test/unit/selector.js @@ -2,6 +2,8 @@ module("selector"); test("element", function() { expect(9); + reset(); + ok( jQuery("*").size() >= 30, "Select all" ); var all = jQuery("*"), good = true; for ( var i = 0; i < all.length; i++ ) @@ -39,7 +41,7 @@ test("broken", function() { name + ": " + selector ); } } - + broken( "Broken Selector", "[", [] ); broken( "Broken Selector", "(", [] ); broken( "Broken Selector", "{", [] ); @@ -139,7 +141,7 @@ test("multiple", function() { }); test("child and adjacent", function() { - expect(38); + expect(41); t( "Child", "p > a", ["simon1","google","groups","mark","yahoo","simon"] ); t( "Child", "p> a", ["simon1","google","groups","mark","yahoo","simon"] ); t( "Child", "p >a", ["simon1","google","groups","mark","yahoo","simon"] ); @@ -154,6 +156,10 @@ test("child and adjacent", function() { t( "Adjacent", "p + p", ["ap","en","sap"] ); t( "Comma, Child, and Adjacent", "a + a, code > a", ["groups","anchor1","anchor2"] ); + isSet( jQuery("> :first", document.getElementById("nothiddendiv")), q("nothiddendivchild"), "Verify child context positional selctor" ); + isSet( jQuery("> :eq(0)", document.getElementById("nothiddendiv")), q("nothiddendivchild"), "Verify child context positional selctor" ); + isSet( jQuery("> *:first", document.getElementById("nothiddendiv")), q("nothiddendivchild"), "Verify child context positional selctor" ); + t( "Non-existant ancestors", ".fototab > .thumbnails > a", [] ); t( "First Child", "p:first-child", ["firstp","sndp"] ); @@ -162,8 +168,8 @@ test("child and adjacent", function() { t( "Last Child", "p:last-child", ["sap"] ); t( "Last Child", "a:last-child", ["simon1","anchor1","mark","yahoo","anchor2","simon"] ); - t( "Nth-child", "#main form#form > *:nth-child(2)", ["text2"] ); - t( "Nth-child", "#main form#form > :nth-child(2)", ["text2"] ); + t( "Nth-child", "#main form#form > *:nth-child(2)", ["text1"] ); + t( "Nth-child", "#main form#form > :nth-child(2)", ["text1"] ); t( "Nth-child", "#form select:first option:nth-child(3)", ["option1c"] ); t( "Nth-child", "#form select:first option:nth-child(0n+3)", ["option1c"] ); @@ -186,15 +192,24 @@ test("child and adjacent", function() { }); test("attributes", function() { - expect(21); + expect(27); t( "Attribute Exists", "a[title]", ["google"] ); t( "Attribute Exists", "*[title]", ["google"] ); t( "Attribute Exists", "[title]", ["google"] ); + t( "Attribute Exists", "a[ title ]", ["google"] ); t( "Attribute Equals", "a[rel='bookmark']", ["simon1"] ); t( "Attribute Equals", 'a[rel="bookmark"]', ["simon1"] ); t( "Attribute Equals", "a[rel=bookmark]", ["simon1"] ); t( "Attribute Equals", "a[href='http://www.google.com/']", ["google"] ); + t( "Attribute Equals", "a[ rel = 'bookmark' ]", ["simon1"] ); + + document.getElementById("anchor2").href = "#2"; + t( "href Attribute", "p a[href^=#]", ["anchor2"] ); + t( "href Attribute", "p a[href*=#]", ["simon1", "anchor2"] ); + + t( "for Attribute", "form label[for]", ["label-for"] ); + t( "for Attribute in form", "#form [for=action]", ["label-for"] ); var results = ["hidden1","radio1","radio2"]; -- 1.7.10.4