Reputation: 21
I'm having troubles with my javascript code, I have a snippet that creates a number of button depending on the loop range, the buttons share the same class but the ids are different
<div class="panel-footer" id="loop">
<ul class="post-action">
{% for i in range %}
<button class="btn btn-success guess" id="{{ i }}" value="{{ i }}" onclick="transferField(this.value)">{{ i }} </button>
{% endfor %}
</ul>
</div>
I am trying to change the color of each button when it is clicked and when clicked again changes back to default color but its not working fine, when i click on button 5 it changes color but once i click on button 6, it wont change color until i click button 6 or click another button again. Here is the js code:
<script>
clicked = true;
$(".guess").click(function(){
xyz = this.id
console.log(xyz)
if(clicked){
$('#' + this.id).css('background-color', '#FF8E2B');
clicked = false;
} else {
$('#' + this.id).css('background-color', '#27AE60');
clicked = true;
}
});
</script>
What have i done wrong?
Upvotes: 0
Views: 3121
Reputation: 19202
What have i done wrong?
The main issue you have with your code is that you have one variable keeping track of the clicked state of multiple button elements.
The way to fix this is to add state to the element itself essentially giving multiple variables for multiple elements.
I'm doing this by adding an event
object to the callback of the click
handler and getting event.currentTarget
. The value of event.currentTarget
is the element object being clicked. You can add state to this object just like you'd add state to another other javascript object
event.currentTarget.clicked = true;
Now you can keep track of the state for each element!
// just some simple code to get your template in pure JS, don't worry about the code here
const range = [0,1,2,3,4,5];
const template = `<div class="panel-footer" id="loop">
<ul class="post-action">
${range.map(i => `
<button class="btn btn-success guess" id="${i}" value="${i}">${i}</button>
`)}
</ul>
</div>`;
const div = document.createElement('div');
div.innerHTML = template;
document.body.appendChild(div);
// here are where the changes start
// var clicked = true; instead of having a global variable to keep track of the state of all your buttons
$(".guess").click(function(event) {
// you need local state attached to the button
// here we're getting the button element being clicked
const currentTarget = event.currentTarget;
xyz = this.id
console.log(xyz);
// if clicked is truthy
if (currentTarget.clicked) {
$('#' + this.id).css('background-color', '#FF8E2B');
currentTarget.clicked = false;
} else {
$('#' + this.id).css('background-color', '#27AE60');
// set on the element some state
currentTarget.clicked = true;
}
});
.guess {
/* start out in the orange state */
background-color: #FF8E2B;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Upvotes: 0
Reputation: 1
You are trying to "track" the state of multiple buttons using a single var, of course this wont work
try the following instead
$(".guess").click(function(){
var $this = $(this);
var clicked = $this.data('clicked');
if(clicked) {
$this.css('background-color', '#FF8E2B');
} else {
$this.css('background-color', '#27AE60');
}
$this.data('clicked', !clicked);
});
Upvotes: 0
Reputation: 6923
Your problem is you are using clicked
as a global variable.
Just store clicked
in this
.
$(".guess").click(function(){
xyz = this.id
console.log(xyz)
if(this.clicked){
$(this).css('background-color', '#FF8E2B');
this.clicked = false;
} else {
$(this).css('background-color', '#27AE60');
this.clicked = true;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="panel-footer" id="loop">
<ul class="post-action">
<button class="btn btn-success guess" id="one" value="one" > one</button>
<button class="btn btn-success guess" id="two" value="two" > two</button>
<button class="btn btn-success guess" id="three" value="three" > three</button>
</ul>
</div>
Upvotes: 3
Reputation: 1
You can store an array of color for each element at data-*
of element, use .data()
, Array.prototype.reverse()
to toggle to array, set background
to element at index 0
of array
$("button").on("click", function() {
$(this).css("background", $(this).data().colors.reverse()[0])
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button data-colors='["#FF8E2B", "#27AE60"]' style="background:#FF8E2B">click</button>
Upvotes: 0