The first part of the code is working correctly, but now that each button appears, how do i add functionality to each of them? currently the only button which does something when pressed is always the last one, the rest do nothing.
Change it to
{
var output = "";
var data = JSON.parse(e.target.responseText);
for(var i=0; i<data.length; i++)
{
output = data[i].title + ' ';
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
button.innerHTML = "Download";
p.appendChild(button);
div.appendChild(p);
button.addEventListener ("click", () =>
{
alert("Test");
});
}
}
You are adding the below code out side the for loop
button.addEventListener ("click", () =>
{
alert("Test");
} );
Keep the above code inside the for loop. So that for each button the event listener will be added.
Another way to approach this would be to add the callback function to the onclick variable of the elements prototype:
function doStuff() {
var output = "";
var data = JSON.parse(e.target.responseText);
for (var i = 0; i < data.length; i++) {
output = data[i].title + ' ';
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
button.innerHTML = "Download";
// Adds the callback function here
button.onclick = () => {
// fill in your arrow function here...
alert("Test");
};
p.appendChild(button);
div.appendChild(p);
};
}
doStuff();
Here is a jsFiddle
You should use event delegation for dynamically added elements
// sample data
var data = [{
title: 'one'
}, {
title: 'two'
},{
title: 'three'
}];
var output = "";
for (var i = 0; i < data.length; i++) {
var output = data[i].title + " ";
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
// added output to button text for identification
button.innerHTML = output + " Download";
p.appendChild(button);
div.appendChild(p);
}
// Get the parent element, add a click listener
document.getElementById("response").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was a button
if (e.target && e.target.nodeName == "BUTTON") {
// Button found! Output the identifying data!
// do other work on click
document.getElementById("display").innerHTML = e.target.innerHTML + " Clicked";
}
});
<div id="response"></div>
<div id="display">Display</div>
Related
I am trying to change the css property of the "node"-class by clicking on the div inside of it which got the class "expand".
When I click on the "expand" div inside the "note", I want to go to parent "note" for changing it size:
var text = document.getElementById("text");
var add = document.getElementById("add");
var notespace = document.getElementById("notespace");
var expand = document.getElementsByClassName("expand");
var notes = document.getElementsByClassName("note");
add.addEventListener("click", function () {
var textValue = text.value;
var p = document.createElement("p");
p.innerHTML = "<div class='note'>" + textValue +
"<br/><br/><div class='expand'> Expand </div></div>";
notespace.appendChild(p);
text.value = "";
for (var i = 0; i < expand.length; i++) {
expand[i].addEventListener("click", function () {
notes[i].style.size = "3000px";
})
}
})
You have to re-get the values of expand and notes, because after you add them to your html, the two variables expand and notes, dont know yet that you have added them and they don't contain them. ( you also have to removee the eventlistner otherwise you're gonna get a bugg at approximately twelve notes added :D because you will have too many eventListners on each element
var text = document.getElementById("text");
var add = document.getElementById("add");
var notespace = document.getElementById("notespace");
var expand = document.getElementsByClassName("expand");
var notes = document.getElementsByClassName("note");
add.addEventListener("click", function(){
var textValue = text.value;
var p = document.createElement("p");
p.innerHTML = "<div class='note'>" + textValue + "<br/><br/><div class='expand'> Expand </div></div>";
notespace.appendChild(p);
text.value = "";
for( var i = 0; i < expand.length; i++){
const note = notes[i];
expand[i].addEventListener("click", function() {
note.style.size = "3000px";
note.style.backgroundColor = "red";
});
}
})
#notespace {
width: 100%,
height: 100%,
background: grey,
}
<button type="button" id="add">add</button>
<input id="text"/>
<div id="notespace">
</div>
You can use the parentNode attribute :
for( var i = 0; i < expand.length; i++){
expand[i].addEventListener("click", function(){
this.parentNode.style.size = "3000px";
})
}
Or the closest() method :
for( var i = 0; i < expand.length; i++){
expand[i].addEventListener("click", function(){
this.closest(".note").style.size = "3000px";
})
}
Note that closest() is not supported on IE.
With a loop, I´m creating some inputs and buttons. One button is a remove button. If I press the remove button, I want to remove all inputs and buttons with that loop.
So e.g. if I press the third remove button, all of the created elements in the third loop run should be removed.
My function for that button isn´t working. Can someone help me out and tell/show me what I have to change in my code in order for it to work?
Thank you and Kind Regards
This is a part of my code:
for(var i = 0; i < arrayinput.length; i++){
// example input
var myParent1 = InputContainer;
var numberfield = document.createElement("input");
numberfield.setAttribute('class','InputNew');
numberfield.setAttribute('id','InputNew-' + i);
numberfield.setAttribute('value','0');
myParent1.appendChild(numberfield);
//example button
var myParent2 = AddContainer;
var addierenButton = document.createElement("button");
addierenButton.setAttribute('class','addButton');
addierenButton.textContent = "+";
addierenButton.id = "add_btn_" + i;
addierenButton.setAttribute('onclick','add(this)');
myParent.appendChild(addButton);
//remove button
var myParent3 = RemoveContainer;
var removeButton = document.createElement("button");
removeButton.setAttribute('class','removeButton');
removeButton.id = "remove_btn_" + i;
removeButton.textContent = "X";
removeButton.setAttribute('onclick','remove(this)');
myParent3.appendChild(removeButton);
};
function remove(btn){
const num = btn.id.replace("remove_btn_", "");
var delInput= document.getElementById("InputNew-" + num);
var delAdd= document.getElementById("add_btn_" + num);
var delRemove= document.getElementById("remove_btn_" + num);
delInput.remove();
delAdd.remove();
delRemove.remove();
};
The code logic is good but you had a few syntax errors.
Try the following snippet
const arrayinput = [0, 1, 2];
window.onload = (event) => {
for(var i = 0; i < arrayinput.length; i++){
// example input
var myParent1 = document.getElementById('root');
var numberfield = document.createElement("input");
numberfield.setAttribute('class','InputNew');
numberfield.setAttribute('id','InputNew-' + i);
numberfield.setAttribute('value','0');
myParent1.appendChild(numberfield);
//example button
var myParent2 = document.getElementById('root');
var addButton = document.createElement("button");
addButton.setAttribute('class','addButton');
addButton.textContent = "+";
addButton.id = "add_btn_" + i;
addButton.setAttribute('onclick','add(this)');
myParent2.appendChild(addButton);
//remove button
var myParent3 = document.getElementById('root');
var removeButton = document.createElement("button");
removeButton.setAttribute('class','removeButton');
removeButton.id = "remove_btn_" + i;
removeButton.textContent = "X";
removeButton.setAttribute('onclick','remove(this)');
myParent3.appendChild(removeButton);
}
}
function remove(btn){
const num = btn.id.replace("remove_btn_", "");
var delInput= document.getElementById("InputNew-" + num);
var delAdd= document.getElementById("add_btn_" + num);
var delRemove= document.getElementById("remove_btn_" + num);
delInput.remove();
delAdd.remove();
delRemove.remove();
}
<div id="root"></div>
I used this code:
var list = was_talkWindows.querySelectorAll('.msg:not(.was_added)');
var i;
for (i = 0; i < list.length; i++)
{
list[i].className += cssClass;
var btn = document.createElement('button');
btn.setAttribute('type', 'button');
btn.setAttribute('class', 'was_addButton');
btn.addEventListener('click', function() {
was_button_act(this.parentElement);
});
btn.innerHTML = buttonName;
list[i].appendChild(btn);
}
however, friend told me that .msg:not(.was_added) is too slow, so doing it in the opposite way:
var cssClass = ' was_added';
var buttonName = 'start waiting';
if (was_set_standby_auto == true)
{
cssClass += ' was_standby';
buttonName = 'cancel';
}
try {
var currectMSG = was_talkWindows.querySelector('.msg:last-child');
while (currectMSG.classList.contains('was_added') == false)
{
currectMSG.className += cssClass;
var btn = document.createElement('button');
btn.setAttribute('type', 'button');
btn.setAttribute('class', 'was_addButton');
btn.addEventListener('click', function() {
was_button_act(this.parentElement);
});
btn.innerHTML = buttonName;
currectMSG.appendChild(btn);
currectMSG = currectMSG.previousElementSibling;
}
} catch (err) {}
but the code add the button twice each time for the last one.
not really understand this behavor.
Use previousElementSibling instead of previousSibling, so that it skips over text nodes.
And add the was_added class to the element so it won't be processed again later.
var was_talkWindows = document;
var cssClass = " newclass";
var buttonName = "Click me";
try {
var currectMSG = was_talkWindows.querySelectorAll('.msg:last-child')[0];
while (currectMSG.classList.contains('was_added') == false) {
currectMSG.className += cssClass;
currectMSG.classList.add('was_added');
var btn = document.createElement('button');
btn.setAttribute('type', 'button');
btn.setAttribute('class', 'was_addButton');
btn.addEventListener('click', function() {
was_button_act(this.parentElement);
});
btn.innerHTML = buttonName;
currectMSG.appendChild(btn);
currectMSG = currectMSG.previousElementSibling;
}
} catch (err) {}
<ol>
<li class="msg was_added">Text</li>
<li class="msg was_added">Text</li>
<li class="msg">Text</li>
<li class="msg">Text</li>
<li class="msg">Text</li>
</ol>
The problem with a site that is not under your control, it does not always know what is running, and it took me a long time to realize that the problem is not adding buttons twice (against logic), but anyone who does not I edit the code at the same time.
so declare just once:
var was_msgList = was_talkWindows.getElementsByClassName('msg');
and the loop (every 2 seconds):
for ( var i=was_msgList.length; i-- && was_msgList[i].getAttribute('data-status') == null; )
{
was_load_addButton(was_msgList[i],attStatus,buttonText);
}
any ideas for change are welcome.
I'm creating 3 buttons dynamically. Now I need to add an onclick event. How can I make the onclick work?
var btns='';
var category = ["fur_", "fts_", "fas_"];
for(i = 1; i < category.length; i++){
btns +='<button type="button" class='+category[i]+' id= "myBtn'+i+'">Button</button>';
}
document.getElementById('div').innerHTML = btns;
var button = document.getElementById('myBtn1');
button.addEventListener('click', function () {
alert('Clicked');
}, false);
You can get all the button elements and add the click event handler using a loop
var btns = '';
var category = ["fur_", "fts_", "fas_"];
for (i = 1; i < category.length; i++) {
btns += '<button type="button" class=' + category[i] + ' id= "myBtn' + i + '">.....</button>';
}
var div = document.getElementById('div');
div.innerHTML = btns;
var handler = function () {
alert('Clicked');
};
var buttons = div.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', handler, false);
}
Demo: Fiddle
Another approach is to create a button element in the loop
var div = document.getElementById('div');
var btn;
var category = ["fur_", "fts_", "fas_"];
var handler = function () {
alert('Clicked');
};
for (var i = 1; i < category.length; i++) {
btn = document.createElement('button');
btn.cassName = category[i];
btn.cassName = 'myBtn' + i;
btn.innerHTML = '....';
btn.addEventListener('click', handler, false);
div.appendChild(btn);
}
Demo: Fiddle
So I'm trying to to basically dynamically create li's inside an array, and I would like to create a 'delete' button within each li, so that when I click that li, I can delete that specific li.
I know this seems very basic, but I've been looking at JS for hours now, and am starting to really confuse myself here.
I keep getting errors like addChild() is not a function... I feel like I'm close, but no cigar. Thanks in advance!
Anyway, here's my add function:
function add(){
var deleteBtn = document.createElement('input');
deleteBtn.type = 'submit';
deleteBtn.name = 'addButton';
deleteBtn.className = 'deleteButton';
for(i=0;i<1;i++){
id_number[i] = i+1;
var newSong = '<li class="li_test" id="' + id_number[i] + '">' + "<span>" + "</span>" + '</li>';
// $(newSong).appendChild(deleteBtn);
$(deleteBtn).appendTo("#playlist-1");
$(newSong).appendTo("#playlist-1");
showList.push(newSong);
deleteBtn.addEventListener('click', function(evt) {
deleteFromPlaylist(newSong);
});
}
}
Here's my delete function
function deleteFromPlaylist(newSong){
var deleteBtn = document.getElementsByTagName('deleteButton');
// var deleteMe = deleteBtn.parentNode;
alert(deleteBtn);
for(i=0;i<showList.length;i++){
if(newSong === showList[i]){
showList.splice(i,1);
// var pp = p.parentNode;
// pp.removeChild (p);
deleteMe = deleteMe.parentNode.remove("li_test");
deleteMe.removeChild(deleteBtn);
}
// console.log(deleteMe);
}
}
EDIT: 1 More Related Question
I would like to only add an item if it doesn't exist already in the array. Here is what I have so far. Any tips on where I'm going wrong?
for (i = 0; i < showList.length; i++) {
if (newSong !== showList[i]){
ul_list.innerHTML = newSong;
container_div.appendChild(ul_list); //append the info
container_div.appendChild(deleteBtn);
document.getElementById('playlist-1').appendChild(container_div); //finally add it to the playlist div
showList.push(newSong);
deleteBtn.addEventListener('click', function(evt) {
deleteFromPlaylist(evt, newSong);
});
inc++;
alert("It IS in the Array!");
}else{
alert("This already exists!");
}
}
You seem to have a strange mix of code. Forget the jQuery stuff until you know javascript.
> function add(){
> var deleteBtn = document.createElement('input');
> deleteBtn.type = 'submit';
I don't think that's a good idea. Much better to use type button or a button element.
> deleteBtn.name = 'addButton';
> deleteBtn.className = 'deleteButton';
>
> for(i=0;i<1;i++){
Presumably i will go a bit higher in future. ;-)
> id_number[i] = i+1;
Where did id_number come from?
>
> var newSong = '<li class="li_test" id="' + id_number[i] + '">' + "<span>" + "</span>" + '</li>';
> // $(newSong).appendChild(deleteBtn);
Stick to one method of creating elements. Consider using a document fragment to hold the parts.
> $(deleteBtn).appendTo("#playlist-1");
> $(newSong).appendTo("#playlist-1");
> showList.push(newSong);
Where did showList come from?
> deleteBtn.addEventListener('click', function(evt) {
> deleteFromPlaylist(newSong);
> });
Not all browsers support addEventListener. Since you are only adding one listener, consider just assigning to the button's onclick property. Note that newSong is just a string.
> }
> }
In the other function:
> function deleteFromPlaylist(newSong){
> var deleteBtn = document.getElementsByTagName('deleteButton');
There is no HTML "deleteButton" element, so that will return an empty collection.
> // var deleteMe = deleteBtn.parentNode;
> alert(deleteBtn);
> for(i=0;i<showList.length;i++){
> if(newSong === showList[i]){
> showList.splice(i,1);
> // var pp = p.parentNode;
>
> // pp.removeChild (p);
> deleteMe = deleteMe.parentNode.remove("li_test");
Where did deleteMe come from? You commented out where it was declared and it hasn't been assigned a value, so deleteMe.parentNode will throw an error.
> deleteMe.removeChild(deleteBtn);
> }
> // console.log(deleteMe);
> }
> }
> }
Anyhow, here's some working code, it's still pretty awful but I'll leave it to you go improve it.
<script>
var showList = [];
function add(){
var id_number = [];
var deleteBtn = document.createElement('input');
deleteBtn.type = 'button';
deleteBtn.name = 'addButton';
deleteBtn.className = 'deleteButton';
deleteBtn.value = 'Delete Button';
for (i=0; i<1; i++) {
id_number[i] = i + 1;
// '<li class="li_test" id="' + id_number[i] + '">' + "<span>" + "</span>" + '</li>';
var newSong = document.createElement('li');
newSong.className = 'li_test';
newSong.id = id_number[i];
newSong.appendChild(document.createElement('span').appendChild(document.createTextNode('song')));
showList.push(newSong);
deleteBtn.onclick = (function(id) {
return function(){deleteFromPlaylist(id);}
}(newSong.id));
newSong.appendChild(deleteBtn);
document.getElementById('playlist-1').appendChild(newSong);
}
}
function deleteFromPlaylist(id) {
var song = document.getElementById(id);
if (song) {
song.parentNode.removeChild(song);
}
}
window.onload = function() {
add();
}
</script>
<ul id="playlist-1">
<li>Original
</ul>
I've altered your code and functions to purely use javascript, instead of a mixture containg jquery. I've added comments in the code to explain my actions. If you have any questions, feel free to ask.
var showList = [];
var inc = 1;
function add() {
//create the container element. If we do this, keeping track of all elements
//becomes easier, since we just have to remove the container.
var container_div = document.createElement('div');
container_div.id = "cont_" + inc;
var ul_list = document.createElement('ul');
var deleteBtn = document.createElement('input');
deleteBtn.type = 'button';
deleteBtn.value = 'remove song';
deleteBtn.name = 'addButton';
deleteBtn.className = 'deleteButton';
var id_number = [];
var newSong = "";
for (i = 0; i < 1; i++) {
id_number[i] = i + 1;
newSong += '<li class="li_test" id="cont_' + inc + '_song_id_' + id_number[i] + '">' + "<span>test " + inc + "</span>" + '</li>\n'; //all ids must be unique, so we construct it here
}
ul_list.innerHTML = newSong;
container_div.appendChild(ul_list); //append the info
container_div.appendChild(deleteBtn);
document.getElementById('playlist-1').appendChild(container_div); //finally add it to the playlist div
showList.push(newSong);
deleteBtn.addEventListener('click', function(evt) {
deleteFromPlaylist(evt, newSong);
});
inc++;
}
function deleteFromPlaylist(evt, newSong) {
var deleteBtn = evt.target; //target the button clicked, instead of a list of all buttons
var container_div = deleteBtn.parentNode; //get the parent div of the button
var cont_parent = container_div.parentNode; //and the parent of the container div
for (i = 0; i < showList.length; i++) {
if (newSong === showList[i]) {
showList.splice(i, 1);
}
}
cont_parent.removeChild(container_div); //finally, remove the container from the parent
}
Update:
I've modified the above function to strictly use objects, rather than strings, because it is easier to extract relevant information from objects, than strings.
I've added in comments to assist with understanding the code. Again, if you have any questions, feel free to ask.
function add() {
var list_bool;
//create the container element. If we do this, keeping track of all elements
//becomes easier, since we just have to remove the container.
var container_div = document.createElement('div');
container_div.id = "cont_" + inc;
var ul_list = document.createElement('ul');
var deleteBtn = document.createElement('input');
deleteBtn.type = 'button';
deleteBtn.value = 'remove song';
deleteBtn.name = 'addButton';
deleteBtn.className = 'deleteButton';
var list_item = document.createElement("li"); //create list element
list_item.className = "li_test"; //set element class
var list_span = document.createElement("span"); //create span element
list_span.innerHTML = "test"; //set span text
list_item.appendChild(list_span); //append span to list element
ul_list.appendChild(list_item); //append list element to un-ordered list element
var list_bool = false; //create local boolean variable
if (showList.length > 0) { // loop through showList if it isn't empty
for (var i = 0; i < showList.length; i++) {
if (showList[i].innerText !== list_item.innerText) {
list_bool = true; //if song exists(comparing text values, set bool to true
} else if (showList[i].innerText === list_item.innerText) {
list_bool = false; //else, set it to false
break; //break out of loop.. we don't want it becoming true again, now do we?
}
}
} else {
list_bool = true; //showList is empty, set to true
}
if (list_bool) { //if true, do action of appending to list
container_div.appendChild(ul_list); //append the info
container_div.appendChild(deleteBtn);
document.getElementById('playlist-1').appendChild(container_div); //finally add it to the playlist div
showList.push(list_item);
deleteBtn.addEventListener('click', function(evt) {
deleteFromPlaylist(evt, newSong);
});
inc++;
}
}
DEMO, notice that add() is executed twice, but because the song 'test' already exists, it only executes the end action once.