sizzle.js 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. /*!
  2. * Sizzle CSS Selector Engine - v1.0
  3. * Copyright 2009, The Dojo Foundation
  4. * Released under the MIT, BSD, and GPL Licenses.
  5. * More information: http://sizzlejs.com/
  6. */
  7. exports.sizzleInit = function(window, document){
  8. var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
  9. done = 0,
  10. toString = Object.prototype.toString,
  11. hasDuplicate = false,
  12. baseHasDuplicate = true;
  13. // Here we check if the JavaScript engine is using some sort of
  14. // optimization where it does not always call our comparision
  15. // function. If that is the case, discard the hasDuplicate value.
  16. // Thus far that includes Google Chrome.
  17. [0, 0].sort(function(){
  18. baseHasDuplicate = false;
  19. return 0;
  20. });
  21. var Sizzle = function(selector, context, results, seed) {
  22. results = results || [];
  23. var origContext = context = context || document;
  24. if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
  25. return [];
  26. }
  27. if ( !selector || typeof selector !== "string" ) {
  28. return results;
  29. }
  30. var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
  31. soFar = selector;
  32. // Reset the position of the chunker regexp (start from head)
  33. while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
  34. soFar = m[3];
  35. parts.push( m[1] );
  36. if ( m[2] ) {
  37. extra = m[3];
  38. break;
  39. }
  40. }
  41. if ( parts.length > 1 && origPOS.exec( selector ) ) {
  42. if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
  43. set = posProcess( parts[0] + parts[1], context );
  44. } else {
  45. set = Expr.relative[ parts[0] ] ?
  46. [ context ] :
  47. Sizzle( parts.shift(), context );
  48. while ( parts.length ) {
  49. selector = parts.shift();
  50. if ( Expr.relative[ selector ] ) {
  51. selector += parts.shift();
  52. }
  53. set = posProcess( selector, set );
  54. }
  55. }
  56. } else {
  57. // Take a shortcut and set the context if the root selector is an ID
  58. // (but not if it'll be faster if the inner selector is an ID)
  59. if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
  60. Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
  61. var ret = Sizzle.find( parts.shift(), context, contextXML );
  62. context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
  63. }
  64. if ( context ) {
  65. var ret = seed ?
  66. { expr: parts.pop(), set: makeArray(seed) } :
  67. Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
  68. set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
  69. if ( parts.length > 0 ) {
  70. checkSet = makeArray(set);
  71. } else {
  72. prune = false;
  73. }
  74. while ( parts.length ) {
  75. var cur = parts.pop(), pop = cur;
  76. if ( !Expr.relative[ cur ] ) {
  77. cur = "";
  78. } else {
  79. pop = parts.pop();
  80. }
  81. if ( pop == null ) {
  82. pop = context;
  83. }
  84. Expr.relative[ cur ]( checkSet, pop, contextXML );
  85. }
  86. } else {
  87. checkSet = parts = [];
  88. }
  89. }
  90. if ( !checkSet ) {
  91. checkSet = set;
  92. }
  93. if ( !checkSet ) {
  94. Sizzle.error( cur || selector );
  95. }
  96. if ( toString.call(checkSet) === "[object Array]" ) {
  97. if ( !prune ) {
  98. results.push.apply( results, checkSet );
  99. } else if ( context && context.nodeType === 1 ) {
  100. for ( var i = 0; checkSet[i] != null; i++ ) {
  101. if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
  102. results.push( set[i] );
  103. }
  104. }
  105. } else {
  106. for ( var i = 0; checkSet[i] != null; i++ ) {
  107. if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
  108. results.push( set[i] );
  109. }
  110. }
  111. }
  112. } else {
  113. makeArray( checkSet, results );
  114. }
  115. if ( extra ) {
  116. Sizzle( extra, origContext, results, seed );
  117. Sizzle.uniqueSort( results );
  118. }
  119. return results;
  120. };
  121. Sizzle.uniqueSort = function(results){
  122. if ( sortOrder ) {
  123. hasDuplicate = baseHasDuplicate;
  124. results.sort(sortOrder);
  125. if ( hasDuplicate ) {
  126. for ( var i = 1; i < results.length; i++ ) {
  127. if ( results[i] === results[i-1] ) {
  128. results.splice(i--, 1);
  129. }
  130. }
  131. }
  132. }
  133. return results;
  134. };
  135. Sizzle.matches = function(expr, set){
  136. return Sizzle(expr, null, null, set);
  137. };
  138. Sizzle.find = function(expr, context, isXML){
  139. var set, match;
  140. if ( !expr ) {
  141. return [];
  142. }
  143. for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
  144. var type = Expr.order[i], match;
  145. if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
  146. var left = match[1];
  147. match.splice(1,1);
  148. if ( left.substr( left.length - 1 ) !== "\\" ) {
  149. match[1] = (match[1] || "").replace(/\\/g, "");
  150. set = Expr.find[ type ]( match, context, isXML );
  151. if ( set != null ) {
  152. expr = expr.replace( Expr.match[ type ], "" );
  153. break;
  154. }
  155. }
  156. }
  157. }
  158. if ( !set ) {
  159. set = context.getElementsByTagName("*");
  160. }
  161. return {set: set, expr: expr};
  162. };
  163. Sizzle.filter = function(expr, set, inplace, not){
  164. var old = expr, result = [], curLoop = set, match, anyFound,
  165. isXMLFilter = set && set[0] && isXML(set[0]);
  166. while ( expr && set.length ) {
  167. for ( var type in Expr.filter ) {
  168. if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
  169. var filter = Expr.filter[ type ], found, item, left = match[1];
  170. anyFound = false;
  171. match.splice(1,1);
  172. if ( left.substr( left.length - 1 ) === "\\" ) {
  173. continue;
  174. }
  175. if ( curLoop === result ) {
  176. result = [];
  177. }
  178. if ( Expr.preFilter[ type ] ) {
  179. match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
  180. if ( !match ) {
  181. anyFound = found = true;
  182. } else if ( match === true ) {
  183. continue;
  184. }
  185. }
  186. if ( match ) {
  187. for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
  188. if ( item ) {
  189. found = filter( item, match, i, curLoop );
  190. var pass = not ^ !!found;
  191. if ( inplace && found != null ) {
  192. if ( pass ) {
  193. anyFound = true;
  194. } else {
  195. curLoop[i] = false;
  196. }
  197. } else if ( pass ) {
  198. result.push( item );
  199. anyFound = true;
  200. }
  201. }
  202. }
  203. }
  204. if ( found !== undefined ) {
  205. if ( !inplace ) {
  206. curLoop = result;
  207. }
  208. expr = expr.replace( Expr.match[ type ], "" );
  209. if ( !anyFound ) {
  210. return [];
  211. }
  212. break;
  213. }
  214. }
  215. }
  216. // Improper expression
  217. if ( expr === old ) {
  218. if ( anyFound == null ) {
  219. Sizzle.error( expr );
  220. } else {
  221. break;
  222. }
  223. }
  224. old = expr;
  225. }
  226. return curLoop;
  227. };
  228. Sizzle.error = function( msg ) {
  229. throw "Syntax error, unrecognized expression: " + msg;
  230. };
  231. var Expr = Sizzle.selectors = {
  232. order: [ "ID", "NAME", "TAG" ],
  233. match: {
  234. ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
  235. CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
  236. NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
  237. ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
  238. TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
  239. CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
  240. POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
  241. PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
  242. },
  243. leftMatch: {},
  244. attrMap: {
  245. "class": "className",
  246. "for": "htmlFor"
  247. },
  248. attrHandle: {
  249. href: function(elem){
  250. return elem.getAttribute("href");
  251. }
  252. },
  253. relative: {
  254. "+": function(checkSet, part){
  255. var isPartStr = typeof part === "string",
  256. isTag = isPartStr && !/\W/.test(part),
  257. isPartStrNotTag = isPartStr && !isTag;
  258. if ( isTag ) {
  259. part = part.toLowerCase();
  260. }
  261. for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
  262. if ( (elem = checkSet[i]) ) {
  263. while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
  264. checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
  265. elem || false :
  266. elem === part;
  267. }
  268. }
  269. if ( isPartStrNotTag ) {
  270. Sizzle.filter( part, checkSet, true );
  271. }
  272. },
  273. ">": function(checkSet, part){
  274. var isPartStr = typeof part === "string";
  275. if ( isPartStr && !/\W/.test(part) ) {
  276. part = part.toLowerCase();
  277. for ( var i = 0, l = checkSet.length; i < l; i++ ) {
  278. var elem = checkSet[i];
  279. if ( elem ) {
  280. var parent = elem.parentNode;
  281. checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
  282. }
  283. }
  284. } else {
  285. for ( var i = 0, l = checkSet.length; i < l; i++ ) {
  286. var elem = checkSet[i];
  287. if ( elem ) {
  288. checkSet[i] = isPartStr ?
  289. elem.parentNode :
  290. elem.parentNode === part;
  291. }
  292. }
  293. if ( isPartStr ) {
  294. Sizzle.filter( part, checkSet, true );
  295. }
  296. }
  297. },
  298. "": function(checkSet, part, isXML){
  299. var doneName = done++, checkFn = dirCheck;
  300. if ( typeof part === "string" && !/\W/.test(part) ) {
  301. var nodeCheck = part = part.toLowerCase();
  302. checkFn = dirNodeCheck;
  303. }
  304. checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
  305. },
  306. "~": function(checkSet, part, isXML){
  307. var doneName = done++, checkFn = dirCheck;
  308. if ( typeof part === "string" && !/\W/.test(part) ) {
  309. var nodeCheck = part = part.toLowerCase();
  310. checkFn = dirNodeCheck;
  311. }
  312. checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
  313. }
  314. },
  315. find: {
  316. ID: function(match, context, isXML){
  317. if ( typeof context.getElementById !== "undefined" && !isXML ) {
  318. var m = context.getElementById(match[1]);
  319. return m ? [m] : [];
  320. }
  321. },
  322. NAME: function(match, context){
  323. if ( typeof context.getElementsByName !== "undefined" ) {
  324. var ret = [], results = context.getElementsByName(match[1]);
  325. for ( var i = 0, l = results.length; i < l; i++ ) {
  326. if ( results[i].getAttribute("name") === match[1] ) {
  327. ret.push( results[i] );
  328. }
  329. }
  330. return ret.length === 0 ? null : ret;
  331. }
  332. },
  333. TAG: function(match, context){
  334. return context.getElementsByTagName(match[1]);
  335. }
  336. },
  337. preFilter: {
  338. CLASS: function(match, curLoop, inplace, result, not, isXML){
  339. match = " " + match[1].replace(/\\/g, "") + " ";
  340. if ( isXML ) {
  341. return match;
  342. }
  343. for ( var i = 0, elem; (elem = curLoop.item(i)) != null; i++ ) {
  344. if ( elem ) {
  345. if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
  346. if ( !inplace ) {
  347. result.push( elem );
  348. }
  349. } else if ( inplace ) {
  350. curLoop[i] = false;
  351. }
  352. }
  353. }
  354. return false;
  355. },
  356. ID: function(match){
  357. return match[1].replace(/\\/g, "");
  358. },
  359. TAG: function(match, curLoop){
  360. return match[1].toLowerCase();
  361. },
  362. CHILD: function(match){
  363. if ( match[1] === "nth" ) {
  364. // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
  365. var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
  366. match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
  367. !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
  368. // calculate the numbers (first)n+(last) including if they are negative
  369. match[2] = (test[1] + (test[2] || 1)) - 0;
  370. match[3] = test[3] - 0;
  371. }
  372. // TODO: Move to normal caching system
  373. match[0] = done++;
  374. return match;
  375. },
  376. ATTR: function(match, curLoop, inplace, result, not, isXML){
  377. var name = match[1].replace(/\\/g, "");
  378. if ( !isXML && Expr.attrMap[name] ) {
  379. match[1] = Expr.attrMap[name];
  380. }
  381. if ( match[2] === "~=" ) {
  382. match[4] = " " + match[4] + " ";
  383. }
  384. return match;
  385. },
  386. PSEUDO: function(match, curLoop, inplace, result, not){
  387. if ( match[1] === "not" ) {
  388. // If we're dealing with a complex expression, or a simple one
  389. if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
  390. match[3] = Sizzle(match[3], null, null, curLoop);
  391. } else {
  392. var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
  393. if ( !inplace ) {
  394. result.push.apply( result, ret );
  395. }
  396. return false;
  397. }
  398. } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
  399. return true;
  400. }
  401. return match;
  402. },
  403. POS: function(match){
  404. match.unshift( true );
  405. return match;
  406. }
  407. },
  408. filters: {
  409. enabled: function(elem){
  410. return elem.disabled === false && elem.type !== "hidden";
  411. },
  412. disabled: function(elem){
  413. return elem.disabled === true;
  414. },
  415. checked: function(elem){
  416. return elem.checked === true;
  417. },
  418. selected: function(elem){
  419. // Accessing this property makes selected-by-default
  420. // options in Safari work properly
  421. elem.parentNode.selectedIndex;
  422. return elem.selected === true;
  423. },
  424. parent: function(elem){
  425. return !!elem.firstChild;
  426. },
  427. empty: function(elem){
  428. return !elem.firstChild;
  429. },
  430. has: function(elem, i, match){
  431. return !!Sizzle( match[3], elem ).length;
  432. },
  433. header: function(elem){
  434. return /h\d/i.test( elem.nodeName );
  435. },
  436. text: function(elem){
  437. return "text" === elem.type;
  438. },
  439. radio: function(elem){
  440. return "radio" === elem.type;
  441. },
  442. checkbox: function(elem){
  443. return "checkbox" === elem.type;
  444. },
  445. file: function(elem){
  446. return "file" === elem.type;
  447. },
  448. password: function(elem){
  449. return "password" === elem.type;
  450. },
  451. submit: function(elem){
  452. return "submit" === elem.type;
  453. },
  454. image: function(elem){
  455. return "image" === elem.type;
  456. },
  457. reset: function(elem){
  458. return "reset" === elem.type;
  459. },
  460. button: function(elem){
  461. return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
  462. },
  463. input: function(elem){
  464. return /input|select|textarea|button/i.test(elem.nodeName);
  465. }
  466. },
  467. setFilters: {
  468. first: function(elem, i){
  469. return i === 0;
  470. },
  471. last: function(elem, i, match, array){
  472. return i === array.length - 1;
  473. },
  474. even: function(elem, i){
  475. return i % 2 === 0;
  476. },
  477. odd: function(elem, i){
  478. return i % 2 === 1;
  479. },
  480. lt: function(elem, i, match){
  481. return i < match[3] - 0;
  482. },
  483. gt: function(elem, i, match){
  484. return i > match[3] - 0;
  485. },
  486. nth: function(elem, i, match){
  487. return match[3] - 0 === i;
  488. },
  489. eq: function(elem, i, match){
  490. return match[3] - 0 === i;
  491. }
  492. },
  493. filter: {
  494. PSEUDO: function(elem, match, i, array){
  495. var name = match[1], filter = Expr.filters[ name ];
  496. if ( filter ) {
  497. return filter( elem, i, match, array );
  498. } else if ( name === "contains" ) {
  499. return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
  500. } else if ( name === "not" ) {
  501. var not = match[3];
  502. for ( var i = 0, l = not.length; i < l; i++ ) {
  503. if ( not[i] === elem ) {
  504. return false;
  505. }
  506. }
  507. return true;
  508. } else {
  509. Sizzle.error( "Syntax error, unrecognized expression: " + name );
  510. }
  511. },
  512. CHILD: function(elem, match){
  513. var type = match[1], node = elem;
  514. switch (type) {
  515. case 'only':
  516. case 'first':
  517. while ( (node = node.previousSibling) ) {
  518. if ( node.nodeType === 1 ) {
  519. return false;
  520. }
  521. }
  522. if ( type === "first" ) {
  523. return true;
  524. }
  525. node = elem;
  526. case 'last':
  527. while ( (node = node.nextSibling) ) {
  528. if ( node.nodeType === 1 ) {
  529. return false;
  530. }
  531. }
  532. return true;
  533. case 'nth':
  534. var first = match[2], last = match[3];
  535. if ( first === 1 && last === 0 ) {
  536. return true;
  537. }
  538. var doneName = match[0],
  539. parent = elem.parentNode;
  540. if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
  541. var count = 0;
  542. for ( node = parent.firstChild; node; node = node.nextSibling ) {
  543. if ( node.nodeType === 1 ) {
  544. node.nodeIndex = ++count;
  545. }
  546. }
  547. parent.sizcache = doneName;
  548. }
  549. var diff = elem.nodeIndex - last;
  550. if ( first === 0 ) {
  551. return diff === 0;
  552. } else {
  553. return ( diff % first === 0 && diff / first >= 0 );
  554. }
  555. }
  556. },
  557. ID: function(elem, match){
  558. return elem.nodeType === 1 && elem.getAttribute("id") === match;
  559. },
  560. TAG: function(elem, match){
  561. return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
  562. },
  563. CLASS: function(elem, match){
  564. return (" " + (elem.className || elem.getAttribute("class")) + " ")
  565. .indexOf( match ) > -1;
  566. },
  567. ATTR: function(elem, match){
  568. var name = match[1],
  569. result = Expr.attrHandle[ name ] ?
  570. Expr.attrHandle[ name ]( elem ) :
  571. elem[ name ] != null ?
  572. elem[ name ] :
  573. elem.getAttribute( name ),
  574. value = result + "",
  575. type = match[2],
  576. check = match[4];
  577. return result == null ?
  578. type === "!=" :
  579. type === "=" ?
  580. value === check :
  581. type === "*=" ?
  582. value.indexOf(check) >= 0 :
  583. type === "~=" ?
  584. (" " + value + " ").indexOf(check) >= 0 :
  585. !check ?
  586. value && result !== false :
  587. type === "!=" ?
  588. value !== check :
  589. type === "^=" ?
  590. value.indexOf(check) === 0 :
  591. type === "$=" ?
  592. value.substr(value.length - check.length) === check :
  593. type === "|=" ?
  594. value === check || value.substr(0, check.length + 1) === check + "-" :
  595. false;
  596. },
  597. POS: function(elem, match, i, array){
  598. var name = match[2], filter = Expr.setFilters[ name ];
  599. if ( filter ) {
  600. return filter( elem, i, match, array );
  601. }
  602. }
  603. }
  604. };
  605. var origPOS = Expr.match.POS;
  606. for ( var type in Expr.match ) {
  607. Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
  608. Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
  609. return "\\" + (num - 0 + 1);
  610. }));
  611. }
  612. var makeArray = function(array, results) {
  613. array = Array.prototype.slice.call( array, 0 );
  614. if ( results ) {
  615. results.push.apply( results, array );
  616. return results;
  617. }
  618. return array;
  619. };
  620. // Perform a simple check to determine if the browser is capable of
  621. // converting a NodeList to an array using builtin methods.
  622. //try {
  623. // Array.prototype.slice.call( document.documentElement.childNodes, 0 );
  624. // Provide a fallback method if it does not work
  625. //} catch(e){
  626. makeArray = function(array, results) {
  627. var ret = results || [];
  628. if ( toString.call(array) === "[object Array]" ) {
  629. Array.prototype.push.apply( ret, array );
  630. } else {
  631. if ( typeof array.length === "number" ) {
  632. for ( var i = 0, l = array.length; i < l; i++ ) {
  633. // tmpvar's "fix"
  634. if (array.item) {
  635. ret.push(array.item(i));
  636. } else {
  637. ret.push( array[i] );
  638. }
  639. }
  640. } else {
  641. for ( var i = 0; array[i]; i++ ) {
  642. // tmpvar's "fix"
  643. if (array.item) {
  644. ret.push(array.item(i));
  645. } else {
  646. ret.push( array[i] );
  647. }
  648. }
  649. }
  650. }
  651. return ret;
  652. };
  653. //}
  654. var sortOrder;
  655. if ( document.documentElement.compareDocumentPosition ) {
  656. sortOrder = function( a, b ) {
  657. if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
  658. if ( a == b ) {
  659. hasDuplicate = true;
  660. }
  661. return a.compareDocumentPosition ? -1 : 1;
  662. }
  663. var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
  664. if ( ret === 0 ) {
  665. hasDuplicate = true;
  666. }
  667. return ret;
  668. };
  669. } else if ( "sourceIndex" in document.documentElement ) {
  670. sortOrder = function( a, b ) {
  671. if ( !a.sourceIndex || !b.sourceIndex ) {
  672. if ( a == b ) {
  673. hasDuplicate = true;
  674. }
  675. return a.sourceIndex ? -1 : 1;
  676. }
  677. var ret = a.sourceIndex - b.sourceIndex;
  678. if ( ret === 0 ) {
  679. hasDuplicate = true;
  680. }
  681. return ret;
  682. };
  683. } else if ( document.createRange ) {
  684. sortOrder = function( a, b ) {
  685. if ( !a.ownerDocument || !b.ownerDocument ) {
  686. if ( a == b ) {
  687. hasDuplicate = true;
  688. }
  689. return a.ownerDocument ? -1 : 1;
  690. }
  691. var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
  692. aRange.setStart(a, 0);
  693. aRange.setEnd(a, 0);
  694. bRange.setStart(b, 0);
  695. bRange.setEnd(b, 0);
  696. var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
  697. if ( ret === 0 ) {
  698. hasDuplicate = true;
  699. }
  700. return ret;
  701. };
  702. }
  703. // Utility function for retreiving the text value of an array of DOM nodes
  704. function getText( elems ) {
  705. var ret = "", elem;
  706. for ( var i = 0; elems[i]; i++ ) {
  707. elem = elems[i];
  708. // Get the text from text nodes and CDATA nodes
  709. if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
  710. ret += elem.nodeValue;
  711. // Traverse everything else, except comment nodes
  712. } else if ( elem.nodeType !== 8 ) {
  713. ret += getText( elem.childNodes );
  714. }
  715. }
  716. return ret;
  717. }
  718. // Check to see if the browser returns elements by name when
  719. // querying by getElementById (and provide a workaround)
  720. (function(){
  721. // We're going to inject a fake input element with a specified name
  722. var form = document.createElement("div"),
  723. id = "script" + (new Date).getTime();
  724. form.innerHTML = "<a name='" + id + "'/>";
  725. // Inject it into the root element, check its status, and remove it quickly
  726. var root = document.documentElement;
  727. root.insertBefore( form, root.firstChild );
  728. // The workaround has to do additional checks after a getElementById
  729. // Which slows things down for other browsers (hence the branching)
  730. if ( document.getElementById( id ) ) {
  731. Expr.find.ID = function(match, context, isXML){
  732. if ( typeof context.getElementById !== "undefined" && !isXML ) {
  733. var m = context.getElementById(match[1]);
  734. return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
  735. }
  736. };
  737. Expr.filter.ID = function(elem, match){
  738. var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
  739. return elem.nodeType === 1 && node && node.nodeValue === match;
  740. };
  741. }
  742. root.removeChild( form );
  743. root = form = null; // release memory in IE
  744. })();
  745. (function(){
  746. // Check to see if the browser returns only elements
  747. // when doing getElementsByTagName("*")
  748. // Create a fake element
  749. var div = document.createElement("div");
  750. div.appendChild( document.createComment("") );
  751. // Make sure no comments are found
  752. if ( div.getElementsByTagName("*").length > 0 ) {
  753. Expr.find.TAG = function(match, context){
  754. var results = context.getElementsByTagName(match[1]);
  755. // Filter out possible comments
  756. if ( match[1] === "*" ) {
  757. var tmp = [];
  758. for ( var i = 0; results.item(i); i++ ) {
  759. if ( results.item(i).nodeType === 1 ) {
  760. tmp.push( results.item(i) );
  761. }
  762. }
  763. results = tmp;
  764. }
  765. return results;
  766. };
  767. }
  768. // Check to see if an attribute returns normalized href attributes
  769. div.innerHTML = "<a href='#'></a>";
  770. if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
  771. div.firstChild.getAttribute("href") !== "#" ) {
  772. Expr.attrHandle.href = function(elem){
  773. return elem.getAttribute("href", 2);
  774. };
  775. }
  776. div = null; // release memory in IE
  777. })();
  778. if ( document.querySelectorAll ) {
  779. (function(){
  780. var oldSizzle = Sizzle, div = document.createElement("div");
  781. div.innerHTML = "<p class='TEST'></p>";
  782. // Safari can't handle uppercase or unicode characters when
  783. // in quirks mode.
  784. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
  785. return;
  786. }
  787. Sizzle = function(query, context, extra, seed){
  788. context = context || document;
  789. // Only use querySelectorAll on non-XML documents
  790. // (ID selectors don't work in non-HTML documents)
  791. if ( !seed && context.nodeType === 9 && !isXML(context) ) {
  792. try {
  793. return makeArray( context.querySelectorAll(query), extra );
  794. } catch(e){}
  795. }
  796. return oldSizzle(query, context, extra, seed);
  797. };
  798. for ( var prop in oldSizzle ) {
  799. Sizzle[ prop ] = oldSizzle[ prop ];
  800. }
  801. div = null; // release memory in IE
  802. })();
  803. }
  804. (function(){
  805. var div = document.createElement("div");
  806. div.innerHTML = "<div class='test e'></div><div class='test'></div>";
  807. // Opera can't find a second classname (in 9.6)
  808. // Also, make sure that getElementsByClassName actually exists
  809. if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
  810. return;
  811. }
  812. // Safari caches class attributes, doesn't catch changes (in 3.2)
  813. div.lastChild.className = "e";
  814. if ( div.getElementsByClassName("e").length === 1 ) {
  815. return;
  816. }
  817. Expr.order.splice(1, 0, "CLASS");
  818. Expr.find.CLASS = function(match, context, isXML) {
  819. if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
  820. return context.getElementsByClassName(match[1]);
  821. }
  822. };
  823. div = null; // release memory in IE
  824. })();
  825. function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
  826. for ( var i = 0, l = checkSet.length; i < l; i++ ) {
  827. var elem = checkSet[i];
  828. if ( elem ) {
  829. elem = elem[dir];
  830. var match = false;
  831. while ( elem ) {
  832. if ( elem.sizcache === doneName ) {
  833. match = checkSet[elem.sizset];
  834. break;
  835. }
  836. if ( elem.nodeType === 1 && !isXML ){
  837. elem.sizcache = doneName;
  838. elem.sizset = i;
  839. }
  840. if ( elem.nodeName.toLowerCase() === cur ) {
  841. match = elem;
  842. break;
  843. }
  844. elem = elem[dir];
  845. }
  846. checkSet[i] = match;
  847. }
  848. }
  849. }
  850. function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
  851. for ( var i = 0, l = checkSet.length; i < l; i++ ) {
  852. var elem = checkSet[i];
  853. if ( elem ) {
  854. elem = elem[dir];
  855. var match = false;
  856. while ( elem ) {
  857. if ( elem.sizcache === doneName ) {
  858. match = checkSet[elem.sizset];
  859. break;
  860. }
  861. if ( elem.nodeType === 1 ) {
  862. if ( !isXML ) {
  863. elem.sizcache = doneName;
  864. elem.sizset = i;
  865. }
  866. if ( typeof cur !== "string" ) {
  867. if ( elem === cur ) {
  868. match = true;
  869. break;
  870. }
  871. } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
  872. match = elem;
  873. break;
  874. }
  875. }
  876. elem = elem[dir];
  877. }
  878. checkSet[i] = match;
  879. }
  880. }
  881. }
  882. var contains = document.compareDocumentPosition ? function(a, b){
  883. return !!(a.compareDocumentPosition(b) & 16);
  884. } : function(a, b){
  885. return a !== b && (a.contains ? a.contains(b) : true);
  886. };
  887. var isXML = function(elem){
  888. // documentElement is verified for cases where it doesn't yet exist
  889. // (such as loading iframes in IE - #4833)
  890. var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
  891. return documentElement ? documentElement.nodeName !== "HTML" : false;
  892. };
  893. var posProcess = function(selector, context){
  894. var tmpSet = [], later = "", match,
  895. root = context.nodeType ? [context] : context;
  896. // Position selectors must be done after the filter
  897. // And so must :not(positional) so we move all PSEUDOs to the end
  898. while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
  899. later += match[0];
  900. selector = selector.replace( Expr.match.PSEUDO, "" );
  901. }
  902. selector = Expr.relative[selector] ? selector + "*" : selector;
  903. for ( var i = 0, l = root.length; i < l; i++ ) {
  904. Sizzle( selector, root[i], tmpSet );
  905. }
  906. return Sizzle.filter( later, tmpSet );
  907. };
  908. // EXPOSE
  909. return Sizzle;
  910. };