hookedonwinter
hookedonwinter

Reputation: 12666

jQuery click on li with nested ul

I have a list within lists. When a user clicks on a list item (<li>), I want the nested <ul> to show up. Before I started adding the nested lists, I just had it where clicking a list item would run a function. Now, clicking any of the nested lists also runs that function. Which makes sense, since they're part of the list item.

Besides wrapping a <span> around the first part of the list item and running the function on that, is there a selector that will let me run something on the parent <li> but not any of its children, specifically not the child lists and list items?

HTML:

<ul class="buckets">        
    <li class="bucket">
        <img src="arrow_group_collapsed_true.png" class="arrow">
        <img src="blue_folder.png" class="folder">
        View all
    </li>

    <li class="bucket">
        <img src="arrow_group_collapsed_false.png" class="arrow">
        <img src="blue_folder.png" class="folder">
        Groups
        <ul style="display: block;">
            <li id="group_id_15036" class="group_bucket">
                <img src="arrow_group_collapsed_true.png" class="arrow">
                <img src="blue_folder.png" class="folder">
                Group 1
            </li>
            <li id="group_id_14910" class="group_bucket">
                <img src="arrow_group_collapsed_true.png" class="arrow">
                <img src="blue_folder.png" class="folder">
                Group 2
            </li>
        </ul>
    </li>
</ul>

Javascript (not much of it, I can show more if needed):

$( 'li.bucket' ).live( 'click',
    function()
    {
        // do stuff
    })

I want a click on "Groups" or "View All" to run the click function, but a click on "Group 1" or "Group 2" should not.

Upvotes: 3

Views: 10512

Answers (3)

Jonathan Park
Jonathan Park

Reputation: 775

I like @MvanGeest's solution but there is a better way by understanding the event propagation. When an element is clicked the contained elements get the event first and trickle up through the tree. If I understand your request you would like to prevent the contained ul sending events up the tree. I think here a visual is best.

<ul>
  <li></li>
  <li onclick="ShowChildUL()">
    <ul onclick="function(event) { event.stopPropagation() }">
      <li onclick="DoSomethingFun()"></li>
      <li></li>
      </ul>
  </li>
</ul>

In this case you will see that the onclick on the ul in the middle will stop propagation up to the li. Also event.stopPropagation() is not cross browser. I recommend this method as your onclick function.

function StopPropagation(e) {
  var event = e || window.event;

  [body of event handler function goes here]

  if (event.stopPropagation) {
    event.stopPropagation();
  } else {
    event.cancelBubble = true;
  } 
}

Upvotes: 1

loxxy
loxxy

Reputation: 13151

you can control the above function onmouseover the list item & remove it onmouseout event of the item. But I don't know about how efficient it would be against other ways though.

Upvotes: 2

MvanGeest
MvanGeest

Reputation: 9661

There's an official way, but in your case, it might be rather expensive:

$('li.bucket *').live('click', function(event) { event.stopPropagation() });

The li's children will now have a handler that stops the event from propagating upwards and triggering the li's handler. Please try it and see if the application isn't slowed down too much.

Upvotes: 11

Related Questions