Buttons only affecting every other div instead of every single div - javascript

I am trying to create a "library" where you can add books by yourself and they also get a "remove" button that removes the book and a "change status" button that changes the status of the book has been read or not.
Everything works fine except the "change status" button, which only lets the user change the status of every other book. for example if you add 4 books you would only be able to change book 2 and 4, if you add 5 books you can only change books 1,3,5 instead of working for all of them.
const myLibrary = [];
function Book(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
// Prototype functions
Book.prototype.info = function() {
return `${this.title} by ${this.author}, ${this.pages} pages, ${this.read}`;
};
Book.prototype.changeStatus = function() {
if ((this.read) == 'Already read') {
this.read = 'Haven\'t read yet';
} else if ((this.read) == 'Haven\'t read yet') {
this.read = 'Already read';
}
}
// Add a new book to the array
function addBookToLibrary(title, author, pages, read) {
const newBook = new Book(title, author, pages, read);
myLibrary.push(newBook);
}
// Examples
addBookToLibrary('Title', 'Author', 251, 'Already read');
addBookToLibrary('The book', 'John Smith', 511, 'Already read');
addBookToLibrary('Rich quick', 'Robert', 2541, 'Haven\'t read yet');
addBookToLibrary('How to code', 'Odin', 221, 'Already read');
const books = document.querySelector('.books');
// Display examples for testing
for (let i = 0; i < myLibrary.length; i++) {
console.log(myLibrary[i].info());
const container = document.createElement('div');
books.appendChild(container);
const div = document.createElement('div');
div.textContent = myLibrary[i].info();
container.appendChild(div);
}
// Display submitted books
function displayBooks() {
const index = myLibrary.length - 1;
const container = document.createElement('div');
container.classList.add('bookContainer');
container.setAttribute('data-', `${index}`);
books.appendChild(container);
const div = document.createElement('div');
div.classList.add('aBook');
div.setAttribute('data-', `${index}`);
div.textContent = myLibrary[index].info();
container.appendChild(div);
const btn1 = document.createElement('button');
btn1.classList.add('remover');
btn1.setAttribute('data-', `${index}`);
btn1.textContent = 'Remove';
container.appendChild(btn1);
createRemover();
const btn2 = document.createElement('button');
btn2.classList.add('changer');
btn2.setAttribute('data-', `${index}`);
btn2.textContent = 'Change Status';
container.appendChild(btn2);
createChanger();
}
const form = document.querySelector('form');
form.style.display = "none"
// Event handler for new book button
function toggleFormOn() {
form.style.display = "block"
}
// Event handler for submit form button
function toggleFormOff(event) {
const createBook = [];
const inputs = document.querySelectorAll('input');
const select = document.querySelector('select');
inputs.forEach((input) => {
console.log(input.value);
createBook.push(input.value);
input.value = '';
})
console.log(select.value);
createBook.push(select.value);
form.style.display = "none";
console.log(createBook);
addBookToLibrary(...createBook)
for (let i = 0; i < myLibrary.length; i++) {
console.log(myLibrary[i].info());
}
displayBooks();
event.preventDefault();
}
// Basic Event listeners
const newBtn = document.querySelector('#newBtn');
newBtn.addEventListener('click', toggleFormOn);
const subBtn = document.querySelector('#sub');
subBtn.addEventListener('click', toggleFormOff);
// Event listening and handling
function createRemover() {
const removeBtn = document.querySelectorAll('.remover');
removeBtn.forEach((button) => {
button.addEventListener('click', function(e) {
const placement = button.getAttribute('data-');
const bookDiv = document.querySelectorAll('.bookContainer');
bookDiv.forEach((div) => {
if (div.firstElementChild.textContent == (myLibrary[placement].info())) {
div.remove();
}
})
})
})
}
function createChanger() {
const changeBtn = document.querySelectorAll('.changer');
changeBtn.forEach((button) => {
button.addEventListener('click', function(e) {
const placement = button.getAttribute('data-');
const bookDiv = document.querySelectorAll('.bookContainer');
bookDiv.forEach((div) => {
if (div.firstElementChild.textContent == (myLibrary[placement].info())) {
myLibrary[placement].changeStatus();
div.firstElementChild.textContent = myLibrary[placement].info();
}
})
})
})
}
<div class="books">
</div>
<button id="newBtn">NEW BOOK</button>
<form>
<ul>
<li>
<label for="bookTitle">Title</label>
<input type="text" id="bookTitle" name="bookTitle">
</li>
<li>
<label for="bookAuthor">Author</label>
<input type="text" id="bookAuthor" name="bookAuthor">
</li>
<li>
<label for="bookPages">Pages</label>
<input type="text" id="bookPages" name="bookPages">
</li>
<li id="heading">Did you read it?</li>
<li>
<select name="bookRead" id="bookRead">
<option value="Already read">Read</option>
<option value="Haven't read yet">Didn't read</option>
</select>
</li>
<li class="btn">
<button type="submit" id="sub">Submit</button>
</li>
</ul>
</form>
I tried changing a lot of stuff: tweaking the html structure, modifying the createChanger() and also displayBooks(). Nothing seems to work since I can't identify the issue that is causing it to only change every other book and not every single book.

Related

How do I make a button delete an item from array in JavaScript?

I'm currently making a Library project, and I made it so that each book entered is stored in an array (in this case, the array is myLibrary). Then I made it so that each book in the array creates a new div with the class of "card." I've implemented a "Remove Button" for each card, but I'm not sure as to how I can make the button delete the book from the array. Any help would be appreciated, thank you.
I've tried
const remBtn = document.createElement("button");
card.appendChild(remBtn);
remBtn.textContent = "Remove";
remBtn.onclick = remBook;
// Remove book function
function remBook() {
const findBook = myLibrary.findIndex((element) => element === book);
const delBook = myLibrary.slice(findBook, 1);
}
Here are my codes:
html:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Library</title>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div class="header">Library</div>
<form id="submitInput" action="">
<label for="title">Title:</label>
<input type="text" id="formTitle" name="title" required />
<label for="author">Author:</label>
<input type="text" id="formAuthor" name="author" required />
<label for="page">Page:</label>
<input type="text" id="formPage" name="page" required />
<div class="read">
<label for="read">Read</label>
<input type="checkbox" id="formRead" name="read" value="" />
</div>
<input type="submit" id="submitBtn" value="Add Book" />
</form>
<div class="currentDisplay"></div>
</body>
<script src="./script.js"></script>
</html>
JS:
// Data inputs
let myLibrary = [
{
title: "test",
author: "test",
page: "123",
read: true,
},
];
// Object constructor
function book(title, author, page, read) {
this.title = title;
this.author = author;
this.page = page;
this.read = read;
}
// Add new books to library
function addBookToLibrary() {
let a = document.getElementById("formTitle").value;
let b = document.getElementById("formAuthor").value;
let c = document.getElementById("formPage").value;
let d = document.getElementById("formRead").checked;
if (a !== "" && b !== "" && c !== "") {
myLibrary.push(new book(a, b, c, d));
}
}
const submit = document.getElementById("submitInput");
submit.addEventListener("submit", () => {
event.preventDefault();
addBookToLibrary();
submit.reset();
displayBooks();
});
// Display each book as cards
function displayBooks() {
const currentDisplay = document.querySelector(".currentDisplay");
currentDisplay.textContent = "";
myLibrary.forEach((myLibrary) => {
let card = document.createElement("div");
card.classList.add("card");
currentDisplay.appendChild(card);
for (let key in myLibrary) {
const text = document.createElement("p");
text.textContent = `${key}: ${myLibrary[key]}`;
card.appendChild(text);
}
const readBtn = document.createElement("button");
card.appendChild(readBtn);
if (myLibrary.read === true) {
readBtn.textContent = "Read";
}
if (myLibrary.read === false) {
readBtn.textContent = "Not Read";
}
readBtn.addEventListener("click", () => {
if (readBtn.textContent === "Read") {
readBtn.textContent = "Not Read";
myLibrary.read = false;
} else if (readBtn.textContent === "Not Read") {
readBtn.textContent = "Read";
myLibrary.read = true;
}
});
const remBtn = document.createElement("button");
card.appendChild(remBtn);
remBtn.textContent = "Remove";
remBtn.onclick = remBook;
});
}
// Remove book function
function remBook() {
const findBook = myLibrary.findIndex((element) => element === book);
const delBook = myLibrary.slice(findBook, 1);
}
displayBooks();
First let's give each Book object a unique property.
// Object constructor
function Book(title, author, page, read) {
this.bookId = `book${++Book.id}`;
this.title = title;
this.author = author;
this.page = page;
this.read = read;
}
//static property
Book.id = 0;
While rendering a book we use the bookId property as class name for the div. This will be used for deleting the element.
card.classList.add(`${myLibrary.bookId}`);
Inside remove book function, we find the book using bookId property. we use the splice method to remove an element from array. Then we call the remove method on div element to delete the div.
// Remove book function
function remBook() {
const bookId = this.parentElement.classList[1];
const findBook = myLibrary.findIndex(
(element) => element.bookId === bookId
);
const delBook = myLibrary.splice(findBook, 1);
this.parentElement.remove();
}
// Data inputs
let myLibrary = [{
title: 'test',
author: 'test',
page: '123',
read: true,
}, ];
// Object constructor
function Book(title, author, page, read) {
this.bookId = `book${++Book.id}`;
this.title = title;
this.author = author;
this.page = page;
this.read = read;
}
//static property
Book.id = 0;
// Add new books to library
function addBookToLibrary() {
let a = document.getElementById('formTitle').value;
let b = document.getElementById('formAuthor').value;
let c = document.getElementById('formPage').value;
let d = document.getElementById('formRead').checked;
if (a !== '' && b !== '' && c !== '') {
myLibrary.push(new Book(a, b, c, d));
}
}
const submit = document.getElementById('submitInput');
submit.addEventListener('submit', () => {
event.preventDefault();
addBookToLibrary();
submit.reset();
displayBooks();
});
// Display each book as cards
function displayBooks() {
const currentDisplay = document.querySelector('.currentDisplay');
currentDisplay.textContent = '';
myLibrary.forEach((myLibrary) => {
let card = document.createElement('div');
card.classList.add('card');
card.classList.add(`${myLibrary.bookId}`);
currentDisplay.appendChild(card);
for (let key in myLibrary) {
const text = document.createElement('p');
text.textContent = `${key}: ${myLibrary[key]}`;
card.appendChild(text);
}
const readBtn = document.createElement('button');
card.appendChild(readBtn);
if (myLibrary.read === true) {
readBtn.textContent = 'Read';
}
if (myLibrary.read === false) {
readBtn.textContent = 'Not Read';
}
readBtn.addEventListener('click', () => {
if (readBtn.textContent === 'Read') {
readBtn.textContent = 'Not Read';
myLibrary.read = false;
} else if (readBtn.textContent === 'Not Read') {
readBtn.textContent = 'Read';
myLibrary.read = true;
}
});
const remBtn = document.createElement('button');
card.appendChild(remBtn);
remBtn.textContent = 'Remove';
remBtn.onclick = remBook;
});
}
// Remove book function
function remBook() {
const bookId = this.parentElement.classList[1];
const findBook = myLibrary.findIndex(
(element) => element.bookId === bookId
);
const delBook = myLibrary.splice(findBook, 1);
this.parentElement.remove();
}
displayBooks();
<div class="header">Library</div>
<form id="submitInput" action="">
<label for="title">Title:</label>
<input type="text" id="formTitle" name="title" required />
<label for="author">Author:</label>
<input type="text" id="formAuthor" name="author" required />
<label for="page">Page:</label>
<input type="text" id="formPage" name="page" required />
<div class="read">
<label for="read">Read</label>
<input type="checkbox" id="formRead" name="read" value="" />
</div>
<input type="submit" id="submitBtn" value="Add Book" />
</form>
<div class="currentDisplay"></div>
I think you can add specific ids whenever you add a new card. And call the card classes using querySelectorAll. That will return you a nodelist. Loop that nodelist and check if the specific id that you are click right now match with the looped element's id. If true, you can do your stuffs in that loop cuz whatever you're doing will only apply to the button that you're clicking.
I made a sample here. By the way, I used JSON to check the condition in string state.
function remBook(obj) {
let card = document.querySelectorAll(".card");
for(let x=0; x<card.length; x++) {
if(JSON.stringfy(card[y].id) === JSON.stringfy(obj.id) {
/* You can do your stuff here using index */
}
}
}
https://jsfiddle.net/xw26rbvc/

How do I add user input to list, strike through task on mark on complete and localstore the lists?

What I am trying to achieve is the following with my code:
User input is printed on created task?
currently, as it stands, the user input is not printed and I am not sure how to achieve that.
How to make it that when the checkbox is ticked the word is strikethrough with a line?
I know if I do
if(checkbox) {element.style.textDecoration ="line-through"
but I am not sure how to call the element
How to make the list local storage?
I know the local storage is saves on the browser, but I am not sure where to put the local storage in this code that I wrote.
/************************************
* creates an object of elements needed *
************************************/
const elements = {
form: document.querySelector("#new-task-form"),
input: document.querySelector("#new-task-input"),
list: document.querySelector("#tasks"),
cal: document.querySelector("#calendar")
}
/****************************
* Generates an ID for task *
****************************/
const createId = () => `${Math.floor(Math.random() * 10000)}-${new Date().getTime()}`
/**********************************************
* function that creates the HTML elements *
**********************************************/
const createTask = () => {
const id = createId()
const task = elements.input.value;
const date = elements.cal.value;
if(!task && !date) return alert("Please fill in task and select date");
if(!task) return alert("Please fill in task");
if(!date) return alert("Please select date");
const tasks = document.createElement("div");
tasks.innerHTML = `
<button class = "sort">Sort</button>
<div class="task" data-id = "${id}">
<div class="content">
<input type ="checkbox" class="tick">
<input type ="text" class = "text" id = "text" readonly>${texting}
<label class = "due-date" for ="text">${date}</label>
<input type ="date" class = "date" id = "date">
</div>
<div class = "actions">
<button class="edit" data-id="${id}">Edit</button>
<button class="delete" data-id="${id}">Delete</button>
</div>
</div>
`
elements.list.appendChild(tasks)
return tasks
}
/**************************************************************
* Event that listens for the edit,save and delete buttons *
**************************************************************/
elements.list.addEventListener('click',event => {
const {target} = event
const {id} = target.dataset
const {texting} = target.dataset
const task = id ? document.querySelector(`[data-id="${id}"]`):null;
const taskList = document.querySelector('text')
const type = {
edit: event.target.classList.contains('edit'),
delete: event.target.classList.contains('delete')
}
const isFromSaveLabel = target.innerText.toLowerCase() === 'save'
//Checking to see if buttons are pressed
if(task && type.edit && isFromSaveLabel){
const text = task.querySelector('text')
target.innerText = 'Edit'
text.setAttribute('readonly','true')
return
};
if(task && type.edit){
const text = task.querySelector('text')
target.innerText = 'save'
text.removeAttribute('readonly')
text.focus()
return
};
if(task && type.delete){
return
}
});
/*******************************************************************
* Submits the HTML elements to have the lists submited and created*
*******************************************************************/
const submitHandler = (event) =>{
event.preventDefault();
createTask();
}
elements.form.addEventListener("submit", submitHandler);
The javascript code above is the action once the task has been created.
You can find the version where it is running here - https://jsfiddle.net/blaze92/seLvzd1h/
TO ANSWER ONE QUESTION AT A TIME
To achieve the strike through
Create a separate function for that and run it every time you add new element as follows
function Listen(){
var allCheckboxes=document.querySelectorAll('.tick')
allCheckboxes.forEach(checkbox=>{
checkbox.addEventListener('change',(e)=>{
var parentElem=e.target.parentElement
if(e.target.checked){
parentElem.style.textDecoration ="line-through"
}else{
parentElem.style.textDecoration ="none"
}
})
})
}
Then you can call the listen() function
At the bottom of createTask() after The append statement
Full code
/************************************
* creates an object of elements needed *
************************************/
const elements = {
form: document.querySelector("#new-task-form"),
input: document.querySelector("#new-task-input"),
list: document.querySelector("#tasks"),
cal: document.querySelector("#calendar")
}
/****************************
* Generates an ID for task *
****************************/
const createId = () => `${Math.floor(Math.random() * 10000)}-${new Date().getTime()}`
/**********************************************
* function that creates the HTML elements *
**********************************************/
function Listen(){
var allCheckboxes=document.querySelectorAll('.tick')
allCheckboxes.forEach(checkbox=>{
checkbox.addEventListener('change',(e)=>{
var parentElem=e.target.parentElement
if(e.target.checked){
parentElem.style.textDecoration ="line-through"
}else{
parentElem.style.textDecoration ="none"
}
})
})
}
const createTask = () => {
const id = createId()
const task = elements.input.value;
const date = elements.cal.value;
if(!task && !date) return alert("Please fill in task and select date");
if(!task) return alert("Please fill in task");
if(!date) return alert("Please select date");
const tasks = document.createElement("div");
tasks.innerHTML = `
<button class = "sort">Sort</button>
<div class="task" data-id = "${id}">
<div class="content">
<input type ="checkbox" class="tick">
<input type ="text" class = "text" id = "text" readonly>${texting}
<label class = "due-date" for ="text">${date}</label>
<input type ="date" class = "date" id = "date">
</div>
<div class = "actions">
<button class="edit" data-id="${id}">Edit</button>
<button class="delete" data-id="${id}">Delete</button>
</div>
</div>
`
elements.list.append(tasks)
listen()
return tasks
}
/**************************************************************
* Event that listens for the edit,save and delete buttons *
**************************************************************/
elements.list.addEventListener('click',event => {
const {target} = event
const {id} = target.dataset
const {texting} = target.dataset
const task = id ? document.querySelector(`[data-id="${id}"]`):null;
const taskList = document.querySelector('text')
const type = {
edit: event.target.classList.contains('edit'),
delete: event.target.classList.contains('delete')
}
const isFromSaveLabel = target.innerText.toLowerCase() === 'save'
//Checking to see if buttons are pressed
if(task && type.edit && isFromSaveLabel){
const text = task.querySelector('text')
target.innerText = 'Edit'
text.setAttribute('readonly','true')
return
};
if(task && type.edit){
const text = task.querySelector('text')
target.innerText = 'save'
text.removeAttribute('readonly')
text.focus()
return
};
if(task && type.delete){
return
}
});
/*******************************************************************
* Submits the HTML elements to have the lists submited and created*
*******************************************************************/
const submitHandler = (event) =>{
event.preventDefault();
createTask();
}
elements.form.addEventListener("submit", submitHandler);

The node to be removed is not a child of this node JavaScript

Other stack answers have failed to fix my problem because I think this occurs for different reasons. My JS code:
const addButton = document.querySelector('.addButton')
var input = document.querySelector('.input')
const draggable_list = document.getElementById('draggable-list'); //draggable_list is a ul
let itemBox;
let items;
const array = [];
const listItems = [];
let dragStartIndex;
class item {
constructor(itemName) {
this.createDiv(itemName);
}
createDiv(itemName) {
let removeButton = document.createElement('button');
removeButton.innerHTML = 'REMOVE';
removeButton.classList.add('removeButton');
draggable_list.appendChild(items);
items.appendChild(removeButton);
removeButton.addEventListener('click', () => this.remove(items);
}
async remove(item, value) {
draggable_list.removeChild(item)
}
}
async function check() {
if (input.value != '') {
array.push(input.value)
listItems.push(input.value)
array.forEach((numbers,index) => {
items = document.createElement('li')
items.setAttribute('data-index', index)
items.innerHTML = `
<div class="draggable" draggable="true">
<p class="phone-number">${numbers}</p>
<i class="fas fa-grip-lines"></i>
</div>`;
} )
new item(input.value)
input.value = ''
}
addButton.addEventListener('click', check)
When remove() is called for the first time, it successfully removes the last li element. But when it is called again, I get the following error:
Uncaught (in promise) DOMException: Node.removeChild: The node to be removed is not a child of this node
Does this work for you...
const addButton = document.querySelector('.addButton');
const input = document.querySelector('.input');
const draggable_list = document.getElementById('draggable-list');
//draggable_list is a ul
let itemBox;
let items;
const array = [];
const listItems = [];
let dragStartIndex;
class Item {
constructor(itemName) {
this.createDiv(itemName);
}
createDiv(itemName) {
let input = document.createElement('input');
input.value = itemName;
let removeButton = document.createElement('button');
removeButton.innerHTML = 'REMOVE'
removeButton.classList.add('removeButton');
draggable_list.appendChild(items);
items.appendChild(removeButton);
removeButton.addEventListener('click', (event) => {
if (event && event.target.parentElement) {
// this.remove(items));
this.remove(event.target.parentElement);
}
});
}
remove(item, value) {
draggable_list.removeChild(item);
}
}
function check() {
if (input.value != '') {
array.push(input.value);
listItems.push(input.value);
array.forEach((numbers, index) => {
items = document.createElement('li');
items.setAttribute('data-index', index)
items.innerHTML = `
<div class="draggable" draggable="true">
<p class="phone-number">${numbers}</p>
<i class="fas fa-grip-lines"></i>
</div>`;
});
new Item(input.value);
input.value = '';
}
}
addButton.addEventListener('click', check)
<button class="addButton">+</button>
<input type="text" class="input" />
<ul id="draggable-list">
</ul>
Instead of copying and pasting some convoluted code you don't understand you should try and write it yourself. Try and focus on what you require and nothing else.
Here is one way of doing it:
const [inp,btn,ul]=["input","button","ul"].map(e=>document.querySelector(e));
btn.onclick=function(){
ul.innerHTML+=`<li><p>${inp.value}</p><button>delete</button></li>`;
inp.value="";
}
ul.onclick=function(ev){
if (ev.target.tagName==="BUTTON")
ul.removeChild(ev.target.closest("li"));
}
<input type="text">
<button>add</button>
<ul></ul>

Regarding task display/non-display switching function

{
document.addEventListener('DOMContentLoaded', () => {
const addTaskTrigger = document.getElementsByClassName('addTask-trigger')[0];
const addTaskTarget = document.getElementsByClassName('addTask-target')[0];
const addTaskValue = document.getElementsByClassName('addTask-value')[0];
const radioWork = document.getElementById('radio-work');
const radioDone = document.getElementById('radio-done');
let nextId = 0;
const todos = [];
//Taskとidを作成
const addTask = (task, id, tableItem) => {
const idSpanTd = document.createElement('td');
const taskSpanTd = document.createElement('td');
//タスク追加時にtodosにtodoを追加
const todo = {
task: 'taskSpanTd',
status: '作業中'
};
todos.push(todo);
//要素内のHTML文章を変更する
idSpanTd.innerText = id;
taskSpanTd.innerText = task;
//生成したテーブル要素をブラウザに表示する
tableItem.append(idSpanTd);
tableItem.append(taskSpanTd);
addTaskTarget.append(tableItem);
};
//Button要素を生成する
const addButton = (tableItem, removeButton, createButton) => {
const createButtonTd = document.createElement('td');
const removeButtonTd = document.createElement('td');
//要素内のHTML文章を変更する
createButton.innerText = '作業中';
removeButton.innerText = '削除';
//生成したテーブル要素をブラウザに表示する
tableItem.append(createButtonTd);
tableItem.append(removeButtonTd);
addTaskTarget.append(tableItem);
//生成したbutton要素を生成する
createButtonTd.append(createButton);
removeButtonTd.append(removeButton);
};
//Perform processing to add td element when clicking the add button
addTaskTrigger.addEventListener('click', () => {
const task = addTaskValue.value;
const tableItem = document.createElement('tr');
const removeButton = document.createElement('button');
const createButton = document.createElement('button');
addTask(task, nextId++, tableItem);
addButton(tableItem, removeButton, createButton);
addTaskValue.value = '';
// //削除ボタンを押した時にタスクを削除する
const deleteElement = (a) => {
const tableTag = a.target.closest('tr');
if (tableTag) tableTag.remove();
updateId();
}
removeButton.addEventListener('click', deleteElement, false);
//When you press the button, it changes from working to completion
createButton.addEventListener('click', (a) => {
if (createButton.textContent === "作業中") {
createButton.textContent = "完了";
const doneParent = a.target.parentNode;
doneParent.className = 'workDone';/*完了class*/
} else {
createButton.textContent = "作業中";
const workParent = a.target.parentNode;
workParent.className = 'work';/*作業中class*/
}
});
})
/*Processing when pressing the radio button in progress*/
radioDone.addEventListener('click', function () {
let workTasks = document.getElementsByClassName('work');
workTasks = Array.from(workTasks);
if (radioWork.checked === true) {
workTasks.forEach(function (workTasks) {
workTasks.style.display = "none";
})
} else {
workTasks.forEach(function (workTasks) {
workTasks.style.display = "none";
})
}
})
//Processing when radio button complete is pressed
radioWork.addEventListener('click', function () {
let doneTasks = document.getElementsByClassName('workDone');
doneTasks = Array.from(doneTasks);
if (radioDone.checked === true) {
doneTasks.forEach(function (doneTasks) {
doneTasks.style.display = "none";
})
} else {
doneTasks.forEach(function (doneTasks) {
doneTasks.style.display = "none";
})
}
})
// Serial number reassignment
const updateId = () => {
const tbody = document.getElementsByTagName("tbody")[0];
const taskList = tbody.getElementsByTagName('tr');
nextId = 0;
Array.from(taskList, tr => {
tr.getElementsByTagName('td')[0].textContent = nextId;
nextId++
});
}
});
}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
<title>Todoリスト</title>
</head>
<body>
<h1>Todoリスト</h1>
<p>
<input type="radio" name="task" value="1" checked ="checked">全て
<input type="radio" id="radio-work" name="task" value="2">作業中
<input type="radio" id="radio-done" name="task" value="3">完了
</p>
<p></p>
<table>
<thead>
<th>ID</th>
<th>コメント</th>
<th>状態</th>
<th></th>
</thead>
<tbody class="addTask-target" id="tbody"></tbody>
</table>
<h2>新規タスクの追加</h2>
<input class="addTask-value" type="text" />
<button class="addTask-trigger" type="button">追加</button>
<script src="js/main.js"></script>
</body>
</html>
I am creating a Todo list and trying to implement it with the following contents.
https://gyazo.com/0b47106078622a1e44e912f56b5e9603
-Show/hide depending on task status
-Toggle task display depending on radio button selected
-If you add a new task when "Working" is selected, the task will be displayed
-If you add a new task when "Complete" is selected, the task will not be displayed (but it is added correctly in the background)
■ Current problems
(1) If you press the task completion button and then put the check box into operation, "Only the completion button" will be hidden.
→I want to hide every td
(2) Even if you click the in-process button and then click the completion check box, it will not be hidden
■ Tried
if (createButton.textContent === "Working") {
createButton.textContent = "Done";
const doneParent = a.target.parentNode;
doneParent.className ='workDone'; /* Done class */
Here is this.parentNode;
I changed it to
If you have any other problems, please let me know.
Thank you for your guidance.

Element text not changing when passing selected textContent and new value to an update function

I'm creating a CRUD page where the user can add, delete and edit text, but I have an issue in updating the text after I select it for edit.
In editText function when I click the edit button the text that was added will pop up inside the input field. When I click on the update button (triggering the updateText function), I can see the text in console log but the corresponding html is not updated.
HTML
<div class="main">
<form>
<input type="text" placeholder="search">
</form>
<ul></ul>
<div>
<input class="add-text" type="text" placeholder="Add Text">
<button id="add">Add</button>
<button id="update">update</button>
</div>
</div>
Javascript
const inputsearch = document.querySelector('form input');
const addInputBtn = document.querySelector('#add');
const update = document.querySelector('#update');
addInputBtn.addEventListener('click', addtext);
function addtext(){
let li = document.createElement('li');
let inputadd = document.querySelector('.add-text');
let addedtext = inputadd.value;
let h1Tag = '<h1 id="text">'+addedtext+'</h1>';
let tags = h1Tag + '<button id="delete">Delete</button><button id="edit">Edit</button>';
if(addedtext == ''){
alert('please add some text');
return;
}else{
li.innerHTML = tags;
document.querySelector('ul').appendChild(li);
}
li.querySelectorAll('#delete')[0].addEventListener('click', deleteText);
li.querySelectorAll('#edit')[0].addEventListener('click', editText);
getlist(li, h1Tag);
inputadd.value = '';
}
function deleteText(e) {
e.target.parentNode.remove();
document.querySelector('.add-text').value = '';
}
function editText(e) {
let currentText = e.target.parentNode.firstChild.textContent;
let currentValue = document.querySelector('.add-text');
currentValue.value = currentText;
getupdate(currentText, currentValue);
}
function getupdate(currentText, currentValue) {
update.addEventListener('click', updateText);
function updateText() {
currentText = currentValue.value
console.log(currentText = currentValue.value);
}
}
function getlist(li, h1Tag) {
inputsearch.addEventListener('keyup', serchText);
function serchText(e) {
let typetext = e.target.value.toLowerCase();
if(h1Tag.toLowerCase().indexOf(typetext) != -1){
li.style.display = 'block';
}else{
li.style.display = 'none';
}
}
}
To solve the issue without changing your overall approach, your edit button click needs to get the corresponding element (not just its textContent) and pass it to your getupdate() function to be updated when your update button is clicked. Relatively minor changes to your current functions:
function editText(e) {
const currentText = e.target.parentNode.firstChild;
const currentValue = document.querySelector('.add-text');
currentValue.value = currentText.textContent;
getupdate(currentText, currentValue);
}
function getupdate(currentText, currentValue) {
update.addEventListener('click', updateText);
function updateText() {
currentText.textContent = currentValue.value;
}
}
There are some other issues with your code, particularly the creation of multiple elements with the same id (which is malformed and will likely become problematic as you add additional features). Following is a snippet that addresses that issue as well as simplifying some of your functions and fixing the search.
const search = document.querySelector('form input');
const input = document.querySelector('.add-text');
const container = document.querySelector('ul');
let items = null;
let currentItem = null;
const searchItems = (event) => {
if (items) {
const s = event.currentTarget.value.toLowerCase();
for (const item of items) {
if (item.firstChild.textContent.toLowerCase().indexOf(s) !== -1) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
}
}
};
const deleteItem = (event) => {
currentItem = null;
event.currentTarget.parentNode.remove();
};
const editItem = (event) => {
currentItem = event.currentTarget.parentNode.firstChild;
input.value = currentItem.textContent;
};
const updateItem = () => {
if (currentItem) {
currentItem.textContent = input.value;
}
};
const addItem = () => {
let val = input.value
if (val) {
const li = document.createElement('li');
let inner = '<h1 class="text">' + val + '</h1>';
inner += '<button class="delete">Delete</button>';
inner += '<button class="edit">Edit</button>';
li.innerHTML = inner;
container.appendChild(li);
val = '';
currentItem = li.firstChild;
items = document.querySelectorAll('li');
for (let del of document.querySelectorAll('.delete')) {
del.addEventListener('click', deleteItem);
}
for (let edit of document.querySelectorAll('.edit')) {
edit.addEventListener('click', editItem);
}
} else {
alert('please add some text');
return;
}
};
search.addEventListener('keyup', searchItems);
document.querySelector('#add').addEventListener('click', addItem);
document.querySelector('#update').addEventListener('click', updateItem);
<div class="main">
<form>
<input type="text" placeholder="Search">
</form>
<ul></ul>
<div>
<input class="add-text" type="text" placeholder="Add Text">
<button id="add">Add</button>
<button id="update">Update</button>
</div>
</div>

Categories