3

I use this code to delete the last item of an <ul> list, but only on the second, fourth, sixth, ... every second click on the button the item gets removed, but every click the message appears. What can I do that the element gets deleted on every click.

document.getElementsByTagName('input')[0].onclick = function () {
    'use strict';
    var list = document.getElementById('list'), item = list.lastChild;
    list.removeChild(item);
    window.alert("Removed");
};
<ul id="list">
    <li>List item 1</li>
    <li>List item 2</li>
    <li>List item 3</li>
    <li id="child">List item 4</li>
    <li>List item 5</li>
</ul>
<input type="button" value="Delete last">
scniro
  • 16,844
  • 8
  • 62
  • 106

2 Answers2

11

This is because .lastChild returns all nodes, including empty text nodes which exist in your <ul>. Use .lastElementChild instead to target your <li> nodes

The difference between this property and lastElementChild, is that lastChild returns the last child node as an element node, a text node or a comment node (depending on which one's last), while lastElementChild returns the last child node as an element node (ignores text and comment nodes).

See HTML DOM lastChild Property and HTML DOM lastElementChild Property for more information

document.getElementsByTagName('input')[0].onclick = function () {
    var list = document.getElementById('list'), item = list.lastElementChild;
    list.removeChild(item);
};
<ul id="list">
    <li>List item 1</li>
    <li>List item 2</li>
    <li>List item 3</li>
    <li id="child">List item 4</li>
    <li>List item 5</li>
</ul>
<input type="button" value="Delete last">

Some more details on why this is happening... When you format your markup with clean spacing, what I think of as "phantom" text nodes silently exist within your <ul>. If you minify this markup to the following, your first example would indeed work fine

<ul id="list"><li>List item 1</li><li>List item 2</li><li>List item 3</li><li id="child">List item 4</li><li>List item 5</li></ul>

Plunker Link - minifed markup example using .lastChild

scniro
  • 16,844
  • 8
  • 62
  • 106
  • Ok, it works now, I thought the text node is a child node of the element node, so removing the element node also removes the text node. –  May 15 '15 at 14:53
  • @danielr1996 which it does, but you were removing the `text node` not the `element node` using `lastElementChild` does remove the `element node` which also removes the `text node` – Edwin Reynoso May 15 '15 at 14:56
  • @danielr1996 it's weird, there are what I consider "phantom" text nodes in your `
      `. Check out [this Plunker](http://plnkr.co/edit/6aaN2Cq7JAJiJWvOpaff?p=preview) to see the empty text nodes logged out to the console
    – scniro May 15 '15 at 14:57
  • @danielr1996 I added some additional detail to the answer that may be helpful – scniro May 15 '15 at 15:01
1

Change:

item = list.lastChild;

to

item = list.lastElementChild;
stile17
  • 171
  • 8