Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete Specific <li> elements using JavaScript

Tags:

javascript

dom

The function does not seem to delete the Node containing the specified value unless it is first value (in this case 'apples'). The for loop also has to execute twice before deletion of any kind. Why is that so?

function removeSpec()
{
    var query = document.getElementById('spec').value;  /* Value inputted by user */
    elements = document.getElementsByClassName('fruit'); /* Get the li elements in the list */
    var myList = document.getElementById("myList3"); /* Var to reference the list */
    var length = (document.getElementsByClassName('fruit').length); /* # of li elements */
    var checker = 'false'; /* boolean-ish value to determine if value was found */

    for(var counter = 0; counter < length; counter ++)
    {
        if (elements[counter].textContent == query )
        {
             alert("Counter : " + counter);
             myList.removeChild(myList.childNodes[ (counter) ]);
             checker="true";
        }
    }
  if ( checker == "false") 
   {
       alert("Not Found");
   }
}

The corresponding HTML:

  <ul id="myList3">
                <li class="fruit" >Apples</li>
                <li class="fruit" >Oranges</li>
                <li class="fruit" >Banannas</li>
                <li class="fruit">Strawberry</li>
   </ul>
   <form> 
           Value: <input type="text" name="" value="" id="spec">
   <br><br>
    </form>
    <button type="button" style="height:20px;width:200px" href="javascript:void(0)" onclick="removeSpec()" > 

        Remove Specified 
   </button>
like image 771
Nahmed39 Avatar asked Jan 02 '17 05:01

Nahmed39


2 Answers

childNodes returns a list of all child nodes. That includes text nodes. Between every <li> element you have a text node that contains spaces and a line break. So, childNodes returns a list of 9 nodes, but you are assuming list of 4 nodes (document.getElementsByClassName('fruit').length).

You could use .children instead of .childNodes. .children returns a list of only element nodes. Or better yet, use elements, since that's what you are iterating over.

You also need to stop iterating after you found an removed a node, otherwise you will be trying to access a position that doesn't exist anymore.

function removeSpec()
{
    var query = document.getElementById('spec').value;  /* Value inputted by user */
    elements = document.getElementsByClassName('fruit'); /* Get the li elements in the list */
    var myList = document.getElementById("myList3"); /* Var to reference the list */
    var length = (document.getElementsByClassName('fruit').length); /* # of li elements */
    var checker = 'false'; /* boolean-ish value to determine if value was found */

    for(var counter = 0; counter < length; counter ++)
    {
        if (elements[counter].textContent == query )
        {
             myList.removeChild(myList.children[ (counter) ]);
             // better: myList.removeChild(elements[counter]);
             checker="true";
             break;
        }
    }
  if ( checker == "false") 
   {
       alert("Not Found");
   }
}
<ul id="myList3">
                <li class="fruit" >Apples</li>
                <li class="fruit" >Oranges</li>
                <li class="fruit" >Banannas</li>
                <li class="fruit">Strawberry</li>
   </ul>
   <form> 
           Value: <input type="text" name="" value="" id="spec">
   <br><br>
    </form>
    <button type="button" style="height:20px;width:200px" href="javascript:void(0)" onclick="removeSpec()" > 

        Remove Specified 
   </button>

There are other things that could be improved (e.g. why not assign an actual boolean value to checker?), but they are not related to your question.

like image 94
Felix Kling Avatar answered Oct 26 '22 12:10

Felix Kling


I run this code. you should add this line

elements[counter].remove();

instead of this line

myList.removeChild(myList.childNodes[ (counter) ]);
like image 35
Shaybi Avatar answered Oct 26 '22 11:10

Shaybi