Event on created element - javascript

In my to-do-list deleteButton and doneButton work only on premade tasks.
They arent working on created elements li even that created elements are the same as premade. I am trying to use vanila js.
js:
var deleteButton = document.querySelectorAll('.delete');
for(i = 0; i < deleteButton.length; i++){
deleteButton[i].addEventListener('click', function() {
var li = this.parentNode;
li.classList.add('li-delete');
})
};
var doneButton = document.querySelectorAll('.done');
for (i = 0; i < doneButton.length; i++)
doneButton[i].addEventListener('click', function(){
if (this.classList.contains('done-green')) {
this.classList.remove('done-green');
} else {
this.classList.add('done-green');
}
});
var add = document.querySelector('.add');
add.addEventListener('click', function(){
var newLi = document.createElement('li');
var input = document.querySelector('input');
var ul = document.querySelector('ul');
var newP = document.createElement('p');
newLi.innerHTML = "<i class='icon-ok done'></i><i class='icon-trash delete'></i>"
newP.appendChild(document.createTextNode(input.value));
newLi.appendChild(newP);
ul.appendChild(newLi);
input.value = null;
})
html:
<div id="buttons">
<input type="text" placeholder="your new task...">
<button type="submit" class="add">add</button>
</div>
<div id="tasks">
<ul>
<li><i class="icon-ok done"></i>
<p>asd</p>
<i class="icon-trash delete"></i></li>
<li><i class="icon-ok done"></i>
<p>asd</p>
<i class="icon-trash delete"></i></li>
<li><i class="icon-ok done"></i>
<p>asd</p>
<i class="icon-trash delete"></i></li>
</ul>
</div>

You must attach listener after creation element.
Or you can attach listener to parent container of elements.
I think this answer can help you Attach event to dynamic elements in javascript

Related

getting null value of button

I am creating a todo app. I create add button which is working perfectly fine. But, the trash button it keeps on returning null value.
I can not find solution on the google i didnt find the solution.
Can Anybody Help me here
var todoList = document.getElementById("todolist");
var addBtn = document.getElementById("add-btn");
var taskName = document.getElementById("task-name");
var trashBtn = document.getElementById("trash");
addBtn.addEventListener("click", addFunction);
function addFunction() {
var task = document.createElement("div");
task.classList.add("task");
var tname = document.createElement("li");
tname.setAttribute("id", "li-task");
var trash = document.createElement("BUTTON");
trash.setAttribute("id", "trash");
trash.innerHTML = '<i class="fas fa-trash"></i>';
tname.appendChild(trash);
task.appendChild(tname);
todoList.appendChild(task);
}
console.log(trashBtn);
console.log(addBtn);
<div class="main">
<header>
<h1>Doer's List</h1>
</header>
<div class="add-task">
<form>
<input type="text" id="task-name">
<button id="add-btn" type="button"><i class="fas fa-plus-circle"></i></button>
</form>
</div>
<div class="to-do-list">
<ul id="todolist"></ul>
</div>
</div>
Help Here
You need to get the Trash Button by id AFTER you've added it to the page.
I instead of creating new variable trashBtn, I used the variable which is define when creating Elemnt.

hide remove button <span> and remove <li> on click JavaScript

I would like to display the title of a task when onclick, it gives me "remove" text(span) as well. I tried to display my task without remove when a user clicks on each list... but it wont work..
I also want to remove each list when a user clicks on the remove button.. Can you give me some tips? I have tried multiple ways.. but it wont work :(
I have attached the image of my to do list app.
I appreciate it in advance!
var title = document.getElementById('title');
var list = document.getElementById('list');
var li = list.getElementsByTagName('li');
var addBtn = document.getElementById('add-btn');
var i;
var span = document.getElementsByTagName('span');
var listspan = document.getElementById('list-span');
list.addEventListener('click', activeItem);
function activeItem(event) {
if (event.target.nodeName == 'LI') {
document.getElementById("list-span").style.visibility = "";
title.innerHTML = event.target.innerText;
for (var i = 0; i < event.target.parentNode.children.length; i++) {
event.target.parentNode.children[i].removeAttribute('class');
}
event.target.setAttribute('class', 'active');
}
}
addBtn.addEventListener('click', function() {
var txt = prompt('add task');
list.innerHTML += '<li>' + txt + '<span>' + "REMOVE" + '</span>' + '</li>';
list.addEventListener('click', activeItem);
});
<section class="container">
<div class="header-div">
<h1 id='title'>ADD A TASK</h1>
</div>
<div class="button-div">
<button id="add-btn">ADD A TASK</button>
</div>
<div class="list-div">
<ul id='list'>
<li>Walk my dog<span id="list-span">remove</span></li>
<li>Go grocery shopping<span id="list-span">remove</span></li>
<li>Call mom<span id="list-span">remove</span></li>
<li>Do laundry<span id="list-span">remove</span></li>
<li>Call Jane<span id="list-span">remove</span></li>
<li>Eat lunch<span id="list-span">remove</span></li>
</ul>
</div>
</section>

Stuck with JS DOM Manipulation

I am stuck with this simple JS DOM manipulation.
Following is my HTML markup. I am trying to dynamically generate the individual list items with JS.
My issue: Each individual Span tag should contain an individual item from an array of objects but in my case, one span tag is containing all elements. How can I get it to work? I know this must be something very simple but I have not been able to figure out where am I wrong here?
HTML CODE:
<ul class="collection" id="web-book-list">
<li class="collection-item">
<span class="flow-text">item 1</span>
<a href="#!" class="secondary-content"
><i class="small material-icons black-text">visibility</i></a
>
<a href="#!" class="secondary-content"
><i class="small material-icons red-text">delete_forever</i></a
>
</li>
<li class="collection-item">
<span class="flow-text">item 2</span>
<a href="#!" class="secondary-content"
><i class="small material-icons black-text">visibility</i></a
>
<a href="#!" class="secondary-content"
><i class="small material-icons red-text">delete_forever</i></a
>
</li>
</ul>
JS CODE:
let bookList = document.getElementById("web-book-list");
// Create element
let li = document.createElement("li");
let span = document.createElement("span");
let linkA = document.createElement("a");
let linkB = document.createElement("a");
let visible = document.createElement("i");
let deleteBtn = document.createElement("i");
// Add classes to elements
li.className = "collection-item";
span.className = "flow-text";
linkA.className = "secondary-content";
linkB.className = "secondary-content";
visible.className = "small material-icons black-text";
deleteBtn.className = "small material-icons red-text";
// create text nodes
visible.appendChild(document.createTextNode("visibility"));
deleteBtn.appendChild(document.createTextNode("delete_forever"));
linkA.appendChild(visible);
linkB.appendChild(deleteBtn);
//Loop through the webBooks
for (let i = 0; i < webBooks.length; i++) {
console.log(webBooks[i]);
span.innerHTML += webBooks[i].name; // Problem is here!
li.appendChild(span);
li.appendChild(linkA);
li.appendChild(linkB);
bookList.appendChild(li);
}
console.log(bookList);
Remove the += and to append use bookList.appendChild(li.cloneNode(true));
var bookList = document.getElementById("web-book-list");
// Create element
var li = document.createElement("li");
var span = document.createElement("span");
var linkA = document.createElement("a");
var linkB = document.createElement("a");
var visible = document.createElement("i");
var deleteBtn = document.createElement("i");
// Add classes to elements
li.className = "collection-item";
span.className = "flow-text";
linkA.className = "secondary-content";
linkB.className = "secondary-content";
linkA.href = "#0";
linkB.href = "#0";
visible.className = "small material-icons black-text";
deleteBtn.className = "small material-icons red-text";
// create text nodes
visible.appendChild(document.createTextNode("visibility "));
deleteBtn.appendChild(document.createTextNode("delete_forever"));
linkA.appendChild(visible);
linkB.appendChild(deleteBtn);
//Loop through the webBooks
for (let i = 0; i < 10; i++) {
span.innerHTML = "test"+i+ " "; // Problem is here!
li.appendChild(span);
li.appendChild(linkA);
li.appendChild(linkB);
bookList.appendChild(li.cloneNode(true));
}
<ul class="collection" id="web-book-list">
<li class="collection-item">
<span class="flow-text">item 1</span>
<a href="#!" class="secondary-content"
><i class="small material-icons black-text">visibility</i></a
>
<a href="#!" class="secondary-content"
><i class="small material-icons red-text">delete_forever</i></a
>
</li>
<li class="collection-item">
<span class="flow-text">item 2</span>
<a href="#!" class="secondary-content"
><i class="small material-icons black-text">visibility</i></a
>
<a href="#!" class="secondary-content"
><i class="small material-icons red-text">delete_forever</i></a
>
</li>
</ul>
dont forget the href too
linkA.href = "#0";
linkB.href = "#0";
You need to create a span element for each book in the loop. You also need to create lis and links as well. When you use appendChild to append an element that's already elsewhere in the document, it gets moved, not copied.
Since you're setting classes on the elements and such, the easiest way to create individual ones for each iteration of the loop is to use cloneNode:
let bookList = document.getElementById("web-book-list");
// Create element
let li = document.createElement("li");
let span; // *** No need to create one here
let linkA = document.createElement("a");
let linkB = document.createElement("a");
// ...
for (let i = 0; i < webBooks.length; i++) {
console.log(webBooks[i]);
const thisSpan = span.cloneNode(true); // ***
thisSpan.innerHTML = webBooks[i].name; // *** No need for += since we're creating a new span
const thisLi = li.clone(true); // ***
thisLi.appendChild(thisSpan); // ***
thisLi.appendChild(linkA.cloneNode(true)); // ***
thisLi.appendChild(linkB.cloneNode(true)); // ***
bookList.appendChild(thisLi); // ***
}
I also suggest not treating text as HTML, which you're doing here:
thisSpan.innerHTML = webBooks[i].name;
If that name has < in it (or even malicious script content), it would be a problem to treat it as HTML. Instead:
thisSpan.appendChild(document.createTextNode(webBooks[i].name));

How to remove added item from a list?

I'm trying to learn JS and I decided to make a real app so that I can learn while I'm doing some stuff. I'm trying to make a TODO list app, I made the adding items but I can't figure out how to remove items when they got clicked.
Here's the code iteself:
MY TODO'S
<input id= "input" class="form-control" placeholder="Add items to your TODO list." type="text">
<button id="button" class="button btn btn-primary btn-block">Add</button>
<div class="items">
<ul id= "listGroup" class="list-group">
</ul>
</div> <!-- JS Items !-->
</div> <!-- End Div -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<script src="app.js"></script>
JS:
var button1 = document.getElementById("button")
button1.addEventListener("click", addItem)
function addItem() {
let item = document.getElementById("input").value
let add = document.getElementById("listGroup")
let makeLi = document.createElement("li")
let makeText = document.createTextNode(item)
makeLi.className += "list-group-item"
let icon = document.createElement("i")
icon.className += "fa fa-times"
add.appendChild(makeLi).appendChild(makeText)
}
function revomeItem() {
}
var div1 = document.getElementById("div-01")
div1.addEventListener("click", removeItem);
function removeItem(e){
e.target.remove();
}
This should work..
makeLi.onclick = function(){
this.remove();
};

Add new element into DOM with JavaScript

I am struggling with adding new "button" element into my "list". I was trying to append or someting els but doesn't work. It is not usual ul to li. If you ask why button parent it is form bootstrap list-group
UPDATE JS. IT is now adding "button but not corectlly.
<div class="list-group">
<button type="button" class="list-group-item">
<ul class="desc">
<li class="t-desc50">Add Device</li>
<li class="t-desc55"><i class="fa fa-plus fa-2x" aria-hidden="true"></i></li>
</ul>
</button>
<button type="button" class="list-group-item" id="new-item>
<ul class="desc">
<li class="t-desc">Lamp</li>
<li class="t-desc2">5 kwH</li>
<li class="t-desc3"><label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label></li>
</ul>
</button>
<button type="button" class="list-group-item" id="new-item>
<ul class="desc">
<li class="t-desc">AC</li>
<li class="t-desc2">5 kwH</li>
<li class="t-desc3"><label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label></li>
</ul>
</button>
</div>
JS
document.querySelector('.fa-plus').addEventListener('click', addItem
);
function addItem() {
var list = document.getElementById("list-group");
var li = document.createElement("button");
li.setAttribute('id', li);
li.appendChild(document.createTextNode(li));
list.appendChild(li);
}
If you want to add an element to the dom, you can use :
var element = document.createElement(tagName);
https://developer.mozilla.org/fr/docs/Web/API/Document/createElement
Then append your element.
You can add event listener to element, and add class before if you need.
Comment answer
The code you need is probably something like that :
function addItem() {
var list = document.getElementById('list-group')
//Button
var button = document.createElement('button');
button.classList.add("list-group-item");
//Ul
var ul = document.createElement('ul');
ul.classList.add("desc");
//li
var liFirst = document.createElement('li');
var liSecond = document.createElement('li');
var liThird = document.createElement('li');
liFirst.innerHTML = "Lamp"
liSecond.innerHTML = "5 kwH"
//Label
var label = document.createElement('label');
label.classList.add("switch");
var input = document.createElement('input');
input.type = 'checkbox';
var span = document.createElement('span');
span.classList.add("slider");
span.classList.add("round");
label.append(input)
label.append(span)
liThird.append(label)
ul.append(liFirst)
ul.append(liSecond)
ul.append(liThird)
button.append(ul)
list.append(button)
}
You need to pass the function as argument instead of calling it:
// wrong:
document.querySelector('.fa-plus').addEventListener('click', addElement());
// right:
document.querySelector('.fa-plus').addEventListener('click', addElement);
addEventListener expects a callback function, if you call the function first, you are sending the result of the function as argument, which is wrong.
You need to pass the addElement function instead, so the addEventListener calls it.
got it!
function addItem() {
var list = document.getElementById('list-group')
var button = document.createElement('button');
var ul = document.createElement('ul');
var liFirst = document.createElement('li');
var liSecond = document.createElement('li');
var liThird = document.createElement('li');
button.classList.add("list-group-item");
ul.classList.add("desc");
liFirst.classList.add("t-desc")
liSecond.classList.add("t-desc2")
liThird.classList.add("t-desc3")
liFirst.innerText = 'TV'
liSecond.innerText = '5kwh'
liThird.innerHTML = `<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>`
ul.append(liFirst)
ul.append(liSecond)
ul.append(liThird)
button.append(ul)
list.append(button)
}
There are several semantic errors in both the markup and the code. Firstly, <button type="button" class="list-group-item" id="new-item> misses the closing double quotes. Secondly, one should not use an id twice as the OP's example does with id="new-item. At third addEventListener misses its 3rd argument.
Besides that it will be hard if not impossible to capture any click event on the fa-plus classified <i/> element; one should use the whole button instead ... that's what a button is for.
Additionally one might rethink how to retrieve/query the structure one wants to add the new element to. I would suggest a more generic approach that retrieves the top most group parent from within the structure where the click event did occur, thus one can make use of more than just on list-group classified element.
Having sanitized the code the OP'S given example then might look similar to this ...
function getClosestParentByClassName(elm, className) {
while (elm && !elm.classList.contains(className)) {
elm = elm.parentNode;
}
return elm;
}
function addItem(evt) {
//console.log(evt.currentTarget);
var
groupParent = getClosestParentByClassName(evt.currentTarget, 'list-group'),
itemBlueprint = groupParent && groupParent.querySelector('.list-group-item.new-item'),
newGroupItem = (itemBlueprint && itemBlueprint.cloneNode(true)) || createDefaultItem();
//console.log(groupParent, itemBlueprint, newGroupItem);
if (newGroupItem) {
// do whatever needs to be done in order to place the right content into this structure.
groupParent.appendChild(newGroupItem);
}
}
getClosestParentByClassName(document.querySelector('.fa-plus'), 'list-group-item').addEventListener('click', addItem, false);
function createDefaultItem() {
var
renderContainer = document.createElement('div');
renderContainer.innerHTML = [
'<button type="button" class="list-group-item new-item">'
, '<ul class="desc">'
, '<li class="t-desc">#missing t-desc</li>'
, '<li class="t-desc2">#missing t-desc2</li>'
, '<li class="t-desc3">'
, '<label class="switch">'
, '<input type="checkbox">'
, '<span class="slider round"></span>'
, '</label>'
, '</li>'
, '</ul>'
, '</button>'
].join('');
return renderContainer.querySelector('button');
}
.as-console-wrapper { max-height: 100%!important; top: 0; }
<div class="list-group">
<button type="button" class="list-group-item">
<ul class="desc">
<li class="t-desc50">Add Device</li>
<li class="t-desc55"><i class="fa fa-plus fa-2x" aria-hidden="true"></i></li>
</ul>
</button>
<button type="button" class="list-group-item new-item">
<ul class="desc">
<li class="t-desc">Lamp</li>
<li class="t-desc2">5 kwH</li>
<li class="t-desc3">
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</li>
</ul>
</button>
<button type="button" class="list-group-item new-item">
<ul class="desc">
<li class="t-desc">AC</li>
<li class="t-desc2">5 kwH</li>
<li class="t-desc3">
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</li>
</ul>
</button>
</div>

Categories

Resources