if ( typeof t != "string" )
return [ t ];
- // Make sure that the context is a DOM Element
- if ( context && !context.nodeType )
- context = null;
+ // check to make sure context is a DOM element or a document
+ if ( context && context.nodeType != 1 && context.nodeType != 9)
+ return [ ];
// Set the correct context (if none is provided)
context = context || document;
// Initialize the search
- var ret = [context], done = [], last;
+ var ret = [context], done = [], last, nodeName;
// Continue while a selector expression exists, and while
// we're no longer looping upon ourselves
var m = re.exec(t);
if ( m ) {
- var nodeName = m[1].toUpperCase();
+ nodeName = m[1].toUpperCase();
// 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.toUpperCase() == nodeName.toUpperCase()) )
+ if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
r.push( c );
ret = r;
if ( (m = re.exec(t)) != null ) {
r = [];
- var nodeName = m[2], merge = {};
+ var merge = {};
+ nodeName = m[2].toUpperCase();
m = m[1];
for ( var j = 0, rl = ret.length; j < rl; j++ ) {
if ( m == "~" && merge[id] ) break;
- if (!nodeName || n.nodeName.toUpperCase() == nodeName.toUpperCase() ) {
+ if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
if ( m == "~" ) merge[id] = true;
r.push( n );
}
// Re-organize the results, so that they're consistent
if ( m ) {
- m = [ 0, m[2], m[3], m[1] ];
+ m = [ 0, m[2], m[3], m[1] ];
} else {
// Otherwise, do a traditional filter check for
var last;
// Look for common filter expressions
- while ( t && t != last ) {
+ while ( t && t != last ) {
last = t;
var p = jQuery.parse, m;
// :not() is a special case that can be optimized by
// keeping it out of the expression list
if ( m[1] == ":" && m[2] == "not" )
- r = jQuery.filter(m[3], r, true).r;
+ // optimize if only one selector found (most common case)
+ r = isSimple.test( m[3] ) ?
+ jQuery.filter(m[3], r, true).r :
+ jQuery( r ).not( m[3] );
// We can get a big speed boost by filtering by class here
else if ( m[1] == "." )
// We can get a speed boost by handling nth-child here
} else if ( m[1] == ":" && m[2] == "nth-child" ) {
var merge = {}, tmp = [],
- test = /(\d*)n\+?(\d*)/.exec(
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
- !/\D/.test(m[3]) && "n+" + m[3] || m[3]),
- first = (test[1] || 1) - 0, last = test[2] - 0;
-
+ !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
+ // calculate the numbers (first)n+(last) including if they are negative
+ first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
+
+ // loop through all the elements left in the jQuery object
for ( var i = 0, rl = r.length; i < rl; i++ ) {
var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
var add = false;
- if ( first == 1 ) {
- if ( last == 0 || node.nodeIndex == last )
+ if ( first == 0 ) {
+ if ( node.nodeIndex == last )
add = true;
- } else if ( (node.nodeIndex + last) % first == 0 )
+ } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
add = true;
if ( add ^ not )
return r;
}
});
+