I am doing a to-do list web page using HTML/CSS/JavaScript. I did only up to display the content entered by users with priority bases (high/low/medium). I am not able to do the last section (select to get specific task).
The main concept is, If the user clicks on the high/medium/low buttons, It should display the corresponding priority list only. If the user clicks the high priority button then display only high priority list data.
High priority (background -red), medium priority (background -yellow), low priority (background -green). You can display that last section anywhere, further, we can do modifications.
Below you can see my code. Please, can you help me?
const lists = document.getElementsByClassName('task-list')[0];
const radios = document.getElementsByName('rgPrior');
function onClick()
{
for (let i = 0, length = radios.length; i < length; i++)
{
if (radios[i].checked)
{
btn_selected_color = radios[i].value + 'P';
break;
}
}
const task = document.getElementById('item').value;
// Add it to the HTML
addTodo(task, btn_selected_color);
// Save it to localStorage
let data = JSON.parse(localStorage.getItem('todo')) || [];
data.push([
task,
btn_selected_color
]);
localStorage.setItem('todo', JSON.stringify(data));
}
function addTodo(todo, priority)
{
let entry = document.createElement('li');
let close = document.createElement('button');
entry.className = priority;
close.className = 'close-btn';
close.innerText = 'X';
close.addEventListener('click', function(e)
{
// Delete from localstorage
let data = JSON.parse(localStorage.getItem('todo'));
let index = data.indexOf([
todo,
priority
]);
data.splice(index, 1);
localStorage.setItem('todo', JSON.stringify(data));
// Delete HTML
this.parentElement.remove();
});
entry.appendChild(close);
entry.appendChild(document.createTextNode(todo));
lists.appendChild(entry);
}
// When the page is loaded, get from localStorage
window.addEventListener('load', function()
{
const data = JSON.parse(localStorage.getItem('todo'));
data.forEach(function(task)
{
addTodo(...task);
});
});
.hiP {background-color : red;}
.medP {background-color: #ffbf00;}
.lowP {background-color: green;}
.ch5 {padding-left: 30px;}
#box{
width: 500px;
padding: 20px;
margin: 20px;
margin-left: auto;
margin-right: auto;
background-color: white;
border-radius: 40px;
box-shadow: 0 5px 15px 0 rgba(0, 0, 0, .5);
}
#box1{
text-align: center;
width: 400px;
padding: 30px;
margin: 30px;
margin-left: auto;
margin-right: auto;
/* background-color: #140101; */
/* background-color: #37283b; */
background-image: linear-gradient(rgb(218, 76, 76),#d1b562, rgb(122, 233, 122));
border-radius: 20px;
}
#box2{
width: 400px;
padding: 30px;
margin: 30px;
margin-top: auto;
margin-left: auto;
margin-right: auto;
/* background-image: linear-gradient(red,#ffbf00, green); */
/* background-color: rgb(160, 10, 122); */
background-color: #c1d7f5;
border-radius: 20px;
}
#box3{
text-align: center;
width: 400px;
padding: 30px;
margin: 30px;
margin-top: auto;
margin-left: auto;
margin-right: auto;
/* background-color: rgb(22, 240, 22); */
background-color: #93f6c6;
border-radius: 20px;
}
.header{
/* background-color: #5a9cda; */
background-color: #38045a;
color: white ;
padding: 20px ;
margin-top: -10px;
margin: -10px;
font-size: large;
}
.footer{
position: fixed;
padding: 10px 10px 0px 10px;
margin: -10px;
font-size: large;
color: white;
bottom: 0;
width: 100%;
height: 40px;
/* background: #5a9cda; */
background-color: #04267c;
}
.button1 {
background-color: white;
color: black;
border: 2px solid #f44336;
border-radius: 10px;
}
.button1:hover {
background-color: #f44336;
color: white;
}
.button2 {
background-color: white;
color: black;
border: 2px solid #ffbf00;
border-radius: 10px;
}
.button2:hover {
background-color: #ffbf00;
color: white;
}
.button3 {
background-color: white;
color: black;
border: 2px solid green;
border-radius: 10px;
}
.button3:hover {
background-color: green;
color: white;
}
.button4 {
background-color: white;
color: black;
border: 2px solid green;
border-radius: 10px;
}
.button4:hover {
background-color: green;
color: white;
}
<div class="header" align="center">
<header>MY TO_DO LIST</header>
</div>
<div id="box">
<div id="box1" >
<form >
<label for="txtAdd" style="font-size: 20px;color: white;"><b> Enter New thing to do: </b></label>
<input name="txtAdd" type="text" id="item" />
</form>
<p style="font-size: 20px; color: white;"><b> Set Priority </b></p>
<p>
<label style="color: #ce1126; font-size: 20px;"><input type="radio" name="rgPrior" value="hi" id="rgPrior_0"/>HIGH</label>
<label style="color: #ce1126; font-size: 20px;"><input type="radio" name="rgPrior" value="med" id="rgPrior_1"/>MEDIUM</label>
<label style="color: #ce1126; font-size: 20px;"><input type="radio" name="rgPrior" value="low" id="rgPrior_2"/>LOW</label>
</p>
<input type="button" name="btnAdd" class="button4" id="btnAdd" value="Save The Task" onClick="onClick()" />
</div>
<p style="text-align: center; color: rgba(3, 95, 30, 0.767); font-size: 20px;"><b> WORK TO-DO </b></p>
<div id="box2">
<ul class="task-list"> </ul>
</div>
<div id="box3">
<p style" -20px;color: rgb(56, 4, 155); font-size: 20px;">Select to get Specific tasks</p>
<button class="button1">HIGH</button>
<button class="button2">MEDIUM</button>
<button class="button3">LOW</button>
</div>
</div>
<div class="footer" align="center" >
<marquee direction="right" >ThankYou, Visit again</marquee>
</div>
Array.prototype.filter()
Here's a working example of how to filter a list:
const items = [{
value: 'Item 1',
className: 'low',
}, {
value: 'Item 2',
className: 'high',
}, {
value: 'Item 3',
className: 'low',
}, {
value: 'Item 4',
className: 'medium',
}, {
value: 'Item 5',
className: 'medium',
}];
const ul = document.getElementById('filtered-list');
const button1 = document.getElementById('high-priority');
const button2 = document.getElementById('medium-priority');
const button3 = document.getElementById('low-priority');
const createListItems = function createListItems(filteredList) {
ul.innerHTML = '';
filteredList.map((item) => {
const li = document.createElement('li');
li.append(item.value);
li.className = item.className;
ul.append(li);
});
};
const click = function click(event) {
event.preventDefault();
const t = this;
const filtered = items.filter(item => item.className === t.priority);
createListItems(filtered);
}
button1.addEventListener('click', click.bind({ priority: 'high' }));
button2.addEventListener('click', click.bind({ priority: 'medium' }));
button3.addEventListener('click', click.bind({ priority: 'low' }));
createListItems(items);
.high { background-color: red; }
.medium { background-color: yellow; }
.low { background-color: green; }
<ul id="filtered-list"></ul>
<button id="high-priority" type="button">High Priority</button>
<button id="medium-priority" type="button">Medium Priority</button>
<button id="low-priority" type="button">Low Priority</button>
Below is how it could look in your code. Just remove onClick from your HTML otherwise it will add the item twice.
const lists = document.getElementsByClassName('task-list')[0];
const radios = [...document.getElementsByName('rgPrior')];
const btnAdd = document.getElementById('btnAdd');
const button1 = document.getElementsByClassName('button1')[0];
const button2 = document.getElementsByClassName('button2')[0];
const button3 = document.getElementsByClassName('button3')[0];
const items = [];
const addTodo = function addTodo(todo, priority) {
const entry = document.createElement('li');
const close = document.createElement('button');
items.push({
value: todo,
className: priority,
});
entry.className = priority;
close.className = 'close-btn';
close.innerText = 'X';
close.addEventListener('click', function click(event) {
event.preventDefault();
// Delete from localstorage
const data = JSON.parse(localStorage.getItem('todo'));
const index = data.indexOf([
todo,
priority,
]);
data.splice(index, 1);
localStorage.setItem('todo', JSON.stringify(data));
// Delete HTML
this.parentElement.remove();
});
entry.appendChild(close);
entry.appendChild(document.createTextNode(todo));
lists.appendChild(entry);
};
const onClick = function onClick() {
let btnSelectedColor;
radios.map((radio) => {
if (radio.checked) {
btnSelectedColor = `${radio.value}P`;
}
return false;
});
const task = document.getElementById('item').value;
// Add it to the HTML
addTodo(task, btnSelectedColor);
// Save it to localStorage
const data = JSON.parse(localStorage.getItem('todo')) || [];
data.push([task, btnSelectedColor]);
localStorage.setItem('todo', JSON.stringify(data));
};
btnAdd.addEventListener('click', onClick);
const createListItems = function createListItems(filteredList) {
lists.innerHTML = '';
filteredList.map((item) => {
const li = document.createElement('li');
li.append(item.value);
li.className = item.className;
lists.append(li);
return false;
});
};
const filterItems = function filterItems(event) {
event.preventDefault();
const t = this;
const filtered = items.filter((item) => item.className === t.priority);
createListItems(filtered);
};
button1.addEventListener('click', filterItems.bind({ priority: 'hiP' }));
button2.addEventListener('click', filterItems.bind({ priority: 'medP' }));
button3.addEventListener('click', filterItems.bind({ priority: 'lowP' }));
// When the page is loaded, get from localStorage
window.addEventListener('load', () => {
const data = JSON.parse(localStorage.getItem('todo'));
data.forEach((task) => {
addTodo(...task);
});
});
Related
Still learning so bear with me.
I am building a test project where I have a simple input that I show it on the same page as a list. (grocery or to do list project)
So when a user hits the ok button I create a new li inside a ul element. That goes ok.
I want to implement the following though: When the user clicks on the new element (li) I want to change the text decoration to line-though and show a trash icon where it will remove this li element by clicking on it.
I have managed to do that. The problem is that when the user clicks again on the new element (li) I get a second trash image.
I want help to succeed in this: when a user clicks on the element while it has text-decoration = line-through to hide or remove the trash icon and make text-decoration none again.
Here is a code pen for this project to check out. Just insert a new item on the list and then click twice on it: https://codepen.io/dourvas-ioannis/pen/MWVBjNZ
This is the function I am using when the user hits the add button to add a list item:
function addToList(){
let newListItem = document.createElement('li');
newListItem.textContent = userInput.value;
list.appendChild(newListItem);
userInput.value = "";
newListItem.addEventListener('click', function(){
this.style.textDecoration = 'line-through';
let itemButton = document.createElement('a');
itemButton.setAttribute('href', '#');
itemButton.classList.add('trash-image');
itemButton.innerHTML = '<i class="material-icons">delete</i><a/>';
itemButton.addEventListener("click", deleteOneItem);
this.appendChild(itemButton);
});
}
function deleteOneItem(){
this.parentNode.remove();
}
//select from DOM
let allItems = document.querySelector('#allItems');
let button = document.querySelector('#add-button');
let userInput = document.querySelector('#item');
let list = document.querySelector('#list');
let clear = document.querySelector('#clear-button');
//add event listener
button.addEventListener('click', addToList);
clear.addEventListener('click', clearAll);
//functions
function addToList() {
let newListItem = document.createElement('li');
newListItem.textContent = userInput.value;
list.appendChild(newListItem);
userInput.value = "";
newListItem.addEventListener('click', function() {
this.style.textDecoration = 'line-through';
let itemButton = document.createElement('a');
itemButton.setAttribute('href', '#');
itemButton.classList.add('trash-image');
itemButton.innerHTML = '<i class="material-icons">delete</i><a/>';
itemButton.addEventListener("click", deleteOneItem);
this.appendChild(itemButton);
});
}
function deleteOneItem() {
this.parentNode.remove();
}
function clearAll() {
list.innerHTML = "";
}
body {
font-size: 10px;
font-family: Arial, Helvetica, sans-serif;
margin: 0;
background-color: antiquewhite;
}
#container {
width: 80%;
margin: auto;
padding-top: 10px;
background-color: rgb(200, 225, 225);
color: rgb(52, 48, 48);
border-radius: 10px;
}
p {
font-size: 20px;
text-align: center;
padding: 30px, 0px, 5px, 0px;
}
#formdiv {
text-align: center;
}
#item {
size: 100px;
}
#clear {
margin-top: 60px;
text-align: center;
}
li {
list-style-type: none;
font-size: 3.2em;
padding: 0.5em;
margin: 1em;
background-color: lightyellow;
border-radius: 5px;
border: 1px solid grey;
}
.trash-image {
float: right;
margin: -2px 3px 3px 3px;
vertical-align: middle;
height: 4px;
}
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<body>
<br> <br> <br>
<div id='container'>
<p>My list</p>
<br>
<div id="formdiv">
<label for="item">add this.. </label><br>
<input type="text" name="item" id="item">
<button id="add-button"> add </button>
</div>
<div id="allItems">
<ul id="list">
</ul>
</div>
<div id="clear">
<button id="clear-button"> Clear List </button><br> <br> <br>
</div>
</div>
Here's a quick example implementation of the approach I mentioned in the comments. I've just hacked it together quickly, so there's a small difference for the bin.
I've used an img (without a src) instead of a 'character' from the
font. I've styled the img to be 16x16 for the same reason. It also
makes it visible instead of being 0x0 pixels. I also set the cursor.
"use strict";
window.addEventListener('load', onLoad, false);
function onLoad(evt) {
document.querySelector('button').addEventListener('click', onAddBtnClicked, false);
}
function onAddBtnClicked(evt) {
let userText = document.querySelector('input').value;
let newLi = document.createElement('li');
newLi.textContent = userText;
newLi.addEventListener('click', onIncompleteItemClicked, false);
document.querySelector('ul').appendChild(newLi);
}
function onIncompleteItemClicked(evt) {
let clickedLi = this;
clickedLi.classList.toggle('itemComplete');
let binImg = document.createElement('img');
binImg.addEventListener('click', onBinIconClicked, false);
clickedLi.appendChild(binImg);
clickedLi.removeEventListener('click', onIncompleteItemClicked, false);
clickedLi.addEventListener('click', onCompletedItemClicked, false);
}
function onCompletedItemClicked(evt) {
let clickedLi = this;
clickedLi.classList.toggle('itemComplete');
let binImg = clickedLi.querySelector('img');
clickedLi.removeChild(binImg);
clickedLi.removeEventListener('click', onCompletedItemClicked, false);
clickedLi.addEventListener('click', onIncompleteItemClicked, false);
}
function onBinIconClicked(evt) {
let clickedBin = this;
let containingLi = clickedBin.parentNode;
containingLi.remove();
}
.itemComplete {
text-decoration: line-through;
}
li>img {
cursor: pointer;
width: 16px;
height: 16px;
}
<input value='blah-blah'></input><button>Add</button>
<ul></ul>
Add a variable indicating that the icon has been already added.
Check if icon is added on click
If yes - skip
If not - set icon
//select from DOM
let allItems = document.querySelector('#allItems');
let button = document.querySelector('#add-button');
let userInput = document.querySelector('#item');
let list = document.querySelector('#list');
let clear = document.querySelector('#clear-button');
//add event listener
button.addEventListener('click', addToList);
clear.addEventListener('click', clearAll);
//functions
function addToList() {
let newListItem = document.createElement('li');
newListItem.textContent = userInput.value;
list.appendChild(newListItem);
userInput.value = "";
// declare boolean variable
let hasTrashIcon = false
newListItem.addEventListener('click', function() {
// if has thrash icon skip
if (hasTrashIcon) return
// set has trash icon
hasTrashIcon = true
this.style.textDecoration = 'line-through';
let itemButton = document.createElement('a');
itemButton.setAttribute('href', '#');
itemButton.classList.add('trash-image');
itemButton.innerHTML = '<i class="material-icons">delete</i><a/>';
itemButton.addEventListener("click", deleteOneItem);
this.appendChild(itemButton);
});
}
function deleteOneItem() {
this.parentNode.remove();
}
function clearAll() {
list.innerHTML = "";
}
body {
font-size: 10px;
font-family: Arial, Helvetica, sans-serif;
margin: 0;
background-color: antiquewhite;
}
#container {
width: 80%;
margin: auto;
padding-top: 10px;
background-color: rgb(200, 225, 225);
color: rgb(52, 48, 48);
border-radius: 10px;
}
p {
font-size: 20px;
text-align: center;
padding: 30px, 0px, 5px, 0px;
}
#formdiv {
text-align: center;
}
#item {
size: 100px;
}
#clear {
margin-top: 60px;
text-align: center;
}
li {
list-style-type: none;
font-size: 3.2em;
padding: 0.5em;
margin: 1em;
background-color: lightyellow;
border-radius: 5px;
border: 1px solid grey;
}
.trash-image {
float: right;
margin: -2px 3px 3px 3px;
vertical-align: middle;
height: 4px;
}
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<body>
<br> <br> <br>
<div id='container'>
<p>My list</p>
<br>
<div id="formdiv">
<label for="item">add this.. </label><br>
<input type="text" name="item" id="item">
<button id="add-button"> add </button>
</div>
<div id="allItems">
<ul id="list">
</ul>
</div>
<div id="clear">
<button id="clear-button"> Clear List </button><br> <br> <br>
</div>
</div>
I have a couple of buttons with one button that should disable all others. I wrote a code that selects buttons by adding a class and when clicked again deletes the class. It also pushed the value into an array. I want to make the no preference button in my code to delete a certain class from all buttons, except for the no preference button.
I already made it so it deletes everything in the array when it is clicked, but I just gotta delete the class from all buttons.
Code:
let div = document.getElementById('buttonDiv');
let arr = [];
div.addEventListener("click", function (event) {
let tgt = event.target;
function SelectedClass() {
if (tgt.classList.contains('Selected')) {
tgt.classList.remove('Selected');
} else {
tgt.classList.add('Selected');
}
}
if (tgt.classList.contains('buttons')) {
if (arr.indexOf(tgt.value) === -1) {
if (tgt.value === 'Ignore') {
if (tgt.classList.contains('Selected')) {
tgt.classList.remove('Selected');
} else {
tgt.classList.add('Selected');
arr = [];
}
} else {
SelectedClass();
arr.push(tgt.value);
}
} else {
arr.splice(arr.indexOf(tgt.value), 1);
SelectedClass();
}
}
console.log(arr);
})
.buttondiv {
position: relative;
width: 200px;
height: 675px;
margin-left: 50%;
transform: translateX(-50%);
margin-top: 50px;
}
.buttons {
width: 275px;
height: 50px;
display: inline-block;
margin-bottom: 15px;
;
border: 2px solid black;
border-radius: 3px;
background-color: white;
color: black;
}
.Selected {
background-color: orangered;
color: white;
border: none;
}
<div class="buttondiv" id="buttonDiv">
<button value="btn1" class="buttons">1</button>
<button value="btn2" class="buttons">2</button>
<button value="btn3" class="buttons">3</button>
<button value="btn4" class="buttons">4</button>
<button value="Ignore" class="buttons">No Preference</button>
</div>
I tried doing it with a for loop and a queryselector, but that didn't work. Does anybody know a solution?
If I understand you correctly the code can be simplified. See example below where different actions are taken place based on weather you press the no preference button or an other button. For this I added a class to the no preference button so we can easily query on that.
let div = document.getElementById('buttonDiv');
let arr = [];
div.addEventListener("click", function (event) {
let tgt = event.target;
if (tgt.classList.contains('buttons')) {
//when no preference is clicked remove all selected classes and empty the array
if(tgt.value === 'Ignore') {
event.currentTarget.querySelectorAll('.buttons').forEach((el) => {
el.classList.remove('Selected');
arr = [];
});
}
//when other button is clicked removed the selected class from the no preference button and push the current value to the array
else {
event.currentTarget.querySelector('.buttons.ignore').classList.remove('Selected');
arr.push(tgt.value);
}
//always add selected class to the current button.
tgt.classList.add('Selected');
}
console.log(JSON.stringify(arr));
})
.buttondiv {
position: relative;
width: 200px;
height: 675px;
margin-left: 50%;
transform: translateX(-50%);
margin-top: 50px;
}
.buttons {
width: 275px;
height: 50px;
display: inline-block;
margin-bottom: 15px;
;
border: 2px solid black;
border-radius: 3px;
background-color: white;
color: black;
}
.Selected {
background-color: orangered;
color: white;
border: none;
}
<div class="buttondiv" id="buttonDiv">
<button value="btn1" class="buttons">1</button>
<button value="btn2" class="buttons">2</button>
<button value="btn3" class="buttons">3</button>
<button value="btn4" class="buttons">4</button>
<button value="Ignore" class="buttons ignore">No Preference</button>
</div>
As you can see from my example i add a querySelectorAll to all button except for ignore button, when user click to "No Preference" forEach will disabled or enabled all.
let div = document.getElementById('buttonDiv');
let arr = [];
div.addEventListener("click", function(event) {
let tgt = event.target;
function SelectedClass() {
if (tgt.classList.contains('Selected')) {
tgt.classList.remove('Selected');
} else {
tgt.classList.add('Selected');
}
}
if (tgt.classList.contains('buttons')) {
if (arr.indexOf(tgt.value) === -1) {
if (tgt.value === 'Ignore') {
if (tgt.classList.contains('Selected')) {
tgt.classList.remove('Selected');
document.querySelectorAll('button:not(.ignore)').forEach(el => {
el.disabled = false;
});
} else {
tgt.classList.add('Selected');
document.querySelectorAll('button:not(.ignore)').forEach(el => {
if (el.classList.contains('Selected')) {
el.classList.remove('Selected');
}
el.disabled = true;
});
arr = [];
}
} else {
SelectedClass();
arr.push(tgt.value);
}
} else {
arr.splice(arr.indexOf(tgt.value), 1);
SelectedClass();
}
}
console.log(arr);
})
.buttondiv {
position: relative;
width: 200px;
height: 675px;
margin-left: 50%;
transform: translateX(-50%);
margin-top: 50px;
}
.buttons {
width: 275px;
height: 50px;
display: inline-block;
margin-bottom: 15px;
;
border: 2px solid black;
border-radius: 3px;
background-color: white;
color: black;
}
.Selected {
background-color: orangered;
color: white;
border: none;
}
<div class="buttondiv" id="buttonDiv">
<button value="btn1" class="buttons">1</button>
<button value="btn2" class="buttons">2</button>
<button value="btn3" class="buttons">3</button>
<button value="btn4" class="buttons">4</button>
<button value="Ignore" class="buttons ignore">No Preference</button>
</div>
Reference:
Document.querySelectorAll()
disabled
const addBtn = document.querySelector(".add");
const modal = document.querySelector(".modal__container");
const library = document.querySelector(".library__container");
const submitBook = document.querySelector(".add__book");
const deleteBtn = document.querySelector(".fas fa-trash-alt");
//Modal inputs
const modalTitle = document.querySelector("#title");
const modalAuthor = document.querySelector("#author");
const modalPages = document.querySelector("#pages");
const isRead = document.querySelector("#read-status");
//Toggle Modal
const hideModal = () => {
modal.style.display = "none";
};
const showModal = () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", (e) => {
e.preventDefault();
hideModal();
});
};
addBtn.addEventListener("click", showModal);
let myLibrary = [];
let index = 0;
function Book(title, author, pages, read) {
this.title = title,
this.author = author,
this.pages = pages,
this.read = read
}
submitBook.addEventListener("click", addBookToLibrary);
function addBookToLibrary(e) {
e.preventDefault();
let bookTitle = modalTitle.value;
let bookAuthor = modalAuthor.value;
let bookPages = modalPages.value;
let bookStatus = isRead.checked;
//Display error message if inputs are empty
if (bookTitle === "" || bookAuthor === "" || bookPages === "") {
const errorMessage = document.querySelector(".error__message--container");
hideModal();
errorMessage.style.display = "block";
const errorBtn = document.querySelector(".error-btn");
errorBtn.addEventListener("click", () => {
errorMessage.style.display = "none";
showModal();
})
} else {
let book = new Book(bookTitle, bookAuthor, bookPages, bookStatus);
myLibrary.push(book);
hideModal();
render();
}
}
function render() {
library.innerHTML = "";
for (let i = 0; i < myLibrary.length; i++) {
library.innerHTML +=
'<div class="book__container">' +
'<div class="book">' +
'<div class="title__content">' +
'<span class="main">Title : </span><span class="book__title">' +` ${myLibrary[i].title}`+'</span>' +
'</div>' +
'<div class="author__content">' +
'<span class="main">Author : </span><span class="book__author">'+` ${myLibrary[i].author}`+'</span>' +
'</div>' +
'<div class="pages__content">' +
'<span class="main">Pages : </span><span class="book__pages">'+` ${myLibrary[i].pages}`+'</span>' +
'</div>' +
'<div class="book__read-elements">' +
'<span class="book__read">I read it</span>' +
'<i class="fas fa-check"></i>' +
'<a href="#"><i class="fas fa-times"></i>' +
'<i class="fas fa-trash-alt"></i>' +
'</div>' +
'</div>' +
'</div>'
readStatus(myLibrary[i].checked)
}
modalTitle.value = "";
modalAuthor.value = "";
modalPages.value = "";
isRead.checked = false;
}
function readStatus(bookStatus) {
const bookStatusContainer = document.querySelector(".book__read");
if (bookStatus) {
bookStatusContainer.classList.add("yes");
bookStatusContainer.textContent = "I read it";
bookStatusContainer.style.color = "rgb(110, 176, 120)";
} else {
bookStatusContainer.classList.add("no");
bookStatusContainer.textContent = "I have not read it";
bookStatusContainer.style.color = "rgb(194, 89, 89)";
}
}
#import url('https://fonts.googleapis.com/css2?family=Poppins:wght#300;400;600&display=swap');
:root {
--light-gray: #dededef3;
--title-color: #333756;
--main-color: #c6c6c6f3;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
font-family: 'Poppins', sans-serif;
background-color: var(--light-gray);
}
header {
text-align: center;
padding-top: 4rem;
color: var(--title-color);
text-transform: uppercase;
letter-spacing: 4px;
}
button {
margin: 1rem;
padding: 0.8rem 2rem;
font-size: 14px;
border-radius: 25px;
background: white;
color: #333756;
font-weight: 600;
border: none;
cursor: pointer;
transition: 0.6s all ease;
}
:focus {
/*outline: 1px solid white;*/
}
button:hover {
background: var(--title-color);
color: white;
}
.add__book:hover,
.cancel:hover {
background: var(--main-color);
color: var(--title-color)
}
.all,
.books__read,
.books__not-read {
border-radius: 0;
text-transform: uppercase;
letter-spacing: 0.1rem;
background: var(--light-gray);
border-bottom: 4px solid var(--title-color)
}
.library__container {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.book__container {
display: flex;
margin: 2rem 2rem;
}
.modal__container {
display: none;
position: fixed;
z-index: 4;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
padding-top: 0px;
}
.book,
.modal {
padding: 2rem 2rem;
border-radius: 15px;
background: #333756;
line-height: 3rem;
}
.modal {
position: relative;
width: 50%;
margin: 0 auto;
margin-top: 8rem;
}
.modal__content {
display: flex;
flex-direction: column;
}
label {
color: white;
margin-right: 1rem;
}
input {
padding: 0.5rem;
font-size: 14px;
}
.book__read-elements {
display: flex;
justify-content: space-between;
}
.main,
i {
color: white;
pointer-events: none;
margin: 0.5rem;
}
.book__title,
.book__author,
.book__pages,
.book__read {
color: var(--main-color)
}
.error__message--container {
display: none;
position: fixed;
z-index: 4;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
.error__message--modal {
position: relative;
margin: 0 auto;
margin-top: 10rem;
width:40%;
}
.error {
display: flex;
flex-direction: column;
align-items: center;
color: rgb(101, 3, 3);
font-size: 20px;
font-weight: bold;
background: rgb(189, 96, 96);
padding: 3rem 5rem;
border-radius: 10px;
}
.error-btn {
color: rgb(101, 3, 3);
font-weight: bold;
}
.error-btn:hover {
color: white;
background: rgb(101, 3, 3);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" integrity="sha256-2XFplPlrFClt0bIdPgpz8H7ojnk10H69xRqd9+uTShA=" crossorigin="anonymous" />
<link rel="stylesheet" href="styles.css">
<title>Library</title>
</head>
<body>
<header>
<h1>My Library</h1>
<button class="add">Add New Book</button>
<div class="buttons">
<button class="all">View All</button>
<button class="books__read">Read</button>
<button class="books__not-read">Not Read</button>
</div>
</header>
<div class="error__message--container">
<div class="error__message--modal">
<div class="error">
<p>Complete the form!</p>
<button class ="error-btn">Ok</button>
</div>
</div>
</div>
<!--Modal-->
<form class="modal__container">
<div class="modal">
<div class="modal__content">
<label for="">Title:</label>
<input type="text" id="title">
</div>
<div class="modal__content">
<label for="">Author:</label>
<input type="text" id="author">
</div>
<div class="modal__content">
<label for="">Pages:</label>
<input type="number" id="pages">
</div>
<div>
<label for="read-status">Check the box if you've read this book</label>
<input type="checkbox" id="read-status" value ="check">
</div>
<button class="add__book">Add</button>
<button class="cancel">Cancel</button>
</div>
</form>
<!--End of Modal-->
<div class="library__container"></div>
<script src="script.js"></script>
</body>
</html>
I'm new to OOP and I'm struggling.
I'm building a library where you can add a book with the title, author nr of pages and if you've read it or not. When I add the first book if I check the box it displays that to book is not read(which is false). When I add a new book the read functionality is not applied to that book at all. I have no idea how to fix it
In this function you are checking the status if isRead which is incorrect.
Do this
Call the readStatus function inside the for loop
Pass the current parameter readStatus(myLibrary[i].checked)
Modify readStatus as shown below
function readStatus(status) {
const bookReadStatus = document.querySelector(".book__read");
if (status) {
bookReadStatus.classList.add("yes");
bookReadStatus.textContent = "I read it";
bookReadStatus.style.color = "rgb(110, 176, 120)";
} else {
bookReadStatus.classList.add("no");
bookReadStatus.textContent = "I have not read it";
bookReadStatus.style.color = "rgb(194, 89, 89)";
}
}
I have several inputs, which I am copying n times and I am trying to add numeric values from inputs in the array. I marked word "add" because an array may be already filled by other numbers.
I'm trying to apply method from UncleDave's answer here:
JavaScript - Add Value from input box to array
Example:
I have an array:
var exampleArray = [[1, 1.5], [1, 1], [0, 25.5]];
What I have done:
Wrote value 25 in first input. Wrote value 1.5 in the second input.
Create two new inputs.
Wrote value 25.4 in first input. Wrote value 1 in the second input.
Pressed button for adding into an array.
What I am trying to reach:
var exampleArray = [[1, 1.5], [1, 1], [0, 25.5], [25, 1.5], [25.4, 1]];
What I have reached:
"Udefined" in the console log.
Here Is jsfiddle link with my code: https://jsfiddle.net/aectann/k3qwoz0g/12/
updated with snippet (ok, it was not hard at this time, MTCoster, thank you for advice):
var totalInputs;
var myInputs;
var tmpARR = [];
var count = 0,
types = ['t', 'C' /*, 'Q'*/ ],
button = document.getElementById('button');
button.addEventListener("click", createInputs, false);
function createInputs() {
if (!validInput()) {
return;
}
count += 1;
createInput(count);
}
function createInput(count) {
totalInputs = document.getElementsByClassName('myInput').length;
var existingNode = document.getElementsByClassName('myInput')[totalInputs - 1];
types.forEach(function(type) {
var newNode = existingNode.cloneNode();
newNode.value = null;
newNode.id = type + +count;
newNode.placeholder = 'Placeholder ' + type;
newNode.dataset.id = 'id' + count;
appendNode(newNode);
})
}
function appendNode(node) {
document.querySelector('#div').appendChild(node);
}
function validInput() {
myInputs = document.getElementsByClassName('myInput');
var valid = true;
Array.prototype.slice.call(myInputs).forEach(function(input) {
input.classList.remove('error');
if (!input.value) {
input.classList.add('error');
valid = false;
}
});
return valid;
}
function removeError(event) {
event.classList.remove('error');
}
function guardarNumeros() {
boxvalue = document.getElementsByClassName('myInput').value;
tmpARR.push(boxvalue);
console.log(tmpARR);
return false;
}
#title {
font-family: 'Times New Roman', Times, serif;
font-size: 200%;
}
#step {
font-size: 15pt;
clear: both;
}
#step2 {
font-size: 15pt;
clear: both;
}
#step3 {
font-size: 15pt;
clear: both;
}
summary {
background: #009688;
color: #fff;
padding: 5px;
margin-bottom: 3px;
text-align: left;
cursor: pointer;
padding: 5px;
width: 250px;
/*background-color: #4CAF50;*/
}
summary:hover {
background: #008999;
}
.displayBlockInline-Flex {
display: inline-flex;
}
#margin20 {
margin-left: 20px;
vertical-align: middle;
}
#container {
width: auto;
height: auto;
margin: 0 auto;
display: none;
}
a.myButton {
color: #fff;
/* цвет текста */
text-decoration: none;
/* убирать подчёркивание у ссылок */
user-select: none;
/* убирать выделение текста */
background: rgb(212, 75, 56);
/* фон кнопки */
outline: none;
/* убирать контур в Mozilla */
text-align: center;
cursor: pointer;
width: 150px;
padding-bottom: 11px;
}
a.myButton:hover {
background: rgb(232, 95, 76);
}
/* при наведении курсора мышки */
a.myButton:active {
background: rgb(152, 15, 0);
}
/* при нажатии */
.button1 {
/* background-color: #fc0; /* Цвет фона слоя */
/* padding: 5px; /* Поля вокруг текста */
float: left;
/* Обтекание по правому краю */
width: 450px;
/* Ширина слоя */
}
.button2 {
/* background-color: #c0c0c0; /* Цвет фона слоя */
/* padding: 5px; /* Поля вокруг текста */
width: 650px;
/* Ширина слоя */
float: right;
/* Обтекание по правому краю */
}
.clear {
clear: left;
/* Отмена обтекания */
}
.wrapper {
width: 1100px;
margin-left: 20px;
}
/*inputs*/
#div {
text-align: center;
}
.myInput {
height: 40px;
outline: none;
width: auto;
border: 1px solid #999;
border-radius: 4px;
padding: 5px 10px;
margin: 5px;
display: inline-block;
}
.myInput.error {
border: 1px solid red;
}
#action {
margin: 10px 0;
text-align: center;
}
#button {
width: 190px;
height: 40px;
background: #009688;
color: #fff;
font-weight: 600;
font-size: 13px;
border-radius: 4px;
border: none;
/* text-transform: uppercase;*/
outline: none;
cursor: pointer;
}
#button:hover {
background: #008999;
}
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<center>
<input type="text" class="myInput" name="nameAlloy" placeholder="Name">
</center>
<div id="div">
<!--<form onsubmit="return guardarNumeros()">-->
<div id="action">
<button type="button" id="button">Add more inputs</button>
</div>
<input type="number" onkeypress="removeError(this)" class="myInput" data-id="id0" name="value[]" placeholder="Enter value 1">
<input type="number" onkeypress="removeError(this)" class="myInput" data-id="id0" name="value[]" placeholder="Enter value 2">
<div id="action">
<input type="submit" id="button" value="Add to array">
</div>
<!--</form>-->
</div>
The getElementsByClassName() method returns a collection of all
elements in the document with the specified class name, as a NodeList
object.
You can iterate over the collections for all the numeric inputs and update your result. But I would suggest is to create another class for numeric inputs, so you wouldn't need to check for the type of the input and would keep your code generic.
You can try this code and feel free to clear your doubts in the comments.
function guardarNumeros() {
boxvalue = document.getElementsByClassName('myInput');
i = 0;
while (i < boxvalue.length) {
if (boxvalue[i].type == "number") {
if (boxvalue[i+1] && boxvalue[i+1].type == "number") {
tmp = [boxvalue[i].value, boxvalue[i+1].value]
tmpARR.push(tmp);
i+=2;
}
} else {
i++;
}
}
console.log(tmpARR);
return false;
}
The error is in "guardarNumeros" function because getElementsByClassName returns a collection and collection does not have a "value" property.
try this code
function guardarNumeros() {
const inputs = [...document.getElementsByClassName('myInput')];
const inputNumberArr = inputs.filter(x => x.type === 'number');
// tmpARR = [];
for (let i = 0; i < inputNumberArr.length; i++) {
const element = inputNumberArr[i];
if (i % 2 === 0) {
tmpARR.push([element.value]);
} else if (tmpARR[tmpARR.length -1] instanceof Array) {
tmpARR[tmpARR.length -1].push(element.value);
} else {
tmpARR.push([element.value]);
}
}
return false;
}
Hello I'm stuck on how to add category for my to do list. When you click on Button of category need change class name. I don't understand how to correctly write if/else statement when button is clicked.
plan how it need to work
Write task name
Choose Category
Add new task
May be somebody can help me out ore give some advice how to solve this problem!
Sorry for my english and if my question is to badly explained!
var toDoList = function() {
var addNewTask = function() {
var input = document.getElementById("taks-input").value,
itemTexts = input,
colA = document.getElementById('task-col-a').children.length,
colB = document.getElementById('task-col-b').children.length,
taskBoks = document.createElement("div"),
work = document.getElementById("work"),
Category = "color-2",
taskCount = 1;
if (work.onclick === true) {
var Category = "color";
}
taskBoks.className = "min-box";
taskBoks.innerHTML = '<div class="col-3 chack" id="task_' + (taskCount++) + '"><i class="fa fa-star"></i></div><div class="col-8 task-text" id="taskContent"><p>' + itemTexts + '</p><span id="time-now"></span></div><div class="col-1 ' + (Category) + '"></div>'
if (colB < colA) {
var todolist = document.getElementById("task-col-b");
} else {
var todolist = document.getElementById("task-col-a");
}
//todolist.appendChild(taskBoks);
todolist.insertBefore(taskBoks, todolist.childNodes[0]);
},
addButton = function() {
var btn2 = document.getElementById("add-task-box");
btn2.onclick = addNewTask;
};
addButton()
}
toDoList();
p {
padding: 20px 20px 20px 45px;
}
.chack {
background-color: #4c4b62;
height: 100%;
width: 40px;
}
.task-text {
background-color: #55566e;
height: 100%;
width: 255px;
}
.color {
width: 5px;
height: 100%;
background-color: #fdcd63;
float: right;
}
.color-2 {
width: 5px;
height: 100%;
background-color: red;
float: right;
}
.color-3 {
width: 5px;
height: 100%;
background-color: purple;
float: right;
}
.task {
height: 100px;
width: 300px;
border: 1px solid #fff;
float: left;
}
.chack,
.task-text {
float: left;
}
.add-new-task {
margin-bottom: 50px;
height: 80px;
width: 588px;
background-color: rgb(85, 86, 110);
padding-top: 30px;
padding-left: 15px;
}
.min-box {
height: 100px;
border-bottom: 1px solid #fff;
}
.center {
padding-top: 20px;
padding-left: 50px;
}
.fa-star {
padding-left: 14px;
padding-top: 100%;
}
#add-task-box {
float: right;
margin-right: 10px;
margin-top: -7px;
border: none;
background-color: rgb(255, 198, 94);
padding: 10px;
}
#taks-input {
height: 30px;
width: 350px;
margin-top: -7px;
}
.category {
margin-top: 10px;
}
<div class="container">
<div class="add-new-task">
<input type="text" id="taks-input">
<button id="add-task-box">Add New Task box</button>
<div class="category">
<button class="catBtn" id="work">Work</button>
<button class="catBtn" id="home">Home</button>
<button class="catBtn" id="other">Other</button>
</div>
</div>
<div class="lg-task" id="bigTask"></div>
<div class="task" id="task-col-a"></div>
<div class="task" id="task-col-b"></div>
</div>
you need to bind click event to your buttons and store that value in Category, so in you js add this
var toDoList = function() {
// set to default
var Category = "color-3";
// attach event to buttons
var catButtons = document.getElementsByClassName("catBtn");
// assign value based on event
var myCatEventFunc = function() {
var attribute = this.getAttribute("id");
if (attribute === 'work') {
Category = 'color';
} else if (attribute === 'home') {
Category = 'color-2';
}
};
for (var i = 0; i < catButtons.length; i++) {
catButtons[i].addEventListener('click', myCatEventFunc, false);
}
Demo: Fiddle
and remove this code from addNewTask function
if (work.onclick === true) {
var Category = "color";
}
It is a bit hard to understand what you are doing, what you are going for (a module of some kind?). You were not that far away from a working state.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Task</title>
<style>
p {
padding: 20px 20px 20px 45px;
}
.chack {
background-color: #4c4b62;
height: 100%;
width: 40px;
}
.task-text {
background-color: #55566e;
height: 100%;
width: 255px;
}
.color {
width: 5px;
height: 100%;
background-color: #fdcd63;
float: right;
}
.color-2 {
width: 5px;
height: 100%;
background-color: red;
float: right;
}
.color-3 {
width: 5px;
height: 100%;
background-color: purple;
float: right;
}
.task {
height: 100px;
width: 300px;
border: 1px solid #fff;
float: left;
}
.chack,
.task-text {
float: left;
}
.add-new-task {
margin-bottom: 50px;
height: 80px;
width: 588px;
background-color: rgb(85, 86, 110);
padding-top: 30px;
padding-left: 15px;
}
.min-box {
height: 100px;
border-bottom: 1px solid #fff;
}
.center {
padding-top: 20px;
padding-left: 50px;
}
.fa-star {
padding-left: 14px;
padding-top: 100%;
}
#add-task-box {
float: right;
margin-right: 10px;
margin-top: -7px;
border: none;
background-color: rgb(255, 198, 94);
padding: 10px;
}
#taks-input {
height: 30px;
width: 350px;
margin-top: -7px;
}
.category {
margin-top: 10px;
}
</style>
<script>
var toDoList = function() {
var addNewTask = function() {
var input = document.getElementById("taks-input").value,
itemTexts = input,
colA = document.getElementById('task-col-a').children.length,
colB = document.getElementById('task-col-b').children.length,
taskBoks = document.createElement("div"),
work = document.getElementById("work"),
Category = "color-2",
taskCount = 1;
if (work.onclick === true) {
Category = "color";
}
taskBoks.className = "min-box";
taskBoks.innerHTML = '<div class="col-3 chack" id="task_'
+ (taskCount++) +
'"><i class="fa fa-star"></i></div><div class="col-8 task-text" id="taskContent"><p>'
+ itemTexts +
'</p><span id="time-now"></span></div><div class="col-1 '
+ (Category) + '"></div>'
if (colB < colA) {
var todolist = document.getElementById("task-col-b");
} else {
var todolist = document.getElementById("task-col-a");
}
//todolist.appendChild(taskBoks);
todolist.insertBefore(taskBoks, todolist.childNodes[0]);
},
// I don't know what to do with that?
addButton = function() {
var btn2 = document.getElementById("add-task-box");
btn2.onclick = addNewTask();
};
// return the stuff you want to have public
return {
addNewTask:addNewTask
};
}
var f;
// wait until all HTML is loaded and put the stuff from above into the variable `f`
// you can call it with f.someFunction() in your case f.addNewTask()
window.onload = function(){
f = toDoList();
}
</script>
</head>
<body>
<div class="container">
<div class="add-new-task">
<input type="text" id="taks-input">
<button id="add-task-box" onclick="f.addNewTask()">Add New Task box</button>
<div class="category">
<button class="catBtn" id="work" >Work</button>
<button class="catBtn" id="home">Home</button>
<button class="catBtn" id="other">Other</button>
</div>
</div>
<div class="lg-task" id="bigTask"></div>
<div class="task" id="task-col-a"></div>
<div class="task" id="task-col-b"></div>
</div>
</body>
</html
I hope you understood what I did?