source: Dev/trunk/d3/lib/sizzle/sizzle.js @ 76

Last change on this file since 76 was 76, checked in by fpvanagthoven, 14 years ago

d3

File size: 31.0 KB
Line 
1/*!
2 * Sizzle CSS Selector Engine
3 *  Copyright 2011, The Dojo Foundation
4 *  Released under the MIT, BSD, and GPL Licenses.
5 *  More information: http://sizzlejs.com/
6 */
7(function(){
8
9var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
10        done = 0,
11        toString = Object.prototype.toString,
12        hasDuplicate = false,
13        baseHasDuplicate = true;
14
15// Here we check if the JavaScript engine is using some sort of
16// optimization where it does not always call our comparision
17// function. If that is the case, discard the hasDuplicate value.
18//   Thus far that includes Google Chrome.
19[0, 0].sort(function() {
20        baseHasDuplicate = false;
21        return 0;
22});
23
24var Sizzle = function( selector, context, results, seed ) {
25        results = results || [];
26        context = context || document;
27
28        var origContext = context;
29
30        if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
31                return [];
32        }
33       
34        if ( !selector || typeof selector !== "string" ) {
35                return results;
36        }
37
38        var m, set, checkSet, extra, ret, cur, pop, i,
39                prune = true,
40                contextXML = Sizzle.isXML( context ),
41                parts = [],
42                soFar = selector;
43       
44        // Reset the position of the chunker regexp (start from head)
45        do {
46                chunker.exec( "" );
47                m = chunker.exec( soFar );
48
49                if ( m ) {
50                        soFar = m[3];
51               
52                        parts.push( m[1] );
53               
54                        if ( m[2] ) {
55                                extra = m[3];
56                                break;
57                        }
58                }
59        } while ( m );
60
61        if ( parts.length > 1 && origPOS.exec( selector ) ) {
62
63                if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
64                        set = posProcess( parts[0] + parts[1], context );
65
66                } else {
67                        set = Expr.relative[ parts[0] ] ?
68                                [ context ] :
69                                Sizzle( parts.shift(), context );
70
71                        while ( parts.length ) {
72                                selector = parts.shift();
73
74                                if ( Expr.relative[ selector ] ) {
75                                        selector += parts.shift();
76                                }
77                               
78                                set = posProcess( selector, set );
79                        }
80                }
81
82        } else {
83                // Take a shortcut and set the context if the root selector is an ID
84                // (but not if it'll be faster if the inner selector is an ID)
85                if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
86                                Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
87
88                        ret = Sizzle.find( parts.shift(), context, contextXML );
89                        context = ret.expr ?
90                                Sizzle.filter( ret.expr, ret.set )[0] :
91                                ret.set[0];
92                }
93
94                if ( context ) {
95                        ret = seed ?
96                                { expr: parts.pop(), set: makeArray(seed) } :
97                                Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
98
99                        set = ret.expr ?
100                                Sizzle.filter( ret.expr, ret.set ) :
101                                ret.set;
102
103                        if ( parts.length > 0 ) {
104                                checkSet = makeArray( set );
105
106                        } else {
107                                prune = false;
108                        }
109
110                        while ( parts.length ) {
111                                cur = parts.pop();
112                                pop = cur;
113
114                                if ( !Expr.relative[ cur ] ) {
115                                        cur = "";
116                                } else {
117                                        pop = parts.pop();
118                                }
119
120                                if ( pop == null ) {
121                                        pop = context;
122                                }
123
124                                Expr.relative[ cur ]( checkSet, pop, contextXML );
125                        }
126
127                } else {
128                        checkSet = parts = [];
129                }
130        }
131
132        if ( !checkSet ) {
133                checkSet = set;
134        }
135
136        if ( !checkSet ) {
137                Sizzle.error( cur || selector );
138        }
139
140        if ( toString.call(checkSet) === "[object Array]" ) {
141                if ( !prune ) {
142                        results.push.apply( results, checkSet );
143
144                } else if ( context && context.nodeType === 1 ) {
145                        for ( i = 0; checkSet[i] != null; i++ ) {
146                                if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
147                                        results.push( set[i] );
148                                }
149                        }
150
151                } else {
152                        for ( i = 0; checkSet[i] != null; i++ ) {
153                                if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
154                                        results.push( set[i] );
155                                }
156                        }
157                }
158
159        } else {
160                makeArray( checkSet, results );
161        }
162
163        if ( extra ) {
164                Sizzle( extra, origContext, results, seed );
165                Sizzle.uniqueSort( results );
166        }
167
168        return results;
169};
170
171Sizzle.uniqueSort = function( results ) {
172        if ( sortOrder ) {
173                hasDuplicate = baseHasDuplicate;
174                results.sort( sortOrder );
175
176                if ( hasDuplicate ) {
177                        for ( var i = 1; i < results.length; i++ ) {
178                                if ( results[i] === results[ i - 1 ] ) {
179                                        results.splice( i--, 1 );
180                                }
181                        }
182                }
183        }
184
185        return results;
186};
187
188Sizzle.matches = function( expr, set ) {
189        return Sizzle( expr, null, null, set );
190};
191
192Sizzle.matchesSelector = function( node, expr ) {
193        return Sizzle( expr, null, null, [node] ).length > 0;
194};
195
196Sizzle.find = function( expr, context, isXML ) {
197        var set;
198
199        if ( !expr ) {
200                return [];
201        }
202
203        for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
204                var match,
205                        type = Expr.order[i];
206               
207                if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
208                        var left = match[1];
209                        match.splice( 1, 1 );
210
211                        if ( left.substr( left.length - 1 ) !== "\\" ) {
212                                match[1] = (match[1] || "").replace(/\\/g, "");
213                                set = Expr.find[ type ]( match, context, isXML );
214
215                                if ( set != null ) {
216                                        expr = expr.replace( Expr.match[ type ], "" );
217                                        break;
218                                }
219                        }
220                }
221        }
222
223        if ( !set ) {
224                set = typeof context.getElementsByTagName !== "undefined" ?
225                        context.getElementsByTagName( "*" ) :
226                        [];
227        }
228
229        return { set: set, expr: expr };
230};
231
232Sizzle.filter = function( expr, set, inplace, not ) {
233        var match, anyFound,
234                old = expr,
235                result = [],
236                curLoop = set,
237                isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
238
239        while ( expr && set.length ) {
240                for ( var type in Expr.filter ) {
241                        if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
242                                var found, item,
243                                        filter = Expr.filter[ type ],
244                                        left = match[1];
245
246                                anyFound = false;
247
248                                match.splice(1,1);
249
250                                if ( left.substr( left.length - 1 ) === "\\" ) {
251                                        continue;
252                                }
253
254                                if ( curLoop === result ) {
255                                        result = [];
256                                }
257
258                                if ( Expr.preFilter[ type ] ) {
259                                        match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
260
261                                        if ( !match ) {
262                                                anyFound = found = true;
263
264                                        } else if ( match === true ) {
265                                                continue;
266                                        }
267                                }
268
269                                if ( match ) {
270                                        for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
271                                                if ( item ) {
272                                                        found = filter( item, match, i, curLoop );
273                                                        var pass = not ^ !!found;
274
275                                                        if ( inplace && found != null ) {
276                                                                if ( pass ) {
277                                                                        anyFound = true;
278
279                                                                } else {
280                                                                        curLoop[i] = false;
281                                                                }
282
283                                                        } else if ( pass ) {
284                                                                result.push( item );
285                                                                anyFound = true;
286                                                        }
287                                                }
288                                        }
289                                }
290
291                                if ( found !== undefined ) {
292                                        if ( !inplace ) {
293                                                curLoop = result;
294                                        }
295
296                                        expr = expr.replace( Expr.match[ type ], "" );
297
298                                        if ( !anyFound ) {
299                                                return [];
300                                        }
301
302                                        break;
303                                }
304                        }
305                }
306
307                // Improper expression
308                if ( expr === old ) {
309                        if ( anyFound == null ) {
310                                Sizzle.error( expr );
311
312                        } else {
313                                break;
314                        }
315                }
316
317                old = expr;
318        }
319
320        return curLoop;
321};
322
323Sizzle.error = function( msg ) {
324        throw "Syntax error, unrecognized expression: " + msg;
325};
326
327var Expr = Sizzle.selectors = {
328        order: [ "ID", "NAME", "TAG" ],
329
330        match: {
331                ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
332                CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
333                NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
334                ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
335                TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
336                CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
337                POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
338                PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
339        },
340
341        leftMatch: {},
342
343        attrMap: {
344                "class": "className",
345                "for": "htmlFor"
346        },
347
348        attrHandle: {
349                href: function( elem ) {
350                        return elem.getAttribute( "href" );
351                }
352        },
353
354        relative: {
355                "+": function(checkSet, part){
356                        var isPartStr = typeof part === "string",
357                                isTag = isPartStr && !/\W/.test( part ),
358                                isPartStrNotTag = isPartStr && !isTag;
359
360                        if ( isTag ) {
361                                part = part.toLowerCase();
362                        }
363
364                        for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
365                                if ( (elem = checkSet[i]) ) {
366                                        while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
367
368                                        checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
369                                                elem || false :
370                                                elem === part;
371                                }
372                        }
373
374                        if ( isPartStrNotTag ) {
375                                Sizzle.filter( part, checkSet, true );
376                        }
377                },
378
379                ">": function( checkSet, part ) {
380                        var elem,
381                                isPartStr = typeof part === "string",
382                                i = 0,
383                                l = checkSet.length;
384
385                        if ( isPartStr && !/\W/.test( part ) ) {
386                                part = part.toLowerCase();
387
388                                for ( ; i < l; i++ ) {
389                                        elem = checkSet[i];
390
391                                        if ( elem ) {
392                                                var parent = elem.parentNode;
393                                                checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
394                                        }
395                                }
396
397                        } else {
398                                for ( ; i < l; i++ ) {
399                                        elem = checkSet[i];
400
401                                        if ( elem ) {
402                                                checkSet[i] = isPartStr ?
403                                                        elem.parentNode :
404                                                        elem.parentNode === part;
405                                        }
406                                }
407
408                                if ( isPartStr ) {
409                                        Sizzle.filter( part, checkSet, true );
410                                }
411                        }
412                },
413
414                "": function(checkSet, part, isXML){
415                        var nodeCheck,
416                                doneName = done++,
417                                checkFn = dirCheck;
418
419                        if ( typeof part === "string" && !/\W/.test(part) ) {
420                                part = part.toLowerCase();
421                                nodeCheck = part;
422                                checkFn = dirNodeCheck;
423                        }
424
425                        checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
426                },
427
428                "~": function( checkSet, part, isXML ) {
429                        var nodeCheck,
430                                doneName = done++,
431                                checkFn = dirCheck;
432
433                        if ( typeof part === "string" && !/\W/.test( part ) ) {
434                                part = part.toLowerCase();
435                                nodeCheck = part;
436                                checkFn = dirNodeCheck;
437                        }
438
439                        checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
440                }
441        },
442
443        find: {
444                ID: function( match, context, isXML ) {
445                        if ( typeof context.getElementById !== "undefined" && !isXML ) {
446                                var m = context.getElementById(match[1]);
447                                // Check parentNode to catch when Blackberry 4.6 returns
448                                // nodes that are no longer in the document #6963
449                                return m && m.parentNode ? [m] : [];
450                        }
451                },
452
453                NAME: function( match, context ) {
454                        if ( typeof context.getElementsByName !== "undefined" ) {
455                                var ret = [],
456                                        results = context.getElementsByName( match[1] );
457
458                                for ( var i = 0, l = results.length; i < l; i++ ) {
459                                        if ( results[i].getAttribute("name") === match[1] ) {
460                                                ret.push( results[i] );
461                                        }
462                                }
463
464                                return ret.length === 0 ? null : ret;
465                        }
466                },
467
468                TAG: function( match, context ) {
469                        if ( typeof context.getElementsByTagName !== "undefined" ) {
470                                return context.getElementsByTagName( match[1] );
471                        }
472                }
473        },
474        preFilter: {
475                CLASS: function( match, curLoop, inplace, result, not, isXML ) {
476                        match = " " + match[1].replace(/\\/g, "") + " ";
477
478                        if ( isXML ) {
479                                return match;
480                        }
481
482                        for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
483                                if ( elem ) {
484                                        if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
485                                                if ( !inplace ) {
486                                                        result.push( elem );
487                                                }
488
489                                        } else if ( inplace ) {
490                                                curLoop[i] = false;
491                                        }
492                                }
493                        }
494
495                        return false;
496                },
497
498                ID: function( match ) {
499                        return match[1].replace(/\\/g, "");
500                },
501
502                TAG: function( match, curLoop ) {
503                        return match[1].toLowerCase();
504                },
505
506                CHILD: function( match ) {
507                        if ( match[1] === "nth" ) {
508                                if ( !match[2] ) {
509                                        Sizzle.error( match[0] );
510                                }
511
512                                match[2] = match[2].replace(/^\+|\s*/g, '');
513
514                                // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
515                                var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
516                                        match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
517                                        !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
518
519                                // calculate the numbers (first)n+(last) including if they are negative
520                                match[2] = (test[1] + (test[2] || 1)) - 0;
521                                match[3] = test[3] - 0;
522                        }
523                        else if ( match[2] ) {
524                                Sizzle.error( match[0] );
525                        }
526
527                        // TODO: Move to normal caching system
528                        match[0] = done++;
529
530                        return match;
531                },
532
533                ATTR: function( match, curLoop, inplace, result, not, isXML ) {
534                        var name = match[1] = match[1].replace(/\\/g, "");
535                       
536                        if ( !isXML && Expr.attrMap[name] ) {
537                                match[1] = Expr.attrMap[name];
538                        }
539
540                        // Handle if an un-quoted value was used
541                        match[4] = ( match[4] || match[5] || "" ).replace(/\\/g, "");
542
543                        if ( match[2] === "~=" ) {
544                                match[4] = " " + match[4] + " ";
545                        }
546
547                        return match;
548                },
549
550                PSEUDO: function( match, curLoop, inplace, result, not ) {
551                        if ( match[1] === "not" ) {
552                                // If we're dealing with a complex expression, or a simple one
553                                if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
554                                        match[3] = Sizzle(match[3], null, null, curLoop);
555
556                                } else {
557                                        var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
558
559                                        if ( !inplace ) {
560                                                result.push.apply( result, ret );
561                                        }
562
563                                        return false;
564                                }
565
566                        } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
567                                return true;
568                        }
569                       
570                        return match;
571                },
572
573                POS: function( match ) {
574                        match.unshift( true );
575
576                        return match;
577                }
578        },
579       
580        filters: {
581                enabled: function( elem ) {
582                        return elem.disabled === false && elem.type !== "hidden";
583                },
584
585                disabled: function( elem ) {
586                        return elem.disabled === true;
587                },
588
589                checked: function( elem ) {
590                        return elem.checked === true;
591                },
592               
593                selected: function( elem ) {
594                        // Accessing this property makes selected-by-default
595                        // options in Safari work properly
596                        elem.parentNode.selectedIndex;
597                       
598                        return elem.selected === true;
599                },
600
601                parent: function( elem ) {
602                        return !!elem.firstChild;
603                },
604
605                empty: function( elem ) {
606                        return !elem.firstChild;
607                },
608
609                has: function( elem, i, match ) {
610                        return !!Sizzle( match[3], elem ).length;
611                },
612
613                header: function( elem ) {
614                        return (/h\d/i).test( elem.nodeName );
615                },
616
617                text: function( elem ) {
618                        return "text" === elem.type;
619                },
620                radio: function( elem ) {
621                        return "radio" === elem.type;
622                },
623
624                checkbox: function( elem ) {
625                        return "checkbox" === elem.type;
626                },
627
628                file: function( elem ) {
629                        return "file" === elem.type;
630                },
631                password: function( elem ) {
632                        return "password" === elem.type;
633                },
634
635                submit: function( elem ) {
636                        return "submit" === elem.type;
637                },
638
639                image: function( elem ) {
640                        return "image" === elem.type;
641                },
642
643                reset: function( elem ) {
644                        return "reset" === elem.type;
645                },
646
647                button: function( elem ) {
648                        return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
649                },
650
651                input: function( elem ) {
652                        return (/input|select|textarea|button/i).test( elem.nodeName );
653                }
654        },
655        setFilters: {
656                first: function( elem, i ) {
657                        return i === 0;
658                },
659
660                last: function( elem, i, match, array ) {
661                        return i === array.length - 1;
662                },
663
664                even: function( elem, i ) {
665                        return i % 2 === 0;
666                },
667
668                odd: function( elem, i ) {
669                        return i % 2 === 1;
670                },
671
672                lt: function( elem, i, match ) {
673                        return i < match[3] - 0;
674                },
675
676                gt: function( elem, i, match ) {
677                        return i > match[3] - 0;
678                },
679
680                nth: function( elem, i, match ) {
681                        return match[3] - 0 === i;
682                },
683
684                eq: function( elem, i, match ) {
685                        return match[3] - 0 === i;
686                }
687        },
688        filter: {
689                PSEUDO: function( elem, match, i, array ) {
690                        var name = match[1],
691                                filter = Expr.filters[ name ];
692
693                        if ( filter ) {
694                                return filter( elem, i, match, array );
695
696                        } else if ( name === "contains" ) {
697                                return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
698
699                        } else if ( name === "not" ) {
700                                var not = match[3];
701
702                                for ( var j = 0, l = not.length; j < l; j++ ) {
703                                        if ( not[j] === elem ) {
704                                                return false;
705                                        }
706                                }
707
708                                return true;
709
710                        } else {
711                                Sizzle.error( name );
712                        }
713                },
714
715                CHILD: function( elem, match ) {
716                        var type = match[1],
717                                node = elem;
718
719                        switch ( type ) {
720                                case "only":
721                                case "first":
722                                        while ( (node = node.previousSibling) )  {
723                                                if ( node.nodeType === 1 ) {
724                                                        return false;
725                                                }
726                                        }
727
728                                        if ( type === "first" ) {
729                                                return true;
730                                        }
731
732                                        node = elem;
733
734                                case "last":
735                                        while ( (node = node.nextSibling) )      {
736                                                if ( node.nodeType === 1 ) {
737                                                        return false;
738                                                }
739                                        }
740
741                                        return true;
742
743                                case "nth":
744                                        var first = match[2],
745                                                last = match[3];
746
747                                        if ( first === 1 && last === 0 ) {
748                                                return true;
749                                        }
750                                       
751                                        var doneName = match[0],
752                                                parent = elem.parentNode;
753       
754                                        if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
755                                                var count = 0;
756                                               
757                                                for ( node = parent.firstChild; node; node = node.nextSibling ) {
758                                                        if ( node.nodeType === 1 ) {
759                                                                node.nodeIndex = ++count;
760                                                        }
761                                                }
762
763                                                parent.sizcache = doneName;
764                                        }
765                                       
766                                        var diff = elem.nodeIndex - last;
767
768                                        if ( first === 0 ) {
769                                                return diff === 0;
770
771                                        } else {
772                                                return ( diff % first === 0 && diff / first >= 0 );
773                                        }
774                        }
775                },
776
777                ID: function( elem, match ) {
778                        return elem.nodeType === 1 && elem.getAttribute("id") === match;
779                },
780
781                TAG: function( elem, match ) {
782                        return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
783                },
784               
785                CLASS: function( elem, match ) {
786                        return (" " + (elem.className || elem.getAttribute("class")) + " ")
787                                .indexOf( match ) > -1;
788                },
789
790                ATTR: function( elem, match ) {
791                        var name = match[1],
792                                result = Expr.attrHandle[ name ] ?
793                                        Expr.attrHandle[ name ]( elem ) :
794                                        elem[ name ] != null ?
795                                                elem[ name ] :
796                                                elem.getAttribute( name ),
797                                value = result + "",
798                                type = match[2],
799                                check = match[4];
800
801                        return result == null ?
802                                type === "!=" :
803                                type === "=" ?
804                                value === check :
805                                type === "*=" ?
806                                value.indexOf(check) >= 0 :
807                                type === "~=" ?
808                                (" " + value + " ").indexOf(check) >= 0 :
809                                !check ?
810                                value && result !== false :
811                                type === "!=" ?
812                                value !== check :
813                                type === "^=" ?
814                                value.indexOf(check) === 0 :
815                                type === "$=" ?
816                                value.substr(value.length - check.length) === check :
817                                type === "|=" ?
818                                value === check || value.substr(0, check.length + 1) === check + "-" :
819                                false;
820                },
821
822                POS: function( elem, match, i, array ) {
823                        var name = match[2],
824                                filter = Expr.setFilters[ name ];
825
826                        if ( filter ) {
827                                return filter( elem, i, match, array );
828                        }
829                }
830        }
831};
832
833var origPOS = Expr.match.POS,
834        fescape = function(all, num){
835                return "\\" + (num - 0 + 1);
836        };
837
838for ( var type in Expr.match ) {
839        Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
840        Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
841}
842
843var makeArray = function( array, results ) {
844        array = Array.prototype.slice.call( array, 0 );
845
846        if ( results ) {
847                results.push.apply( results, array );
848                return results;
849        }
850       
851        return array;
852};
853
854// Perform a simple check to determine if the browser is capable of
855// converting a NodeList to an array using builtin methods.
856// Also verifies that the returned array holds DOM nodes
857// (which is not the case in the Blackberry browser)
858try {
859        Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
860
861// Provide a fallback method if it does not work
862} catch( e ) {
863        makeArray = function( array, results ) {
864                var i = 0,
865                        ret = results || [];
866
867                if ( toString.call(array) === "[object Array]" ) {
868                        Array.prototype.push.apply( ret, array );
869
870                } else {
871                        if ( typeof array.length === "number" ) {
872                                for ( var l = array.length; i < l; i++ ) {
873                                        ret.push( array[i] );
874                                }
875
876                        } else {
877                                for ( ; array[i]; i++ ) {
878                                        ret.push( array[i] );
879                                }
880                        }
881                }
882
883                return ret;
884        };
885}
886
887var sortOrder, siblingCheck;
888
889if ( document.documentElement.compareDocumentPosition ) {
890        sortOrder = function( a, b ) {
891                if ( a === b ) {
892                        hasDuplicate = true;
893                        return 0;
894                }
895
896                if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
897                        return a.compareDocumentPosition ? -1 : 1;
898                }
899
900                return a.compareDocumentPosition(b) & 4 ? -1 : 1;
901        };
902
903} else {
904        sortOrder = function( a, b ) {
905                var al, bl,
906                        ap = [],
907                        bp = [],
908                        aup = a.parentNode,
909                        bup = b.parentNode,
910                        cur = aup;
911
912                // The nodes are identical, we can exit early
913                if ( a === b ) {
914                        hasDuplicate = true;
915                        return 0;
916
917                // If the nodes are siblings (or identical) we can do a quick check
918                } else if ( aup === bup ) {
919                        return siblingCheck( a, b );
920
921                // If no parents were found then the nodes are disconnected
922                } else if ( !aup ) {
923                        return -1;
924
925                } else if ( !bup ) {
926                        return 1;
927                }
928
929                // Otherwise they're somewhere else in the tree so we need
930                // to build up a full list of the parentNodes for comparison
931                while ( cur ) {
932                        ap.unshift( cur );
933                        cur = cur.parentNode;
934                }
935
936                cur = bup;
937
938                while ( cur ) {
939                        bp.unshift( cur );
940                        cur = cur.parentNode;
941                }
942
943                al = ap.length;
944                bl = bp.length;
945
946                // Start walking down the tree looking for a discrepancy
947                for ( var i = 0; i < al && i < bl; i++ ) {
948                        if ( ap[i] !== bp[i] ) {
949                                return siblingCheck( ap[i], bp[i] );
950                        }
951                }
952
953                // We ended someplace up the tree so do a sibling check
954                return i === al ?
955                        siblingCheck( a, bp[i], -1 ) :
956                        siblingCheck( ap[i], b, 1 );
957        };
958
959        siblingCheck = function( a, b, ret ) {
960                if ( a === b ) {
961                        return ret;
962                }
963
964                var cur = a.nextSibling;
965
966                while ( cur ) {
967                        if ( cur === b ) {
968                                return -1;
969                        }
970
971                        cur = cur.nextSibling;
972                }
973
974                return 1;
975        };
976}
977
978// Utility function for retreiving the text value of an array of DOM nodes
979Sizzle.getText = function( elems ) {
980        var ret = "", elem;
981
982        for ( var i = 0; elems[i]; i++ ) {
983                elem = elems[i];
984
985                // Get the text from text nodes and CDATA nodes
986                if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
987                        ret += elem.nodeValue;
988
989                // Traverse everything else, except comment nodes
990                } else if ( elem.nodeType !== 8 ) {
991                        ret += Sizzle.getText( elem.childNodes );
992                }
993        }
994
995        return ret;
996};
997
998// Check to see if the browser returns elements by name when
999// querying by getElementById (and provide a workaround)
1000(function(){
1001        // We're going to inject a fake input element with a specified name
1002        var form = document.createElement("div"),
1003                id = "script" + (new Date()).getTime(),
1004                root = document.documentElement;
1005
1006        form.innerHTML = "<a name='" + id + "'/>";
1007
1008        // Inject it into the root element, check its status, and remove it quickly
1009        root.insertBefore( form, root.firstChild );
1010
1011        // The workaround has to do additional checks after a getElementById
1012        // Which slows things down for other browsers (hence the branching)
1013        if ( document.getElementById( id ) ) {
1014                Expr.find.ID = function( match, context, isXML ) {
1015                        if ( typeof context.getElementById !== "undefined" && !isXML ) {
1016                                var m = context.getElementById(match[1]);
1017
1018                                return m ?
1019                                        m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
1020                                                [m] :
1021                                                undefined :
1022                                        [];
1023                        }
1024                };
1025
1026                Expr.filter.ID = function( elem, match ) {
1027                        var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
1028
1029                        return elem.nodeType === 1 && node && node.nodeValue === match;
1030                };
1031        }
1032
1033        root.removeChild( form );
1034
1035        // release memory in IE
1036        root = form = null;
1037})();
1038
1039(function(){
1040        // Check to see if the browser returns only elements
1041        // when doing getElementsByTagName("*")
1042
1043        // Create a fake element
1044        var div = document.createElement("div");
1045        div.appendChild( document.createComment("") );
1046
1047        // Make sure no comments are found
1048        if ( div.getElementsByTagName("*").length > 0 ) {
1049                Expr.find.TAG = function( match, context ) {
1050                        var results = context.getElementsByTagName( match[1] );
1051
1052                        // Filter out possible comments
1053                        if ( match[1] === "*" ) {
1054                                var tmp = [];
1055
1056                                for ( var i = 0; results[i]; i++ ) {
1057                                        if ( results[i].nodeType === 1 ) {
1058                                                tmp.push( results[i] );
1059                                        }
1060                                }
1061
1062                                results = tmp;
1063                        }
1064
1065                        return results;
1066                };
1067        }
1068
1069        // Check to see if an attribute returns normalized href attributes
1070        div.innerHTML = "<a href='#'></a>";
1071
1072        if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
1073                        div.firstChild.getAttribute("href") !== "#" ) {
1074
1075                Expr.attrHandle.href = function( elem ) {
1076                        return elem.getAttribute( "href", 2 );
1077                };
1078        }
1079
1080        // release memory in IE
1081        div = null;
1082})();
1083
1084if ( document.querySelectorAll ) {
1085        (function(){
1086                var oldSizzle = Sizzle,
1087                        div = document.createElement("div"),
1088                        id = "__sizzle__";
1089
1090                div.innerHTML = "<p class='TEST'></p>";
1091
1092                // Safari can't handle uppercase or unicode characters when
1093                // in quirks mode.
1094                if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
1095                        return;
1096                }
1097       
1098                Sizzle = function( query, context, extra, seed ) {
1099                        context = context || document;
1100
1101                        // Only use querySelectorAll on non-XML documents
1102                        // (ID selectors don't work in non-HTML documents)
1103                        if ( !seed && !Sizzle.isXML(context) ) {
1104                                // See if we find a selector to speed up
1105                                var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
1106                               
1107                                if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
1108                                        // Speed-up: Sizzle("TAG")
1109                                        if ( match[1] ) {
1110                                                return makeArray( context.getElementsByTagName( query ), extra );
1111                                       
1112                                        // Speed-up: Sizzle(".CLASS")
1113                                        } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
1114                                                return makeArray( context.getElementsByClassName( match[2] ), extra );
1115                                        }
1116                                }
1117                               
1118                                if ( context.nodeType === 9 ) {
1119                                        // Speed-up: Sizzle("body")
1120                                        // The body element only exists once, optimize finding it
1121                                        if ( query === "body" && context.body ) {
1122                                                return makeArray( [ context.body ], extra );
1123                                               
1124                                        // Speed-up: Sizzle("#ID")
1125                                        } else if ( match && match[3] ) {
1126                                                var elem = context.getElementById( match[3] );
1127
1128                                                // Check parentNode to catch when Blackberry 4.6 returns
1129                                                // nodes that are no longer in the document #6963
1130                                                if ( elem && elem.parentNode ) {
1131                                                        // Handle the case where IE and Opera return items
1132                                                        // by name instead of ID
1133                                                        if ( elem.id === match[3] ) {
1134                                                                return makeArray( [ elem ], extra );
1135                                                        }
1136                                                       
1137                                                } else {
1138                                                        return makeArray( [], extra );
1139                                                }
1140                                        }
1141                                       
1142                                        try {
1143                                                return makeArray( context.querySelectorAll(query), extra );
1144                                        } catch(qsaError) {}
1145
1146                                // qSA works strangely on Element-rooted queries
1147                                // We can work around this by specifying an extra ID on the root
1148                                // and working up from there (Thanks to Andrew Dupont for the technique)
1149                                // IE 8 doesn't work on object elements
1150                                } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
1151                                        var old = context.getAttribute( "id" ),
1152                                                nid = old || id,
1153                                                hasParent = context.parentNode,
1154                                                relativeHierarchySelector = /^\s*[+~]/.test( query );
1155
1156                                        if ( !old ) {
1157                                                context.setAttribute( "id", nid );
1158                                        } else {
1159                                                nid = nid.replace( /'/g, "\\$&" );
1160                                        }
1161                                        if ( relativeHierarchySelector && hasParent ) {
1162                                                context = context.parentNode;
1163                                        }
1164
1165                                        try {
1166                                                if ( !relativeHierarchySelector || hasParent ) {
1167                                                        return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
1168                                                }
1169
1170                                        } catch(pseudoError) {
1171                                        } finally {
1172                                                if ( !old ) {
1173                                                        context.removeAttribute( "id" );
1174                                                }
1175                                        }
1176                                }
1177                        }
1178               
1179                        return oldSizzle(query, context, extra, seed);
1180                };
1181
1182                for ( var prop in oldSizzle ) {
1183                        Sizzle[ prop ] = oldSizzle[ prop ];
1184                }
1185
1186                // release memory in IE
1187                div = null;
1188        })();
1189}
1190
1191(function(){
1192        var html = document.documentElement,
1193                matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,
1194                pseudoWorks = false;
1195
1196        try {
1197                // This should fail with an exception
1198                // Gecko does not error, returns false instead
1199                matches.call( document.documentElement, "[test!='']:sizzle" );
1200       
1201        } catch( pseudoError ) {
1202                pseudoWorks = true;
1203        }
1204
1205        if ( matches ) {
1206                Sizzle.matchesSelector = function( node, expr ) {
1207                        // Make sure that attribute selectors are quoted
1208                        expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
1209
1210                        if ( !Sizzle.isXML( node ) ) {
1211                                try {
1212                                        if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
1213                                                return matches.call( node, expr );
1214                                        }
1215                                } catch(e) {}
1216                        }
1217
1218                        return Sizzle(expr, null, null, [node]).length > 0;
1219                };
1220        }
1221})();
1222
1223(function(){
1224        var div = document.createElement("div");
1225
1226        div.innerHTML = "<div class='test e'></div><div class='test'></div>";
1227
1228        // Opera can't find a second classname (in 9.6)
1229        // Also, make sure that getElementsByClassName actually exists
1230        if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
1231                return;
1232        }
1233
1234        // Safari caches class attributes, doesn't catch changes (in 3.2)
1235        div.lastChild.className = "e";
1236
1237        if ( div.getElementsByClassName("e").length === 1 ) {
1238                return;
1239        }
1240       
1241        Expr.order.splice(1, 0, "CLASS");
1242        Expr.find.CLASS = function( match, context, isXML ) {
1243                if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
1244                        return context.getElementsByClassName(match[1]);
1245                }
1246        };
1247
1248        // release memory in IE
1249        div = null;
1250})();
1251
1252function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
1253        for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1254                var elem = checkSet[i];
1255
1256                if ( elem ) {
1257                        var match = false;
1258
1259                        elem = elem[dir];
1260
1261                        while ( elem ) {
1262                                if ( elem.sizcache === doneName ) {
1263                                        match = checkSet[elem.sizset];
1264                                        break;
1265                                }
1266
1267                                if ( elem.nodeType === 1 && !isXML ){
1268                                        elem.sizcache = doneName;
1269                                        elem.sizset = i;
1270                                }
1271
1272                                if ( elem.nodeName.toLowerCase() === cur ) {
1273                                        match = elem;
1274                                        break;
1275                                }
1276
1277                                elem = elem[dir];
1278                        }
1279
1280                        checkSet[i] = match;
1281                }
1282        }
1283}
1284
1285function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
1286        for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1287                var elem = checkSet[i];
1288
1289                if ( elem ) {
1290                        var match = false;
1291                       
1292                        elem = elem[dir];
1293
1294                        while ( elem ) {
1295                                if ( elem.sizcache === doneName ) {
1296                                        match = checkSet[elem.sizset];
1297                                        break;
1298                                }
1299
1300                                if ( elem.nodeType === 1 ) {
1301                                        if ( !isXML ) {
1302                                                elem.sizcache = doneName;
1303                                                elem.sizset = i;
1304                                        }
1305
1306                                        if ( typeof cur !== "string" ) {
1307                                                if ( elem === cur ) {
1308                                                        match = true;
1309                                                        break;
1310                                                }
1311
1312                                        } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
1313                                                match = elem;
1314                                                break;
1315                                        }
1316                                }
1317
1318                                elem = elem[dir];
1319                        }
1320
1321                        checkSet[i] = match;
1322                }
1323        }
1324}
1325
1326if ( document.documentElement.contains ) {
1327        Sizzle.contains = function( a, b ) {
1328                return a !== b && (a.contains ? a.contains(b) : true);
1329        };
1330
1331} else if ( document.documentElement.compareDocumentPosition ) {
1332        Sizzle.contains = function( a, b ) {
1333                return !!(a.compareDocumentPosition(b) & 16);
1334        };
1335
1336} else {
1337        Sizzle.contains = function() {
1338                return false;
1339        };
1340}
1341
1342Sizzle.isXML = function( elem ) {
1343        // documentElement is verified for cases where it doesn't yet exist
1344        // (such as loading iframes in IE - #4833)
1345        var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
1346
1347        return documentElement ? documentElement.nodeName !== "HTML" : false;
1348};
1349
1350var posProcess = function( selector, context ) {
1351        var match,
1352                tmpSet = [],
1353                later = "",
1354                root = context.nodeType ? [context] : context;
1355
1356        // Position selectors must be done after the filter
1357        // And so must :not(positional) so we move all PSEUDOs to the end
1358        while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
1359                later += match[0];
1360                selector = selector.replace( Expr.match.PSEUDO, "" );
1361        }
1362
1363        selector = Expr.relative[selector] ? selector + "*" : selector;
1364
1365        for ( var i = 0, l = root.length; i < l; i++ ) {
1366                Sizzle( selector, root[i], tmpSet );
1367        }
1368
1369        return Sizzle.filter( later, tmpSet );
1370};
1371
1372// EXPOSE
1373
1374window.Sizzle = Sizzle;
1375
1376})();
Note: See TracBrowser for help on using the repository browser.