Single jQuery function to manipulate elements with the same ".class" independently - javascript

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 + "%");
}
});
});

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 + "%");
}
});
});
DEMO
Note: this answer upon to your request .. you will need to work on it a little bit to reach a style you want

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.

Related

What is the error when im trying to add image?

The output should be that every time that there is an opponent's player around the click, he becomes the player who is currently pressed. The code I sent is a check for the row above and chanching its image. The problem is that every time it comes to adding the image, it writes a red line underneath and nothing happens. What is the reason for this?
function Eating_Action(idClicked, rowClicked, colClicked) {
IDRup = (rowClicked - 1) * BoardSize + colClicked;
IDRdown = (rowClicked + 1) * BoardSize + colClicked
IDCright = rowClicked * BoardSize + (colClicked + 1);
IDCleft = Number(rowClicked) * Number(BoardSize) + (Number(colClicked) - 1);
IDDleftdown = Number(First1Clicked) + Number(Number(BoardSize) - 1);
IDDleftup = (rowClicked - 1) * BoardSize + (colClicked - 1);
IDDrightdown = Number(First1Clicked) + Number(Number(BoardSize) + 1);
IDDrightup = (First1Clicked) - (BoardSize - 1);
//check all the pieces around the place that was clicked and change it to
if (intBoard[rowClicked][colClicked] == 1) {
//check eating for UP ROW
if (rowClicked - 1 >= 0) {
if (intBoard[rowClicked - 1][colClicked] == 2) {
document.getElementById(IDRup).innerHTML = "<img width='50px' height='50px' src='O.png'/>";
intBoard[rowClicked - 1][colClicked] = 1;
}
}

How can I rewrite innerHTML everytime function is called javascript

function he() {
var x = Math.floor((Math.random() * 100) + 1);
document.getElementById("res1").innerHTML = "Heroes have dealt " + x + " damage on villains.";
var vhp = villains - x;
document.getElementById("res2").innerHTML = "<br/>Villains have " + vhp + " hp left.";
vok();
}
function vok() {
var y = Math.floor((Math.random() * 100) + 1);
document.getElementById("res3").innerHTML = "<br/>Villains have dealt " + y + " damage on Heroes.";
var hhp = hero - y;
document.getElementById("res4").innerHTML = "<br/>Heroes have " + hhp + " hp left.";
he();
}
Here is the above code I made function he() is called when a button is clicked and vok function is called after execution of he() function but it's not going good currently i want to overwrite the innerHTML every time the function is runned how am I supposed to do so?

Javascript move down scrollbar using element not working

Hey all I have the html code below that should allow the page to scroll all the way down to the nextChatHolder element when you push the button.
It adds the chat bubble just fine at the bottom but I want it to scroll down to the nextChatHolder each time I press the button.
I have no errors and these examples work standalone. So naturally there somewhere in my javascript or css that is causing it not to scroll - and I am unable to find what that it!
Visual: https://jsbin.com/xihosicayo/edit?js,output
function getElementY(query) {
return window.pageYOffset + document.querySelector(query).getBoundingClientRect().top;
}
function scrollToItem(item) {
var diff = (item.offsetTop-window.scrollY)/8;
if (Math.abs(diff) > 1) {
window.scrollTo(0, (window.scrollY+diff));
clearTimeout(window._TO);
window._TO=setTimeout(scrollToItem, 30, item);
} else {
window.scrollTo(0, item.offsetTop);
}
}
function doScrolling(element, duration) {
var startingY = window.pageYOffset
var elementY = getElementY(element)
var targetY = document.body.scrollHeight - elementY < window.innerHeight ? document.body.scrollHeight - window.innerHeight : elementY
var diff = targetY - startingY
var easing = function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1; }
var start;
if (!diff) return
window.requestAnimationFrame(function step(timestamp) {
if (!start) start = timestamp;
var time = timestamp - start;
var percent = Math.min(time / duration, 1);
percent = easing(percent);
window.scrollTo(0, startingY + diff * percent);
if (time < duration) {
window.requestAnimationFrame(step);
}
})
}
function newTalk(textVal, pic) {
var my_elem = document.getElementById("nextChatHolder");
var div = document.createElement('div');
div.innerHTML = '<div class="animated animatedFadeInUp fadeInUp">' +
'<div class="chat self">' +
'<div class="user-photo">' +
'<img src="' + pic + '">' +
'</div>' +
'<p class="chat-message">' + textVal + '</p>' +
'<span class="timeself">11:01 PM | Oct 11 2019</span>' +
'</div>' +
'</div>';
my_elem.parentNode.insertBefore(div, my_elem);
//scrollToItem(my_elem))
}
I believe you're looking for:
my_elem.scrollIntoView({behavior: "smooth",block: "end"})
as the last line in newTalk.
Documentation

.append not working on click

Simple button that should be creating new <p> elements when its clicked but it isn't working and I'm not sure why as I've compared it to other code of mine.
Demo
var battle = function() {
while(monsterHP > 0){
var playerDam = Math.floor(Math.random() * ((playerAtk - monsterAtk) + 2);
$('#battle').append("<p>You have hit the monster for " + playerDam + " damage. The monster has " + (monsterHP - playerDam) + "HP left</p>");
monsterHP -= playerDam;
if(monsterHP <= 0) {
$('#battle').append("<p>You have defeated the monster</p>");
}
}
}
$('#battleButton').click(function() {
battle();
}
You have many syntax errors in your code. If you correct them (as below), then it works fine. When you write a JQuery append, you need to put a ')' after your argument. Likewise, functions need to have a '}' after them.
var playerAtk = 5;
var playerDef = 5;
var playerHP = 10;
var monsterAtk = 4;
var monsterDef = 4;
var monsterHP = 8;
var battle = function() {
while(monsterHP > 0){
var playerDam = Math.floor(Math.random() * ((playerAtk - monsterAtk) + 2));
$('#battle').append("<p>You have hit the monster for " + playerDam + " damage. The monster has " + (monsterHP - playerDam) + "HP left</p>");
monsterHP -= playerDam;
if(monsterHP <= 0) {
$('#battle').append("<p>You have defeated the monster</p>");
}
}
}
$('#battleButton').click(function() {
battle();
});

JS Calculate total on change

I Have this script that calculates the total of some values as the user selects them from dropdowns. Im no expert with JS. Additionally to onchange I would like this code to calculate the value on page load? I would assume it is some copy and paste of this code with an alteration on the function and an if statement?
<script>
$(function() {
$(".DropChange").change(function(){
var valone = $('#ValOne').val();
var valtwo = $('#ValTwo').val();
var valthree = $('#ValThree').val();
var valfour = $('#ValFour').val();
var valfive = $('#ValFive').val();
var valsix = $('#ValSix').val();
var valseven = $('#ValSeven').val();
var valeight = $('#ValEight').val();
var total = ((valone * 1) + (valtwo * 1) + (valthree * 1) + (valfour * 1) + (valfive * 1) + (valsix * 1) + (valseven * 1) + (valeight * 1));
$('#Total').text(total);
});
});
</script>
Probably your simplest option is to stick the current onchange function into another function.
var calculateTotals = function(){
var valone = $('#ValOne').val();
var valtwo = $('#ValTwo').val();
var valthree = $('#ValThree').val();
var valfour = $('#ValFour').val();
var valfive = $('#ValFive').val();
var valsix = $('#ValSix').val();
var valseven = $('#ValSeven').val();
var valeight = $('#ValEight').val();
var total = ((valone * 1) + (valtwo * 1) + (valthree * 1) + (valfour * 1) + (valfive * 1) + (valsix * 1) + (valseven * 1) + (valeight * 1));
$('#Total').text(total);
};
Then change your onchange to
$(".DropChange").change(calculateTotals);
So your $(function(){ ... }); now looks like;
$(function(){
$(".DropChange").change(calculateTotals); // assign event
calculateTotals(); // calculate totals on load
});
Here is what you need:
<script>
(function() {
$(document).ready(function(){
showSum();
});
$(".DropChange").change(function(){
showSum();
}
function showSum(){
var valone = $('#ValOne').val();
var valtwo = $('#ValTwo').val();
var valthree = $('#ValThree').val();
var valfour = $('#ValFour').val();
var valfive = $('#ValFive').val();
var valsix = $('#ValSix').val();
var valseven = $('#ValSeven').val();
var valeight = $('#ValEight').val();
var total = ((valone * 1) + (valtwo * 1) + (valthree * 1) + (valfour * 1) + (valfive * 1) + (valsix * 1) + (valseven * 1) + (valeight * 1));
$('#Total').text(total);
}
}());
</script>

Categories