user3361789 user3361789 - 2 months ago 11
Javascript Question

Javascript - Deleting a list item

How do you properly delete list item by clicking on it?

I have been using the following line for code to delete an item but instead this deletes the entire list itself:

var list = document.getElementById("shoppinglist");

list.onclick = function() { list.parentNode.removeChild(list);}


I have been searching online on how to do this and the same kind of code keeps appearing and I am not sure how to solve this. I assumed that the list item generated was a child of the "shoppinglist".

I am very new to Javascript and I know this is a rookie mistake but I would really appreciate any help. Thank you.


<!doctype html>
<html dir="ltr" lang="en-gb">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<style>
body {
/* Sets the width then uses the margin auto feature to centre the page in the browser */
width:800px;
margin: 0px auto; /*0px top/bottom auto left/right */
font-size:10px; /* By default fonts are usually 16px but may not be in some browsers */
}
p, li {
font-size:1.5em; /* Set all text to be 1.5 * overall font size = 15 pixels */
}
section {
/* each of the two sections will use just under half the width of the width of the body */
width:395px;
display:block;
}
#choices {
/* float the choices list to the left of the page */
float:left;
background-color: #FFFF99;
}
#cart {
/* float the shopping cart to the right of the page */
float:right;
background-color: #7FFF00;
}
.cartlist {
/* Simplify the display of the lists, removing default bullet points and indentation */
list-style-type:none;
margin:0px;
padding:0px;
width:inherit;
}
.cartlist li {
/* Set each list item to be 2* the height of the text */
height:2em;
}
.cartlist li:nth-child(odd) {
/* Colour odd list items ie first, third, fifth etc, a different colour */
background-color:#eee;
}
#outputinfo {
/* prevents the DIV from joining the floating behaviour so it displays below the lists */
clear:both;
}
</style>
</head>
<body>
<section id="choices">
<p>Available Choices</p>
<ul id="sourcelist" class="cartlist">
<li data-value="2.99">&pound;2.99 : Chocolate</li>
<li data-value="3.49">&pound;3.49 : Cereal</li>
<li data-value="0.98">&pound;0.98 : Milk</li>
<li data-value="0.89">&pound;0.89 : Bread</li>
<li data-value="3.79">&pound;3.79 : Coffee</li>
<li data-value="2.53">&pound;2.53 : Strawberries</li>
<li data-value="3.89">&pound;3.89 : Cheesecake</li>
</ul>
</section>
<section id="cart">
<p>Shopping Cart</p>
<ul id="shoppinglist" class="cartlist"></ul>
</section>
<div id="outputinfo">
<p><button id="calctotal">Calculate Total</button> : <span id="totalresult"></span></p>
</div>
</body>

<script>

function getTargetElement(e) {
var targetelement=null;
targetelement=(e.srcElement || e.target || e.toElement)
return targetelement;
}

function calcTotal() {
var shoppinglist=document.getElementById("shoppinglist");
var total=0;
for(i=0;i<shoppinglist.children.length;i++) {
total+=parseFloat(shoppinglist.children[i].getAttribute("data-value"));
}
var totalresult=document.getElementById("totalresult");
totalresult.innerHTML="&pound;"+total.toFixed(2);
}

function handleEvent(e) {
var listclicked=getTargetElement(e);
var newlistitem=document.createElement("li");
var datavalue=listclicked.getAttribute("data-value");
newlistitem.setAttribute("data-value",datavalue);
newlisttext=document.createTextNode(listclicked.innerHTML)
newlistitem.appendChild(newlisttext);
var shoppinglist = document.getElementById("shoppinglist");
shoppinglist.appendChild(newlistitem);

var list = document.getElementById("shoppinglist");

list.onclick = function() { list.parentNode.removeChild(list);}


console.log(listclicked);
}

function removeItem(e){

var listclicked=getTargetElement(e);
var node = document.getElementById('shoppinglist');
listclicked.parentNode.removeChild(listclicked);
}

document.onreadystatechange = function(){
if(document.readyState=="complete") {
var sourcelist=document.getElementById("sourcelist");

for(i=0;i<sourcelist.children.length;i++) {
if(document.addEventListener) {
sourcelist.children[i].addEventListener("click", handleEvent, false);

} else {
sourcelist.children[i].attachEvent("onclick", handleEvent);
}

var totalbutton=document.getElementById("calctotal");
if(document.addEventListener) {
totalbutton.addEventListener("click",calcTotal,false);
} else {
totalbutton.attachEvent("onclick",calcTotal);
}

}

}
}
</script>

</html>




Answer

You don't want to remove the entire list, just the clicked LI element.

As you don't seem to have nested elements, event delegation becomes a little easier

var list = document.getElementById("shoppinglist");   

list.addEventListener('click', function(evt) { 
    list.removeChild(evt.target);
},false);

FIDDLE

For the future, if you wanted nesten elements, you could use element.closest()

var list = document.getElementById("shoppinglist");   

list.addEventListener('click', function(evt) {
    var p = evt.target.closest('li');
   list.removeChild(p);
}, false);

Note the somewhat lacking support in older browsers for closest(), but there are several polyfills available if needed.

Also note that you're binding event handlers inside event handlers, which is a big no-no, your code does the equivalent of

var sourcelist = document.getElementById("sourcelist");

for(i = 0; i < sourcelist.children.length; i++) {
    sourcelist.children[i].addEventListener("click", handleEvent, false);
    ...

// and then

function handleEvent(e) {

    var list = document.getElementById("shoppinglist");   

    list.addEventListener('click', function(evt) { 
        list.removeChild(evt.target);
    },false);
    ....

so every time you add another list item to the list, you bind a new event handler, and it adds up, but you only need one single event handler, having multiple event handlers will just try to remove the same element over and over again, but it's removed the first time.

Comments