2010-05-30 3 views
0

J'ai une page simple avec une liste d'articles. Je permets aux utilisateurs de voter sur ces éléments, mais je veux seulement permettre à l'utilisateur de voter une fois par. article.Aide avec jQuery question

J'ai fait un script jQuery qui ajoute une classe aux éléments que l'utilisateur a voté sur:

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(); 
    }); 
}; 

Ceci est le script qui empêche l'utilisateur de voter à nouveau sur le même article.

$(".votebutton").click(function() { 
    $("div#"+offerid).find(".item").addClass("voted"); 
}); 

Cela ne fonctionne pas. Lors du survol d'un élément, la fonction hover continue à s'exécuter même si le second script a ajouté avec succès la classe "voté" au html.

Pourquoi cela peut-il être?

Répondre

7

Vous devez utiliser .live() (ou .delegate()) pour éviter cela, car .hover() attache à l'élément DOM, le fait que ce sont des changements de classe ne délie pas les mousenter et mouseleave gestionnaires d'événements (ce qui est ce vol stationnaire se fixe en fait) .

Cependant, .live() évalue si les matches de classe lorsque vous survolez (car il fonctionne de bouillonnement d'événement, il vérifie si correspond à la sélection avant d'exécuter), et ferez ce que vous voulez, comme ceci:

$(".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(); 
}); 

Il n'y a aucune raison de faire l'instruction if, cela fonctionnera pour tous les éléments et vous ne devriez l'exécuter qu'une seule fois. Précédemment, il vérifiait si l'élément actuel avait la classe voted ... mais appliquait ensuite le pointeur à tous les éléments .item (n nombre de fois) pour chacun des éléments qui n'avaient pas la classe ... au lieu de cela, exécutez cette opération une seule fois En dehors de la boucle dans laquelle vous vous trouvez, elle devrait être directement dans un gestionnaire document.ready.

Edit: Vous pouvez raccourcir ce aussi bien puisque vous êtes juste basculer les éléments autour, en utilisant .toggle(), il est le même effet, juste un peu plus simple/plus concise:

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

Merci beaucoup! Après la mise à niveau vers jQuery 1.4, cela a fonctionné parfaitement :-) –

1

Vous ajoutez la classe voted plus tard dans le code, mais votre .hover() lié les événements mouseenter et mouseleave au .item déjà.

Si vous voulez que votre arrêt de votre gestionnaire d'événements de continuer sur si l'élément a la classe voted, vous pouvez vérifier la classe et revenir au début du gestionnaire d'événements:

$(".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(); 
}); 

Ou après avoir voté peut supprimer les gestionnaires d'événements: