I am making a generic todolist, the problem with my todolist is that it removes elements based on their INDEX while it takes their ID to get a position to delete
(example: let's say I add 6 items in my todolist, they all have an id from 1 to 6, if I remove 3 and 4, and then I try to remove 6, it won't work, because it tries taking the ID of element 6 which is 6 but it tries to delete the item at index 6 instead of ID 6)
Please help me remove them based on their ID and not index but I want it with PLAIN javascript, not jQuery, thank you.
ul.addEventListener("click", function(event){
console.log(event.target.parentNode.id);
if (event.target.className === "buttonClass"){
for (let z = 0; z < ul.children.length; z++){
let eh = event.target.parentNode.id;
ul.children.getAttribute("id")[eh].remove()
}
}
}
While i think this code is enough, I will add all of it below it
let ul = document.querySelector("ul")
let li = document.querySelectorAll("li");
let selectInput = document.querySelector("input");
let createLi = function(){
let createLi = document.createElement("li");
let addNow = ul.appendChild(createLi);
addNow.textContent = selectInput.value;
selectInput.value = "";
let btn = document.createElement("button");
let createButton = addNow.appendChild(btn);
createButton.textContent = "Button";
createButton.setAttribute("class", "buttonClass");
for(let i = 0; i < ul.children.length; i++){
addNow.setAttribute("id", i)
}
};
HTML BELOW
<button id="main" onclick="createLi()"> add</button>
<input type="text" class="input">
<ul>
</ul>
You can get your li element by its ID and remove it or Just use remove to the parent element which is the same li tag:
ul.addEventListener("click", function(event){
let id = event.target.parentNode.id;
document.getElementById(id).remove();
// Or directly
event.target.parentNode.remove();
});
Here is an example:
let ul = document.querySelector("ul")
let li = document.querySelectorAll("li");
let selectInput = document.querySelector("input");
let createLi = function() {
let createLi = document.createElement("li");
let addNow = ul.appendChild(createLi);
addNow.textContent = selectInput.value;
selectInput.value = "";
let btn = document.createElement("button");
let createButton = addNow.appendChild(btn);
createButton.textContent = "Button";
createButton.setAttribute("class", "buttonClass");
for(let i = 0; i < ul.children.length; i++){
addNow.setAttribute("id", i);
}
};
ul.addEventListener("click", function(event){
console.log(event.target.parentNode.id);
event.target.parentNode.remove();
});
<button id="main" onclick="createLi()"> add</button>
<input type="text" class="input">
<ul>
</ul>
Id is not needed to remove element:
<u onclick=this.parentNode.removeChild(this)> Click to remove </u>
or event.target to get the element that as clicked:
<ul onclick=event.target.parentNode.removeChild(event.target)>
<li> Item 1 </li>
<li> Item 2 </li>
<li> Item 3 </li>
<li> Item 4 </li>
</ul>
Bonus: It can even be faked with CSS (but JavaScript is still needed to add nodes) :
<style>[type], :checked + * { display: none }</style>
<input id=i><button onclick="i.value&&body.insertAdjacentHTML('beforeend', `<input type=
checkbox id=${n=Date.now()}><label for=${n}>${i.value}<br></label>`)">Add</button><br>
<input type=checkbox id=1><label for=1> Item 1 <br></label>
<input type=checkbox id=2><label for=2> Item 2 <br></label>
<input type=checkbox id=3><label for=3> Item 3 <br></label>
<input type=checkbox id=4><label for=4> Item 4 <br></label>
Related
I'm trying to code a small application that lets you dynamically add text strings in an unordered list, but the problem is the strings I pass as input do not show up after clicking the "Invia/Send" button. I have tried with a few solutions from other questions, but none of them worked. Any ideas?
<html>
<head>
<title>Promemoria esercizi</title>
</head>
<body>
<ul id="paragraphList">
</ul>
<form id="paragraphForm">
<br></br>
<textarea id="insertParagraph" rows="5" cols="100"></textarea>
<label>Inserisci il paragrafo:
<input type="radio" id="insertType" name="InsertType" value="last">In fondo
<input type="radio" id="insertType" name="InsertType" value="before">Dietro il paragrafo
<select id="beforeParagraph"></select><br></br>
</label>
<button id="add" onclick="addParagraph(paragraphArray)">Inserisci</button><br></br>
</form>
<script>
var paragraphArray = [];
document.getElementById("paragraphList").innerHTML = paragraphArray;
function addParagraph(paragraphArray){
var text = document.getElementById("insertParagraph").value;
var radio = document.getElementById("insertType");
var selectedInsertType = "";
var ul = document.getElementById("paragraphList");
var sel = document.getElementById("beforeParagraph");
var selectedBeforeParagraph = sel.options[sel.selectedIndex].value;
for(i = 0; i < radio.length; i++){
if(radio[i].checked){
selectedInsertType = radio[i].value;
}
}
if(selectedInsertType = "last"){
paragraphArray.push(text);
}else if(selectedInsertType = "before"){
paragraphArray.splice((selectedBeforeParagraph-1), 0, text);
}
var newChoice = document.createElement("option");
newChoice.value = paragraphArray.length.toString();
newChoice.text = paragraphArray.length.toString();
for(i = 0; i < paragraphArray.length; i++){
var li = document.createElement("li");
li.innerHTML = paragraphArray[i];
}
document.getElementById("paragraphList").innerHTML = paragraphArray;
}
</script>
</body>
</html>
There were a few issues:
A common problem people run into with the button tag is by default, it has a type of 'submit' which will submit the form. There are a few ways to disable this, my preferred method is to set the type as button.
Another issue is you don't have any content in the select box, which was causing an error trying to get the value of a select box with no options that can be selected.
I updated your radios, to use querySelectorAll and look for :checked that way you don't need to create an if statement.
I also removed the paragraphArray from addParagraph() since it is a global variable.
<html>
<head>
<title>Promemoria esercizi</title>
</head>
<body>
<ul id="paragraphList">
</ul>
<form id="paragraphForm">
<br></br>
<textarea id="insertParagraph" rows="5" cols="100"></textarea>
<label>Inserisci il paragrafo:
<input type="radio" id="insertType" name="InsertType" value="last">In fondo
<input type="radio" id="insertType" name="InsertType" value="before">Dietro il paragrafo
<select id="beforeParagraph"></select><br></br>
</label>
<button type="button" id="add" onclick="addParagraph()">Inserisci</button><br></br>
</form>
<script>
var paragraphArray = [];
document.getElementById("paragraphList").innerHTML = paragraphArray;
function addParagraph(){
var text = document.getElementById("insertParagraph").value;
var radio = document.querySelectorAll("#insertType:checked");
var selectedInsertType = "";
var ul = document.getElementById("paragraphList");
var sel = document.querySelector("#beforeParagraph");
var selectedBeforeParagraph = (sel.selectedIndex > -1) ? sel.options[sel.selectedIndex].value : "";
for(i = 0; i < radio.length; i++){
selectedInsertType = radio[i].value;
}
if(selectedInsertType = "last"){
paragraphArray.push(text);
}else if(selectedInsertType = "before"){
paragraphArray.splice((selectedBeforeParagraph-1), 0, text);
}
var newChoice = document.createElement("option");
newChoice.value = paragraphArray.length.toString();
newChoice.text = paragraphArray.length.toString();
for(i = 0; i < paragraphArray.length; i++){
var li = document.createElement("li");
li.innerHTML = paragraphArray[i];
}
document.getElementById("paragraphList").innerHTML = paragraphArray;
}
</script>
</body>
</html>
I tried to remove the list item inside ul with querySelectorAll and remove going through each li element. Where is the mistake please, and how is it fixed?
<div class='container'>
<h1> New todo list</h1>
<form>
<input type= 'text' id='item'
required>
<ul> </ul>
<button id='button'> clear all</
button>
</div>
Here's the code:
var form =
document.querySelector('form')
var ul = document.querySelector('ul')
var button =
document.querySelector(#button)
var input =
document.querySelector('item')
var liMaker = text => {
var li =
document.createElement('li')
li.textContent = text
ul.insertBefore(li,
ul.childNodes[0])
button.onclick = remove
}
form.addEventListener('submit',
function(e){
e.preventDefault()
liMaker(input.value)
input.value = ' '
})
function remove(e){
Array.from(
document.querySelectorAll('
li')).forEach(item =>
e.target.item.remove())
}
I have edited your code a little and added a new button to keep the functionality separate. I think this is the kind of functionality you were after if I understood your question correctly.
<div class='container'>
<h1> New todo list</h1>
<form>
<input type='text' id='item' required>
<ul id="myList"></ul>
<button id='button'>add</button>
</form>
<button id="clear">Clear</button>
</div>
JS:
var form = document.querySelector('form')
var ul = document.querySelector('ul')
var button = document.querySelector('#button');
var input = document.querySelector('#item');
var clear = document.querySelector('#clear');
var liMaker = text => {
var li = document.createElement('li');
li.textContent = text;
ul.insertBefore(li, ul.childNodes[0])
}
form.addEventListener('submit', function(e) {
e.preventDefault()
liMaker(input.value)
input.value = '';
});
clear.addEventListener('click', remove);
function remove(){
saveToDos();
while (ul.firstChild) {
ul.removeChild(ul.firstChild);
}
}
function saveToDos() {
var items = ul.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i) {
savedToDos.push(items[i].innerHTML);
}
localStorage.setItem('savedValues', savedToDos);
}
Here is a link to a working pen: https://codepen.io/caeking/pen/RzyKmV
I am at the end of my Project. I have problem with add favorites and to remove item from local storage. It works to delete it from html but when you refresh the page, items are again here. Also remove whole favorites its not working. I hope that someone see my mistake
I try to remove whole list with function but its also not working.
<body>
<main>
<h1>Your Favourite Recipes</h1>
<p>These are your favourite recipes that we have saved for you.</p>
<button id="probam" type="button"
name="button" onclick="deleteListe()">brisi</button>
<p id="fav"></p>
<script>
let list = localStorage.getItem('favorites');
list = list ? list.split(',') : [];
var ll = [];
ll = list;
var output = document.createElement('ul');
output.setAttribute('id', 'list')
for (let i = 0; i < ll.length; i++) {
var it = document.createElement('li');
var bt = document.createElement('button');
bt.innerHTML = ('Delete');
bt.setAttribute('class', 'delete')
it.appendChild(document.createTextNode(ll[i]));
it.appendChild(bt);
output.appendChild(it);
}
document.getElementById('fav').appendChild(output);
var del = document.getElementsByClassName('delete');
for (let j = 0; j < del.length; j++) {
del[j].addEventListener('click', function() {
// console.log((del[j].parentNode).parentNode);
(del[j].parentNode).parentNode.removeChild(del[j].parentNode);
})
}
function deleteListe() {
localStorage.removeItem("favorites");
}
</script>
<button type="button" name="button"></button>
<a href="index.html" class='vido'>Home</a>
</main>
</body>
I little change your code, and i added for all button required functions
<h1>Your Favourite Recipes</h1>
<p>These are your favourite recipes that we have saved for you.</p>
<button id="probam" type="button" name="button" onclick="deleteListe()">brisi</button>
<p id="fav"></p>
<script>
function deleteListe() {
localStorage.removeItem("favorites");
}
function deleteElement(element) {
const newFavorites = (localStorage.getItem('favorites')||"").replace(element,"");
localStorage.setItem("favorites",newFavorites.split(",").filter(Boolean).join(","));
setTimeout(()=>{
localStorage.getItem('favorites')
location.reload();
},10);
}
let list = (localStorage.getItem('favorites')||"").split(",").filter(Boolean);
var output = document.createElement('ul');
output.setAttribute('id', 'list')
list.forEach((el)=>{
var it = document.createElement('li');
var bt = document.createElement('button');
bt.innerHTML = ('Delete');
bt.setAttribute('class', 'delete');
bt.setAttribute('title', el);
it.appendChild(document.createTextNode(el));
it.appendChild(bt);
output.appendChild(it);
});
document.getElementById('fav').appendChild(output);
var del = document.getElementsByClassName('delete');
for (let j = 0; j < del.length; j++) {
del[j].addEventListener('click', function() {
deleteElement(this.getAttribute('title'));
(this.parentNode).parentNode.removeChild(this.parentNode);
})
}
</script>
<button type="button" name="button"></button>
<a href="index.html" class='vido'>Home</a>
Let's say I have the following input field:
<input id="inputField" type="number" value="">
and some divs such as:
<div id="1000"></div>
<div id="1200"></div>
<div id="1500"></div>
<div id="1900"></div>
...
When the user enters a number in the input field, I want my code to go to the nearest div id to that number.
e.g: If user enters 1300 then show div with id = "1200".
What's the most efficient way to implement that in javascript considering there will be a large number of divs?
Right now I'm doing:
<script>
function myFunction()
{
var x = document.getElementById("inputField").value;
if(x >= 1750 && x <= 1900)
{
window.location.hash = '#1800';
}
}
</script>
One way is to wrap all your divs with number ids in another div if you can (and give it some id, say 'numbers'); this allows you to find all the divs in your javascript file.
Javascript:
// Get all the divs with numbers, if they are children of div, id="numbers"
let children = document.getElementById('numbers').children;
let array = [];
for (i = 0; i < children.length; i++) {
// Append the integer of the id of every child to an array
array.push(parseInt(children[i].id));
}
// However you are getting your input number goes here
let number = 1300 // Replace
currentNumber = array[0]
for (const value of array){
if (Math.abs(number - value) < Math.abs(number - currentNumber)){
currentNumber = value;
}
}
// You say you want your code to go to the nearest div,
// I don't know what you mean by go to, but here is the div of the closest number
let target = document.getElementById(currentNumber.toString());
Let me know if there's more I can add to help.
Demo
function closestNum() {
let children = document.getElementById('numbers').children;
let array = [];
for (i = 0; i < children.length; i++) {
array.push(parseInt(children[i].id));
}
let number = document.getElementById('inputnum').value;
currentNumber = array[0]
for (const value of array) {
if (Math.abs(number - value) < Math.abs(number - currentNumber)) {
currentNumber = value;
}
}
let target = document.getElementById(currentNumber.toString());
document.getElementById('target').innerHTML = target.innerHTML;
}
<div id="numbers">
<div id="1000">1000</div>
<div id="2000">2000</div>
<div id="3000">3000</div>
<div id="4000">4000</div>
<div id="5000">5000</div>
</div>
<br />
<input type="text" id="inputnum" placeholder="Input Number" onchange="closestNum()" />
<br />
<br /> Target:
<div id="target"></div>
With some optimization this shall be ok-
var element;
document.addEventListener("change",
function(evt){
if(element && element.classList){
element.classList.remove("selected", false);
element.classList.add("unselected", true);
}
var listOfDivs =
document.querySelectorAll(".unselected");
var val = evt.target.value;
var leastAbs=listOfDivs[0].id;
for(let anIndex=0, len=listOfDivs.length;anIndex<len;anIndex++){
if(Math.abs(listOfDivs[anIndex].id-val)<leastAbs){
leastAbs = Math.abs(listOfDivs[anIndex].id-val);
element = listOfDivs[anIndex];
}
}
element.classList.remove("unselected");
element.classList.add("selected");
});
.selected{
background-color:red;
}
.unselected{
background-color:yellow;
}
.unselected, .selected{
width:100%;
height:50px;
}
<input id="inputField" type="number" value="">
<div id="1000" class='unselected'>1</div>
<div id="1200" class='unselected'>2</div>
<div id="1500" class='unselected'>3</div>
<div id="1900" class='unselected'>4</div>
This may work for you. Loops through each div and compared it to your inputted ID. Tracks closest one, hides all divs, then displays the closest.
document.getElementById("inputField").addEventListener("change", function(){
var divs = document.getElementsByTagName("div");
var closestDiv = -1;
var inputId = document.getElementById("inputField").value;
for(var i=0; i<divs.length; i++)
{
if(Math.abs(inputId - closestDiv) > Math.abs(inputId - divs[i].id) || closestDiv == -1)
{
closestDiv = divs[i].id;
for (var x = 0; x < divs.length; x++) {
divs[x].style.display = 'none';
}
divs[i].style.display = "block";
}
}
});
See it Live: jsfiddle.net
I have a simple HTML unordered list and a JavaScript function that adds items at position [0], and another that deletes items at [0] as well, but what can I add to the delete function (strictly basic JavaScript please even if it's longer) so it deletes the last added item? Thank you in advance:
HTML:
<html>
<body>
<h1> Shopping List </h1>
<button onclick="adding()"> Add </button>
<input type="text" id="input" placeholder="Enter Items"> </input>
<button onclick="remove()"> Remove Last </button>
<ul id="list">
</ul>
</body>
</html>
Javascript:
function adding() {
var input = document.getElementById("input").value;
var newEl = document.createElement("li");
var newText = document.createTextNode(input);
newEl.appendChild(newText);
var position = document.getElementsByTagName("ul")[0];
position.appendChild(newEl);
document.getElementById("input").value = "";
}
function remove() {
var removeEl = document.getElementsByTagName("li")[0];
var containerEl = removeEl.parentNode;
containerEl.removeChild(removeEl);
}
function adding() {
var input = document.getElementById("input").value;
var newEl = document.createElement("li");
var newText = document.createTextNode(input);
newEl.appendChild(newText);
var position = document.getElementsByTagName("ul")[0];
position.appendChild(newEl);
document.getElementById("input").value = "";
}
function remove() {
var els = document.getElementsByTagName("li");
var removeEl = els[els.length - 1]; // <-- fetching last el
var containerEl = removeEl.parentNode;
containerEl.removeChild(removeEl);
}
<html>
<h1> Shopping List </h1>
<button onclick="adding()"> Add </button>
<input type="text" id="input" placeholder="Enter Items"> </input>
<button onclick="remove()"> Remove Last </button>
<ul id="list">
</ul>
</body>
</html>
If els is an array, it has indices from 0 to els.length - 1. 0 is the first, els.length - 1 is the last index.
Besides, try not to use attribute event handlers like onclick="adding()". A much better practice is to attach them programmatically, for clean separation of concerns:
<button id="add">Add</button>
and then
document.getElementById('add').addEventListener('click', adding);
Purely speaking this answers the question as it only removes the last added item then won't remove anything else
window.lastadded = false;
function adding() {
var input = document.getElementById("input").value;
var newEl = document.createElement("li");
newEl.id = Date.parse(new Date());
var newText = document.createTextNode(input);
window.lastadded = newEl.id;
newEl.appendChild(newText);
var position = document.getElementsByTagName("ul")[0];
position.appendChild(newEl);
document.getElementById("input").value = "";
}
function remove() {
lastElement = document.getElementById(window.lastadded);
lastElement.parentNode.removeChild(lastElement);
}