Tell us what’s happening:
I only have tests 5 and 23 left. Surprisingly, none of the other questions helped, despite having the same issues. Please help.
Your code so far
<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.0">
<title>Bookmark Manager</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<section id="main-section">
<h1>Bookmark Manager</h1>
<div id="dropdown">
<label for="category-dropdown">Select a category:</label>
<select id="category-dropdown" name="options">
<option value="news" selected>News</option>
<option value="entertainment">Entertainment</option>
<option value="work">Work</option>
<option value="miscellaneous">Miscellaneous</option>
</select>
</div>
<div id="buttons">
<button type="button" id="view-category-button">View Category</button>
<button type="button" id="add-bookmark-button">Add Bookmark</button>
</div>
</section>
<section id="form-section" class="hidden">
<form>
<h2 class="category-name"></h2>
<div>
<label for="name">Name:</label>
<input type="text" id="name">
</div>
<div>
<label for="url">URL:</label>
<input type="text" id="url">
</div>
<div>
<button type="button" id="close-form-button">Go Back</button>
<button type="button" id="add-bookmark-button-form">Add Bookmark</button>
</div>
</form>
</section>
<section id="bookmark-list-section" class="hidden">
<h2 class="category-name"></h2>
<div id="category-list">
</div>
<div>
<button type="button" id="close-list-button">Go Back</button>
<button type="button" id="delete-bookmark-button">Delete Bookmark</button>
</div>
</section>
</main>
<script src="script.js"></script>
</body>
</html>
/* file: script.js */
function getBookmarks() {
const bookmarks = localStorage.getItem('bookmarks');
if (!bookmarks) return [];
try {
const parsedBookmarks = JSON.parse(bookmarks);
if (Array.isArray(parsedBookmarks)) {
return parsedBookmarks;
} else {
return [];
}
} catch (e) {
return [];
}
}
function displayOrCloseForm() {
const mainSection = document.getElementById('main-section');
const formSection = document.getElementById('form-section');
mainSection.classList.toggle('hidden');
formSection.classList.toggle('hidden');
}
function displayOrHideCategory() {
const mainSection = document.getElementById('main-section');
const bookmarkListSection = document.getElementById('bookmark-list-section');
mainSection.classList.toggle('hidden');
bookmarkListSection.classList.toggle('hidden');
}
document.getElementById('add-bookmark-button').addEventListener('click', () => {
const categoryName = document.querySelector('#category-dropdown option:checked').text;
document.querySelector('.category-name').innerText = categoryName;
displayOrCloseForm();
});
document.getElementById('close-form-button').addEventListener('click', displayOrCloseForm);
document.getElementById('add-bookmark-button-form').addEventListener('click', () => {
const name = document.getElementById('name').value;
const url = document.getElementById('url').value;
const category = document.getElementById('category-dropdown').value;
const bookmarks = getBookmarks();
bookmarks.push({ name, url, category });
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
document.getElementById('name').value = '';
document.getElementById('url').value = '';
displayOrCloseForm();
});
document.getElementById('view-category-button').addEventListener('click', () => {
const selectedCategory = document.getElementById('category-dropdown').value;
document.querySelector('.category-name').innerText = selectedCategory;
const bookmarks = getBookmarks();
const categoryList = document.getElementById('category-list');
categoryList.innerHTML = '';
const filteredBookmarks = bookmarks.filter(b => b.category === selectedCategory);
if (filteredBookmarks.length === 0) {
categoryList.innerHTML = '<p>No Bookmarks Found</p>';
} else {
filteredBookmarks.forEach(bookmark => {
const radioId = bookmark.name.replace(/\s+/g, '-');
categoryList.innerHTML += `
<div>
<input type="radio" id="${radioId}" name="bookmark" value="${bookmark.name}">
<label for="${radioId}">
<a href="${bookmark.url}" target="_blank">${bookmark.name}</a>
</label>
</div>
`;
});
}
displayOrHideCategory();
});
document.getElementById('close-list-button').addEventListener('click', displayOrHideCategory);
document.getElementById('delete-bookmark-button').addEventListener('click', () => {
const bookmarks = getBookmarks();
const selectedBookmarkName = document.querySelector('input[name="bookmark"]:checked');
if (selectedBookmarkName) {
const updatedBookmarks = bookmarks.filter(b => b.name !== selectedBookmarkName.value);
localStorage.setItem('bookmarks', JSON.stringify(updatedBookmarks));
displayOrHideCategory();
}
});
/* file: styles.css */
:root {
--light-grey: #f5f6f7;
--dark-grey: #0a0a23;
--yellow: #f1be32;
--golden-yellow: #feac32;
}
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
main {
display: flex;
justify-content: center;
}
body {
background-color: var(--dark-grey);
}
.hidden {
display: none;
}
section {
display: flex;
flex-direction: column;
justify-content: center;
}
select,
input,
label {
margin-left: 10px;
}
div {
padding: 30px;
display: flex;
justify-content: center;
}
.close-form-button {
background: none;
border: none;
cursor: pointer;
}
h1, h2 {
margin-top: 20px;
text-align: center;
}
#category-list {
text-align: center;
display: flex;
flex-direction: column;
justify-content: flex-start;
background-color: var(--light-grey);
align-self: center;
width: 80%;
margin-top: 15px;
border-radius: 10px;
}
#category-list,
h1,
h2,
label {
color: var(--light-grey);
}
#category-list p {
color: var(--dark-grey);
}
button {
cursor: pointer;
padding: 5px;
width: 100px;
margin: 10px;
color: var(--dark-grey);
background-color: var(--golden-yellow);
background-image: linear-gradient(#fecc4c, #ffac33);
border-color: var(--golden-yellow);
border-width: 3px;
}
button:hover {
background-image: linear-gradient(#ffcc4c, #f89808);
}
section {
margin-top: 60px;
border: 2px solid var(--golden-yellow);
width: fit-content;
border-radius: 10px;
}
Your browser information:
User Agent is: Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Challenge Information:
Build a Bookmark Manager App - Build a Bookmark Manager App
ILM
April 14, 2025, 6:55pm
2
for test 5, test your app with these
localStorage.setItem("bookmarks", 'invalid');
const arrayFromInvalidValue = getBookmarks();
console.log("Expected empty array:");
console.log(arrayFromInvalidValue);
console.log('\ntry 2');
localStorage.setItem("bookmarks", JSON.stringify([{name: "example1", category: "news", notUrl: "example1.com"}]));
const arrayFromInvalidArray = getBookmarks();
console.log("Expected empty array:");
console.log(arrayFromInvalidArray);
ILM
April 14, 2025, 7:01pm
3
for the deletion of the bookmark, don’t close the category once the bookmark is deleted, that is causing some issues with the tests
Ok, that solved test 5, but what about test 23?
Current Javascript:
function getBookmarks() {
const bookmarks = localStorage.getItem('bookmarks');
if (!bookmarks) return [];
try {
const parsedBookmarks = JSON.parse(bookmarks);
if (Array.isArray(parsedBookmarks)) {
return parsedBookmarks.filter(b =>
typeof b.name === 'string' &&
typeof b.url === 'string' &&
typeof b.category === 'string'
);
} else {
return [];
}
} catch (e) {
return [];
}
}
function displayOrCloseForm() {
const mainSection = document.getElementById('main-section');
const formSection = document.getElementById('form-section');
mainSection.classList.toggle('hidden');
formSection.classList.toggle('hidden');
}
function displayOrHideCategory() {
const mainSection = document.getElementById('main-section');
const bookmarkListSection = document.getElementById('bookmark-list-section');
mainSection.classList.toggle('hidden');
bookmarkListSection.classList.toggle('hidden');
}
document.getElementById('add-bookmark-button').addEventListener('click', () => {
const categoryName = document.querySelector('#category-dropdown option:checked').text;
document.querySelector('.category-name').innerText = categoryName;
displayOrCloseForm();
});
document.getElementById('close-form-button').addEventListener('click', displayOrCloseForm);
document.getElementById('add-bookmark-button-form').addEventListener('click', () => {
const name = document.getElementById('name').value;
const url = document.getElementById('url').value;
const category = document.getElementById('category-dropdown').value;
const bookmarks = getBookmarks();
bookmarks.push({ name, url, category });
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
document.getElementById('name').value = '';
document.getElementById('url').value = '';
displayOrCloseForm();
});
document.getElementById('view-category-button').addEventListener('click', () => {
const selectedCategory = document.getElementById('category-dropdown').value;
document.querySelector('.category-name').innerText = selectedCategory;
const bookmarks = getBookmarks();
const categoryList = document.getElementById('category-list');
categoryList.innerHTML = '';
const filteredBookmarks = bookmarks.filter(b => b.category === selectedCategory);
if (filteredBookmarks.length === 0) {
categoryList.innerHTML = '<p>No Bookmarks Found</p>';
} else {
filteredBookmarks.forEach(bookmark => {
const radioId = bookmark.name.replace(/\s+/g, '-');
categoryList.innerHTML += `
<div>
<input type="radio" id="${radioId}" name="bookmark" value="${bookmark.name}">
<label for="${radioId}">
<a href="${bookmark.url}" target="_blank">${bookmark.name}</a>
</label>
</div>
`;
});
}
displayOrHideCategory();
});
document.getElementById('close-list-button').addEventListener('click', displayOrHideCategory);
document.getElementById('delete-bookmark-button').addEventListener('click', () => {
const bookmarks = getBookmarks();
const selectedBookmarkName = document.querySelector('input[name="bookmark"]:checked');
if (selectedBookmarkName) {
const updatedBookmarks = bookmarks.filter(b => b.name !== selectedBookmarkName.value);
localStorage.setItem('bookmarks', JSON.stringify(updatedBookmarks));
displayOrHideCategory();
}
});
ILM
April 14, 2025, 7:12pm
5
const viewCategoryButtonTest = document.getElementById("view-category-button");
const deleteBookmarkButtonTest = document.getElementById("delete-bookmark-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
localStorage.setItem("bookmarks", JSON.stringify([{name: "example1", category: "news", url: "example1.com"}, {name: "example2", category: "entertainment", url: "example2.com"}, {name: "example3", category: "work", url: "example3.com"}, {name: "example4", category: "news", url: "example4.com"}]));
categoryDropdownTest.value = "news";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const firstRadioButton = document.querySelector('#category-list input[type="radio"]');
firstRadioButton.checked = true;
deleteBookmarkButtonTest.dispatchEvent(new Event("click"));
let bookmarksDisplayed = document.querySelectorAll('#category-list input[type="radio"]');
let bookmarkLabelsDisplayed = document.querySelectorAll('#category-list label');
console.log("actual:",bookmarksDisplayed.length, "expected:", 1);
there is one more bookmarksDisplayed
than there should be, this is not the whole test for the bookmark deletion but it’s where it break
doing the things by the hand the bookmarks go away, but the requirement is to still be on that same category of bookmarks, I think the issue may be there (try to delete a bookmark in the sample app for comparison)
Okay, so I believe got the bug, but the test itself won’t pass.
Current Javascript:
function getBookmarks() {
const bookmarks = localStorage.getItem('bookmarks');
if (!bookmarks) return [];
try {
const parsedBookmarks = JSON.parse(bookmarks);
if (Array.isArray(parsedBookmarks)) {
return parsedBookmarks.filter(b =>
typeof b.name === 'string' &&
typeof b.url === 'string' &&
typeof b.category === 'string'
);
} else {
return [];
}
} catch (e) {
return [];
}
}
function displayOrCloseForm() {
const mainSection = document.getElementById('main-section');
const formSection = document.getElementById('form-section');
mainSection.classList.toggle('hidden');
formSection.classList.toggle('hidden');
}
function displayOrHideCategory() {
const mainSection = document.getElementById('main-section');
const bookmarkListSection = document.getElementById('bookmark-list-section');
mainSection.classList.toggle('hidden');
bookmarkListSection.classList.toggle('hidden');
}
document.getElementById('add-bookmark-button').addEventListener('click', () => {
const categoryName = document.querySelector('#category-dropdown option:checked').text;
document.querySelector('.category-name').innerText = categoryName;
displayOrCloseForm();
});
document.getElementById('close-form-button').addEventListener('click', displayOrCloseForm);
document.getElementById('add-bookmark-button-form').addEventListener('click', () => {
const name = document.getElementById('name').value;
const url = document.getElementById('url').value;
const category = document.getElementById('category-dropdown').value;
const bookmarks = getBookmarks();
bookmarks.push({ name, url, category });
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
document.getElementById('name').value = '';
document.getElementById('url').value = '';
displayOrCloseForm();
});
document.getElementById('view-category-button').addEventListener('click', () => {
const selectedCategory = document.getElementById('category-dropdown').value;
document.querySelector('.category-name').innerText = selectedCategory;
const bookmarks = getBookmarks();
const categoryList = document.getElementById('category-list');
categoryList.innerHTML = '';
const filteredBookmarks = bookmarks.filter(b => b.category === selectedCategory);
if (filteredBookmarks.length === 0) {
categoryList.innerHTML = '<p>No Bookmarks Found</p>';
} else {
filteredBookmarks.forEach(bookmark => {
const radioId = bookmark.name.replace(/\s+/g, '-');
categoryList.innerHTML += `
<div>
<input type="radio" id="${radioId}" name="bookmark" value="${bookmark.name}">
<label for="${radioId}">
<a href="${bookmark.url}" target="_blank">${bookmark.name}</a>
</label>
</div>
`;
});
}
displayOrHideCategory();
});
document.getElementById('close-list-button').addEventListener('click', displayOrHideCategory);
document.getElementById('delete-bookmark-button').addEventListener('click', () => {
const bookmarks = getBookmarks();
const selectedBookmarkName = document.querySelector('input[name="bookmark"]:checked');
if (selectedBookmarkName) {
const updatedBookmarks = bookmarks.filter(b => b.name !== selectedBookmarkName.value);
localStorage.setItem('bookmarks', JSON.stringify(updatedBookmarks));
const selectedCategory = document.getElementById('category-dropdown').value;
const filteredBookmarks = updatedBookmarks.filter(b => b.category === selectedCategory);
const categoryList = document.getElementById('category-list');
categoryList.innerHTML = '';
if (filteredBookmarks.length === 0) {
categoryList.innerHTML = '<p>No Bookmarks Found</p>';
} else {
filteredBookmarks.forEach(bookmark => {
const radioId = bookmark.name.replace(/\s+/g, '-');
categoryList.innerHTML += `
<div>
<input type="radio" id="${radioId}" name="bookmark" value="${bookmark.name}">
<label for="${radioId}">
<a href="${bookmark.url}" target="_blank">${bookmark.name}</a>
</label>
</div>
`;
});
}
}
});
ILM
April 14, 2025, 7:23pm
7
your last challenge is to set this
localStorage.setItem("bookmarks", JSON.stringify([{name: "duplicated-name", category: "news", url: "example1.com"}, {name: "duplicated-name", category: "entertainment", url: "example2.com"}]))
delete one bookmark without deleting the other
I’ve been working on it for a while now, and I don’t think I have gotten anywhere. I’ve been questioning if I have the code in the correct spot.
document.getElementById('delete-bookmark-button').addEventListener('click', () => {
const bookmarks = getBookmarks();
const selectedBookmarkName = document.querySelector('input[name="bookmark"]:checked');
if (selectedBookmarkName) {
const updatedBookmarks = bookmarks.filter(b => b.name !== selectedBookmarkName.value);
localStorage.setItem("bookmarks", JSON.stringify([
{name: "duplicated-name", category: "news", url: "example1.com"},
{name: "duplicated-name", category: "entertainment", url: "example2.com"}
]));
const selectedCategory = document.getElementById('category-dropdown').value;
const filteredBookmarks = updatedBookmarks.filter(b => b.category === selectedCategory);
const categoryList = document.getElementById('category-list');
categoryList.innerHTML = '';
if (filteredBookmarks.length === 0) {
categoryList.innerHTML = '<p>No Bookmarks Found</p>';
} else {
filteredBookmarks.forEach(bookmark => {
const radioId = bookmark.name.replace(/\s+/g, '-');
categoryList.innerHTML += `
<div>
<input type="radio" id="${radioId}" name="bookmark" value="${bookmark.name}">
<label for="${radioId}">
<a href="${bookmark.url}" target="_blank">${bookmark.name}</a>
</label>
</div>
`;
});
}
}
});
the middle one is where I put the code
ILM
April 14, 2025, 7:58pm
9
you should put any code used for testing after your code, including this snipped:
localStorage.setItem("bookmarks", JSON.stringify([{name: "duplicated-name", category: "news", url: "example1.com"}, {name: "duplicated-name", category: "entertainment", url: "example2.com"}]))
then to manually test, go to one of the two categories (News or Entertainment), delete the bookmark there, then go to the other category and verify if the other bookmark is still there
Okay, so my code works now, but the final test still doesn’t pass.
Current Javascript:
function getBookmarks() {
const bookmarks = localStorage.getItem('bookmarks');
if (!bookmarks) return [];
try {
const parsedBookmarks = JSON.parse(bookmarks);
if (Array.isArray(parsedBookmarks)) {
return parsedBookmarks.filter(b =>
typeof b.name === 'string' &&
typeof b.url === 'string' &&
typeof b.category === 'string'
);
} else {
return [];
}
} catch (e) {
return [];
}
}
function displayOrCloseForm() {
const mainSection = document.getElementById('main-section');
const formSection = document.getElementById('form-section');
mainSection.classList.toggle('hidden');
formSection.classList.toggle('hidden');
}
function displayOrHideCategory() {
const mainSection = document.getElementById('main-section');
const bookmarkListSection = document.getElementById('bookmark-list-section');
mainSection.classList.toggle('hidden');
bookmarkListSection.classList.toggle('hidden');
}
document.getElementById('add-bookmark-button').addEventListener('click', () => {
const categoryName = document.querySelector('#category-dropdown option:checked').text;
document.querySelector('.category-name').innerText = categoryName;
displayOrCloseForm();
});
document.getElementById('close-form-button').addEventListener('click', displayOrCloseForm);
document.getElementById('add-bookmark-button-form').addEventListener('click', () => {
const name = document.getElementById('name').value;
const url = document.getElementById('url').value;
const category = document.getElementById('category-dropdown').value;
const bookmarks = getBookmarks();
bookmarks.push({ name, url, category });
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
document.getElementById('name').value = '';
document.getElementById('url').value = '';
displayOrCloseForm();
});
document.getElementById('view-category-button').addEventListener('click', () => {
const selectedCategory = document.getElementById('category-dropdown').value;
document.querySelector('.category-name').innerText = selectedCategory;
const bookmarks = getBookmarks();
const categoryList = document.getElementById('category-list');
categoryList.innerHTML = '';
const filteredBookmarks = bookmarks.filter(b => b.category === selectedCategory);
if (filteredBookmarks.length === 0) {
categoryList.innerHTML = '<p>No Bookmarks Found</p>';
} else {
filteredBookmarks.forEach(bookmark => {
const radioId = bookmark.name.replace(/\s+/g, '-');
categoryList.innerHTML += `
<div>
<input type="radio" id="${radioId}" name="bookmark" value="${bookmark.name}">
<label for="${radioId}">
<a href="${bookmark.url}" target="_blank">${bookmark.name}</a>
</label>
</div>
`;
});
}
displayOrHideCategory();
});
document.getElementById('close-list-button').addEventListener('click', displayOrHideCategory);
document.getElementById('delete-bookmark-button').addEventListener('click', () => {
const bookmarks = getBookmarks();
const selectedBookmarkName = document.querySelector('input[name="bookmark"]:checked');
if (selectedBookmarkName) {
const updatedBookmarks = bookmarks.filter(b => b.name !== selectedBookmarkName.value);
localStorage.setItem('bookmarks', JSON.stringify(updatedBookmarks));
const selectedCategory = document.getElementById('category-dropdown').value;
const filteredBookmarks = updatedBookmarks.filter(b => b.category === selectedCategory);
const categoryList = document.getElementById('category-list');
categoryList.innerHTML = '';
if (filteredBookmarks.length === 0) {
categoryList.innerHTML = '<p>No Bookmarks Found</p>';
} else {
filteredBookmarks.forEach(bookmark => {
const radioId = bookmark.name.replace(/\s+/g, '-');
categoryList.innerHTML += `
<div>
<input type="radio" id="${radioId}" name="bookmark" value="${bookmark.name}">
<label for="${radioId}">
<a href="${bookmark.url}" target="_blank">${bookmark.name}</a>
</label>
</div>
`;
});
}
}
});
localStorage.setItem("bookmarks", JSON.stringify([{name: "duplicated-name", category: "news", url: "example1.com"}, {name: "duplicated-name", category: "entertainment", url: "example2.com"}]))
I just had to add the snippet to the bottom to make the code work.
ILM
April 14, 2025, 8:06pm
12
are you sure it works? because if I go to News, delete the bookmark, and the go to Entertainment, there is no bookmark there either
you are still deleting both at once, it doesn’t work
That’s… strange. I deleted the bookmark in News, went to Entertainment, and it said no bookmarks were there. I thought it worked, but I’m assuming I was just seeing things.
I’ve been checking for bugs, but I don’t see any existing bugs in my code. I’ve also been working on the code, but nothing I do seems to work. It either has no effect or makes a lot of passes stop passing.
I finally passed it, and now my brain is exhausted. Thank you for your help, @ILM !