Why are copies of whats in my array posting? - javascript

i want the value from my input to render on my page when i click on my button to add text to my page. For some reason with the current code that i have, the new value from my input is displayed in addition to a copy of what was already there, so basically previous input values are showing more than once on the front end as opposed to a new item just being added to the list
heres a link to the codepen so you can see what happens https://codepen.io/matthew-angel/pen/jOmJLBW
// Log out "Button clicked!" when the user clicks the "SAVE INPUT" button
let myLeads = []
const button = document.querySelector("#input-btn")
const inputEl = document.querySelector("#input-el")
// let inputText = inputEl.value
const ulEl = document.querySelector("#ul-el")
button.addEventListener("click", addText)
function addText() {
console.log(inputEl.value)
myLeads.push(inputEl.value)
console.log(myLeads)
render()
}
function render(){
for(let i = 0; i < myLeads.length; i++) {
// create element
// set text content
// append to ul
let li = document.createElement('li')
li.innerText += myLeads[i]
ulEl.appendChild(li)
console.log(li)
console.log(ulEl)
console.log( li.textContent)
}
}

Related

How to show "cart is empty" after all items have been removed using Javascript?

I am a bit stuck and hoping someone can help me, please.
Basically I have coded a shopping cart and am currently trying to get the cart to display a message saying "Cart is empty" after all of the cart items have been removed.
Everything is working ok apart from the "Cart is empty" message being re-displayed after the cart is empty.
I have tried a few things but cannot seem to get the emptyCartMessage to display when removing the last cart item.
Just for extra context my cart items each have an independent 'remove' button attached to them.
My code is below.
Thank you for any help, I do appreciate it!
const currentCartItems = document.getElementsByClassName('cart-item');
const emptyCartMessage = document.createElement('p');
emptyCartMessage.innerHTML = 'Your cart is empty.';
// EMPTY CART ITEM DISPLAY MESSAGE
shoppingCart.appendChild(emptyCartMessage);
// SHOPPING AREA BUTTON EVENT LISTENER
for (var i = 0; i < addToCartButton.length; i++) {
addToCartButton[i].addEventListener('click', createCartItem);
}
function createCartItem(event) {
//CREATE CART LI ITEM
const newItem = document.createElement('li');
newItem.className = 'cart-item';
//newItem.innerHTML = event.target.value;
//GET AND SET SHOP/CART ITEM VALUE
const itemValue = document.createElement('p');
itemValue.innerHTML = event.target.value;
//CREATE CART ITEM DESCRIPTION
const p = document.createElement('p');
p.innerHTML = itemDescription;
//CREATE CANCEL CART ITEM BUTTON
const cancelItemImage = document.createElement('img');
cancelItemImage.className = "remove-button";
cancelItemImage.src = "images/cancel-icon.png";
cancelItemImage.alt = "red remove icon";
newItem.appendChild(itemValue);
newItem.appendChild(p);
newItem.appendChild(cancelItemImage);
shoppingCart.appendChild(newItem);
if (currentCartItems.length > 0) {
emptyCartMessage.className = 'hide-empty-cart';
} else if (currentCartItems.length <= 0) {
emptyCartMessage.classList.remove('hide-empty-cart');
}
}
// REMOVE CART ITEMS BUTTON
shoppingCart.addEventListener('click', (e) => {
if (e.target.className === 'remove-button'){
const li = e.target.parentNode;
const ol = li.parentNode;
ol.removeChild(li);
}
});
Please remove this line
const currentCartItems = document.getElementsByClassName('cart-item');
We will use this variable inside the function 'createCartItem' and inside 'removeCartItem' tha i just created.
So when calling createCartItem we can always show the cart items, because this function adds new items, so the cart is not empty.
Inside remove function first we getting the count of current items, then checking if it is less or equal 0 then we hide cart.
So the final version would be.
const emptyCartMessage = document.createElement('p');
emptyCartMessage.innerHTML = 'Your cart is empty.';
// EMPTY CART ITEM DISPLAY MESSAGE
shoppingCart.appendChild(emptyCartMessage);
// SHOPPING AREA BUTTON EVENT LISTENER
for (var i = 0; i < addToCartButton.length; i++) {
addToCartButton[i].addEventListener('click', createCartItem);
}
function createCartItem(event) {
//CREATE CART LI ITEM
const newItem = document.createElement('li');
newItem.className = 'cart-item';
//newItem.innerHTML = event.target.value;
//GET AND SET SHOP/CART ITEM VALUE
const itemValue = document.createElement('p');
itemValue.innerHTML = event.target.value;
//CREATE CART ITEM DESCRIPTION
const p = document.createElement('p');
p.innerHTML = itemDescription;
//CREATE CANCEL CART ITEM BUTTON
const cancelItemImage = document.createElement('img');
cancelItemImage.className = "remove-button";
cancelItemImage.src = "images/cancel-icon.png";
cancelItemImage.alt = "red remove icon";
newItem.appendChild(itemValue);
newItem.appendChild(p);
newItem.appendChild(cancelItemImage);
shoppingCart.appendChild(newItem);
// Always show because after every adding, we know that there is
// at least one item, so we always showing cart
emptyCartMessage.className = 'hide-empty-cart';
}
function removeCartItem(event){
if (event.target.className === 'remove-button'){
const li = e.target.parentNode;
const ol = li.parentNode;
ol.removeChild(li);
// Get cart's current items
const currentCartItems = document.getElementsByClassName('cart-item');
// If cart items less then or equal to 0 then hide
if (currentCartItems.length <= 0) {
emptyCartMessage.classList.remove('hide-empty-cart');
}
}
}
// REMOVE CART ITEMS BUTTON
shoppingCart.addEventListener('click', removeCartItem);

Moving a Checked Li to the Bottom of a UL

I am making a todo list, i have just about everything for it figured out but one area i am stuck on is my UL and Li.
Basically when you enter items into the list, you have the ability to click the checkbox beside said item when you complete the task, and it will put a line through the text.
But i also want it to move that item to the bottom of the list when it is clicked.
would anyone be able to help me with how i would go about doing that
code Below
// making event listener for adding item
let addBTN = document.getElementById('addBtn');
addBTN.addEventListener('click', addItem);
// this creates a new li based on the entered value in the text box that it gets when you hit the button
// Through Research found that setAttribute isn't really needed and i can just use .id , .type etc
function addItem() {
// Creating needed elements as well as getting text from textbox
let newLi = document.createElement("li");
let myLiValue = document.getElementById('textBoxAdd').value;
let liTextNode = document.createElement("label");
liTextNode.textContent = myLiValue;
// makes div for li
let newDivID = ('div_' + myLiValue);
let newDiv = document.createElement('div');
newDiv.id = newDivID;
// makes checkboxes for the li
let newCheckBoxID = ('checkbox_' + myLiValue);
let newCheckBox = document.createElement('input');
newCheckBox.type = 'checkbox';
newCheckBox.id = newCheckBoxID;
// makes delete button for the li
let newDeleteID = ('deleteButton_' + myLiValue);
let newDeleteButton = document.createElement("button")
newDeleteButton.type = 'button';
newDeleteButton.id = newDeleteID
newDeleteButton.textContent = 'Delete';
//newDeleteButton.setAttribute('onclick', 'deleteItem()');
newDeleteButton.innerHTML = 'Delete';
// appends it to my newDiv
newDiv.appendChild(newCheckBox);
newDiv.appendChild(liTextNode);
newDiv.appendChild(newDeleteButton);
// then appends my new div to the new Li
newLi.appendChild(newDiv);
// this just makes sure a user cant enter in a blank value
if (myLiValue == "") {
alert("Please Enter Something Before Hitting Add Item");
} else {
document.getElementById('theNewList').appendChild(newLi);
document.getElementById('textBoxAdd').value = "";
}
}
//creating event listener for checkbox line through text and moving item
let theList = document.getElementById('theNewList');
theList.addEventListener('click', checkedComplete);
// function that will target every check box in the list and if any get checked then it will add a line through the text
function checkedComplete(event) {
const checkboxElement = event.target;
if (checkboxElement.type === 'checkbox') {
if (checkboxElement.checked) {
checkboxElement.nextElementSibling.style.textDecoration = 'line-through';
// add in moving item
} else {
checkboxElement.nextElementSibling.style.textDecoration = 'none';
}
}
}
// adds deleteItem listener to the list
theList.addEventListener('click', deleteItem);
function deleteItem(event) {
const deleteButton = event.target;
if (deleteButton.type === 'button') {
const deleteParentNode = deleteButton.parentNode;
deleteParentNode.parentNode.removeChild(deleteParentNode);
}
}
You are going to have a storage of you todos, right? Even if you did not think about it, it can do all the work. Just create the array (you could use localStorage to prevent you data from disappearing after browser is restarted) containing your todos and their condition, like
const todos = [{todo:"watch the movie", completed: false}, {...}, {...}]
Now you can easily add or remove items with standard array methods pop&push, delete with splice, filter etc. After array is mdified, just update the page and build your list using Array.map.
You should just add the following logic where you have // add in moving item comment:
const theList = document.getElementById('theNewList');
const lastListItem = theList.children[theList.children.length - 1];
theList.insertBefore(lastListItem, checkboxElement.parentNode.parentNode);
We're selecting your ul and searching for its last li and then we're simply placing the li belonging to the checkboxElement after the last li.
Working example:
// making event listener for adding item
let addBTN = document.getElementById('addBtn');
addBTN.addEventListener('click', addItem);
// this creates a new li based on the entered value in the text box that it gets when you hit the button
// Through Research found that setAttribute isn't really needed and i can just use .id , .type etc
function addItem() {
// Creating needed elements as well as getting text from textbox
let newLi = document.createElement("li");
let myLiValue = document.getElementById('textBoxAdd').value;
let liTextNode = document.createElement("label");
liTextNode.textContent = myLiValue;
// makes div for li
let newDivID = ('div_' + myLiValue);
let newDiv = document.createElement('div');
newDiv.id = newDivID;
// makes checkboxes for the li
let newCheckBoxID = ('checkbox_' + myLiValue);
let newCheckBox = document.createElement('input');
newCheckBox.type = 'checkbox';
newCheckBox.id = newCheckBoxID;
// makes delete button for the li
let newDeleteID = ('deleteButton_' + myLiValue);
let newDeleteButton = document.createElement("button")
newDeleteButton.type = 'button';
newDeleteButton.id = newDeleteID
newDeleteButton.textContent = 'Delete';
//newDeleteButton.setAttribute('onclick', 'deleteItem()');
newDeleteButton.innerHTML = 'Delete';
// appends it to my newDiv
newDiv.appendChild(newCheckBox);
newDiv.appendChild(liTextNode);
newDiv.appendChild(newDeleteButton);
// then appends my new div to the new Li
newLi.appendChild(newDiv);
// this just makes sure a user cant enter in a blank value
if (myLiValue == "") {
alert("Please Enter Something Before Hitting Add Item");
} else {
document.getElementById('theNewList').appendChild(newLi);
document.getElementById('textBoxAdd').value = "";
}
}
//creating event listener for checkbox line through text and moving item
let theList = document.getElementById('theNewList');
theList.addEventListener('click', checkedComplete);
// function that will target every check box in the list and if any get checked then it will add a line through the text
function checkedComplete(event) {
const checkboxElement = event.target;
if (checkboxElement.type === 'checkbox') {
if (checkboxElement.checked) {
checkboxElement.nextElementSibling.style.textDecoration = 'line-through';
const theList = document.getElementById('theNewList');
const lastListItem = theList.children[theList.children.length - 1];
theList.insertBefore(checkboxElement.parentNode.parentNode, lastListItem.nextSilbing);
} else {
checkboxElement.nextElementSibling.style.textDecoration = 'none';
}
}
}
// adds deleteItem listener to the list
theList.addEventListener('click', deleteItem);
function deleteItem(event) {
const deleteButton = event.target;
if (deleteButton.type === 'button') {
const deleteParentNode = deleteButton.parentNode;
deleteParentNode.parentNode.removeChild(deleteParentNode);
}
}
<input id="textBoxAdd" type="text" />
<button id="addBtn" type="button">Add</button>
<ul id="theNewList"></ul>

How to set the li value (text inside the li) in the input filed in TODO application when user click on update button?

Below is my code actually I wanted to set the li text into the input field when a user click on update button . The code is working input element is shown when user click on update button but the value which is in the li tag is not shown in the input filed but it is shown in the console I also attached the picture to clear this when I replace the input with a button
[function addTodo() {
// create li
var todo_input = document.getElementById('todo-input');
var li = document.createElement('li');
var textNode = document.createTextNode(todo_input.value);
li.setAttribute('class', 'li');
li.appendChild(textNode);
// create update button
var updateBtn = document.createElement('button');
var updateText = document.createTextNode('UPDATE');
li.appendChild(updateBtn);
li.appendChild(deleteBtn);
addList.appendChild(li);
}
function updateItem(e) {
var val1 = e.parentNode.firstChild;
var inputVal = document.createElement('input');
inputVal.setAttribute('class','todo-input');
inputVal.setAttribute('type','text');
var textNode = document.createTextNode(val1.nodeValue);
inputVal.appendChild(textNode);
}][1]
Don't append the text in the input box. Use the value attribute.
inputVal.value = val1.nodeValue;

After Click Event Instead of Showing all Notes Display only Current Note

Program starts with displaying all notes from localstore, but when I click the addButton it display my current note only.
I want to show all the notes and after click event new note will add with previous notes.
let addButton = document.querySelector(".addBtn");
let userNotes = [];
displayNotes();
//addButton Event Listner
addButton.addEventListener("click", function(e) {
e.preventDefault();
//get the user inputs
let userInputs = {
title: document.getElementById("title_input").value,
description: document.getElementById("des_input").value
};
//push user inputs to arrays
userNotes.push(userInputs);
document.querySelector("form").reset();
//store to the localstorage
localStorage.setItem("Notes", JSON.stringify(userNotes));
//display to the user
displayNotes();
});
function displayNotes() {
let gettingNotes = localStorage.getItem("Notes");
let allNotes = JSON.parse(gettingNotes);
let html = "";
allNotes.forEach(element => {
html += `
<div class="single-item">
<h2 class="single-item-title">
${element.title}
</h2>
<p class="single-item-description">
${element.description}
</p>
</div>
`;
});
document.querySelector(".item-list").innerHTML = html;
}
It happens because you set userNotes to be an empty array and you add only your current note. Try to initialize userNotes with a value from localStorage, i.e
let userNotes = JSON.parse(localStorage.getItem('Notes')) || []
Also, then you are able to use userNotes variable in displayNotes function, instead of allNotes.

adding an onchange event to select

I have the following js code:
function createConBox() {
var charDiv = document.getElementById("characterList"); // reference to "characterList" div
header = document.createElement("p"); // creates the <p> tag
charDiv.appendChild(header); // adds the <p> tag to the parent node
title = document.createTextNode("Show Only Lines By:"); // creates the text string
header.appendChild(title); // adds the text string to the parent node
// create select box and add elements
selectBox = document.createElement("select");
selectBox.setAttribute("id", "cList");
charDiv.appendChild(selectBox);
charNames = uniqueElemText("h3"); // array of character names
newOption = document.createElement("option");
selectBox.appendChild(newOption);
newOptionTitle = document.createTextNode("Show All Lines");
newOption.appendChild(newOptionTitle);
for (i = 0; i < charNames.length; i++) {
newOption = document.createElement("option");
selectBox.appendChild(newOption);
newOptionTitle = document.createTextNode(charNames[i]);
newOption.appendChild(newOptionTitle);
}
}
function showLines() {
alert("The Box has been changed");
}
Every time the option in the box is changed, I want it to call 'showLines()'. However, every time I try to implement an event, I can only get it to trigger when the page loads, and never again thereafter.
selectBox.onchange = showLines; should solve your problem.
in some browsers onchange get fired only after blurring select box. to over come this you can use onclick instead of onchange
My guess is that you're doing this:
selectBox.onchange = showLines();
If that's the case, just remove the ():
selectBox.onchange = showLines;
When I pass dynamically id in case then what I do:
var selectcell = tablerow.insertCell(1);
var selectelmt = document.createElement('select');
selectelmt.name = 'Select';
selectelmt.value = 'select';
selectelmt.classList = 'form-control input-sm cobclass';
selectelmt.onchange= onselectchange(i);
selectelmt.id = 'cobselect' + i;
selectelmt.options[0] = new Option('select');
selectcell.appendChild(selectelmt);
// ddrbind(i);
show();
i++;`

Categories