Dynamically creating elements with onclick only executes the last element [duplicate] - javascript

This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 3 years ago.
I am dynamically creating an onclick event for html elements that are also created dynamically. I can make the elements just fine, but when I click on a specific one, it always runs the onclick for whatever the last element created was.
var parentNode = document.getElementById('mpacks');
parentNode.innerHTML = '';
for (var i = 0, size = listOfItems.length; i < size; i++){
var listNode = document.createElement('LI');
var tmp = document.createElement('a');
tmp.id = listOfItems[i];
tmp.innerText = listOfItems[i];
listNode.appendChild(tmp);
parentNode.appendChild(listNode);
tmp.onclick = function() {insertParam(listOfItems[i])};
}
For example: If I have the list [link1, link2, link3], I render them fine and they all show up on my page. When I click link 1, I would like that to be passed into the onclick function as shown... insertParam("link1"). Instead, when I click on link1, it passes in insertParam("link3") for some reason.

This is happening because of closure. Use let instead of var in for loop
for (let i = 0, size = listOfItems.length; i < size; i++)

Related

I cannot seem to get my Img to display on my webpage [duplicate]

This question already has answers here:
Adding images to an HTML document with JavaScript
(7 answers)
Closed 1 year ago.
I double checked the SRC. i'm a newbie so perhaps there is something i'm not seeing.
<script>
window.addEventListener('load', generateFaces);
let numberOfFaces = 5;
const theLeftSide = document.getElementById("leftSide");
const theRightSide = document.getElementById("rightSide");
// const theBody = document.getElementsByTagName("body")[0];
function generateFaces() {
for (let i=0; i<numberOfFaces; i++) {
let face = document.createElement ('img');
face.setAttribute("src",'images/smile.png');
You are currently only creating the img objects but you also need to append them to your div. You can use the following code for appending:
theLeftSide.appendChild(face);
See Stackblitz for working example: https://stackblitz.com/edit/web-platform-jdsz4u?file=index.html

I can't assign a function with dynamic parameters as the “onclick” for an element [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 2 years ago.
I'm trying to assign the "onclick" for a javascript generated <a> element to some function, loadfunction(project[j].getName(), project[j].getPath()).
var projects = []; //Some array of classes in it
function loadProject(aName, aPath){
//does some stuff
}
var j;
for(j = 0; j < projects.length; j++){
var div = document.createElement("div");
var a = document.createElement("a");
var linkText = document.createTextNode(projects[j]);
a.appendChild(linkText);
a.title = projects[j].getName();
a.href = "AProject.html";
a.onclick = function(){loadProject(projects[j].getName(), projects[j].getPath());};
div.appendChild(a)
div.classList.add("project");
document.getElementById("projcontainer").appendChild(div)
}
Ideally, this should set the onclick to call loadProject() with a defined parameter. The elements are generated, but they are not assigned any onclick function and I can't figure out why. Any help would be appreciated.

Fade In random quote's from array [duplicate]

This question already has answers here:
CSS transition fade in
(4 answers)
Closed 3 years ago.
I need to get quotes to Fade In when clicking on the Get Quotes button. I am very new to JS and CSS and feel relatively lost. I also want to do this not using Jquery.
var quoteText = document.querySelector("h2");
var authorText = document.querySelector("h3")
var button = document.querySelector("button");
var body = document.querySelector("body");
button.addEventListener("click", function(){
var colorRandom = Math.floor(Math.random()*255)
var random = Math.floor(Math.random()*quotes.length)
quoteText.textContent = quotes[random];
authorText.textContent = "- " + authors[random];
})
First, if you want to get all (more than one) quotes you have to use querySelectorAll(), because they querySelector() method returns the first element. When you get all elements you can return random index in range of nodeList.length.
This is very simple example in https://codepen.io/iganchev87/pen/vqxjNm . If you want you can add in function with event listener and so on.
I hope it will help you.
var allQuotes = document.querySelectorAll("h2");
var randomIndex = Math.floor(Math.random()*(allQuotes.length));
console.log(allQuotes[randomIndex].textContent);

appendChild from childNodes doesn't work

This is an interesting question I saw on the net but didn't know the answer:
The following code is intended to add five identical boxes containing links to the document, but it doesn’t work properly. Why not?
// Copies the contents of one box into another
function copyContents(from, to){
for( var i=0; i<=from.childNodes.length-1; i++){
to.appendChild(from.childNodes[i]); // <---- Error on this line.
}
}
//create a box to copy:
var referenceBox = document.createElement('div');
var link = document.createElement('a');
link.href = 'http://www.example.com/';
link.textContent = 'A link';
referenceBox.appendChild(link);
//Add box copies to the document
for(var i=0; i<5; i++){
var newBox = document.createElement('div');
copyContents(referenceBox, newBox);
document.body.appendChild(newBox);
}
Options:
to.appendChild() expects HTML, but from.childNodes[i] is a node object, so all the boxes will contain the texts[Object Node].
document.createElement() reuses existing elements with the same tag, so only one box is added to the document.
The same link element can’t have multiple parents,so only one box ends up with a link in it.
A link’s href has to be set using setAttribute(); setting the property link.href won’t do anything,so none of the links in the boxes will point anywhere.
I guess the answer is 3, but not sure and don't know why?
Any explanation? Tnx
link: to the question
You should only iterate from i = 0 to childNodes.length - 1 in copyContent. Also, you should clone DOM nodes if you want to append them to multiple locations in your document (= 3rd option):
// Copies the contents of one box into another:
function copyContents(from, to) {
for (var i = 0; i < from.childNodes.length; i++) { // <-- change <= to <
to.appendChild(from.childNodes[i].cloneNode(true)); // <-- add cloneNode(true); to clone node and all its children
}
}
// Create a box to copy:
var referenceBox = document.createElement('div');
var link = document.createElement('a');
link.href = 'http://www.example.com/';
link.textContent = 'A link';
referenceBox.appendChild(link);
// Add box copies to the document:
for (var i = 0; i < 5; i++) {
var newBox = document.createElement('div');
copyContents(referenceBox, newBox);
document.body.appendChild(newBox);
}
See also appendChild only works first time

How to open a specific URL onclick? [duplicate]

This question already has answers here:
Adding an onclick function to go to url in JavaScript?
(9 answers)
Closed 9 years ago.
I want to open a URL when the following is clicked:
<span class="taglib-text">Forgot Password</span>
Can anybody provide me with its Javascript?
Actually, I cannot control the HTML that's why I need to call an event using Javascript and class name i.e. taglib-text
Try this:
var url = 'http://www.google.com';
var element = document.getElementsByClassName('taglib-text')[0]; // only targets the first element it finds
element.addEventListener('click',function(){
location.href = url;
});
If you have many elements with that class you can instead use:
var url = 'http://www.google.com';
var elements = document.getElementsByClassName('taglib-text');
for (var i = 0; i < elements.length; i++){
elements[i].addEventListener('click', function () {
location.href = url;
});
}
FIDDLE
I changed my answer from using .querySelector() to .getElementsByClassName() because of Shawn's comment and this test

Categories

Resources