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 trialKevin Barnes
18,352 PointsHere's my solution - curious if there's anything I can improve
This frustrated the hell out of me at first, I was trying to re-add & then remove buttons again and had way too much code. Reading through some of the answers here turned me onto the idea of just hiding the unused buttons, this is the end result:
I created the function hideUnusedButtons(), and then called it when the buttons were being added, and during the list modification events. I found that it originally broke when the list only had a single item (it would show Up or Down depending what was on the item before the other item was removed). I've fixed this with a conditional check on the length of the list.
Really keen to hear any feedback for improvements, I'm happy with how little code it took, but I'm always looking to optimise as I learn this stuff.
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;
let firstListItem = listUl.firstElementChild;
let lastListItem = listUl.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);
}
function hideUnusedButtons() {
let first = lis[0].querySelector('button.up');
let last = lis[lis.length - 1].querySelector('button.down');
// Hide the necessary buttons for first and last items
first.style.visibility = 'hidden';
last.style.visibility = 'hidden';
// Unhide the previous first and last elements, this only runs if there is >1 item in the list to ensure a single item doesn't have 'Up' or 'Down' buttons
if (lis.length > 1) {
let prevFirst = lis[1].querySelector('button.up');
let prevLast = lis[lis.length - 2].querySelector('button.down');
prevFirst.style.visibility = 'visible';
prevLast.style.visibility = 'visible';
}
}
for (let i = 0; i < lis.length; i++) {
attachListItemButtons(lis[i]);
}
hideUnusedButtons();
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);
}
}
if (event.target.className == 'down') {
let li = event.target.parentNode;
let nextLi = li.nextElementSibling;
let ul = li.parentNode;
if (nextLi) {
ul.insertBefore(nextLi, li);
}
}
hideUnusedButtons();
}
});
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 = '';
hideUnusedButtons();
})
1 Answer
KRIS NIKOLAISEN
54,971 PointsIf you want to share a workspace you need to create a snapshot. Click the camera icon in the upper right corner of the workspace, then 'Take Snapshot' then post the link created here.
For your hideUnusedButtons() function one suggestion would be to check the length of lis
before using list items. Below causes an error when lis.length
equals 0
.
let first = lis[0].querySelector('button.up');
let last = lis[lis.length - 1].querySelector('button.down');
Kevin Barnes
18,352 PointsKevin Barnes
18,352 PointsP.S. Here's the workspace with it (hopefully) in action! http://port-80-b0w6osnomu.treehouse-app.com/