How to use removeChild method? - javascript

const toDoForm = document.querySelector(".todo__form"),
toDoInput = document.querySelector(".todo__input");
toDoList = document.querySelector("li");
let toDoArray = [];
function addToDoList() {
toDoForm.addEventListener('submit', event => {
toDoArray.push(toDoInput.value);
toDoList.innerHTML += `<ul>${toDoArray[toDoArray.length-1]}</ul>`;
event.preventDefault();
toDoInput.value = "";
});
}
function clearList() {
const toDoUl = document.querySelector("ul");
toDoForm.addEventListener('click', event => {
toDoArray = [];
toDoUl.parentNode.removeChild(toDoUl);
});
}
function init() {
addToDoList();
clearList();
}
init();
<h1>To-Do List</h1>
<div class="todo">
<form class="todo__form">
<input class="todo__input" type="text">
<input class="todo__submit" type="submit" value="Submit">
<input class="todo__clear" type="button" value="Clear">
</form>
</div>
<div class="todo-list">
<li></li>
</div>
I'm making a to-do list with javascript and i tried to use removeChild method to clear to-do list but when i run the code, it keeps getting an error like this -> Uncaught TypeError: Cannot read property 'parentNode' of null at HTMLFormElement. How can i solve it?

The query document.querySelector("ul"); is returning undefined because there is no ul element in the HTML. Try changing the div to ul tag
<ul class="todo-list">
<li></li>
</ul>

First, I thought you want remove one item at a time, then I made some changes which may be useful but you if you don't need it, you could remove delete function.
For adding an item, you enter a job name, for example 'Job1' an then press "Submit" button.
For deleting an item, you enter a job name, for example 'Job1' an then press "Delete" button.
Press 'Clear' to clear all items.
JavaScript:
<script>
let toDoArray = [];
let toDoForm;
window.onload = () => {
toDoForm = document.querySelector(".todo__form"),
toDoInput = document.querySelector(".todo__input");
toDoList = document.querySelector("ul");
clearButton = document.querySelector(".todo__clear");
deleteButton = document.querySelector(".todo__delete");
init();
};
function addToDoList() {
toDoForm.addEventListener('submit', event => {
toDoList.innerHTML += `<li>${toDoInput.value}</li>`;
event.preventDefault();
toDoInput.value = "";
});
}
function deleteItem() {
deleteButton.addEventListener('click', event => {
const toDoUl = document.querySelector("ul");
let allLi = document.querySelectorAll('li');
allLi.forEach(li => {
if (li.innerHTML === toDoInput.value)
toDoUl.removeChild(li);
});
toDoInput.value = "";
});
}
function clearList() {
clearButton.addEventListener('click', event => {
const toDoUl = document.querySelector("ul");
toDoUl.innerHTML = '';
});
}
function init() {
addToDoList();
deleteItem();
clearList();
}
</script>
HTML:
<body>
<h1>To-Do List</h1>
<div class="todo">
<form class="todo__form">
<input class="todo__input" type="text">
<input class="todo__submit" type="submit" value="Submit">
<input class="todo__delete" type="button" value="Delete">
<input class="todo__clear" type="button" value="Clear">
</form>
</div>
<div class="todo-list">
<ul></ul>
</div>
<script src="todo.js"></script>
</body>

First, you need to change <li></li> to <ul></ul>. You can get help from w3school link.
There is a StackOverflow answer about this issue Stackoverflow. You can check that.

Related

why doesn't my local storage works but, copy of same code works

i got two copies of the same code with slight variation but seems the second one isnt working.
I have tried using ChatGPT to identify issues however, nothing was found. But as far as i can see, it should work.
But, everything i refresh, its removed.
I want the buttons to stay there.
working code:
const todoList = document.querySelector(".todo-list");
const todoForm = document.querySelector(".add-todo");
const removeList = document.querySelector(".remove-List");
let items = JSON.parse(localStorage.getItem("todoList")) || [
{
title: "Write on, 'do not forget to', and press '+' to add",
done: false,
},
{
title: "press 'X' to remove",
done: false,
},
{
title: "search via 'search box'",
done: false,
},
{
title: "filter via 'all'",
done: false,
},
];
function addTodo(e) {
e.preventDefault();
const title = this.querySelector("[name=item]").value;
const todo = {
title,
done: false,
};
items.push(todo);
saveTodos();
this.reset();
}
function createList(list = [], listTarget) {
listTarget.innerHTML = list
.map((item, i) => {
return `<li>
<input type="checkbox" id="todo${i}" data-index="${i}"
${item.done ? "checked" : ""} />
<label for="todo${i}">${item.title}
<span class="font-size:30px" data-index="${i}">X</span>
</label>
</li>`;
})
.join("");
}
function toggleDone(e) {
if (!e.target.matches("input")) return;
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
saveTodos();
}
function removeSingle(e) {
if (!e.target.matches("span")) return;
const el = e.target;
const index = el.dataset.index;
items.splice(index, 1);
saveTodos();
if (items.length === 0) {
removeList.classList.add("hidden");
}
}
function saveTodos() {
localStorage.setItem("todoList", JSON.stringify(items));
createList(items, todoList);
showRemoveButton();
}
function removeData() {
items = [];
localStorage.removeItem("todoList");
createList(items, todoList);
removeList.classList.add("hidden");
}
function showRemoveButton() {
if (items.length > 1) return;
removeList.classList.remove("hidden");
}
todoList.addEventListener("click", toggleDone);
todoList.addEventListener("click", removeSingle);
todoForm.addEventListener("submit", addTodo);
removeList.addEventListener("click", removeData);
// Init list
createList(items, todoList);
<div class="ToDo-container">
<header class="app-header">
<div class="app-header1">
<div class="title">
<h1 class="app-title">ToDo List</h1>
</div>
<div class="select-button">
<select id="filter">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="incomplete">Incomplete</option>
</select>
</div>
</div>
<div class="search-header">
<input type="text" id="search" placeholder="Search Todos">
<button type="button" id="search-button" class="btn">Search</button>
</div>
</header>
<section class="app-body">
<div id="toDo">
<ul class="todo-list"></ul>
<form class="add-todo">
<input
type="text"
placeholder="Don't Forget to..."
name="item"
required
/>
<input type="submit" value="+" />
</form>
</div>
<button class="remove-List btn">Remove All</button>
</section>
</div>
// Add button function
function addButton() {
// Prompt for button link and name
var link = prompt("Enter the button link:");
var name = prompt("Enter the button name:");
// Create new button element
var newButton = document.createElement("button");
newButton.innerHTML = name;
newButton.setAttribute("onclick", "location.href='" + link + "'");
// Append new button to button container
document.getElementById("button-container").appendChild(newButton);
// Save buttons to local storage
saveButtons();
}
// Remove buttons function
function removeButtons() {
// Clear button container
document.getElementById("button-container").innerHTML = "";
// Save buttons to local storage
saveButtons();
}
// Save buttons to local storage
function saveButtons() {
// Get button container HTML
var buttonHTML = document.getElementById("button-container").innerHTML;
// Save button HTML to local storage
localStorage.setItem("buttons", buttonHTML);
}
// Load buttons from local storage on page load
window.onload = function () {
// Get button HTML from local storage
var buttonHTML = localStorage.getItem("buttons");
// Set button container HTML
document.getElementById("button-container").innerHTML = buttonHTML;
};
<div class="shortcuts-container">
<header class="shortcut-header">
<h1 class="shortcut-title">Quick Links</h1>
</header>
<section class="shortcut-body">
<form id="button-form">
<div id="button-container"></div>
<button type="button" onclick="addButton()">Add Button</button>
<button type="button" onclick="removeButtons()">Remove Buttons</button>
</form>
</section>
</div>
i want some help with identifying the bug in my code
As you have mentioned that your "second one" is not working, I have focused on the second piece of code. This peice of code adds a button for which we need to provide a link and name via alert box, which is technically supposed to be a hyperlink. I have added 2 buttons using that and refreshed page multiple times but the newly added buttons always stay. Local storage is working just fine.
Also, looking at your code, there is NO localStorage.removeItem() present. Hence the window.onload works fine. However, if you have any error logs in console of dev tools, please provide them for further debugging.
Also, if there is a way for you attach a video link of testing with dev tools console visible that would really help to understand why it doesn't work for you.

The delete button is duplicating when you create a second task so that you see two delete buttons for the second task

I have a to do list that is creating two delete buttons per task for the second task item, three delete buttons for the third task etc. Here is my code.
//Submits the form
function submitForm() {
form.addEventListener('submit', function (e) {
e.preventDefault();
taskData = document.getElementById('activity').value;
addingTask(taskData);
form.reset(taskData);
return taskData;
});
}
//Adds a task element
function addingTask(taskData) {
taskElement = document.createElement('h3');
deleteButton = document.createElement('Button');
taskElement.innerHTML = taskData;
taskElement.id = 'taskElement';
deleteButton.innerHTML = 'Delete';
//deleteButton.id = taskData;
deleteButton.addEventListener('click', deletingTask);
document.body.appendChild(taskElement);
document.body.appendChild(deleteButton);
}
//Removes a task element
function deletingTask() {
taskElement.remove();
deleteButton.remove();
}
<body>
<form id="form"> <label for="activity">Activity</label><br> <input type="text" id="activity"
name="activity"><br><br> <input type="submit" value="Submit" onclick="submitForm()"> </form>
<!-- your content here... -->
<script src="script.js"></script>
</body>
You shouldn't create new event listeners each time you submit the form. Add the event listener only once:
//Submits the form
form.addEventListener('submit', function (e) {
e.preventDefault();
taskData = document.getElementById('activity').value;
addingTask(taskData);
form.reset(taskData);
return taskData;
});
//Adds a task element
function addingTask(taskData) {
taskElement = document.createElement('h3');
deleteButton = document.createElement('Button');
taskElement.innerHTML = taskData;
taskElement.id = 'taskElement';
deleteButton.innerHTML = 'Delete';
//deleteButton.id = taskData;
deleteButton.addEventListener('click', deletingTask);
document.body.appendChild(taskElement);
document.body.appendChild(deleteButton);
}
//Removes a task element
function deletingTask() {
taskElement.remove();
deleteButton.remove();
}
<form id="form">
<label for="activity">Activity</label><br> <input type="text" id="activity" name="activity">
<br><br>
<input type="submit" value="Submit">
</form>
The issue is you do this each time you submit
form.addEventListener('submit', function (e) {
Also form.reset does not take a parameter.
Lastly ne need to return the data in the submit event
You should delegate and have a div per task
const container = document.getElementById("container");
//Submits the form
form.addEventListener('submit', function(e) {
e.preventDefault();
taskData = document.getElementById('activity').value;
addingTask(taskData);
this.reset();
});
container.addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("delete")) {
//Removes a task element
tgt.closest("div").remove();
}
})
//Adds a task element
function addingTask(taskData) {
const taskElement = document.createElement('div');
const header = document.createElement('h3');
deleteButton = document.createElement('Button');
header.innerHTML = taskData;
deleteButton.innerHTML = 'Delete';
deleteButton.classList.add("delete");
taskElement.appendChild(header);
taskElement.appendChild(deleteButton);
container.append(taskElement);
}
<form id="form">
<label for="activity">Activity</label>
<input type="text" id="activity" name="activity">
<input type="submit" value="Submit">
<div id="container"></div>
</form>

Event listener not displaying line-through when ticking checkbox of list item

I’ve created a function named checkedItems. I want the function to cross an item out each time the check box attached to it is ticked. However, nothing happens when I do so. If someone could point out where I’ve gone wrong in my code and fix it, that would be great.
var elUlList = document.getElementById("ulList");
var btn = document.getElementById("btn");
const elInput = document.getElementById("input");
const footer = document.querySelector("footer");
const message = document.getElementById("message");
const elCounter = document.getElementById("counter");
function createListItems() {
var elements = document.getElementsByTagName('li');
console.log(elements)
var inputValue = elInput.value;
var newLi = document.createElement("li");
var input = document.createElement("input")
input.type = "checkbox"
var newText = document.createTextNode(inputValue);
newLi.appendChild(input);
newLi.appendChild(newText);
elUlList.appendChild(newLi)
}
btn.addEventListener("click", createListItems, false);
elInput.addEventListener("keyup", function(e) {
if (e.keyCode === 13) {
e.preventDefault();
btn.click()
}
})
elInput.addEventListener("mouseover", emptyField, false)
function emptyField() {
this.value = "";
}
elUlList.addEventListener("change", checkedItems, false)
function checkedItems() {
var checkboxes = document.querySelectorAll("input[type=checkbox]")
var checkboxesArray = Array.from(checkboxes);
console.log(checkboxes.length);
if (checkboxes.length > 1) {
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked
? checkboxes[i].classList.toggle("lineThrough")
: null;
}
}
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="message" class=""></div>
<ul id="ulList"></ul>
<button id="btn" type="button" name="button">click here to add items</button>
<input id="input" type="text" name="" value="">
<div id="counter" class=""></div>
<footer></footer>
<script src="index.js" type="text/javascript"></script>
</body>
</html>
Converting comments to an answer: you’re applying the lineThrough class to the checkbox, not its parent element, the <li>. The <li> contains the text.
The function referenced in elUlList.addEventListener("change", checkedItems, false) can be shortened:
const checkedItems = ({target}) => {
if(target.matches("input[type=checkbox]")){
target.closest("li").classList.toggle("lineThrough", target.checked);
}
}
target.closest("li") will always find the <li> that contains target (and is the closest parent node in the DOM tree).
toggle accepts a second argument that will set or unset the class "lineThrough" based on the boolean target.checked.
No need to loop, because a change event will only be triggered when you change one specific checkbox, and you want to strike out the text in only this list item, so it’s sufficient to only target that one.
And your conditional operator was wrong: why do you toggle only when the checkbox is checked?
Another thing: checkedItems isn’t a good name for this function, as this name implies that the function returns a list of checked items or something similar, but it doesn’t. strikeOutCheckedItem or toggleCheckedItem is better; there’s also no plural, because this function only deals with one list item at a time.
Finally, make sure you actually have the CSS class defined:
.lineThrough {
text-decoration: line-through;
}
I think this is a better approach
const elUlList = document.getElementById("ulList");
const btn = document.getElementById("btn");
const elInput = document.getElementById("input");
function addItem() {
if (elInput.value !== "") {
const listItem = `<li>
<input type="checkbox">
<span>${elInput.value}</span>
</li>`;
elUlList.insertAdjacentHTML("afterbegin", listItem);
elInput.value = "";
}
}
btn.addEventListener("click", addItem);
elInput.addEventListener("keyup", (e) => {
if (e.key === "Enter") {
addItem();
}
});
function isCompleted() {
const checkboxs = document.querySelectorAll("li input");
const tasks = document.querySelectorAll("li span");
for (let i = 0; i < checkboxs.length; i++) {
if (checkboxs[i].checked) {
tasks[i].classList.toggle("lineThrough");
}
}
}
elUlList.addEventListener("change", isCompleted);
.lineThrough {
text-decoration: line-through;
}
<ul id="ulList"></ul>
<button id="btn" type="button" name="button">
click here to add items
</button>
<input id="input" type="text" />
...

Javascript function stops immediately

I have a function which enables the button 2(id keuze1) and button 3 ( id keuze 3) If i press button 1 (id = naam).
function init() {
let startKnop = document.getElementsByTagName("button")[0].addEventListener("click", startClicked, false);
}
function startClicked(event) {
let knop2 = document.getElementById("keuze1");
knop2.removeAttribute("disabled");
let knop3 = document.getElementById("keuze2");
knop3.removeAttribute("disabled");
toonVraag();
}
function toonVraag(event) {
let i = vraagTeller.value;
let vraag = document.getElementById('vraag');
vraag.innerHTML = "Hello World";
}
<label for="naam">Code: </label><input type="text" id="naam" />
</div>
<button disabled>Start</button>
<div>
<p id="vraag">Een vraag</p>
<button id="keuze1" disabled>Keuze1</button>
<button id="keuze2" disabled>Keuze2</button>
</div>
So it successfully runs the function startClicked(), but stops immediately.
If I add the code event.preventDefault() it doesn't go through to changing the text from my element(id = vraag).
Seems to work just fine, as exemplified in this JSFiddle
I did some clean-up though:
Removed the disabled attribute from the first button
Removed the </div> from the 2nd line
Added call to the init() function
As such:
function init() {
let startKnop = document.getElementsByTagName("button")[0].addEventListener("click", startClicked, false);
}
init();
function startClicked(event) {
let knop2 = document.getElementById("keuze1");
knop2.removeAttribute("disabled");
let knop3 = document.getElementById("keuze2");
knop3.removeAttribute("disabled");
toonVraag();
}
function toonVraag(event) {
let vraag = document.getElementById('vraag');
vraag.innerHTML = "Hello World";
}
<label for="naam">Code: </label><input type="text" id="naam" />
<button>Start</button>
<div>
<p id="vraag">Een vraag</p>
<button id="keuze1" disabled>Keuze1</button>
<button id="keuze2" disabled>Keuze2</button>
</div>

how to display value of input in DIV object in real time

F.e I have div which id is someDiv and input text which id is someInput - and how to do that value of input object will display in DIV in real time? If i type letter "a" in input, it should automatically display in DIV.
Which function should I use?
I'm the real begginer in jQuery.
I find this code:
$(function() {
$('#someInput').keyup(function() {
$('#someDiv').text($(this).val());
});
});
Use input event
$(function() {
$('#someInput').on("input", function() {
$('#someDiv').text($(this).val());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="someInput">
<div id="someDiv"></div>
<input id="realTimeInput" type="text"/>
<div id="someDiv">
</div>
<script>
$("#realTimeInput").on('change',function(){
$("#someDiv").text($("#realTimeInput").text());
}
</script>
you can check this code , when you keyup theb this value will show in content div so you can also input event like keypress, change etc
$('#someInput').keyup(function () {
$('#yourinput').show();
// var dev = $(this).val();
$('#yourinput').html($(this).val());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Enter Text :<input id="someInput" type="text"/>
<div id="yourinput" style="display: none;border: 1px solid #ccc;margin-top:10px;">
</div>
for more information
https://www.w3schools.com/jquery/event_keyup.asp
Vanilla Javascript Alternative:
Use the addEventListener() method to invoke a callback function when a specified event type occurs (e.g: keydown) on an EventTarget.
ES5:
var INPUT_EL = document.getElementById('UI_input'),
OUTPUT_EL = document.getElementById('UI_output');
function updateText() {
OUTPUT_EL.innerHTML = INPUT_EL.value;
}
INPUT_EL.addEventListener('keydown', updateText);
var INPUT_EL = document.getElementById('UI_input'),
OUTPUT_EL = document.getElementById('UI_output');
function updateText() {
OUTPUT_EL.innerHTML = INPUT_EL.value;
}
INPUT_EL.addEventListener('keydown', updateText);
<body>
<input type="text" id="UI_input" value="test value">
<div id="UI_output">this is sample</div>
</body>
ES6:
const INPUT_EL = document.getElementById('UI_input');
const OUTPUT_EL = document.getElementById('UI_output');
let updateText = () => OUTPUT_EL.innerHTML = INPUT_EL.value;
INPUT_EL.addEventListener('keydown', updateText);
const INPUT_EL = document.getElementById('UI_input');
const OUTPUT_EL = document.getElementById('UI_output');
let updateText = () => OUTPUT_EL.innerHTML = INPUT_EL.value;
INPUT_EL.addEventListener('keydown', updateText);
<body>
<input type="text" id="UI_input" value="test value">
<div id="UI_output">this is sample</div>
</body>

Categories

Resources