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

Trying to remove the first up button and last down button. Can you help me?

I am trying to accomplish this:

  1. Remove the up button from the the first list item.
  2. Remove the down button from the last list item.
  3. If I move any of the item in the list, make sure that it still keeps the first up button and the last down button on the list removed.

Here is an attachhment to my workspace. Any input would be appreciated. Thank you!

https://teamtreehouse.com/workspaces/23127862

Steven Parker
Steven Parker
243,658 Points

:x: You can't share a direct URL to your workspace, it's temporary and only exists while you are using it.

:information_source: But you can use the snapshot function in the workspace and provide the link to that.

Here is a snapshot of my workspace.

https://w.trhou.se/tngl2ynw6u

4 Answers

Hi Zachery, I couldn't work out what your code was doing so I just started from the final code from the solution.

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;
const firstListItem = listUl.firstElementChild;
const lastListItem = listUl.lastElementChild;

firstListItem.style.backgroundColor = 'lightskyblue';
lastListItem.style.backgroundColor = 'lightsteelblue';

function hideAndShowButtons() {
  const lastItem = listUl.lastElementChild;
  const secoundToLastItem = listUl.lastElementChild.previousElementSibling;
  const firstItem = listUl.firstElementChild;
  const secoundItem = listUl.firstElementChild.nextElementSibling;

  lastItem.firstElementChild.style.visibility = 'visible';
  lastItem.firstElementChild.nextElementSibling.style.visibility = 'hidden';

  secoundToLastItem.firstElementChild.style.visibility = 'visible';
  secoundToLastItem.firstElementChild.nextElementSibling.style.visibility = 'visible';

  firstItem.firstElementChild.style.visibility = 'hidden';
  firstItem.firstElementChild.nextElementSibling.style.visibility = 'visible';

  secoundItem.firstElementChild.style.visibility = 'visible';
  secoundItem.firstElementChild.nextElementSibling.style.visibility = 'visible';  
}

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

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

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

hideAndShowButtons();

It works fine as is when you have 4 or more list items, but once you get smaller than that you could add conditional checks. This was just one way to do it, there would be heaps more, but you really only have to worry about the top 2 list items and the bottom 2 list items cause every other list item will display both buttons (up and down).

Thank you, this is awesome! Can you explain to me what you added? I am still a little rough around the edges with Vanilla javascript. :-)

Thank you so much for the replies above, it really helped me understand what we needed to do, and build upon that. The code above (which is wonderful and I super appreciate it) assumes that there are only 4 list items, and doesn't work when you add a new item to the list. SO, here's my code, in entirety, that will loop through the list and check for first item / last item, and then hide the corresponding buttons (up or down), regardless of the number of list items.

Hope this helps anybody who was going crazy trying to figure this out like I was! :)

const toggleList = document.querySelector('#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 listItems = document.querySelectorAll('li');
const lis = listUl.children;


//create a function to hide the first up button and the last down button
function hideAndShowButtons() {
  let firstItem = listUl.firstElementChild;
  let lastItem = listUl.lastElementChild;

  for (let i = 0; i < listUl.children.length; i++) {
    if (listUl.children[i] === firstItem) {
      listUl.children[i].firstElementChild.style.visibility = 'hidden';
    }
    if (listUl.children[i] === lastItem) {
      listUl.children[i].firstElementChild.nextElementSibling.style.visibility = 'hidden';
    }
    if (listUl.children[i] !== lastItem) {
      listUl.children[i].firstElementChild.nextElementSibling.style.visibility = 'visible';
    }
    if (listUl.children[i] !== firstItem) {
      listUl.children[i].firstElementChild.style.visibility = 'visible';
    }
  }
}

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

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

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.querySelectorAll('ul')[0];
  let li = document.createElement('li');
  li.textContent = addItemInput.value;
  attachListItemButtons(li);
  ul.appendChild(li);
  hideAndShowButtons();
  addItemInput.value = '';
});

  hideAndShowButtons();

Thank you! You were such a big help! with your added function and calls to that function, the bugs got fixed. Now you can add an item and the list will remove the last button as it adds items to the list.

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;
const firstListItem = listUl.firstElementChild;
const lastListItem = listUl.lastElementChild;

//firstListItem.style.backgroundColor = 'lightskyblue';
//lastListItem.style.backgroundColor = 'lightsteelblue';

function hideAndShowButtons() {
  const lastItem = listUl.lastElementChild;
  const secoundToLastItem = listUl.lastElementChild.previousElementSibling;
  const firstItem = listUl.firstElementChild;
  const secoundItem = listUl.firstElementChild.nextElementSibling;

  secoundToLastItem.firstElementChild.style.visibility = 'visible';
  secoundToLastItem.firstElementChild.nextElementSibling.style.visibility = 'visible';

  secoundItem.firstElementChild.style.visibility = 'visible';
  secoundItem.firstElementChild.nextElementSibling.style.visibility = 'visible';  
  firstItem.firstElementChild.nextElementSibling.style.visibility = 'visible';
  lastItem.firstElementChild.style.visibility = 'visible';
  lastItem.firstElementChild.nextElementSibling.style.visibility = 'hidden';
  firstItem.firstElementChild.style.visibility = 'hidden';

}

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

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

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

hideAndShowButtons();

I've edited your answer a bit to add code formatting. Be sure to check out the Markdown Cheatsheet below the editor for more information!