* A low-level selection function that works with jQuery's compiled * selector functions * @param {String|Function} selector A selector or a pre-compiled * selector function built with jQuery selector compile * @param {Element} context * @param {Array} [results] * @param {Array} [seed] A set
( selector, context, results, seed )
| 2607 | * @param {Array} [seed] A set of elements to match against |
| 2608 | */ |
| 2609 | function select( selector, context, results, seed ) { |
| 2610 | var i, tokens, token, type, find, |
| 2611 | compiled = typeof selector === "function" && selector, |
| 2612 | match = !seed && tokenize( ( selector = compiled.selector || selector ) ); |
| 2613 | |
| 2614 | results = results || []; |
| 2615 | |
| 2616 | // Try to minimize operations if there is only one selector in the list and no seed |
| 2617 | // (the latter of which guarantees us context) |
| 2618 | if ( match.length === 1 ) { |
| 2619 | |
| 2620 | // Reduce context if the leading compound selector is an ID |
| 2621 | tokens = match[ 0 ] = match[ 0 ].slice( 0 ); |
| 2622 | if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && |
| 2623 | context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { |
| 2624 | |
| 2625 | context = ( Expr.find.ID( |
| 2626 | token.matches[ 0 ].replace( runescape, funescape ), |
| 2627 | context |
| 2628 | ) || [] )[ 0 ]; |
| 2629 | if ( !context ) { |
| 2630 | return results; |
| 2631 | |
| 2632 | // Precompiled matchers will still verify ancestry, so step up a level |
| 2633 | } else if ( compiled ) { |
| 2634 | context = context.parentNode; |
| 2635 | } |
| 2636 | |
| 2637 | selector = selector.slice( tokens.shift().value.length ); |
| 2638 | } |
| 2639 | |
| 2640 | // Fetch a seed set for right-to-left matching |
| 2641 | i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length; |
| 2642 | while ( i-- ) { |
| 2643 | token = tokens[ i ]; |
| 2644 | |
| 2645 | // Abort if we hit a combinator |
| 2646 | if ( Expr.relative[ ( type = token.type ) ] ) { |
| 2647 | break; |
| 2648 | } |
| 2649 | if ( ( find = Expr.find[ type ] ) ) { |
| 2650 | |
| 2651 | // Search, expanding context for leading sibling combinators |
| 2652 | if ( ( seed = find( |
| 2653 | token.matches[ 0 ].replace( runescape, funescape ), |
| 2654 | rsibling.test( tokens[ 0 ].type ) && |
| 2655 | testContext( context.parentNode ) || context |
| 2656 | ) ) ) { |
| 2657 | |
| 2658 | // If seed is empty or no tokens remain, we can return early |
| 2659 | tokens.splice( i, 1 ); |
| 2660 | selector = seed.length && toSelector( tokens ); |
| 2661 | if ( !selector ) { |
| 2662 | push.apply( results, seed ); |
| 2663 | return results; |
| 2664 | } |
| 2665 | |
| 2666 | break; |
no test coverage detected