| 2100 | } |
| 2101 | |
| 2102 | function addCombinator( matcher, combinator, base ) { |
| 2103 | var dir = combinator.dir, |
| 2104 | checkNonElements = base && dir === "parentNode", |
| 2105 | doneName = done++; |
| 2106 | |
| 2107 | return combinator.first ? |
| 2108 | // Check against closest ancestor/preceding element |
| 2109 | function( elem, context, xml ) { |
| 2110 | while ( (elem = elem[ dir ]) ) { |
| 2111 | if ( elem.nodeType === 1 || checkNonElements ) { |
| 2112 | return matcher( elem, context, xml ); |
| 2113 | } |
| 2114 | } |
| 2115 | } : |
| 2116 | |
| 2117 | // Check against all ancestor/preceding elements |
| 2118 | function( elem, context, xml ) { |
| 2119 | var oldCache, outerCache, |
| 2120 | newCache = [ dirruns, doneName ]; |
| 2121 | |
| 2122 | // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching |
| 2123 | if ( xml ) { |
| 2124 | while ( (elem = elem[ dir ]) ) { |
| 2125 | if ( elem.nodeType === 1 || checkNonElements ) { |
| 2126 | if ( matcher( elem, context, xml ) ) { |
| 2127 | return true; |
| 2128 | } |
| 2129 | } |
| 2130 | } |
| 2131 | } else { |
| 2132 | while ( (elem = elem[ dir ]) ) { |
| 2133 | if ( elem.nodeType === 1 || checkNonElements ) { |
| 2134 | outerCache = elem[ expando ] || (elem[ expando ] = {}); |
| 2135 | if ( (oldCache = outerCache[ dir ]) && |
| 2136 | oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { |
| 2137 | |
| 2138 | // Assign to newCache so results back-propagate to previous elements |
| 2139 | return (newCache[ 2 ] = oldCache[ 2 ]); |
| 2140 | } else { |
| 2141 | // Reuse newcache so results back-propagate to previous elements |
| 2142 | outerCache[ dir ] = newCache; |
| 2143 | |
| 2144 | // A match means we're done; a fail means we have to keep checking |
| 2145 | if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { |
| 2146 | return true; |
| 2147 | } |
| 2148 | } |
| 2149 | } |
| 2150 | } |
| 2151 | } |
| 2152 | }; |
| 2153 | } |
| 2154 | |
| 2155 | function elementMatcher( matchers ) { |
| 2156 | return matchers.length > 1 ? |