Reputation: 45
I want to duplicate the "voting-bar-container" div that carries jQuery functionality with it. However, because each duplicate carries with it the same ".classes" (and my jQuery Selectors target those classes), the jQuery is executed on each duplicate regardless of which "voting-bar-container" div is being interacted with.
I want the jQuery events to be executed ONLY on the elements being interacted with.
I believe the answer lies in my choice of Selectors as I know I don't need to duplicate my jQuery code for each duplicate HTML element with different "ID's".
https://jsfiddle.net/STEEZENS/aqd87b2d/
OR
Here is my HTML & jQuery:
<div class="voting-bar-container">
<button class="upvote">
<span class="upvote-counter">0</span>
</button>
<div class="vote-meter">
<div class="upvotes"></div>
<div class="downvotes"></div>
</div>
<button class="downvote">
<span class="downvote-counter">0</span>
</button>
</div>
jQuery:
$(document).ready(function () {
var $downvoteCount = 0;
var $upvoteCount = 0;
$(".upvote").click(function () {
$upvoteCount++;
$(".upvote-counter").text(" " + $upvoteCount);
var $totalVoteCount = $upvoteCount + $downvoteCount;
var $upvoteProportion = Math.round(($upvoteCount / $totalVoteCount) * 100);
var $downvoteProportion = Math.round(($downvoteCount / $totalVoteCount) * 100);
if (($upvoteProportion + $downvoteProportion) > 100) {
$(".upvotes").width(($upvoteProportion - 0.5) + "%");
$(".downvotes").width(($downvoteProportion - 0.5) + "%");
} else {
$(".upvotes").width($upvoteProportion + "%");
$(".downvotes").width($downvoteProportion + "%");
}
});
$(".downvote").click(function () {
$downvoteCount++;
$(".downvote-counter").text(" " + $downvoteCount);
var $totalVoteCount = $upvoteCount + $downvoteCount;
var $upvoteProportion = Math.round(($upvoteCount / $totalVoteCount) * 100);
var $downvoteProportion = Math.round(($downvoteCount / $totalVoteCount) * 100);
if (($upvoteProportion + $downvoteProportion) > 100) {
$(".upvotes").width(($upvoteProportion - 0.5) + "%");
$(".downvotes").width(($downvoteProportion - 0.5) + "%");
} else {
$(".upvotes").width($upvoteProportion + "%");
$(".downvotes").width($downvoteProportion + "%");
}
});
});
Upvotes: 1
Views: 211
Reputation: 24001
you need to use $(this)
$(this).find(".upvote-counter")
instead of
$(".upvote-counter")
while you asked for (*What I want is for the jQuery events to be executed ONLY on the elements being interacted with) .. your code should be something like this .. you will need to use .closest() as well >> to get the downvote div related with the upvote div and reverse
$(document).ready(function () {
var $downvoteCount = 0;
var $upvoteCount = 0;
$(".upvote").click(function () {
$upvoteCount++;
$(this).find(".upvote-counter").text(" " + $upvoteCount);
var $totalVoteCount = $upvoteCount + $downvoteCount;
var $upvoteProportion = Math.round(($upvoteCount / $totalVoteCount) * 100);
var $downvoteProportion = Math.round(($downvoteCount / $totalVoteCount) * 100);
if (($upvoteProportion + $downvoteProportion) > 100) {
$(this).width(($upvoteProportion - 0.5) + "%");
$(this).closest('voting-bar-container').find(".downvotes").width(($downvoteProportion - 0.5) + "%");
} else {
$(this).width($upvoteProportion + "%");
$(this).closest('voting-bar-container').width($downvoteProportion + "%");
}
});
$(".downvote").click(function () {
$downvoteCount++;
$(this).find(".downvote-counter").text(" " + $downvoteCount);
var $totalVoteCount = $upvoteCount + $downvoteCount;
var $upvoteProportion = Math.round(($upvoteCount / $totalVoteCount) * 100);
var $downvoteProportion = Math.round(($downvoteCount / $totalVoteCount) * 100);
if (($upvoteProportion + $downvoteProportion) > 100) {
$(this).closest('voting-bar-container').find(".upvotes").width(($upvoteProportion - 0.5) + "%");
$(this).width(($downvoteProportion - 0.5) + "%");
} else {
$(this).closest('voting-bar-container').find(".upvotes").width($upvoteProportion + "%");
$(this).width($downvoteProportion + "%");
}
});
});
Note: this answer upon to your request .. you will need to work on it a little bit to reach a style you want
Upvotes: 5
Reputation: 50787
You need to be traversing the DOM to find the elements in question relative to the element that was clicked, instead of globally.
First, as you have multiple elements that have upvotes associated with them, the value of this and it's iteration needs to occur based on the existing upvote value of the element that is closest to upvote. Please observe below:
$(".upvote").click(function () {
var upvote_counter = $(this).find('span'),
downvote_counter = $(this).parent().find('.downvote-counter'),
upvotes = $(this).parent().find('.upvotes'),
downvotes = $(this).parent().find('.downvotes'),
$upvoteCount = upvote_counter.text(),
$downvoteCount = downvote_counter.text();
$upvoteCount++;
upvote_counter.text($upvoteCount);
var $totalVoteCount = $upvoteCount + $downvoteCount;
var $upvoteProportion = Math.round(($upvoteCount / $totalVoteCount) * 100);
var $downvoteProportion = Math.round(($downvoteCount / $totalVoteCount) * 100);
if (($upvoteProportion + $downvoteProportion) > 100) {
upvotes.width(($upvoteProportion - 0.5) + "%");
downvotes..width(($downvoteProportion - 0.5) + "%");
} else {
upvotes.width($upvoteProportion + "%");
downvotes.width($downvoteProportion + "%");
}
});
This will allow you to properly select the elements that are closest associated with the upvote
element that is clicked. Do something similar for the downvote function.
Upvotes: 1