JavaScript JavaScript and the DOM Traversing the DOM Getting the First and Last Child

Grzegorz Zielinski
Grzegorz Zielinski
5,838 Points

Buttons challenge solution :) What do you think?

Hello, could anybody give me a feedback of what you think about my solution for challenge please? Thanks!

const descriptionInput = document.querySelector("input.description");
const descriptionP = document.querySelector("p.description");
const descriptionButton = document.querySelector("button.description");

const toggleList = document.querySelector("#toggleList");
const list = document.querySelector(".list");
const ulList = list.querySelector("ul");

const addItemInput = document.querySelector("input.addItemInput");
const addItemButton = document.querySelector("button.addItemButton");

const firstListElement = document.querySelector(".up");
const lis = ulList.children;
const firstPosition = ulList.firstElementChild;
const lastPosition = ulList.lastElementChild;

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

//My part of code starts here

function firstLastRemove() { // Removes "Up" button from first li, and "Down" from last
  let first = ulList.firstElementChild;
  let last = ulList.lastElementChild;
  let up = first.querySelector(".up");
  let down = last.querySelector(".down");
  first.removeChild(up);
  last.removeChild(down);
}

function firstLastBGColor() { // Changes colors of first and last li, and also changes color of first "Down" button to #508abc
  let first = ulList.firstElementChild;
  let last = ulList.lastElementChild;
  for (let i = 0; i < lis.length; i += 1) lis[i].style.background = "white";
  first.style.background = "lightblue";
  last.style.background = "lightpink";
  ulList.firstElementChild.firstElementChild.style.background = "#508abc";
}

function resetAllButtons(li) { // Removes all buttons from every single li
  for (let i = 0; i < li.length; i += 1) {
    let list = li[i];
    var child = list.lastElementChild;
    while (child) {
      list.removeChild(child);
      child = list.lastElementChild;
    }
  }
}

for (let i = 0; i < lis.length; i += 1) { // Simple loop which generate all buttons, then remove  unnecessary buttons and changes background colors
  attachListItemButtons(lis[i]);
}

firstLastRemove();
firstLastBGColor();

list.addEventListener("click", (event) => { // Also simple click event which starts of removing all the buttons, then loops turns in and do exactly the same process like above.
  resetAllButtons(lis);
  for (let i = 0; i < lis.length; i += 1) {
    attachListItemButtons(lis[i]);
  }
  firstLastRemove();
  firstLastBGColor();
});

//End of my part

ulList.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 nextLi = li.nextElementSibling;
      let ul = li.parentNode;
      if (nextLi) {
        ul.insertBefore(nextLi, li);
      }
    }
  }
});

descriptionButton.addEventListener("click", () => {
  descriptionP.innerHTML = `<h2>${descriptionInput.value}:</h2>`;
  descriptionInput.value = "";
});

toggleList.addEventListener("click", () => {
  if (list.style.display == "none") {
    list.style.display = "block";
    toggleList.textContent = "Hide List";
  } else {
    list.style.display = "none";
    toggleList.textContent = "Show List";
  }
});

addItemButton.addEventListener("click", () => {
  let ul = document.querySelector("ul");
  let li = document.createElement("li");
  li.textContent = addItemInput.value;
  attachListItemButtons(li);
  ul.appendChild(li);
  addItemInput.value = "";
});

Generally my code removes and generates all the buttons over and over again every time somebody uses one of them.

My part is quite short, but seems to work fine :) Let me know if I could change something or improve, thanks!

1 Answer

Steven Parker
Steven Parker
201,999 Points

Assuming it performs as required, that's easily 90% of the job. :+1:

But to tune it for efficiency, you might see if you could use logic to avoid creating something that would need to be removed, and avoid removing anything that would need to be re-created.