Michael De Keyser
Michael De Keyser

Reputation: 797

Add a click event to list items in a tree of lists

I have a tree of lists in Html such as this:

<ul class="myTree">
    <li class="treeItem">Category 1
        <ul>
            <li class="treeItem">Subcategory 1 1</li>
            <li class="treeItem">Subcategory 1 2
                <ul>
                    <li class="plus"><input type="text" value="Add a product"/></li>
                </ul>
            </li>
        </ul>
    </li>
    <li class="treeItem">Category 2
        <ul>
            <li class="treeItem">Subcategory 1 1</li>
            <li class="treeItem">Subcategory 1 2
                <ul>
                    <li class="plus"><input type="text" value="Add a product"/></li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

So as you can see, it's a kinda elaborated list.

Now what I need is a click event on those "treeItem" class elements that would retrieve the corresponding name (Category 1, Subcategory 1 1, etc).

I came up with this:

$(".myTree").on("click", ".treeItem", function() {
    var categoryName = $(this).text();
    alert(categoryName);
});

The only problem I'm facing right now is that first of all, categoryName contains

Category 2

                Subcategory 1 1
                Subcategory 1 2

when I click on a "level 1" <li> (such as Category 1). I could bypass this by adding some catname attribute to my <li>'s but most importantly, when I click on a "level 2" <li> (such as Subcategory 1 1), it first triggers click event on level 2 <li>, does the stuff and then fires a new click event on level 1 <li>...

It's quite obvious why it does that, but I need a way around to have it only happen once in the highest level (when I click on "Subcategory 1 1", it should NOT fire an event on "Category 1").

It's also worth noting that this tree will be generated automatically, which means I could label my treeItem's with some other class such as "level1" or something like that but if I could avoid that, I'd love it.

... Alright this question might need a summary as I felt I kinda lost myself in it...

  1. I need a click event on a tree of lists
  2. I need that click event to only be fired at the highest level (the deepest).
  3. Adding some class names is possible but would like to be avoided.

Thank you!

Upvotes: 1

Views: 2704

Answers (2)

Rory McCrossan
Rory McCrossan

Reputation: 337580

First of all you need to use event.stopPropagation to stop the event bubbling up the DOM and repeating itself. Then you need to get the first text node within the li. Try this:

$(".myTree").on("click", ".treeItem", function(e) {
    e.stopPropagation();
    var categoryName = $(this).contents().filter(function() {
        return !!$.trim(this.innerHTML||this.data);
    }).first().text();
    alert(categoryName);
});

Example fiddle

Upvotes: 3

Jamie Dixon
Jamie Dixon

Reputation: 53989

You need to use event.stopPropagation() on the event.

$(".myTree").on("click", ".treeItem", function(event) {
    var categoryName = $(this).text();
    alert(categoryName);
    event.stopPropagation()
});

Upvotes: 0

Related Questions