开发者

Help with jQuery issue

开发者 https://www.devze.com 2023-01-01 19:34 出处:网络
I have a simple page with a list of items. I am allowing users to vote on these items, but I only want to allow the user to vote once per. item.

I have a simple page with a list of items. I am allowing users to vote on these items, but I only want to allow the user to vote once per. item.

I made a jQuery script that adds a class to the items the user has voted on:

if(!$(this).find(".item span").hasClass("voted")) {
  $(".item").hover(function() {
    $(this).find(".ratingbar").hide();
    $(this).find(".votebar").show();
  }, function() {
    $(this).find(".votebar").hide();
    $(this).find(".ratingbar").show();
  });
};

This is the script that prevents the user from voting again on the same item.

$(".votebutton").click(function() {
  $("div#"+offerid).find(".item").addClass("开发者_JAVA技巧voted");
});

This isn't working. When hovering an item, the hover function still runs even though the second script successfully added the class "voted" to the html.

Why can this be?


You need to use .live() (or .delegate()) to prevent this, since .hover() attaches to the DOM element, the fact that it's class changes doesn't unbind those mousenter and mouseleave event handlers (this is what hover actually binds to).

However, .live() evaluates if the class matches when you hover (because it works off event bubbling, so it checks if the selector matches before executing), and will do what you want, like this:

$(".item:not(.voted)").live('mouseenter', function() {
  $(this).find(".ratingbar").hide();
  $(this).find(".votebar").show();
}).live('mouseleave', function() {
  $(this).find(".votebar").hide();
  $(this).find(".ratingbar").show();
});

There's no reason to do the if statement, this will work for all elements and you should only run it once. Previously it was checking if the current item had the voted class...but then applying the hover to all .item (n number of times) elements for each one that didn't have the class...instead run this just once outside whatever loop you're in now, it should be directly in a document.ready handler.

Edit: You can shorten this as well since you're just toggling the elements around, using .toggle(), it's the same effect, just a bit simpler/more concise:

$(".item:not(.voted)").live('mouseenter mouseleave', function() {
  $(".ratingbar, .votebar", this).toggle();
});


You are adding the class voted later in the code, but your .hover() bound the events mouseenter and mouseleave to the .item already.

If you want your stop your event handler from continuing on if the element has the voted class, you can check for the class and return early from the event handler:

$(".item").hover(function() {
  // save this variable so we don't need to call $() three times
  var $this = $(this);
  // stop processing the event if the item has the 'voted' class
  if ($this.is('.voted')) return; 

  $this.find(".ratingbar").hide();
  $this.find(".votebar").show();
}, function() {
  var $this = $(this);
  // note - you might still want to process this event as they mouse out after voting?
  if ($this.is('.voted')) return; 

  $this.find(".votebar").hide();
  $this.find(".ratingbar").show();
});

Or after voting you can remove the event handlers:

$(".votebutton").click(function() {
  $("div#"+offerid).find(".item").addClass("voted").unbind('mouseenter mouseleave');
});
0

精彩评论

暂无评论...
验证码 换一张
取 消