I have a toggle switch and a button on a page. I also have a variable called "count". My goal is for "count" to record the number of times the button is pressed but ONLY when the toggle switch is ON.
Here's my code
var count = 0;
btnReset.addEventListener("click",
function(count) {
if (toggle.checked == true) {
count += 1;
document.getElementById('count').innerHTML=count;
}
});
Problem is, it's returning "[object MouseEvent]1" rather than the value of "count".
How do I get it to return var count (i.e. # of clicks when toggle is on)?
Thanks in advance.
Your issue is that an event listener receives the Event object. For some reason, you put count there and hoped it would be that?
Here is the right way to do it:
let count = 0;
const toggle = document.querySelector('#chkToggle');
const btn = document.querySelector('#btnCount');
const output = document.querySelector('.count');
btn.addEventListener("click", function(evt) {
if (toggle.checked == true) {
count++;
output.innerHTML = count;
}
});
Enabled: <input type="checkbox" id="chkToggle"><br>
<button type="button" id="btnCount">Count</button>
<div class="count">0</div>
Related
I have a little problem that I replicated in the little code snippet below (in the most simple way possible, however it still shows the problem I am facing).
Here is the snippet :
const searchBar = document.getElementById('search');
const resBox = document.getElementById('results');
searchBar.addEventListener('input', function handler(e) {
if (e.target.value === '') {
resBox.innerHTML = '';
return false;
}
setTimeout(() => populate(e), 300);
});
function populate(e) {
const btnBox = document.createElement('div');
for (let i = 1; i <= 3; i++) {
const btn = document.createElement('button');
btn.classList.add('js-click')
btn.innerText = 'Click me';
btnBox.appendChild(btn);
}
resBox.appendChild(btnBox);
dynamicBtnClickListener();
}
function dynamicBtnClickListener() {
resBox.addEventListener('click', function handler(e) {
console.log('You clicked me !');
});
// THE SOLUTION I FOUND FOR THE MOMENT :
//const btns = document.querySelectorAll('button.js-click');
//btns.forEach(btn => {
// btn.addEventListener('click', function handler(e) {
// console.log('You clicked me !');
// });
//});
}
<input type="text" id="search">
<div id="results"></div>
As you can see in the snippet, I have a first listener on input that generates a list of buttons when you type in it. When it is empty, the buttons disappear. In my real world case, it is a search input, that when a user types in, calls a function that populates a result box below it with results from DB.
I then have an on click listener on the buttons. In the code snippet, I simply put a console('You clicked me') when you click on the buttons. In my real app, it takes the result item (each result is an user) and inserts it in a table.
The problem appears when you open, close, then re-open the results box. This is done by inputing something, clearing the input, then re-input something. When you do that and then click on one of the buttons, it fires the click event on them as many times as you opened / closed the result box, so you will see the "You clicked me" on console multiple times.
I have done some research and most of it calls for using event.stopPropagation() and / or removing the event listener(s). I did try all these possible solutions, in every way I could think of, but I couldn't make it work.
Anyways I found a way around this (the commented portion of the dynamicBtnClickListener() function), but I feel it is not optimal. It consists of getting all the buttons with querySelectorAll(), then loop through them and add the click listener to every one of them, but I do not think it is optimal nor best-practice like. This is why I come here to ask if maybe there is a better solution, possibly one that keeps the click listener on the results box (if that is the most optimal solution. Is it by the way ?).
So even though I found a solution to this problem, could someone please tell me what is the best practice and optimal way of doing this ?
Thank you very much for your help
Each time the you type in the text area, resBox is accessed each time and the actual element resBox gets a new event listener every time(the buttons don't have any specific listener themselves, so I make EACH BUTTON have a specific listener individually)
const searchBar = document.getElementById('search');
const resBox = document.getElementById('results');
searchBar.addEventListener('input', function handler(e) {
if (e.target.value === '') {
resBox.innerHTML = '';
return false;
}
setTimeout(() => populate(e), 300);
});
function populate(e) {
const btnBox = document.createElement('div');
for (let i = 1; i <= 3; i++) {
const btn = document.createElement('button');
btn.classList.add('js-click')
btn.innerText = 'Click me';
btn.addEventListener('click',function(ev){console.log('You clicked me !')})
btnBox.appendChild(btn);
}
resBox.appendChild(btnBox);
}
<input type="text" id="search">
<div id="results"></div>
Now, here is an example that only has one event listener but would completely handle the situation >:D
Technically this should be faster(since one event listener compared to many), but personally I prefer this option because it "feels better" due to one function controlling the whole button layout(which would make it less "rigid")
PS: The speed difference is so insignificant, you can pick and choose(but if a whole chuck ton of buttons, yea this becomes better)
const searchBar = document.getElementById('search');
const resBox = document.getElementById('results');
const randChars=()=>{ //random characters to prove ONE event listener can work for multiple buttons in resBox
let arr=["a","b","c","d","e"]
let randIndex=()=>Math.floor(Math.random()*arr.length)||1
let n=randIndex(); let returnChar=""
for(let i=0;i<n;i++){returnChar+=arr[randIndex()]}
return returnChar
}
searchBar.addEventListener('input', function handler(e) {
if (e.target.value === '') {
resBox.innerHTML = '';
return false;
}
setTimeout(() => populate(e), 300);
});
resBox.addEventListener('click',function(ev){ //single event listener for all buttons
let currentButton=ev.path[0]
if(currentButton.tagName!="BUTTON"){return;} //if a button was not clicked
console.log("Button with text\n'"+currentButton.innerText+"'\nwas clicked")
})
function populate(e) {
const btnBox = document.createElement('div');
for (let i = 1; i <= 3; i++) {
const btn = document.createElement('button');
btn.classList.add('js-click')
btn.innerText = 'Click me '+randChars();
btnBox.appendChild(btn);
}
resBox.appendChild(btnBox);
}
<input type="text" id="search">
<div id="results"></div>
This question already has answers here:
How to check if a button has been clicked using javascript?
(4 answers)
Closed 2 years ago.
I was wondering if there is a way of checking if a button has been clicked? This is the button I want to check:
<button id="money" onClick="myFunction()"> £25 </button>
I've looked all over to try and find a solution but any method I've tried just creates errors, this is one solution I've tried:
function myFunction{
if(document.getElementById('money').clicked == true){
alert("button was clicked")
}
}
Any help is greatly appreciated! Thanks
you can add class isClicked at the end of your function and after that each time you click it never work in your condition
function myFunction(){
const el = document.getElementById('money');
if (!Object.values(el.classList).some(function(x) {return x == 'isClicked'})) {
alert('your code');
}
el.classList.add('isClicked');
}
<button id="money" onClick="myFunction()"> £25 </button>
It should work when you remove the if(document.getElementById('money').clicked == true){ line and the corresponding curly brace, e.g.:
var clickedPreviously = false;
function myFunction() {
if (clickedPreviously) {
alert("button was clicked");
}
clickedPreviously = true;
}
To do this you can add the element a specific class name which is "alreadyClicked" in this snippet after that you can check the element has this class or not with the hasClass() function that I share below.
function myFunction() {
if(hasClass(document.getElementById('money'),'alreadyClicked')){
console.log("button was already clicked");
}
else {
console.log("First click, added to class: alreadyClicked to element");
document.getElementById('money').classList.add("alreadyClicked");
}
}
function hasClass(el, cn){
var classes = el.classList;
for(var j = 0; j < classes.length; j++){
if(classes[j] == cn){
return true;
}
}
}
<button id="money" onClick="myFunction()"> £25 </button>
Another solution is using a new attribute with the same logic. You can add an attribute your element like data-clicked="false". According to Mozilla explained here;
Any attribute on any element whose attribute name starts with data- is
a data attribute. Say you have an article and you want to store some
extra information that doesn’t have any visual representation. Just
use data attributes for that.
<button
id="money"
data-clicked="true"
data-clicked-count="3">
£25</button>
To reach the data attributes with Javascript you can use below snippet.
var element = document.getElementById('money');
element.dataset.clicked; // true
element.dataset.clickedCount; // 3
And also you can set them more easily than class name updating and checking.
var element = document.getElementById('money');
element.dataset.clickedCount = 4
Full Solution with Data Attr
function myFunction() {
const myButton = document.querySelector('#money');
if(myButton.dataset.clicked == 'false'){
myButton.dataset.clicked = 'true';
console.log("data-clicked updated!");
}
myButton.dataset.clickedCount = parseInt(myButton.dataset.clickedCount)+1;
console.log("count of click : "+myButton.dataset.clickedCount);
}
function hasClass(el, cn){
var classes = el.classList;
for(var j = 0; j < classes.length; j++){
if(classes[j] == cn){
return true;
}
}
}
<button
id="money"
onClick="myFunction()"
data-clicked='false'
data-clicked-count='0'>
£25
</button>
You don't need the if statement. You would just have to add an event listener on the button like this:
function myFunction() {
document.getElementById('money').addEventlistener('click', () => {
alert('button clicked')
}
Try like this
document.getElementById('money').onclick = function() {
alert("button was clicked");
};
document.getElementById('money').onclick = function() {
alert("button was clicked");
};
<button id="money"> £25 </button>
I am trying to code a simple quiz app. I am trying to put a hidden screen at the end when one clicks on a button 3 times at the end. This is what I have tried:
for (var i = 0; i > 2; i++) {
onEvent("button26", "click", function() {
setScreen("TrollScreen");
playSound("sound://default.mp3", false);
});
}
I am fairly new to code, and I'm not sure how to do this. Help is appreciated.
You need to keep the count of the clicks outside of the event handler. Then inside it you can check that value and show the screen or increase the counter accordingly.
var count = 0;
onEvent("button26", "click", function(){
if(count > 2){
setScreen("TrollScreen");
playSound("sound://default.mp3", false);
}else{
count++;
}
});
Since all DOM elements are actually objects, you can attach a property to them that will serve as a counter, thus when a button gets clicked, you increment that property by 1 and then check if it reached 3 already.
A more subtle approach is to use a helper function that attaches the event and set up the counter as a closured variable, here is how:
function attachEventWithCounter(elem, func, maxClickCount) {
let count = 0;
elem.addEventListener("click", function(e) {
count++;
if(count >= maxClickCount) {
func.call(this, e);
// and probably reset 'count' to 0
}
});
}
You can then use it like so:
attachEventWithCounter(myButton, myEventListener, 3);
attachEventWithCounter just takes a DOM element, a function that will serve as the event listener and a number that will be the maximum amount of tries. It then attaches a click event listener (you could pass in the type of the event as well if you want) and then whenever that event happens, it increments a locally declared variable count (initially set to 0) and checks if it reached the maximum amount of tries, if so it just calls the function passed as parameter (using Function#call to pass a custom this and the event argument to mimic the actual event listener).
Example:
function attachEventWithCounter(elem, func, maxClickCount) {
let count = 0;
elem.addEventListener("click", function(e) {
count++;
if(count >= maxClickCount) {
func.call(this, e);
count = 0;
}
});
}
let btn = document.getElementById("myButton");
function listener() {
alert("Clicked at last!!!");
}
attachEventWithCounter(btn, listener, 3);
<button id="myButton">Click me 3 times</button>
this will click the button three times every time you press it (at least I think). instead, make a counter variable that starts at 0 and increment it up by 1 each time the button is pressed. the put the action you want to perform inside in an if statement ie
if(counter >= 3){
//do some action
}
hope that helps!
you want to keep a counter variable outside the scope of the event to keep track of how many times it was clicked. Ex.
let counter = 0;
onEvent("button26", "click", function() {
if(counter >= 3) {
setScreen("TrollScreen");
playSound("sound://default.mp3", false);
}
counter ++;
});
//create a variable to check how many times the button has been clicked
var buttonClick = 0;
function CheckCount() {
//Check if the buttonClick variable is three
if (buttonClick == 3) {
//if it is equal to three, display the screen and play the sound
//below commented out for sake of demo
//setScreen("TrollScreen");
//playSound("sound://default.mp3", false);
document.getElementById('buttonclickcount').innerHTML = "You clicked it three times";
} else {
//if it is not so, then increment the buttonClick variable by 1
buttonClick++
//so you can see how many times the button has been clicked
document.getElementById('buttonclickcount').innerHTML = buttonClick;
}
};
<!--I would create an onclick event on the button itself that runs a function when -->
<button onclick="CheckCount()">You Win!</button>
<div id="buttonclickcount"></div>
You should look at using closures. This is where you define a variable before returning a function; your returned function closes around this variable. You could do something like in this fiddle.
const button = document.getElementById('button');
const output = document.getElementById('output');
const click = (function() {
let count = 0;
return function() {
count++;
if(count > 3) {
output.innerHTML = 'Count is greater than 3: ' + count
}
}
})();
button.addEventListener('click', click);
I would like to change an inputs value whenever one of my many "li" tags are clicked (without using jQuery). I listed two of the list tags in my HTML below and I want to differentiate between them in my if statement. What would I put inside the if parameters to display buttons[0] being clicked or buttons[1]?
function myFunction() {
var input = document.getElementById('values');
var buttons = document.getElementsByTagName('li');
if(buttons[0]) {
input.value = 0;
}
else if(buttons[1]) {
input.value += 1;
}
};
HTML :
<div class="box">
<input id="values" type="text" placeholder="2017">
<ul>
<li onclick="myFunction()" id="1">C</li>
<li onclick="myFunction()" id="2">1</li>
</ul>
</div>
Two mistakes.
First, It is because of your if statement checks whether button[0] and button[1] are undefined.
Since button[0] is defined, it never goes to your second condition. So, your statement is just the same as:
function myFunction() {
var input = document.getElementById('values');
var buttons = document.getElementsByTagName('li');
if(buttons[0]) {
input.value = 0;
}
// the second if else is redundant because buttons[0] is not undefined
};
Second, input value is in string, so to increment, you need to parse it to integer. So for the fix:
function myFunction(e) {
var input = document.getElementById('values');
var buttons = document.getElementsByTagName('li');
if(buttons[0].id === e.target.id) {
input.value = 0;
}
else if(buttons[1].id === e.target.id) {
input.value = parseInt(input.value) + 1;
}
};
And your html needs to change a bit, because the function needs to capture the click event:
<div class="box">
<input id="values" type="text" placeholder="2017">
<ul>
<li onclick="myFunction(event)" id="1">C</li>
<li onclick="myFunction(event)" id="2">1</li>
</ul>
</div>
Given html at Question, if <li> elements have an id, you can pass this to myFunction, use id of li element
<li onclick="myFunction(this)" id="1">C</li>
<li onclick="myFunction(this)" id="2">1</li>
if(this.id === "1") {
input.value = 0;
}
else if(this.id === "2") {
input.value += 1;
}
I am somewhat confused as to what you want, but I think this should come pretty close? Let me know and I'm happy to help further.
EDIT: Just noticed you were calling this function from the element itself. Ignore this unless you want to abstract it, which I would usually suggest.
function myFunction() {
var input = document.getElementById('values');
var buttons = document.getElementsByTagName('li');
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
if (i === 0) {
input.value = 0;
}
else if(i === 1) {
input.value += 1;
}
})
}
}
Instead of binding events to each <li>, use event delegation. Details are commented in Snippet.
SNIPPET
// Reference the <ul>
var list = document.querySelector('ul');
// When list is clicked call function delegator()
list.addEventListener('click', delegator, false);
/* This function uses a pattern called event...
||...delegation. Basically we register the event...
||...on the parent of multiple clickable elements...
||...In this case it would be <ul> and the children...
||...<li> would be the last in an event chain...
||...which would make that particular <li>...
||...the event.target (the one that's clicked)...
||...Any other elements above event.target are...
||...event.currentTarget. By knowing this, we can...
||...determine event.target by determining what is...
||...event.currentTarget.
*/
function delegator(event) {
// If it ain't event.currentTarget...
if (event.target !== event.currentTarget) {
/*...then it's gotta be event.target...
||...so let's store it's id in a var
*/
var tgt = event.target.id;
// Reference the id to as an DOM object
var target = document.getElementById(tgt);
// Get and store target's text
var value = target.textContent;
// Get and set textbox's value to the text of target
document.getElementById('values').value = value;
}
return false;
}
<div class="box">
<input id="values" type="text" placeholder="2017">
<ul>
<li id="i1">C</li>
<li id="i2">1</li>
</ul>
</div>
I have a radio button which by default comes checked when the page loads ,and user can un_check if he want by single click but its not working in single click .. after three clicks the radio button un_checked.
Please see
JSFIDDLE . in the code the radio button with value 7 comes with checked by default , I can be able to un_check by clicking three times on it.is there any way to un_check it by just single click .Any help is appreciated.
Thank you.
<td style="padding-right:0px;"><input type="radio" name="TEST" onclick=" var allRadios = document.getElementsByName('TEST'); var booRadio; var x = 0; for(x = 0; x < allRadios.length; x++){ allRadios[x].onclick = function() { if (booRadio == this) { this.checked = false; booRadio = null; }else{ booRadio = this; } }; }" value="7" CHECKED> 7</td>
A JQuery solution, if you assing a class radioClass to your radio buttons:
(function () {
$('.radioClass').on('mouseup', function (e) {
var xRadioB = this;
if ($(xRadioB).is(':checked')) {
setTimeout(function () {
$(xRadioB).prop('checked', false);
}, 5);
}
});
})();
JSfiddle Example: https://jsfiddle.net/nfed1f7c/
First of all, I hope this is just for a test and that you will not embed events in your HTML as this will become very hard to manage, very quickly. I've manage to get a version working with some improve JavaScript. While I did not play with this for too long, I suspect there are better ways but that's a good first draft to get the results you desire: https://jsfiddle.net/0kyyfvy6/5/
var radioElements = document.querySelectorAll('input[type=radio]');
for (var iterator = 0; iterator < radioElements.length; iterator++) {
var radioElement = radioElements[iterator];
radioElement.addEventListener('mousedown', function (event) {
if (event.currentTarget.checked) {
var radioElement = event.currentTarget;
setTimeout(function () {
radioElement.checked = '';
}, 100);
}
})
}
I tried to have event.stopImmediatePropagation() and so on instead of the setTimeout but for some reasons it did not work. This seems relatively safe to implement depending on your use case.