To-Do-List Delete All Function - javascript

How can I fix the function to delete all todoItems? My guess is that the for loops is not working right :\ I appreciate any help with my problem! I have only 1-month of experience with javascript.
How can I fix the function to delete all todoItems? My guess is that the for loops is not working right :\ I appreciate any help with my problem! I have only 1-month of experience with javascript.
function selectColorStatus(event){
let target = event.target;
target.classList.toggle('todoTextSelected');
}
function createToDoItem(userInputValue){
// To-Do Item Container
let todoItem = document.createElement("div");
todoItem.classList.add("row", "flx");
todoItem.onclick = selectColorStatus;
// Clear List
let btnDeleteItem = document.getElementById('btnDeleteItem');
btnDeleteItem.onclick = function (){
for(let i = 0; i < todoItem; i++){
todoItem.remove();
}
}
// Inner Text
let todoText = document.createElement('div');
todoText.classList.add('grow');
todoText.innerText = userInputValue;
// Date
let CreateDate = document.createElement('div');
CreateDate.classList.add('date');
let date = new Date();
year = date.getFullYear();
month = date.getMonth();
day = date.getDay();
CreateDate.innerText = 'Created at ' + year + '-' + month + '-'+ day;
// Delete Button
let deleteBtn = document.createElement('div');
deleteBtn.classList.add('btnDelete');
deleteBtn.innerText = 'X';
deleteBtn.onclick = function(){
todoItem.remove();
}
todoItem.appendChild(todoText);
todoItem.appendChild(CreateDate)
todoItem.appendChild(deleteBtn);
let todoItemsContainer = document.getElementById('todoItemsContainer');
todoItemsContainer.appendChild(todoItem);
}
// Item Entry and Validation
function ToDoItemHandler(){
let userInput = document.getElementById('toDoEntry');
let userInputValue = userInput.value;
if(userInputValue == ''){
alert('Entry can not be empty!')
}else{
createToDoItem(userInputValue);
userInput.value = '';
}
}
// Add Item Button
let btnAddItem = document.getElementById('btnAddItem');
btnAddItem.onclick = ToDoItemHandler;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href = './style/style.css' rel='stylesheet'>
<title>To-Do-List</title>
</head>
<body>
<div id = 'container'>
<div id="toDoHeader">
<h1>To-Do List</h1>
<div id = 'toDoContent'>
<input type = 'text' id = 'toDoEntry' name = 'toDoEntry' placeholder = 'Add item here'>
<button type = 'button' id = 'btnAddItem' name = 'addToDoList'>Add</button>
<button type = 'button' id = 'btnDeleteItem' name = 'deleteList'>Delete All</button>
</div>
</div>
<div id="todoItemsContainer">
</div>
</div>
<script src = './js/app.js'></script>
</body>
</html>

Change your delete function to
let btnDeleteItem = document.getElementById('btnDeleteItem');
btnDeleteItem.onclick = function (){
const items = document.querySelectorAll('.row') // select all todos
items.forEach(el => {
el.remove() // remove each one
})
}
function selectColorStatus(event) {
let target = event.target;
target.classList.toggle('todoTextSelected');
}
function createToDoItem(userInputValue) {
// To-Do Item Container
let todoItem = document.createElement("div");
todoItem.classList.add("row", "flx");
todoItem.onclick = selectColorStatus;
// Clear List
let btnDeleteItem = document.getElementById('btnDeleteItem');
btnDeleteItem.onclick = function () {
const items = document.querySelectorAll('.row')
items.forEach(el => {
el.remove()
})
}
// Inner Text
let todoText = document.createElement('div');
todoText.classList.add('grow');
todoText.innerText = userInputValue;
// Date
let CreateDate = document.createElement('div');
CreateDate.classList.add('date');
let date = new Date();
year = date.getFullYear();
month = date.getMonth();
day = date.getDay();
CreateDate.innerText = 'Created at ' + year + '-' + month + '-' + day;
// Delete Button
let deleteBtn = document.createElement('div');
deleteBtn.classList.add('btnDelete');
deleteBtn.innerText = 'X';
deleteBtn.onclick = function () {
todoItem.remove();
}
todoItem.appendChild(todoText);
todoItem.appendChild(CreateDate)
todoItem.appendChild(deleteBtn);
let todoItemsContainer = document.getElementById('todoItemsContainer');
todoItemsContainer.appendChild(todoItem);
}
// Item Entry and Validation
function ToDoItemHandler() {
let userInput = document.getElementById('toDoEntry');
let userInputValue = userInput.value;
if (userInputValue == '') {
alert('Entry can not be empty!')
} else {
createToDoItem(userInputValue);
userInput.value = '';
}
}
// Add Item Button
let btnAddItem = document.getElementById('btnAddItem');
btnAddItem.onclick = ToDoItemHandler;
<div id = 'container'>
<div id="toDoHeader">
<h1>To-Do List</h1>
<div id = 'toDoContent'>
<input type ='text' id='toDoEntry' name ='toDoEntry' placeholder = 'Add item here'>
<button type ='button' id='btnAddItem' name ='addToDoList'>Add</button>
<button type ='button' id='btnDeleteItem' name ='deleteList'>Delete All</button>
</div>
</div>
<div id="todoItemsContainer">
</div>
</div>

simply do:
// Clear List
let btnDeleteItem = document.getElementById('btnDeleteItem');
btnDeleteItem.onclick = function () {
document.getElementById('todoItemsContainer').innerHTML = ''
}

Related

Elements that were returned from a function don't work with event listeners

There is a quest I've been trying to solve for quite a time.
In my code, I have a "To-Do List".
And there, I want to make the buttons ("doneButton", "deleteButton") workable with "addEventListener".
Somehow, the buttons don't work as expected.
When I run this within the code console.log(todoItem.doneButton), it shows the correct button.
But just the line below, where I try to "addEventListener" to the same very element, it doesn't work at all.
(function() {
function createAppTitle(title) {
let appTitle = document.createElement('h2');
appTitle.textContent = title;
appTitle.classList.add('mt-5', 'mb-3');
return appTitle;
}
function createToDoList() {
let list = document.createElement('ul')
return list;
}
function createToDoForm() {
let buttonWrapper = document.createElement('div')
let form = document.createElement('form')
let input = document.createElement('input')
let button = document.createElement('button')
form.classList.add('input-group', 'mb-3');
input.classList.add('form-control');
input.placeholder = 'Enter the name of the task';
buttonWrapper.classList.add('input-group-append');
button.classList.add('btn', 'btn-primary');
button.textContent = 'Add a task';
buttonWrapper.append(button);
form.append(input);
form.append(buttonWrapper);
return {
form,
input,
button
};
}
function createToDoItem (name) {
let item = document.createElement('li')
let buttonGroup = document.createElement('div')
let doneButton = document.createElement('button')
let deleteButton = document.createElement('button')
item.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'align-items-center');
item.textContent = name;
buttonGroup.classList.add('btn-group','btn-group-sm');
doneButton.classList.add('btn','btn-success');
doneButton.textContent = "Done";
deleteButton.classList.add('btn','btn-danger');
deleteButton.textContent = 'Delete';
buttonGroup.append(doneButton);
buttonGroup.append(deleteButton);
item.append(buttonGroup);
return {
item,
doneButton,
deleteButton
}
}
document.addEventListener('DOMContentLoaded', function () {
let container = document.querySelector('.container');
let appTitle = createAppTitle('Name of the Target');
let list = createToDoList();
let form = createToDoForm();
let todoItems = [createToDoItem('Book your trip'), createToDoItem('Fly to Dubai'), createToDoItem('Book' +
' your trip')];
container.append(appTitle);
container.append(form.form);
container.append(list);
list.append(todoItems[0].item)
list.append(todoItems[1].item)
list.append(todoItems[2].item)
form.form.addEventListener('submit', (e)=> {
e.preventDefault();
if (!form.input.value) {
return;
}
let todoItem = createToDoItem(form.input.value);
console.log(todoItem.doneButton)
todoItem.doneButton.addEventListener('click', function () {
console.log('done button clicked');
});
todoItem.deleteButton.addEventListener('click', ()=> {
console.log('delete button clicked');
})
list.append(createToDoItem(form.input.value).item)
form.input.value = '';
});
})
})();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ToDo</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
crossorigin="anonymous">
<script src="index.js" defer></script>
</head>
<body>
<div id="toDo" class="container"></div>
</body>
</html>
You should attach the event inside the createToDoItem()
(function() {
function createAppTitle(title) {
let appTitle = document.createElement('h2');
appTitle.textContent = title;
appTitle.classList.add('mt-5', 'mb-3');
return appTitle;
}
function createToDoList() {
let list = document.createElement('ul')
return list;
}
function createToDoForm() {
let buttonWrapper = document.createElement('div')
let form = document.createElement('form')
let input = document.createElement('input')
let button = document.createElement('button')
form.classList.add('input-group', 'mb-3');
input.classList.add('form-control');
input.placeholder = 'Enter the name of the task';
buttonWrapper.classList.add('input-group-append');
button.classList.add('btn', 'btn-primary');
button.textContent = 'Add a task';
buttonWrapper.append(button);
form.append(input);
form.append(buttonWrapper);
return {
form,
input,
button
};
}
function createToDoItem (name) {
let item = document.createElement('li')
let buttonGroup = document.createElement('div')
let doneButton = document.createElement('button')
let deleteButton = document.createElement('button')
item.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'align-items-center');
item.textContent = name;
buttonGroup.classList.add('btn-group','btn-group-sm');
doneButton.classList.add('btn','btn-success');
doneButton.textContent = "Done";
deleteButton.classList.add('btn','btn-danger');
deleteButton.textContent = 'Delete';
buttonGroup.append(doneButton);
buttonGroup.append(deleteButton);
item.append(buttonGroup);
doneButton.addEventListener('click', function () {
console.log('done button clicked');
});
deleteButton.addEventListener('click', ()=> {
console.log('delete button clicked');
})
return {
item,
doneButton,
deleteButton
}
}
document.addEventListener('DOMContentLoaded', function () {
let container = document.querySelector('.container');
let appTitle = createAppTitle('Name of the Target');
let list = createToDoList();
let form = createToDoForm();
let todoItems = [createToDoItem('Book your trip'), createToDoItem('Fly to Dubai'), createToDoItem('Book' +
' your trip')];
container.append(appTitle);
container.append(form.form);
container.append(list);
list.append(todoItems[0].item)
list.append(todoItems[1].item)
list.append(todoItems[2].item)
form.form.addEventListener('submit', (e)=> {
e.preventDefault();
if (!form.input.value) {
return;
}
let todoItem = createToDoItem(form.input.value);
console.log(todoItem.doneButton)
list.append(createToDoItem(form.input.value).item)
form.input.value = '';
});
})
})();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ToDo</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
crossorigin="anonymous">
<script src="index.js" defer></script>
</head>
<body>
<div id="toDo" class="container"></div>
</body>
</html>

All buttons only affect one input instead of respective input

I am making a little project for my self. So basically its main function is to create a base counter for each game.
For example: If there are two players it should create three bases. (This is for the card game "smash up" if that helps you understand better.) But when the Buttons populate they all only effect the last input. I can not figure out how to make them effect their respective inputs.
The problem I am having is that every button I click only effects the last input.
<html>
<title> Base Maker </title>
<body>
<div>
<hl> Score Keeper </h1>
<hr>
<input type = "text" placeholder = "How many players?">
<button id = "enter" onclick = "baseMaker()">
Enter
</button>
</div>
<p></p>
</body>
</html>
var parent = document.querySelector("p");
var input = document.querySelector("input");
var enter = document.getElementById("enter");
function baseMaker()
{
for(var i = 0; i <= input.value; i++)
{
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement( "input");
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement( "button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', function() {
score.value++; });
//downbutton
var downButton = document.createElement( "button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', function() {
score.value--; });
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
input.value = "";
}
This is a common thing to run into especially when not using a framework in javascript.
I am not sure why this happens but when a function is defined directly in a loop, the closure for these created functions becomes whatever it is after the last iteration. I believe it is because the closure for each callback function is only "sealed up" (for lack of a better word) at the end of the loop-containing-function's execution which is after the last iteration. It's really beyond me, though.
There are some easy ways to avoid this behavior:
use bind to ensure a callback gets called with the correct input (used in solution at bottom)
create a function which creates a handler function for you and use that in the loop body
function createIncrementHandler(input, howMuch){
return () => input.valueAsNumber += howMuch;
}
/// then in your loop body:
downButton.addEventListener('click', createIncrementHandler(score, 1));
get the correct input by using the event parameter in the handler
downButton.addEventListener('click', (event) => event.target.valueAsNumber += 1);
make the entire body of the loop into a function, for example:
function createInputs(i) {
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement("input");
score.type = "number";
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement( "button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', function() {
score.value++; });
//downbutton
var downButton = document.createElement( "button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', function() {
score.value--; });
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
Here is a full example of one of the possible fixes.
<html>
<title> Base Maker </title>
<body>
<div>
<hl> Score Keeper </h1>
<hr>
<input type="text" placeholder="How many players?">
<button id="enter" onclick="baseMaker()">
Enter
</button>
</div>
<p></p>
<script>
var parent = document.querySelector("p");
var input = document.querySelector("input");
var enter = document.getElementById("enter");
function incrementInput(input, byHowMuch) {
input.valueAsNumber = input.valueAsNumber + byHowMuch;
}
function baseMaker() {
for (var i = 0; i <= input.value; i++) {
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement("input");
score.type = "number";
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement("button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', incrementInput.bind(null, score, 1));
//downbutton
var downButton = document.createElement("button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', incrementInput.bind(null, score, -1));
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
input.value = "";
}
</script>
</body>
</html>
I will do that this way :
const
AllBases = document.querySelector('#bases')
, bt_Start = document.querySelector('#game-go')
, bt_newGame = document.querySelector('#new-game')
, playerCount = document.querySelector("#play-start > input")
;
playerCount.value = ''
playerCount.focus()
playerCount.oninput = () =>
{
playerCount.value.trim()
bt_Start.disabled = (playerCount.value === '' || isNaN(playerCount.value))
playerCount.value = (bt_Start.disabled) ? ''
: (playerCount.valueAsNumber > playerCount.max) ? playerCount.max
: (playerCount.valueAsNumber < playerCount.min) ? playerCount.min
: playerCount.value
}
bt_newGame.onclick = () =>
{
playerCount.value = ''
playerCount.disabled = false
bt_Start.disabled = true
bt_newGame.disabled = true
AllBases.innerHTML = ''
playerCount.focus()
}
bt_Start.onclick = () =>
{
playerCount.disabled = true
bt_Start.disabled = true
bt_newGame.disabled = false
for(let i = 0; i <= playerCount.valueAsNumber; i++)
{
let base = document.createElement('p')
base.countValue = 20 // create a counter property on <p>
base.innerHTML = `Base ${i+1} : <span>${base.countValue}</span> <button>+</button> <button>−</button>\n`
AllBases.appendChild(base)
}
}
AllBases.onclick = ({target}) =>
{
if (!target.matches('button')) return // verify clicked element
let countElm = target.closest('p')
if (target.textContent==='+') countElm.countValue++
else countElm.countValue--
countElm.querySelector('span').textContent = countElm.countValue
}
#bases p span {
display : inline-block;
width : 6em;
border-bottom : 2px solid aqua;
padding-right : .2em;
text-align : right;
margin : 0 .3em;
}
#bases p button {
width : 2em;
margin : 0 .1em;
cursor : pointer;
}
<hr>
<hl> Score Keeper </h1>
<hr>
<div id="play-start" >
<input type="number" placeholder="How many players?" min="2" max="4">
<button id="game-go" disabled> Enter </button>
<button id="new-game" disabled> new </button>
</div>
<hr>
<div id="bases"></div>
If it helps, I can add more explanations

comment appending on the first post only in Vanilla JavaScript

I am creating a status posting and commenting system.
It is implemented in Vanilla JavaScript. Anyone can add a post and can comment on the post.
Everything is working fine but the comment section is working on first post only.
deletion of comment and post is working fine.
I don't know what's the problem is, if anyone could help me..
Here is the HTML code
<div class="container-post" id="container-post">
<div class="create-post">
<form>
<div class="form-group">
<div class="username">
<p class="name" style="top:15px;">User Name</p>
</div>
<p class="qoutes">
<textarea style=" font-size: 15pt;" class="form-control" id="enter-post" rows="7" id="mypara" placeholder="Share Your Thoughts..."></textarea>
</p>
<div class="postbar">
<button type="button" class="btn btn-primary post-me" id="post-button"> <span id="postText">Post</span></button>
</div>
</div>
</form>
</div>
<hr class="line-bar">
<div class="allpost">
<div class="mainpost" id="post-div"></div>
</div>
Here is the JavaSCript code
showTask();
showComment();
let addPost = document.getElementById("enter-post");
let addPostBtton = document.getElementById("post-button");
addPostBtton.addEventListener("click", function () {
var addPostVal = addPost.value;
if (addPostVal.trim() != 0) {
let webtask = localStorage.getItem("localtask");
if (webtask == null) {
var taskObj = [];
}
else {
taskObj = JSON.parse(webtask);
}
taskObj.push(addPostVal);
localStorage.setItem("localtask", JSON.stringify(taskObj));
}
showTask();
});
function showTask() {
let webtask = localStorage.getItem("localtask");
if (webtask == null) {
var taskObj = [];
}
else {
taskObj = JSON.parse(webtask);
}
let htmlVal = '';
let createPost = document.getElementById("post-div");
taskObj.forEach((item, index) => {
htmlVal += `
<div class="post-class"><div class="username u-name">
<p class="name i-name">${"User Name " + index}</p>
<i class="fas fa-trash-alt" onclick="removePost(${index});"></i></button>
</div>
<hr>
<p class="quotes">
${item}
</p>
<div class="comment-section" id="comment-section">
<p class="comment-qoute">
<textarea style=" font-size: 15pt;" class="form-control commentBox" rows="3" id="mypara" placeholder="Leave a comment"></textarea>
</p>
<button class="btn btn-primary comment-btn" id="commentBtn">comment</button>
<ul class="comments" id="comments-portion">
<p></p>
</ul>
</div>
</div>
<br><br>`
});
createPost.innerHTML = htmlVal;
}
function removePost(index) {
let webtask = localStorage.getItem("localtask");
let taskObj = JSON.parse(webtask);
taskObj.splice(index, 1);
localStorage.setItem("localtask", JSON.stringify(taskObj));
showTask();
}
var commentPost = document.getElementById('mypara');
var commentBtn = document.getElementById('commentBtn');
commentBtn.addEventListener('click', function () {
var commentValue = commentPost.value;
if (commentValue.trim() != 0) {
let commentTask = localStorage.getItem("comments");
if (commentTask == null) {
var commentObj = [];
}
else {
commentObj = JSON.parse(commentTask);
}
commentObj.push(commentValue);
localStorage.setItem("comments", JSON.stringify(commentObj));
}
showComment();
});
function showComment() {
let commentsTask = localStorage.getItem("comments");
if (commentsTask == null) {
var commentObj = [];
}
else {
commentObj = JSON.parse(commentsTask);
}
let commentHTMLValue = '';
var createComment = document.getElementById("comments-portion");
commentObj.forEach((item, index) => {
commentHTMLValue += `<div class="comment-box-btn">
<p>${index + ". "}<span>${item}</span></p>
<i class="far fa-times-circle fa-2x" onclick="removeComment(${index});"></i>
</div>
`;
});
createComment.innerHTML = commentHTMLValue;
}
var deleteBtn = document.querySelector('.comment-del');
deleteBtn.addEventListener('click', () => {
});
// remove comment
function removeComment(index) {
let commentTask = localStorage.getItem("comments");
let commentObj = JSON.parse(commentTask);
commentObj.splice(index, 1);
localStorage.setItem("comments", JSON.stringify(commentObj));
showComment();
}
When you use code like:
createComment.innerHTML = commentHTMLValue;
you are completely replacing the contents of the element. Try using:
createComment.innerHTML += commentHTMLValue;
which appends new content to the end of the existing contents.
I can't do a snippet here as the use of localStorage is not allowed. Copy this block into a blank file and save it as an html file and then open that in a browser.
This is how I think you are describing your requirements and is also based on the data format in my comments. It's not pretty and needs plenty of sprucing up, but it runs.
<!DOCTYPE html>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<html>
<head>
<title>Task listing</title>
<script type="text/javascript">
let taskList = [];
function checkTasks() {
let tasksList = getTasksList();
if (tasksList.length == 0) {
let newTask = prompt("Please enter a task description");
if (newTask) {
let thisIndex = getNewIndex();
let a = {"id": thisIndex, "task": newTask, "comments": []}
taskList.push(a);
saveTasksList(taskList);
}
}
displayTasks();
}
function displayTasks() {
let container = document.getElementById("tasks");
container.innerHTML = "";
let taskList = getTasksList();
taskList.forEach(function(task){
let d = document.createElement("div");
d.id = "task_" + task.id;
d.className = "commentdiv";
d.innerHTML = "<h3>" + task.task + "</h3>";
let l = document.createElement("ul");
l.id = "comments_" + task.id;
let comments = task.comments;
if (comments.length > 0) {
let commentindex = 0;
comments.forEach(function(comment) {
let c = document.createElement("li");
c.innerHTML = comment;
let cb = document.createElement("button");
cb.id = "deletecomment_" + task.id + "_" + commentindex;
cb.innerHTML = "Delete comment";
cb.onclick = function() {deleteComment(task.id, commentindex);};
c.appendChild(cb);
l.appendChild(c);
})
}
let b = document.createElement("button");
b.id = "addcomment_" + task.id;
b.onclick = function() {addComment(task.id);};
b.innerHTML = "Add comment";
d.appendChild(b);
d.appendChild(l);
container.appendChild(d);
})
}
function addComment(taskid) {
let newcomment = prompt("Enter comment");
if (newcomment) {
let tasklist = getTasksList();
let filtered = tasklist.filter(task => task.id == taskid);
if (filtered[0]) {
let thisTask = filtered[0];
thisTask.comments.push(newcomment);
let thisIndex = taskList.findIndex((task) => task.id == taskid);
taskList[thisIndex] = thisTask;
}
saveTasksList(taskList);
displayTasks();
}
}
function addNewTask() {
let newTask = prompt("Enter task description");
let taskList = getTasksList();
let lastindex = localStorage.getItem("tasksindex");
let index = getNewIndex();
let a = {"id": index, "task": newTask, "comments": []}
taskList.push(a);
saveTasksList(taskList);
displayTasks();
}
function deleteComment(taskid, commentindex) {
let tasklist = getTasksList();
let filtered = tasklist.filter(task => task.id == taskid);
// as long as there is at least one task with the taskid value, find and delete the comment
// based on the index position of the comment in the comments array
if (filtered[0]) {
let thisTask = filtered[0];
thisTask.comments.splice(commentindex, 1);
let thisIndex = taskList.findIndex((task) => task.id == taskid);
taskList[thisIndex] = thisTask;
}
saveTasksList(taskList);
displayTasks();
}
function getTasksList() {
let tasks = localStorage.getItem("tasks");
taskList = JSON.parse(tasks);
if (!taskList) {
taskList = [];
}
return taskList;
}
function saveTasksList(taskList) {
localStorage.setItem("tasks", JSON.stringify(taskList));
}
function getNewIndex() {
let lastindex = localStorage.getItem("tasksindex");
let idx = 0;
if (!lastindex) {
idx = 1;
} else {
idx = Number(lastindex) + 1;
}
localStorage.setItem("tasksindex", idx);
return idx;
}
function removeAll() {
localStorage.removeItem("tasks");
localStorage.removeItem("tasksindex");
displayTasks();
}
window.onload = checkTasks;
</script>
<style type="text/css">
.commentdiv {
border:1px solid black;
width:1000px;
padding:5px;
border-radius:5px;
}
button {
margin-left:10px;
}
h3 {
width:100%;
border-bottom: 1px dotted black;
}
ul {
list-style-type:decimal;
}
</style>
</head>
<body>
<h2>My task list <button id="addNewTaskButton" onclick="addNewTask();">Add new task</button></h2>
<hr>
<div id="tasks">
</div>
<button id="removeAll" onclick="removeAll();">Remove all tasks</button>
</body>
</html>

Repeated objects with input values

I have a javascript repeater that creates forms,
but the problem is that when I bring the values ​​they are all entered in a single object instead of separate objects, which inside array locations should create a similar structure.
"locations":[
{
"coordinates":[
-80.128473,
25.781842
],
"description":"Lummus Park Beach",
"day":1
},
{
"coordinates":[
-80.647885,
24.909047
],
"description":"Islamorada",
"day":2
},
]
My code takes information from inputs but puts it in the same object instead of separate objects.
//This is the code which take input value and inser in boject structure
const createTour_form = document.querySelector('.form-create__tour');
if (createTour_form) {
createTour_form.addEventListener('submit', (cr) => {
cr.preventDefault();
//Ceeate an empty array
let loc_coordinates = [];
let loc_description = [];
let loc_day = [];
let get_locations = [];
//Get Coordinates
document.querySelectorAll(".location_field_card").forEach(f => {
let obj = [];
f.querySelectorAll(".location_new_tour").forEach(ele => obj[ele.value] = ele.value || "");
loc_coordinates.push(Object.keys(obj));
});
//Get Descriptions
document.querySelectorAll(".location_field_card").forEach(f => {
let obj1 = {};
f.querySelectorAll(".description_location").forEach(ele => obj1[ele.name] = ele.value || "");
loc_description.push(obj1)
});
//Get Day
document.querySelectorAll(".location_field_card").forEach(f => {
let obj2 = {};
f.querySelectorAll(".location_day").forEach(ele => obj2[ele.name] = ele.value || "");
loc_day.push(obj2)
});
//Reverse Coordinates
const getGeo = [...loc_coordinates].toString().split(',').reverse().join(' ').replace(' ', ' ,');
get_locations.push(getGeo)
const getLocation = Object.values(...loc_description);
const getValLocation = getLocation.toString();
const getDay = Object.values(...loc_day);
const getValDay =parseInt(getDay.toString());
let getTotaLocation = new Object({
"coordinates":[...get_locations],
"description":getValLocation,
"day":getValDay
});
console.log(getTotaLocation);
})
}
<form class="form form-create__tour">
<h1 class="title--create--tourpage">Locations</h1>
<div class="form__group all_tours_options">
<div id="add_location_field">
<div class="location_field_card">
<p class="subfield_natours_create_tour">Location</p>
<input class="form__input location_new_tour" type="text" value="24.5647846,-81.8068843">
<p class="subfield_natours_create_tour">Location Description</p>
<input class="form__input description_location" type="text" value="Lummus Park Beach">
<p class="subfield_natours_create_tour">Day</p>
<input class="form__input location_day" type="number" value="1" >
</div>
</div>
<button class="btn btn--small--add btn--green" id="add_location_fields">Add Location Field</button>
</div>
<div class="form__group right"><button class="btn btn--small btn--green" id="createTour">Create Tour</button></div>
</form>
<!--This Javascript code generate new fields when Add Locaton field is clicked-->
<script>
const addLocation = document.getElementById('add_location_fields');
if(addLocation){
let count_createdCards = 0;
let count_Deletebutton = 0;
let incrementFunction = 0;
addLocation.addEventListener('click',(st)=>{
st.preventDefault();
let createAddField = document.getElementById('add_location_field');
// Crd
count_createdCards++;
count_Deletebutton ++;
incrementFunction ++;
let card = document.createElement('div');
card.setAttribute('class','location_field_card');
card.setAttribute('id','delete_card_'+ count_createdCards)
//First Card Title
let cartTitle1 = document.createElement('p');
cartTitle1.setAttribute('class','subfield_natours_create_tour');
cartTitle1.textContent = 'Location';
let inputLocation = document.createElement('input');
inputLocation.classList.add('form__input');
inputLocation.classList.add('location_new_tour');
inputLocation.setAttribute('type','text');
inputLocation.setAttribute('value','24.5647846,-81.8068843');
//Second Card Title
let cartTitle2 = document.createElement('p');
cartTitle2.setAttribute('class','subfield_natours_create_tour');
cartTitle2.textContent = 'Location Description';
let inputDescription_location = document.createElement('input');
inputDescription_location.classList.add('form__input');
inputDescription_location.classList.add('description_location');
inputDescription_location.setAttribute('type','text');
inputDescription_location.setAttribute('value','Lummus Park Beach');
//Third Card Title
let cartTitle3 = document.createElement('p');
cartTitle3.setAttribute('class','subfield_natours_create_tour');
cartTitle3.textContent = 'Day';
let inputDescription_day = document.createElement('input');
inputDescription_day.classList.add('form__input');
inputDescription_day.classList.add('location_day');
inputDescription_day.setAttribute('type','number');
inputDescription_day.setAttribute('value','1');
let removeButton = document.createElement('a');
removeButton.classList.add('btn');
removeButton.classList.add('btn--small--add');
removeButton.classList.add('btn--red');
removeButton.setAttribute('onclick','removeAction_'+count_Deletebutton+'()');
let removeScript = document.createElement('script');
removeScript.innerHTML = "function removeAction_".concat(count_Deletebutton, "() {\n\n var delCard_")
.concat(incrementFunction, " = document.getElementById(\"delete_card_")
.concat(count_createdCards, "\");\ndelCard_")
.concat(incrementFunction, ".remove();}");
removeButton.textContent = 'Remove Location Field';
card.appendChild(cartTitle1);
card.appendChild(inputLocation);
card.appendChild(cartTitle2);
card.appendChild(inputDescription_location);
card.appendChild(cartTitle3);
card.appendChild(inputDescription_day);
card.appendChild(removeButton);
card.appendChild(removeScript);
createAddField.appendChild(card);
});
}
</script>
I solved the problem by adding in the folds that repeat the dynamic id:
//Increment Coordinates
let incrementCoordiantes = 0;
//Increment Description
let incrementDescription = 0;
//Increment Day
let incrementDay = 0;
addLocation.addEventListener('click',(st)=>{
let createAddField = document.getElementById('add_location_field');
incrementCoordiantes ++;
incrementDescription ++;
incrementDay ++;
let card = document.createElement('div');
......
inputLocation.setAttribute('id','getCoordinates_'+ incrementCoordiantes);
inputDescription_location.setAttribute('id','getDescription_' + incrementDescription);
inputDescription_day.setAttribute('id','getDay_' + incrementDay );
I use querySelectorAll to get the number of colums from repeater and after that I use for to incremet id to match the id from html file, all the value it's push after that in an array, and it's work.
const push_location_data = [];
const getAll_locations = document.querySelectorAll(".location_field_card");
for (let i=1; i< getAll_locations.length; i++) {
let cord_lat_lng = 'getCoordinates_' + i;
let cord_description = 'getDescription_' + i;
let cord_day = 'getDay_' + i;
let dinamic_obj = {
coordinates:[[document.getElementById(cord_lat_lng).value].toString().split(',').reverse().join(' ').replace(' ', ' ,')],
description:document.getElementById(cord_description).value,
day:document.getElementById(cord_day).value
}
push_location_data.push(dinamic_obj);
};
location arrray

How to remove array objects from localStorage using dynamic buttons? [JS only]

New to JS here, been struggling with this one for a few hours now.
So I created a to do list with a button that stores objects in an array inside localStorage and also creates dynamic list items with content and delete buttons. Whenever I click the delete button it removes the dynamic list item but doesn't remove it from localStorage. I can't figure out how to assign each button to the specific array index in localStorage.
https://codepen.io/jupiterisland/pen/ooPXWV
var taskList = []; //build array
if(localStorage.taskList){ //call func to recreate li's on refresh
taskList = JSON.parse(localStorage.taskList) || [];
createTasks(taskList)
}
function submitFunc() {
var task = { //build objects
desc: document.getElementsByTagName("textarea")[0].value,
date: document.getElementsByTagName("input")[0].value,
time: document.getElementsByTagName("input")[1].value,
important: document.getElementsByTagName("input")[1].checked
};
if(task.desc && task.date !== ""){
taskList[taskList.length] = task; //put objects inside array
localStorage.taskList = JSON.stringify(taskList); //store array with stringify
newTaskList = JSON.parse(localStorage.taskList); //retrieve array with parse
createTasks(newTaskList)
document.getElementById("error").style.display = "none";
return false; //prevent submit
} else {
document.getElementById("error").style.display = "block";
document.getElementById("error").innerHTML = "Please enter a task description and a date.";
return false;
}
}
function createTasks (newTaskList){
for (i = 0; i < newTaskList.length; i++) { // display objects in list items
var currentTask = newTaskList[i];
var taskIndex = newTaskList.indexOf(currentTask);
newElement();
function newElement() {
var liNode = document.createElement("li");
var titleNode = document.createElement("h3");
var dNode = document.createElement("p");
var tNode = document.createElement("p");
var delNode = document.createElement("button")
liNode.className = "liNode";
titleNode.className = "titleNode";
dNode.className = "dNode";
tNode.className = "tNode";
delNode.className = "delete";
delNode.innerText = "Delete";
var titleText = newTaskList[i].desc;
var dateText = newTaskList[i].date;
var timeText = newTaskList[i].time;
var descNode = document.createTextNode(titleText);
var dateNode = document.createTextNode(dateText);
var timeNode = document.createTextNode(timeText);
titleNode.appendChild(descNode);
dNode.appendChild(dateNode);
tNode.appendChild(timeNode);
liNode.appendChild(titleNode);
liNode.appendChild(dNode);
liNode.appendChild(tNode);
liNode.appendChild(delNode);
document.getElementById("taskBoard").appendChild(liNode);
if (taskBoard.childElementCount > newTaskList.length) { //remove excess divs
for (n = 0; taskBoard.childElementCount - 2; n++) {
taskBoard.removeChild(taskBoard.firstChild);
}
}
function deleteTasks(){
var listItem = this.parentNode;
var ul = listItem.parentNode;
ul.removeChild(listItem);
}
delNode.addEventListener("click", deleteTasks);
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>My Task Board</h1>
<div class="container">
<form onsubmit="return submitFunc()">
<div>
<label for="">Task:</label>
<textarea name="name" rows="8" cols="80"placeholder="Please enter your task description"></textarea>
</div>
<div>
<label for="">Deadline:</label>
<input type="date" placeholder="Choose a date">
<input type="time" placeholder="Set time">
</div>
<div>
<label for="">Important:</label>
<input type="checkbox" name="" value="">
</div>
<button type="submit" name="button">Add Task</button>
<div id="error"></div>
</form>
</div>
<div>
<ul id="taskBoard"></ul>
</div>
</body>
</html>
var taskList = []; //build array
if(localStorage.taskList){ //call func to recreate li's on refresh
taskList = JSON.parse(localStorage.taskList) || [];
createTasks(taskList)
}
function fakeGuid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
function submitFunc() {
var task = { //build objects
desc: document.getElementsByTagName("textarea")[0].value,
date: document.getElementsByTagName("input")[0].value,
time: document.getElementsByTagName("input")[1].value,
important: document.getElementsByTagName("input")[1].checked,
id :fakeGuid()
};
if(task.desc && task.date !== ""){
taskList[taskList.length] = task; //put objects inside array
localStorage.taskList = JSON.stringify(taskList); //store array with stringify
newTaskList = JSON.parse(localStorage.taskList); //retrieve array with parse
createTasks(newTaskList)
document.getElementById("error").style.display = "none";
return false; //prevent submit
} else {
document.getElementById("error").style.display = "block";
document.getElementById("error").innerHTML = "Please enter a task description and a date.";
return false;
}
}
function createTasks (newTaskList){
for (i = 0; i < newTaskList.length; i++) { // display objects in list items
newElement(i);
function newElement(currentIndex) {
var liNode = document.createElement("li");
var titleNode = document.createElement("h3");
var dNode = document.createElement("p");
var tNode = document.createElement("p");
var delNode = document.createElement("button")
liNode.className = "liNode";
titleNode.className = "titleNode";
dNode.className = "dNode";
tNode.className = "tNode";
delNode.className = "delete";
delNode.innerText = "Delete";
var titleText = newTaskList[i].desc;
var dateText = newTaskList[i].date;
var timeText = newTaskList[i].time;
var descNode = document.createTextNode(titleText);
var dateNode = document.createTextNode(dateText);
var timeNode = document.createTextNode(timeText);
titleNode.appendChild(descNode);
dNode.appendChild(dateNode);
tNode.appendChild(timeNode);
liNode.appendChild(titleNode);
liNode.appendChild(dNode);
liNode.appendChild(tNode);
liNode.appendChild(delNode);
document.getElementById("taskBoard").appendChild(liNode);
if (taskBoard.childElementCount > newTaskList.length) { //remove excess divs
for (n = 0; taskBoard.childElementCount - 2; n++) {
taskBoard.removeChild(taskBoard.firstChild);
}
}
function deleteTasks(node, currentTask) {
var listItem = node.parentNode;
var ul = listItem.parentNode;
ul.removeChild(listItem);
taskList = taskList.filter(function(t) {
return t.id !== currentTask.id;
});
localStorage.taskList = JSON.stringify(taskList); //store array with stringify
}
var currentTask = newTaskList[currentIndex];
delNode.addEventListener("click", () => deleteTasks(delNode, currentTask));
}
}
}
Don't try to use index to manipulate DOM element. Instead use some kind of unique ID. In this case I created a fake GUID.
Read more on closure. The reason you are not able to pass index down to the function is because the index is bound to another context.
Any reason to stringify JSON for local storage? You can simply store an array.

Categories