X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fselector.js;h=0cce515dd06eaefbe7e1673b96ad1f512be074b3;hb=58a17e6e6d57d0ba71acfcb36f7da4fcacfbeeae;hp=e1e272bcbcc961d2e748980f3023ccc763b95455;hpb=2e42c5b0445b7c871c67b0a3bb7a0dc42d1d2112;p=jquery.git diff --git a/src/selector.js b/src/selector.js index e1e272b..0cce515 100644 --- a/src/selector.js +++ b/src/selector.js @@ -1,12 +1,12 @@ /*! - * Sizzle CSS Selector Engine - v0.9.1 + * Sizzle CSS Selector Engine - v0.9.2 * Copyright 2009, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){ -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|[^[\]]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g, +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g, done = 0, toString = Object.prototype.toString; @@ -35,40 +35,27 @@ var Sizzle = function(selector, context, results, seed) { } } - if ( parts.length > 1 && Expr.match.POS.exec( selector ) ) { + if ( parts.length > 1 && origPOS.exec( selector ) ) { if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - var later = "", match; - - // Position selectors must be done after the filter - while ( (match = Expr.match.POS.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.POS, "" ); - } - - set = Sizzle.filter( later, Sizzle( selector, context ) ); + set = posProcess( parts[0] + parts[1], context ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : Sizzle( parts.shift(), context ); while ( parts.length ) { - var tmpSet = []; - selector = parts.shift(); + if ( Expr.relative[ selector ] ) selector += parts.shift(); - for ( var i = 0, l = set.length; i < l; i++ ) { - Sizzle( selector, set[i], tmpSet ); - } - - set = tmpSet; + set = posProcess( selector, set ); } } } else { var ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context ); + Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) ); set = Sizzle.filter( ret.expr, ret.set ); if ( parts.length > 0 ) { @@ -133,7 +120,7 @@ Sizzle.matches = function(expr, set){ return Sizzle(expr, null, null, set); }; -Sizzle.find = function(expr, context){ +Sizzle.find = function(expr, context, isXML){ var set, match; if ( !expr ) { @@ -148,7 +135,7 @@ Sizzle.find = function(expr, context){ if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace(/\\/g, ""); - set = Expr.find[ type ]( match, context ); + set = Expr.find[ type ]( match, context, isXML ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; @@ -170,7 +157,7 @@ Sizzle.filter = function(expr, set, inplace, not){ while ( expr && set.length ) { for ( var type in Expr.filter ) { if ( (match = Expr.match[ type ].exec( expr )) != null ) { - var filter = Expr.filter[ type ], goodArray = null, goodPos = 0, found, item; + var filter = Expr.filter[ type ], found, item; anyFound = false; if ( curLoop == result ) { @@ -182,26 +169,15 @@ Sizzle.filter = function(expr, set, inplace, not){ if ( !match ) { anyFound = found = true; - } else if ( match[0] === true ) { - goodArray = []; - var last = null, elem; - for ( var i = 0; (elem = curLoop[i]) !== undefined; i++ ) { - if ( elem && last !== elem ) { - goodArray.push( elem ); - last = elem; - } - } + } else if ( match === true ) { + continue; } } if ( match ) { - for ( var i = 0; (item = curLoop[i]) !== undefined; i++ ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { if ( item ) { - if ( goodArray && item != goodArray[goodPos] ) { - goodPos++; - } - - found = filter( item, match, goodPos, goodArray ); + found = filter( item, match, i, curLoop ); var pass = not ^ !!found; if ( inplace && found != null ) { @@ -257,7 +233,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*)\))?(?=[^-]|$)/, @@ -267,6 +243,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++ ) { @@ -320,7 +301,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; @@ -330,18 +311,20 @@ var Expr = Sizzle.selectors = { checkFn = dirNodeCheck; } - checkFn("previousSibling", part, doneName, checkSet, nodeCheck); + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); } }, find: { - ID: function(match, context){ - if ( context.getElementById ) { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? [m] : []; } }, - NAME: function(match, context){ - return context.getElementsByName ? context.getElementsByName(match[1]) : null; + NAME: function(match, context, isXML){ + if ( typeof context.getElementsByName !== "undefined" && !isXML ) { + return context.getElementsByName(match[1]); + } }, TAG: function(match, context){ return context.getElementsByTagName(match[1]); @@ -351,12 +334,15 @@ var Expr = Sizzle.selectors = { CLASS: function(match, curLoop, inplace, result, not){ match = " " + match[1].replace(/\\/g, "") + " "; - for ( var i = 0; curLoop[i]; i++ ) { - if ( not ^ (" " + curLoop[i].className + " ").indexOf(match) >= 0 ) { - if ( !inplace ) - result.push( curLoop[i] ); - } else if ( inplace ) { - curLoop[i] = false; + var elem; + for ( var i = 0; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (" " + elem.className + " ").indexOf(match) >= 0 ) { + if ( !inplace ) + result.push( elem ); + } else if ( inplace ) { + curLoop[i] = false; + } } } @@ -366,8 +352,8 @@ var Expr = Sizzle.selectors = { return match[1].replace(/\\/g, ""); }, TAG: function(match, curLoop){ - for ( var i = 0; !curLoop[i]; i++ ){} - return isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); + for ( var i = 0; curLoop[i] === false; i++ ){} + return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); }, CHILD: function(match){ if ( match[1] == "nth" ) { @@ -387,7 +373,7 @@ var Expr = Sizzle.selectors = { return match; }, ATTR: function(match){ - var name = match[1]; + var name = match[1].replace(/\\/g, ""); if ( Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; @@ -411,6 +397,8 @@ var Expr = Sizzle.selectors = { } return false; } + } else if ( Expr.match.POS.test( match[0] ) ) { + return true; } return match; @@ -511,7 +499,7 @@ var Expr = Sizzle.selectors = { var doneName = match[0]; - if ( parent && !parent[ doneName ] ) { + if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) { var count = 1; for ( var node = parent.firstChild; node; node = node.nextSibling ) { @@ -576,9 +564,9 @@ 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 === "!=" : type === "=" ? value === check : type === "*=" ? @@ -607,6 +595,8 @@ var Expr = Sizzle.selectors = { } }; +var origPOS = Expr.match.POS; + for ( var type in Expr.match ) { Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); } @@ -681,9 +671,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("") ); @@ -709,15 +700,32 @@ try { return results; }; } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + if ( div.firstChild && div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } })(); if ( document.querySelectorAll ) (function(){ - var oldSizzle = Sizzle; + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "

"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } Sizzle = function(query, context, extra, seed){ context = context || document; - if ( !seed && context.nodeType === 9 ) { + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && context.nodeType === 9 && !isXML(context) ) { try { return makeArray( context.querySelectorAll(query), extra ); } catch(e){} @@ -732,14 +740,14 @@ if ( document.querySelectorAll ) (function(){ Sizzle.matches = oldSizzle.matches; })(); -if ( document.documentElement.getElementsByClassName ) { +if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) { Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function(match, context) { return context.getElementsByClassName(match[1]); }; } -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 ) { @@ -753,7 +761,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 ) { @@ -769,7 +777,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 ) { @@ -783,7 +791,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 ) { @@ -812,8 +821,28 @@ var contains = document.compareDocumentPosition ? function(a, b){ }; var isXML = function(elem){ - return elem.documentElement && !elem.body || - elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; + return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || + !!elem.ownerDocument && isXML( elem.ownerDocument ); +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); }; // EXPOSE