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 Getting the First and Last Child

Michael Brown
Michael Brown
12,406 Points

How to remove "up" button from the firstListItem and "down" from lastListitem?

I have been having issues with this for at least 3 hours now and I feel like it's something so simple, but I've gotten the list items to initially show properly, but the moment I click on "down" or "up" the list items move, but they items that were previously without buttons, stay the same. For example, when I click down on the first list item, it goes to the next list item, but still doesn't have the "up" button. I'd like to figure this out, where can I start?

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');
const lis = listUl.children;
let firstListItem = listUl.firstElementChild;
let lastListItem = listUl.lastElementChild;

function attachListItemButtons(li){
  if (li != firstListItem) {
    let up = document.createElement('button');
    up.className = "up";
    up.textContent = "Up";
    li.appendChild(up);
}
  if (li != lastListItem){
    let down = document.createElement('button');
    down.className = "down";
    down.textContent = "Down";
    li.appendChild(down);
  }
  let remove = document.createElement('button');
  remove.className = "remove";
  remove.textContent = "Remove";
  li.appendChild(remove);
}

for (let i = 0; i < lis.length; i += 1) {
  attachListItemButtons(lis[i]);
}

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);
      }
    }
    if (event.target.className == 'down') {
      let li = event.target.parentNode;
      let prevLi = li.previousElementSibling;
      let nextLi = li.nextElementSibling;
      let ul = li.parentNode;
      if (nextLi) {
        ul.insertBefore(nextLi, li);
      }
    }
  }
});

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 = '';
});

addItemButton.addEventListener('click', () => {
  let ul = document.getElementsByTagName('ul')[0];
  let li = document.createElement('li');
  li.textContent = addItemInput.value;
  attachListItemButtons(li);
  ul.appendChild(li);
  addItemInput.value = '';
});

1 Answer

Steven Parker
Steven Parker
229,785 Points

Whenever you handle a movement button push, you'll need to determine if that button has reached the upper or lower limit (has become a first or last child), and remove the appropriate button. At the same time, you'll want to add that same button to the sibling element that it passed.

But you'll also want to check if an item is moving away from either end, and if so give it the missing button and remove that same button from the sibling it just passed.

Michael Brown
Michael Brown
12,406 Points

you'll need to determine if that button has reached the upper or lower limit (has become a first or last child), and remove the appropriate button

So I've added a conditional statement which checks if the button is equal to the first element child of the list item, if so, then the "up" button is to be removed as seen below. But for some reason it keeps saying "up is undefined". How can that be if it is there as a child to the list element?

if (li == ul.firstElementChild) {
        li.removeChild(up);
      }
Steven Parker
Steven Parker
229,785 Points

The button may exist, but within the handler you still need to create a variable to reference it. So you probably need something like this before the removeChild statement:

let up = li.getElementsByClassName("up")[0];