How to make application remember To-do data - javascript

I have looked about for quite a while now, and nothing seems to work or fit my current problem.
I am creating a To-Do project and I want chrome to remember your To-Dos, even if you refresh the browser.
I have tried a few methods, but this is where I am at the moment. The javascript updates the localstorage everytime the 'createPost' function is called, and then it is loaded by the code at the bottom (i flagged the relavant lines).
View the updated demo here: https://dominicody.netlify.app/todo/
( the main website isnt finished so dont judge please lol)
let form = document.getElementById("todo-form");
let input = document.getElementById("input");
let msg = document.getElementById("msg");
let todos = document.getElementById("todos");
let right = document.getElementById("right")
let noToDo = document.getElementById("notodo")
let counter = 0; /* new line */
form.addEventListener("submit", e => {
e.preventDefault();
console.log("button clicked");
formValidation();
});
let formValidation = () => {
if (input.value === "") {
msg.innerHTML = "To-Do cannot be blank";
} else {
msg.innerHTML = "";
acceptData();
}
};
let data = [];
let acceptData = () => {
data = [...data, {
"text": input.value
}];
input.value = "";
localStorage.setItem('todoItemsRef', JSON.stringify(data));
createToDo(data[data.length - 1]);
};
let createToDo = () => {
counter++; /* new line */
todos.innerHTML += `
<div>
<p>${data.text}</p>
<span class="options">
<i onClick="completedToDo(this)" class='bx bx-check-circle'></i>
<i onClick="editToDo(this)" class='bx bx-edit-alt'></i>
<i onClick="deleteToDo(this)" class='bx bx-trash' ></i>
</span>
</div>
`;
input.value = "";
};
let completedToDo = (e) => {
e.parentElement.parentElement.classList.toggle('completed')
}
let deleteToDo = (e) => {
e.parentElement.parentElement.remove();
counter--;
if (counter === 0) {
showNoToDo();
}
};
let editToDo = (e) => {
input.value = e.parentElement.previousElementSibling.innerHTML;
e.parentElement.parentElement.remove();
};
let hideNoToDo = () => {
noToDo.classList.add('hidden')
form.classList.remove('form-reg-position')
}
let showNoToDo = () => {
noToDo.classList.remove('hidden')
form.classList.add('form-reg-position')
}
/* localStorage.setItem('todoItemsRef', JSON.stringify(data)); */
document.addEventListener('DOMContentLoaded', () => {
const ref = localStorage.getItem('todoItemsRef');
if (ref) {
data = JSON.parse(ref);
data.forEach(t => {
createToDo(t);
});
}
});
#import url('https://fonts.googleapis.com/css2?family=Kanit:wght#100;200;300;400;500;600;700;800;900&family=League+Spartan:wght#200;300;400;500;600;700;800;900&family=Noto+Serif:wght#400;700&display=swap');
:root {
--primary-color: rgb(240, 69, 114);
--primary-color-ligh: rgb(220, 100, 124);
--secondary-color: rgb(25, 24, 44);
--secondary-color-ligh: rgb(64, 64, 83);
--white: rgb(255, 255, 255);
--primary-font: 'League Spartan', sans-serif;
--secondary-font: 'Noto Serif', serif;
--kanit-font: 'Kanit', sans-serif;
--swiper-theme-color: rgb(240, 69, 114);
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'League Spartan', sans-serif;
}
body {
width: 100%;
background-color: #fff;
max-height: 100%;
overflow: hidden;
}
h1 {
position: absolute;
top: 10%;
left: 50%;
transform: translateX(-50%);
font-size: 4rem;
opacity: 0.5;
}
.todo-main {
position: absolute;
top: 30%;
left: 50%;
width: 75%;
height: 70%;
transform: translateX(-50%);
overflow-y: auto;
overflow-x: hidden;
}
.no-todo {
position: absolute;
top: 23%;
left: 50%;
transform: translateX(-50%);
text-align: center;
}
.no-todo img {
width: 150px;
}
.no-todo p {
font-family: var(--primary-font);
font-weight: 600;
font-size: 1.3rem;
margin-top: 24px;
margin-bottom: 10px;
}
.no-todo p2 {
font-family: var(--primary-font);
font-weight: 600;
font-size: 1.2rem;
color: #000;
opacity: 0.6;
}
.no-todo.hidden {
display: none;
}
form {
margin-left: 100%;
transform: translateX(-50%);
width: 100%;
;
}
.textarea {
margin-top: 24px;
min-width: 95%;
max-width: 95%;
min-height: 40px;
max-height: 40px;
display: flex;
outline: none;
border: none;
border: 2px solid var(--secondary-color);
border-radius: 5px;
padding: 10px;
font-size: 20px;
font-weight: 400;
margin-top: 5px;
color: #000;
transform: translateX(-50%);
overflow-y: hidden;
transition-duration: 0.7s;
}
.form-reg-position {
transform: translateY(250%) translateX(-50%);
transition-duration: 0.7s;
}
.textarea::placeholder {
color: #000;
}
#todos div {
display: flex;
align-items: center;
justify-content: space-between;
transform: translateX(-50%);
font-family: var(--kanit-font);
font-weight: 500;
font-size: 1.2rem;
margin-bottom: 15px;
width: 95%;
margin-left: 50%;
border: 2px solid var(--secondary-color);
border-radius: 5px;
padding: 8px;
color: #000;
}
#todos div.completed {
background-color: #00FF00;
color: #000;
}
.options {
display: flex;
gap: 25px;
color: var(--secondary-color);
}
i {
cursor: pointer;
}
#msg {
position: absolute;
left: 0%;
transform: translateX(-50%);
color: red;
margin-bottom: 10px;
}
/* TOP NAV */
.top-nav-img-only {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 8%;
display: flex;
align-items: center;
z-index: 99;
}
.top-nav-img-only a img {
position: absolute;
top: 20%;
left: 5%;
height: 60%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>bydom</title>
<link rel="stylesheet" href="/todo/todo.css">
<link href='https://unpkg.com/boxicons#2.1.2/css/boxicons.min.css' rel='stylesheet'>
</head>
<body>
<div class="top-nav-img-only">
<a href="/">
<img src="/images/logo.png">
</a>
</div>
<h1>todos</h1>
<div class="no-todo" id="notodo">
<img src="/svg/checklist.svg">
<p>Add your first To-Do</p>
<p2>What's first on your list?</p2>
</div>
<div class="todo-main">
<form class="form-reg-position" id="todo-form">
<br><br>
<input class="textarea" type="text" name="todo" id="input" placeholder="Add new To-do"></input>
<br><br>
<div id="msg"></div>
</form>
<div id="todos">
</div>
</div>
<script src="/todo/todo.js"></script>
</body>
</html>

The first thing you need to do is update Local Storage whenever you change something in the tasks.
You can create a function to update Local Storage and this function will be called whenever you update something in the tasks, when you mark it as complete and when you delete a task.
const updateLocalStorage = () => {
}
This function will pick up all the tasks that are on the screen
Add task in Local Storage
localStorage.setItem("tasks", JSON.stringify([...JSON.parse(localStorage.getItem("tasks") || "[]"), { task: task.value, completed: false }]));

There seem to be a few issues with the example/code provided, but the main thing seems to be how you were trying to store the todo list. Your list was an array called data and when each new todo item was created, it would overwrite the previous value of data["text"]. Also, because of the way you structured your array (which was more like an object), you could not stringify the list.
So the first fix was to make your array an array of objects [{},{}]. This would allow each item on the list to have its own text value.
Another issue was calling a function that didn't exist renderTodo. (OP did mention in a comment this was later corrected).
There are also a lot of weird ways some of the code is structured, but with all of that aside, here is a basic example of what you seem to need. I removed functions and code that wasn't necessary for the question asked. This solution will save your todo list in localStorage and load it when the page loads. Anything else is a different question/topic.
let form = document.getElementById("todo-form"),
input = document.getElementById("input"),
msg = document.getElementById("msg"),
todos = document.getElementById("todos"),
data = [];
form.addEventListener("submit", e => {
e.preventDefault();
formValidation();
});
let formValidation = () => {
if (input.value === "") {
msg.innerHTML = "To-Do cannot be blank";
} else {
msg.innerHTML = "";
acceptData();
}
};
let acceptData = () => {
data = [...data, {"text": input.value}];
input.value = "";
localStorage.setItem('todoItemsRef', JSON.stringify(data));
renderTodo(data[data.length-1]);
};
let renderTodo = (t) => {
let todo = document.createElement("div");
todo.innerHTML = `<p>${t.text}</p>`;
todos.append(todo);
};
document.addEventListener('DOMContentLoaded', () => {
const ref = localStorage.getItem('todoItemsRef');
if(ref) {
data = JSON.parse(ref);
data.forEach(t => {
renderTodo(t);
});
}
});
:root {
--primary-color: rgb(240, 69, 114);
--primary-color-ligh: rgb(220, 100, 124);
--secondary-color: rgb(25, 24, 44);
--secondary-color-ligh: rgb(64, 64, 83);
--white: rgb(255, 255, 255);
--primary-font: 'League Spartan', sans-serif;
--secondary-font: 'Noto Serif', serif;
--kanit-font: 'Kanit', sans-serif;
--swiper-theme-color: rgb(240, 69, 114);
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'League Spartan', sans-serif;
}
body {
width: 100%;
background-color: #fff;
max-height: 100%;
overflow: hidden;
}
h1 {
position: absolute;
top: 10%;
left: 50%;
transform: translateX(-50%);
font-size: 4rem;
opacity: 0.5;
}
.todo-main {
position: absolute;
top: 30%;
left: 50%;
width: 75%;
height: 70%;
transform: translateX(-50%);
overflow-y: auto;
overflow-x: hidden;
}
.textarea {
margin-top: 24px;
min-width: 95%;
max-width: 95%;
min-height: 40px;
max-height: 40px;
display: flex;
outline: none;
border: none;
border: 2px solid var(--secondary-color);
border-radius: 5px;
padding: 10px;
font-size: 20px;
font-weight: 400;
margin-top: 5px;
color: #000;
transform: translateX(-50%);
overflow-y: hidden;
transition-duration: 0.7s;
}
form {
margin-left: 100%;
transform: translateX(-50%);
width: 100%;
}
#todos div {
display: flex;
align-items: center;
justify-content: space-between;
transform: translateX(-50%);
font-family: var(--kanit-font);
font-weight: 500;
font-size: 1.2rem;
margin-bottom: 15px;
width: 95%;
margin-left: 50%;
border: 2px solid var(--secondary-color);
border-radius: 5px;
padding: 8px;
color: #000;
}
<h1>todos</h1>
<div class="todo-main">
<form class="form-reg-position" id="todo-form">
<br><br>
<input class="textarea" type="text" name="todo" id="input" placeholder="Add new To-do">
<br><br>
<div id="msg"></div>
</form>
<div id="todos"></div>
</div>
NOTE This example will not run on Stack Overflow because of a lack of access to the localStorage object.
EDIT I also have a relevant CodePen with more of the original code for reference. localStorage will function in this CodePen example.

Related

This last step on my Note app... When I click on view more modal window is created, but the wrong one

'use strict';
// Select all elements needed for this task (querySelector)
const form = document.querySelector('.form');
const input = document.querySelector('.input__text');
let container = document.querySelector('.notes-container');
const button = document.querySelector('.btn');
const noteDiv = document.querySelector('.note');
let modal = document.querySelector('.modal');
const overlay = document.querySelector('.overlay');
const btnClose = document.querySelectorAll('.close-modal');
const btnView = document.querySelector('.btn-view');
let noteCount = 0;
// Create function that reads when the button is clicked on form
form.addEventListener('submit', function (e) {
e.preventDefault();
// if input filed is empty note will not be added!
if (!input.value == '') {
// Every time i click on button, notCount is incremented by one. Then that count i store and use to count number of note
if (button.click) noteCount++;
// Creating div element where notes will go
const divNotes = document.createElement('div');
// Adding class to that div element
divNotes.classList.add('note');
// Inserting HTML content into created div
const createdNote = (divNotes.innerHTML += `
<h4 class="note__heading">Note ${noteCount}</h4>
<p class="note__text">${input.value}</p>
<button class="btn btn-view">View Detail</button>
`);
container.appendChild(divNotes);
//
container.addEventListener('click', function (e) {
if (!e.target.classList.contains('btn-view')) {
return;
}
modal.classList.remove('hidden');
overlay.classList.remove('hidden');
modal.innerHTML = `<h4 class="note__heading">Note ${noteCount}</h4>
<p class="note__text">${input.value}</p>
<button class="close-modal">X</button>
`;
});
modal.addEventListener('click', function (e) {
if (!e.target.classList.contains('close-modal')) {
return;
}
modal.classList.add('hidden');
overlay.classList.add('hidden');
});
}
});
html {
margin: 0;
padding: 0;
font-family: 'Courier New', Courier, monospace;
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
}
.container__app {
text-align: center;
}
h1 {
font-size: 4rem;
font-weight: 100;
}
h3 {
font-size: 2rem;
color: green;
margin-top: -40px;
}
.input__text {
width: 1310px;
height: 50px;
margin-bottom: 15px;
padding: 10px;
font-size: 16px;
resize: none;
}
label {
bottom: 36px;
padding: 3px;
vertical-align: top;
font-size: 25px;
font-weight: 600;
}
.btn-green {
color: white;
background-color: green;
width: 100px;
height: 35px;
border-radius: 5px;
border: none;
}
.btn-span {
margin-top: 15px;
}
.btn-green:active {
transform: translateY(4px);
}
.notes-container {
margin: auto;
padding: 25px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
grid-gap: 1.5rem;
}
.note {
border: 1px solid gray;
padding-bottom: 18px;
margin-top: 15px;
}
.note__text {
overflow: hidden;
max-height: 7rem;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
-webkit-line-clamp: 4;
word-wrap: break-word;
padding: 0 20px 4px 20px;
}
h4 {
font-size: 25px;
}
p {
font-size: 20px;
}
.btn-view {
color: white;
background-color: rgb(24, 113, 197);
width: 100px;
height: 35px;
border-radius: 5px;
border: none;
}
.btn-view:active {
transform: translateY(4px);
}
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 70%;
border-radius: 5px;
background-color: white;
padding: 6rem;
box-shadow: 0 3rem 5rem rgba(0 0 0 0.3);
z-index: 10;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(3px);
z-index: 5;
}
.hidden {
display: none;
}
.close-modal {
position: absolute;
top: 1.2rem;
right: 2rem;
font-size: 2rem;
color: #333;
cursor: pointer;
border: none;
background: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Note Taker App</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<div class="container__app">
<h1>Note Taker</h1>
<h3>Add a new note:</h3>
<div class="input__field">
<form class="form">
<label class="input__text-name">Note: </label>
<textarea
rows="5"
cols=""
class="input__text"
placeholder="Write your note here"
></textarea>
<label for="submit"></label><br />
<button class="btn btn-green" type="submit">Add Note</button>
</form>
</div>
<div class="modal hidden">
<button class="close-modal">X</button>
</div>
<div class="overlay hidden"></div>
<div class="notes-container">
<!-- <div class="note">
<h4 class="note__heading">Note1</h4>
<p class="note__text">
MY note text
</p>
<div class="note__btn">
<button class="btn btn-view">View Detail</button>
</div>
</div> -->
</div>
</div>
</body>
</html>
Im new to programming, please help. I finished almost everything except last step. This is the problem: when I press button view more (it should create modal window related to that note and button). Thing is that everything is working fine when you press buttons in order (like note1, note2, note3), but if you press 6th button and then the first one, only last element will be created. If someone can explain me how this works. https://codepen.io/Niksani/pen/GROXGyN
const form = document.querySelector('.form');
const input = document.querySelector('.input__text');
let container = document.querySelector('.notes-container');
const button = document.querySelector('.btn');
const noteDiv = document.querySelector('.note');
let modal = document.querySelector('.modal');
const overlay = document.querySelector('.overlay');
const btnClose = document.querySelectorAll('.close-modal');
const btnView = document.querySelector('.btn-view');
let noteCount = 0;
form.addEventListener('submit', function (e) {
e.preventDefault();
if (!input.value == '') {
and use to count number of note
if (button.click) noteCount++;
const divNotes = document.createElement('div');
divNotes.classList.add('note');
const createdNote = (divNotes.innerHTML += `
<h4 class="note__heading">Note ${noteCount}</h4>
<p class="note__text">${input.value}</p>
<button class="btn btn-view">View Detail</button>
`);
container.appendChild(divNotes);
//
container.addEventListener('click', function (e) {
if (!e.target.classList.contains('btn-view')) {
return;
}
modal.classList.remove('hidden');
overlay.classList.remove('hidden');
modal.innerHTML = `<h4 class="note__heading">Note ${noteCount}</h4>
<p class="note__text">${input.value}</p>
<button class="close-modal">X</button>
`;
});
modal.addEventListener('click', function (e) {
if (!e.target.classList.contains('close-modal')) {
return;
}
modal.classList.add('hidden');
overlay.classList.add('hidden');
});
}
});
'use strict';
// Select all elements needed for this task (querySelector)
const form = document.querySelector('.form');
const input = document.querySelector('.input__text');
let container = document.querySelector('.notes-container');
const button = document.querySelector('.btn');
const noteDiv = document.querySelector('.note');
let modal = document.querySelector('.modal');
const overlay = document.querySelector('.overlay');
const btnClose = document.querySelectorAll('.close-modal');
const btnView = document.querySelector('.btn-view');
let noteCount = 0;
// Create function that reads when the button is clicked on form
form.addEventListener('submit', function (e) {
e.preventDefault();
// if input filed is empty note will not be added!
if (!input.value == '') {
// Every time i click on button, notCount is incremented by one. Then that count i store and use to count number of note
if (button.click) noteCount++;
// Creating div element where notes will go
const divNotes = document.createElement('div');
// Adding class to that div element
divNotes.classList.add('note');
// Inserting HTML content into created div
const createdNote = (divNotes.innerHTML += `
<h4 class="note__heading">Note ${noteCount}</h4>
<p id='note${noteCount}' class="note__text">${input.value}</p>
<button class="btn btn-view" value='${noteCount}'>View Detail</button>
`);
container.appendChild(divNotes);
//
container.addEventListener('click', function (e) {
if (!e.target.classList.contains('btn-view')) {
return;
}
let showNote = '';
showNote = e.target.value;
let noteText = document.getElementById(`note${showNote}`).innerHTML;
modal.classList.remove('hidden');
overlay.classList.remove('hidden');
modal.innerHTML = `<h4 class="note__heading">Note ${showNote}</h4>
<p class="note__text">${noteText}</p>
<button class="close-modal">X</button>
`;
});
modal.addEventListener('click', function (e) {
if (!e.target.classList.contains('close-modal')) {
return;
}
modal.classList.add('hidden');
overlay.classList.add('hidden');
});
}
});
html {
margin: 0;
padding: 0;
font-family: 'Courier New', Courier, monospace;
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
}
.container__app {
text-align: center;
}
h1 {
font-size: 4rem;
font-weight: 100;
}
h3 {
font-size: 2rem;
color: green;
margin-top: -40px;
}
.input__text {
width: 1310px;
height: 50px;
margin-bottom: 15px;
padding: 10px;
font-size: 16px;
resize: none;
}
label {
bottom: 36px;
padding: 3px;
vertical-align: top;
font-size: 25px;
font-weight: 600;
}
.btn-green {
color: white;
background-color: green;
width: 100px;
height: 35px;
border-radius: 5px;
border: none;
}
.btn-span {
margin-top: 15px;
}
.btn-green:active {
transform: translateY(4px);
}
.notes-container {
margin: auto;
padding: 25px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
grid-gap: 1.5rem;
}
.note {
border: 1px solid gray;
padding-bottom: 18px;
margin-top: 15px;
}
.note__text {
overflow: hidden;
max-height: 7rem;
-webkit-box-orient: vertical;
display: -webkit-box;
text-overflow: ellipsis;
-webkit-line-clamp: 4;
word-wrap: break-word;
padding: 0 20px 4px 20px;
}
h4 {
font-size: 25px;
}
p {
font-size: 20px;
}
.btn-view {
color: white;
background-color: rgb(24, 113, 197);
width: 100px;
height: 35px;
border-radius: 5px;
border: none;
}
.btn-view:active {
transform: translateY(4px);
}
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 70%;
border-radius: 5px;
background-color: white;
padding: 6rem;
box-shadow: 0 3rem 5rem rgba(0 0 0 0.3);
z-index: 10;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(3px);
z-index: 5;
}
.hidden {
display: none;
}
.close-modal {
position: absolute;
top: 1.2rem;
right: 2rem;
font-size: 2rem;
color: #333;
cursor: pointer;
border: none;
background: none;
}
<div class="container__app">
<h1>Note Taker</h1>
<h3>Add a new note:</h3>
<div class="input__field">
<form class="form">
<label class="input__text-name">Note: </label>
<textarea
rows="5"
cols=""
class="input__text"
placeholder="Write your note here"
></textarea>
<label for="submit"></label><br />
<button class="btn btn-green" type="submit">Add Note</button>
</form>
</div>
<div class="modal hidden">
<button class="close-modal">X</button>
</div>
<div class="overlay hidden"></div>
<div class="notes-container">
<!-- <div class="note">
<h4 class="note__heading">Note1</h4>
<p class="note__text">
MY note text
</p>
<div class="note__btn">
<button class="btn btn-view">View Detail</button>
</div>
</div> -->
</div>
</div>
check out the new event listener for your btn.click event...I am determining which note to show by getting the button value attribute that was added to the string literal....I am using that value to get the text of the note by giving the p an id and referencing that....I believe this gives you what you are looking for

All values are true, although the values have been changed

I have three input fields. Once for email, password and confirm password. If the user presses a button then a method checkAll() should be executed, this checks if the defaults for the fields are correct, if not another class should be assigned to the fields and the variable should be false.
The problem is, if all values are true then the default classes should be displayed again and console.log("Everything ok"); should be output. However, if I reload the page and don't fill anything (everything should be set to false) then I still get an Everything ok in the console and all the variables are set to true, even though the method has set the values to false. Why is that?
SignUp.js
import React, { useState } from "react";
import "./SignUp.css";
function SignUp() {
const [email, setEmail] = useState(true);
const [value_email, setValue_email] = useState('')
const [password, setPassword] = useState('')
const [passwordLength, setPasswordLenth] = useState(true)
const [passwordValueEqual, setPasswordValueEqual] = useState('')
const [passwordEqual, setPasswordEqual] = useState(true)
const [emailExist, setEmailExist] = useState(false)
const checkEmail = async () => {
// eslint-disable-next-line
var reg = /^([A-Za-z0-9_\-\.])+\#([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
if (reg.test(value_email) === false) {
console.log("E-Mail is wrong");
setEmail(false);
}
else {
setEmail(true);
}
};
const checkPasswortLength = async () => {
if(password.length < 5 ) {
console.log("Passwort zu kurz");
setPasswordLenth(false);
}
else{
setPasswordLenth(true);
}
}
const checkPasswortEqual = async () => {
if(passwordValueEqual === password ) {
setPasswordEqual(true);
console.log("Passwörter sind gleich");
}
else{
console.log("Passwörter sind ungleich");
setPasswordEqual(false);
}
}
async function checkAll() {
await checkEmail();
await checkPasswortLength();
await checkPasswortEqual();
if(email === true && passwordLength === true && passwordEqual === true ) {
console.log("Everything ok");
setEmailExist(true);
}
}
return (
<div className="SignUp">
<div className="container" id="container">
<div className="form-container sign-in-container">
<form>
<h2>Registriere dich jetzt</h2>
<input type="email" className={email ? 'input-form' : 'input-form-validation-wrong'} placeholder="E-Mail" onChange={event => setValue_email(event.target.value)} />
<p className={email ? 'validation-email-right' : 'validation-email-wrong'}>E-Mail ist falsch</p>
<input type="password" id="password" className={passwordLength ? 'input-form' : 'input-form-validation-wrong'} placeholder="Passwort" onChange={event => setPassword(event.target.value)} />
<p className={passwordLength ? 'validation-password-short-right' : 'validation-password-short-wrong'}>Passwort ist zu kurz</p>
<input type="password" id="password-confirm" className={ passwordEqual ? 'input-form' : 'input-form-validation-wrong'} placeholder="Passwort bestätigen" onChange={event => setPasswordValueEqual(event.target.value)} />
<p className={passwordEqual ? 'validation-password-equal-right' : 'validation-password-equal-wrong'}>Passwörter stimmen nicht über ein</p>
{emailExist === true &&
<p className='validation-password-equal-wrong'>E-Mail gibt es bereits</p>
}
<div className='buttons-container'>
<button className="button-registration" type="button" onClick={checkAll}>Registrieren</button>
</div>
<a className="already-account" href="/login">Du hast bereits einen Account?</a>
</form>
</div>
<div className="overlay-container">
<div className="overlay">
<div className="overlay-panel overlay-right">
</div>
</div>
</div>
</div>
</div>
);
}
export default SignUp;
SignUp.css
#import url('https://fonts.googleapis.com/css?family=Montserrat:400,800');
* {
box-sizing: border-box;
}
body {
background: #fff;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: 'Montserrat', sans-serif;
height: 100vh;
}
h1 {
font-weight: bold;
margin: 0;
}
h2 {
text-align: center;
font-weight: normal;
font-size: 18px;
}
p {
font-size: 14px;
font-weight: 100;
line-height: 20px;
letter-spacing: 0.5px;
margin: 20px 0 30px;
}
span {
font-size: 12px;
}
a {
color: #333;
font-size: 14px;
text-decoration: none;
margin: 15px 0;
}
.buttons-container {
text-align: center;
display: flex;
margin-top: 35px;
}
.button-registration {
display: flex;
border-radius: 20px;
border: 1px solid #5869FF;
background-color: #5869FF;
color: #FFFFFF;
font-size: 12px;
font-weight: bold;
padding: 12px 25px;
letter-spacing: 1px;
text-transform: uppercase;
transition: transform 80ms ease-in;
}
button:active {
transform: scale(0.95);
}
button:focus {
outline: none;
}
button.ghost {
background-color: transparent;
border-color: #FFFFFF;
}
form {
background-color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 50px;
height: 100%;
text-align: center;
}
.input-form {
background-color: #e6e6e6;
border: none;
border-radius: 20px;
padding: 12px 15px;
margin: 8px 0;
width: 100%;
}
.input-form:focus {
outline: none;
box-shadow: 0px 0px 2px #5869FF;
}
.input-form-validation-wrong {
background-color: #e6e6e6;
border: none;
border-radius: 20px;
padding: 12px 15px;
margin: 8px 0;
width: 100%;
}
.input-form-validation-wrong {
background-color: #e6e6e6;
border: none;
border-radius: 20px;
padding: 12px 15px;
margin: 8px 0;
width: 100%;
box-shadow: 0px 0px 4px #ff5858;
}
.input-form-validation-wrong:focus {
outline: none;
box-shadow: 0px 0px 4px #ff5858;
}
.input-form-validation-wrong::placeholder {
color: #ff5858;
}
.input-remain {
}
.optional-buttons {
text-align: center;
display: inline-block;
font-size: 12px;
}
.already-account {
color: #5869FF;
text-decoration: underline;
font-size: 12px;
text-align: center;
}
.already-account:hover {
color: #6a79fc;
text-decoration: underline;
}
.container {
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
overflow: hidden;
}
.form-container {
position: absolute;
top: 0;
height: 100%;
max-width: 40%;
}
.sign-in-container {
left: 0;
width: 50%;
z-index: 2;
}
.container.right-panel-active .sign-in-container {
transform: translateX(100%);
}
.sign-up-container {
left: 0;
width: 50%;
opacity: 0;
z-index: 1;
}
.validation-wrong {
color: #ff5858;
margin-top: -2px;
margin-bottom: -2px;
text-align: left;
}
.validation-email-wrong {
color: #ff5858;
margin-top: -2px;
margin-bottom: -2px;
text-align: left;
}
.validation-email-right {
visibility: hidden;
margin-top: -2px;
margin-bottom: -2px;
}
.validation-password-short-wrong {
color: #ff5858;
margin-top: -2px;
margin-bottom: -2px;
text-align: left;
}
.validation-password-short-right {
visibility: hidden;
margin-top: -2px;
margin-bottom: -2px;
}
.validation-password-equal-wrong {
color: #ff5858;
margin-top: -2px;
margin-bottom: -2px;
text-align: left;
}
.validation-password-equal-right {
visibility: hidden;
margin-top: -2px;
margin-bottom: -2px;
}
.validation-right {
visibility: hidden;
margin-top: -2px;
margin-bottom: -2px;
}
.container.right-panel-active .sign-up-container {
transform: translateX(100%);
opacity: 1;
z-index: 5;
animation: show 0.6s;
}
#keyframes show {
0%, 49.99% {
opacity: 0;
z-index: 1;
}
50%, 100% {
opacity: 1;
z-index: 5;
}
}
.overlay-container {
position: absolute;
top: 0;
left: 40%;
width: 60%;
height: 100%;
overflow: hidden;
transition: transform 0.6s ease-in-out;
z-index: 100;
background-image: url('../../images/wallpaper.PNG');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.container.right-panel-active .overlay-container{
transform: translateX(-100%);
}
.overlay {
/*background: -webkit-linear-gradient(to right top, #5869ff, #5c66ff, #6063ff, #6460ff, #685dff, #6d5bff, #715aff, #7658ff, #7c58ff, #8158ff, #8658ff, #8b58ff);*/
/*background: linear-gradient(to right top, #5869ff, #5c66ff, #6063ff, #6460ff, #685dff, #6d5bff, #715aff, #7658ff, #7c58ff, #8158ff, #8658ff, #8b58ff);*/
background-repeat: no-repeat;
background-size: cover;
background-position: 0 0;
color: #FFFFFF;
position: relative;
left: -100%;
height: 100%;
width: 200%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.container.right-panel-active .overlay {
transform: translateX(50%);
}
.overlay-panel {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 40px;
text-align: center;
top: 0;
height: 100%;
width: 50%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.overlay-left {
transform: translateX(-20%);
}
.container.right-panel-active .overlay-left {
transform: translateX(0);
}
.overlay-right {
right: 0;
transform: translateX(0);
}
.container.right-panel-active .overlay-right {
transform: translateX(20%);
}
.social-container {
margin: 20px 0;
}
.social-container a {
border: 1px solid #DDDDDD;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
margin: 0 5px;
height: 40px;
width: 40px;
}
#media screen and (max-width: 960px) {
.overlay {
visibility: hidden;
}
.overlay-container {
visibility: hidden;
}
.form-container {
max-width: 100%;
min-width: 100%;
}
.optional-buttons {
display: flex;
align-items: center;
}
}
App.js
import "./styles.css";
import SignUp from "./SignUp";
export default function App() {
return (
<div className="App">
<SignUp></SignUp>
</div>
);
}
Reload Page
First Button click (the yellow mark is wrong)
Second Button click this time without the print statement everything okay
Since you are calling a function that updates a state on another function, the following code on the same function block won't use the updated value.
what you can do is return the updated value whenever you set it:
const checkEmail = async () => {
// eslint-disable-next-line
var reg = /^([A-Za-z0-9_\-\.])+\#([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
if (reg.test(value_email) === false) {
console.log("E-Mail is wrong");
setEmail(false);
return false; // add this one -------
}
else {
setEmail(true);
return true; // add this one --------
}
};
^^ do that for the other functions as well (checkPasswortLength, and checkPasswortEqual)
Then, on your checkAll:
async function checkAll() {
const emailCheck = await checkEmail();
const passwordLengthCheck = await checkPasswortLength();
const passwordEqualCheck = await checkPasswortEqual();
if(emailCheck === true && passwordLengthCheck === true && passwordEqualCheck === true ) {
console.log("Everything ok");
setEmailExist(true);
}
}
UPDATE
We can't use setstate callback functions since the setstate is called on another function, One other way is to use useEffect.
useEffect(() => {
if(email === true && passwordLength === true && passwordEqual === true ) {
console.log("Everything ok");
setEmailExist(true);
}
}, [])
async function checkAll() {
await checkEmail();
await checkPasswortLength();
await checkPasswortEqual();
// we removed the condition here
}
this way you don't have to "return" the value and will automatically notify the user everytime everything is ok.

Why does my eventlistener for input search doesnt work?

I am working on an application to search for cities. It returns a card with the flag, capital, population and region; however, it works only until I try to add an eventListener to the input search, after which, it does nothing.
Am I calling the search incorrectly? should I maybe do a search function?
P. S: I started coding ~6 months ago and sorry if it is a not well-constructed code.
const APICALL = 'https://restcountries.eu/rest/v2/';
const form = document.querySelector('.recherche')
const input = document.querySelector('.inpRecherche');
const searchBtn = document.querySelector('.searchBtn');
const affichage = document.querySelector('.affichage');
let cities = [];
//API call
async function dataApi(cities) {
const call = await fetch(APICALL);
const data = await call.json();
cities = data;
//console.log(cities);
createCard(cities);
}
dataApi(cities)
function createCard(cities) {
for (let i = 0; i < cities.length; i++) {
const cardHTML = `
<div class="carte">
<img src="${[cities[i].flag]}" alt="flag" class="avatar">
<h2>${[cities[i].name]}</h2>
<ul class="cont-infos">
<li class="capital">Capital : ${[cities[i].capital]}</li>
<li class="population">Population: ${[cities[i].population]}</li>
<li class="subregion">Region : ${[cities[i].subregion]}</li>
</ul>
</div>
`;
affichage.innerHTML = cardHTML;
}
}
searchBtn.addEventListener('click', dataApi);
form.addEventListener('submit', (e) => {
e.preventDefault()
if (e.value > 0) {
//console.log('hello');
dataApi([cities[i]]);
input.value = "";
}
})
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
height: 100vh;
background-image: url("Background.jpg");
font-family: Arial, Helvetica, sans-serif;
background-size: cover;
}
h1 {
font-size: 35px;
text-align: center;
margin: 30px;
}
.inpRecherche {
display: block;
width: 250px;
padding: 3px;
font-size: 12px;
}
form,
.affichage {
display: flex;
width: 100%;
height: auto;
align-items: center;
justify-content: center;
border-radius: 2px;
}
.affichage {
position: absolute;
justify-content: center;
border: 2px solid whitesmoke;
border-radius: 5px;
width: 300px;
height: 300px;
margin: 20px 480px;
}
.searchBtn {
height: 25px;
padding: 2px 5px;
background-color: #2896F6;
box-shadow: none;
cursor: pointer;
color: whitesmoke;
font-weight: bold;
border-radius: 3px solid white;
}
.searchBtn:hover {
background-color: #167CD4;
}
/* a partir d'ici c'est à créer
*/
.card {
width: 500px;
height: auto;
position: relative;
margin-top: 200px;
padding-bottom: 20px;
border-radius: 5px;
background-color: beige;
}
.avatar {
height: 150px;
width: 150px;
margin-top: 80px;
border-radius: 50%;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
background-color: #000;
border: 1px solid black;
}
h2 {
margin-top: 100px;
text-align: center;
font-size: 25px;
}
.cont-infos {
border-top: 1px dashed black;
margin-top: 20px;
list-style-type: none;
}
li {
padding: 10px 20px;
text-align: justify;
font-size: 22px;
}
li:nth-child(1) {
margin-top: 15px;
}
<h1>City finder 🌍🏃</h1>
<form class="recherche">
<input type="text" class="inpRecherche" placeholder="Rechercher une ville">
<button class="searchBtn">Chercher</button>
</form>
<div class="affichage">
</div>
The first thing that comes to my attention is the argument you're passing to the dataApi function. When you pass it to the event listener, the argument it receives is an event object (you're just naming it "cities"), and then you're trying to overwrite it with data from the API call instead of updating the global cities array.
Hi Lizeth and welcome to StackOverflow.
I'm not completely sure of what you are trying to do, but right now, your function createCard is not looping over all the cities you receive from the API, but writing over and over the content of cardHTML. To display all the cities, you can add a +in front of the = and
function createCard(cities) {
for (let i = 0; i < cities.length; i++) {
const cardHTML = `
<div class="carte">
<img src="${[cities[i].flag]}" alt="flag" class="avatar">
<h2>${[cities[i].name]}</h2>
<ul class="cont-infos">
<li class="capital">Capital : ${[cities[i].capital]}</li>
<li class="population">Population: ${[cities[i].population]}</li>
<li class="subregion">Region : ${[cities[i].subregion]}</li>
</ul>
</div>
`;
affichage.innerHTML += cardHTML;
}
}
And change your css classes to
.affichage {
justify-content: center;
border: 2px solid whitesmoke;
border-radius: 5px;
width: 90vw;
height: auto;
margin: 20px auto 0 auto;
display: flex;
flex-flow: row wrap;
}
.avatar {
height: 150px;
width: 150px;
margin: 10px auto;
border-radius: 50%;
position: initial;
background-color: #000;
border: 1px solid black;
margin: 10px auto;
}
But, be warned, building html this way can be very dangerous, see XSS attacks.
And to search for a city using the input, Yes, you need to build a search function yourself, and display the result. Regex could be a way to do it

Mouseover event with mousedown

I need your help. There is an APP Virtual-piano. When I click the key, the relevent note is reproduced.If the click is single, everything is fine. But when I hold down the mouse button and lead the cursor over the keys, the sound is not produced. What could be the problem? I suppose that the problem is in function on the line 15. But i don`t know how to fix it. Help me please. Thanks in advance.
This is JS code
const piano = document.querySelector(".piano");
const collectionPiano = document.querySelectorAll(".piano-key");
function setActiveKey(event) { //active status keys mouse event
event.target.classList.add("piano-key-active", "piano-key-active-pseudo");
}
function removeActiveKey(event) { //remove active status keys mouse event
event.target.classList.remove("piano-key-active", "piano-key-active-pseudo");
}
function playAudio (note) { //start function playAudio
const audio = document.querySelector(`audio[data-note="${note}"]`);
audio.currentTime = 0;
audio.play();
}
function startKeyActive (event) { //mouseover and mouseout events for active status keys, pseudo and play audio
if (event.target.classList.contains("piano-key")) {
event.target.classList.add("piano-key-active", "piano-key-active-pseudo");
const note = event.target.dataset.note;
playAudio(note);
}
collectionPiano.forEach((el) => {
// el.addEventListener("mouseover", playAudio);
el.addEventListener("mouseover", setActiveKey);
el.addEventListener("mouseout", removeActiveKey);
});
};
function stopKeyIActive () { //remove mouseover and mouseout events for active status keys, pseudo and play audio
collectionPiano.forEach((el) => {
el.classList.remove("piano-key-active", "piano-key-active-pseudo");
// el.removeEventListener("mouseover", playAudio);
el.removeEventListener("mouseover", setActiveKey);
el.removeEventListener("mouseout", removeActiveKey);
});
};
piano.addEventListener("mousedown", startKeyActive);
piano.addEventListener("mousedown", playAudio);
document.addEventListener("mouseup", stopKeyIActive);
window.addEventListener("keydown", (event) => { // Event keyboard - play audio
if (event.repeat) {
return;
}
const audioKeys = document.querySelector(`audio[data-key="${event.keyCode}"]`);
const pianoKey = document.querySelector(`.piano-key[data-key="${event.keyCode}"]`);
audioKeys.currentTime = 0;
audioKeys.play();
pianoKey.classList.add('piano-key-active');
window.addEventListener("keyup", () => {
pianoKey.classList.remove('piano-key-active');
})
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
user-select: none;
}
a:focus {
outline: 0;
}
html {
background: #313940;
}
body {
min-height: 100vh;
background-color: #313940;
font-family: "Open Sans", Arial, Helvetica, sans-serif;
background: #313940;
overflow-x: hidden;
}
.header {
text-align: center;
width: 100%;
border-bottom: 1px solid;
border-image-slice: 1;
border-image-source: linear-gradient(to left, #38495a, #a2abb3, #38495a);
}
.header-title {
line-height: 60px;
font-weight: 300;
color: #fff;
}
.main {
min-height: calc(100vh - 110px);
padding: 60px 10px 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: space-between;
width: 100%;
max-width: 1140px;
margin: 0 auto;
}
.btn-container {
display: flex;
justify-content: space-between;
width: 306px;
height: 40px;
margin: 0 auto;
margin-bottom: 80px;
}
.btn {
width: 150px;
height: 40px;
padding: 0 10px;
background-color: #454c53;
border: 0;
border-radius: 2px;
font-family: "Open Sans", sans-serif;
font-size: 16px;
font-weight: 300;
color: #fff;
outline: 0;
cursor: pointer;
transition: 0.3s;
}
.btn:not(.btn-active):hover {
background-color: #515961;
}
.btn:active {
background-color: #00c9b7;
}
.btn-active {
background-color: #00b4a4;
}
.btn-active:hover {
background-color: #00c9b7;
}
.piano {
position: relative;
display: flex;
justify-content: space-between;
width: 100%;
height: 270px;
max-width: 560px;
margin: 0 auto 60px;
}
.piano-key {
position: relative;
width: 80px;
height: 270px;
background-color: rgba(255, 255, 255, 0.85);
border: 4px solid #313940;
border-radius: 0px 0px 12px 12px;
transition: 0.3s;
cursor: pointer;
}
.piano-key:hover {
background-color: #fff;
}
.keys-sharp {
position: absolute;
top: 0;
bottom: 0;
left: 53px;
right: 53px;
display: flex;
justify-content: space-between;
pointer-events: none;
}
.piano-key.sharp {
width: 54px;
height: 170px;
background-color: #313940;
border: 0;
border-radius: 0px 0px 9px 9px;
top: 0;
z-index: 3;
pointer-events: auto;
transform-origin: center top;
}
.piano-key.piano-key-active,
.piano-key.sharp.piano-key-active {
transform: scale(0.96);
}
.piano-key.none {
background-color: transparent;
border: 0;
border-radius: 0;
pointer-events: none;
}
.piano-key::before,
.piano-key::after {
content: attr(data-note);
position: absolute;
width: 40px;
height: 40px;
font-size: 26px;
line-height: 40px;
text-align: center;
color: #a2abb3;
bottom: -45px;
left: 20px;
transition: 0.3s;
pointer-events: none;
}
.piano-key::after {
display: none;
content: attr(data-letter);
}
.piano-key:hover::before,
.piano-key:hover::after {
color: #d7dfe6;
}
.sharp:active {
border-top: 0;
}
.piano-key.sharp::before,
.piano-key.sharp::after {
bottom: 175px;
left: 7px;
}
.piano-key.letter::before {
display: none;
}
.piano-key.letter::after {
display: block;
}
.piano-key-letter::before {
content: attr(data-letter);
}
.piano-key-remove-mouse:active::before {
color: #a2abb3;
}
.piano-key-active-pseudo:hover::after,
.piano-key-active-pseudo:hover::before,
.piano-key-active::after,
.piano-key-active::before {
color: #00b4a4;
}
.fullscreen {
position: fixed;
top: 120px;
right: 40px;
width: 40px;
height: 40px;
background-color: rgba(255, 255, 255, 0.3);
border: 0;
outline: 0;
background-size: contain;
transition: 0.3s;
cursor: pointer;
background-image: url("assets/svg/fullscreen-open.svg");
}
.fullscreen:hover {
background-color: rgba(255, 255, 255, 0.5);
}
:-webkit-full-screen .fullscreen {
background-image: url("assets/svg/fullscreen-exit.svg");
}
.footer {
border-top: 1px solid;
border-image-slice: 1;
border-image-source: linear-gradient(to left, #38495a, #a2abb3, #38495a);
}
.footer-container {
padding: 0 15px;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
max-width: 1140px;
margin: 0 auto;
}
.github {
display: block;
width: 120px;
height: 45px;
padding-left: 45px;
background-image: url("assets/svg/github.svg");
background-size: 35px;
background-repeat: no-repeat;
background-position: left center;
line-height: 45px;
color: #cbd5de;
font-size: 16px;
font-family: "Open Sans", sans-serif;
transition: 0.3s;
}
.github:hover {
color: #fff;
}
.rss {
display: block;
position: relative;
font-family: "Open Sans", sans-serif;
width: 86px;
height: 32px;
background-image: url("assets/svg/rss.svg");
background-size: contain;
background-repeat: no-repeat;
background-position: left center;
padding-right: 111px;
}
.rss-year {
position: absolute;
bottom: 0;
right: 0;
font-size: 21px;
letter-spacing: -2px;
color: #cbd5de;
line-height: 0.9;
font-weight: bold;
transition: 0.3s;
}
.rss:hover .rss-year {
right: -5px;
letter-spacing: 0;
}
#media (max-width: 768px) {
.fullscreen {
top: 10px;
right: 20px;
width: 40px;
height: 40px;
}
}
#media (max-width: 600px) {
.main {
padding-top: 40px;
}
.piano {
width: 310px;
height: 160px;
}
.piano-key {
width: 44px;
height: 160px;
border-radius: 0px 0px 8px 8px;
border: 2px solid #313940;
}
.keys-sharp {
left: 26px;
right: 26px;
}
.piano-key.sharp {
width: 36px;
height: 100px;
border-radius: 0px 0px 6px 6px;
}
.piano-key::before,
.piano-key::after {
width: 30px;
height: 30px;
font-size: 22px;
bottom: -35px;
left: 7px;
font-size: 22px;
}
.piano-key.sharp::before,
.piano-key.sharp::after {
bottom: 115px;
left: 3px;
}
.btn-container {
width: 244px;
height: 40px;
margin-bottom: 80px;
}
.btn {
width: 120px;
height: 40px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="assets/piano.ico" rel="shortcut icon">
<link href="https://fonts.gstatic.com" rel="preconnect">
<link
href="https://fonts.googleapis.com/css2?family=Open+Sans+Condensed:wght#300&family=Open+Sans:wght#300;400;800&display=swap"
rel="stylesheet">
<link href="style.css" rel="stylesheet">
<title>virtual-piano</title>
</head>
<body>
<header class="header">
<h1 class="header-title">Virtual Piano</h1>
</header>
<main class="main">
<div class="btn-container">
<button class="btn btn-notes btn-active">Notes</button>
<button class="btn btn-letters">Letters</button>
</div>
<div class="piano">
<div class="piano-key" data-key="68" data-letter="D" data-note="c"></div>
<div class="piano-key" data-key="70" data-letter="F" data-note="d"></div>
<div class="piano-key" data-key="71" data-letter="G" data-note="e"></div>
<div class="piano-key" data-key="72" data-letter="H" data-note="f"></div>
<div class="piano-key" data-key="74" data-letter="J" data-note="g"></div>
<div class="piano-key" data-key="75" data-letter="K" data-note="a"></div>
<div class="piano-key" data-key="76" data-letter="L" data-note="b"></div>
<div class="keys-sharp">
<div class="piano-key sharp" data-key="82" data-letter="R" data-note="c♯"></div>
<div class="piano-key sharp" data-key="84" data-letter="T" data-note="d♯"></div>
<div class="piano-key sharp none"></div>
<div class="piano-key sharp" data-key="85" data-letter="U" data-note="f♯"></div>
<div class="piano-key sharp" data-key="73" data-letter="I" data-note="g♯"></div>
<div class="piano-key sharp" data-key="79" data-letter="O" data-note="a♯"></div>
</div>
</div>
<audio data-key="75" data-note="a" src="assets/audio/a.mp3"></audio>
<audio data-key="79" data-note="a♯" src="assets/audio/a♯.mp3"></audio>
<audio data-key="76" data-note="b" src="assets/audio/b.mp3"></audio>
<audio data-key="68" data-note="c" src="assets/audio/c.mp3"></audio>
<audio data-key="82" data-note="c♯" src="assets/audio/c♯.mp3"></audio>
<audio data-key="70" data-note="d" src="assets/audio/d.mp3"></audio>
<audio data-key="84" data-note="d♯" src="assets/audio/d♯.mp3"></audio>
<audio data-key="71" data-note="e" src="assets/audio/e.mp3"></audio>
<audio data-key="72" data-note="f" src="assets/audio/f.mp3"></audio>
<audio data-key="85" data-note="f♯" src="assets/audio/f♯.mp3"></audio>
<audio data-key="74" data-note="g" src="assets/audio/g.mp3"></audio>
<audio data-key="73" data-note="g♯" src="assets/audio/g♯.mp3"></audio>
<button class="fullscreen openfullscreen"></button>
</main>
<footer class="footer">
<div class="footer-container">
<a class="github" href="#" target="_blank" rel="noopener noreferrer">github</a>
<a class="rss" href="https://rs.school/js/" target="_blank" rel="noopener noreferrer">
<span class="rss-year">'21</span>
</a>
</div>
</footer>
<script src="script.js"></script>
</body>
</html>
I did it, here is the final code JS
const piano = document.querySelector(".piano");
const collectionPiano = document.querySelectorAll(".piano-key");
function playAudio (event) { //active status keys mouse event
event.target.classList.add("piano-key-active", "piano-key-active-pseudo");
const note = event.target.dataset.note;
const audio = document.querySelector(`audio[data-note="${note}"]`);
audio.currentTime = 0;
audio.play();
}
function removeActiveKey(event) { //remove active status keys mouse event
event.target.classList.remove("piano-key-active", "piano-key-active-pseudo");
}
function startKeyActive (event) { //mouseover and mouseout events for active status keys, pseudo and play audio
if (event.target.classList.contains("piano-key")) {
event.target.classList.add("piano-key-active", "piano-key-active-pseudo");
}
collectionPiano.forEach((el) => {
el.addEventListener("mouseover", playAudio);
el.addEventListener("mouseout", removeActiveKey);
});
};
function stopKeyIActive () { //remove mouseover and mouseout events for active status keys, pseudo and play audio
collectionPiano.forEach((el) => {
el.classList.remove("piano-key-active", "piano-key-active-pseudo");
el.removeEventListener("mouseover", playAudio);
el.removeEventListener("mouseout", removeActiveKey);
});
};
piano.addEventListener("mousedown", startKeyActive);
piano.addEventListener("mousedown", playAudio);
document.addEventListener("mouseup", stopKeyIActive);
window.addEventListener("keydown", (event) => { // Event keyboard - play audio
if (event.repeat) {
return;
}
const audioKeys = document.querySelector(`audio[data-key="${event.keyCode}"]`);
const pianoKey = document.querySelector(`.piano-key[data-key="${event.keyCode}"]`);
audioKeys.currentTime = 0;
audioKeys.play();
pianoKey.classList.add('piano-key-active');
window.addEventListener("keyup", () => {
pianoKey.classList.remove('piano-key-active');
})
});

My pre-loader is not working as expected, Animation not work

Want to create the pre-loader page, and have reference URL "https://www.priyaty.com/".
But somehow I'm not able to create the same loader as the above link.
I'm facing an issue when I applied the few CSS but, somehow I'm not matched with the above link loader.
can anyone help me out to build the same loader?
I'm using HTML, CSS, and JavaScript
function counter() {
var count = setInterval(function() {
var c = document.getElementById("counter")
int = parseInt(c.textContent);
c.textContent = (++int).toString();
if (int == 100) {
clearInterval(count);
c.classList.add("hide");
document.getElementById("preloader").classList.add("slide-up")
}
}, 40)
}
counter();
.preloader {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
.preloader .preloaderp {
font-size: 5em;
font-weight: bold;
color: rgba(255, 255, 255, .05);
position: absolute;
padding: 15px;
text-align: center;
text-transform: uppercase;
}
.preloader.slide-up {
height: 0px;
transition: .5s;
transition-delay: 1s;
font-size: 0px;
}
.counter {
font-size: 5em;
color: #fff;
font-weight: bold;
}
.counter.hide {
opacity: 0;
transition: 1s;
}
.counter::after {
content: "%";
font-size: .5em;
}
#media only screen and (max-width: 575px) {
.preloaderp {
font-size: 2em;
}
.counter {
font-size: 2em;
}
}
<div class="preloader" id="preloader">
<p class="preloaderp">Loading</p>
<div class="counter" id="counter">
0
</div>
</div>
Were you looking for this?
var counting = setInterval(function() {
var loader = document.getElementById("loader");
var currval = parseInt(loader.innerHTML);
var Width = 100 - currval;
var loadscreen = document.getElementById("loadscreen");
loader.innerHTML = ++currval;
if (currval === 100) {
clearInterval(counting);
loadscreen.style.display = "none";
}
loadscreen.style.transition = "0.1s";
loadscreen.style.width = Width + "%";
}, 10);
.loading-screen {
width: 100%;
height: 100%;
}
.loader {
font-size: 50px;
font-family: Arial;
position: fixed;
left: 45%;
z-index: 1000;
color: red;
}
.loader:after {
content: " %";
font-size: 100%;
}
.after-load {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
color: white;
text-align: center;
border: none;
}
<div class="loading-screen"></div>
<div class="after-load" id="loadscreen">
<div class="loader" style="top: 50%;" id="loader">0</div>
</div>

Categories

Resources