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.
Related
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)
I am populating an unordered list item with javascript as follows:
for(var i = 0; i < ourData.length; i++){
$('#searchTeamResultView').append(`<li> <Button class="ui-btn" value=${ourData[i]}> ${ourData[i]["team_long_name"]} </Button> </li>`)
}
The ourData is an array of json objects. I want to get log the value of whatever the button user clicks. I am detecting the click using the following code
$("#searchTeamResultView").on("click", "li", function(){
console.log("FML"); // I don't understand what to put inside the log
})
I am unsure on how to log the value of list item on which the user clicks. It would be great if someone could assist me with it. Sorry if this is a noob question. I was unable to figure it out on my own.
If you attach the event handler to the button element instead of the li, which makes more sense semantically, then you can simply use this.value within the event handler. Try this:
let ourData = ['lorem', 'ipsum', 'dolor'];
for (var i = 0; i < ourData.length; i++) {
$('#searchTeamResultView').append(`<li><button class="ui-btn" value="${ourData[i]}">${ourData[i]}</button></li>`);
}
$("#searchTeamResultView").on("click", "button", function() {
console.log(this.value);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="searchTeamResultView"></ul>
Once added onclick event, you can get exact element by "this" value.
For example.
$( document ).ready(function() {
let $elementsDiv = $('.elements');
for(let i = 0; i < 5; i++) {
//Creating new div with on click handler and adding attr subIndex
let $newOnclickElement = $('<div></div>')
.on('click', function() {
handleOnClick(this);
})
.attr('subIndex', i)
.html('element ' + i);
$elementsDiv.append($newOnclickElement);
}
});
function handleOnClick(subElement) {
console.log(subElement);
//To get its attr for example some new index we gonna add;
let $subElemenet = $(subElement);
//Console log subIndex
console.log($subElemenet.attr('subIndex'));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='elements'>
</div>
Someone beat me to it :(
I'm trying to add an event listener (onclick) onto every li element that gets created in a specific for loop - using JavaScript.
First I tried using tempLi.onclick (see code below for context), but it wouldn't run the function. After that I searched for the issue here on Stackoverflow, and I read that this method I'm using below should work - but it doesn't (not in my case at least).
if (users.length !== 0) {
for (let i = 0; i < users.length; i++) {
let tempLi = d.createElement('li');
tempLi.className = 'btn btn-primary knappur'
tempLi.innerHTML = users[i];
getId('usersUl').appendChild(tempLi);
(function(value) {
tempLi.addEventListener("click", function() {
alert(value);
}, false);
})(users[i]);
getId('usersUl').innerHTML += '<br>';
}
}
The code is in a function called loginPrepare:
let loginPrepare = () => { ... }
How can I execute code when I click on the generated li (tempLi)?
EDIT: The code that I'd like to run when clicked on the "li" is login(users[i])
I would put the event handler on your ul and rely on event bubbling instead of attaching an event handler to each. It would look something like this.
document.getElementById('usersUl')
.addEventListener('click', function(e) {
if (e.target.hasClass('knappur') {
// Do your work
}
});
You are creating a function inside a loop, referencing the ever-changing index i, which, when the loop is done might be a completely different value than what you think it is.
Also, I think this way you are attaching the event-listener before the tempLi has had time to be properly integrated into the dom.
Third: you don't need to create a new event-listener for each list item. One is enough.//
Try this instead:
if (users.length !== 0) {
const list = getId('usersUl')
for (let i = 0; i < users.length; i++) {
let tempLi = d.createElement('li');
tempLi.className = 'btn btn-primary knappur';
tempLi.innerHTML = users[i];
tempLi.setAttribute('data-user', users[i])
list.appendChild(tempLi);
//list.innerHTML += '<br>'; don't do this btw, <br />s aren't valid children of lists!
}
list.addEventListener("click", event => {
const user = event.target.getAttribute('data-user');
alert(user);
});
}
We can achieve event binding to HTML in very simple way using JQuery like below:
$("#usersUl").on('click',function(e){
//what we do
});
I have a loop, and I am creating a button within each iteration. I am attaching an event listener to each newly created button, and I need to pass unique parameters through. Please see the code below (in this case, just passing the index from the loop through the event listener)
for (i = 0; i <= worklog.worklogs.length; i++) {
if (worklog.total > 0) {
var theButton = document.createElement("button");
theButton.addEventListener("click", alertButton(i));
theButton.innerHTML = "Add";
mySpan.appendChild(theButton);
}
}
function alertButton(arg) {
return function () {
alert(arg);
};
}
Currently, the event listener fires on only the button implemented on the very last iteration. If I remove the "return function(){}" within my alertButton function, then the event listener is fired on each iteration without the user clicking on the button.
If you have any ideas I would be extremely appreciative. I am finding other people who have had this problem, yet the solutions provided don't seem to work so well for me. Hopefully I am overlooking something simple.
Thanks!
Issue is in the way you are assigning listener:
theButton.addEventListener("click", alertButton(i));
in above code, alertButton(i) will call function and not assign to it. If you want to pass a value to a function assignment, you should bind value.
theButton.addEventListener("click", alertButton.bind(this,i));
As pointed by #Andreas, a working example.
function createButtons() {
for (var i = 0; i < 5; i++) {
var theButton = document.createElement("button");
theButton.addEventListener("click", alertButton.bind(this, i));
theButton.innerHTML = "Add";
content.appendChild(theButton);
}
}
function alertButton(arg) {
console.log(arg)
}
createButtons();
<div id="content"></div>
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);
}