How to Remove Particular Element from Array in Javascript with a button - javascript

I want to be able to press on my trashcan and be able to delete any todo i want. Right now i can only remove the first index off my todo with with the help off splice. Also when i inspect my array in console i want to be able to use true or false. So when i click on my button my object gets removed from my screen and inside off the array in console it should show that my object indeed have been removed and turns into true instead of false( todoIsRemoved: false). here is a link so you can see all off my code: https://jsfiddle.net/marvstarv/tqdzn8bg/.
this is my class:
let p=0;
let allTheToDos = [];
class Todo{
constructor(toDoItem, removedToDo){
this.Id= p ++;
this.toDoItem = toDoItem;
this.removedToDo = removedToDo;
}
}
this is the function i need help with,
function removeTask (){
let liContainer = document.getElementById ("mySection"); // contains my label(checkmark), Li, and trashcan button.
allTheToDos.splice(Todo,1);
liContainer.innerHTML="";
generateHtml();
console.log(allTheToDos);
}
this function is conected to line 64 off my "main.js": deleteButton.addEventListener('click', () =>{removeTask(allTheToDos[i])});
i appriciate all the help, get back to me if anything was unclear.enter code here

I updated your Js file to:
window.onload = function(){
// without this my site keeps realoding when adding a new item
let firstTask = new Todo ('Bädda sängen',false);
let secondTask = new Todo ('Hänga upp tavlorna',false);
let thirdTask = new Todo ('Kick back & realx',false);
// Adding my premade todo's into my Array that has the variable 'allTheToDos'
allTheToDos.push(firstTask);
allTheToDos.push(secondTask);
allTheToDos.push(thirdTask);
// creating a function so that the user can add a new todo
let addButton = document.getElementById('addBtn');
addButton.addEventListener('click',addNewTask);
generateHtml ();
// let checkedLi = document.getElementById('listItem')
// checkedLi.addEventListener('click',)
console.log(allTheToDos);
}
// my puublic
let p=0;
let allTheToDos = [];
class Todo{
constructor(toDoItem, removedToDo){
this.Id= p ++;
this.toDoItem = toDoItem;
this.removedToDo = removedToDo;
}
}
function generateHtml (){
// Creating an Ul for my items
let section = document.getElementById('mySection');
let myUl = document.createElement('ul');
myUl.className = 'listContainer';
section.appendChild(myUl);
// Creating the loop for my premade todo objects
for(i=0; i<allTheToDos.length; i++){
// Create a div wrapper for my li
let myListWrapperItemContainer = document.createElement('div');
myListWrapperItemContainer.className = "listItemsWrapper";
let id = `to_do_${i}`;
myListWrapperItemContainer.id = id;
// Creating Checked button
let checkedIcon = document.createElement('label');
checkedIcon.className = 'checkedIcon listItemsIcon';
checkedIcon.innerHTML = '<i class="fas fa-check"></i>';
//Creating li
let myLi = document.createElement("li");
myLi.classList = "listItem lineTrough";
myLi.id= "listItem";
// Creating delete button
let deleteButton = document.createElement('button');
deleteButton.id ="deleteButton";
deleteButton.className = 'trashCan listItemsIcon';
deleteButton.innerHTML = '<i class="fas fa-trash-alt"></i>';
// OnClick
deleteButton.addEventListener('click', () => {removeTask(id)});
// Adding everything to my html
myListWrapperItemContainer.appendChild(checkedIcon);
myListWrapperItemContainer.appendChild(myLi);
myListWrapperItemContainer.appendChild(deleteButton);
myLi.innerHTML = allTheToDos[i].toDoItem;
myUl.appendChild(myListWrapperItemContainer);
}
}
function addNewTask (stopRefresh){
stopRefresh.preventDefault();
let liContainer = document.getElementById ("mySection");
let inputValue = document.getElementById('textBox').value;
liContainer.innerHTML="";
if (inputValue == ""){
alert("Type in something");
generateHtml();
}
else{
let newInputValue = new Todo (inputValue);
allTheToDos.push(newInputValue);
generateHtml();
}
}
function removeTask (id){
let element = document.getElementById(id);
let index = allTheToDos.findIndex(e => e.toDoItem === element.textContent);
allTheToDos.splice(index,1);
element.parentNode.removeChild(element);
}

Related

Remove repetition of javascript html tag creation

If you go through the process of creating html elements in JavaScript, you can see that this process is repeated a lot. For example I made a function to create, edit and delete comments in real time, please see the following code.
function addComment(comment, score) {
// Create a list for comments
const newComment = document.createElement('li');
newComment.setAttribute('data-commentid', comment._id);
newComment.classList.add('detail__comment');
// Creating a Comments Information
const commentInfo = document.createElement('div');
commentInfo.classList.add('detail__comment__info');
const scoreConfigWrap = document.createElement('div');
scoreConfigWrap.classList.add('detail__comment__score');
for (let i = 0; i < score; i++) {
const filledScore = document.createElement('i');
const filledScoreClass = ['fa-solid', 'fa-star', 'filled'];
filledScore.classList.add(...filledScoreClass);
scoreConfigWrap.appendChild(filledScore);
}
for (let j = score; j < 5; j++) {
const score = document.createElement('i');
const scoreClass = ['fa-solid', 'fa-star'];
score.classList.add(...scoreClass);
scoreConfigWrap.appendChild(score);
}
// Create a comment edit button and include it in its parent
const commentBtns = document.createElement('div');
commentBtns.classList.add('detail__comment__btns');
const modifyBtn = document.createElement('button');
modifyBtn.innerText = 'Update';
modifyBtn.classList.add('detail__comment__modify-btn');
const cancelModifyBtn = document.createElement('button');
cancelModifyBtn.innerText = 'Cancel';
cancelModifyBtn.classList.add('detail__comment__modify-cancel');
cancelModifyBtn.classList.add('hidden');
commentBtns.appendChild(modifyBtn);
commentBtns.appendChild(cancelModifyBtn);
commentInfo.appendChild(scoreConfigWrap);
commentInfo.appendChild(commentBtns);
// Create space for comment text, author
const commentText = document.createElement('div');
commentText.classList.add('detail__comment__text');
const span = document.createElement('span');
span.innerText = comment.text;
const commentOwner = document.createElement('a');
commentOwner.setAttribute('href', `users/${comment.owner._id}`);
commentOwner.innerText = comment.owner.uid;
commentText.appendChild(span);
commentText.appendChild(commentOwner);
// Create a delete comment button
const deleteBtn = document.createElement('button');
deleteBtn.innerText = 'X';
deleteBtn.classList.add('detail__comment__delete');
// Saving information to be used for comment editing and deletion functions
comment = {
text: comment.text,
_id: comment._id,
};
commentObj = {
comment,
commentBtns,
commentElement: commentText,
};
// Link all elements related to comments with their parent
newComment.appendChild(commentInfo);
newComment.appendChild(commentText);
newComment.appendChild(modifyForm);
newComment.appendChild(deleteBtn);
detailComments.prepend(newComment);
}
Doesn't it make you annoyed just by looking at it? The problem is I don't know how to refactor this iteration. I thought about making the process of creating html elements into a separate function.
export default function createHtmlTag(
element,
text,
attrObj,
className,
parentNode
) {
const newElement = document.createElement(element);
if (attrObj) {
newElement.setAttribute(attrObj.key, attrObj.value);
}
if (text) {
newElement.innerText = text;
}
if (className) {
newElement.classList.add(className);
}
parentNode.appendChild(newElement);
}
But even then, the code looked like it was less readable. So I'd like to get a little hint about the refactoring process.

How do I display every element from my localStorage item?

i'm trying to create a simple To-do list, and my question is how do i get all elements of a single item in localStorage displayed?
pushing things into localStorage in a form of an array works fine, but only thing I see on my page is the first index of the "tasks" array.
const inputEl = document.getElementById("inputEl")
const submitBtn = document.getElementById("submit")
const clearBtn = document.getElementById("clearBtn")
const todoListContainer = document.getElementById("todoList")
const taskContainer = document.querySelector(".task")
const cancelBtn = document.querySelector(".cancelBtn")
const doneBtn = document.querySelector(".doneBtn")
const errorMsg = document.querySelector(".error")
let localStorageContent = localStorage.getItem("tasks")
let tasks = []
function createTask(){
if(inputEl.value.length != 0){
const newDiv = document.createElement("div")
newDiv.classList.add("task")
const newParagraph = document.createElement("p")
const newCancelBtn = document.createElement("button")
newCancelBtn.classList.add("cancelBtn")
newCancelBtn.textContent = "X"
const newDoneBtn = document.createElement("button")
newDoneBtn.classList.add("doneBtn")
newDoneBtn.textContent = "Done"
todoListContainer.appendChild(newDiv)
newDiv.appendChild(newParagraph)
newDiv.appendChild(newCancelBtn)
newDiv.appendChild(newDoneBtn)
//^^ Creating a container for a new task, with all its elements and assigning the classes^^
tasks.push(inputEl.value)
localStorage.setItem("tasks", JSON.stringify(tasks))
inputEl.value = ""
newParagraph.textContent = JSON.parse(localStorageContent)
errorMsg.textContent = ""
}else{
errorMsg.textContent = "You have to type something in!"
errorMsg.classList.toggle("visibility")
}
}
submitBtn.addEventListener("click", () =>{
createTask()
})
When you execute JSON.parse(localStorageContent) you convert your string into an array, that's right.
But:
newParagraph.textContent = JSON.parse(localStorageContent)
is the same as:
newParagraph.textContent = JSON.parse(localStorageContent)[0]
So, you have to loop through your JSON.parse(localStorageContent)
array... Therefore, create a new variable:
let tasksItem = JSON.parse(localStorageContent)
and loop on with .forEach method

innerText resulting in [object HTMLLIElement] instead of the li text

Beginner here.
I'm in the process of building a simple to do website with Javascript. The website allows you to set a title for the task and add steps too.
I'm having some troubles displaying task steps once you add the task to the task list.
The following code:
let data = document.getElementById('task-steps-new');
let dataList = data.childNodes;
let list = document.querySelector('.task-ul');
dataList.forEach((item)=> {
li = document.createElement('li');
li.innerText = item;
list.appendChild(li);
});
displays the task steps as [object HTMLLIElement] instead of the actual text. Cannot wrap my head around why it's not working, so any help would be greatly appreciated! I've also added below the whole function which grabs the task title input and steps and moves it to the task list. Everything works except the issue stated above.
function addTask() {
const inputValue = document.getElementById("add-task").value;
const newTask = document.createElement('h2');
const t = document.createTextNode(inputValue);
const stepList = document.getElementById('task-steps-new');
const newUl = document.createElement('ul');
const newLi = document.createElement('li');
newTask.appendChild(t);
if (inputValue === '') {
alert("You must type something!")
} else {
newLi.className = "task";
newTask.className = "task-title";
newUl.className = "task-ul";
document.querySelector(".task-list").appendChild(newLi);
newLi.appendChild(newTask);
newLi.appendChild(newUl);
let data = document.getElementById('task-steps-new');
let dataList = data.childNodes;
let list = document.querySelector('.task-ul');
dataList.forEach((item)=> {
li = document.createElement('li');
li.innerText = item;
list.appendChild(li);
});
}
document.getElementById("add-task").value = "";
stepList.innerHTML = '';
var span = document.createElement("SPAN");
var txt = document.createTextNode("\u00D7");
span.className = "close";
span.appendChild(txt);
newLi.appendChild(span);
for (i = 0; i < close.length; i++) {
close[i].onclick = function() {
var div = this.parentElement;
div.remove();
}
}
}

I'm trying to delete a child element, but I keep getting the error node not found

I'm very new to coding so I'm not sure if you get the whole picture with this much, but I can clarify more if this isn't sufficient. Greatly appreciate any help. Thank you!
//remove and complete svg format
var removeSVG = '<svg></svg>';
var completeSVG = '<svg></svg>';
//user clicked on the add button
//If there is any text in the input field add that to the Todo list
document.getElementById('add').addEventListener('click', function () {
var value = document.getElementById('item').value;
if (value) {
addItemTodo(value);
document.getElementById('item').value = "";
}
});
function deleteItem() {
var item = this.parentNode.parentNode;
var parent = this.parentNode;
parent.removeChild(item);
}
function completeItem() {
var item = this.parentNode.parentNode;
var parent = this.parentNode;
var id = parent.id;
var target = (id === 'todo') ? document.getElementById('completed') : document.getElementById('todo');
parent.removeChild(item);
target.insertBefore(item, target.childNodes[0]);
}
//Adds a new item to the todo list
function addItemTodo(text) {
var list = document.getElementById('todo');
var item = document.createElement('li');
item.innerText = text;
var buttons = document.createElement('div');
buttons.classList.add('buttons');
var remove = document.createElement('button');
remove.classList.add('remove');
remove.innerHTML = removeSVG;
//add click event for remove button
remove.addEventListener('click', deleteItem);
var complete = document.createElement('button');
complete.classList.add('complete');
complete.innerHTML = completeSVG;
//add click event for the complete button
complete.addEventListener('click', completeItem);
buttons.appendChild(remove);
buttons.appendChild(complete);
item.appendChild(buttons);
list.insertBefore(item, list.childNodes[0]);
}
//add click event for remove button
remove.addEventListener('click', deleteItem);
So I posted the whole javascript, so you get an idea of the structure, The html itself is just two tags with id=todo and completed respectively
check this https://jsfiddle.net/dp722j27/
function deleteItem() {
var parent = this.parentNode.parentNode.parentNode;
var item = this.parentNode.parentNode;
parent.removeChild(item);
}
If you want to delete button, that was clicked, do like this:
function deleteItem(event) {
var item = event.target.parentNode;
var parent = event.target.parentNode.parentNode;
parent.removeChild(item);
}
//add click event for remove button
document.addEventListener('click', deleteItem);

Add style color to an appended li - Javascript

When adding a new item to the list i would like it to change color based on the input value.
How do i add the input.value to my new appended li item?
I have created a codepen if anyone would be able to help
http://codepen.io/o-sewell/pen/mOBjvQ
// DIV TOGGLE
const toggleButton = document.querySelector('#toggleList');
const listDiv = document.querySelector('.list');
// User INPUT
const userInput = document.querySelector('.userInput');
const button = document.querySelector('button.description');
const p = document.querySelector('p.description');
let listItem = document.querySelectorAll('li');
// ADD ITEM
const addItemInput = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('button.addItemButton');
button.addEventListener('click', () => {
for (let i = 0; i < listItem.length; i++) {
listItem[i].style.color = userInput.value;
}
p.innerHTML = userInput.value + ':';
});
toggleButton.addEventListener('click', () => {
if (listDiv.style.display == 'none') {
listDiv.style.display = 'block';
toggleButton.textContent = 'Hide list';
} else {
listDiv.style.display = 'none';
toggleButton.textContent = 'Show list';
}
});
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
console.log(appendedItem);
for (let i = 0; i < appendedItem.length; i++) {
appendedItem[i].style.color = userInput.value;
}
console.log(appended item);
addItemInput.value = '';
});
Here is the new one :
//DIV TOGGLE
const toggleButton = document.querySelector('#toggleList');
const listDiv = document.querySelector('.list');
var lastPickedColor = "black"; // it will store the last picked color
//User INPUT
const userInput = document.querySelector('.userInput');
const button = document.querySelector('button.description');
const p = document.querySelector('p.description');
let listItem = document.querySelectorAll('li');
//ADD ITEM
const addItemInput = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('button.addItemButton');
button.addEventListener('click', () => {
lastPickedColor = userInput.value;
for(let i = 0; i < listItem.length; i++) {
listItem[i].style.color = lastPickedColor;
}
p.innerHTML = userInput.value + ':';
});
toggleButton.addEventListener('click', () => {
if (listDiv.style.display == 'none') {
listDiv.style.display = 'block';
toggleButton.textContent = 'Hide list';
} else {
listDiv.style.display = 'none';
toggleButton.textContent = 'Show list';
}
});
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.style.color = lastPickedColor; // so it will add li with last picked color
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
console.log(appendedItem);
for(let i = 0; i < appendedItem.length; i++) {
appendedItem[i].style.color = userInput.value;
}
console.log(appendeditem);
addItemInput.value = '';
});
I added lastPickedColor variable to top of the page whenever you change the color, it will store the lastPickedColor and all list add with this color.
The answer is quite simple.
You're defining the initial list when the js is executed, but the new element is created dynamically. Therefore, you'll have to create a new nodelist based on all elements, including the new one. You can simply redefine it inside the current click event:
button.addEventListener('click', () => {
listItem = document.querySelectorAll('li');
for(let i = 0; i < listItem.length; i++) {
listItem[i].style.color = userInput.value;
}
p.innerHTML = userInput.value + ':';
});
To give it the same color as the existing ones, change this function to apply the styling directly on the latest added element:
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
appendedItem.style.color = userInput.value;
addItemInput.value = '';
});
Working codepen example
so I have made 2 changes for your code to work. Please see
http://codepen.io/amoolya/pen/GNMXqa?editors=1111
First change
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
appendedItem.style.color = list.firstElementChild.style.color; //The newly appended item is given the color of the first list element. In your case, this would be whatever color the user chose last.
});
Second Change:
I added
document.querySelectorAll('li');
inside your event handler for the color change button so that each time, the length of the new list is calculated.

Categories