The problem is event propagation, prevent it
$('li:has(ul)').click(function (e) {
$(this).children('ul').addClass('thisOne').toggle();
});
$('li').click(function (e) {
e.stopPropagation();
});
Demo: Fiddle
Question
I have a 'tree' of information that's displayed in many nested lists (ul li ul li ....). Two problems:
<li>
, the parent ul is toggled as well as the child.<li>
in a nested list that does not have a ul in it (say, Blue under Cranberry below) the parent ul is toggle, even though this shouldn't be matching 'li.has(ul)'.I've tried various JQuery selectors, next(ul), children().first(), etc with the same results. No luck - though I'm sure I'm just missing something simple here.
On JSFiddle.
$('li.has(ul)').click(function() {
$(this).children('ul').toggle();
});
And the html:
<ul class="unstyled" id="full_ontology">
<li>Apple</li>
<li>Banana</li>
<li>Cranberry
<ul>
<li>Blue</li>
<li>Red
<ul>
<li>Round</li>
<li>Square</li>
<li>Circular</li>
</ul>
</li>
<li>Purple</li>
</ul>
</li>
<li>Date</li>
<li>Elderberry
<ul>
<li>Yellow</li>
<li>Pink</li>
<li>Black</li>
</ul>
</li>
<li>Fig</li>
</ul>
La solution
The problem is event propagation, prevent it
$('li:has(ul)').click(function (e) {
$(this).children('ul').addClass('thisOne').toggle();
});
$('li').click(function (e) {
e.stopPropagation();
});
Demo: Fiddle
Autres conseils
It's all about propagation.
Here is the working JavaScript:
$('li').click(function(e) {
if ($(this).has('ul')) {
$(this).children('ul').addClass('thisOne').toggle();
}
e.stopPropagation();
});
JSFiddle: http://jsfiddle.net/zkFGU/3/
Basically, first you want this event on all of the list items, not just the ones that have the ul. The reason is because if you don't, you can't stop propagation. For example, "Blue" under "Cranberry" has no list, so it wouldn't call the event. However, because "Blue" is actually in Cranberry, which is a list item and does trigger the event, clicking Blue counts as clicking Cranberry, so Cranberry retracts. By giving Blue a change to chance to stop propagation, it prevents Cranberry from erroneously collapsing.
The other part of stopping propagation is simply to stop parents. We want only the element we directly clicked on (which is triggered first) and no other element to (attempt) to toggle.