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

Doron Geyer
seal-mask
.a{fill-rule:evenodd;}techdegree
Doron Geyer
Full Stack JavaScript Techdegree Student 13,897 Points

My Solution, with a slight quirk

so my solution works for adding and removing buttons and moving them up and down. The issue I have found is that if I remove items from the top down the last item remaining has only got the remove button ( no up and no down button) great! But if I remove the items from the bottom up, the last item has the remove and down button. Any idea how I can get it to not show the down button.

I tried setting another conditional that says to hide all other buttons if the length of the list collection is 1 but it works sporadically , I tried to set it as a trial if an item is first child && last child element that it disables all the other buttons. Ive spend about 2 hours messing with this but every idea I have seems to produce a new level of headbutting my desk to deal with.

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 ListItem= listUL.lastElementChild;
const allButtons=document.querySelectorAll("button");

function hideButtons(list){
  let firstPosition = listUL.firstElementChild;
  let lastPosition = listUL.lastElementChild;
 for(let i=0;i<list.length;i++){
  let buttonUp= list[i].querySelector("button.up");
  let buttonDown=list[i].querySelector("button.down");
   if(list[i]==firstPosition){
    buttonUp.style.display="none";
   }else if (list[i]==lastPosition){
    buttonDown.style.display="none";
   }
  }  
}
function showButtons(list) {
  let firstPosition = listUL.firstElementChild;
  let lastPosition = listUL.lastElementChild;  
  for(let i = 0 ; i <list.length;i++){
    if(list[i]!=firstPosition && list[i]!=lastPosition){
      let buttonUp= list[i].querySelector("button.up");
      let buttonDown=list[i].querySelector("button.down");
      buttonDown.style.display="";
      buttonUp.style.display="";
    }
  }
}
listDiv.addEventListener("click",(e)=>{
     if(e.target.tagName= "BUTTON"){  
       hideButtons(lis);
       showButtons(lis);
      }   
     });

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);

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

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', () => {
   if(descriptionInput.value==""){
  descriptionP.innerHTML ="No list name provided :";
  }else {                                           
  descriptionP.innerHTML = descriptionInput.value + ':';
  descriptionInput.value = '';
  }                       
});

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

2 Answers

Your hideButtons function initially tests if(list[i]==firstPosition), and if true won't test if (list[i]==lastPosition) to see if also true to set the down style. You can reverse these two if blocks and see the opposite effect where removing the items from the bottom up works but removing the items from top to bottom doesn't. To fix this add an initial condition that checks if both first and last are true:

function hideButtons(list){
  let firstPosition = listUL.firstElementChild;
  let lastPosition = listUL.lastElementChild;

  for(let i=0;i<list.length;i++){
    let buttonUp= list[i].querySelector("button.up");
    let buttonDown=list[i].querySelector("button.down");

    if (list[i]==firstPosition && list[i]==lastPosition){
       buttonUp.style.display="none";
       buttonDown.style.display="none";
    } else if(list[i]==firstPosition){
         buttonUp.style.display="none";
    } else if (list[i]==lastPosition){
         buttonDown.style.display="none";
    }
  }  
}

or just have two separate if blocks

function hideButtons(list){
  let firstPosition = listUL.firstElementChild;
  let lastPosition = listUL.lastElementChild;

  for(let i=0;i<list.length;i++){
    let buttonUp= list[i].querySelector("button.up");
    let buttonDown=list[i].querySelector("button.down");

    if(list[i]==firstPosition){
      buttonUp.style.display="none";
    }

    if (list[i]==lastPosition){
      buttonDown.style.display="none";
    }
  }  
}
Doron Geyer
seal-mask
.a{fill-rule:evenodd;}techdegree
Doron Geyer
Full Stack JavaScript Techdegree Student 13,897 Points

Thanks for responding Kris, will give it a shot now that I've had a decent night's sleep. I think I spend too long staring at the problem. Perhaps with a fresh mind, it will be an easy fix.

Going to give your suggestions a try and let you know how it works out.

Cheers, Doron

Doron Geyer
seal-mask
.a{fill-rule:evenodd;}techdegree
Doron Geyer
Full Stack JavaScript Techdegree Student 13,897 Points
if (list[i]==firstPosition && list[i]==lastPosition){
       buttonUp.style.display="none";
       buttonDown.style.display="none";

ok popped it in and it works, which is quite frustrating! as I said in my original post

" tried to set it as a trial if an item is first child && last child element that it disables all the other buttons"

that was one of the first things I tried , guess I was just too tired and muddled to do a decent job of it. sometimes its better to leave it alone and come back to it.

Thanks again.

not sure where to call the function. Nothing is making it work. could someone post finished code so i can compare?