after I keep creating new DIVs with my javascript functions, the new ones don't delete themselves.
My codes creates a post it div which gives info about title, author, and pages, and a X button that when you press it, it deletes it.
It works for my first 4 HTML examples, but not with the newly added divs from javascript.
const container = document.querySelector('.right');
let removeButtons = document.querySelectorAll('.remove');
let removeButtonsArray = Array.prototype.slice.call(removeButtons);
let bookNum = 4;
function addBook() {
const titleAdd = document.getElementById('title-add').value;
const readAdd = document.getElementById('read-add').value;
const totalAdd = document.getElementById('total-add').value;
if (titleAdd == '' || readAdd == '' || totalAdd == '') {
alert('Complete all of the boxes');
return;
} else if (readAdd > totalAdd) {
alert('why are you lying? =[[');
return;
}
const book = document.createElement('div');
book.classList.add('book');
container.appendChild(book);
const xButton = document.createElement('button');
xButton.classList.add('remove');
book.appendChild(xButton);
xButton.innerHTML = 'X';
const title = document.createElement('h2');
book.appendChild(title);
title.innerHTML = titleAdd;
const author = document.createElement('h3');
book.appendChild(author);
author.innerHTML = document.getElementById('author-add').value;
const pages = document.createElement('h3');
book.appendChild(pages);
const pagesNumber = readAdd + '/' + totalAdd;
pages.classList.add('page-num')
pages.innerHTML = pagesNumber;
bookNum++;
removeButtons = document.querySelectorAll('.remove');
removeButtonsArray = Array.prototype.slice.call(removeButtons);
}
const button = document.querySelector('.add');
button.onclick = addBook;
removeButtonsArray.forEach(removeButton => removeButton.addEventListener('click', function() {
const remove = removeButtonsArray.indexOf(removeButton);
removeButtonsArray.splice(remove, 1);
document.querySelector('.book').remove();
bookNum--;
}));
<div class="container">
<div class="left">
<div class="title-add">
<h2>Title:</h2>
<input type="text" id="title-add" name="title-add" max="30">
</div>
<div class="author-add">
<h2>Author:</h2>
<input type="text" id="author-add" name="author-add" max="30">
</div>
<div class="pages">
<div class="pages-read">
<h3>Pages read:</h3>
<input type="number" id="read-add" min="0" name="read">
</div>
<div class="pages-total">
<h3>Total pages:</h3>
<input type="number" id="total-add" min="1" name="total">
</div>
</div>
<button class="add">Add book</button>
</div>
<div class="right">
<div class="book">
<button class="remove">X</button>
<h2 class="title">muie</h2 >
<h3 class="author">Csokmai Robert123</h3>
<h3 class="page-num">31/316</h3>
</div>
<div class="book">
<button class="remove">X</button>
<h2>muie</h2 >
<h3>Csokmai Robert</h3>
<h3 class="page-num">31/316</h3>
</div>
<div class="book">
<button class="remove">X</button>
<h2>muie</h2 >
<h3>Csokmai Robert</h3>
<h3 class="page-num">31/316</h3>
</div>
<div class="book">
<button class="remove">X</button>
<h2>muie</h2 >
<h3>Csokmai Robert</h3>
<h3 class="page-num">31/316</h3>
</div>
</div>
</div>
I tried everything but I just don't know how to fix it
Problems:
There are a few Problems with your code:
Delete function doesn't actually work, because every time you are just removing the first element which has book class. document.querySelector('.book').remove();
The reason the Delete button for Dynamically added books was not working is because this bit of code removeButtonsArray.forEach(removeButton => removeButton.addEventListener was executed only on first execution. So, newly added buttons weren't getting the Event Listener registered for them.
Solutions:
Delete functionality can be easily handled by targeting the parentElement of the Delete Button which was clicked.
For the Dynamically added Books' Delete Functionality, We need to register the click Event Listener for each one of them during creation.
const container = document.querySelector('.right');
let removeButtons = document.querySelectorAll('.remove');
let bookNum = 4;
function addBook() {
const titleAdd = document.getElementById('title-add').value;
const readAdd = document.getElementById('read-add').value;
const totalAdd = document.getElementById('total-add').value;
if (titleAdd == '' || readAdd == '' || totalAdd == '') {
alert('Complete all of the boxes');
return;
} else if (readAdd > totalAdd) {
alert('why are you lying? =[[');
return;
}
const book = document.createElement('div');
book.classList.add('book');
container.appendChild(book);
const xButton = document.createElement('button');
xButton.classList.add('remove');
book.appendChild(xButton);
xButton.innerHTML = 'X';
const title = document.createElement('h2');
book.appendChild(title);
title.innerHTML = titleAdd;
const author = document.createElement('h3');
book.appendChild(author);
author.innerHTML = document.getElementById('author-add').value;
const pages = document.createElement('h3');
book.appendChild(pages);
const pagesNumber = readAdd + '/' + totalAdd;
pages.classList.add('page-num')
pages.innerHTML = pagesNumber;
bookNum++;
// Adding Click Event to new Books Delete Button
xButton.addEventListener("click", removeBook);
}
const button = document.querySelector('.add');
button.onclick = addBook;
// Function for Removing Book
function removeBook(e) {
// Since we are getting the Delete Buttons event as Frunction Argument
// We can get access to it's parentElement i.e., the target Book Div
e.target.parentElement.remove();
bookNum--;
}
removeButtons.forEach(removeButton => removeButton.addEventListener('click', removeBook));
<div class="container">
<div class="left">
<div class="title-add">
<h2>Title:</h2>
<input type="text" id="title-add" name="title-add" max="30">
</div>
<div class="author-add">
<h2>Author:</h2>
<input type="text" id="author-add" name="author-add" max="30">
</div>
<div class="pages">
<div class="pages-read">
<h3>Pages read:</h3>
<input type="number" id="read-add" min="0" name="read">
</div>
<div class="pages-total">
<h3>Total pages:</h3>
<input type="number" id="total-add" min="1" name="total">
</div>
</div>
<button class="add">Add book</button>
</div>
<div class="right">
<div class="book">
<button class="remove">X</button>
<h2 class="title">muie</h2>
<h3 class="author">Csokmai Robert123</h3>
<h3 class="page-num">31/316</h3>
</div>
<div class="book">
<button class="remove">X</button>
<h2>muie</h2>
<h3>Csokmai Robert</h3>
<h3 class="page-num">31/317</h3>
</div>
<div class="book">
<button class="remove">X</button>
<h2>muie</h2>
<h3>Csokmai Robert</h3>
<h3 class="page-num">31/315</h3>
</div>
<div class="book">
<button class="remove">X</button>
<h2>muie</h2>
<h3>Csokmai Robert</h3>
<h3 class="page-num">31/314</h3>
</div>
</div>
</div>
Related
Whenever I want to play the sound of the
word it doesn't play that sound and gives me an error of "The element has no supported sources".
Have a look into this please and let me know where I'm doing something wrong.
Html
<audio id="micCheck"></audio>
<div id="container">
<div id="box-1">
<input
type="text"
placeholder="Type your word here.."
id="searchWord"
/>
<button id="btn">Search</button>
</div>
<div class="output" id="output"></div>
</div>
<script src="script.js"></script>
Javascript
const searchButton = document.getElementById("btn");
const searchField = document.getElementById("searchWord");
const volume = document.getElementById("micCheck");
const url = "https://api.dictionaryapi.dev/api/v2/entries/en/";
searchButton.addEventListener("click", () => {
let saveWord = searchField.value;
fetch(`${url}${saveWord}`)
.then((response) => response.json())
.then((values) => {
console.log(values);
output.innerHTML = `
<div id="box-2">
<h3>${values[0].word}</h3>
<button onclick="playSound()">
<i class="fas fa-volume-up">
</i>
</button>
</div>
<div id="box-3">
<p>${values[0].meanings[0].partOfSpeech}</p>
<p> ${values[0].phonetic} </p>
</div>
<div id="box-4">
<p>
${values[0].meanings[0].definitions[0].definition}</br>
</p>
<p id="paragraph-2">
${values[0].meanings[0].definitions[0].example || ""}
</p>`;
volume.setAttribute("src", `https:${values[0].phonetics[0].audio}`);
});
});
function playSound() {
volume.play();
}
I'm finishing the project and I'm struggling with couple things:
1 Shopping Cart in javascript
I expected <p class="subTotal">$ 0</p> to update after adding, or deleting elements from the shopping cart. Instead, when I add element to the shopping cart, p.subTotal updates 2x the price of dish.
The next one is deleting elements from the shopping cart. When I do that, the console return this:
Console screenshot #1
2 Removing the object
To remove object from the shopping cart I had to select parent of the parent of the button.
Inside the button I've put the svg icon. Somehow, when I click on svg icon, javascript code selects parent of the parent of the svg instead of the button's.
3 Adding dishes to the shopping cart
I've put <a href="#" class="addToCart"> inside of <div class="food">.
This action results in console, showing me another error:
Console screenshot #2
If You can answer even one question I will really appreciate that.
I have only few hours left to finish it.
Code:
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', ready);
} else {
ready();
}
function ready() {
var removeCartItemButtons = document.getElementsByClassName('trash');
for (var i = 0; i < removeCartItemButtons.length; i++) {
var button = removeCartItemButtons[i];
button.addEventListener('click', removeCartItem);
}
var quantityInputs = document.getElementsByClassName('quantity');
for (var i = 0; i < quantityInputs.length; i++) {
var input = quantityInputs[i];
input.addEventListener('change', quantityChanged);
}
var addToCart = document.getElementsByClassName('addToCart');
for (var i = 0; i < addToCart.length; i++) {
var button = addToCart[i];
button.addEventListener('click', addToCartClicked);
}
}
function removeCartItem(event) {
var buttonClicked = event.target;
buttonClicked.parentElement.parentElement.remove();
updateCartTotal();
}
function quantityChanged(event) {
var input = event.target;
if (isNaN(input.value) || input.value <= 0) {
input.value = 1;
}
updateCartTotal();
}
function addToCartClicked(event) {
var button = event.target;
var shopItem = button.parentElement;
var title = shopItem.getElementsByClassName('name')[0].innerText;
var price = shopItem.getElementsByClassName('price')[0].innerText;
var imageSrc = shopItem.getElementsByClassName('foodImg')[0].src;
addItemToCart(title, price, imageSrc);
updateCartTotal();
}
function addItemToCart(title, price, imageSrc) {
var product = document.createElement('div');
product.classList.add('product');
var basket = document.getElementsByClassName('basket')[0];
var productContents = `
<div class="product">
<div class="productInfo">
<div class="productName">
<img src="${imageSrc}" alt="Spicy seasoned seafood noodles">
<div>
<p class="productTitle">${title}</p>
<p class="money">${price}</p>
</div>
</div>
<input class="quantity" type="text" value="1">
<p class="cash">${price}</p>
</div>
<div class="note">
<input type="text" placeholder="Order Note...">
<button class="trash"><svg width="24" height="24" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path
d="M18.8789 8.71882L18.9784 8.72017C19.3475 8.75069 19.6304 9.05716 19.65 9.42605L19.6405 9.63174L19.326 13.483L18.9961 17.2414C18.9263 17.9917 18.8638 18.6245 18.8099 19.1227C18.6225 20.8588 17.4955 21.9323 15.7966 21.9641C13.1494 22.013 10.6048 22.0125 8.13373 21.9591C6.48398 21.9244 5.37366 20.8393 5.18955 19.1297L5.0623 17.8702L4.83994 15.427L4.61216 12.7461L4.35172 9.52788C4.31935 9.11498 4.61951 8.75335 5.02215 8.72016C5.39123 8.68973 5.7183 8.94584 5.79519 9.30677L5.82511 9.60173L6.06966 12.6187L6.33669 15.7459C6.45646 17.0996 6.56034 18.1952 6.64346 18.9648C6.74838 19.939 7.26138 20.4404 8.16411 20.4593C10.6159 20.5124 13.1415 20.5129 15.7701 20.4643C16.7277 20.4464 17.2488 19.9499 17.356 18.9574L17.4827 17.7046C17.5198 17.3185 17.5594 16.8923 17.6013 16.4293L17.8686 13.3538L18.1906 9.4075C18.2204 9.02902 18.5192 8.7389 18.8789 8.71882ZM3.73139 6.98918C3.32745 6.98918 3 6.65338 3 6.23916C3 5.85945 3.27515 5.54564 3.63214 5.49597L3.73139 5.48913H6.91772C7.29636 5.48913 7.62785 5.23928 7.74642 4.87929L7.77543 4.76813L8.02304 3.50533C8.24111 2.66897 8.9492 2.07349 9.779 2.00633L9.93592 2H14.0639C14.9075 2 15.6523 2.54628 15.9391 3.39039L15.9874 3.55209L16.2243 4.76783C16.2987 5.14872 16.6025 5.4332 16.9701 5.48177L17.0821 5.48913H20.2686C20.6725 5.48913 21 5.82493 21 6.23916C21 6.61887 20.7248 6.93267 20.3679 6.98234L20.2686 6.98918H3.73139ZM14.0639 3.50006H9.93592C9.7307 3.50006 9.54829 3.62322 9.47252 3.77803L9.44682 3.84604L9.20979 5.06238C9.1808 5.21084 9.13879 5.3538 9.08512 5.49012L14.9148 5.49031C14.8813 5.40526 14.8523 5.31763 14.8282 5.22768L14.79 5.06208L14.5636 3.8928C14.5107 3.68991 14.3473 3.54138 14.1502 3.50742L14.0639 3.50006Z" />
</svg></button>
</div>
</div>`;
product.innerHTML = productContents;
basket.append(product);
product
.getElementsByClassName('trash')[0]
.addEventListener('click', removeCartItem);
product
.getElementsByClassName('quantity')[0]
.addEventListener('change', quantityChanged);
}
function updateCartTotal() {
var cartItemContainer = document.getElementsByClassName('basket')[0];
var products = cartItemContainer.getElementsByClassName('product');
var total = 0;
for (var i = 0; i < products.length; i++) {
var product = products[i];
var priceElement = product.getElementsByClassName('money')[0];
var quantityElement = product.getElementsByClassName('quantity')[0];
var price = parseFloat(priceElement.innerText.replace('$', ''));
var quantity = quantityElement.value;
total = total + price * quantity;
}
total = Math.round(total * 100) / 100;
document.getElementsByClassName('subTotal')[0].innerText = '$ ' + total;
}
// Date in header
var dt = new Date();
document.getElementById('datetime').innerHTML = dt.toLocaleDateString();
<div id="foodCard">
<div class="food">
<a href="#" class="addToCart">
<div class="bg">
<img class="foodImg" src="style/img/Image 1.png" alt="Spicy seasoned seafood noodles">
<div class="text">
<p class="name">Spicy seasoned seafood noodles</p>
<div>
<p class="price">$ 2.29</p>
<p class="availability">20 Bowls available</p>
</div>
</div>
</div>
</a>
</div>
<div class="food">
<a href="#" class="addToCart">
<div class="bg">
<img class="foodImg" src="style/img/Image 2.png" alt="Salted Pasta with mushroom sauce">
<div class="text">
<p class="name">Salted Pasta with mushroom sauce</p>
<div>
<p class="price">$ 2.69</p>
<p class="availability">11 Bowls available</p>
</div>
</div>
</div>
</a>
</div>
<div class="food">
<a href="#" class="addToCart">
<div class="bg">
<img class="foodImg" src="style/img/Image 3.png" alt="Beef dumpling in hot and sour soup">
<div class="text">
<p class="name">Beef dumpling in hot and sour soup</p>
<div>
<p class="price">$ 2.99</p>
<p class="availability">16 Bowls available</p>
</div>
</div>
</div>
</a>
</div>
<div class="food">
<a href="#" class="addToCart">
<div class="bg">
<img class="foodImg" src="style/img/Image 5.png" alt="Spicy seasoned seafood noodles">
<div class="text">
<p class="name">Spicy seasoned seafood noodles</p>
<div>
<p class="price">$ 2.29</p>
<p class="availability">20 Bowls available</p>
</div>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</main>
<section id="order">
<div id="container">
<header>
<h2>Orders #34562</h2>
<div id="selector">
<button class="active">Dine in</button>
<button>To Go</button>
<button>Delivery</button>
</div>
<div id="description">
<p>Item</p>
<p>Qty</p>
<p>Price</p>
</div>
</header>
<div class="basket">
</div>
<div id="bottom">
<div id="total">
<div id="discount">
<p>Discount</p>
<p>$0</p>
</div>
<div id="subTotal">
<p>Sub total</p>
<p class="subTotal">$ 0</p>
</div>
I couldn't have time to go through the full code, but I had an observation. document.getElementsByClassName('subTotal')[0].innerText = '$ ' + total;, is the getElementsByClassName('subTotal') returning a element or just returning undefined? Because, you can't access innerHTML from undefined.
Also, is shopItem.getElementsByClassName('foodImg')[0] not undefined? If it is undefined, then you will get src of undefined error. Is there an element with class name foodImg?
When I type something in the first box, and click Next, the word I typed is inserted on my page. However, if I click Back and then click Next again, it is printed a second time.
I want the keyword appended after I've clicked Next to be deleted if I click Back so that if I click Next again it is printed only once (and updated if I have made any edit).
document.addEventListener("DOMContentLoaded", function() {
var stepOne = document.getElementsByClassName("step-1");
var stepTwo = document.getElementsByClassName("step-2");
var nextButton = document.getElementsByClassName("next");
var backButton = document.getElementsByClassName("back");
nextButton[0].onclick = function() {
stepOne[0].style.display = "none";
stepTwo[0].style.display = "block";
var inputKeyword = document.getElementById("inputJobTitle").value;
var newKeyword = document.createElement("p");
newKeyword.setAttribute("id", "retrievedField-1");
newKeyword.setAttribute("class", "retrievedFieldName");
newKeyword.innerText = inputKeyword;
newKeyword.setAttribute("id", "retrievedField-1");
newKeyword.setAttribute("class", "retrievedFieldName");
document.getElementById("retrievedFields").appendChild(newKeyword);
}
backButton[0].onclick = function() {
stepOne[0].style.display = "block";
stepTwo[0].style.display = "none";
}
})
.step-1 {
display: block;
}
.step-2 {
display: none;
}
<!--STEP 1-->
<div class="main step-1">
<div class="tab" id="tab-1">
<div class="inputFields">
<p id="jobtitle" class="inputFieldName">Job title</p>
<input type="search" id="inputJobTitle" class="inputBar" />
<p class="and">AND</p>
</div>
<div class="button">
<button class="next">Next ></button>
</div>
</div>
</div>
<!--STEP 2-->
<div class="main step-2">
<div class="tab" id="tab-1">
<div class="inputFields">
<div id="retrievedFields"></div>
<input type="search" class="inputBarAlternative" />
<div class="add">
<button class="addButton">+ Add Keyword</button>
<p id="addKeyword">
Add a skill or keyword that must be in your search results
</p>
</div>
</div>
<div class="buttons">
<button class="back">Back</button>
<button class="next">Next</button>
</div>
</div>
</div>
</body>
Each new click on the next button will trigger an append. So you just have to do the opposite of an append on the click on back. Just add this line in your onclick:
document.getElementById("retrievedFields").removeChild(document.getElementById("retrievedFields").lastElementChild);
You could also check to see if the element exists before you create it..
nextButton[0].onclick = function() {
stepOne[0].style.display = "none";
stepTwo[0].style.display = "block";
var inputKeyword = document.getElementById("inputJobTitle").value;
var newKeyword = document.getElementById("retrievedField-1")
if (!newKeyword) {
newKeyword = document.createElement("p");
newKeyword.setAttribute("id", "retrievedField-1");
newKeyword.setAttribute("class", "retrievedFieldName");
document.getElementById("retrievedFields").appendChild(newKeyword);
}
newKeyword.innerText = inputKeyword;
}
Using innerHTML when I add a new item, the query selector does not seem to add it.
So when I try to calculate my items. I only am getting the original ones to calculate, but not the newly generated ones.
Even when you console.log() the elements by the variable it will only show the original elements.
All these elements have the same class name as the original element.
Just cannot get them to be seen or added on the generated items.
Fiddle code snippet.
const total = document.querySelectorAll(".tot")
const price = document.querySelectorAll(".cost");
let textval = document.querySelectorAll('.qty-item');
const cal = document.getElementById("calc");
const errorMessage = document.querySelectorAll('.error');
//
let theform = document.querySelector(".theform");
let newitem = document.querySelector('.new-item');
let createBtn = document.getElementById("create");
let theItem = document.querySelector(".newStuff");
//
form.addEventListener("click",function(e){
let theHtml = `
<div>
<span class="cost">${newitem.value}</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
`
});
cal.addEventListener('mouseover', function(e) {
console.log('total', total);
for (var i = 0; i < price.length; i++) {
let xPrice = price[i].innerHTML.split("$");
let parsePrice = parseFloat(xPrice[1]);
if (textval[i].value === "" || isNaN(textval[i].value)) {
console.log("No Good");
} else {
let x = parseFloat(textval[i].value);
let y = parsePrice;
let z = x * y;
total[i].innerText = z.toFixed(2);
total[i].innerText = z;
for (let k = 0; k < total.length; k++) {
let j = parseFloat(total[k].innerHTML);
console.log(j);
}
}
}
});
<body>
<div class="main">
<span class="title">A Title</span>
</div>
<div class="content">
<div class="item">
<span>Item 1</span>
</div>
<div>
<span class="cost">$100.00</span>
</div>
<div id="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
<p class="error"></p>
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
</div>
<br><br>
<div class="main">
<span class="title">A Title</span>
</div>
<div class="content">
<div class="item">
<span>Item 2</span>
</div>
<div>
<span class="cost">$50.00</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
<p class="error"></p>
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
</div>
<form class ='theform'>
<label>NewItem</label><input placeholder="0" class="new-item">
<button id="create">create</button>
</form>
<span class ="newStuff"></span>
<div class="calc-button">
<button id="calc">Calculate Prices</button>
</div>
</body>
#Phil is right on this. You are running the query selectors at the start of your script and will therefore run only once. So when the user clicks a button and you dynamically add new html to the page, the query selectors will not fire again.
You can initialize those queries at the top of your script just like you have them now, but you will need to re-assign their values to new queries inside your event listener something like the following:
const total = document.querySelectorAll(".tot")
const price = document.querySelectorAll(".cost");
let textval = document.querySelectorAll('.qty-item');
let cal = document.getElementById("calc");
const errorMessage = document.querySelectorAll('.error');
//
let theform = document.querySelector(".theform");
let newitem = document.querySelector('.new-item');
let createBtn = document.getElementById("create");
let theItem = document.querySelector(".newStuff");
form.addEventListener("click",function(e){
let theHtml = `
<div>
<span class="cost">${newitem.value}</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
`
//append your HTML to the correct target element then update your query inside the event listener
textval = document.querySelectorAll('.qty-item');
cal = document.getElementById("calc");
});
Given all your querySelectorAll() queries are using simple, single-class-name selectors, you can replace them all with document.getElementsByClassName(), ie
const total = document.getElementsByClassName('tot')
const price = document.getElementsByClassName('cost');
const textval = document.getElementsByClassName('qty-item');
const errorMessage = document.getElementsByClassName('error');
This behaves almost the same as querySelectorAll() with one difference...
elements is a live HTMLCollection of found elements.
The elements referenced in these collections will update automatically as elements are added or removed from the document.
For a todo list, I'm trying to dynamically add a button as a child of a list element and a sibling of a text node as below.
<ul>
<li>Hello world <button>X</button></li>
</ul>
The unordered list is in the HTML file but the list, text and button need to be inserted dynamically from the JS file. Is this possible without wrapping the text in a p tag?
Here's the code:
const todoInputEl = document.querySelector(".todo__input");
const todoListEl = document.querySelector(".todo__list");
const todoItemEls = document.querySelector(".todo__item");
const deleteItemEl = document.querySelector(".done");
function addListItem() {
todoInputEl.addEventListener("keypress", function(e) {
if (e.keyCode === 13) {
let newListItem = createListItem(todoInputEl.value);
todoListEl.insertBefore(newListItem, todoListEl.childNodes[0]);
todoInputEl.value = "";
}
})
}
function createListItem(text) {
const deleteButton = document.createElement("button");
const newListElement = document.createElement("li");
const newParaElement = document.createElement("p");
deleteButton.setAttribute("type", "button");
deleteButton.classList.add("delete");
deleteButton.innerHTML = "×";
newListElement.appendChild(newParaElement);
newListElement.setAttribute("class", "todo__item");
newParaElement.setAttribute("class", "todo__p");
newParaElement.textContent = text;
newParaElement.parentNode.insertBefore(deleteButton, deleteButton.nextElementSibling);
return newListElement;
}
addListItem();
<main>
<div class="container">
<div class="todo">
<div class="todo__header">
<h1 class="todo__title">to dos</h1>
<label for="todo input">
<input type="text" class="todo__input" placeholder="enter a thing to do">
</label>
</div>
<div class="todo__body">
<ul class="todo__list">
</ul>
</div>
</div>
</div>
</main>
As you see, it works if the text is inside a p tag, but I can't get it to work insert to the same place if it's just a plain text node. I looked extensively for examples of this being done, but haven't found any yet.
DOM manipulation can be expensive (jQuery DOM manipulations - performance comparation?). Using innerHTML sidesteps this and in my opinion makes things simpler.
const todoInputEl = document.querySelector(".todo__input");
const todoListEl = document.querySelector(".todo__list");
const todoItemEls = document.querySelector(".todo__item");
const deleteItemEl = document.querySelector(".done");
function addListItem() {
todoInputEl.addEventListener("keypress", function(e) {
if (e.keyCode === 13) {
todoListEl.innerHTML += createListItem(todoInputEl.value);
}
})
}
function createListItem(text) {
let listTemplate = "<li>{{ToDo}} <button type='button' class='delete'>×</button></li>";
return listTemplate.replace("{{ToDo}}", text);
}
addListItem();
<main>
<div class="container">
<div class="todo">
<div class="todo__header">
<h1 class="todo__title">to dos</h1>
<label for="todo input">
<input type="text" class="todo__input" placeholder="enter a thing to do">
</label>
</div>
<div class="todo__body">
<ul class="todo__list">
</ul>
</div>
</div>
</div>
</main>