When used with the child selector >
, the two variants of jQuery's "has" behave differently.
Take this HTML:
<div>
<span>Text</span>
</div>
Now:
$("div:has(>span)");
would return it, while:
$("div").has(">span");
would not. Is it a bug or a feature? Compare here: http://jsfiddle.net/aC9dP/
EDIT: This may be a bug or at least undocumented inconsistent behavior.
Anyway, I think it would be beneficial to have the child selector consistently work as an unary operator. It enables you to do something that otherwise would require a custom filter function — it lets you directly select elements that have certain children:
$("ul:has(>li.active)").show(); // works
$("ul").has(">li.active)").show(); // doesn't work, but IMHO it should
as opposed to:
$("ul").filter(function () {
return $(this).children("li.active").length > 0;
}).show();
I've opened a jQuery ticket (7205) for this.
This happens because the sizzle selector is looking at all Div's that have span children in the :has example. But in the .has example, it's passing all DIV's to the .has(), which then looks for something that shouldn't be a stand-alone selection. ("Has children of nothing").
Basically, :has() is part of the selection, but .has() gets passed those divs and then re-selects from them.
Ideally, you don't use selectors like this. The > being in the selector is probably a bug, as it's semantically awkward. Note: the child operator isn't meant to be stand-alone.
I'm always talking about v1.4.2 of jquery development release.
Description: Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element.
Code:
var targets = jQuery( target );
return this.filter(function() {
for ( var i = 0, l = targets.length; i < l; i++ ) {
if ( jQuery.contains( this, targets[i] ) ) { //Calls line 3642
return true;
}
}
});
Line 3642 relates to a 2008 plugin compareDocumentPosition, but the important bit here is that we're now basically just running two jquery queries here, where the first one selects $("DIV")
and the next one selects $(">span")
(which returns null), then we check for children.
Description: Selects elements which contain at least one element that matches the specified selector.
Code:
return !!Sizzle( match[3], elem ).length;
They are two differnt tools, the :has uses sizzle 100%, and .has uses targets passed to it.
Note: if you think this is a bug, go fill out the bug ticket.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With