Prevent duplicate selectors from having to match in closest.
[jquery.git] / src / traversing.js
index a467e7c..609e2eb 100644 (file)
@@ -6,9 +6,9 @@ var winnow = function( elements, qualifier, keep ) {
        } else if( qualifier.nodeType ) {
                return jQuery.grep(elements, function(elem, i) {
                        return (elem === qualifier) === keep;
-               })
+               });
        } else if( typeof qualifier === "string" ) {
-               var filtered = jQuery.grep(elements, function(elem) { return elem.nodeType === 1 });
+               var filtered = jQuery.grep(elements, function(elem) { return elem.nodeType === 1; });
 
                if(isSimple.test( qualifier )) {
                        return jQuery.filter(qualifier, filtered, !keep);
@@ -20,7 +20,7 @@ var winnow = function( elements, qualifier, keep ) {
        return jQuery.grep(elements, function(elem, i) {
                return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
        });
-}
+};
 
 jQuery.fn.extend({
        find: function( selector ) {
@@ -54,21 +54,50 @@ jQuery.fn.extend({
                return this.pushStack( winnow(this, selector, true), "filter", selector );
        },
 
-       closest: function( selector, context ) {
-               var pos = jQuery.expr.match.POS.test( selector ) ? 
-                       jQuery( selector, context || this.context ) : null;
+       closest: function( selectors, context ) {
+               if ( jQuery.isArray( selectors ) ) {
+                       var ret = [], cur = this[0], match, selector, done;
+
+                       if ( cur && selectors.length ) {
+                               for ( var i = 0, l = selectors.length; i < l; i++ ) {
+                                       selectors[i] = jQuery.expr.match.POS.test( selector ) ? 
+                                               jQuery( selector, context || this.context ) :
+                                               selectors[i];
+                               }
+
+                               while ( cur && cur.ownerDocument && cur !== context ) {
+                                       for ( var i = 0; i < selectors.length; i++ ) {
+                                               match = selectors[i];
+                                               selector = match.selector || match;
+
+                                               // Get rid of duplicate selectors
+                                               if ( selector === done ) {
+                                                       selectors.splice(i--, 1);
+
+                                               // See if we have a match
+                                               } else if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
+                                                       ret.push({ selector: selector, elem: cur });
+                                                       selectors.splice(i--, 1);
+                                                       done = selector;
+                                               }
+                                       }
+                                       cur = cur.parentNode;
+                               }
+                       }
+
+                       return ret;
+               }
+
+               var pos = jQuery.expr.match.POS.test( selectors ) ? 
+                       jQuery( selectors, context || this.context ) : null;
 
-               return this.map(function(){
-                       var cur = this, closer = 0;
+               return this.map(function(i, cur){
                        while ( cur && cur.ownerDocument && cur !== context ) {
-                               if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
-                                       jQuery.lastCloser = closer;
+                               if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
                                        return cur;
                                }
                                cur = cur.parentNode;
-                               closer++;
                        }
-                       jQuery.lastCloser = -1;
                        return null;
                });
        },