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