JavaScript, how to limit todo list number? - javascript

I was making a to-do list and I couldn't figure out how can I limit the number of creating li. I want to stop it from creating li when it reaches 4 li by not showing it on ul and stop submitting it. This is the one I wrote. If anyone can give me advice or ideas on how to solve this one. Thank you.
const form = document.querySelector('form')
const input = document.querySelector('input')
const memo = document.querySelector('ul')
form.addEventListener('submit', function(e) {
const line = document.ul.child
if (line > 5) {
e.preventDefault()
ToDo()
input.value = ""
}
})
function ToDo() {
if (input.value == '') {
alert('please write')
} else {
const value = input.value
const newList = document.createElement('li')
newList.textContent = value
memo.append(newList)
const deleteBtn = document.createElement('button')
newList.append(' ', ' ', deleteBtn)
deleteBtn.textContent = "DELETE"
console.log(newList)
}
}
memo.addEventListener('click', function(e) {
if (e.target.nodeName === 'BUTTON') {
e.target.closest('LI').remove();
}
})
whole code: here

This lineconst line = document.ul.child would give an error, as it is not valid way to query things from the DOM. Also e.preventDefault() shouldn't be in the if block even if it were correct. This would work:
const form = document.querySelector("form");
const input = document.querySelector("input");
const memo = document.querySelector("ul");
form.addEventListener("submit", function (e) {
e.preventDefault();
const liNumber = document.querySelectorAll("ul li").length;
if (liNumber < 4) {
ToDo();
input.value = "";
} else {
alert("Maximum number reached");
}
});
function ToDo() {
if (input.value == "") {
alert("please write");
} else {
const value = input.value;
const newList = document.createElement("li");
newList.textContent = value;
memo.append(newList);
const deleteBtn = document.createElement("button");
newList.append(" ", " ", deleteBtn);
deleteBtn.textContent = "DELETE";
}
}
memo.addEventListener("click", function (e) {
if (e.target.nodeName === "BUTTON") {
e.target.closest("LI").remove();
}
});
body {
background-image: linear-gradient(
83.2deg,
rgba(150, 93, 233, 1) 10.8%,
rgba(99, 88, 238, 1) 94.3%
);
}
h1 {
text-align: center;
font-size: 50px;
font-weight: 500;
font-family: "Lucida Sans", "Lucida Sans Regular", "Lucida Grande",
"Lucida Sans Unicode", Geneva, Verdana, sans-serif;
color: #fbfbf2;
}
.option {
margin-top: 4rem;
display: flex;
justify-content: center;
align-content: center;
flex-direction: row-reverse;
}
#input {
width: 400px;
height: 60px;
border-radius: 10px;
box-shadow: none;
font-size: 20px;
}
#submit {
margin-right: 5px;
padding: 10px 10px;
border-radius: 10px;
background-color: #5a189a;
color: #fbfbf2;
}
#input,
#submit {
padding: 10px 10px;
border: none;
}
.lists {
background-color: #efd9ce;
height: 400px;
border-radius: 15px;
}
.memo {
padding: 15px;
font-size: 30px;
}
ul li {
margin: 20px;
}
button {
background-color: #5a189a;
border-radius: 15px;
color: #fbfbf2;
font-size: 20px;
}
<form>
<h1>TO DO LIST</h1>
<div class="option">
<input type="text" id="input" placeholder="enter a task" />
<button type="submit" id="submit">SUBMIT</button>
</div>
</form>
<div class="lists">
<ul class="memo"></ul>
</div>

Related

Is there any other way to sort a drag and drop todo list without using the index of the items?

I'm working on a javascript to-do list where you can view all the elements on the list or you can view just the active items or the completed items.
Each of the views has its own array which I sorted out using the index of each element
but when I reorder the list on one of the views, the change is not implemented in the other views.
How do I rectify this?
const dragArea1 = document.querySelector('#task1');
const dragArea2 = document.querySelector('#task2');
const dragArea3 = document.querySelector('#task3');
const addnew = document.querySelector('[name="addnew"]')
const add = document.querySelector('[name="new"]')
const countIt = document.querySelector('#count')
var all = [];
var active = [];
var complete = [];
var lists = document.querySelectorAll('ul');
var views = document.querySelectorAll('.action .views a');
var mobileViews = document.querySelectorAll('#views a');
var list = document.querySelector('.list');
countIt.innerHTML = active.length;
addnew.addEventListener('click', () => {
var newItem
if (addnew.checked == true) {
newItem = {
val: add.value,
checked: false
}
all.push(newItem);
active.push(newItem);
window.setTimeout(() => {
addnew.checked = false;
add.value = '';
}, 300);
displayAll();
count();
}
})
list.addEventListener('click', (ev) => {
if (ev.target.tagName === 'LABEL' || ev.target.tagName === 'P' || ev.target.tagName === 'LI') {
ev.target.classList.toggle('checked');
sortAllList();
if (lists[1].style.display == 'block') {
activeToComplete();
}
if (lists[2].style.display == 'block') {
completeToActive();
}
sortActive();
sortComplete();
}
if (all.length == 0) {
var htmlCode = `<em style="text-align: center; width: 100%; padding: 20px;">add a todo item</em>`;
lists[0].innerHTML = htmlCode;
}
if (active.length == 0) {
var htmlCode = `<em style="text-align: center; width: 100%; padding: 20px;">add a todo item</em>`;
lists[1].innerHTML = htmlCode;
}
if (complete.length == 0) {
var htmlCode = `<em style="text-align: center; width: 100%; padding: 20px;">complete a todo item</em>`;
lists[2].innerHTML = htmlCode;
}
// console.log(ev.target.tagName);
})
function count() {
// to keep count of active items
countIt.innerHTML = active.length;
}
views[0].classList.add('view')
mobileViews[0].classList.add('view')
function displayAll() {
sortActive();
sortComplete();
var htmlCode = "";
if (all.length !== 0) {
for (let i = 0; i < all.length; i++) {
htmlCode += `
<li draggable="true">
<div class="check">
<input type="checkbox" name="listItem" id="item${i}">
<label for="item${i}"></label>
</div>
<p class="itemdesc">${all[i].val}</p>
<span onclick="del(${i})">╳</span>
</li>
`
}
lists[0].innerHTML = htmlCode;
}
lists[0].style.display = 'block';
lists[1].style.display = 'none';
lists[2].style.display = 'none';
views[0].classList.add('view')
views[1].classList.remove('view')
views[2].classList.remove('view')
mobileViews[0].classList.add('view')
mobileViews[1].classList.remove('view')
mobileViews[2].classList.remove('view')
count()
keepChecked();
}
function sortActive() {
// to add active items to the active array
var fit
fit = all.filter(el => el.checked == false)
active = fit
count();
}
function sortComplete() {
//to add completed items to the complete array
var com
com = all.filter(el => el.checked == true)
complete = com
// console.log('complete', complete);
}
function sortAllList() {
// to sort the items into active and completed
const items = document.querySelectorAll('#task1 li');
for (let i = 0; i < all.length; i++) {
if (items[i].classList.contains('checked') == true) {
all[i].checked = true
} else {
all[i].checked = false
}
}
}
function activeToComplete() {
let newA
const items = document.querySelectorAll('#task2 li')
for (let i = 0; i < active.length; i++) {
if (items[i].classList.contains('checked') == true) {
active[i].checked = true;
// active.splice(i,1);
// console.log(active.splice());
} else {
active[i].checked = false
}
}
newA = active.filter(el => el.checked !== true)
console.log(newA);
active = newA;
}
function keepChecked() {
// to keep the completed items checked afetr changing views
const allItems = document.querySelectorAll('#task1 li');
for (let i = 0; i < all.length; i++) {
if (all[i].checked == true) {
allItems[i].classList.add('checked')
}
}
}
function completeToActive() {
const items = document.querySelectorAll('#task3 li')
for (let i = 0; i < complete.length; i++) {
if (items[i].classList.contains('checked') == true) {
complete[i].checked = true;
} else {
complete[i].checked = false
complete.splice(i, 1);
console.log(complete.splice());
}
}
}
function displayActive() {
sortAllList();
sortActive();
var htmlCode = "";
if (active.length !== 0) {
for (let i = 0; i < active.length; i++) {
htmlCode += `
<li draggable="true">
<div class="check">
<input type="checkbox" name="listItem" id="item${i}">
<label for="item${i}"></label>
</div>
<p class="itemdesc">${active[i].val}</p>
<span onclick="del(${i})">╳</span>
</li>
`
}
lists[1].innerHTML = htmlCode;
}
lists[1].style.display = 'block';
lists[0].style.display = 'none';
lists[2].style.display = 'none';
views[1].classList.add('view')
views[0].classList.remove('view')
views[2].classList.remove('view')
mobileViews[1].classList.add('view')
mobileViews[0].classList.remove('view')
mobileViews[2].classList.remove('view')
count()
}
function displayCompleted() {
let unique = [...new Set(complete)]
// console.log(unique[0].val);
var htmlCode = "";
if (unique.length !== 0) {
for (let i = 0; i < unique.length; i++) {
htmlCode += `
<li draggable="true" class="checked">
<div class="check">
<input type="checkbox" name="listItem" id="item${i}">
<label for="item${i}"></label>
</div>
<p class="itemdesc">${unique[i].val}</p>
<span onclick="del(${i})">╳</span>
</li>
`
}
lists[2].innerHTML = htmlCode;
}
lists[2].style.display = 'block';
lists[1].style.display = 'none';
lists[0].style.display = 'none';
views[2].classList.add('view')
views[0].classList.remove('view')
views[1].classList.remove('view')
mobileViews[2].classList.add('view')
mobileViews[1].classList.remove('view')
mobileViews[0].classList.remove('view')
count()
}
function clearComplete() {
var htmlCode = `<em style="text-align: center; width: 100%; padding: 20px;">complete a todo item</em>`;
complete = [];
lists[2].innerHTML = htmlCode;
}
function del(theIndex) {
let i = theIndex;
if (lists[0].style.display == 'block') {
all.splice(i, 1);
displayAll();
}
if (lists[1].style.display == 'block') {
active.splice(i, 1);
let removeFromAll = all.find(el => {
el == active.splice()
})
all.splice(removeFromAll, 1);
displayActive();
}
if (lists[2].style.display == 'block') {
complete.splice(i, 1);
let removeFromAll = all.find(el => {
el == complete.splice()
})
all.splice(removeFromAll, 1);
displayCompleted();
}
sortActive();
sortComplete();
}
new Sortable(dragArea1, {
animation: 350
})
new Sortable(dragArea2, {
animation: 350
})
new Sortable(dragArea3, {
animation: 350
})
:root {
--blue: hsl(220, 98%, 61%);
/* vd -> Very Drak */
--vdblue: hsl(235, 21%, 11%);
--vdDesaturatedblue: hsl(235, 24%, 19%);
--lightgrayblue: hsl(234, 39%, 85%);
--lightgrayblueh: hsl(236, 33%, 92%);
--darkgrayblue: hsl(234, 11%, 52%);
--vdGrayishblueh: hsl(233, 14%, 35%);
--vdGrayishblue: hsl(237, 14%, 26%);
--checkbg: linear-gradient(rgba(87, 221, 255, .7), rgba(192, 88, 243, .7));
--font: 'Josefin Sans', sans-serif;
font-size: 18px;
}
* {
padding: 0;
margin: 0;
font-family: var(--font);
/* font-weight: 700; */
}
*,
*::after,
*::before {
box-sizing: border-box;
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover,
textarea:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
border: none;
-webkit-text-fill-color: white;
background-color: transparent !important;
-webkit-box-shadow: 0 0 0px 1000px #00000000 inset;
transition: background-color 5000s ease-in-out 0s;
}
input:focus, input:active, input:visited, textarea:focus, textarea:active, textarea:visited{
background-color: transparent;
border: none;
outline: none;
}
a, em, span{
display: inline-block;
cursor: pointer;
}
a{
text-decoration: none;
display: inline-block;
}
header, main, footer{
width: 100%;
max-width: 30rem;
padding: 10px;
}
main {
display: flex;
flex-direction: column;
gap: 30px;
align-items: center;
}
main #new,
li {
display: flex;
align-items: center;
gap: 20px;
padding: 1rem;
width: 100%;
}
main section,
main #views {
width: 100%;
}
main section,
main #new,
main #views {
border-radius: 5px;
}
main .list {
min-height: 2.5rem;
max-height: 20rem;
/* height: 10rem; */
position: relative;
overflow-y: auto;
}
main .list ul {
/* position: absolute; */
/* top: 20px; */
width: 100%;
display: none;
}
main .list ul:nth-child(1) {
display: block;
}
main #new input[name="new"] {
padding: 10px;
height: inherit;
}
input {
background-color: transparent;
width: calc(100% - 70px);
border: none;
font-size: 1rem;
}
li {
justify-content: flex-start;
}
li .check {
position: relative;
}
main #new .check input,
li .check input {
display: none;
}
main #new .check label,
li .check label {
width: 30px;
height: 30px;
border-radius: 30px;
display: inline-block;
}
main #new .check input:checked~label,
li.checked .check label {
background-image: var(--checkbg), url(images/icon-check.svg);
background-position: center center;
background-repeat: no-repeat;
}
li p {
width: 85%;
}
li.checked label {
background-color: #66666696;
}
li.checked p {
text-decoration: line-through;
}
li span {
/* justify-self: flex-end; */
display: none;
}
li:hover span {
display: flex;
}
main .action {
display: flex;
justify-content: space-between;
/* gap: 2rem; */
padding: 1.1rem;
font-size: .8rem;
}
.views a,
#views a {
font-weight: 700;
}
.action a.view {
color: var(--blue);
}
main #views {
padding: .8rem;
text-align: center;
font-size: .8rem;
display: none;
}
#views a.view {
color: var(--blue);
}
main #views+p {
font-size: .7rem;
}
li,
em {
border-bottom: 1px solid var(--darkgrayblue);
}
li,
li p,
main .action a:hover {
color: var(--lightgrayblue);
}
a,
em,
li.checked p,
p,
span,
input,
li span {
color: var(--darkgrayblue);
}
header img {
content: url("images/icon-sun.svg");
}
main #new {
background-color: var(--vdDesaturatedblue);
}
main #new .check label,
li .check label {
border: 1px solid var(--vdGrayishblue);
}
main #new .check label:hover,
li .check label:hover {
border: 1px solid var(--vdGrayishblue);
}
main section,
main #views {
background-color: var(--vdDesaturatedblue);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js"></script>
<main role="main">
<div id="new">
<div class="check">
<input type="checkbox" name="addnew" id="addnew">
<label for="addnew"></label>
</div>
<input type="text" name="new" placeholder="Create a new todo...">
</div>
<section>
<div class="list">
<ul id="task1">
<em style="text-align: center; width: 100%; padding: 20px;">add a todo item</em>
</ul>
<ul id="task2">
<em style="text-align: center; width: 100%; padding: 20px;">add a todo item</em>
</ul>
<ul id="task3">
<em draggable="true" style="text-align: center; width: 100%; padding: 20px;">complete a todo item</em>
</ul>
</div>
<div class="action">
<p>
<span id="count"></span> items left
</p>
<div class="views">
All
Active
Completed
</div>
Clear Completed
</div>
</section>
<div id="views">
All
Active
Completed
</div>
<p>Drag and drop to reorder list</p>
</main>

Javascript todo list app. I can't delete the last remaining li and clear all button is not working, only local storage gets deleted

I encountered 2 problems regarding my todo app. I am just coding along from one of the Youtube tutorials to improve my Javascript knowledge. I cannot delete the last remaining li in my todo list but the local storage shows it is already deleted. Same as my clear all button, the local storage is already been deleted but my li's are still showing. Aside from that, after I click clear all button, I cannot delete the li's one by one even if it's still showing(my guess is the local storage is already empty and there is no more data to be deleted). Thank you for the future responses!
const inputBox = document.querySelector('.input-container input')
const addBtn = document.querySelector('.input-container button')
const todo = document.querySelector('.todo-list')
const deleteAllBtn = document.querySelector('.footer button')
// input button
inputBox.onkeyup = () => {
let userData= inputBox.value;
if (userData.trim() != 0 ) {
addBtn.classList.add('active')
} else {
addBtn.classList.remove('active');
}
}
showTask();
//adding it to local storage
addBtn.onclick = () => {
let userData = inputBox.value;
let getLocalStorage = localStorage.getItem("New Todo")
if (getLocalStorage == null) {
listArr = [];
} else {
listArr = JSON.parse(getLocalStorage);
}
listArr.push(userData);
localStorage.setItem("New Todo", JSON.stringify(listArr));
showTask();
addBtn.classList.remove('active');
}
//add task
function showTask() {
let getLocalStorage = localStorage.getItem("New Todo")
if (getLocalStorage == null) {
listArr = [];
} else {
listArr = JSON.parse(getLocalStorage);
}
const pendingNumb = document.querySelector('.pending');
pendingNumb.textContent= listArr.length;
let newLiTag = '';
listArr.forEach((element, index) => {
newLiTag += `<li> ${element} <span onclick="deleteTask(${index})";><i class="fas fa-trash-alt"></i></span></li>
`;
todo.innerHTML = newLiTag;
inputBox.value = '';
});
}
//delete task
function deleteTask(index) {
let getLocalStorage = localStorage.getItem("New Todo");
listArr = JSON.parse(getLocalStorage);
listArr.splice(index, 1);
localStorage.setItem("New Todo", JSON.stringify(listArr));
showTask();
}
//delete all task
deleteAllBtn.onclick = () => {
listArr = [];
localStorage.setItem("New Todo", JSON.stringify(listArr));
showTask();
}
.todo-list {
margin: 10px 0;
width: 360px;
height: 260px;
max-height: 250px;
overflow-y: auto;
}
.todo-list li {
position: relative;
list-style-type: none;
background: #f2f2f2;
margin: 5px 0;
display: flex;
justify-content: space-between;
padding: 5px 5px;
overflow: hidden;
}
.todo-list li span {
position: absolute;
right: -30px;
top: 0;
background: #d00000;
color: #fff;
width: 35px;
height: 35px;
padding-top: 5px;
text-align: center;
transition: all 0.3s ease;
cursor: pointer;
}
.todo-list li:hover span {
right: 0;
}
.footer {
font-size: 17px;
font-weight: bold;
margin: 0 10px;
}
.footer span {
margin: 0 10px;
}
.footer button {
height: 2.5rem;
width: 5rem;
font-size: 1rem;
color: #fff;
background: #d00000;
border: none;
cursor: pointer;
}
<div class="container">
<h1>TODO list</h1>
<div class="input-container">
<input type="text" class="input" placeholder="Input Text Here">
<button><i class="fas fa-plus"></i></button>
</div>
<ul class="todo-list">
</ul>
<div class="footer">
<span>You have<span class="pending">0</span>pending task left</span>
<button>Clear All</button>
</div>
you should update todo element outside of forEach
function showTask() {
let getLocalStorage = localStorage.getItem("New Todo")
if (getLocalStorage == null) {
listArr = [];
} else {
listArr = JSON.parse(getLocalStorage);
}
const pendingNumb = document.querySelector('.pending');
pendingNumb.textContent = listArr.length;
let newLiTag = '';
listArr.forEach((element, index) => {
newLiTag += `<li> ${element} <span onclick="deleteTask(${index})";><i class="fas fa-trash-alt"></i></span></li>
`;
});
//move it here
todo.innerHTML = newLiTag;
inputBox.value = '';
}

Function removes items from localStorage only if run manually

I'm looking for advice/tips on how to fix a function that is supposed to remove items from localStorage. I'm following a tutorial by John Smilga that I found on Youtube. Although I've modeled my code on his, apparently, I have missed something.
This function works perfectly well if I run it manually from the console and pass in the id of the item that I want to remove from localStorage.
function removeFromLocalStorage(id) {
console.log(id);
let storageItems = getLocalStorage();
console.log(storageItems);
storageItems = storageItems.filter(function(singleItem) {
if (singleItem.id !== id) {
return singleItem;
}
})
console.log(storageItems);
localStorage.setItem("list", JSON.stringify(storageItems));
}
However, when this function is triggered by the deleteItem() function, it refuses to remove the item from localStorage. It still works, there are a bunch of console.logs in it that track its execution, and I can check that it receives the correct item id as the argument, but for some reason it doesn't filter out the item that needs to be removed. I am completely lost and have no idea how to identify the problem. I can't debug it with console.logs as I usually do. I will be very grateful if you help me find the problem. Any advice will be appreciated.
In case the entire code is needed, please find it below.
const form = document.querySelector(".app__form");
const alert = document.querySelector(".app__alert");
const input = document.querySelector(".app__input");
const submitBtn = document.querySelector(".app__submit-btn");
const itemsContainer = document.querySelector(".app__items-container");
const itemsList = document.querySelector(".app__items-list");
const clearBtn = document.querySelector(".app__clear-btn");
let editElement;
let editFlag = false;
let editId = "";
form.addEventListener("submit", addItem);
clearBtn.addEventListener("click", clearItems);
function addItem(e) {
e.preventDefault();
const id = Math.floor(Math.random() * 9999999999);
if (input.value && !editFlag) {
const item = document.createElement("div");
item.classList.add("app__item");
const attr = document.createAttribute("data-id");
attr.value = id;
item.setAttributeNode(attr);
item.innerHTML = `<p class='app__item-text'>${input.value}</p>
<div class='app__item-btn-cont'>
<button class='app__item-btn app__item-btn--edit'>edit</button>
<button class='app__item-btn app__item-btn--delete'>delete</button>
</div>`
const editBtn = item.querySelector(".app__item-btn--edit");
const deleteBtn = item.querySelector(".app__item-btn--delete");
editBtn.addEventListener("click", editItem);
deleteBtn.addEventListener("click", deleteItem);
itemsList.appendChild(item);
displayAlert("item added", "success");
addToLocalStorage(id, input.value);
setBackToDefault();
itemsContainer.classList.add("app__items-container--visible");
} else if (input.value && editFlag) {
editElement.textContent = input.value;
// edit local storage
editLocalStorage(editId, input.value);
setBackToDefault();
displayAlert("item edited", "success");
} else {
displayAlert("empty field", "warning");
}
}
function setBackToDefault() {
input.value = "";
editFlag = false;
editId = "";
submitBtn.textContent = "Submit";
submitBtn.className = "app__submit-btn";
}
function displayAlert(text, action) {
alert.textContent = text;
alert.classList.add(`app__alert--${action}`);
setTimeout(function() {
alert.textContent = "";
alert.classList.remove(`app__alert--${action}`);
}, 700)
}
function clearItems() {
const items = document.querySelectorAll(".app__item");
if (items.length > 0) {
items.forEach(function(singleItem) {
itemsList.removeChild(singleItem);
})
itemsContainer.classList.remove("app__items-container--visible");
displayAlert("items cleared", "cleared");
setBackToDefault();
}
}
function editItem(e) {
const item = e.currentTarget.parentElement.parentElement;
editElement = e.currentTarget.parentElement.previousElementSibling;
editId = item.dataset.id;
editFlag = true;
input.value = editElement.textContent;
submitBtn.textContent = "Edit";
submitBtn.classList.add("app__submit-btn--edit");
input.focus();
}
function deleteItem(e) {
const item = e.currentTarget.parentElement.parentElement;
const itemId = item.dataset.id;
removeFromLocalStorage(itemId);
displayAlert("item removed", "cleared");
setBackToDefault();
itemsList.removeChild(item);
if (itemsList.children.length === 0) {
itemsContainer.classList.remove("app__items-container--visible");
}
}
function addToLocalStorage(id, value) {
const itemsObj = {id: id, value: input.value};
let storageItems = getLocalStorage();
storageItems.push(itemsObj);
localStorage.setItem("list", JSON.stringify(storageItems));
}
function removeFromLocalStorage(id) {
console.log(id);
let storageItems = getLocalStorage();
console.log(storageItems);
storageItems = storageItems.filter(function(singleItem) {
if (singleItem.id !== id) {
return singleItem;
}
})
console.log(storageItems);
localStorage.setItem("list", JSON.stringify(storageItems));
}
function editLocalStorage(id, value) {
}
function getLocalStorage() {
return localStorage.getItem("list") ? JSON.parse(localStorage.getItem("list")) : [];
}
* {
margin: 0;
padding: 0;
}
.app {
width: 70%;
max-width: 600px;
margin: 75px auto 0;
}
.app__title {
text-align: center;
/* color: #1B5D81; */
margin-top: 20px;
color: #377FB4;
}
.app__alert {
width: 60%;
margin: 0 auto;
text-align: center;
font-size: 20px;
color: #215884;
border-radius: 7px;
height: 23px;
transition: 0.4s;
text-transform: capitalize;
}
.app__alert--warning {
background-color: rgba(243, 117, 66, 0.2);
color: #006699;
}
.app__alert--success {
background-color: rgba(165, 237, 92, 0.4);
color: #3333ff;
}
.app__alert--cleared {
background-color: #a978da;
color: white;
}
.app__input-btn-cont {
display: flex;
margin-top: 30px;
}
.app__input {
width: 80%;
box-sizing: border-box;
font-size: 20px;
padding: 3px 0 3px 10px;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
border-right: none;
border: 1px solid #67B5E2;
background-color: #EDF9FF;
}
.app__input:focus {
outline: transparent;
}
.app__submit-btn {
display: block;
width: 20%;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
border-left: none;
background-color: #67B5E2;
border: 1px solid #67B5E2;
cursor: pointer;
font-size: 20px;
color: white;
transition: background-color 0.7s;
padding: 3px 0;
}
.app__submit-btn--edit {
background-color: #95CB5D;
}
.app__submit-btn:active {
width: 19.9%;
padding: 0 0;
}
.app__submit-btn:hover {
background-color: #377FB4;
}
.app__submit-btn--edit:hover {
background-color: #81AF51;
}
.app__items-container {
visibility: hidden;
/* transition: 0.7s; */
}
.app__items-container--visible {
visibility: visible;
}
.app__item {
display: flex;
justify-content: space-between;
margin: 20px 0;
}
.app__item:hover {
background-color: #b9e2fa;
border-radius: 10px;
}
.app__item-text {
padding-left: 10px;
font-size: 20px;
color: #1B5D81;
}
.app__item-btn-cont {
display: flex;
}
.app__item-btn-img {
width: 20px;
height: 20px;
}
.app__item-btn {
border: none;
background-color: transparent;
cursor: pointer;
display: block;
font-size: 18px;
}
.app__item-btn--edit {
margin-right: 45px;
color: #2c800f;
}
.app__item-btn--delete {
margin-right: 15px;
color: rgb(243, 117, 66);
}
.app__clear-btn {
display: block;
width: 150px;
margin: 20px auto;
border: none;
background-color: transparent;
font-size: 20px;
color: rgb(243, 117, 66);
letter-spacing: 2px;
cursor: pointer;
transition: border 0.3s;
border: 1px solid transparent;
}
.app__clear-btn:hover {
border: 1px solid rgb(243, 117, 66);
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" name="viewport" content="width=device-width,
initial-scale=1">
<link rel="stylesheet" href="list.css">
<title>To Do List App</title>
</head>
<body>
<section class="app">
<form class="app__form">
<p class="app__alert"></p>
<h2 class="app__title">To Do List</h2>
<div class="app__input-btn-cont">
<input class="app__input" type="text" id="todo" placeholder="do stuff">
<button class="app__submit-btn">Submit</button>
</div>
</form>
<div class="app__items-container">
<div class="app__items-list">
</div>
<button class="app__clear-btn">Clear Items</button>
</div>
</section>
<script src="list.js"></script>
</body>
</html>
Your code is fine you just used the wrong comparison operator.
In your case you are comparing 2 IDs (operands) to see if they match up, so you should use normal operators such as (==, !=), but instead in your case, you have used strict operators which are used to compare the operand type and the operand itself.
You can learn more about Comparison Operators here.
Ultimatly,
In your function removeFromLocalStorage(id), you have an extra equal sign in your if function.
Instead of:
if (singleItem.id !== id) {
return singleItem;}
It should be:
if (singleItem.id != id) {
return singleItem;}
Hope this helps.

Why isn't the string.length updating?

This is my first piece of code js done on my own. I am trying to have an input field to add items to the list and then if you press the button to generate code it will collect all the checked items and copy the text into another div.
Basically, my question is around two variables:
const list = listUl.children;
const listCopy = listUl.querySelectorAll('span');
Let say I have 4 items in the list. If I add a new item to the list I can see the list.length add this new item, it changes from 4 to 5.
But it doesn't happen with listCopy.length the value keeps being 4.
Why is it happening if lstCopy is inside of list?
How can I have listCopy updated too?
Here is my code:
const addItemInput = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('.addItemButton');
const copyText = document.querySelector('.generateCode');
const listUl = document.querySelector('.list');
const list = listUl.children;
const listCopy = listUl.querySelectorAll('span');
const clonedCode = document.querySelector('.code p');
//FUNCTION: Generate value/items = Draggable, Checkbox, Remove button
const attachItemListButton = (item) => {
//Draggable
item.draggable = "true";
item.classList.add("list--item");
//Checkbox
let checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = 'checkbox';
checkbox.name = "chkboxName1";
checkbox.value = "value";
checkbox.id = "id";
item.insertBefore(checkbox, item.childNodes[0] || null);
//Remove button
let remove = document.createElement('button');
remove.className = 'remove';
remove.textContent = 'x';
item.appendChild(remove);
};
for (let i = 0; i < list.length; i += 1) {
attachItemListButton(list[i]);
}
//Cloning code if there are checked items
copyText.addEventListener('click', () => {
let copyTextFromList = "";
for (let i = 0; i < listCopy.length; i += 1) {
if (listCopy[i].parentNode.querySelector("input:checked")) {
copyTextFromList += listCopy[i].textContent + ',';
}
}
clonedCode.innerHTML = copyTextFromList;
});
//Add item from the input field to the list
addItemButton.addEventListener('click', () => {
let li = document.createElement('li');
let span = document.createElement('span');
span.textContent = addItemInput.value;
listUl.appendChild(li);
li.appendChild(span);
attachItemListButton(li);
addItemInput.value = '';
});
//FUNCTION: Remove button
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);
}
}
});
/* Google fonts */
#import url('https://fonts.googleapis.com/css?family=Heebo:300,400,700');
/* Root */
:root {
--color-white: #fff;
--color-black: #2D3142;
--color-black-2: #0E1116;
--color-gray: #CEE5F2;
--color-gray-2: #ACCBE1;
--color-gray-3: #CEE5F2;
--color-green: #439775;
--color-blue: #4686CC;
}
body {
font-family: 'Heebo', sans-serif;
font-weight: 400;
font-size: 16px;
color: black;
}
h2 {
font-weight: 700;
font-size: 1.5rem;
}
h3 {
font-weight: 700;
font-size: 1.25rem;
}
button {
background: var(--color-blue);
padding: 5px 10px;
border-radius: 5px;
color: var(--color-white);
}
[draggable] {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
-khtml-user-drag: element;
-webkit-user-drag: element;
}
ul.list {
list-style-type: none;
padding: 0;
max-width: 300px;
}
.list button {
background: var(--color-black);
}
.list--item {
display: flex;
justify-content: space-between;
align-items: center;
width: auto;
margin: 5px auto;
padding: 5px;
cursor: move;
background: var(--color-gray);
border-radius: 5px;
}
.list--item.draggingElement {
opacity: 0.4;
}
.list--item.over {
border-top: 3px solid var(--color-green);
}
button.remove {
margin: auto 0 auto auto;
}
input#id {
margin: auto 5px auto 0;
}
.button-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
max-width: 300px;
}
.button-wrapper .addItemInput {
width: 63%;
border-radius: 5px 0 0 5px;
}
.button-wrapper .addItemButton {
width: 35%;
border-radius: 0 5px 5px 0;
}
.button-wrapper .generateCode {
width: 100%;
background: var(--color-green);
margin-top: 5px;
}
.code p {
background: var(--color-gray); padding: 5px;
border: 1px solid var(--color-gray-2);
min-height: 20px;
font-weight: 300;
}
<ul class="list">
<li><span>Header</span></li>
<li><span>Hero</span></li>
<li><span>Intro</span></li>
<li><span>Footer</span></li>
</ul>
<div class="button-wrapper">
<input type="text" class="addItemInput" placeholder="Item description">
<button class="addItemButton">Add item</button>
<button class="generateCode">Generate code</button>
</div>
<div class="code">
<h2>Code</h2>
<p></p>
</div>
There are two variants of NodeList, live and non-live ones. querySelectorAll returns a static NodeList that is not live. .children returns a live one (technically it returns an HTMLCollection but you can ignore this distinction for now).
To make listCopy be live as well, you could use listUl.getElementsByTagName('span')…
To select elements by their classes, use getElementsByClassName. There is no way (that I know of) to get a live collection with CSS or XPath (i.e. more complex) queries, though.
The problem is that const listCopy = listUl.querySelectorAll('span'); is initiated with the span array from the beginning.
In order to get updated list
const listCopy = listUl.querySelectorAll('span'); will be let listCopy = listUl.querySelectorAll('span'); and in your function
//Cloning code if there are checked items
copyText.addEventListener('click', () => {
// add the following line - in this way you will select the span from the updated list
listCopy = listUl.querySelectorAll('span');
let copyTextFromList = "";
for (let i = 0; i < listCopy.length; i += 1) {
if (listCopy[i].parentNode.querySelector("input:checked")) {
copyTextFromList += listCopy[i].textContent + ',';
}
}
clonedCode.innerHTML = copyTextFromList;
});
if you want to use querySelectorAll, this maybe help. with this every time you check the length it recalculates and returns the value. Symbol.iterator helps you to manipulate for...of loops.
const addItemInput = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('.addItemButton');
const copyText = document.querySelector('.generateCode');
const listUl = document.querySelector('.list');
const list = listUl.children;
const listCopy = {
get length() {
return listUl.querySelectorAll('span').length
},
*[Symbol.iterator]() {
let i = 0;
const l = listUl.querySelectorAll('span');
while( i < l.length ) {
yield l[i];
i++;
}
}
};
const clonedCode = document.querySelector('.code p');
//FUNCTION: Generate value/items = Draggable, Checkbox, Remove button
const attachItemListButton = (item) => {
//Draggable
item.draggable = "true";
item.classList.add("list--item");
//Checkbox
let checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = 'checkbox';
checkbox.name = "chkboxName1";
checkbox.value = "value";
checkbox.id = "id";
item.insertBefore(checkbox, item.childNodes[0] || null);
//Remove button
let remove = document.createElement('button');
remove.className = 'remove';
remove.textContent = 'x';
item.appendChild(remove);
};
for (let i = 0; i < list.length; i += 1) {
attachItemListButton(list[i]);
}
//Cloning code if there are checked items
copyText.addEventListener('click', () => {
let copyTextFromList = "";
for (let item of listCopy) {
if (item.parentNode.querySelector("input:checked")) {
copyTextFromList += item.textContent + ',';
}
}
clonedCode.innerHTML = copyTextFromList;
});
//Add item from the input field to the list
addItemButton.addEventListener('click', () => {
let li = document.createElement('li');
let span = document.createElement('span');
span.textContent = addItemInput.value;
listUl.appendChild(li);
li.appendChild(span);
attachItemListButton(li);
addItemInput.value = '';
});
//FUNCTION: Remove button
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);
}
}
});
/* Google fonts */
#import url('https://fonts.googleapis.com/css?family=Heebo:300,400,700');
/* Root */
:root {
--color-white: #fff;
--color-black: #2D3142;
--color-black-2: #0E1116;
--color-gray: #CEE5F2;
--color-gray-2: #ACCBE1;
--color-gray-3: #CEE5F2;
--color-green: #439775;
--color-blue: #4686CC;
}
body {
font-family: 'Heebo', sans-serif;
font-weight: 400;
font-size: 16px;
color: black;
}
h2 {
font-weight: 700;
font-size: 1.5rem;
}
h3 {
font-weight: 700;
font-size: 1.25rem;
}
button {
background: var(--color-blue);
padding: 5px 10px;
border-radius: 5px;
color: var(--color-white);
}
[draggable] {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
-khtml-user-drag: element;
-webkit-user-drag: element;
}
ul.list {
list-style-type: none;
padding: 0;
max-width: 300px;
}
.list button {
background: var(--color-black);
}
.list--item {
display: flex;
justify-content: space-between;
align-items: center;
width: auto;
margin: 5px auto;
padding: 5px;
cursor: move;
background: var(--color-gray);
border-radius: 5px;
}
.list--item.draggingElement {
opacity: 0.4;
}
.list--item.over {
border-top: 3px solid var(--color-green);
}
button.remove {
margin: auto 0 auto auto;
}
input#id {
margin: auto 5px auto 0;
}
.button-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
max-width: 300px;
}
.button-wrapper .addItemInput {
width: 63%;
border-radius: 5px 0 0 5px;
}
.button-wrapper .addItemButton {
width: 35%;
border-radius: 0 5px 5px 0;
}
.button-wrapper .generateCode {
width: 100%;
background: var(--color-green);
margin-top: 5px;
}
.code p {
background: var(--color-gray); padding: 5px;
border: 1px solid var(--color-gray-2);
min-height: 20px;
font-weight: 300;
}
<ul class="list">
<li><span>Header</span></li>
<li><span>Hero</span></li>
<li><span>Intro</span></li>
<li><span>Footer</span></li>
</ul>
<div class="button-wrapper">
<input type="text" class="addItemInput" placeholder="Item description">
<button class="addItemButton">Add item</button>
<button class="generateCode">Generate code</button>
</div>
<div class="code">
<h2>Code</h2>
<p></p>
</div>

How can I add a desired feature to my personal list using Javascript?

As you can see below I have a very simple list which let user add and remove items as well as change the order using 3 buttons for each item.
The feature which wanna add is removing up button for first item and down button for last item. At the begging, you may feel it works fine but in fact I've only used 4 lines code to remove up and down from current list but the problem comes when the user change the order of items, add or remove them.
I'm sure you guys have intelligently ways to add this but I personally have below idea and unfortunately I can't get it to work. I've spent more than 2 hour to fix it but still it doesn't work.
My idea:
FIRST PART : Making below functions for removing up button from 2nd li and re-add it to 1st li. Also, removing down button from n-1th li and re-add to nth li.
function upButtonFixer (li1,li2){
var up = document.createElement("BUTTON");
up.className = "up"
up.textContent="up"
li1.appendChild(up);
var upper = li2.getElementsByClassName('up')[0];
li2.removeChild(upper);
}
function downButtonFixer (li1,li2){
var down = document.createElement("BUTTON");
down.className = "down"
down.textContent="down"
li2.appendChild(down);
var downer = li1.getElementsByClassName('down')[0];
li1.removeChild(downer);
}
SECOND PART :
Then I called both function into a if statement like below:
ul.addEventListener('click',(event)=>{
if (event.target.tagName == "BUTTON"){
if (event.target.className=="up"){
**if (prevLi == ul.firstElementChild)
upAdderRemover(prevLi,li);**
}
if (event.target.className=="down"){
**if (li==ul.lastElementChild)
downAdderRemover(li,nextLi);**
}
}
const listDiv = document.querySelector("div");
const inputDescription = document.querySelector("input.description");
const pDescription = document.querySelector('p.description');
const buttonDescription = document.querySelector('button.description');
const addItemList = document.querySelector('button.adder');
const addInput = document.getElementsByClassName('addInput')[0];
const ul = document.querySelector('ul');
const removeButton = document.querySelector('button.remover');
const lis = ul.children;
function addButtons (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);
}
for (var i = 0 ; i<lis.length ;i++){
addButtons(lis[i]);
}
buttonDescription.addEventListener('click', ()=>{
pDescription.textContent = inputDescription.value+':';
});
addItemList.addEventListener('click',()=>{
let newLI = document.createElement("li");
newLI.textContent = addInput.value;
addButtons(newLI)
ul.appendChild(newLI);
addInput.value = '';
});
removeButton.addEventListener('click', ()=>{
const lastChild = document.querySelector('li:last-child');
ul.removeChild(lastChild);
});
ul.addEventListener('click',(event)=>{
if (event.target.tagName == "BUTTON"){
if (event.target.className=="remove"){
const par1 = event.target.parentNode;
const par2 = par1.parentNode;
par2.removeChild(par1);
}
if (event.target.className=="up"){
const li = event.target.parentNode;
const prevLi = li.previousElementSibling;
if (prevLi)
ul.insertBefore(li,prevLi);
}
else if (event.target.className=="down"){
const li = event.target.parentNode;
const nextLi = li.nextElementSibling;
if (nextLi)
ul.insertBefore(nextLi,li);
}
}
});
var first = ul.firstElementChild;
var last = ul.lastElementChild;
var u = first.getElementsByClassName("up")[0];
var d = last.getElementsByClassName("down")[0];
first.removeChild(u);
last.removeChild(d);
#import 'https://fonts.googleapis.com/css?family=Lato:400,700';
body {
color: #484848;
font-family: 'Lato', sans-serif;
padding: .45em 2.65em 3em;
line-height: 1.5;
}
h1 {
margin-bottom: 0;
}
h1 + p {
font-size: 1.08em;
color: #637a91;
margin-top: .5em;
margin-bottom: 2.65em;
padding-bottom: 1.325em;
border-bottom: 1px dotted;
}
ul {
padding-left: 0;
list-style: none;
}
li {
padding: .45em .5em;
margin-bottom: .35em;
display: flex;
align-items: center;
}
input,
button {
font-size: .85em;
padding: .65em 1em;
border-radius: .3em;
outline: 0;
}
input {
border: 1px solid #dcdcdc;
margin-right: 1em;
}
div {
margin-top: 2.8em;
padding: 1.5em 0 .5em;
border-top: 1px dotted #637a91;
}
p.description,
p:nth-of-type(2) {
font-weight: bold;
}
/* Buttons */
button {
color: white;
background: #508abc;
border: solid 1px;
border-color: rgba(0, 0, 0, .1);
cursor: pointer;
}
button + button {
margin-left: .5em;
}
p + button {
background: #52bab3;
}
.list button + button {
background: #768da3;
}
.list li button + button {
background: #508abc;
}
li button:first-child {
margin-left: auto;
background: #52bab3;
}
.list li button:last-child {
background: #768da3;
}
li button {
font-size: .75em;
padding: .5em .65em;
}
<!DOCTYPE html>
<html>
<head>
<title>My First Website</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h2>Im the H2!</h2>
<p>Im the p!</p>
<div class="list">
<p class="description">The title of the list</p>
<input type="text" class="description">
<button class="description">change the title!</button>
<ul>
<li>first </li>
<li>second</li>
<li>third</li>
<li>forth</li>
<li>fifth</li>
<li>sixth</li>
<li>seventh</li>
</ul>
<input type="text" class="addInput">
<button class="adder">Add!</button>
<button class="remover">Remove!</button>
</div>
<script src="app.js"></script>
</body>
</html>
I found the solution after 4 hours. It's not optimized but I've finally implemented using javascript! So happy :)
Thanks for your CSS solutions. Please check it out.
Here we go!
const toggleList = document.getElementById('toggle');
const listDiv = document.querySelector("div");
const inputDescription = document.querySelector("input.description");
const pDescription = document.querySelector('p.description');
const buttonDescription = document.querySelector('button.description');
const addItemList = document.querySelector('button.adder');
const addInput = document.getElementsByClassName('addInput')[0];
const ul = document.querySelector('ul');
const removeButton = document.querySelector('button.remover');
const lis = ul.children;
function addButtons (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);
}
for (var i = 0 ; i<lis.length ;i++){
addButtons(lis[i]);
}
function addup (li){
let up = document.createElement("BUTTON");
up.className = "up"
up.textContent="up"
li.appendChild(up);
}
buttonDescription.addEventListener('click', ()=>{
pDescription.textContent = inputDescription.value+':';
});
addItemList.addEventListener('click',()=>{
let newLI = document.createElement("li");
newLI.textContent = addInput.value;
addButtons(newLI)
ul.appendChild(newLI);
addInput.value = '';
});
removeButton.addEventListener('click', ()=>{
const lastChild = document.querySelector('li:last-child');
ul.removeChild(lastChild);
});
function remove3Buttons(li){
let x = li.firstElementChild;
let y = li.lastElementChild;
li.removeChild(x);
li.removeChild(y);
}
//ul.addEventListener('mouseover', (event)=>{
//
//
// if (event.target.tagName=="LI"){
//
// event.target.textContent=event.target.textContent.toUpperCase();
// }
//});
//
//ul.addEventListener('click', (event)=>{
//
//
// if (event.target.tagName=="LI"){
// const par = event.target.parentNode;
// par.removeChild(event.target);
// }
//});
//
//ul.addEventListener('mouseout', (event)=>{
//
//
// if (event.target.tagName=="LI"){
// event.target.textContent=event.target.textContent.toLowerCase();
// }
//});
//
function upButtonFixer (li1,li2){
var up = document.createElement("BUTTON");
up.className = "up"
up.textContent="up"
li1.appendChild(up);
var upper = li2.getElementsByTagName('BUTTON')[0];
li2.removeChild(upper);
}
function downButtonFixer (li1,li2){
var down = document.createElement("BUTTON");
down.className = "down"
down.textContent="down"
li2.appendChild(down);
var downer = li1.getElementsByTagName('BUTTON')[1];
li1.removeChild(downer);
}
ul.addEventListener('click',(event)=>{
if (event.target.tagName == "BUTTON"){
if (event.target.className=="remove"){
const par1 = event.target.parentNode;
const par2 = par1.parentNode;
par2.removeChild(par1);
}
if (event.target.className=="up"){
const first = ul.firstElementChild;
const second = first.nextElementSibling;
const last = ul.lastElementChild;
const secondEnd = last.previousElementSibling;
const li = event.target.parentNode;
const prevLi = li.previousElementSibling;
if (prevLi)
ul.insertBefore(li,prevLi);
if (li == last){
var z0 = secondEnd.firstElementChild;
var z1 = secondEnd.lastElementChild;
var z2 = z1.previousElementSibling;
remove3Buttons(li);
addButtons(li);
secondEnd.removeChild(z2);
}
if (li == second){
var a1 = li.firstElementChild;
li.removeChild(a1);
remove3Buttons(prevLi);
addButtons(prevLi);
}}
if (event.target.className=="down"){
const last = ul.lastElementChild;
const secondEnd = last.previousElementSibling;
const first = ul.firstElementChild;
const second = first.nextElementSibling;
const li = event.target.parentNode;
const nextLi = li.nextElementSibling;
if (nextLi)
ul.insertBefore(nextLi,li);
if (li == secondEnd){
var z0 = li.firstElementChild;
var z1 = li.lastElementChild;
var z2 = z1.previousElementSibling;
remove3Buttons(nextLi);
addButtons(nextLi);
li.removeChild(z2)
}
if (li == first){
var z0 = second.firstElementChild;
var z1 = second.lastElementChild;
var z2 = z1.previousElementSibling;
remove3Buttons(li);
addButtons(li);
second.removeChild(z0);
}
}
}
});
var first = ul.firstElementChild;
var last = ul.lastElementChild;
var u = first.getElementsByClassName("up")[0];
var d = last.getElementsByClassName("down")[0];
first.removeChild(u);
last.removeChild(d);
#import 'https://fonts.googleapis.com/css?family=Lato:400,700';
body {
color: #484848;
font-family: 'Lato', sans-serif;
padding: .45em 2.65em 3em;
line-height: 1.5;
}
h1 {
margin-bottom: 0;
}
h1 + p {
font-size: 1.08em;
color: #637a91;
margin-top: .5em;
margin-bottom: 2.65em;
padding-bottom: 1.325em;
border-bottom: 1px dotted;
}
ul {
padding-left: 0;
list-style: none;
}
li {
padding: .45em .5em;
margin-bottom: .35em;
display: flex;
align-items: center;
}
input,
button {
font-size: .85em;
padding: .65em 1em;
border-radius: .3em;
outline: 0;
}
input {
border: 1px solid #dcdcdc;
margin-right: 1em;
}
div {
margin-top: 2.8em;
padding: 1.5em 0 .5em;
border-top: 1px dotted #637a91;
}
p.description,
p:nth-of-type(2) {
font-weight: bold;
}
/* Buttons */
button {
color: white;
background: #508abc;
border: solid 1px;
border-color: rgba(0, 0, 0, .1);
cursor: pointer;
}
button + button {
margin-left: .5em;
}
p + button {
background: #52bab3;
}
.list button + button {
background: #768da3;
}
.list li button + button {
background: #508abc;
}
li button:first-child {
margin-left: auto;
background: #52bab3;
}
.list li button:last-child {
background: #768da3;
}
li button {
font-size: .75em;
padding: .5em .65em;
}
<!DOCTYPE html>
<html>
<head>
<title>My First Website</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h2>Im the H2!</h2>
<p>Im the p!</p>
<button id="toggle">Hide list!</button>
<div class="list">
<p class="description">The title of the list</p>
<input type="text" class="description">
<button class="description">change the title!</button>
<ul>
<li>first </li>
<li>second</li>
<li>third</li>
<li>forth</li>
<li>fifth</li>
<li>sixth</li>
<li>seventh</li>
</ul>
<input type="text" class="addInput">
<button class="adder">Add!</button>
<button class="remover">Remove!</button>
</div>
<script src="app.js"></script>
</body>
</html>
This can be done using CSS. I have noticed it has moved the first set of buttons to the left but overall this does what you are asking for.
I'm sure you can play around with the css to fix the minor issue.
I have removed the javascript that removes the first up and last down button and used css to hide the first up and last down button using the following...
ul li:first-child .up{
display:none;
}
ul li:last-child .down{
display:none;
}
const listDiv = document.querySelector("div");
const inputDescription = document.querySelector("input.description");
const pDescription = document.querySelector('p.description');
const buttonDescription = document.querySelector('button.description');
const addItemList = document.querySelector('button.adder');
const addInput = document.getElementsByClassName('addInput')[0];
const ul = document.querySelector('ul');
const removeButton = document.querySelector('button.remover');
const lis = ul.children;
function addButtons(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);
}
for (var i = 0; i < lis.length; i++) {
addButtons(lis[i]);
}
buttonDescription.addEventListener('click', () => {
pDescription.textContent = inputDescription.value + ':';
});
addItemList.addEventListener('click', () => {
let newLI = document.createElement("li");
newLI.textContent = addInput.value;
addButtons(newLI)
ul.appendChild(newLI);
addInput.value = '';
});
removeButton.addEventListener('click', () => {
const lastChild = document.querySelector('li:last-child');
ul.removeChild(lastChild);
});
ul.addEventListener('click', (event) => {
if (event.target.tagName == "BUTTON") {
if (event.target.className == "remove") {
const par1 = event.target.parentNode;
const par2 = par1.parentNode;
par2.removeChild(par1);
}
if (event.target.className == "up") {
const li = event.target.parentNode;
const prevLi = li.previousElementSibling;
if (prevLi)
ul.insertBefore(li, prevLi);
} else if (event.target.className == "down") {
const li = event.target.parentNode;
const nextLi = li.nextElementSibling;
if (nextLi)
ul.insertBefore(nextLi, li);
}
}
});
//Deleted source code to remove first & last up/down buttons
#import 'https://fonts.googleapis.com/css?family=Lato:400,700';
body {
color: #484848;
font-family: 'Lato', sans-serif;
padding: .45em 2.65em 3em;
line-height: 1.5;
}
h1 {
margin-bottom: 0;
}
h1+p {
font-size: 1.08em;
color: #637a91;
margin-top: .5em;
margin-bottom: 2.65em;
padding-bottom: 1.325em;
border-bottom: 1px dotted;
}
ul {
padding-left: 0;
list-style: none;
}
li {
padding: .45em .5em;
margin-bottom: .35em;
display: flex;
align-items: center;
}
input,
button {
font-size: .85em;
padding: .65em 1em;
border-radius: .3em;
outline: 0;
}
input {
border: 1px solid #dcdcdc;
margin-right: 1em;
}
div {
margin-top: 2.8em;
padding: 1.5em 0 .5em;
border-top: 1px dotted #637a91;
}
p.description,
p:nth-of-type(2) {
font-weight: bold;
}
/* Buttons */
/* Added.....*/
ul li:first-child .up{
display:none;
}
ul li:last-child .down{
display:none;
}
button {
color: white;
background: #508abc;
border: solid 1px;
border-color: rgba(0, 0, 0, .1);
cursor: pointer;
}
button+button {
margin-left: .5em;
}
p+button {
background: #52bab3;
}
.list button+button {
background: #768da3;
}
.list li button+button {
background: #508abc;
}
li button:first-child {
margin-left: auto;
background: #52bab3;
}
.list li button:last-child {
background: #768da3;
}
li button {
font-size: .75em;
padding: .5em .65em;
}
<h2>Im the H2!</h2>
<p>Im the p!</p>
<div class="list">
<p class="description">The title of the list</p>
<input type="text" class="description">
<button class="description">change the title!</button>
<ul>
<li>first </li>
<li>second</li>
<li>third</li>
<li>forth</li>
<li>fifth</li>
<li>sixth</li>
<li>seventh</li>
</ul>
<input type="text" class="addInput">
<button class="adder">Add!</button>
<button class="remover">Remove!</button>
</div>
</html>
If you have any questions about the edit(s) I have made then please leave a comment below and I will get back to you as soon as possible.
I hope this helps. Happy coding!
Edit: button alignment fix
If you want a quick fix for those buttons you can replace the css to the following
ul li:first-child .up{
visibility:hidden;
}
This will be the CSS solution for your requirement, this method would be the simplest.
i am using the :last-child and :first-child to show/hide the up and down buttons.
.list>ul>li:first-child>button.up{
display:none;
}
.list>ul>li:first-child>button.down{
margin-left: auto;
}
.list>ul>li:last-child>button.down{
display:none;
}
const listDiv = document.querySelector("div");
const inputDescription = document.querySelector("input.description");
const pDescription = document.querySelector('p.description');
const buttonDescription = document.querySelector('button.description');
const addItemList = document.querySelector('button.adder');
const addInput = document.getElementsByClassName('addInput')[0];
const ul = document.querySelector('ul');
const removeButton = document.querySelector('button.remover');
const lis = ul.children;
function addButtons (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);
}
for (var i = 0 ; i<lis.length ;i++){
addButtons(lis[i]);
}
buttonDescription.addEventListener('click', ()=>{
pDescription.textContent = inputDescription.value+':';
});
addItemList.addEventListener('click',()=>{
let newLI = document.createElement("li");
newLI.textContent = addInput.value;
addButtons(newLI)
ul.appendChild(newLI);
addInput.value = '';
});
removeButton.addEventListener('click', ()=>{
const lastChild = document.querySelector('li:last-child');
ul.removeChild(lastChild);
});
ul.addEventListener('click',(event)=>{
if (event.target.tagName == "BUTTON"){
if (event.target.className=="remove"){
const par1 = event.target.parentNode;
const par2 = par1.parentNode;
par2.removeChild(par1);
}
if (event.target.className=="up"){
const li = event.target.parentNode;
const prevLi = li.previousElementSibling;
if (prevLi)
ul.insertBefore(li,prevLi);
}
else if (event.target.className=="down"){
const li = event.target.parentNode;
const nextLi = li.nextElementSibling;
if (nextLi)
ul.insertBefore(nextLi,li);
}
}
});
#import 'https://fonts.googleapis.com/css?family=Lato:400,700';
body {
color: #484848;
font-family: 'Lato', sans-serif;
padding: .45em 2.65em 3em;
line-height: 1.5;
}
h1 {
margin-bottom: 0;
}
.list>ul>li:first-child>button.up{
display:none;
}
.list>ul>li:first-child>button.down{
margin-left: auto;
}
.list>ul>li:last-child>button.down{
display:none;
}
h1 + p {
font-size: 1.08em;
color: #637a91;
margin-top: .5em;
margin-bottom: 2.65em;
padding-bottom: 1.325em;
border-bottom: 1px dotted;
}
ul {
padding-left: 0;
list-style: none;
}
li {
padding: .45em .5em;
margin-bottom: .35em;
display: flex;
align-items: center;
}
input,
button {
font-size: .85em;
padding: .65em 1em;
border-radius: .3em;
outline: 0;
}
input {
border: 1px solid #dcdcdc;
margin-right: 1em;
}
div {
margin-top: 2.8em;
padding: 1.5em 0 .5em;
border-top: 1px dotted #637a91;
}
p.description,
p:nth-of-type(2) {
font-weight: bold;
}
/* Buttons */
button {
color: white;
background: #508abc;
border: solid 1px;
border-color: rgba(0, 0, 0, .1);
cursor: pointer;
}
button + button {
margin-left: .5em;
}
p + button {
background: #52bab3;
}
.list button + button {
background: #768da3;
}
.list li button + button {
background: #508abc;
}
li button:first-child {
margin-left: auto;
background: #52bab3;
}
.list li button:last-child {
background: #768da3;
}
li button {
font-size: .75em;
padding: .5em .65em;
}
<!DOCTYPE html>
<html>
<head>
<title>My First Website</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h2>Im the H2!</h2>
<p>Im the p!</p>
<div class="list">
<p class="description">The title of the list</p>
<input type="text" class="description">
<button class="description">change the title!</button>
<ul>
<li>first </li>
<li>second</li>
<li>third</li>
<li>forth</li>
<li>fifth</li>
<li>sixth</li>
<li>seventh</li>
</ul>
<input type="text" class="addInput">
<button class="adder">Add!</button>
<button class="remover">Remove!</button>
</div>
<script src="app.js"></script>
</body>
</html>

Categories

Resources