Tagging the 1.5rc1 release.
[jquery.git] / src / traversing.js
index f57819d..90601df 100644 (file)
@@ -4,18 +4,21 @@ var runtil = /Until$/,
        rparentsprev = /^(?:parents|prevUntil|prevAll)/,
        // Note: This RegExp should be improved, or likely pulled from Sizzle
        rmultiselector = /,/,
-       rchild = /^\s*>/,
        isSimple = /^.[^:#\[\.,]*$/,
-       slice = Array.prototype.slice;
+       slice = Array.prototype.slice,
+       POS = jQuery.expr.match.POS,
+       // methods guaranteed to produce a unique set when starting from a unique set
+       guaranteedUnique = {
+               children: true,
+               contents: true,
+               next: true,
+               prev: true
+       };
 
 jQuery.fn.extend({
        find: function( selector ) {
-               // Handle "> div" child selectors and pass them to .children()
-               if ( typeof selector === "string" && rchild.test( selector ) ) {
-                       return this.children( selector.replace( rchild, "" ) );
-               }
-
-               var ret = this.pushStack( "", "find", selector ), length = 0;
+               var ret = this.pushStack( "", "find", selector ),
+                       length = 0;
 
                for ( var i = 0, l = this.length; i < l; i++ ) {
                        length = ret.length;
@@ -55,24 +58,25 @@ jQuery.fn.extend({
        filter: function( selector ) {
                return this.pushStack( winnow(this, selector, true), "filter", selector );
        },
-       
+
        is: function( selector ) {
                return !!selector && jQuery.filter( selector, this ).length > 0;
        },
 
        closest: function( selectors, context ) {
-               var ret;
+               var ret = [], i, l, cur = this[0];
 
                if ( jQuery.isArray( selectors ) ) {
-                       var cur = this[0], match, matches = {}, selector, level = 1;
-                       ret = [];
+                       var match, selector,
+                               matches = {},
+                               level = 1;
 
                        if ( cur && selectors.length ) {
-                               for ( var i = 0, l = selectors.length; i < l; i++ ) {
+                               for ( i = 0, l = selectors.length; i < l; i++ ) {
                                        selector = selectors[i];
 
                                        if ( !matches[selector] ) {
-                                               matches[selector] = jQuery.expr.match.POS.test( selector ) ? 
+                                               matches[selector] = jQuery.expr.match.POS.test( selector ) ?
                                                        jQuery( selector, context || this.context ) :
                                                        selector;
                                        }
@@ -95,26 +99,31 @@ jQuery.fn.extend({
                        return ret;
                }
 
-               var pos = jQuery.expr.match.POS.test( selectors ) ? 
+               var pos = POS.test( selectors ) ?
                        jQuery( selectors, context || this.context ) : null;
 
-               ret = jQuery.map(this.get(),function( cur,i ) {
-                       while ( cur && cur.ownerDocument && cur !== context ) {
-                               if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
-                                       return cur;
-                               }
+               for ( i = 0, l = this.length; i < l; i++ ) {
+                       cur = this[i];
+
+                       while ( cur ) {
+                               if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+                                       ret.push( cur );
+                                       break;
 
-                               cur = cur.parentNode;
+                               } else {
+                                       cur = cur.parentNode;
+                                       if ( !cur || !cur.ownerDocument || cur === context ) {
+                                               break;
+                                       }
+                               }
                        }
+               }
 
-                       return null;
-               });
-               
                ret = ret.length > 1 ? jQuery.unique(ret) : ret;
-               
+
                return this.pushStack( ret, "closest", selectors );
        },
-       
+
        // Determine the position of an element within
        // the matched set of elements
        index: function( elem ) {
@@ -132,7 +141,7 @@ jQuery.fn.extend({
 
        add: function( selector, context ) {
                var set = typeof selector === "string" ?
-                               jQuery( selector, context || this.context ) :
+                               jQuery( selector, context ) :
                                jQuery.makeArray( selector ),
                        all = jQuery.merge( this.get(), set );
 
@@ -194,8 +203,13 @@ jQuery.each({
        }
 }, function( name, fn ) {
        jQuery.fn[ name ] = function( until, selector ) {
-               var ret = jQuery.map( this, fn, until );
-               
+               var ret = jQuery.map( this, fn, until ),
+                // The variable 'args' was introduced in
+                // https://github.com/jquery/jquery/commit/52a0238
+                // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
+                // http://code.google.com/p/v8/issues/detail?id=1050
+                    args = slice.call(arguments);
+
                if ( !runtil.test( name ) ) {
                        selector = until;
                }
@@ -204,13 +218,13 @@ jQuery.each({
                        ret = jQuery.filter( selector, ret );
                }
 
-               ret = this.length > 1 ? jQuery.unique( ret ) : ret;
+               ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
 
                if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
                        ret = ret.reverse();
                }
 
-               return this.pushStack( ret, name, slice.call(arguments).join(",") );
+               return this.pushStack( ret, name, args.join(",") );
        };
 });
 
@@ -220,11 +234,15 @@ jQuery.extend({
                        expr = ":not(" + expr + ")";
                }
 
-               return jQuery.find.matches(expr, elems);
+               return elems.length === 1 ?
+                       jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+                       jQuery.find.matches(expr, elems);
        },
-       
+
        dir: function( elem, dir, until ) {
-               var matched = [], cur = elem[dir];
+               var matched = [],
+                       cur = elem[ dir ];
+
                while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
                        if ( cur.nodeType === 1 ) {
                                matched.push( cur );