Food Ranking List Challenge (TestDome)

1.1k views Asked by At

I get stuck on this challenge so I need help.

A website needs a list where users can rank their favorite foods. Write the setup function, which should register click handlers on all Up! and Down! buttons. The Up! button should move the list item one place up in the list, while Down! button should move the list item one place down in the list.

For example, consider this code:

document.body.innerHTML = `<ol>
  <li><button>Up!</button>Taco<button>Down!</button></li>
  <li><button>Up!</button>Pizza<button>Down!</button></li>
  <li><button>Up!</button>Eggs<button>Down!</button></li>
</ol>`;

setup();

If the button Up! button in Pizza list item is clicked, Pizza should be the first item in the list, while Taco should be the second item.

This is my current code:

function setup() {
  let list = document.getElementByTagName('li');
  let btnList = document.getElementByTagName('button');
  let up;
  let down;
  
  for (let l = 0; l < list.length; l++){
    for (let b = 0; b< btnList.length; b++){
      btnList[b].addEventListener("click", (item, index)=>{
        if(btnList[b].textContent == "Up!"){
          up = list[l - 1]
        } else if(btnList[b].textContent == "Down!"){
          down = list[l + 1]
        } else{
          return list
        }
      })
    }
  }
    return list;  
      
    })
  }
}

I need to solve it without jQuery.

3

There are 3 answers

0
Zsolt Meszaros On

You don't need two for loops to iterate over the list elements and the buttons. You only need the buttons, the li elements are their parentNodes.

Moving up

Once you add the event listeners to every button, you can check if they are up or down buttons by checking their textContent. If it's an "up" button, you will need to check if it's the first element in the list. If it is, don't do anything, you can't move it any higher. :)

If it's not the first element, you can use insertBefore to swap nodes. Its first parameter is the node you want to insert, in this case the parent element; li. The second parameter is the reference; the node before which the li is inserted. That's the previousElementSibling of the parent.

Moving down

To move an element down is pretty similar. You probably think that you will use insertAfter to swap, but there is no insertAfter method. You can use insertBefore again, but this time the node you insert will be the nextElementSibling and the reference is the parent.

Check out the snippet below:

document.body.innerHTML = `<ol>
  <li><button>Up!</button>Taco<button>Down!</button></li>
  <li><button>Up!</button>Pizza<button>Down!</button></li>
  <li><button>Up!</button>Eggs<button>Down!</button></li>
</ol>`

function setup() {
  let btnList = document.querySelectorAll('button')

  for (let button of btnList) {
    button.addEventListener('click', handleClick)
  }
}

function handleClick(e) {
  let parent = e.target.parentElement
  let isUp = e.target.textContent === 'Up!'
  let isDown = e.target.textContent === 'Down!'
  let isFirst = !parent.previousElementSibling
  let isLast = !parent.nextElementSibling

  if (isUp && !isFirst)
    parent.parentNode.insertBefore(parent, parent.previousElementSibling)

  if (isDown && !isLast)
    parent.parentNode.insertBefore(parent.nextElementSibling, parent)
}

setup()
button {
  background-color: hsl(206, 100%, 52%);
  border: 0;
  border-radius: 4px;
  color: #fff;
  cursor: pointer;
  margin: 2px 4px;
  padding: 4px 8px;
}

button:hover {
  background-color: hsl(206, 100%, 40%);
}

You could also just add a single event listener on the ol element and check if the click target is a button. You can use event.target.tagName for this. If the tagName is BUTTON (always uppercase in HTML), you just return to exit early:

document.body.innerHTML = `<ol>
  <li><button>Up!</button>Taco<button>Down!</button></li>
  <li><button>Up!</button>Pizza<button>Down!</button></li>
  <li><button>Up!</button>Eggs<button>Down!</button></li>
</ol>`

function setup() {
  document.querySelector('ol').addEventListener('click', e => {
    if (e.target.tagName !== 'BUTTON')
      return

    let parent = e.target.parentElement
    let isUp = e.target.textContent === 'Up!'
    let isDown = e.target.textContent === 'Down!'
    let isFirst = !parent.previousElementSibling
    let isLast = !parent.nextElementSibling

    if (isUp && !isFirst)
      parent.parentNode.insertBefore(parent, parent.previousElementSibling)

    if (isDown && !isLast)
      parent.parentNode.insertBefore(parent.nextElementSibling, parent)
  })
}

setup()
button {
  background-color: hsl(206, 100%, 52%);
  border: 0;
  border-radius: 4px;
  color: #fff;
  cursor: pointer;
  margin: 2px 4px;
  padding: 4px 8px;
}

button:hover {
  background-color: hsl(206, 100%, 40%);
}

0
Musaib Mushtaq On

//Following code will give you 100% perfect score.
   

function setup() {
  let buttons = document.querySelectorAll('button');
// console.log(buttons);
  buttons.forEach(function(btn){
// console.log(btn);
    btn.addEventListener("click", function(){
// console.log(btn.textContent);
      if(btn.textContent.includes('Up!')){ 
//      console.log(btn.parentElement.previousElementSibling);
//      console.log(btn.parentElement.nextElementSibling);
if(btn.parentElement.previousElementSibling != null){
var store = btn.parentElement.previousElementSibling.innerHTML;
btn.parentElement.previousElementSibling.innerHTML= btn.parentElement.innerHTML;
btn.parentElement.innerHTML= store;
setup();
}else{ console.log("Hello Developer, this element is at start");}
}else{ 
// taking down.
if(btn.parentElement.nextElementSibling != null){
    var stored = btn.parentElement.nextElementSibling.innerHTML;
    btn.parentElement.nextElementSibling.innerHTML = btn.parentElement.innerHTML;
btn.parentElement.innerHTML = stored;
setup(); 
} else {
console.log("Hi developer, element already at last");
}
}
    });
  });
}

// Example case
document.body.innerHTML = `<ol>
  <li><button>Up!</button>Taco<button>Down!</button></li>
  <li><button>Up!</button>Pizza<button>Down!</button></li>
  <li><button>Up!</button>Eggs<button>Down!</button></li>
</ol>`;

setup();
document.getElementsByTagName('button')[2].click();
console.log(document.body.innerHTML);

1
Habeeb On

Use the code below

function setup() {
  //Write your code here
  $.fn.moveUp = function() {
  before = $(this).prev();
  $(this).insertBefore(before)
}

$.fn.moveDown = function() {
  after=$(this).next();
  $(this).insertAfter(after)
}

$("button:contains('Up!')").click(function() {
  $(this).parent().moveUp()
})

$("button:contains('Down!')").click(function() {
  $(this).parent().moveDown()
})
}