-
var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
"(?:[\\w*_-]|\\\\.)" :
"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
jQuery.extend({
expr: {
- "": "m[2]=='*'||jQuery.nodeName(a,m[2])",
- "#": "a.getAttribute('id')==m[2]",
+ "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
+ "#": function(a,i,m){return a.getAttribute("id")==m[2];},
":": {
// Position Checks
- lt: "i<m[3]-0",
- gt: "i>m[3]-0",
- nth: "m[3]-0==i",
- eq: "m[3]-0==i",
- first: "i==0",
- last: "i==r.length-1",
- even: "i%2==0",
- odd: "i%2",
+ lt: function(a,i,m){return i<m[3]-0;},
+ gt: function(a,i,m){return i>m[3]-0;},
+ nth: function(a,i,m){return m[3]-0==i;},
+ eq: function(a,i,m){return m[3]-0==i;},
+ first: function(a,i){return i==0;},
+ last: function(a,i,m,r){return i==r.length-1;},
+ even: function(a,i){return i%2==0;},
+ odd: function(a,i){return i%2;},
// Child Checks
- "first-child": "a.parentNode.getElementsByTagName('*')[0]==a",
- "last-child": "jQuery.nth(a.parentNode.lastChild,1,'previousSibling')==a",
- "only-child": "!jQuery.nth(a.parentNode.lastChild,2,'previousSibling')",
+ "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
+ "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
+ "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
// Parent Checks
- parent: "a.firstChild",
- empty: "!a.firstChild",
+ parent: function(a){return a.firstChild;},
+ empty: function(a){return !a.firstChild;},
// Text Check
- contains: "(a.textContent||a.innerText||jQuery(a).text()||'').indexOf(m[3])>=0",
+ contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
// Visibility
- visible: '"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"',
- hidden: '"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"',
+ visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
+ hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
// Form attributes
- enabled: "!a.disabled",
- disabled: "a.disabled",
- checked: "a.checked",
- selected: "a.selected||jQuery.attr(a,'selected')",
+ enabled: function(a){return !a.disabled;},
+ disabled: function(a){return a.disabled;},
+ checked: function(a){return a.checked;},
+ selected: function(a){return a.selected||jQuery.attr(a,"selected");},
// Form elements
- text: "'text'==a.type",
- radio: "'radio'==a.type",
- checkbox: "'checkbox'==a.type",
- file: "'file'==a.type",
- password: "'password'==a.type",
- submit: "'submit'==a.type",
- 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)",
+ text: function(a){return "text"==a.type;},
+ radio: function(a){return "radio"==a.type;},
+ checkbox: function(a){return "checkbox"==a.type;},
+ file: function(a){return "file"==a.type;},
+ password: function(a){return "password"==a.type;},
+ submit: function(a){return "submit"==a.type;},
+ image: function(a){return "image"==a.type;},
+ reset: function(a){return "reset"==a.type;},
+ button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
+ input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
// :has()
- has: "jQuery.find(m[3],a).length",
+ has: function(a,i,m){return jQuery.find(m[3],a).length;},
// :header
- header: "/h\\d/i.test(a.nodeName)",
+ header: function(a){return /h\d/i.test(a.nodeName);},
// :animated
- animated: "jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length"
+ animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
}
},
-
+
// The regular expressions that power the parsing engine
parse: [
// Match: [@value='test'], [@foo]
// Match: :contains('foo')
/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
- // Match: :even, :last-chlid, #id, .class
+ // Match: :even, :last-child, #id, .class
new RegExp("^([:.#]*)(" + chars + "+)")
],
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
t = jQuery.trim(t);
- var foundToken = false;
+ var foundToken = false,
// An attempt at speeding up child selectors that
// point to a specific element tag
- var re = quickChild;
- var m = re.exec(t);
+ re = quickChild,
+
+ 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++ ) {
var id = jQuery.data(n);
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 );
}
-
+
if ( m == "+" ) break;
}
}
// Optimize for the case nodeName#idName
var re2 = quickID;
var m = re2.exec(t);
-
+
// 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
if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
// Optimization for HTML document case
var oid = elem.getElementById(m[2]);
-
+
// Do a quick check for the existence of the actual ID attribute
// to avoid selecting by the name attribute in IE
// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
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] == "." )
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|selected/.test(m[2]) )
z = jQuery.attr(a,m[2]) || '';
(type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
tmp.push( a );
}
-
+
r = tmp;
// 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 )
// Otherwise, find the expression to execute
} else {
- var f = jQuery.expr[m[1]];
- if ( typeof f != "string" )
- f = jQuery.expr[m[1]][m[2]];
+ var fn = jQuery.expr[ m[1] ];
+ if ( typeof fn == "object" )
+ fn = fn[ m[2] ];
- // Build a custom macro to enclose it
- f = eval("false||function(a,i){return " + f + "}");
+ if ( typeof fn == "string" )
+ fn = eval("false||function(a,i){return " + fn + ";}");
// Execute it against the current filter
- r = jQuery.grep( r, f, not );
+ r = jQuery.grep( r, function(elem, i){
+ return fn(elem, i, m, r);
+ }, not );
}
}
},
dir: function( elem, dir ){
- var matched = [];
- var cur = elem[dir];
+ var matched = [],
+ cur = elem[dir];
while ( cur && cur != document ) {
if ( cur.nodeType == 1 )
matched.push( cur );
}
return matched;
},
-
+
nth: function(cur,result,dir,elem){
result = result || 1;
var num = 0;
return cur;
},
-
+
sibling: function( n, elem ) {
var r = [];
for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType == 1 && (!elem || n != elem) )
+ if ( n.nodeType == 1 && n != elem )
r.push( n );
}