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');
});
精彩评论