| 2064 | } |
| 2065 | |
| 2066 | function addCombinator( matcher, combinator, base ) { |
| 2067 | var dir = combinator.dir, |
| 2068 | checkNonElements = base && dir === "parentNode", |
| 2069 | doneName = done++; |
| 2070 | |
| 2071 | return combinator.first ? |
| 2072 | // Check against closest ancestor/preceding element |
| 2073 | function( elem, context, xml ) { |
| 2074 | while ( (elem = elem[ dir ]) ) { |
| 2075 | if ( elem.nodeType === 1 || checkNonElements ) { |
| 2076 | return matcher( elem, context, xml ); |
| 2077 | } |
| 2078 | } |
| 2079 | } : |
| 2080 | |
| 2081 | // Check against all ancestor/preceding elements |
| 2082 | function( elem, context, xml ) { |
| 2083 | var oldCache, outerCache, |
| 2084 | newCache = [ dirruns, doneName ]; |
| 2085 | |
| 2086 | // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching |
| 2087 | if ( xml ) { |
| 2088 | while ( (elem = elem[ dir ]) ) { |
| 2089 | if ( elem.nodeType === 1 || checkNonElements ) { |
| 2090 | if ( matcher( elem, context, xml ) ) { |
| 2091 | return true; |
| 2092 | } |
| 2093 | } |
| 2094 | } |
| 2095 | } else { |
| 2096 | while ( (elem = elem[ dir ]) ) { |
| 2097 | if ( elem.nodeType === 1 || checkNonElements ) { |
| 2098 | outerCache = elem[ expando ] || (elem[ expando ] = {}); |
| 2099 | if ( (oldCache = outerCache[ dir ]) && |
| 2100 | oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { |
| 2101 | |
| 2102 | // Assign to newCache so results back-propagate to previous elements |
| 2103 | return (newCache[ 2 ] = oldCache[ 2 ]); |
| 2104 | } else { |
| 2105 | // Reuse newcache so results back-propagate to previous elements |
| 2106 | outerCache[ dir ] = newCache; |
| 2107 | |
| 2108 | // A match means we're done; a fail means we have to keep checking |
| 2109 | if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { |
| 2110 | return true; |
| 2111 | } |
| 2112 | } |
| 2113 | } |
| 2114 | } |
| 2115 | } |
| 2116 | }; |
| 2117 | } |
| 2118 | |
| 2119 | function elementMatcher( matchers ) { |
| 2120 | return matchers.length > 1 ? |