Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript JavaScript and the DOM (Retiring) Traversing the DOM Using previousElementSibling and insertBefore

My solution to allowing list items created by the 'Add Item' button to have 'Up' & 'Remove' functionality.

Just for reference, I noticed that following the code from Guil, you could add items to the list using JavaScript. However, unlike items that are present when the page loads (being included inside of the HTML document), any added items lack full functionality.

That is, they lack buttons to move the item up the list, and a button to remove it from the list entirely. Here's my solution to this, amending the event listener 'addItemButton'.

I've included the original code too commented out to make comparisons from the work done in Guil's tutorials.

There's probably a slightly more elegant/succinct way to write this, but here goes:

<!DOCTYPE html>
<html>
  <head>
    <title>JavaScript and the DOM</title>
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <h1 id="myHeading">JavaScript and the DOM</h1>
    <p>Making a web page interactive</p>  
    <button id="toggleList">Hide list</button>

    <div class="list">
      <p class="description">Things that are purple:</p>
      <input type="text" class="description">
      <button class="description">Change list description</button>
      <ul>
        <li>grapes 
          <button class="up">Up</button>
          <button class="remove">Remove</button>
        </li>
        <li>amethyst
          <button class="up">Up</button>
          <button class="remove">Remove</button>
        </li>
        <li>lavender
          <button class="up">Up</button>
          <button class="remove">Remove</button>
        </li>
        <li>plums 
          <button class="up">Up</button>
          <button class="remove">Remove</button>
        </li>
      </ul>
      <input type="text" class="addItemInput">
      <button class="addItemButton">Add item</button>
    </div>
    <script src="app.js"></script>
  </body>
</html>
const toggleList = document.getElementById('toggleList');
const listDiv = document.querySelector('.list');
const descriptionInput = document.querySelector('input.description');
const descriptionP = document.querySelector('p.description');
const descriptionButton = document.querySelector('button.description');
const listUl = listDiv.querySelector('ul');
const addItemInput = document.querySelector('input.addItemInput');
const addItemButton = document.querySelector('button.addItemButton');


listUl.addEventListener('click', (event) => {
    if (event.target.tagName === 'BUTTON') {
      if (event.target.className === 'remove') {
      let li = event.target.parentNode;
      let ul = li.parentNode;
      ul.removeChild(li);
      } 
      if (event.target.className === 'up') {
         let li = event.target.parentNode;
         let prevLi = li.previousElementSibling;
         let ul = li.parentNode;
         if (prevLi) {
         ul.insertBefore(li, prevLi);
         }
      }
    }
 });


toggleList.addEventListener('click', () => {
  if (listDiv.style.display == 'none') {
    toggleList.textContent = 'Hide list';
    listDiv.style.display = 'block';
  } else {
      toggleList.textContent = 'Show list';
      listDiv.style.display = 'none';   
  }                                                
});                            

descriptionButton.addEventListener('click', () => {
  descriptionP.innerHTML = descriptionInput.value + ':';   
  descriptionInput.value = '';
});


//additions made to add Up & Remove buttons to added list items
//Create two further new elements (buttons) when click is registered on addItemButton
//buttons given text content & class names
//These buttons are appended inside the HTML tags of each new list item
//List item is appended to ul as before
//no bugs noted
//scope for refactoring this code block?
addItemButton.addEventListener('click', () => {
  //this method, getElementsByTagName returns a collection, only one unordered list
  //on the page, collection holds only one item, accessed at index zero.
  let ul = document.getElementsByTagName('ul')[0];
  let li = document.createElement('li');
  let buttonUp = document.createElement('button');
  let buttonRemove = document.createElement('button');
  li.textContent = addItemInput.value;
  buttonUp.textContent = 'Up';
  buttonUp.className = 'up';
  buttonRemove.textContent = 'Remove';
  buttonRemove.className = 'remove';
  li.appendChild(buttonUp);
  li.appendChild(buttonRemove);
  ul.appendChild(li);
  addItemInput.value = '';
});

//backup of original code
//addItemButton.addEventListener('click', () => {
//  //this method, getElementsByTagName returns a collection, only one unordered list
//  //on the page, collection holds only one item, accessed at index zero.
//  let ul = document.getElementsByTagName('ul')[0];
//  let li = document.createElement('li');
//  li.textContent = addItemInput.value;
//  ul.appendChild(li);
//  addItemInput.value = '';
//});

snapshot here

1 Answer

Geraldo Hernandez
Geraldo Hernandez
7,515 Points

Good catch! I tested Guil's code after reading your post, and it didn't include this functionality for new list items. I decided to try adding this functionality and my code was similar to your event listener 'addItemButton'. I think your way is fine, since each button has to have its own class name and text content.