/* * Sizzle CSS Selector Engine - v0.9 * Copyright 2009, John Resig (http://ejohn.org/) * released under the MIT License */ (function(){ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]+\]|[^[\]]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g; var done = 0; var Sizzle = function(selector, context, results, seed) { results = results || []; context = context || document; if ( context.nodeType !== 1 && context.nodeType !== 9 ) return []; if ( !selector || typeof selector !== "string" ) { return results; } var parts = [], m, set, checkSet, check, mode, extra; // Reset the position of the chunker regexp (start from head) chunker.lastIndex = 0; while ( (m = chunker.exec(selector)) !== null ) { parts.push( m[1] ); if ( m[2] ) { extra = RegExp.rightContext; break; } } if ( parts.length > 1 && Expr.match.POS.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 ) ); } 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; } } } else { var ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context ); set = Sizzle.filter( ret.expr, ret.set ); if ( parts.length > 0 ) { checkSet = makeArray(set); } while ( parts.length ) { var cur = parts.pop(), pop = cur; if ( !Expr.relative[ cur ] ) { cur = ""; } else { pop = parts.pop(); } if ( pop == null ) { pop = context; } Expr.relative[ cur ]( checkSet, pop ); } } if ( !checkSet ) { checkSet = set; } if ( !checkSet ) { throw "Syntax error, unrecognized expression: " + (cur || selector); } if ( checkSet instanceof Array ) { if ( context.nodeType === 1 ) { for ( var i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { results.push( set[i] ); } } } else { for ( var i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && checkSet[i].nodeType === 1 ) { results.push( set[i] ); } } } } else { makeArray( checkSet, results ); } if ( extra ) { Sizzle( extra, context, results ); } return results; }; Sizzle.matches = function(expr, set){ return Sizzle(expr, null, null, set); }; Sizzle.find = function(expr, context){ var set, match; if ( !expr ) { return []; } var later = "", match; // Pseudo-selectors could contain other selectors (like :not) while ( (match = Expr.match.PSEUDO.exec( expr )) ) { var left = RegExp.leftContext; if ( left.substr( left.length - 1 ) !== "\\" ) { later += match[0]; expr = expr.replace( Expr.match.PSEUDO, "" ); } else { // TODO: Need a better solution, fails: .class\:foo:realfoo(#id) break; } } for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var type = Expr.order[i]; if ( (match = Expr.match[ type ].exec( expr )) ) { var left = RegExp.leftContext; if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace(/\\/g, ""); set = Expr.find[ type ]( match, context ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { set = context.getElementsByTagName("*"); } expr += later; return {set: set, expr: expr}; }; Sizzle.filter = function(expr, set, inplace){ var old = expr, result = [], curLoop = set, match; while ( expr && set.length ) { for ( var type in Expr.filter ) { if ( (match = Expr.match[ type ].exec( expr )) != null ) { var anyFound = false, filter = Expr.filter[ type ], goodArray = null; if ( curLoop == result ) { result = []; } if ( Expr.preFilter[ type ] ) { match = Expr.preFilter[ type ]( match, curLoop ); 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; } } } } var goodPos = 0, found, item; for ( var i = 0; (item = curLoop[i]) !== undefined; i++ ) { if ( item ) { if ( goodArray && item != goodArray[goodPos] ) { goodPos++; } found = filter( item, match, goodPos, goodArray ); if ( inplace && found != null ) { curLoop[i] = found ? curLoop[i] : false; if ( found ) { anyFound = true; } } else if ( found ) { result.push( item ); anyFound = true; } } } if ( found !== undefined ) { if ( !inplace ) { curLoop = result; } expr = expr.replace( Expr.match[ type ], "" ); if ( !anyFound ) { return []; } break; } } } expr = expr.replace(/\s*,\s*/, ""); // Improper expression if ( expr == old ) { throw "Syntax error, unrecognized expression: " + expr; } old = expr; } return curLoop; }; var Expr = Sizzle.selectors = { order: [ "ID", "NAME", "TAG" ], match: { ID: /#((?:[\w\u0128-\uFFFF_-]|\\.)+)/, CLASS: /\.((?:[\w\u0128-\uFFFF_-]|\\.)+)/, NAME: /\[name=((?:[\w\u0128-\uFFFF_-]|\\.)+)\]/, ATTR: /\[((?:[\w\u0128-\uFFFF_-]|\\.)+)\s*(?:(\S{0,1}=)\s*(['"]*)(.*?)\3|)\]/, TAG: /^((?:[\w\u0128-\uFFFF\*_-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child\(?(even|odd|[\dn+-]*)\)?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)\(?(\d*)\)?(?:[^-]|$)/, PSEUDO: /:((?:[\w\u0128-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ }, attrMap: { "class": "className" }, relative: { "+": function(checkSet, part){ for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var cur = elem.previousSibling; while ( cur && cur.nodeType !== 1 ) { cur = cur.previousSibling; } checkSet[i] = typeof part === "string" ? cur || false : cur === part; } } if ( typeof part === "string" ) { Sizzle.filter( part, checkSet, true ); } }, ">": function(checkSet, part){ if ( typeof part === "string" && !/\W/.test(part) ) { part = part.toUpperCase(); for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var parent = elem.parentNode; checkSet[i] = parent.nodeName === part ? parent : false; } } } else { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { checkSet[i] = typeof part === "string" ? elem.parentNode : elem.parentNode === part; } } if ( typeof part === "string" ) { Sizzle.filter( part, checkSet, true ); } } }, "": function(checkSet, part){ var doneName = "done" + (done++), checkFn = dirCheck; if ( !part.match(/\W/) ) { var nodeCheck = part = part.toUpperCase(); checkFn = dirNodeCheck; } checkFn("parentNode", part, doneName, checkSet, nodeCheck); }, "~": function(checkSet, part){ var doneName = "done" + (done++), checkFn = dirCheck; if ( typeof part === "string" && !part.match(/\W/) ) { var nodeCheck = part = part.toUpperCase(); checkFn = dirNodeCheck; } checkFn("previousSibling", part, doneName, checkSet, nodeCheck); } }, find: { ID: function(match, context){ if ( context.getElementById ) { var m = context.getElementById(match[1]); return m ? [m] : []; } }, NAME: function(match, context){ return context.getElementsByName(match[1]); }, TAG: function(match, context){ return context.getElementsByTagName(match[1]); } }, preFilter: { CLASS: function(match){ return new RegExp( "(?:^|\\s)" + match[1] + "(?:\\s|$)" ); }, ID: function(match){ return match[1]; }, TAG: function(match){ return match[1].toUpperCase(); }, CHILD: function(match){ if ( match[1] == "nth" ) { // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); // calculate the numbers (first)n+(last) including if they are negative match[2] = (test[1] + (test[2] || 1)) - 0; match[3] = test[3] - 0; } // TODO: Move to normal caching system match[0] = "done" + (done++); return match; }, ATTR: function(match){ var name = match[1]; if ( Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } if ( match[2] === "~=" ) { match[4] = " " + match[4] + " "; } return match; }, PSEUDO: function(match){ if ( match[1] === "not" ) { match[3] = match[3].split(/\s*,\s*/); } return match; }, POS: function(match){ match.unshift( true ); return match; } }, filters: { enabled: function(elem){ return elem.disabled === false && elem.type !== "hidden"; }, disabled: function(elem){ return elem.disabled === true; }, checked: function(elem){ return elem.checked === true; }, selected: function(elem){ // Accessing this property makes selected-by-default // options in Safari work properly elem.parentNode.selectedIndex; return elem.selected === true; }, parent: function(elem){ return !!elem.firstChild; }, empty: function(elem){ return !elem.firstChild; }, has: function(elem, i, match){ return !!Sizzle( match[3], elem ).length; }, header: function(elem){ return /h\d/i.test( elem.nodeName ); }, text: function(elem){ return "text" === elem.type; }, radio: function(elem){ return "radio" === elem.type; }, checkbox: function(elem){ return "checkbox" === elem.type; }, file: function(elem){ return "file" === elem.type; }, password: function(elem){ return "password" === elem.type; }, submit: function(elem){ return "submit" === elem.type; }, image: function(elem){ return "image" === elem.type; }, reset: function(elem){ return "reset" === elem.type; }, button: function(elem){ return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; }, input: function(elem){ return /input|select|textarea|button/i.test(elem.nodeName); } }, setFilters: { first: function(elem, i){ return i === 0; }, last: function(elem, i, match, array){ return i === array.length - 1; }, even: function(elem, i){ return i % 2 === 0; }, odd: function(elem, i){ return i % 2 === 1; }, lt: function(elem, i, match){ return i < match[3] - 0; }, gt: function(elem, i, match){ return i > match[3] - 0; }, nth: function(elem, i, match){ return match[3] - 0 == i; }, eq: function(elem, i, match){ return match[3] - 0 == i; } }, filter: { CHILD: function(elem, match){ var type = match[1], parent = elem.parentNode; var doneName = match[0]; if ( parent && !parent[ doneName ] ) { var count = 1; for ( var node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType == 1 ) { node.nodeIndex = count++; } } parent[ doneName ] = count - 1; } if ( type == "first" ) { return elem.nodeIndex == 1; } else if ( type == "last" ) { return elem.nodeIndex == parent[ doneName ]; } else if ( type == "only" ) { return parent[ doneName ] == 1; } else if ( type == "nth" ) { var add = false, first = match[2], last = match[3]; if ( first == 1 && last == 0 ) { return true; } if ( first == 0 ) { if ( elem.nodeIndex == last ) { add = true; } } else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) { add = true; } return add; } }, PSEUDO: function(elem, match, i, array){ var name = match[1], filter = Expr.filters[ name ]; if ( filter ) { return filter( elem, i, match, array ) } else if ( name === "contains" ) { return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; } else if ( name === "not" ) { var not = match[3]; for ( var i = 0, l = not.length; i < l; i++ ) { if ( Sizzle.filter(not[i], [elem]).length > 0 ) { return false; } } return true; } }, ID: function(elem, match){ return elem.nodeType === 1 && elem.getAttribute("id") === match; }, TAG: function(elem, match){ return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; }, CLASS: function(elem, match){ 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]; return result == null ? false : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !match[4] ? result : type === "!=" ? value != check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; }, POS: function(elem, match, i, array){ var name = match[2], filter = Expr.setFilters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } } } }; var makeArray = function(array, results) { array = Array.prototype.slice.call( array ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. try { Array.prototype.slice.call( document.documentElement.childNodes ); // Provide a fallback method if it does not work } catch(e){ makeArray = function(array, results) { var ret = results || []; if ( array instanceof Array ) { Array.prototype.push.apply( ret, array ); } else { if ( typeof array.length === "number" ) { for ( var i = 0, l = array.length; i < l; i++ ) { ret.push( array[i] ); } } else { for ( var i = 0; array[i]; i++ ) { ret.push( array[i] ); } } } return ret; }; } // Check to see if the browser returns elements by name when // querying by getElementById (and provide a workaround) (function(){ // We're going to inject a fake input element with a specified name var form = document.createElement("form"), id = "script" + (new Date).getTime(); form.innerHTML = ""; // Inject it into the root element, check its status, and remove it quickly var root = document.documentElement; root.insertBefore( form, root.firstChild ); // The workaround has to do additional checks after a getElementById // Which slows things down for other browsers (hence the branching) if ( !!document.getElementById( id ) ) { Expr.find.ID = function(match, context){ if ( context.getElementById ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || m.getAttributeNode && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } }; Expr.filter.ID = function(elem, match){ var node = elem.getAttributeNode && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); })(); // Check to see if the browser returns only elements // when doing getElementsByTagName("*") (function(){ // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); // Make sure no comments are found if ( div.getElementsByTagName("*").length > 0 ) { Expr.find.TAG = function(match, context){ var results = context.getElementsByTagName(match[1]); // Filter out possible comments if ( match[1] === "*" ) { var tmp = []; for ( var i = 0; results[i]; i++ ) { if ( results[i].nodeType === 1 ) { tmp.push( results[i] ); } } results = tmp; } return results; }; } })(); if ( document.querySelectorAll ) (function(){ var oldSizzle = Sizzle; Sizzle = function(query, context, extra){ context = context || document; if ( context.nodeType === 9 ) { try { return makeArray( context.querySelectorAll(query) ); } catch(e){} } return oldSizzle(query, context, extra); }; Sizzle.find = oldSizzle.find; Sizzle.filter = oldSizzle.filter; Sizzle.selectors = oldSizzle.selectors; })(); if ( 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 ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { elem = elem[dir] var match = false; while ( elem && elem.nodeType ) { var done = elem[doneName]; if ( done ) { match = checkSet[ done ]; break; } if ( elem.nodeType === 1 ) elem[doneName] = i; if ( elem.nodeName === cur ) { match = elem; break; } elem = elem[dir]; } checkSet[i] = match; } } } function dirCheck( dir, cur, doneName, checkSet, nodeCheck ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { elem = elem[dir] var match = false; while ( elem && elem.nodeType ) { if ( elem[doneName] ) { match = checkSet[ elem[doneName] ]; break; } if ( elem.nodeType === 1 ) { elem[doneName] = i; if ( typeof cur !== "string" ) { if ( elem === cur ) { match = true; break; } } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { match = elem; break; } } elem = elem[dir]; } checkSet[i] = match; } } } var contains = document.compareDocumentPosition ? function(a, b){ return a.compareDocumentPosition(b) & 16; } : function(a, b){ return a !== b && a.contains(b); }; // EXPOSE jQuery.find = Sizzle; jQuery.filter = Sizzle.filter; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; Sizzle.selectors.filters.hidden = function(elem){ return "hidden" === elem.type || jQuery.css(elem, "display") === "none" || jQuery.css(elem, "visibility") === "hidden"; }; Sizzle.selectors.filters.visible = function(elem){ return "hidden" !== elem.type && jQuery.css(elem, "display") !== "none" && jQuery.css(elem, "visibility") !== "hidden"; }; jQuery.multiFilter = function( expr, elems, not ) { if ( not ) { return jQuery.multiFilter( ":not(" + expr + ")", elems ); } var exprs = expr.split(/\s*,\s*/), cur = []; for ( var i = 0; i < exprs.length; i++ ) { cur = jQuery.merge( cur, jQuery.filter( exprs[i], elems ) ); } return cur; }; jQuery.dir = function( elem, dir ){ var matched = [], cur = elem[dir]; while ( cur && cur != document ) { if ( cur.nodeType == 1 ) matched.push( cur ); cur = cur[dir]; } return matched; }; jQuery.nth = function(cur, result, dir, elem){ result = result || 1; var num = 0; for ( ; cur; cur = cur[dir] ) if ( cur.nodeType == 1 && ++num == result ) break; return cur; }; jQuery.sibling = function(n, elem){ var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType == 1 && n != elem ) r.push( n ); } return r; }; return; window.Sizzle = Sizzle; })();