Merge branch '2773_find_closest' of https://github.com/timmywil/jquery into timmywil-2773_find_closest

Conflicts:
	test/unit/traversing.js
This commit is contained in:
jeresig 2011-04-10 16:37:09 -04:00
commit 523db95de2
3 changed files with 76 additions and 15 deletions

View file

@ -88,7 +88,7 @@ jQuery.fn = jQuery.prototype = {
if ( selector === "body" && !context && document.body ) { if ( selector === "body" && !context && document.body ) {
this.context = document; this.context = document;
this[0] = document.body; this[0] = document.body;
this.selector = "body"; this.selector = selector;
this.length = 1; this.length = 1;
return this; return this;
} }

View file

@ -17,17 +17,30 @@ var runtil = /Until$/,
jQuery.fn.extend({ jQuery.fn.extend({
find: function( selector ) { find: function( selector ) {
var ret = this.pushStack( "", "find", selector ), var self = this,
length = 0; i, l;
for ( var i = 0, l = this.length; i < l; i++ ) { if ( typeof selector !== "string" ) {
return jQuery( selector ).filter(function() {
for ( i = 0, l = self.length; i < l; i++ ) {
if ( jQuery.contains( self[ i ], this ) ) {
return true;
}
}
});
}
var ret = this.pushStack( "", "find", selector ),
length, n, r;
for ( i = 0, l = this.length; i < l; i++ ) {
length = ret.length; length = ret.length;
jQuery.find( selector, this[i], ret ); jQuery.find( selector, this[i], ret );
if ( i > 0 ) { if ( i > 0 ) {
// Make sure that the results are unique // Make sure that the results are unique
for ( var n = length; n < ret.length; n++ ) { for ( n = length; n < ret.length; n++ ) {
for ( var r = 0; r < length; r++ ) { for ( r = 0; r < length; r++ ) {
if ( ret[r] === ret[n] ) { if ( ret[r] === ret[n] ) {
ret.splice(n--, 1); ret.splice(n--, 1);
break; break;
@ -68,6 +81,7 @@ jQuery.fn.extend({
closest: function( selectors, context ) { closest: function( selectors, context ) {
var ret = [], i, l, cur = this[0]; var ret = [], i, l, cur = this[0];
// Array
if ( jQuery.isArray( selectors ) ) { if ( jQuery.isArray( selectors ) ) {
var match, selector, var match, selector,
matches = {}, matches = {},
@ -77,8 +91,8 @@ jQuery.fn.extend({
for ( i = 0, l = selectors.length; i < l; i++ ) { for ( i = 0, l = selectors.length; i < l; i++ ) {
selector = selectors[i]; selector = selectors[i];
if ( !matches[selector] ) { if ( !matches[ selector ] ) {
matches[selector] = jQuery.expr.match.POS.test( selector ) ? matches[ selector ] = POS.test( selector ) ?
jQuery( selector, context || this.context ) : jQuery( selector, context || this.context ) :
selector; selector;
} }
@ -86,9 +100,9 @@ jQuery.fn.extend({
while ( cur && cur.ownerDocument && cur !== context ) { while ( cur && cur.ownerDocument && cur !== context ) {
for ( selector in matches ) { for ( selector in matches ) {
match = matches[selector]; match = matches[ selector ];
if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {
ret.push({ selector: selector, elem: cur, level: level }); ret.push({ selector: selector, elem: cur, level: level });
} }
} }
@ -101,8 +115,10 @@ jQuery.fn.extend({
return ret; return ret;
} }
var pos = POS.test( selectors ) ? // String
jQuery( selectors, context || this.context ) : null; var pos = POS.test( selectors ) || typeof selectors !== "string" ?
jQuery( selectors, context || this.context ) :
0;
for ( i = 0, l = this.length; i < l; i++ ) { for ( i = 0, l = this.length; i < l; i++ ) {
cur = this[i]; cur = this[i];
@ -121,7 +137,7 @@ jQuery.fn.extend({
} }
} }
ret = ret.length > 1 ? jQuery.unique(ret) : ret; ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
return this.pushStack( ret, "closest", selectors ); return this.pushStack( ret, "closest", selectors );
}, },

View file

@ -13,6 +13,30 @@ test("find(String)", function() {
same( jQuery("#main").find("> #foo > p").get(), q("sndp", "en", "sap"), "find child elements" ); same( jQuery("#main").find("> #foo > p").get(), q("sndp", "en", "sap"), "find child elements" );
}); });
test("find(node|jQuery object)", function() {
expect( 11 );
var $foo = jQuery('#foo'),
$blog = jQuery('.blogTest'),
$first = jQuery('#first'),
$two = $blog.add( $first ),
$fooTwo = $foo.add( $blog );
equals( $foo.find( $blog ).text(), 'Yahoo', 'Find with blog jQuery object' );
equals( $foo.find( $blog[0] ).text(), 'Yahoo', 'Find with blog node' );
equals( $foo.find( $first ).length, 0, '#first is not in #foo' );
equals( $foo.find( $first[0]).length, 0, '#first not in #foo (node)' );
ok( $foo.find( $two ).is('.blogTest'), 'Find returns only nodes within #foo' );
ok( $fooTwo.find( $blog ).is('.blogTest'), 'Blog is part of the collection, but also within foo' );
ok( $fooTwo.find( $blog[0] ).is('.blogTest'), 'Blog is part of the collection, but also within foo(node)' );
equals( $two.find( $foo ).length, 0, 'Foo is not in two elements' );
equals( $two.find( $foo[0] ).length, 0, 'Foo is not in two elements(node)' );
equals( $two.find( $first ).length, 0, 'first is in the collection and not within two' );
equals( $two.find( $first ).length, 0, 'first is in the collection and not within two(node)' );
});
test("is(String|undefined)", function() { test("is(String|undefined)", function() {
expect(27); expect(27);
ok( jQuery('#form').is('form'), 'Check for element: A form must be a form' ); ok( jQuery('#form').is('form'), 'Check for element: A form must be a form' );
@ -161,7 +185,7 @@ test("filter(jQuery)", function() {
}) })
test("closest()", function() { test("closest()", function() {
expect(11); expect(13);
same( jQuery("body").closest("body").get(), q("body"), "closest(body)" ); same( jQuery("body").closest("body").get(), q("body"), "closest(body)" );
same( jQuery("body").closest("html").get(), q("html"), "closest(html)" ); same( jQuery("body").closest("html").get(), q("html"), "closest(html)" );
same( jQuery("body").closest("div").get(), [], "closest(div)" ); same( jQuery("body").closest("div").get(), [], "closest(div)" );
@ -195,8 +219,29 @@ test("closest(Array)", function() {
same( jQuery("body").closest(["span","html"]), [{selector:"html", elem:document.documentElement, level:2}], "closest([body, html])" ); same( jQuery("body").closest(["span","html"]), [{selector:"html", elem:document.documentElement, level:2}], "closest([body, html])" );
}); });
<<<<<<< HEAD
test("not(Selector|undefined)", function() { test("not(Selector|undefined)", function() {
expect(11); expect(11);
=======
test("closest(jQuery)", function() {
expect(8);
var $child = jQuery("#nothiddendivchild"),
$parent = jQuery("#nothiddendiv"),
$main = jQuery("#main"),
$body = jQuery("body");
ok( $child.closest( $parent ).is('#nothiddendiv'), "closest( jQuery('#nothiddendiv') )" );
ok( $child.closest( $parent[0] ).is('#nothiddendiv'), "closest( jQuery('#nothiddendiv') ) :: node" );
ok( $child.closest( $child ).is('#nothiddendivchild'), "child is included" );
ok( $child.closest( $child[0] ).is('#nothiddendivchild'), "child is included :: node" );
equals( $child.closest( document.createElement('div') ).length, 0, "created element is not related" );
equals( $child.closest( $main ).length, 0, "Main not a parent of child" );
equals( $child.closest( $main[0] ).length, 0, "Main not a parent of child :: node" );
ok( $child.closest( $body.add($parent) ).is('#nothiddendiv'), "Closest ancestor retrieved." );
});
test("not(Selector)", function() {
expect(7);
>>>>>>> 1a167767305202797cf4c839eb64bd7adfb00182
equals( jQuery("#main > p#ap > a").not("#google").length, 2, "not('selector')" ); equals( jQuery("#main > p#ap > a").not("#google").length, 2, "not('selector')" );
same( jQuery("p").not(".result").get(), q("firstp", "ap", "sndp", "en", "sap", "first"), "not('.class')" ); same( jQuery("p").not(".result").get(), q("firstp", "ap", "sndp", "en", "sap", "first"), "not('.class')" );
same( jQuery("p").not("#ap, #sndp, .result").get(), q("firstp", "en", "sap", "first"), "not('selector, selector')" ); same( jQuery("p").not("#ap, #sndp, .result").get(), q("firstp", "en", "sap", "first"), "not('selector, selector')" );