curriculum/challenges/english/blocks/lab-bookmark-manager-app/66def5467aee701733aaf8cc.md
For this lab, all the HTML and CSS has been provided to you. You will use JavaScript to complete the Bookmark Manager app so that it can store a collection of bookmarks in the local storage and read data from it.
Objective: Fulfill the user stories below and get all the tests to pass to complete the lab.
User Stories:
getBookmarks function that returns the bookmarks array stored in the local storage. If the bookmarks key has not been set yet, or it doesn't contain a valid array with bookmarks, the getBookmarks function should return an empty array.bookmarks key stored in the local storage should be an array of bookmark objects. Each bookmark object should have three keys: name, category, and url.displayOrCloseForm that toggles the hidden class on #main-section and #form-section.#add-bookmark-button, you should update the inner text of .category-name to be the value of the selected option from #category-dropdown and call displayOrCloseForm to display the form section and hide the main section.#close-form-button, you should run your function to hide the form section and display the main section.#add-bookmark-button-form, you should update the bookmarks key stored in the local storage by adding a bookmark object to the end of the array. The object should have name set to the value of the #name input, category set to the value of the selected option from the category dropdown, and url set to the value of the #url input.bookmarks key is updated, you should reset the value of #name and #url to an empty string before running your function to hide the form section and show the main section.displayOrHideCategory that toggles the hidden class on #main-section and #bookmark-list-section.#view-category-button, you should update the inner text of .category-name to be the value of the selected option from #category-dropdown, modify the inner HTML of #category-list according to the user stories below, and call the displayOrHideCategory function.#category-list to a p element with the text No Bookmarks Found.#category-list. Give each radio button an id and value set to the bookmark name, and a name that's the same for all the buttons.href attribute set to the bookmark URL.#close-list-button, you should run your function to hide the #bookmark-list-section and display the main section.#delete-bookmark-button, you should delete the bookmark corresponding to the selected radio button and appropriate category from the local storage and update the displayed bookmark list.const getHidden = (notMain) => {
const mainSection = document.querySelector("#main-section");
const formSection = document.querySelector("#form-section");
const bookmarkListSection = document.querySelector("#bookmark-list-section");
if (notMain === "form") {
if (mainSection.classList.contains("hidden") && !formSection.classList.contains("hidden")) {
return "main"
} else if (!mainSection.classList.contains("hidden") && formSection.classList.contains("hidden")) {
return notMain;
}
} else if (notMain === "bookmark list") {
if (mainSection.classList.contains("hidden") && !bookmarkListSection.classList.contains("hidden")) {
return "main"
} else if (!mainSection.classList.contains("hidden") && bookmarkListSection.classList.contains("hidden")) {
return notMain;
}
}
}
const originalLocalStorage = JSON.parse(localStorage.getItem("bookmarks")) || [];
const temp = originalLocalStorage;
function resetLocalStorage() {
localStorage.setItem("bookmarks", JSON.stringify(temp));
}
function setLocalStorage() {
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"}]));
}
function clearCategoryList() {
const categoryList = document.getElementById("category-list");
categoryList.innerHTML = "";
}
You should have a getBookmarks function.
assert.isFunction(getBookmarks);
Your getBookmarks function should return an array.
assert.isArray(getBookmarks());
Your getBookmarks function should return the bookmarks key from localStorage.
try {
setLocalStorage()
const testArr = getBookmarks();
const expected = [{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"}];
assert.deepEqual(testArr, expected);
} finally {
resetLocalStorage();
}
When the bookmarks key is not set in localStorage or is an empty array, the getBookmarks function should return an empty array.
try {
localStorage.setItem("bookmarks", JSON.stringify([]));
assert.isEmpty(getBookmarks());
localStorage.removeItem("bookmarks");
assert.isEmpty(getBookmarks());
} finally {
resetLocalStorage();
}
When the bookmarks key in the localStorage does not contain a valid array of bookmark objects, the getBookmarks function should return an empty array.
try {
localStorage.setItem("bookmarks", 'invalid');
const arrayFromInvalidValue = getBookmarks();
assert.isArray(arrayFromInvalidValue);
assert.isEmpty(arrayFromInvalidValue);
localStorage.setItem("bookmarks", JSON.stringify([{name: "example1", category: "news", notUrl: "example1.com"}]));
const arrayFromInvalidArray = getBookmarks();
assert.isArray(arrayFromInvalidArray)
assert.isEmpty(arrayFromInvalidArray)
} finally {
resetLocalStorage();
}
You should have a function named displayOrCloseForm.
assert.isFunction(displayOrCloseForm);
Your displayOrCloseForm function should toggle the hidden class on #main-section and #form-section.
const hidden = getHidden("form");
displayOrCloseForm();
const hiddenAfterCall = getHidden("form");
assert.isDefined(hidden, hiddenAfterCall);
assert.notEqual(hidden, hiddenAfterCall);
When you click #add-bookmark-button, you should update the inner text of .category-name to be the value of the selected option from #category-dropdown.
const addBookMarkButtonTest = document.getElementById("add-bookmark-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
addBookMarkButtonTest.dispatchEvent(new Event("click"));
const categoryName = document.querySelector(".category-name").innerText.trim();
assert.strictEqual(categoryName.toLowerCase(), categoryDropdownTest.value.toLowerCase());
When you click #add-bookmark-button, you should call displayOrCloseForm to display the form section and hide the main section.
const addBookMarkButtonTest = document.getElementById("add-bookmark-button");
assert.strictEqual(getHidden("form"), "form");
addBookMarkButtonTest.dispatchEvent(new Event("click"));
assert.strictEqual(getHidden("form"), "main");
When you click #close-form-button, you should call displayOrCloseForm to hide the form section and display the main section.
const closeFormButtonTest = document.getElementById("close-form-button");
assert.strictEqual(getHidden("form"), "main");
closeFormButtonTest.dispatchEvent(new Event("click"));
assert.strictEqual(getHidden("form"), "form");
When you click #add-bookmark-button-form, you should update the bookmarks key stored in the local storage by adding an object to the end of the array. The added object should have name set to the value of the #name input, category set to the value of the selected option from the category dropdown, and url set to the value of the #url input.
setLocalStorage();
const addBookmarkButtonFormTest = document.getElementById("add-bookmark-button-form");
const categoryDropdownTest = document.getElementById("category-dropdown");
const bookmarkNameTest = document.getElementById("name");
const bookmarkURLTest = document.getElementById("url");
try {
bookmarkNameTest.value = "test example5";
bookmarkURLTest.value = "test example5.com";
const bookmarkObject = {
name: bookmarkNameTest.value,
category: categoryDropdownTest.value,
url: bookmarkURLTest.value
};
const expected = [{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"}, bookmarkObject];
addBookmarkButtonFormTest.dispatchEvent(new Event("click"));
assert.deepEqual(getBookmarks(), expected);
} finally {
bookmarkNameTest.value = "";
bookmarkURLTest.value = "";
resetLocalStorage();
}
When you click #add-bookmark-button-form, you should reset the value of #name and #url to an empty string.
const addBookmarkButtonFormTest = document.getElementById("add-bookmark-button-form");
const bookmarkNameTest = document.getElementById("name");
const bookmarkURLTest = document.getElementById("url");
try {
bookmarkNameTest.value = "test example2";
bookmarkURLTest.value = "test example2.com";
addBookmarkButtonFormTest.dispatchEvent(new Event("click"));
assert.strictEqual(bookmarkNameTest.value, "");
assert.strictEqual(bookmarkURLTest.value, "");
} finally {
resetLocalStorage()
bookmarkNameTest.value = "";
bookmarkURLTest.value = "";
}
When you click #add-bookmark-button-form, you should run displayOrCloseForm to hide the form section and show the main section.
const addBookmarkButtonFormTest = document.getElementById("add-bookmark-button-form");
const addBookMarkButtonTest = document.getElementById("add-bookmark-button");
const bookmarkNameTest = document.getElementById("name");
const bookmarkURLTest = document.getElementById("url");
try {
bookmarkNameTest.value = "test example3";
bookmarkURLTest.value = "test example3.com";
addBookMarkButtonTest.dispatchEvent(new Event("click"));
assert.strictEqual(getHidden("form"), "main");
addBookmarkButtonFormTest.dispatchEvent(new Event("click"));
assert.strictEqual(getHidden("form"), "form");
} finally {
resetLocalStorage()
}
You should have a function named displayOrHideCategory.
assert.isFunction(displayOrHideCategory);
Your displayOrHideCategory function should toggle the hidden class on #main-section and #bookmark-list-section.
const hidden = getHidden("bookmark list");
displayOrHideCategory();
const hiddenAfterCall = getHidden("bookmark list");
assert.isDefined(hidden, hiddenAfterCall)
assert.notEqual(hidden, hiddenAfterCall)
When you click #view-category-button, you should update the inner text of .category-name to be the value of the selected option from #category-dropdown.
const viewCategoryButtonTest = document.getElementById("view-category-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const categoryName = document.querySelector(".category-name").innerText.trim();
assert.strictEqual(categoryName.toLowerCase(), categoryDropdownTest.value.toLowerCase());
When you click #view-category-button, you should add a p element with the text No Bookmarks Found to #category-list's inner HTML if none of the bookmarks in local storage have the selected category.
try {
const viewCategoryButtonTest = document.getElementById("view-category-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
const categoryListSection = document.getElementById("bookmark-list-section");
const mainSection = document.getElementById("main-section");
const categoryList = document.getElementById("category-list");
mainSection.classList.remove("hidden");
categoryListSection.classList.add("hidden");
categoryList.innerHTML = "";
setLocalStorage()
categoryDropdownTest.value = "miscellaneous";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
assert.strictEqual(categoryList.innerHTML,"<p>No Bookmarks Found</p>")
assert.isFalse(categoryListSection.classList.contains("hidden"));
assert.isTrue(mainSection.classList.contains("hidden"));
} finally {
resetLocalStorage()
clearCategoryList()
}
When you click the #view-category-button, you should modify the #category-list element's inner HTML by adding a radio button. The radio button should have the id and value attributes set to the bookmark name for each bookmark in the selected category. Additionally, each radio button should have the same name attribute.
try {
const viewCategoryButtonTest = document.getElementById("view-category-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
setLocalStorage();
categoryDropdownTest.value = "news";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const bookmarksDisplayed = document.querySelectorAll('#category-list input[type="radio"]');
assert.lengthOf(bookmarksDisplayed, 2);
assert.strictEqual(bookmarksDisplayed[0].id, "example1");
assert.strictEqual(bookmarksDisplayed[0].value, "example1");
assert.strictEqual(bookmarksDisplayed[1].id, "example4");
assert.strictEqual(bookmarksDisplayed[1].value, "example4");
assert.isOk(bookmarksDisplayed[0].name)
assert.strictEqual(bookmarksDisplayed[0].name, bookmarksDisplayed[1].name);
} finally {
resetLocalStorage();
}
Each radio button added to #category-list's inner HTML should have a corresponding label containing an anchor element with the bookmark name and the href attribute set to the bookmark URL.
setLocalStorage();
const viewCategoryButtonTest = document.getElementById("view-category-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
try {
categoryDropdownTest.value = "news";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const bookmarkLabelsDisplayed = document.querySelectorAll('#category-list label');
assert.lengthOf(bookmarkLabelsDisplayed, 2);
assert.strictEqual(bookmarkLabelsDisplayed[0].htmlFor, "example1");
assert.strictEqual(bookmarkLabelsDisplayed[1].htmlFor, "example4");
} finally {
resetLocalStorage();
}
Each label element should contain an anchor element with the bookmark name as text, and the href attribute set to the bookmark URL.
setLocalStorage();
const viewCategoryButtonTest = document.getElementById("view-category-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
try {
categoryDropdownTest.value = "news";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const bookmarkAnchorsDisplayed = document.querySelectorAll('#category-list label>a');
assert.lengthOf(bookmarkAnchorsDisplayed, 2);
assert.strictEqual(bookmarkAnchorsDisplayed[0].innerText.trim(), "example1");
assert.isTrue(bookmarkAnchorsDisplayed[0].href.endsWith("example1.com"));
assert.strictEqual(bookmarkAnchorsDisplayed[1].innerText.trim(), "example4");
assert.isTrue(bookmarkAnchorsDisplayed[1].href.endsWith("example4.com"));
} finally {
resetLocalStorage();
}
When you click #close-list-button, you should hide #bookmark-list-section and display the main section.
const viewCategoryButtonTest = document.getElementById("view-category-button");
const closeListButtonTest = document.getElementById("close-list-button");
viewCategoryButtonTest.dispatchEvent(new Event("click"));
assert.strictEqual(getHidden("bookmark list"), "main");
closeListButtonTest.dispatchEvent(new Event("click"));
assert.strictEqual(getHidden("bookmark list"), "bookmark list");
When you click the #close-list-button and then open any category, the #category-list should contain only data relevant for the selected category, without duplicating entries.
setLocalStorage();
const viewCategoryButtonTest = document.getElementById("view-category-button");
const closeListButtonTest = document.getElementById("close-list-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
try {
categoryDropdownTest.value = "miscellaneous";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const categoryList = document.getElementById("category-list").innerHTML;
assert.strictEqual(categoryList, "<p>No Bookmarks Found</p>");
closeListButtonTest.dispatchEvent(new Event("click"));
categoryDropdownTest.value = "news";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const newsBookmarks = document.querySelectorAll('#category-list input[type="radio"]');
assert.lengthOf(newsBookmarks, 2);
assert.strictEqual(newsBookmarks[0].id, "example1");
assert.strictEqual(newsBookmarks[0].value, "example1");
assert.strictEqual(newsBookmarks[1].id, "example4");
assert.strictEqual(newsBookmarks[1].value, "example4");
closeListButtonTest.dispatchEvent(new Event("click"));
categoryDropdownTest.value = "work";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const workBookmarks = document.querySelectorAll('#category-list input[type="radio"]');
assert.lengthOf(workBookmarks, 1);
assert.strictEqual(workBookmarks[0].id, "example3");
assert.strictEqual(workBookmarks[0].value, "example3");
categoryDropdownTest.value = "miscellaneous";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const paragraphs = document.querySelectorAll("#category-list p");
assert.lengthOf(paragraphs, 1);
assert.strictEqual(paragraphs[0].innerText.trim(), "No Bookmarks Found");
} finally {
resetLocalStorage();
clearCategoryList();
}
When you click the #delete-bookmark-button, you should delete the bookmark corresponding to the selected radio button and appropriate category from the local storage and update the displayed bookmark list.
setLocalStorage();
const viewCategoryButtonTest = document.getElementById("view-category-button");
const deleteBookmarkButtonTest = document.getElementById("delete-bookmark-button");
const categoryDropdownTest = document.getElementById("category-dropdown");
try {
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');
assert.lengthOf(bookmarksDisplayed, 1);
assert.strictEqual(bookmarksDisplayed[0].id, "example4");
assert.strictEqual(bookmarksDisplayed[0].value, "example4");
assert.lengthOf(bookmarkLabelsDisplayed, 1);
assert.strictEqual(bookmarkLabelsDisplayed[0].htmlFor, "example4");
const expected = [{name: "example2", category: "entertainment", url: "example2.com"}, {name: "example3", category: "work", url: "example3.com"}, {name: "example4", category: "news", url: "example4.com"}];
assert.deepEqual(getBookmarks(), expected);
localStorage.setItem("bookmarks", JSON.stringify([{name: "duplicated-name", category: "news", url: "example1.com"}, {name: "duplicated-name", category: "entertainment", url: "example2.com"}]));
categoryDropdownTest.value = "entertainment";
viewCategoryButtonTest.dispatchEvent(new Event("click"));
const radioForDuplicate = document.querySelector('#category-list input[type="radio"]');
radioForDuplicate.checked = true;
deleteBookmarkButtonTest.dispatchEvent(new Event("click"));
assert.deepEqual(getBookmarks(), [{name: "duplicated-name", category: "news", url: "example1.com"}])
} finally {
resetLocalStorage();
}
<!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>
: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;
}
const categoryDropdown = document.getElementById("category-dropdown");
const viewCategoryButton = document.getElementById("view-category-button");
const addBookmarkButton = document.getElementById("add-bookmark-button");
const mainSection = document.getElementById("main-section");
const formSection = document.getElementById("form-section");
const bookmarkListSection = document.getElementById("bookmark-list-section");
const categoryHeading = document.querySelectorAll(".category-name");
const closeFormButton = document.getElementById("close-form-button");
const bookmarkName = document.getElementById("name");
const bookmarkURL = document.getElementById("url");
const addBookmarkButtonForm = document.getElementById("add-bookmark-button-form");
const categoryList = document.getElementById("category-list");
const closeListButton = document.getElementById("close-list-button");
const deleteBookmarkButton = document.getElementById("delete-bookmark-button");
const getBookmarks = () => {
try {
const parsed = JSON.parse(localStorage.getItem("bookmarks"));
if (
Array.isArray(parsed) &&
parsed.every(
(item) =>
item.hasOwnProperty("category") &&
item.hasOwnProperty("name") &&
item.hasOwnProperty("url"),
)
) {
return parsed;
}
return [];
} catch {
return [];
}
};
const displayOrCloseForm = () => {
mainSection.classList.toggle("hidden");
formSection.classList.toggle("hidden");
}
addBookmarkButton.addEventListener("click", () => {
categoryHeading[0].innerText = categoryDropdown.value.charAt(0).toUpperCase()
+ categoryDropdown.value.slice(1);
displayOrCloseForm();
});
closeFormButton.addEventListener("click", displayOrCloseForm);
const addBookmark = () => {
const bookmarkObject = {
name: bookmarkName.value,
category: categoryDropdown.value,
url: bookmarkURL.value
};
if (bookmarkName.value.length && bookmarkURL.value.length) {
localStorage.setItem("bookmarks", JSON.stringify(getBookmarks().concat(bookmarkObject)))
bookmarkName.value = "";
bookmarkURL.value = "";
displayOrCloseForm()
} else {
alert("Please, provide valid name and URL.")
}
}
addBookmarkButtonForm.addEventListener("click", addBookmark);
const displayOrHideCategory = () => {
mainSection.classList.toggle("hidden");
bookmarkListSection.classList.toggle("hidden");
}
const fillBookmarkList = () => {
categoryHeading[1].innerText = categoryDropdown.value.charAt(0).toUpperCase()
+ categoryDropdown.value.slice(1);
const bookmarksToDisplay = getBookmarks().filter((i) => i.category === categoryDropdown.value);
if (bookmarksToDisplay.length) {
categoryList.innerHTML = '';
for (const bookmark of bookmarksToDisplay) {
categoryList.innerHTML += `
<div>
<input type="radio" name="bookmarks" id="${bookmark.name}" value="${bookmark.name}">
<label for="${bookmark.name}">
<a href="${bookmark.url}">${bookmark.name}</a>
</label>
</div>`
}
} else {
categoryList.innerHTML = '<p>No Bookmarks Found</p>';
}
}
viewCategoryButton.addEventListener("click", () => {
fillBookmarkList();
displayOrHideCategory();
})
closeListButton.addEventListener("click", displayOrHideCategory)
const deleteBookmark = () => {
const radioBookmarks = document.querySelectorAll('input[type="radio"]');
for (const radioBookmark of radioBookmarks) {
if (radioBookmark.checked) {
const bookmarks = getBookmarks();
const indexToRemove = bookmarks.findIndex(i => i.name == radioBookmark.value && i.category === categoryDropdown.value);
bookmarks.splice(indexToRemove, 1);
localStorage.setItem("bookmarks", JSON.stringify(bookmarks));
return
}
}
}
deleteBookmarkButton.addEventListener("click", () => {
deleteBookmark();
fillBookmarkList();
})
<!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>
: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;
}