سؤال

I have a 'tree' of information that's displayed in many nested lists (ul li ul li ....). Two problems:

  1. When I click a <li>, the parent ul is toggled as well as the child.
  2. If I click on an <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>
هل كانت مفيدة؟

المحلول

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

نصائح أخرى

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top