I have a function which creates new elements in a for loop. For example, I want a div for every item in an array. But I need the ID of the created html div-tag to trigger another function.
This is what I currently got:
function change() {
for (let i = 0; i <= 2; i++) {
let modal = document.createElement('div');
let a = '<div id="id'+i+'"> innerHTML </div>';
modal.innerHTML = a;
// document.getElementById(a.this.id).innerHTML = "get by id";
document.getElementById('test').appendChild(
modal
);
}
}
<div class="test" id="test">test</div>
<button onclick="change()">Change</button>
I need to get the id of every div which is created onclick.
I tried to to like document.getElementById('id' + i).innerHTML = "do something"; but this doesnt work. Someone have a solution for my problem? jQuery is also an option!
You can only use document.getElementById after the element has been added to the DOM.
//...
document.getElementById('test').appendChild(modal);
document.getElementById('id' + i).innerHTML = "get by id";
//...
Related
I am learning javascript, and i am trying to get accses to a button that is created dynamically within a function. The first function createHtml just gets data and creates elements and store them in a variable that i add to the html element and store them in the beerContainer, and that works. I cant however accses the button that is created in the function createHtml. How can i get the alert to pop up when im clicking on saveBeer?
let btn = document.querySelector('#myBtn');
let beerContainer = document.querySelector('#beer-data');
function createHtml(result) {
var html = '';
for(let i = 0; i < result.data.length; i++) {
html += "<h3>"+ result.data[i].name +"</h3>"
html += "<p>"+ result.data[i].description +"</p>"
html += "<button id='save-beer' data-id='"+ result.data[i].id+"'>Save Beer</button>"
}
beerContainer.innerHTML = html;
}
btn.addEventListener('click', function(event) {
fetchApiData(createHtml);
});
var saveBeer = document.querySelector('.save-beer');
saveBeer.addEventListener('click', function(event) {
alert("Hi");
});
try using
var saveBeer = document.querySelector('#save-beer'); // access by id
rather than
var saveBeer = document.querySelector('.save-beer'); // trying to access by class which does not exist
Note the '#' rather than '.' in the querySelector argument
I have such code:
var pageCount = 5; //for example, doesn't really matter
var paginationList = document.createElement("ul");
paginationList.className = "pagination";
for(var i = 1; i <= pageCount; i++){
var paginationNode = document.createElement("li");
var paginationLink = document.createElement("a");
paginationLink.innerHTML = i;
paginationLink.href = "#";
paginationLink.onclick = function(){ console.log("yay"); }; //removed loadProperties here
paginationNode.appendChild(paginationLink);
paginationList.appendChild(paginationNode);
}
divxml.innerHTML = "";
divxml.appendChild(paginationList);
//code replaced by this comment inserts a lot of content to divxml
//for this bug or something to work, you need next line
divxml.innerHTML += "<br>";
divxml.appendChild(paginationList);
As you can see, I'm doing pagination here. The problem is that first pagination buttons don't work, I can't see yay in console when I click on them, but the second and last ones do work (I see yay in console when I click on them). What's wrong, How do I fix that?
You will have to create two list elements and two sets of list item elements for this to work:
var pageCount = 5; //for example, doesn't really matter
var paginationList1 = document.createElement("ul");
var paginationList2 = document.createElement("ul");
paginationList1.className = paginationList2.className = "pagination";
for(var i = 1; i <= pageCount; i++){
paginationList1.appendChild(createPaginationLink(i));
paginationList2.appendChild(createPaginationLink(i));
}
document.body.appendChild(paginationList1);
document.body.appendChild(document.createElement("br"));
document.body.appendChild(paginationList2);
function createPaginationLink(text) {
var paginationNode = document.createElement("li");
var paginationLink = document.createElement("a");
paginationLink.innerText = text;
paginationLink.href = "#";
paginationLink.addEventListener("click", function(){ console.log("yay"); }); //removed loadProperties here
paginationNode.appendChild(paginationLink);
return paginationNode;
}
And as stated in the other answer, mutating innerHTML will cause your elements to be re-created without their event listeners, so instead create and append your <br/> element using createElement and appendChild.
Codepen
divxml.innerHTML += "<br>";
Reading from innerHTML converts the DOM into HTML. The HTML does not have the event handlers that were attached to the DOM.
Writing the HTML back to the innerHTML (after appending <br> to it) converts the HTML to DOM and overwrites the DOM that was there before.
You have now destroyed the event handlers.
Don't use innerHTML.
What i want it to do is add an additional div every time the add button is clicked. what happens instead is it adds it once and then never runs through the code again. I have tried printing out the count and it increments once and never populates again. If i delete the code about inserting the div the count increments every time the button is clicked. What am i missing here?
var count = 0;
button.onclick = function()
{
popup.document.body.innerHTML += '<div id="queryPart-'+ count+'"></div>';
count = count + 1;
};
here is the whole code block
var popup = open("", "Popup", "width=600,height=200,top=600,left=200");
//var div = popup.document.createElement("DIV");
//div.id = "div";
popup.document.body.innerHTML += '<div id="queryPart-0"></div>';
var div = popup.document.getElementById("queryPart-0");
queryLine(div);
var button = popup.document.createElement("BUTTON");
var t = popup.document.createTextNode("ADD");
button.id = "addbutton";
button.onclick = function()
{
popup.document.body.innerHTML += '<div id="queryPart-'+ count+'"></div>';
count= count + 1;
};
button.appendChild(t);
div.appendChild(button);
You should use Node.appendChild() instead because DOM manipulation is a better approach. You only want to add to the existing document, without obstructing or disturbing other elements. By appending directly to the HTML of the body, you are disassociating the original button with the click handler.
Googling this issue returns many helpful resources:
https://www.google.com/#q=innerhtml+removes+listener
After a bit on redirecting, I found one of the first questions related to this issue, here on Stack Overflow:
Is it possible to append to innerHTML without destroying descendants' onclick functions?
Broken
var button = document.getElementById('addBtn');
var count = 0;
button.onclick = function() {
console.log('click');
document.body.innerHTML += '<div class="queryPart-'+ count+'">' + count + '</div>';
count++;
};
<input type="button" id="addBtn" value="Press Me" />
Corrected
var button = document.getElementById('addBtn');
var count = 0;
button.onclick = function() {
var queryDiv = document.createElement('DIV');
queryDiv.className = 'queryPart-' + count;
queryDiv.innerHTML = count;
document.body.appendChild(queryDiv);
count++;
};
<input type="button" id="addBtn" value="Press Me" />
You could also...
set the outerHTML of a div, so that you don't have to create the Element as you see in the above example.
var button = document.getElementById('addBtn');
var count = 0;
button.onclick = function() {
var queryDiv = document.createElement('DIV');
document.body.appendChild(queryDiv);
queryDiv.outerHTML = '<div class="queryPart-'+ count+'">' + count + '</div>';
count++;
};
<input type="button" id="addBtn" value="Press Me" />
This is happening because of the way innerHTML works.
(get) .innerHTML -> "Enumerate all of the elements in this DOM into "HTML" format, and return it as a string"
(set) .innerHTML = -> "Destroy all elements in this DOM, and then create new ones using the HTML that has been provided."
You're destroying your button, and its event listener, during the set operation. You'll likely want to create your button using a more manual method, like document.createElement, and then append it using myElement.appendChild. These operations are pretty common, so I don't think it would make sense to give a full tutorial here - this could also be easier with a framework like JQuery, which has many methods for adding new DOM elements.
Looks like you messed up the order of the
" and '
try:
var count = 0;
button.onclick = function()
{
popup.document.body.innerHTML += '<div id="queryPart-'+ count + '"></div>';
count = count + 1;
};
I'm having some trouble with jQuery in Meteor - I'm just trying to learn so I hope someone could help.
So when #addButton is clicked it will append the div to the .formField and each div created on click will have an unique class, eg formField[1], formField[2] etc
The trouble is when the button is clicked instead of just changing the name of the div only, the div is also added 50 times. I know how dumb it sounds as its a loop, but how would I loop only the div's class on click so each have a different name?
My code is below:
Template.form.events({
'click #addButton': function(event) {
var i;
for (i = 0; i < 50; i++) {
$(".formField").append('<div class="formField['+i+']">.....</div>');
}
return false;
If I understand what you are doing here you don't need a loop. You just need a variable to increment every time the button is clicked. Take your append out of the loop and instead on click increment your variable by one then call an append. No loop necessary.
var i = 0;
Template.form.events({
'click #addButton': function(event) {
i += 1;
$(".formField").append('<div class="formField['+i+']">.....</div>');
}
});
return false;
Do it like this, (i.e. by creating a closure), click run to verify
var uuid = 0;
$('#addButton').on('click', function (event) {
uuid = uuid + 1;
$(".formField").append('<div class="formField[' + uuid + ']">Form' + uuid + '</div>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="formField"></div>
<input type="button" value="Add New" id="addButton"></input>
Is this possible? Or is there a way to tack on and ID to an existing div?
This is my code. I can't get the code to work using classes, but I found when I used getElementById and changed the div to an ID, that it did. But I have a ton of already posted stuff so it would take forever to go through all those posts and change it manually to an ID.
Can I incorperate JQuery in this and still have it work? I tried that with something I stumbled across but it didn't work so I removed it. I don't remember what it is now though. :S
<div id="imdb" class="imdb">tt2382396</div>
<script>
function imdbdiv() {
var imdbmain = "http://www.imdb.com/title/";
var end = "/#overview-top";
var idnum = document.getElementsByClassName("imdb");
var newdiv = document.createElement("div");
var done = "<a href='" + imdbmain + idnum + end + "'>IMDB</a>";
newdiv.innerHTML = done;
document.body.appendChild(newdiv);
}
window.onload = imdbdiv();
</script>
Can anyone help. I cannot for the life of me figure this out.
JsFiddle
Your problem was, you were appending the collection returned by document.getElementsByClassName instead of looping through the elements in the collection. You can verify this by looking at the href property of the link in your jsFiddle. You must loop through the values, then access the data in their innerHTML property.
You can use document.querySelectorAll to get a list of all elements matching a certain CSS selector, in your case .imdb. This is more flexible, in case you want to select elements with more than one class. I've pasted the code from the updated jsFiddle below.
function imdbdiv() {
var imdbMain = "http://www.imdb.com/title/",
end = "/#overview-top",
imdbValueDivs = document.querySelectorAll('.imdb'),
length = imdbValueDivs.length,
// Iterator values
i,
newDiv,
newLink;
// Loop over all of your link value containers
for (i = 0; i < length; i++) {
// Create the container
newDiv = document.createElement('div');
// Create the new link
newLink = document.createElement('a');
newLink.href = imdbMain + imdbValueDivs[i].innerHTML + end;
newLink.innerHTML = "My favorite film";
// Add the link to the container,
// and add the container to the body
newDiv.appendChild(newLink);
document.body.appendChild(newDiv);
}
}
window.onload = imdbdiv();
If you have many such divs on your page, then it could be like this:
<div class="imdb">tt2382396</div>
<div class="imdb">tt2382396</div>
<div class="imdb">tt2382396</div>
<script>
function imdbdiv() {
var imdbmain = "http://www.imdb.com/title/";
var end = "/#overview-top";
var idnums = document.getElementsByClassName("imdb");
for (var i =0; i < idnums.length; i++) {
var newdiv = document.createElement("div");
var done = "<a href='" + imdbmain + idnums[i].innerText + end + "'>IMDB</a>";
newdiv.innerHTML = done;
document.body.appendChild(newdiv);
}
}
window.onload = imdbdiv();
</script>
See jsfiddle
UPDATE:
The following string was incorrect:
window.onload = imdbdiv;
Okay, so your question is a little bit unclear.
The way I understood your question is that you have a whole bunch of div elements with class attribute and what you want is to simply copy the class value to the id attribute of the div elements.
If that's correct then try something like this with jquery:
<script>
$(document).ready(function(){
$(".imdb").each(function(imdbDiv){
var classValue = imdbDiv.attr("class");
imdbDiv.attr("id", classValue);
});
});
</script>