In the first case you are selecting the list elements that are siblings as long as those list elements have unordered lists as children, then you get the unordered list children. In the second case you are looking for siblings that are unordered lists that are children (immediate or nested) of list elements. The problem is that you are looking in the siblings of a list element which has no unordered list siblings (only list element siblings).
The key is that the selector in the siblings method is a filter. It is only used to select out of the list of unique siblings, those siblings that match the criteria specified in the selector. In your case, there aren't any siblings that do (can) match the criteria in the second case.
Example:
<ul>
<li id='li0' class='selected'>
<ul id='ul0' class='child'>
...
</ul>
</li>
<li id='li1' class='sibling'>
<ul id='ul1' class='child'>
...
</ul>
</li>
<li id='li2' class='sibling'>
<ul id='ul2' class='child'>
<li id='li2_0' class='grandchild'>
<ul id='ul2_0' class='greatgrandchild'>
...
</ul>
</li>
</ul>
</li>
<li id='li3'>
</li>
</ul>
$('.selected').siblings('li:has(ul)')
will return the collection of list elements with ids li1
and li2
. $('.selected').siblings('li:has(ul) ul') will return an empty set because it is the same as
$('.selected').siblings().filter('li:has(ul) ul'). Since siblings returns the set with ids li1' and
li2`, these don't match the filter which selects the unordered list children of a list element (with unordered list children).
You can see the effect using the following snippet of code.
$(function() {
dumpIds('siblings',$('.selected').siblings());
dumpIds('filtered sibs',$('.selected').siblings('li:has(ul)'));
dumpIds('ul filtered sibs',$('.selected').siblings('li:has(ul) ul'));
});
function dumpIds(title,elements) {
var idset = '';
var sep = '';
elements.each( function() {
idset = idset + sep + this.id;
sep = ', ';
});
alert(title + ':' + idset);
}