views:

359

answers:

1

Hi all,

I have a peculiar issue that I'm suspecting may just be normal behavior, but I need people to confirm. I'm hooking up live click events to a number of <li> elements by using this code:

$('li', $list).live("click", rightItemSingleClickEvent);

Note here that I am using a blanket selector here to hook up the same live click event to all <li> elements within $list, which is just an unordered list. I call this code once on $(document).ready(). rightItemSingleClickEvent() actually kills the live click event at the top of the method. This is because there is animation associated with the click, and I am killing it while the animation occurs so that duplicate clicks cannot occur. The code to kill the click is below:

$(this).die("click");

After the animation is complete, I reconnect the click event:

$notesArea.fadeIn(function() {
    $listItem.live("click", rightItemSingleClickEvent);
});

I should point out that all of this code seems to be working fine. I can choose a list item to click, and it's successfully killing and reconnecting each time (thereby preventing duplicate clicks during the animation). However, my problem is that when I think I'm killing only that single list item (<li>), it seems to be killing all of the list items, not just that one. So once I click one list item, while it's functionality continues to work (I'm still able to click), all of the others are not able to be clicked anymore. I'm wondering if this has to do with the fact that I'm connecting the live click event via a blanket statement that covers all <li>'s at once.

So maybe if I were to connect the live event to each <li> individually, instead of just doing them all using a single selector, it might work? I'm just not sure why calling die() on a single <li> is killing all of its siblings as well.

Any insight would be appreciated. Thanks.

CLARIFICATION: I've been asked to post a little more code for rightItemSingleClickEvent. This function essentially handles what happens when the user clicks a list item. I'm simulating a click and unclick by adding and removing css classes. And there's another textbox that gets shown on click and hidden on unclick. This is the animation that must complete before I reconnect the live click events. I should also point out that I'm using helper functions to kill and connect the click events, and handleNotes() is a function that stores the textbox text when the user unclicks, and does a couple other things that I don't think is related to this issue. However more confusing, my code is nonetheless posted below:

function rightItemSingleClickEvent(ev) {

var $target = $(ev.target); // what was clicked on the item
var $clickedItem = $('#' + $(this).attr('id'));

killItemClickEvents($(this)); // kill live click event to prevent extra clicks during animation

if ($target.is('a.ui-icon-circle-close')) { // if clicking remove icon, just remove the item

 removeItem($clickedItem, getLeftList());
}
else { // otherwise, handle click event

 if ($clickedItem.hasClass("ui-state-default")) { // UNCLICK BUTTON LOGIC (if button is clicked)

  handleNotes("hide", $clickedItem); // Hide notes box and store its contents in $(this)'s notes div
  $clickedItem.removeClass("ui-state-default").addClass("ui-state-active"); // unclick button
 }
 else { // CLICK BUTTON LOGIC (if button is unclicked)

  if ($clickedItem.siblings(".ui-state-default").attr('id') != undefined) { // if a button is already clicked
   // got some stuff to do with button that was already clicked
   var $prev_clickedButton = $clickedItem.siblings(".ui-state-default");

   handleNotes("store", $prev_clickedButton);

   // now unclick all buttons -- only one clickable at a time
   $prev_clickedButton.removeClass("ui-state-default").addClass("ui-state-active");

   handleNotes("toggle", $clickedItem);
  }
  else {
   handleNotes("show", $clickedItem); // Show notes box and populate it with $(this)'s notes
  }

  // then click the button that was clicked (by changing its css class)
  $clickedItem.removeClass("ui-state-active").removeClass("ui-state-hover").addClass("ui-state-default"); // click it
 }
}
}

UPDATE: Well I changed my code to connect a click event to each list item individually as it's written to HTML, and the same behavior still remains. I'm honestly just not sure what's happening. But even without a blanket live connect statement, killing the click event on one list item kills it on all of them. And there is only one place in all of my code that kills a live click event, and it's the one I posted above. So I'm at a total loss.

UPDATE 2: Because I was not able to get past this issue, I modified my code to instead check for ":animated" states, and abandoned the idea of killing and reconnecting live click events. However, I'd still be interested to know why kill() on one list item was killing them all, even if I had assigned live click events to each list item individually.

A: 

Your first problem is how you are assigning live events.

Live events currently only work when used against a selector.

Meaning this won't work correctly:

$('li', $list).live("click", rightItemSingleClickEvent);

but this would

$('#'+$list.attr('id')+' li').live("click", rightItemSingleClickEvent);

The reason that your die call kills the event on all the elements is because its bound on the parent element once. When you remove it you remove it for all of them. The main reason you use event delegation (.live()) is because you only bind one event rather then multiple.

PetersenDidIt
@petersendidit: I did always think that the selector I was using might not be right. I used your suggestion, but the same behavior remains. Thanks for the idea, though. I think your way is a better approach, regardless of my issue.
Mega Matt
Can you post more code. What does rightItemSingleClickEvent do?
PetersenDidIt
Also you really shouldn't be killing the event listener and then reconnecting it. On click just check if the current object is(':animated') and if not then do the rest if it is just return false;
PetersenDidIt
I looked into that method, and got nowhere. Doesn't :animated just return all elements that are currently being animated? How can I use that as a boolean check? I'm working on posting some clarification code in the meantime..
Mega Matt
if ($(this).is(':animated')) return false;
PetersenDidIt
Updated my answer with information about why die doesn't do what you think it should
PetersenDidIt