From 213af0e4bcd1efc9a648ab1c753c6f4632047c10 Mon Sep 17 00:00:00 2001
From: Richard Gibson <@gmail.com>
Date: Wed, 16 Nov 2011 15:47:10 -0500
Subject: [PATCH 1/3] Test for non-qSA name selector against non-input
elements. #10799.
---
sizzle.js | 6 ++++++
test/unit/selector.js | 3 ++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/sizzle.js b/sizzle.js
index 10580704..b6df6272 100644
--- a/sizzle.js
+++ b/sizzle.js
@@ -501,6 +501,12 @@ var Expr = Sizzle.selectors = {
var ret = [],
results = context.getElementsByName( match[1] );
+ // sometimes IE places a DOM element at "length"
+ // observed in IE8 during Sizzle QUnit tests
+ if ( isNaN(results.length) ) {
+ results = makeArray( results );
+ }
+
for ( var i = 0, l = results.length; i < l; i++ ) {
if ( results[i].getAttribute("name") === match[1] ) {
ret.push( results[i] );
diff --git a/test/unit/selector.js b/test/unit/selector.js
index a1f464f1..827d6e1c 100644
--- a/test/unit/selector.js
+++ b/test/unit/selector.js
@@ -187,13 +187,14 @@ test("class", function() {
});
test("name", function() {
- expect(15);
+ expect(16);
t( "Name selector", "input[name=action]", ["text1"] );
t( "Name selector with single quotes", "input[name='action']", ["text1"] );
t( "Name selector with double quotes", 'input[name="action"]', ["text1"] );
t( "Name selector non-input", "[name=test]", ["length", "fx-queue"] );
+ t( "Name selector non-input non-qSA", ":not(:selected)[name=test]", ["length", "fx-queue"] );
t( "Name selector non-input", "[name=div]", ["fadein"] );
t( "Name selector non-input", "*[name=iframe]", ["iframe"] );
From 9a6e86d9c85c34cdd8ca9ef273279749f57bcfaf Mon Sep 17 00:00:00 2001
From: Richard Gibson <@gmail.com>
Date: Wed, 16 Nov 2011 15:53:16 -0500
Subject: [PATCH 2/3] Don't optimize with getElementsByName when it is limited
to form controls. Fixes #10799.
---
sizzle.js | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/sizzle.js b/sizzle.js
index b6df6272..84afe209 100644
--- a/sizzle.js
+++ b/sizzle.js
@@ -1055,18 +1055,20 @@ if ( document.documentElement.compareDocumentPosition ) {
// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
+// Also provide a workaround when the browser limits
+// getElementsByName to form controls
(function(){
// We're going to inject a fake input element with a specified name
var form = document.createElement("div"),
id = "script" + (new Date()).getTime(),
root = document.documentElement;
- form.innerHTML = "";
+ form.innerHTML = "
";
// Inject it into the root element, check its status, and remove it quickly
root.insertBefore( form, root.firstChild );
- // The workaround has to do additional checks after a getElementById
+ // The getElementById workaround has to do additional checks
// Which slows things down for other browsers (hence the branching)
if ( document.getElementById( id ) ) {
Expr.find.ID = function( match, context, isXML ) {
@@ -1088,6 +1090,12 @@ if ( document.documentElement.compareDocumentPosition ) {
};
}
+ // The getElementsByName workaround removes [name=*] optimization
+ // Which slows things down for other browsers (hence the branching)
+ if ( typeof document.getElementsByName === "undefined" || document.getElementsByName( id ).length !== 2 ) {
+ Expr.order.splice(1, 1);
+ }
+
root.removeChild( form );
// release memory in IE
From cdd2020fa4b6bbadb76b55cd6c6be7aecaa3e67a Mon Sep 17 00:00:00 2001
From: Richard Gibson
Date: Sat, 10 Dec 2011 18:08:30 -0500
Subject: [PATCH 3/3] smaller file size increase
---
sizzle.js | 146 ++++++++++++++++++++++++------------------------------
1 file changed, 66 insertions(+), 80 deletions(-)
diff --git a/sizzle.js b/sizzle.js
index 84afe209..e3fe7f5a 100644
--- a/sizzle.js
+++ b/sizzle.js
@@ -34,7 +34,7 @@ var Sizzle = function( selector, context, results, seed ) {
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
return [];
}
-
+
if ( !selector || typeof selector !== "string" ) {
return results;
}
@@ -44,7 +44,7 @@ var Sizzle = function( selector, context, results, seed ) {
contextXML = Sizzle.isXML( context ),
parts = [],
soFar = selector;
-
+
// Reset the position of the chunker regexp (start from head)
do {
chunker.exec( "" );
@@ -52,9 +52,9 @@ var Sizzle = function( selector, context, results, seed ) {
if ( m ) {
soFar = m[3];
-
+
parts.push( m[1] );
-
+
if ( m[2] ) {
extra = m[3];
break;
@@ -78,7 +78,7 @@ var Sizzle = function( selector, context, results, seed ) {
if ( Expr.relative[ selector ] ) {
selector += parts.shift();
}
-
+
set = posProcess( selector, set, seed );
}
}
@@ -206,7 +206,7 @@ Sizzle.find = function( expr, context, isXML ) {
for ( i = 0, len = Expr.order.length; i < len; i++ ) {
type = Expr.order[i];
-
+
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
left = match[1];
match.splice( 1, 1 );
@@ -333,7 +333,7 @@ Sizzle.error = function( msg ) {
* @param {Array|Element} elem
*/
var getText = Sizzle.getText = function( elem ) {
- var i, node,
+ var i, node,
nodeType = elem.nodeType,
ret = "";
@@ -368,7 +368,7 @@ var getText = Sizzle.getText = function( elem ) {
};
var Expr = Sizzle.selectors = {
- order: [ "ID", "NAME", "TAG" ],
+ order: [ "ID", "TAG" ],
match: {
ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
@@ -489,7 +489,7 @@ var Expr = Sizzle.selectors = {
find: {
ID: function( match, context, isXML ) {
if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
+ var m = context.getElementById( match[1] );
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
return m && m.parentNode ? [m] : [];
@@ -497,30 +497,15 @@ var Expr = Sizzle.selectors = {
},
NAME: function( match, context ) {
- if ( typeof context.getElementsByName !== "undefined" ) {
- var ret = [],
- results = context.getElementsByName( match[1] );
-
- // sometimes IE places a DOM element at "length"
- // observed in IE8 during Sizzle QUnit tests
- if ( isNaN(results.length) ) {
- results = makeArray( results );
- }
-
- for ( var i = 0, l = results.length; i < l; i++ ) {
- if ( results[i].getAttribute("name") === match[1] ) {
- ret.push( results[i] );
- }
- }
-
- return ret.length === 0 ? null : ret;
- }
+ try {
+ return context.getElementsByName( match[1] );
+ } catch( getElementsByNameError ) {}
},
TAG: function( match, context ) {
- if ( typeof context.getElementsByTagName !== "undefined" ) {
+ try {
return context.getElementsByTagName( match[1] );
- }
+ } catch( getElementsByTagNameError ) {}
}
},
preFilter: {
@@ -584,7 +569,7 @@ var Expr = Sizzle.selectors = {
ATTR: function( match, curLoop, inplace, result, not, isXML ) {
var name = match[1] = match[1].replace( rBackslash, "" );
-
+
if ( !isXML && Expr.attrMap[name] ) {
match[1] = Expr.attrMap[name];
}
@@ -618,7 +603,7 @@ var Expr = Sizzle.selectors = {
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
return true;
}
-
+
return match;
},
@@ -628,7 +613,7 @@ var Expr = Sizzle.selectors = {
return match;
}
},
-
+
filters: {
enabled: function( elem ) {
return elem.disabled === false && elem.type !== "hidden";
@@ -641,14 +626,14 @@ var Expr = Sizzle.selectors = {
checked: function( elem ) {
return elem.checked === true;
},
-
+
selected: function( elem ) {
// Accessing this property makes selected-by-default
// options in Safari work properly
if ( elem.parentNode ) {
elem.parentNode.selectedIndex;
}
-
+
return elem.selected === true;
},
@@ -670,7 +655,7 @@ var Expr = Sizzle.selectors = {
text: function( elem ) {
var attr = elem.getAttribute( "type" ), type = elem.type;
- // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
// use getAttribute instead to test this case
return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
},
@@ -788,22 +773,23 @@ var Expr = Sizzle.selectors = {
switch ( type ) {
case "only":
case "first":
- while ( (node = node.previousSibling) ) {
- if ( node.nodeType === 1 ) {
- return false;
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
}
}
- if ( type === "first" ) {
- return true;
+ if ( type === "first" ) {
+ return true;
}
node = elem;
+ /* falls through */
case "last":
- while ( (node = node.nextSibling) ) {
- if ( node.nodeType === 1 ) {
- return false;
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
}
}
@@ -816,22 +802,22 @@ var Expr = Sizzle.selectors = {
if ( first === 1 && last === 0 ) {
return true;
}
-
+
doneName = match[0];
parent = elem.parentNode;
-
+
if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
count = 0;
-
+
for ( node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType === 1 ) {
node.nodeIndex = ++count;
}
- }
+ }
parent[ expando ] = doneName;
}
-
+
diff = elem.nodeIndex - last;
if ( first === 0 ) {
@@ -850,7 +836,7 @@ var Expr = Sizzle.selectors = {
TAG: function( elem, match ) {
return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
},
-
+
CLASS: function( elem, match ) {
return (" " + (elem.className || elem.getAttribute("class")) + " ")
.indexOf( match ) > -1;
@@ -920,7 +906,7 @@ var makeArray = function( array, results ) {
results.push.apply( results, array );
return results;
}
-
+
return array;
};
@@ -1053,27 +1039,33 @@ if ( document.documentElement.compareDocumentPosition ) {
};
}
-// Check to see if the browser returns elements by name when
-// querying by getElementById (and provide a workaround)
-// Also provide a workaround when the browser limits
-// getElementsByName to form controls
+// Optimize for browsers with compatible getElementsByName
+// Workaround browsers that return by name from getElementById
(function(){
- // We're going to inject a fake input element with a specified name
+ // We're going to inject an input and non-input element with the same name
var form = document.createElement("div"),
- id = "script" + (new Date()).getTime(),
- root = document.documentElement;
+ id = "script" + ( - new Date() );
+ form.id = id + 0;
form.innerHTML = "";
// Inject it into the root element, check its status, and remove it quickly
- root.insertBefore( form, root.firstChild );
+ document.documentElement.insertBefore( form, document.documentElement.firstChild );
+
+ // Optimize NAME checks if the browser provides a compatible getElementsByName
+ // (returning all elements with matching name and not the one with matching id)
+ if ( document.getElementsByName &&
+ document.getElementsByName( id ).length === 2 + document.getElementsByName( id + 0 ).length ) {
+
+ Expr.order.splice(1, 0, "NAME");
+ }
// The getElementById workaround has to do additional checks
// Which slows things down for other browsers (hence the branching)
if ( document.getElementById( id ) ) {
Expr.find.ID = function( match, context, isXML ) {
if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
+ var m = context.getElementById( match[1] );
return m ?
m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
@@ -1090,16 +1082,10 @@ if ( document.documentElement.compareDocumentPosition ) {
};
}
- // The getElementsByName workaround removes [name=*] optimization
- // Which slows things down for other browsers (hence the branching)
- if ( typeof document.getElementsByName === "undefined" || document.getElementsByName( id ).length !== 2 ) {
- Expr.order.splice(1, 1);
- }
-
- root.removeChild( form );
+ document.documentElement.removeChild( form );
// release memory in IE
- root = form = null;
+ form = null;
})();
(function(){
@@ -1160,7 +1146,7 @@ if ( document.querySelectorAll ) {
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
return;
}
-
+
Sizzle = function( query, context, extra, seed ) {
context = context || document;
@@ -1169,24 +1155,24 @@ if ( document.querySelectorAll ) {
if ( !seed && !Sizzle.isXML(context) ) {
// See if we find a selector to speed up
var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
-
+
if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
// Speed-up: Sizzle("TAG")
if ( match[1] ) {
return makeArray( context.getElementsByTagName( query ), extra );
-
+
// Speed-up: Sizzle(".CLASS")
} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
return makeArray( context.getElementsByClassName( match[2] ), extra );
}
}
-
+
if ( context.nodeType === 9 ) {
// Speed-up: Sizzle("body")
// The body element only exists once, optimize finding it
if ( query === "body" && context.body ) {
return makeArray( [ context.body ], extra );
-
+
// Speed-up: Sizzle("#ID")
} else if ( match && match[3] ) {
var elem = context.getElementById( match[3] );
@@ -1199,12 +1185,12 @@ if ( document.querySelectorAll ) {
if ( elem.id === match[3] ) {
return makeArray( [ elem ], extra );
}
-
+
} else {
return makeArray( [], extra );
}
}
-
+
try {
return makeArray( context.querySelectorAll(query), extra );
} catch(qsaError) {}
@@ -1242,7 +1228,7 @@ if ( document.querySelectorAll ) {
}
}
}
-
+
return oldSizzle(query, context, extra, seed);
};
@@ -1269,7 +1255,7 @@ if ( document.querySelectorAll ) {
// This should fail with an exception
// Gecko does not error, returns false instead
matches.call( document.documentElement, "[test!='']:sizzle" );
-
+
} catch( pseudoError ) {
pseudoWorks = true;
}
@@ -1279,7 +1265,7 @@ if ( document.querySelectorAll ) {
expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
if ( !Sizzle.isXML( node ) ) {
- try {
+ try {
if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
var ret = matches.call( node, expr );
@@ -1316,7 +1302,7 @@ if ( document.querySelectorAll ) {
if ( div.getElementsByClassName("e").length === 1 ) {
return;
}
-
+
Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function( match, context, isXML ) {
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
@@ -1367,7 +1353,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
if ( elem ) {
var match = false;
-
+
elem = elem[dir];
while ( elem ) {
@@ -1420,7 +1406,7 @@ if ( document.documentElement.contains ) {
Sizzle.isXML = function( elem ) {
// documentElement is verified for cases where it doesn't yet exist
- // (such as loading iframes in IE - #4833)
+ // (such as loading iframes in IE - #4833)
var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
return documentElement ? documentElement.nodeName !== "HTML" : false;