I am working on a project where the user decides how many buttons are there, and then each button triggers a different function.
What I have done is: I have an input that asks "Enter the number of buttons" and a "Submit" button. When the "Submit" button is clicked, the value of variable n is set to the user-defined value.
I then have the following code (assuming the user has set n to 10):
for (i = 0; i < 10; i++) {
var x = document.createElement('div');
x.id = i;
x.innerHTML = i;
x.onclick = function() {alert(i)};
document.body.appendChild(x);
}
What I want is, that when div with id i is clicked, the pop-up message says i. But what has ended up happening is, that no matter which div I click, the pop-up message always says 10.
Why is this happening? How to fix this?
The only thing you need to change is the assignment of i inside the for-loop. Use let to define a locally-scoped variable. Also, use textContent instead of innerHTML for simple text. It is recommended to used const/let rather than var.
for (let i = 0; i < 10; i++) {
const x = document.createElement('div');
x.id = i;
x.textContent = i;
x.onclick = function() { alert(i) };
document.body.appendChild(x);
}
By iterating over your NodeList elements, you can take this next approach.
First of all, append all your created divs in your HTML and continue by looping through the elements list by document.querySelectorAll("div")
That way you select all elements and then assign an addEventListener to each one of the items. On your alert function, print this.id and it will return you the number of the id of the element which corresponds to your i index.
It would be the same also if you just put the whole addEventListener function inside the other loop.
I just separated both so you can understand it better.
for (i = 0; i < 10; i++) {
var x = document.createElement('div');
x.id = i;
x.innerHTML = i;
document.body.appendChild(x);
}
let divs = document.querySelectorAll("div");
for(var a= 0; a < divs.length; a++){
divs[a].addEventListener("click", function(){
alert(this.id);
});
}
You can use getAttribute to read the id of the elements. I show you an example:
for (i = 0; i < 10; i++) {
var x = document.createElement('div');
x.id = i;
x.innerHTML = i;
x.onclick = function(e) {
let dataId= e.currentTarget.getAttribute("id")
alert(dataId)
};
document.body.appendChild(x);
}
Explanation:
getAtrribute() returns the value of an html attribute as a string, just enter the name of the attribute in braces to get the value. In this case I entered "id" which is the value we want to retrieve.
Also to get the value of the element where you click I use currentTarget, to accurately retrieve the value of the div that the iteration creates. If you use target, and inside the div you have more elements, this code will generate an error. Therefore, it is important to use currentTarget for this application.
This happen because after the initialisationn the function will look for the value of i which is always 10 (once it has been initialized)
EDIT
As explained by #Mr. Polywhirl in his better answer, you can use let in your for loop to declare your variable locally instead of globally.
To solve your problem you can pass an event to the function (the click event) and the getting your value.
It can be done with either :
The value of the content (as you did with x.innerHTML)
Adding an id to the div and getting this id
Example :
for (i = 0; i < 10; i++) {
var x = document.createElement('div');
x.id = i;
x.innerHTML = i;
x.onclick = function(event) {
alert(event.target.innerHTML) // with the content
alert(event.target.id) // with the id
};
document.body.appendChild(x);
}
Related
I have an array n i have a four buttons n I just want to display array values ,if i click on first button ,first value should be displayed ,click on second button ,second value should be displayed n so on using addEventListener event handler but there is a problem when i click it directly display last value?
var element = document.querySelectorAll('.box1');
var city = document.querySelector('#name');
for (var i = 0; i < element.length; i++) {
element[i].addEventListener('click', function () {
var i = 0;
var places = ['San diago,USA', 'chicago,USA', 'phoenix,USA', 'New york,USA'];
while (i <places.length) {
console.log(city.innerHTML = places[i]);
i++;
}
});
}
You were iterating over the list of buttons, then inside each handler were also iterating over the full list (using the same variable i). Each button only needs one handler, so you only need one loop.
I moved your "Cities" array outside the function, there's no reason to define it separately inside each handler.
const places = ['San diego,USA', 'chicago,USA', 'phoenix,USA', 'New york,USA'];
let element = document.querySelectorAll('.box1');
let city = document.querySelector('#name');
for (let i = 0; i < element.length; i++) {
element[i].addEventListener('click', function() {
city.innerHTML = places[i];
});
}
<button class="box1">One</button>
<button class="box1">Two</button>
<button class="box1">Three</button>
<button class="box1">Four</button>
<div id="name"></div>
Take special note of the use of let i instead of var i inside that for loop -- ES6 variables are scoped differently; if I had used var there then all four events would get the value of i after the loop has run (so all the buttons would be looking for places[4]!). With let or const the variable is scoped within its block, so the value you want is captured by each iteration in the loop.
I have created a list using a for loop and want to add an event listener to each of them, so that when each item is clicked, it's logged in the console the item number (e.g. if list item 1 is clicked, console log returns the variable currentNumber as 0).
However, with my current code, all I'm getting in the console log is "4". Can someone please help me with this? Thank you.
for (i = 0; i < tipsCatalog.length; i++) {
var newCategory = document.createElement('li');
newCategory.id = "sMonTipHeadline-" + [i];
newCategory.className = "sMonTipHeadline";
newCategory.innerHTML = tipsCatalog[i].tipHeadline;
catalogContainer.appendChild(newCategory);
}
var currentNumber = [];
for (i = 0; i < tipsCatalog.length; i++) {
currentNumber[i] = i;
tipsCatalogList[i].addEventListener('click', function() {console.log(currentNumber[i])});
}
I would try to add the number inside an element's attribute and then take it from there when you need it.
tipsCatalogList[i].addEventListener('click', function() {console.log($(this).attr('yournumber'))});
I'm having a bit of trouble of getting the JavaScript code right. I need some help on what goes where and how it's supposed to look.
This is what I have so far in my script.
<script>
var i = "1";
var listItem = "";
function processInput() {
if (i <= 5) //Comparison operator//
document.getElementById("listItem").innerHTML = (i <= 5);
</script>
Here is my question:
Create a function called processInput(). Within the function create an if statement that runs if the value of i is less than or equal to 5. The if statement should perform the following actions:
Set the value of the listItem variable to the string "item" concatenated with the value of i.
Set the content of the element with an id equal to listItem to the value of the element with the id or toolbox.
Set the value of the element with the id of toolbox to an empty
string.
I'm not sure if I'm setting this up right. I have tried w3Schools and the information on their site seemed to be unhelpful/unclear.
Going step by step:
Set the value of the listItem variable to the string "item" concatenated with the value of i.
var listItem = "item" + i; // + performs string concatenation
Set the content of the element with an id equal to listItem to the value of the element with the id of toolbox.
document.getElementById(listItem.innerHTML = document.getElementById("toolbox").value;
Set the value of the element with the id of toolbox to an empty string.
document.getElementById("toolbox").value = "";
So the whole function should look like:
function processInput() {
if (i <= 5) {
var listItem = "item" + i;
document.getElementById(listItem.innerHTML = document.getElementById("toolbox").value;
document.getElementById("toolbox").value = "";
}
}
I don't know what's your goal behind this but that's how it's done.
remember that "i" will stay the same because you're not incrementing it
just study more javascript and i hope this helps you buddy
<script type="text/javascript">
var i = 1;
var listItem = "";
var listItemElement = document.getElementById("listItem");
var toolbox = document.getElementById("toolbox");
processInput();
function processInput() {
if (i <= 5) {
listItem = "item " + i;
listItemElement.innerHTML = toolbox.innerHTML;
toolbox.innerHTML = "";
}
}
I think I can explain this properly. I have a function that I want to call with an onclick event on several divs.
$scope.dataArray = []; //array for holding values from another function
$scope.myFunction = function(id) {
var val1 = id[0];
var val2 = id[1];
}
And I want to assign this function to an onclick on divs that I append to a parent inside this function.
$scope.appendDivs = function (someData) {
var result = someData; // an array
var parentContainer = document.getElementById('parent-container');
for( var i = 0; i < result.length; i++)
{
var div = document.createElement('div');
div.className = "child-element";
parentContainer.appendChild(div);
div.onclick = function() {
$scope.myFunction(result.id); //pass an array of data to myFunction
};
div.innerHTML = result[i].data1 + "<br>" + result[i].data2;
}
The problem lies in when I click the div to activate the onclick call and I debug to see what's going on, $scope.myFunction always gets passed the length of "result" where nothing is defined at. i.e. a length of 3 has elements 0, 1 and 2. myFunction tries to look at results[3]. Is there a way I can have each div know which element to pass to myFunction?
I was able to get around my problem by piggybacking my value onto div.id. I don't need the id of the div for anything, and I was able to get rid of the dataArray as well. So now I can just pass the value I need into myFunction and it's the corresponding value to the div that is clicked. Thanks for your time though guys!
I have an array of class names that I want to search a page for. Then I'd like to find all those elements, grab the text inside, and append it to a div.
var div = document.createElement('div');
div.innerHTML = 'List of names from this page';
document.body.appendChild(div);
var classNameArray = ['user', 'username', 'fullname', 'profile-field', 'author', 'screen-name'];
for (var i = 0; i < classNameArray.length; i++) {
element = classNameArray[i];
getSuggestedAuthors(element);
function getSuggestedAuthors(element) {
var classes = document.getElementsByClassName(element);
var index;
for (var index = 0; index < classes.length; index++) {
var class = classes[index];
var textInsideClass = class.innerHTML;
div.appendChild(textInsideClass);
}
}
}
When I run this, it gives me:
Uncaught NotFoundError: An attempt was made to reference a Node in a context where it does not exist.
I believe the problem is occuring at var textInsideClass = class.innerHTML, because when I remove that, it simply grabs all the classes and appends them to the div. However, I'd like to only get the text inside the class.
Anyone know how to do this without jQuery? I'm injected this hs through Google Chrome's executeScript injection.
Thanks so much!
I think your issue is that appendChild only works with nodes. You might be better off just appending to innerHTML using something along the lines of a.innerHTML += f.innerHTML.
You should also be sure to move the getSuggestedAuthors function out of the loop. It works ok as it is, but it's much better form not to declare functions inside a loop.
If you only need to support chrome then all of the handy methods on the Array.prototype should exist :)
var a = document.createElement('div');
a.innerHTML = 'List of names from this page';
document.body.appendChild(a);
function getSuggestedAuthors(elements) {
for (var d = 0; d < elements.length; d++) {
a.appendChild(document.createTextNode(elements[d].innerText));//append loop items text to a
}
}
['user', 'username', 'fullname', 'profile-field', 'author', 'screen-name'].map(function(cls) {
return document.getElementsByClassName(cls);
}).forEach(getSuggestedAuthors);