I have similar problem in my main project. Down below I shown my problem to the simplified way. I know why my code in executing couple times, the question is how to repair this.
HTML Code:
<body>
<button id="btn">CLICK ME</button>
<script src="index.js" defer></script>
</body>
Javascript:
const btn = document.getElementById("btn");
var number = 1;
function load() {
console.log(number);
btn.addEventListener('click', (e) => add(e))
};
function add(e) {
number += 1;
load();
e.stopPropation();
}
load();
And of course when I click the button first time everything is fine, but when I click second time, the button executes function two times, after third click four times and so on. I thought that e.stopPropation(); will solve the problem, but unfortunately is not.
Main Question:
How to kill events which are doubled?
here use this
const btn = document.getElementById("btn");
var number = 1;
function load() {
console.log(number);
btn.addEventListener("click", (e) => add(e));
}
function add(e) {
number += 1;
load();
e.stopImmediatePropagation();
}
load();
Related
I want to make a simple game, learning HTML, CSS and javaScript. I wrote code in which I want a function to go to the next one by clicking a button. Its has a flow like the code below. It does not work as I intend. I want it to return to the first function when a round finished. But from the second round buttons start to call next funcitons several times by one click. What do I misunderstand? I show the console output at the bottom.
<body>
<button id="toFunc2">toFunc2</button>
<button id="toFunc3">toFunc3</button>
<button id ="toFunc4">toFunc4</button>
<button id ="toFunc1">toFunc1</button>
<p></p>
</body>
<script>
window.addEventListener("DOMContentLoaded", function(){
function functionFour(obj) {
obj.nowFunctionFour += 1;
console.log(`nowFunctionFour: ${ obj.nowFunctionFour }`);
obj.toFunc1Button.addEventListener("click", function(){
functionOne(obj);
})
}
function functionThree(obj) {
obj.nowFunctionThree += 1;
console.log(`nowFunctionThree: ${ obj.nowFunctionThree }`);
obj.toFunc4Button.addEventListener("click", function(){
functionFour(obj);
});
}
function functionTwo(obj) {
obj.nowFunctionTwo += 1;
console.log(`nowFunctionTwo: ${ obj.nowFunctionTwo }`);
obj.toFunc3Button.addEventListener("click", function(){
functionThree(obj);
});
}
function functionOne(obj) {
obj.nowFunctionOne += 1;
console.log(`nowFunctionOne: ${ obj.nowFunctionOne }`);
obj.toFunc2Button.addEventListener("click", function(){
functionTwo(obj);
})
}
const obj = {
toFunc2Button: document.getElementById("toFunc2"),
toFunc3Button: document.getElementById("toFunc3"),
toFunc4Button: document.getElementById("toFunc4"),
toFunc1Button: document.getElementById("toFunc1"),
nowFunctionOne: 0,
nowFunctionTwo: 0,
nowFunctionThree: 0,
nowFunctionFour: 0
}
functionOne(obj);
})
</script>
-------Console Output-------
nowFunctionOne: 1
nowFunctionTwo: 1
nowFunctionThree: 1
nowFunctionFour: 1
nowFunctionOne: 2
nowFunctionTwo: 2
nowFunctionTwo: 3
The way the event listeners work in JavaScript is that:
You can attach multiple event listeners to the same DOM element
Because of this, you can accidentally attach the same listener twice or more times to the same element. That way, for each event you will see that the event listener is being invoked multiple times although they are actually different listeners with the same code! This is what has happened with your implementation.
On your first round, when functionOne is invoked, an event listener gets attached. On your second round, functionOne is invoked again & by executing the code line by line another event listener gets attached (with same code) to the element. Hence you get the issue!
I would propose you attach the event handlers separately & for one time only.
Solution
<html>
<body>
<button id="toFunc2">toFunc2</button>
<button id="toFunc3">toFunc3</button>
<button id="toFunc4">toFunc4</button>
<button id="toFunc1">toFunc1</button>
<p></p>
<script>
window.addEventListener("DOMContentLoaded", function () {
const obj = {
nowFunctionOne: 0,
nowFunctionTwo: 0,
nowFunctionThree: 0,
nowFunctionFour: 0,
};
function functionFour() {
obj.nowFunctionFour += 1;
console.log(`nowFunctionFour: ${obj.nowFunctionFour}`);
}
function functionThree() {
obj.nowFunctionThree += 1;
console.log(`nowFunctionThree: ${obj.nowFunctionThree}`);
}
function functionTwo() {
obj.nowFunctionTwo += 1;
console.log(`nowFunctionTwo: ${obj.nowFunctionTwo}`);
}
function functionOne() {
obj.nowFunctionOne += 1;
console.log(`nowFunctionOne: ${obj.nowFunctionOne}`);
}
const attachEventListeners = () => {
document.getElementById("toFunc1").addEventListener("click", functionOne);
document.getElementById("toFunc2").addEventListener("click", functionTwo);
document.getElementById("toFunc3").addEventListener("click", functionThree);
document.getElementById("toFunc4").addEventListener("click", functionFour);
};
attachEventListeners();
})
</script>
</body>
</html>
I have a form that counts when a button (button.clicked in the example below) is clicked. I want to make it operate in two modes: one keeps counting with every click, the other has a timer (started with the click of another button, button.start) that will disable the click-count button when the timer runs out. Each mode is chosen by clicking a button (button.menu-timer and button.menu-clicks). When the count mode is selected, one function (cc) is called. When switched to the timer mode, another function (tt) should be called and the first function should stop.
If I click one mode button, then everything works as it should, but if after that I click the other mode button, both functions continue to operate; each click of button.click adds two to the count. Moreover, if you click the mode buttons several times, clicking the count button will increase the counter many times, rather than only once.
I searched for solutions on the Internet and found one based on return; I tried to use return in various ways but couldn't get it to work.
I need that when choosing the right mode, only the desired function works. And so that when you click several times on one mode, the function will run once.
The following snippet is also available on CodePen.
let clicker = document.querySelector(".click");
let start = document.querySelector(".start");
let clickerValue = document.querySelector(".click").value;
const reset = document.querySelector(".reset");
const menuTimer = document.querySelector(".menu-timer");
const menuClicks = document.querySelector(".menu-clicks");
const times = document.querySelectorAll(".time");
let i = 0;
let y;
let tf;
let timer = 15;
function tt(tf) {
if (tf ===2) {
return;
}
start.addEventListener("click", () => {
start.style.zIndex = "-1";
y = setInterval(() => {
if (i === timer) {
clicker.setAttribute("disabled", "");
} else {
i++;
}
}, 1000);
});
clicker.addEventListener("click", () => {
clicker.textContent = clickerValue++;
});
reset.addEventListener("click", resetF);
}
function cc(tf) {
if (tf = 1) {
return;
}
start.addEventListener("click", () => {
console.log("111111");
start.style.zIndex = "-1";
});
clicker.addEventListener("click", () => {
clicker.textContent = `a ${clickerValue++}`;
});
reset.addEventListener("click", resetF);
}
function resetF() {
clearInterval(y);
i = 0;
start.style.zIndex = "2";
clickerValue = 0;
clicker.textContent = clickerValue;
clicker.removeAttribute("disabled", "");
}
menuTimer.addEventListener("click", function () {
menuTimer.classList.add("active");
menuClicks.classList.remove("active");
tt(1);
resetF();
});
menuClicks.addEventListener("click", function () {
menuClicks.classList.add("active");
menuTimer.classList.remove("active");
cc(2)
resetF();
});
<div class="menu">
<button type="button" onclick="tf = 1" class="menu-timer">TIMER</button>
<button type="button" onclick="tf = 2" class="menu-clicks">CLICKS</button>
</div>
<div class="click-btn">
<button class="click" type="button">0</button>
<button class="start" type="button">START</button>
</div>
<button class="reset" type="button">Reset</button>
You have a typo with assigning = instead of equality operator ===
function cc(tf) {
if (tf = 1) { // should be ===
return;
}
...
}
Also before you addEventListener('click', ...), a good practice is to remove previous click listeners with removeEventListener('click')
function greet () {
console.log ("Hi there!");
}
function addButton () {
document.createElement("[wanted_HTML_tag_here]");
}
There is separate HTML document. It has a button that calls the function addButton() upon being pressed. Said function has to create a new element and append it to the element. Pressing this new button has to call the function greet().
I try with [element_name].setAttribute("[attribute]", "[attribute_value]") but useless
Also trying document.[element_to_append_into].appendChild([element_being_added]); but same
Here's a complete working example (it is one way of doing it):
<html lang="en">
<body>
<button id="btn">Create Button</button>
</body>
<script>
function greet() {
console.log('Hi there')
}
function addButton() {
const button = document.createElement('button')
const buttonTextNode = document.createTextNode('Click')
button.appendChild(buttonTextNode)
button.onclick = greet
document.body.appendChild(button)
}
// get the button that creates other buttons
const buttonCreator = document.getElementById('btn')
buttonCreator.onclick = addButton
</script>
</html>
<html>
<body>
<button onclick = 'click1()'> </button>
</body>
<script>
var one
function click1(){
one = one + 1;
}
if (one == 3){
document.write('yes')
}
</script>
</html>
Here is an example JS / HTML. How can I write yes if the button is clicked three times?. This code would work in python and other languages. How can I do this in JS?
Your code have syntax and logical errors
<html>
<body>
<button onclick='click1()'>click here </button>
<script>
var one = 0;
function click1(){
one = one + 1;
if (one == 3){
alert("here");
}
}
</script>
</body>
</html>
after three clicks you will again have to reset variable one in if statement
if (one == 3){
alert("here");
one = 0;
}
There are multiple issues here.
First of all you should set a default to the variable, otherwise it will be declared as undefined.
Second you should put your if in the same function.
Third you should call your functions with the brackets in your html => 'click1()'
I also recommend making some changes
make your variable a let instead of a var.
use typesafe checks with 3 equal signs
<html>
<body>
<button onclick = 'click1()'> </button>
<script>
let one = 0;
function click1(){
one += 1;
if (one === 3){
document.write('yes')
}
}
</script>
</body>
</html>
var one = 0;
function click1() {
one++
if (one == 3) {
console.log('yes');
one = 0
}
}
<button onclick ='click1()'> </button>
Change your code like this:
<html>
<body>
<button onclick="click1()">Click</button>
</body>
<script>
var one = 0;
const click1 = () => { if (++one === 3) document.write('yes') };
</script>
</html>
Looks like you're missing the brackets on the function call on your button. Try: onclick='click1()'
You could use an approach like below. See the code comments for details:
// Reference to the DOM elements
const countEl = document.querySelector('#count-el');
const buttonEl = document.querySelector('button');
// Init a counter variable and return a function that increments it
const increment = (() => {
let i = 1;
return () => i++;
})();
// The click event listener
buttonEl.addEventListener('click', () => {
// Increment the count and update the UI based on if current click count is 3
if (increment() === 3) {
countEl.textContent = 'yes';
}
});
<span id="count-el"></span>
<br />
<button>Click 3 times</button>
I am trying to make a function that would allow me to toggle eventListener of an element.
In the example below, I have three buttons: main, on and off. When I click on the on button, the main button becomes functional. After I click off button, the main button should not work anymore (but now it still does).
Now I can achieve a desired behavior by clicking on button for the second time, but I guess it's a bad coincidence and it's not supposed to work that way.
Maybe I should add that I would like to work this out without using jQuery or similar and it needs to be a function, because I am going to use it for a lot of buttons.
(I suspect something with scope causes the problem (clickHandler when calling the function to activate the button is not the same as the clickHandler when calling the function to disable the button), but I can't think of a way to test it.)
// buttons definitions, not important
var mainButton = document.querySelector("#mainButton");
var onButton = document.querySelector("#onButton");
var offButton = document.querySelector("#offButton");
// main function
var toggleButtons = function(toggleVal, button, element) {
var activateButton, clickHandler, disableButton;
// callback function for listener bellow
clickHandler = function() {
document.querySelector(element).classList.toggle("yellow");
};
activateButton = function() {
button.addEventListener("click", clickHandler);
};
disableButton = function() {
button.removeEventListener("click", clickHandler);
};
// when first argument is 1, make the button functional, otherwise disable its functionality
if (toggleVal === 1) {
activateButton();
} else {
disableButton();
}
};
// when onButton is clicked, call main function with arguments
// this works
onButton.addEventListener("click", function() {
toggleButtons(1, mainButton, "body");
});
// this fails to disable the button
offButton.addEventListener("click", function() {
toggleButtons(0, mainButton);
});
.yellow {
background-color: yellow;
}
<button type="button" id="mainButton">mainButton
</button>
<button type="button" id="onButton">onButton
</button>
<button type="button" id="offButton">offButton
</button>
<p>mainButton: toggles background color on click
</p>
<p>onButton: turns on mainButtons's functionality</p>
<p>offButton: supposed to turn off mainButton's functionality</p>
var mainButton = document.querySelector("#mainButton");
var onButton = document.querySelector("#onButton");
var offButon = document.querySelector("#offButton");
var element; // declare the element here and change it from toggleButtons when needed.
function clickHandler() {
document.querySelector(element).classList.toggle('yellow');
}
function activateButton(button) { // You missed this part
button.addEventListener('click', clickHandler);
}
function disableButton(button) { // You missed this part
button.removeEventListener('click', clickHandler);
}
function toggleButtons(value, button) {
if (value === 1) {
activateButton(button); // You missed this part
} else {
disableButton(button); // You missed this part
}
};
onButton.addEventListener('click', function() {
element = 'body'; // you can change it to some other element
toggleButtons(1, mainButton);
});
offButton.addEventListener('click', function() {
element = 'body'; // you can change it to some other element
toggleButtons(0, mainButton);
});
Below code helps to toggle between two functions from an eventListener:
var playmusic=false;
function playSound() {
const audio = document.querySelector(`audio[data-key="${event.keyCode}"]`)
audio.currentTime = 0
audio.play()
playmusic=true;
}
function stopSound() {
const audio = document.querySelector(`audio[data-key="${event.keyCode}"]`)
audio.pause()
playmusic=false;
}
window.addEventListener('keydown',
function(){playmusic?stopSound():playSound()} )