X-Git-Url: http://git.asbjorn.it/?a=blobdiff_plain;f=src%2Fselector%2Fselector.js;h=33017aa60af1c7d96fd4d5aeedaa034a4c85e5d2;hb=13b66c8ba9618242df2c1cc352a2b1d879c36188;hp=e6d2d0697708677c271921601e6db3aa13fc7bdb;hpb=7b9d8258909a626f3f380c763ed81150570bbad5;p=jquery.git diff --git a/src/selector/selector.js b/src/selector/selector.js index e6d2d06..33017aa 100644 --- a/src/selector/selector.js +++ b/src/selector/selector.js @@ -1,3 +1,11 @@ + +var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ? + "(?:[\\w*_-]|\\\\.)" : + "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)", + quickChild = new RegExp("^>\\s*(" + chars + "+)"), + quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"), + quickClass = new RegExp("^([#.]?)(" + chars + "*)"); + jQuery.extend({ expr: { "": "m[2]=='*'||jQuery.nodeName(a,m[2])", @@ -45,25 +53,29 @@ jQuery.extend({ image: "'image'==a.type", reset: "'reset'==a.type", button: '"button"==a.type||jQuery.nodeName(a,"button")', - input: "/input|select|textarea|button/i.test(a.nodeName)" - }, - "[": "jQuery.find(m[2],a).length" + input: "/input|select|textarea|button/i.test(a.nodeName)", + + // :has() + has: "jQuery.find(m[3],a).length", + + // :header + header: "/h\\d/i.test(a.nodeName)", + + // :animated + animated: "jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length" + } }, // The regular expressions that power the parsing engine parse: [ // Match: [@value='test'], [@foo] - /^\[ *(@)([\w-]+) *([!*$^=]*) *('?"?)(.*?)\4 *\]/, - - // Match: [div], [div p] - /^(\[)\s*(.*?(\[.*?\])?[^[]*?)\s*\]/, + /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/, // Match: :contains('foo') /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/, // Match: :even, :last-chlid, #id, .class - new RegExp("^([:.#]*)(" + - ( jQuery.chars = "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)" ) + "+)") + new RegExp("^([:.#]*)(" + chars + "+)") ], multiFilter: function( expr, elems, not ) { @@ -79,12 +91,6 @@ jQuery.extend({ return cur; }, - /** - * @name $.find - * @type Array - * @private - * @cat Core - */ find: function( t, context ) { // Quickly handle non-string expressions if ( typeof t != "string" ) @@ -97,19 +103,6 @@ jQuery.extend({ // Set the correct context (if none is provided) context = context || document; - // Handle the common XPath // expression - if ( !t.indexOf("//") ) { - context = context.documentElement; - t = t.substr(2,t.length); - - // And the / root expression - } else if ( !t.indexOf("/") && !context.ownerDocument ) { - context = context.documentElement; - t = t.substr(1,t.length); - if ( t.indexOf("/") >= 1 ) - t = t.substr(t.indexOf("/"),t.length); - } - // Initialize the search var ret = [context], done = [], last; @@ -119,13 +112,13 @@ jQuery.extend({ var r = []; last = t; - t = jQuery.trim(t).replace( /^\/\//, "" ); + t = jQuery.trim(t); var foundToken = false; // An attempt at speeding up child selectors that // point to a specific element tag - var re = new RegExp("^[/>]\\s*(" + jQuery.chars + "+)"); + var re = quickChild; var m = re.exec(t); if ( m ) { @@ -134,7 +127,7 @@ jQuery.extend({ // Perform our own iteration and filter for ( var i = 0; ret[i]; i++ ) for ( var c = ret[i].firstChild; c; c = c.nextSibling ) - if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName == nodeName.toUpperCase()) ) + if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName.toUpperCase()) ) r.push( c ); ret = r; @@ -142,30 +135,28 @@ jQuery.extend({ if ( t.indexOf(" ") == 0 ) continue; foundToken = true; } else { - re = /^((\/?\.\.)|([>\/+~]))\s*([a-z]*)/i; + re = /^([>+~])\s*(\w*)/i; if ( (m = re.exec(t)) != null ) { r = []; - var nodeName = m[4], mergeNum = jQuery.mergeNum++; + var nodeName = m[2], mergeNum = jQuery.mergeNum++; m = m[1]; - for ( var j = 0, rl = ret.length; j < rl; j++ ) - if ( m.indexOf("..") < 0 ) { - var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild; - for ( ; n; n = n.nextSibling ) - if ( n.nodeType == 1 ) { - if ( m == "~" && n.mergeNum == mergeNum ) break; - - if (!nodeName || n.nodeName == nodeName.toUpperCase() ) { - if ( m == "~" ) n.mergeNum = mergeNum; - r.push( n ); - } - - if ( m == "+" ) break; + for ( var j = 0, rl = ret.length; j < rl; j++ ) { + var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild; + for ( ; n; n = n.nextSibling ) + if ( n.nodeType == 1 ) { + if ( m == "~" && n.mergeNum == mergeNum ) break; + + if (!nodeName || n.nodeName.toUpperCase() == nodeName.toUpperCase() ) { + if ( m == "~" ) n.mergeNum = mergeNum; + r.push( n ); } - } else - r.push( ret[j].parentNode ); + + if ( m == "+" ) break; + } + } ret = r; @@ -193,8 +184,8 @@ jQuery.extend({ t = " " + t.substr(1,t.length); } else { - // Optomize for the case nodeName#idName - var re2 = new RegExp("^(" + jQuery.chars + "+)(#)(" + jQuery.chars + "+)"); + // Optimize for the case nodeName#idName + var re2 = quickID; var m = re2.exec(t); // Re-organize the results, so that they're consistent @@ -204,7 +195,7 @@ jQuery.extend({ } else { // Otherwise, do a traditional filter check for // ID, class, and element selectors - re2 = new RegExp("^([#.]?)(" + jQuery.chars + "*)"); + re2 = quickClass; m = re2.exec(t); } @@ -213,7 +204,7 @@ jQuery.extend({ var elem = ret[ret.length-1]; // Try to do a global search by ID, where we can - if ( m[1] == "#" && elem && elem.getElementById ) { + if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) { // Optimization for HTML document case var oid = elem.getElementById(m[2]); @@ -230,7 +221,7 @@ jQuery.extend({ // We need to find all descendant elements for ( var i = 0; ret[i]; i++ ) { // Grab the tag name being searched for - var tag = m[1] != "" || m[0] == "" ? "*" : m[2]; + var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2]; // Handle IE7 being really dumb about s if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" ) @@ -333,21 +324,21 @@ jQuery.extend({ else if ( m[1] == "." ) r = jQuery.classFilter(r, m[2], not); - else if ( m[1] == "@" ) { + else if ( m[1] == "[" ) { var tmp = [], type = m[3]; for ( var i = 0, rl = r.length; i < rl; i++ ) { var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ]; - if ( z == null || /href|src/.test(m[2]) ) - z = jQuery.attr(a,m[2]); + if ( z == null || /href|src|selected/.test(m[2]) ) + z = jQuery.attr(a,m[2]) || ''; if ( (type == "" && !!z || type == "=" && z == m[5] || type == "!=" && z != m[5] || type == "^=" && z && !z.indexOf(m[5]) || type == "$=" && z.substr(z.length - m[5].length) == m[5] || - type == "*=" && z.indexOf(m[5]) >= 0) ^ not ) + (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not ) tmp.push( a ); } @@ -377,7 +368,7 @@ jQuery.extend({ var add = false; if ( first == 1 ) { - if ( node.nodeIndex == last ) + if ( last == 0 || node.nodeIndex == last ) add = true; } else if ( (node.nodeIndex + last) % first == 0 ) add = true; @@ -395,7 +386,7 @@ jQuery.extend({ f = jQuery.expr[m[1]][m[2]]; // Build a custom macro to enclose it - eval("f = function(a,i){return " + f + "}"); + f = eval("false||function(a,i){return " + f + "}"); // Execute it against the current filter r = jQuery.grep( r, f, not ); @@ -407,15 +398,6 @@ jQuery.extend({ return { r: r, t: t }; }, - /** - * All ancestors of a given element. - * - * @private - * @name $.parents - * @type Array - * @param Element elem The element to find the ancestors of. - * @cat DOM/Traversing - */ parents: function( elem ){ var matched = []; var cur = elem.parentNode; @@ -426,18 +408,6 @@ jQuery.extend({ return matched; }, - /** - * A handy, and fast, way to traverse in a particular direction and find - * a specific element. - * - * @private - * @name $.nth - * @type DOMElement - * @param DOMElement cur The element to search from. - * @param String|Number num The Nth result to match. Can be a number or a string (like 'even' or 'odd'). - * @param String dir The direction to move in (pass in something like 'previousSibling' or 'nextSibling'). - * @cat DOM/Traversing - */ nth: function(cur,result,dir,elem){ result = result || 1; var num = 0; @@ -449,15 +419,6 @@ jQuery.extend({ return cur; }, - /** - * All elements on a specified axis. - * - * @private - * @name $.sibling - * @type Array - * @param Element elem The element to find all the siblings of (including itself). - * @cat DOM/Traversing - */ sibling: function( n, elem ) { var r = [];