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

Joseph Bertino
seal-mask
.a{fill-rule:evenodd;}techdegree
Joseph Bertino
Full Stack JavaScript Techdegree Student 14,652 Points

Challenge Solution

Note that I am only including JS code related to manipulating the <ul> element.

const ul = document.querySelector('ul');
const lis = ul.children;
const addItemInput  = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('.addItemButton');
const listItems = document.getElementsByTagName('li');

Array.prototype.forEach.call(lis, li => { attachListItemButtons(li);} );

function addButtonUp(li) {
  let up = document.createElement('button');
  up.className = 'buttonUp';
  up.textContent = 'Up';
  li.appendChild(up);
}

function addButtonDown(li) {
  let down = document.createElement('button');
  down.className = 'buttonDown';
  down.textContent = 'Down';
  li.appendChild(down);
}

function addButtonRemove(li) {
  let remove = document.createElement('button');
  remove.className = 'buttonRemove';
  remove.textContent = 'Remove';
  li.appendChild(remove);
}

function attachListItemButtons(li) {
  if (li.previousElementSibling !== null) {
    addButtonUp(li);
  }
  if (li.nextElementSibling !== null) {
    addButtonDown(li);
  }
  addButtonRemove(li);
}

function swapButtons(first, second){
  // first will be insertBefore()'d second AFTER this function call
  if (second.previousElementSibling === null) {
    let bup = first.getElementsByClassName('buttonUp')[0];
    let bdown = second.getElementsByClassName('buttonDown')[0];
    second.insertBefore(bup, bdown);
  }
  if (first.nextElementSibling === null) {
    let brem = first.getElementsByClassName('buttonRemove')[0];
    let bdown = second.getElementsByClassName('buttonDown')[0];
    first.insertBefore(bdown, brem);
  }
}

ul.addEventListener('click', (event) => {
  if (event.target.tagName ==='BUTTON') {
    let li = event.target.parentNode;
    let prevli = li.previousElementSibling;
    let nextli = li.nextElementSibling;
    let ul = li.parentNode;

    if (event.target.className === 'buttonRemove') {
      if (prevli === null && nextli !== null) {
        let nextUp = nextli.getElementsByClassName('buttonUp')[0];
        nextli.removeChild(nextUp);
      }
      else if (nextli === null && prevli != null) {
        let prevDown = prevli.getElementsByClassName('buttonDown')[0];
        prevli.removeChild(prevDown);
      }
      ul.removeChild(li);
    }

    if (event.target.className === 'buttonUp') {
      if (prevli !== null) {
        swapButtons(li, prevli);
        ul.insertBefore(li, prevli);
      }
    }

    if (event.target.className === 'buttonDown') {
      if (nextli !== null) {
        swapButtons(nextli, li);
        ul.insertBefore(nextli, li); 
      }
    }
  }
});

addItemButton.addEventListener(
  'click', () => {
    let ul = document.getElementsByTagName('ul')[0];

    if (ul.children.length > 0) {
      // if you are adding an item to the end of the list,
      // give the current last item a "Down" button
      let currLast = ul.lastElementChild;
      let downButton = document.createElement('button');
      downButton.className = 'buttonDown';
      downButton.textContent = 'Down';
      let removeButton = currLast.getElementsByClassName('buttonRemove')[0];
      currLast.insertBefore(downButton, removeButton);
    }

    let li = document.createElement('li');
    li.textContent = addItemInput.value;
    ul.appendChild(li);
    attachListItemButtons(li);
    addItemInput.value = '';
})

2 Answers

Reggie Williams
STAFF
Reggie Williams
Treehouse Teacher

It looks like you've gotten that functionality working when I run the code Joseph Bertino, are you getting any errors?

Reggie Williams
STAFF
Reggie Williams
Treehouse Teacher

Hey Joseph Bertino which part of this challenge is your question regarding?

Joseph Bertino
seal-mask
.a{fill-rule:evenodd;}techdegree
Joseph Bertino
Full Stack JavaScript Techdegree Student 14,652 Points

Adding functionality to the page to only give list items the appropriate buttons...e.g. the top list item shouldn't have an "Up" button