javascript click game using less html - javascript

I'm making a basic javascript game where you need to click multiple images in a certain period of time. (currently 4 seconds)
My javascript looks like this
document.getElementById("myBtn").addEventListener("click", countdown);
function countdown() {
setTimeout(function(){
prompt("you got" + counter);
}, 4000);
}
var counter = 0;
function countup() {
counter = counter + 1;
}
And while that does work, every img in my HTML has to have:
onclick="countup(); this.onclick=null"
which after 20 pictures is a lot. My question is, is there a way to condense this? Some js method of collecting all the pictures by class and applying the click countup and null to it?

You can use document.querySelectorAll() to select all your images and add an event listener to count up and remove the event listener like so:
function handleClick(e)
{
countup();
e.target.removeEventListener('click', handleClick);
}
var images = document.querySelectorAll('img');
for (var i = 0; i < images.length; i++)
{
images[i].addEventListener('click', handleClick);
}
More about document.querySelectorAll here: https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
You can also use a classname with querySelectorAll, pass in '.myClass'

Yes - use getElementsByClassName. E.g. if you apply the class 'button' to all of your button images:
var buttons = document.getElementByClassName('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', countup);
}
To remove the event listener after the first click requires something a bit more complicated, however. For example, you can write a second function that adds an event listener which calls your original function and then removes itself.
var buttons = document.getElementByClassName('button');
function clickOnce(el, func) {
function listener() {
func();
el.removeEventListener('click', listener);
}
el.addEventListener('click', listener);
}
for (var i = 0; i < buttons.length; i++) {
clickOnce(buttons[i], countup);
}

Related

How to not lose my event listener in Javascript each time I use .insertBefore?

I am attempting to move a div (which contains text and other elements) each time the user clicks the up or down arrow. The goal is to simply allow users to rearrange divs to their liking, based on clicking the appropriate arrows.
The issue I'm running into is -- when I use .insertBefore to rearrange these elements? It only allows me to click the arrow and perform that action once. After that, nothing happens. It appears that I'm losing my event listener each time I do this. Is there a way for me to somehow say: "Keep that old event listener after it gets moved?"
Here is the code:
for (let i = 0; i < NumberOfSavedIdeas; i++) {
document.getElementById('DeleteIdeaButton' + [i]).addEventListener('click', () => {
var DivToDelete = document.getElementById("SavedIdeaDiv" + [i]);
DivToDelete.remove();
let ArrayContentMatch = FullSavedIdeasArray.indexOf(FullSavedIdeasArray[i])
FullSavedIdeasArray.splice(ArrayContentMatch, 1);
chrome.storage.local.set({SavedIdeas: FullSavedIdeasArray});
});
document.getElementById('MoveIdeaUp' + [i]).addEventListener('click', () => {
var DivToMove1 = document.getElementById("SavedIdeaDiv" + [i]);
var ParentDiv1 = document.getElementById("DivTesting");
ParentDiv1.insertBefore(DivToMove1, ParentDiv1.children[i-1]);
});
document.getElementById('MoveIdeaDown' + [i]).addEventListener('click', () => {
alert('move down')
});
}
Thanks!
This is because new element doesn't exist in DOM when all event listeners are set. Add an event listener on document instead of an element.
It should be wrapped like:
for (let i = 0; i < NumberOfSavedIdeas; i++) {
document.body.addEventListener( 'click', function (e) {
if (e.target.id == 'YourId' + [i]) {
yourFunction();
}
} );
}

How to get value from button after it has been clicked

I'm struggling with this assignment: Pin an event listener to the buttons.
Create a function that gets called when one of the buttons is clicked. Check this with a console.log. Make sure the click event is passed to this function.
Make sure you have access to the value of the button clicked in this function. Check this with console.log. The outcome you want to see in the console when you click is: Leopard / Lion / Elephant / Rhino or Buffalo.
fiveButtons = document.getElementsByClassName("big-five-button");
for (var i = 0; i < fiveButtons.length; i++) {
fiveButtons[i].addEventListener("click", function () {
Array.from(fiveButtons).forEach(function (nameButton) {
console.log(nameButton.innerHTML);
})
});
}
This is what I wrote so far. When I'm clicking the button now, the outcome is the text from all the buttons. While I want the outcome to only be "Lion" after the button lion has been clicked.
<h1>The Big Five</h1>
<ul class="big-five-list">
<li class="big-five-list-item">
<button class="big-five-button">Lion</button>
</li> etc.
when creating an addEventListener you can use the event object to target the element clicked, like this:
fiveButtons[i].addEventListener("click", function (event) {
console.log(event.target.innerHTML);
});
You can change the button to include an onclick function like the below:
https://www.w3schools.com/jsref/event_onclick.asp
<!DOCTYPE html>
<html>
<body>
<button onclick="myFunction('Lion')">Lion</button>
<input type="text" value="" id="getValue">
<p id="demo"></p>
<script>
function myFunction(value) {
document.getElementById("getValue").value = value;
}
</script>
</body>
</html>
The onclick function will then have a value inside the () for the function name. This will pass the value you want across to the function and it can be called whatever you want. The above snippet shows an example of how it can be used
Try this solution!
fiveButtons = document.getElementsByClassName("big-five-button");
for (var i = 0; i < fiveButtons.length; i++) {
fiveButtons[i].addEventListener("click", function (item) {
console.log(item.target.innerHTML);
});
}
The function you pass to addEventListener gives an event argument:
fiveButtons = document.getElementsByClassName("big-five-button");
for (var i = 0; i < fiveButtons.length; i++) {
fiveButtons[i].addEventListener("click", function (event) { // use the first argument
console.log('element value:', event.target.value); // log the 'value' of the event target;
// I suspect you want the innerHTML or innerText
console.log('element innerText:', event.target.innerText);
});
}
You can then get the required information from the DOM node in event.target
You don't need the Array.from inside the for loop. You can just do that:
fiveButtons = document.getElementsByClassName("big-five-button");
for (let i = 0; i < fiveButtons.length; i++) {
fiveButtons[i].addEventListener("click", function () {
console.log(fiveButtons[i].innerText);
});
}
EDITED
// Get all the buttons
const fiveButtons = document.getElementsByClassName("big-five-button");
// Iterate through the collection of buttons
// Here is let i = 0 instead of var i = 0, since var has functional scope and let has block scope
// If we used var i = 0 it would not work implicitly because i would exist in the scope of a function,
// and all the event handlers (for each button) would share the same value of i
for (let i = 0; i < fiveButtons.length; i++) {
// For each button register event handler
fiveButtons[i].addEventListener("click", _ => {
// When button is clicked this part of a code is being called
// Because of javascript CLOSURE, it remembers the i value
console.log(fiveButtons[i].innerHTML)
});
}
If this is not understandable please read about closures in javascript.

Evenet Listener is not executing the functions

Althoug in inline onmauseover="verdadero()" works perfectly
Reviewing I realized that although the box acquires the event listener, simply when I hover over the element the function is not executed, nor is the console.log even written
Note: The Html is simplified for practical purposes
let onCuadro = false;
const cuadro = document.getElementsByClassName("overscroll__box");
for (let i = 0; i < cuadro.length; i++) {
cuadro[i].addEventListener("onmouseover", verdadero,true);
}
for (let i = 0; i < cuadro.length; i++) {
cuadro[i].addEventListener("onmouseleave", falso,true);
}
function verdadero() {
console.log("onCuadro = true");
onCuadro = true;
}
function falso() {
console.log("onCuadro = false");
onCuadro = false;
}
html :
<div class="overscroll__box"></div>
<div class="overscroll__box"></div>
<script src="./index.js"></script>
Event names should not be prefixed with on. Use on when using:
An inline handler, eg <button onclick=, or
When invoking the IDL getter or setter, eg `button.onclick = function() {
But when using addEventListener, only use the event name, without on. The event name here would be mouseover or mouseleave.
for (let i = 0; i < cuadro.length; i++) {
cuadro[i].addEventListener("mouseover", verdadero,true);
cuadro[i].addEventListener("mouseleave", falso,true);
}
Or, more concisely
for (const box of document.getElementsByClassName("overscroll__box")) {
box.addEventListener("mouseover", verdadero, true);
box.addEventListener("mouseleave", falso, true);
}
(You also may well not need to pass a third parameter to addEventListener unless the event delegation really is doing something useful for you)

How to run .remove() after fade-out effect is completed?

I would like to run the line "this.parentElement.remove();" after the line "this.parentElement.classList.add("fade-out");" is completed (fade-out lasts 1 second).
Right now .remove() runs instantly so the fade-out effect does not show.
Many thanks in advance!
var deleteItem = document.querySelectorAll("span");
for (var i = 0; i < deleteItem.length; i++) {
deleteItem[i].addEventListener("click", function(event){
this.parentElement.classList.add("fade-out");
this.parentElement.remove();
event.stopPropagation();
});
}
Specify the duration of your fade inside timeout function and when it's done the callback function will execute
Code sample
const deleteItem = document.querySelectorAll("span");
const FADE_OUT_TIME = 2000;
for (let i = 0; i < deleteItem.length; i++) {
deleteItem[i].addEventListener("click", function(event) {
event.stopPropagation();
this.classList.add("fade-out");
setTimeout(_ => this.remove(), FADE_OUT_TIME)
});
}
.cursor-pointer {
cursor: pointer;
}
<span class="cursor-pointer">first</span>
<span class="cursor-pointer">second</span>
<span class="cursor-pointer">third</span>
One approach would be to listen in on the event's transitionend event (reference).
let el = this.parentElement;
el.addEventListener('transitionend', () => el.remove());
el.classList.add("fade-out");
The attractiveness of this approach versus listening for a timeout means you don't have to hard-code the transition duration in your JavaScript (if you ever change it, you'd have to update both your CSS and your JavaScript.) The event will fire whenever it ends, however long it takes.
Assuming .fade-out triggers an animation, you can add a animationend to the element to achieve this... The callback is called after any animation has ended
var deleteItem = document.querySelectorAll("span");
for (var i = 0; i < deleteItem.length; i++) {
deleteItem[i].addEventListener("click", function(event) {
this.parentElement.addEventListener("animationend", function() {
this.parentElement.remove();
});
this.parentElement.classList.add("fade-out");
event.stopPropagation();
});
}

Event listener in a loop

So I have this eventListner that calls an Class, works like a charm but only once since inte call the add class with index 0.
Im trying to create a loop that will call every add class inside the script, but i cant get loop...
This is the event listner without the loop
var AddEvent = "add";
var addClass = document.getElementsByClassName(AddEvent)[0]
addClass.addEventListener("click", addDiceEvent, false);
function addDiceEvent() {
dicesides_funcfunc();
}
And this is what Im trying to create.
function AddDice(){
for (i = 0; i < 5; i++) {
var addClass = document.getElementsByClassName("add");
addClass.addEventListener("click", addDiceEvent, false);
function addDiceEvent(){
dicesides_funcfunc();
}
}
} AddDice();
Any ideas ?
Hope this work.......
var addClassArr= document.getElementsByClassName(AddEvent);
for (var x in addClassArr)
{
var addClass = addClassArr[x];
addClass.addEventListener("click", addDiceEvent, false);
}
function addDiceEvent() {
dicesides_funcfunc();
}
You need to create new skope in for loop, try this:
function AddDice(){
for (i = 0; i < 5; i++) {
(function(){
var addClass = document.getElementsByClassName("add");
addClass.addEventListener("click", function(){
dicesides_funcfunc();
}, false);
})();
}
}

Categories

Resources