It's difficult to identify the exact issue, My StopWatch is not working when I click on Stop Button and wait for some second then I click on start button then I see that my second is working fine but minutes is not working properly. please check that is there any issue
let start = document.getElementById("start");
let stop = document.getElementById("stop");
let reset = document.getElementById("reset");
let h3 = document.getElementById("h3");
let time = document.getElementById("time");
let h3CreateMin = document.createElement("h3");
let h3CreateHour = document.createElement("h3");
let milisecond = document.getElementById("milisecond");
let second = document.getElementById("second");
let minSpan = document.createElement("span");
let minSpanSigin = document.createElement("span");
let hourSpan = document.createElement("span");
let hourSpanSigin = document.createElement("span");
let secStart = 0;
let miliSecStart = 0;
let minStart = 0;
let hourStart = 0;
let s = true;
start.addEventListener("click", function () {
reset.style.display = "block";
stop.style.display = "block";
start.style.display = "none";
miliSecondStop = setInterval(() => {
let miliSec = miliSecStart + 1;
milisecond.innerText = miliSec;
miliSecStart = miliSec;
if (miliSecStart === 99) {
miliSecStart = 0;
}
}, 10);
// Sec Start
secondStop = setInterval(() => {
let sec = secStart + 1;
secStart = sec;
second.innerText = secStart;
if (sec === 60) {
secStart = 0;
}
}, 1000);
// Min Start
minStop = setInterval(() => {
let min = minStart + 1;
if (s === true) {
time.prepend(h3CreateMin);
}
h3CreateMin.style.display = "block";
h3CreateMin.append(minSpan);
minSpan.classList = "value";
h3CreateMin.classList = "time_s_m_h";
h3CreateMin.append(minSpanSigin);
minSpanSigin.classList = "sigin";
minSpanSigin.innerText = "M";
minStart = min;
minSpan.innerText = min;
if (min === 60) {
minStart = 0;
}
s = false;
}, 60000);
// 60000
// Hour Start
hourStop = setInterval(() => {
let hour = hourStart + 1;
time.prepend(h3CreateHour);
h3CreateHour.style.display = "block";
h3CreateHour.classList = "time_s_m_h";
h3CreateHour.append(hourSpan);
hourSpan.classList = "value";
h3CreateHour.append(hourSpanSigin);
hourSpanSigin.classList = "sigin";
hourSpanSigin.innerText = "H";
hourSpan.innerText = hour;
hourStart = hour;
if (hour === 24) {
hourStart = 0;
}
}, 60000);
// 3600000
});
stop.addEventListener("click", function () {
start.style.display = "block";
stop.style.display = "none";
clearInterval(miliSecondStop);
clearInterval(secondStop);
clearInterval(minStop);
clearInterval(hourStop);
});
reset.addEventListener("click", function () {
start.style.display = "block";
stop.style.display = "none";
clearInterval(miliSecondStop);
miliSecStart = 0;
milisecond.innerText = "00";
clearInterval(secondStop);
secStart = 0;
second.innerText = 0;
clearInterval(minStop);
minStart = 0;
h3CreateMin.style.display = "none";
clearInterval(hourStop);
hourStart = 0;
h3CreateHour.style.display = "none";
});
*{
margin: 0px;
padding: 0px;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
color: white;
}
main{
width: 100%;
height: 500px;
background-color: #FEA600;
display: flex;
flex-direction: column;
align-items: center;
}
main div:first-child{
margin-top: 20px;
}
main div:first-child h1, main div:first-child h2,main div:first-child h3{
font-size: 4rem;
font-weight: 100;
text-align: center;
margin-top: 20px;
}
main div:first-child #time{
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
main div:first-child #time .time_s_m_h{
display: flex;
/* border: 1px solid rgb(0, 8, 255); */
align-items: flex-end;
justify-content: center;
width: 100px;
margin: 5px;
}
main div:first-child h3 .sigin{
font-size: 2rem;
/* border: 1px solid green; */
}
main div:first-child h3 #milisecond{
display: inline-block;
width: 50px;
/* border: 1px solid green; */
}
main div:last-child{
display: flex;
}
main div:last-child button{
padding: 20px;
width: 150px;
background-color: #FEA600;
font-size: 25px;
margin: 10px;
border:1px solid #ffffff;
cursor: pointer;
}
#stop,#reset{
display: none;
}
HTML
<body>
<main>
<div>
<h1>STOP WATCH</h1>
<!-- <h2>Vanilla JavaScript stopwatch</h2> -->
<div id="time">
<h3 class="time_s_m_h">
<span id="second" class="value">0</span>
<span class="sigin">S</span>
</h3>
<h3 id="h3">
<span id="milisecond" class="sigin">00</span>
</h3>
</div>
</div>
<div id="btnDiv">
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="reset">Reset</button>
</div>
</main>
<script src="app.js"></script>
</body>
You should use one timer to count.
Your code does not work exactly for second too.
If you click start and stop quickly, scond label will not increase.
It's because when you click start and stop, all timer will be reset.
So you should use one timer.
let start = document.getElementById("start");
let stop = document.getElementById("stop");
let reset = document.getElementById("reset");
let h3 = document.getElementById("h3");
let time = document.getElementById("time");
let h3CreateMin = document.createElement("h3");
let h3CreateHour = document.createElement("h3");
let milisecond = document.getElementById("milisecond");
let second = document.getElementById("second");
let minSpan = document.createElement("span");
let minSpanSigin = document.createElement("span");
let hourSpan = document.createElement("span");
let hourSpanSigin = document.createElement("span");
let miliSec = 0;
let s = true;
start.addEventListener("click", function () {
reset.style.display = "block";
stop.style.display = "block";
start.style.display = "none";
miliSecondStop = setInterval(() => {
miliSec++;
let milsecText = miliSec % 100;
let secText = (parseInt(miliSec / 100)) % 60;
let minText = (parseInt(miliSec / 6000)) % 60;
let hourText = parseInt(miliSec / 360000);
milisecond.innerText = milsecText;
second.innerText = secText;
if(minText>0){
time.prepend(h3CreateMin);
h3CreateMin.style.display = "block";
h3CreateMin.append(minSpan);
minSpan.classList = "value";
h3CreateMin.classList = "time_s_m_h";
h3CreateMin.append(minSpanSigin);
minSpanSigin.classList = "sigin";
minSpanSigin.innerText = "M";
minSpan.innerText = minText;
}
if(hourText > 0){
time.prepend(h3CreateHour);
h3CreateHour.style.display = "block";
h3CreateHour.classList = "time_s_m_h";
h3CreateHour.append(hourSpan);
hourSpan.classList = "value";
h3CreateHour.append(hourSpanSigin);
hourSpanSigin.classList = "sigin";
hourSpanSigin.innerText = "H";
hourSpan.innerText = hourText;
}
}, 10);
});
stop.addEventListener("click", function () {
start.style.display = "block";
stop.style.display = "none";
clearInterval(miliSecondStop);
});
reset.addEventListener("click", function () {
start.style.display = "block";
stop.style.display = "none";
clearInterval(miliSecondStop);
miliSec = 0;
milisecond.innerText = "00";
h3CreateMin.style.display = "none";
h3CreateHour.style.display = "none";
});
*{
margin: 0px;
padding: 0px;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
color: white;
}
main{
width: 100%;
height: 500px;
background-color: #FEA600;
display: flex;
flex-direction: column;
align-items: center;
}
main div:first-child{
margin-top: 20px;
}
main div:first-child h1, main div:first-child h2,main div:first-child h3{
font-size: 4rem;
font-weight: 100;
text-align: center;
margin-top: 20px;
}
main div:first-child #time{
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
main div:first-child #time .time_s_m_h{
display: flex;
/* border: 1px solid rgb(0, 8, 255); */
align-items: flex-end;
justify-content: center;
width: 100px;
margin: 5px;
}
main div:first-child h3 .sigin{
font-size: 2rem;
/* border: 1px solid green; */
}
main div:first-child h3 #milisecond{
display: inline-block;
width: 50px;
/* border: 1px solid green; */
}
main div:last-child{
display: flex;
}
main div:last-child button{
padding: 20px;
width: 150px;
background-color: #FEA600;
font-size: 25px;
margin: 10px;
border:1px solid #ffffff;
cursor: pointer;
}
#stop,#reset{
display: none;
}
HTML
<body>
<main>
<div>
<h1>STOP WATCH</h1>
<!-- <h2>Vanilla JavaScript stopwatch</h2> -->
<div id="time">
<h3 class="time_s_m_h">
<span id="second" class="value">0</span>
<span class="sigin">S</span>
</h3>
<h3 id="h3">
<span id="milisecond" class="sigin">00</span>
</h3>
</div>
</div>
<div id="btnDiv">
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="reset">Reset</button>
</div>
</main>
<script src="app.js"></script>
</body>
Related
So I'm making an Etch-a-Sketch with a range slider to change the grid size, but the slider keeps resetting to its default size (16x16) as soon as I move the mouse after changing the value (if I change the value and don't move the mouse, the size doesn't reset). For some reason this doesn't happen on Chrome: the value and grid size both change and stay that way until I change them again.
Here's the JSFiddle: https://jsfiddle.net/CamiCoding/7zpt14cs/
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Etch-a-Sketch</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div class="title">
<h1>Etch-a-Sketch</h1>
</div>
<div class="btns">
<button id="blackBtn">Black</button>
<button id="rainbowBtn">Rainbow</button>
<button id="colorBtn">Color</button>
<button id="eraserBtn">Eraser</button>
<button id="resetBtn">Reset</button>
<div class="colorPicker">
<input type="color" id="color" value="#000000">
<span>Pick a color</span>
</div>
<div class="sliderAndValue">
<input type="range" min="2" max="100" value="16" id="slider">
<p class="value">16</p>
</div>
</div>
<div class="grid">
</div>
<script src="script.js" defer></script>
</body>
</html>
CSS:
#font-face {
src: url("../fonts/sf-atarian-system.regular.ttf");
font-family: Atarian;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: Atarian;
background-color: #D1D1D1;
}
.title h1 {
font-size: 80px;
margin: 0px;
}
.btns {
display: flex;
flex-direction: row;
width: 700px;
height: 50px;
justify-content: space-evenly;
margin-top: 20px;
margin-bottom: 20px;
}
.btns button {
font-family: Atarian;
font-size: 24px;
height: 40px;
width: 80px;
border-radius: 5px;
transition: transform 0.2s ease-in-out;
}
.btns button:hover {
transform: scale(1.2);
}
.btns .active {
background-color: #505050;
color: white;
}
.colorPicker {
display: flex;
flex-direction: column;
align-items: center;
font-size: 20px;
}
.color span {
text-align: center;
}
#color {
width: 90px;
}
.sliderAndValue {
-webkit-appearance: none;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 24px;
}
#slider {
-webkit-appearance: none;
width: 150px;
height: 10px;
background: #000;
outline: none;
border: 4px solid gray;
border-radius: 4px;
}
/* for firefox */
#slider::-moz-range-thumb {
width: 5px;
height: 20px;
background: #000;
cursor: pointer;
border: 4px solid gray;
border-radius: 4px;
}
/* for chrome/safari */
#slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 5px;
height: 20px;
background: #000;
cursor: pointer;
border: 4px solid gray;
border-radius: 4px;
}
.cell {
border: 1px solid black;
}
.cell.active {
background-color: black;
}
.grid {
display: inline-grid;
grid-template-columns: repeat(16, 2fr);
grid-template-rows: repeat(16, 2fr);
border: 5px solid gray;
border-radius: 5px;
height: 700px;
width: 700px;
background-color: white;
}
JS:
const grid = document.querySelector('.grid');
const resetBtn = document.getElementById('resetBtn');
const eraserBtn = document.getElementById('eraserBtn');
const blackBtn = document.getElementById('blackBtn');
const colorBtn = document.getElementById('colorBtn')
const colorValue = document.getElementById('color');
const slider = document.getElementById('slider');
const sliderValue = document.querySelector('.value');
const DEFAULT_COLOR = '#000000';
const DEFAULT_MODE = 'black';
const DEFAULT_SIZE = 16;
let currentColor = DEFAULT_COLOR;
let currentMode = DEFAULT_MODE;
let mouseDown = false
document.body.onmousedown = () => (mouseDown = true)
document.body.onmouseup = () => (mouseDown = false)
function setCurrentColor(newColor) {
currentColor = newColor;
}
function setCurrentMode(newMode) {
activateButton(newMode);
currentMode = newMode;
}
blackBtn.onclick = () => setCurrentMode('black');
rainbowBtn.onclick = () => setCurrentMode('rainbow');
eraserBtn.onclick = () => setCurrentMode('eraser');
colorBtn.onclick = () => setCurrentMode('color');
resetBtn.onclick = () => createGrid();
function createGrid() {
removeCells(grid);
let val = document.getElementById('slider').value;
sliderValue.textContent = val;
grid.style.gridTemplateColumns = (`repeat(${val}, 2fr`);
grid.style.gridTemplateRows = (`repeat(${val}, 2fr`);
for(let i = 0; i < val * val; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.addEventListener('mouseover', changeColor);
cell.addEventListener('mousedown', changeColor);
grid.appendChild(cell);
}
}
function activateButton(newMode) {
if (currentMode === 'rainbow') {
rainbowBtn.classList.remove('active');
} else if (currentMode === 'color') {
colorBtn.classList.remove('active');
} else if (currentMode === 'eraser') {
eraserBtn.classList.remove('active');
} else if (currentMode === 'black') {
blackBtn.classList.remove('active');
}
if (newMode === 'rainbow') {
rainbowBtn.classList.add('active');
} else if (newMode === 'color') {
colorBtn.classList.add('active');
} else if (newMode === 'eraser') {
eraserBtn.classList.add('active');
} else if (newMode === 'black') {
blackBtn.classList.add('active');
}
}
function changeColor(e) {
if (e.type === 'mouseover' && !mouseDown) return;
if (currentMode === 'rainbow') {
const randomR = Math.floor(Math.random() * 256);
const randomG = Math.floor(Math.random() * 256);
const randomB = Math.floor(Math.random() * 256);
e.target.style.backgroundColor = `rgb(${randomR}, ${randomG}, ${randomB})`;
} else if (currentMode === 'color') {
e.target.style.backgroundColor = colorValue.value;
} else if (currentMode === 'eraser') {
e.target.style.backgroundColor = '#ffffff';
} else if (currentMode === 'black') {
e.target.style.background = '#000000';
}
}
slider.addEventListener('input', function(){
let val = document.getElementById('slider').value;
sliderValue.textContent = val;
removeCells(grid);
grid.style.gridTemplateColumns = (`repeat(${val}, 2fr`);
grid.style.gridTemplateRows = (`repeat(${val}, 2fr`);
for (let i = 0; i < val * val; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.addEventListener('mouseover', changeColor);
cell.addEventListener('mousedown', changeColor);
grid.appendChild(cell);
}
});
function removeCells(parent){
while(grid.firstChild){
grid.removeChild(grid.firstChild);
}
}
window.onload = () => {
createGrid(DEFAULT_SIZE);
activateButton(DEFAULT_MODE);
}
I do have another question regarding this same project, but about a different issue, please let me know if I should post a different question for it or if I should post it here too!
Thanks a lot in advance :).
I was able to track down the source of the issue, and fix it. Sounds weird, but document.body.onmousedown and document.body.onmouseup were creating the issue.
Replacing them with addEventListener seems to fix it.
I also removed some repeated code (in slider's input listener), by making maximum use of createGrid() function.
const grid = document.querySelector('.grid');
const resetBtn = document.getElementById('resetBtn');
const eraserBtn = document.getElementById('eraserBtn');
const blackBtn = document.getElementById('blackBtn');
const colorBtn = document.getElementById('colorBtn')
const colorValue = document.getElementById('color');
const slider = document.querySelector('#slider');
const sliderValue = document.querySelector('.value');
const DEFAULT_COLOR = '#000000';
const DEFAULT_MODE = 'black';
const DEFAULT_SIZE = 16;
let currentColor = DEFAULT_COLOR;
let currentMode = DEFAULT_MODE;
let mouseDown = false
document.body.addEventListener("mousedown", () => (mouseDown = true))
document.body.addEventListener("mouseup", () => (mouseDown = false))
function setCurrentColor(newColor) {
currentColor = newColor;
}
function setCurrentMode(newMode) {
activateButton(newMode);
currentMode = newMode;
}
blackBtn.onclick = () => setCurrentMode('black');
rainbowBtn.onclick = () => setCurrentMode('rainbow');
eraserBtn.onclick = () => setCurrentMode('eraser');
colorBtn.onclick = () => setCurrentMode('color');
resetBtn.onclick = () => createGrid();
function createGrid(val = 16) {
slider.value = val;
sliderValue.textContent = val;
removeCells(grid);
grid.style.gridTemplateColumns = (`repeat(${val}, 2fr`);
grid.style.gridTemplateRows = (`repeat(${val}, 2fr`);
for (let i = 0; i < val * val; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.addEventListener('mouseover', changeColor);
cell.addEventListener('mousedown', changeColor);
grid.appendChild(cell);
}
}
function activateButton(newMode) {
if (currentMode === 'rainbow') {
rainbowBtn.classList.remove('active');
} else if (currentMode === 'color') {
colorBtn.classList.remove('active');
} else if (currentMode === 'eraser') {
eraserBtn.classList.remove('active');
} else if (currentMode === 'black') {
blackBtn.classList.remove('active');
}
if (newMode === 'rainbow') {
rainbowBtn.classList.add('active');
} else if (newMode === 'color') {
colorBtn.classList.add('active');
} else if (newMode === 'eraser') {
eraserBtn.classList.add('active');
} else if (newMode === 'black') {
blackBtn.classList.add('active');
}
}
function changeColor(e) {
if (e.type === 'mouseover' && !mouseDown) return;
if (currentMode === 'rainbow') {
const randomR = Math.floor(Math.random() * 256);
const randomG = Math.floor(Math.random() * 256);
const randomB = Math.floor(Math.random() * 256);
e.target.style.backgroundColor = `rgb(${randomR}, ${randomG}, ${randomB})`;
} else if (currentMode === 'color') {
e.target.style.backgroundColor = colorValue.value;
} else if (currentMode === 'eraser') {
e.target.style.backgroundColor = '#ffffff';
} else if (currentMode === 'black') {
e.target.style.background = '#000000';
}
}
slider.addEventListener('input', function(e) {
let val = parseInt(document.getElementById('slider').value);
createGrid(val);
});
function removeCells(parent) {
while (grid.firstChild) {
grid.removeChild(grid.firstChild);
}
}
window.onload = () => {
createGrid(DEFAULT_SIZE);
activateButton(DEFAULT_MODE);
}
#font-face {
src: url("../fonts/sf-atarian-system.regular.ttf");
font-family: Atarian;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: Atarian;
background-color: #D1D1D1;
}
.title h1 {
font-size: 80px;
margin: 0px;
}
.btns {
display: flex;
flex-direction: row;
width: 700px;
height: 50px;
justify-content: space-evenly;
margin-top: 20px;
margin-bottom: 20px;
}
.btns button {
font-family: Atarian;
font-size: 24px;
height: 40px;
width: 80px;
border-radius: 5px;
transition: transform 0.2s ease-in-out;
}
.btns button:hover {
transform: scale(1.2);
}
.btns .active {
background-color: #505050;
color: white;
}
.colorPicker {
display: flex;
flex-direction: column;
align-items: center;
font-size: 20px;
}
.color span {
text-align: center;
}
#color {
width: 90px;
}
.sliderAndValue {
-webkit-appearance: none;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 24px;
}
#slider {
-webkit-appearance: none;
width: 150px;
height: 10px;
background: #000;
outline: none;
border: 4px solid gray;
border-radius: 4px;
}
/* for firefox */
#slider::-moz-range-thumb {
width: 5px;
height: 20px;
background: #000;
cursor: pointer;
border: 4px solid gray;
border-radius: 4px;
}
/* for chrome/safari */
#slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 5px;
height: 20px;
background: #000;
cursor: pointer;
border: 4px solid gray;
border-radius: 4px;
}
.cell {
border: 1px solid black;
}
.cell.active {
background-color: black;
}
.grid {
display: inline-grid;
grid-template-columns: repeat(16, 2fr);
grid-template-rows: repeat(16, 2fr);
border: 5px solid gray;
border-radius: 5px;
height: 700px;
width: 700px;
background-color: white;
user-select: none;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Etch-a-Sketch</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div class="title">
<h1>Etch-a-Sketch</h1>
</div>
<div class="btns">
<button id="blackBtn">Black</button>
<button id="rainbowBtn">Rainbow</button>
<button id="colorBtn">Color</button>
<button id="eraserBtn">Eraser</button>
<button id="resetBtn">Reset</button>
<div class="colorPicker">
<input type="color" id="color" value="#000000">
<span>Pick a color</span>
</div>
<div class="sliderAndValue">
<input type="range" min="2" value="16" id="slider">
<p class="value">16</p>
</div>
</div>
<div class="grid">
</div>
<script src="script.js" defer></script>
</body>
</html>
I have an input field that add task. when i add the task a delete button appear next to each task
these task are stored in the local storage as an array
when i click delete button i want to delete the specific item not all the local storage
in general we use localStorage.removeItem(key);
let inputTask = document.querySelector('.input');
let tasks = document.querySelector('.tasks');
let add = document.querySelector('.add');
let alls = [];
//show tasks
function show() {
if (window.localStorage.task) {
let storedTaskes = JSON.parse(localStorage.getItem("task"));
storedTaskes.forEach((item) => {
let paragraph = document.createElement('p');
let deleteBtn = document.createElement('button');
deleteBtn.className = "delete";
deleteBtn.innerHTML = "Delete";
deleteBtn.id = item;
deleteBtn.setAttribute("onclick","deleteBtn(this)");
console.log(deleteBtn.value);
paragraph.innerHTML = item;
paragraph.appendChild(deleteBtn);
tasks.appendChild(paragraph);
});
}
}
// add tasks
add.onclick = function () {
if (inputTask.value.trim() !== "") {
alls.push(inputTask.value);
for (let i = 0; i < alls.length; i++) {
window.localStorage.setItem(`task`, JSON.stringify(alls));
}
}
inputTask.value = '';
show();
}
show();
//Delete Task
function deleteBtn(ob) {
let id = ob.id;
let taskArray = JSON.parse(localStorage.getItem("task"));
for(let i = 0; i < taskArray.length; i++){
if(taskArray[i] === id){
localStorage.removeItem(taskArray[i]);
}
}
}
body{
height: 90vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
display: flex;
align-items: center;
flex-direction: column;
gap: 20px;
}
.form {
background-color: #f0f0f0;
padding: 20px;
width: 500px;
text-align: center;
display: flex;
align-item: center;
justify-content: center;
gap: 15px;
}
.input{
border: 0;
outline: none;
padding: 10px 20px;
width: 300px;
border-radius: 5px;
}
.add,
.delete{
border: 0;
outline: none;
background-color: red;
color: white;
padding: 10px;
border-radius: 5px;
cursor: pointer;
}
.tasks {
background-color: #f0f0f0;
padding: 20px;
width: 500px;
}
p {
display: block;
background-color: white;
padding: 15px;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: space-between;
}
<div class="container">
<div class="form">
<input type="text" class="input">
<input type="submit" class="add" value="Add Task">
</div>
<div class="tasks"></div>
</div>
How can i delete the specific item from the array in the local storage and show the new result for the user
You need to remove from the array and store the array again since that is how your other part works
function deleteBtn(ob) {
let id = ob.id;
let taskArray = JSON.parse(localStorage.getItem("task"));
taskArray = taskArray.filter(item => item != id)
localStorage.setItem("task", JSON.stringify(taskArray));
show()
}
ALso change
for (let i = 0; i < alls.length; i++) {
window.localStorage.setItem(`task`, JSON.stringify(alls));
}
to
localStorage.setItem(`task`, JSON.stringify(alls));
Here is a better version
I use delegation for the delete and save to localstorage without reading it again
I use a generated ID as id
Note I have to comment out the localstorage part since SO does not allow it
let inputTask = document.querySelector('.input');
let tasks = document.querySelector('.tasks');
let add = document.querySelector('.add');
let storedTasks // = localStorage.getItem("task"); // uncomment on your server
let allTasks = storedTasks ? JSON.parse(storedTasks) : [];
function show() {
tasks.innerHTML = allTasks
.map(task => `<p>${task.input} <button class="delete" data-id="${task.id}">X</button></p>`)
.join('<br/>');
}
// add tasks
add.onclick = function() {
const input = inputTask.value.trim();
if (input !== "") {
const id = allTasks.length; // use the length at this time
allTasks.push({ id:new Date().getTime(), input });
// localStorage.setItem("task",JSON.stringify(allTasks)); // uncomment on your server
inputTask.value = '';
show();
}
};
show();
document.querySelector(".tasks").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("delete")) {
let id = tgt.dataset.id;
allTasks = allTasks.filter(item => item.id != id)
tgt.closest("p").remove();
// localStorage.setItem("task",JSON.stringify(allTasks)); // uncomment on your server
}
});
body {
height: 90vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
display: flex;
align-items: center;
flex-direction: column;
gap: 20px;
}
.form {
background-color: #f0f0f0;
padding: 20px;
width: 500px;
text-align: center;
display: flex;
align-item: center;
justify-content: center;
gap: 15px;
}
.input {
border: 0;
outline: none;
padding: 10px 20px;
width: 300px;
border-radius: 5px;
}
.add,
.delete {
border: 0;
outline: none;
background-color: red;
color: white;
padding: 10px;
border-radius: 5px;
cursor: pointer;
}
.tasks {
background-color: #f0f0f0;
padding: 20px;
width: 500px;
}
p {
display: block;
background-color: white;
padding: 15px;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: space-between;
}
<div class="container">
<div class="form">
<input type="text" class="input">
<input type="submit" class="add" value="Add Task">
</div>
<div class="tasks"></div>
</div>
function deleteBtn({id}) {
let taskArray = JSON.parse(localStorage.getItem("task")); // get the array
taskArray = taskArray.filter(ob=> ob.id != id ) // remove the id
localStorage.setItem("task", JSON.stringify(taskArray));
show()
}
but since you are using tasks.appendChild(paragraph)
you will have to change show function to
//show tasks
function show() {
if (window.localStorage.task) {
let storedTaskes = JSON.parse(localStorage.getItem("task"));
tasks.innerHTML = "" // here
storedTaskes.forEach((item) => {
let paragraph = document.createElement('p');
let deleteBtn = document.createElement('button');
deleteBtn.className = "delete";
deleteBtn.innerHTML = "Delete";
deleteBtn.id = item;
deleteBtn.setAttribute("onclick","deleteBtn(this)");
console.log(deleteBtn.value);
paragraph.innerHTML = item;
paragraph.appendChild(deleteBtn);
tasks.appendChild(paragraph)
});
}
}
I am making a Simple Calculator App using vanilla JS and I have a div element to display the numbers. But when the textContent within it exceeds its width it starts looking ugly. I want to make the font-size smaller so that its always within the width.
This is how I am adding numbers to my display div
for(let i=0; i<numbers.length; i++){
numbers[i].addEventListener("click", function(){
display.textContent += this.textContent;
})
}
When the textContent is less it looks good
But when the textContent exceeds the width it looks bad
The original code here.
//Selectors
let numbers = document.querySelectorAll(".numbers")
let operators = document.querySelectorAll(".operators")
let equalto = document.querySelector(".equalto")
let clear = document.querySelector(".clear")
let backspace = document.querySelector(".backspace")
let plusMinus = document.querySelector(".plus-minus")
let dot = document.querySelector(".dot")
let display = document.querySelector(".display")
let output = document.querySelector(".output")
let equaltoPressed = false;
//Event Listeners
for(let i=0; i<numbers.length; i++){
numbers[i].addEventListener("click", function(){
if (equaltoPressed){
display.textContent = "";
equaltoPressed = false;
}
//if condition so that if the display has "Infinity" on it, we don't append digits
if ("0123456789.+-×÷".includes(display.textContent[display.textContent.length-1]) || display.textContent == "")
display.textContent += this.textContent;
evaluate();
})
}
for(let i=0; i<operators.length; i++){
operators[i].addEventListener("click", function(){
equaltoPressed = false;
if ("+-×÷".includes(display.textContent[display.textContent.length-1]))
display.textContent = display.textContent.substring(0,display.textContent.length-1) + this.textContent;
else
display.textContent += this.textContent;
})
}
equalto.addEventListener("click", function(){
if (output.textContent !== ""){
display.textContent = output.textContent;
output.textContent = "";
equaltoPressed = true;
}
});
clear.addEventListener("click", function(){
equaltoPressed = false;
display.textContent = "";
output.textContent = "";
})
backspace.addEventListener("click", function(){
equaltoPressed = false;
display.textContent = display.textContent.substr(0,display.textContent.length-1);
evaluate();
})
plusMinus.addEventListener("click", function(){
equaltoPressed = false;
let expression = display.textContent;
let flag = true;
for (let i=expression.length-1; i>=0; i--){
if ("+-×÷".includes(expression[i])){
if (expression[i] !== "-")
expression = expression.substring(0,i+1) + "-" + expression.substring(i+1,expression.length);
flag = false;
break;
}
}
if (flag)
expression = "-"+expression;
display.textContent = expression;
evaluate();
})
dot.addEventListener("click", function(){
if (equaltoPressed)
display.textContent = "";
let start = 0;
for (let i=display.textContent.length-1; i>=0; i--){
if("+-×÷".includes(display.textContent[i])){
start = i+1;
break;
}
}
if (!display.textContent.substring(start,display.textContent.length).includes("."))
display.textContent += ".";
})
//Functions
function evaluate(){
let expression = display.textContent;
for (let i=0; i<expression.length; i++){
if (expression[i] === "×")
expression = expression.substring(0,i) + "*" + expression.substring(i+1,expression.length);
if (expression[i] === "÷")
expression = expression.substring(0,i) + "/" + expression.substring(i+1,expression.length);
}
if("0123456789.".includes(expression[expression.length-1]) && eval(expression) != expression)
output.textContent = eval(expression);
else
output.textContent = "";
}
*{
border:0;
margin:0;
}
body{
min-height: 100vh;
background: black;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: arial;
font-size: 1.5rem;
color: #f8f8f8;
}
.row{
display: flex;
}
.light-grey{
display: flex;
align-items: center;
justify-content: center;
background-color: #a6a6a6;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
color: black;
}
.dark-grey{
display: flex;
align-items: center;
justify-content: center;
background-color: #333333;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
}
.yellow{
display: flex;
align-items: center;
justify-content: center;
background-color: #ff9501;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
}
#zero{
width: 9.2rem;
border-radius:0 50px 50px 0;
border-top-right-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
border-top-left-radius: 50px;
}
.display{
width: 19.2rem;
height: 3rem;
margin: 0 .4rem 2rem .4rem;
text-align: right;
font-size: 3rem;
}
.output{
width: 19.2rem;
height: 2rem;
margin: 0 .4rem 2rem .4rem;
text-align: right;
font-size: 2rem;
}
i{
font-size: 1.3rem;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" integrity="sha256-46r060N2LrChLLb5zowXQ72/iKKNiw/lAmygmHExk/o=" crossorigin="anonymous" />
<div class="display"></div>
<div class="output"></div>
<div class="row">
<div class="light-grey clear">AC</div>
<div class="light-grey plus-minus">+/-</div>
<div class="light-grey operators">÷</div>
<div class="yellow backspace"><i class="fas fa-backspace"></i></div>
</div>
<div class="row">
<div class="dark-grey numbers">7</div>
<div class="dark-grey numbers">8</div>
<div class="dark-grey numbers">9</div>
<div class="yellow operators">×</div>
</div>
<div class="row">
<div class="dark-grey numbers">4</div>
<div class="dark-grey numbers">5</div>
<div class="dark-grey numbers">6</div>
<div class="yellow operators">-</div>
</div>
<div class="row">
<div class="dark-grey numbers">1</div>
<div class="dark-grey numbers">2</div>
<div class="dark-grey numbers">3</div>
<div class="yellow operators">+</div>
</div>
<div class="row">
<div class="dark-grey numbers" id="zero">0</div>
<div class="dark-grey dot">.</div>
<div class="yellow equalto">=</div>
</div>
Here, better view it on a Full page. Added a cover elements .display-font and .display-cover around .display, fixed their styles a little.
Then added a construction with observer on the end of your JS, which is looking for changing in .display, and then changes the font-size: n% of the .display-cover depends on the size of a .display-font. Here we need .display-font with a fixed value of font-size. Although we can't change font-size of .display, because we are observing the changes in it and font-size changes causes a circle error.
But everything works fine with 2 cover blocks. Look please.
UPDATED
Add everything above to .output block, missed it on the first try.
UPDATE 2
Added white-space: nowrap; to .display-cover and .output-cover to prevent jumping the text to the next line.
Add a lot of comments and explanations to the part of the code, where the changes in .display and .output are observing.
More about MutationObserver. It is not a quantum mechanics or a high level programming. Used it yesterday for the first time, to be honest.
More about while statement. Used it to check if the .display and .output width.
About rounding bug in your comment (when you are using a ling digits, more than 17 symbols).
This bug can be repeated in your original code.
This bug can be repeated in every online calculator i ever found. If you set 100000000000000000+68 - you will get 100000000000000060. This is some Javascript rounding feature. You can test it here https://www.jqueryscript.net/demo/Calculator-App-jQuery-Bootstrap/.
//Selectors
let numbers = document.querySelectorAll(".numbers")
let operators = document.querySelectorAll(".operators")
let equalto = document.querySelector(".equalto")
let clear = document.querySelector(".clear")
let backspace = document.querySelector(".backspace")
let plusMinus = document.querySelector(".plus-minus")
let dot = document.querySelector(".dot")
let display = document.querySelector(".display")
let output = document.querySelector(".output")
let equaltoPressed = false;
//Event Listeners
for (let i = 0; i < numbers.length; i++) {
numbers[i].addEventListener("click", function() {
if (equaltoPressed) {
display.textContent = "";
equaltoPressed = false;
}
//if condition so that if the display has "Infinity" on it, we don't append digits
if ("0123456789.+-×÷".includes(display.textContent[display.textContent.length - 1]) || display.textContent == "")
display.textContent += this.textContent;
evaluate();
})
}
for (let i = 0; i < operators.length; i++) {
operators[i].addEventListener("click", function() {
equaltoPressed = false;
if ("+-×÷".includes(display.textContent[display.textContent.length - 1]))
display.textContent = display.textContent.substring(0, display.textContent.length - 1) + this.textContent;
else
display.textContent += this.textContent;
})
}
equalto.addEventListener("click", function() {
if (output.textContent !== "") {
display.textContent = output.textContent;
output.textContent = "";
equaltoPressed = true;
}
});
clear.addEventListener("click", function() {
equaltoPressed = false;
display.textContent = "";
output.textContent = "";
})
backspace.addEventListener("click", function() {
equaltoPressed = false;
display.textContent = display.textContent.substr(0, display.textContent.length - 1);
evaluate();
})
plusMinus.addEventListener("click", function() {
equaltoPressed = false;
let expression = display.textContent;
let flag = true;
for (let i = expression.length - 1; i >= 0; i--) {
if ("+-×÷".includes(expression[i])) {
if (expression[i] !== "-")
expression = expression.substring(0, i + 1) + "-" + expression.substring(i + 1, expression.length);
flag = false;
break;
}
}
if (flag)
expression = "-" + expression;
display.textContent = expression;
evaluate();
})
dot.addEventListener("click", function() {
if (equaltoPressed)
display.textContent = "";
let start = 0;
for (let i = display.textContent.length - 1; i >= 0; i--) {
if ("+-×÷".includes(display.textContent[i])) {
start = i + 1;
break;
}
}
if (!display.textContent.substring(start, display.textContent.length).includes("."))
display.textContent += ".";
})
//Functions
function evaluate() {
let expression = display.textContent;
for (let i = 0; i < expression.length; i++) {
if (expression[i] === "×")
expression = expression.substring(0, i) + "*" + expression.substring(i + 1, expression.length);
if (expression[i] === "÷")
expression = expression.substring(0, i) + "/" + expression.substring(i + 1, expression.length);
}
if ("0123456789.".includes(expression[expression.length - 1]) && eval(expression) != expression)
output.textContent = eval(expression);
else
output.textContent = "";
}
// .display and .output font resizing changing addon
let displayCover = document.querySelector(".display-cover");
let outputCover = document.querySelector(".output-cover");
let displaySize;
let outputSize;
// This part is a config of MutationObserver, options for the observer (which mutations to observe)
let config = {
attributes: true,
childList: true,
characterData: true
};
// Defining new class of the object MutationObserver, which provides the ability to watch for changes being made to the DOM tree. Basically - this class will be executed on every observing changes in '.display'.
let displayObserver = new MutationObserver(function(mutations) {
displaySize = 100; // we will use it like a base 100% font-size later
// set font size to '.display-cover'
displayCover.style.cssText = 'font-size:' + displaySize + '%';
// 'while' statement creates a loop that executes a specified statement as long as the test condition evaluates to true. The condition is evaluated before executing the statement. Each time we set font size -1 - the width of '.display' changes, and we keeping this loop until the width of '.display' will be not more then it's parent '.display-cover'
while(display.offsetWidth > displayCover.offsetWidth) {
displaySize = displaySize - 1; //decrements font size by 1% each loop
displayCover.style.cssText = 'font-size:' + displaySize + '%';
// basically in DOM you see only result of the very last loop of this 'while' statment
}
});
// Start observing the target node (your '.display') for configured mutations (using config)
displayObserver.observe(display, config);
//----------
// everything the same as above, but for '.output'
let outputObserver = new MutationObserver(function(mutations) {
outputSize = 100;
outputCover.style.cssText = 'font-size:' + outputSize + '%';
while(output.offsetWidth > outputCover.offsetWidth) {
outputSize = outputSize - 1;
outputCover.style.cssText = 'font-size:' + outputSize + '%';
}
});
// as you can see, 'config' is the same
outputObserver.observe(output, config);
* {
border: 0;
margin: 0;
}
body {
min-height: 100vh;
background: black;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: arial;
font-size: 1.5rem;
color: #f8f8f8;
}
.row {
display: flex;
}
.light-grey {
display: flex;
align-items: center;
justify-content: center;
background-color: #a6a6a6;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
color: black;
}
.dark-grey {
display: flex;
align-items: center;
justify-content: center;
background-color: #333333;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
}
.yellow {
display: flex;
align-items: center;
justify-content: center;
background-color: #ff9501;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
}
#zero {
width: 9.2rem;
border-radius: 0 50px 50px 0;
border-top-right-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
border-top-left-radius: 50px;
}
.display-font {
font-size: 3rem;
}
.display-cover {
width: 19.2rem;
height: 3rem;
margin: 0 .4rem 2rem .4rem;
text-align: right;
font-size: 100%;
white-space: nowrap;
}
.display {
font-size: 100%;
display: inline-block;
}
.output-font {
font-size: 2rem;
}
.output-cover {
width: 19.2rem;
height: 2rem;
margin: 0 .4rem 2rem .4rem;
text-align: right;
font-size: 100%;
white-space: nowrap;
}
.output {
font-size: 100%;
display: inline-block;
}
i {
font-size: 1.3rem;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" integrity="sha256-46r060N2LrChLLb5zowXQ72/iKKNiw/lAmygmHExk/o=" crossorigin="anonymous" />
<div class="display-font">
<div class="display-cover">
<div class="display"></div>
</div>
</div>
<div class="output-font">
<div class="output-cover">
<div class="output"></div>
</div>
</div>
<div class="row">
<div class="light-grey clear">AC</div>
<div class="light-grey plus-minus">+/-</div>
<div class="light-grey operators">÷</div>
<div class="yellow backspace"><i class="fas fa-backspace"></i></div>
</div>
<div class="row">
<div class="dark-grey numbers">7</div>
<div class="dark-grey numbers">8</div>
<div class="dark-grey numbers">9</div>
<div class="yellow operators">×</div>
</div>
<div class="row">
<div class="dark-grey numbers">4</div>
<div class="dark-grey numbers">5</div>
<div class="dark-grey numbers">6</div>
<div class="yellow operators">-</div>
</div>
<div class="row">
<div class="dark-grey numbers">1</div>
<div class="dark-grey numbers">2</div>
<div class="dark-grey numbers">3</div>
<div class="yellow operators">+</div>
</div>
<div class="row">
<div class="dark-grey numbers" id="zero">0</div>
<div class="dark-grey dot">.</div>
<div class="yellow equalto">=</div>
</div>
i was trying to made my own TODO app with HTML,CSS and JS .. everything working as expected , exept this weird problem :
when i add an todo item the forloop will put addEventListener on it , so when i click on it , it will launch any code inside
The Problem : if i create more than one todo item .. some items stop working (addEventListener not working when i click on the item).
its like if i create 1 item:
item1 : working.
if i create 2 items:
item1 : not working.
item2 : working.
if i create 3 items:
item1 : working.
item2 : not working.
item2 : working.
...etc.
any explanation how to fix !
HTML CODE
<div id="form">
<p id="error">Fill The Empty !</p>
<input id="input" type="text" placeholder="Text Here!" >
<button id="add" type="submit" onclick="addIt()">Add</button>
</div>
<div id="listContainer">
<ul id="list">
</ul>
<p id="noItems">You Have No Items!</p>
</div>
CSS CODE
margin: 0px;
padding: 0px;
font-family: monospace, sans-serif;
list-style: none;
font-size: 10pt;
box-sizing: border-box;
}
#form{
display: flex;
flex-direction: column;
justify-content: center;
align-items:center;
}
#error{
color: red;
display: none;
margin: 5px 0px;
}
#input{
width: 95%;
height: 40px;
text-align: center;
margin: 5px 0px;
border: 1px purple dashed;
}
#add{
height: 40px;
width: 95%;
border: 0px;
color: white;
background-color: purple;
font-weight: 900;
}
#add:active{
color: purple;
background-color: white;
}
#listContainer{
margin-top: 40px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
}
#list{
display: flex;
flex-direction: column-reverse;
justify-content: center;
align-items: center;
width: 100vw;
}
.item{
position: relative;
text-align: center;
padding: 10px;
margin: 5px;
width: 95%;
color: purple;
background-color: white;
border: 1px purple solid;
font-size: 11pt;
}
.delete{
position: absolute;
right: 0px;
top: 0px;
padding: 10px;
width: 50px;
color: white;
background-color: red;
font-size: 11pt;
font-weight: 900;
}
#noItems{
color: lightgray;
margin-top: 50px;
/*display: none;*/
}
JS CODE
let storeInput = "";
function addIt(){
/*---addIT() start---*/
let input = document.getElementById("input");
storeInput = input.value;
if(storeInput == ""){
let errorMsg = document.getElementById("error");
errorMsg.style.display = "block";
setTimeout(function(){errorMsg.style.display = "none";}, 2000)
}else{
input.value = "";
let item = document.createElement("LI");
item.className = "item";
item.innerHTML = storeInput;
let list = document.getElementById("list");
list.appendChild(item);
let deleteIt = document.createElement("I");
deleteIt.className = "delete";
deleteIt.innerHTML = "X";
item.appendChild(deleteIt);
}
let allItems = document.querySelectorAll(".item");
for(var i = 0; i < allItems.length; i++){
allItems[i].addEventListener("click", function(){
if(this.style.textDecoration == "line-through"){
this.style.textDecoration = "none";
}else{
this.style.textDecoration = "line-through";
}
})
}
let deleteItem = document.querySelectorAll(".delete");
for(var j = 0; j < deleteItem.length; j++){
deleteItem[j].addEventListener("click", function(){
var deleteIt = this.parentElement;
deleteIt.remove();
})
}
document.querySelectorAll(".item").length;
if(allItems.length == 0){
document.getElementById("noItems").style.display = "block";
}else{
document.getElementById("noItems").style.display = "none";
}
/*---addIT() end---*/}
if you want to try the app live :
https://codepen.io/Salsa_Project/pen/NVWPaY?editors=0110
AND TY IN ADVANCE.
The function addit() adds eventlisteners to all the items and delete buttons everytime you add an element. You should only add eventlisteners to the current item. codepen
let storeInput = "";
function addIt(){
/*---addIT() start---*/
let input = document.getElementById("input");
storeInput = input.value;
if(storeInput == ""){
let errorMsg = document.getElementById("error");
errorMsg.style.display = "block";
setTimeout(function(){errorMsg.style.display = "none";}, 2000)
}else{
input.value = "";
let item = document.createElement("LI");
item.className = "item";
item.innerHTML = storeInput;
let list = document.getElementById("list");
list.appendChild(item);
let deleteIt = document.createElement("I");
deleteIt.className = "delete";
deleteIt.innerHTML = "X";
item.appendChild(deleteIt);
item.addEventListener("click", function(){
if(this.style.textDecoration == "line-through"){
this.style.textDecoration = "none";
}else{
this.style.textDecoration = "line-through";
}
});
deleteIt.addEventListener("click", function(){
var deleteIt = this.parentElement;
deleteIt.remove();
})
}
let allItems = document.querySelectorAll(".item");
document.querySelectorAll(".item").length;
if(allItems.length == 0){
document.getElementById("noItems").style.display = "block";
}else{
document.getElementById("noItems").style.display = "none";
}
/*---addIT() end---*/}
Let us use this snippit for example
for(var j = 0; j < deleteItem.length; j++){
deleteItem[j].addEventListener("click", function(){
var deleteIt = this.parentElement;
deleteIt.remove();
})
}
Here, you are running a loop, and foreach iteration, you are creating a new click event. The issue here is your not unbinding events. So, in your current code, if you click the button, it will trigger all call events, that were previously triggered.
The quickest solution for your code, is to add something like
let deleteItem = document.querySelectorAll(".delete");
for(var j = 0; j < deleteItem.length; j++){
deleteItem[j].parentNode.replaceChild(deleteItem[j].cloneNode(true), deleteItem[j]);
})
}
deleteItem = document.querySelectorAll(".delete");
for(var j = 0; j < deleteItem.length; j++){
deleteItem[j].addEventListener("click", function(){
var deleteIt = this.parentElement;
deleteIt.remove();
})
}
Note that
for(var j = 0; j < deleteItem.length; j++){
deleteItem[j].parentNode.replaceChild(deleteItem[j].cloneNode(true), deleteItem[j]);
})
}
Will replace your current element, with itself. The only differenceis, cloneNode, does not copy the event listeners. This fixes your problem.
I want to make javascript countdown continue after refreshing until the end even if page closed if possible without a database. I have done some searching but couldn't apply any on this code at all.
Can anyone help me with this one, please? I need to get it working without replacing the whole thing.
let countdown;
const timerDisplay = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');
const buttons = document.querySelectorAll('[data-time]');
function timer(seconds) {
// clear any existing timers
clearInterval(countdown);
const now = Date.now();
const then = now + seconds * 1000;
displayTimeLeft(seconds);
displayEndTime(then);
countdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);
// check if we should stop it!
if(secondsLeft < 0) {
document.getElementById('itimer').style.display = 'none'
document.getElementById('ifree').innerHTML = "done!";
document.getElementById("ifree").style.fontSize = "3.5rem";
clearInterval(interval);
clearInterval(countdown);
return;
}
// display it
displayTimeLeft(secondsLeft);
}, 1000);
document.getElementById('itimer').style.display = 'unset'
document.getElementById("ifree").style.fontSize = "15px";
}
function displayTimeLeft(seconds){
const minutes = Math.floor(seconds/60);
const remainderSeconds = seconds % 60;
const display = `${minutes}:${remainderSeconds < 10 ? '0' : '' }${remainderSeconds}`;``
document.title = display;
timerDisplay.textContent = display;
}
function displayEndTime(timestamp){
const end = new Date(timestamp);
const hour = end.getHours();
const minutes = end.getMinutes();
endTime.textContent = `... ${hour}:${minutes}`;
}
function startTimer() {
const seconds = parseInt(this.dataset.time);
timer(seconds);
}
buttons.forEach(button => button.addEventListener('click', startTimer));
document.customForm.addEventListener('submit', function(e) {
e.preventDefault();
const mins = this.minutes.value;
console.log(mins);
timer(mins * 60);
this.reset();
});
.body{
direction: rtl;
font-family: 'Droid Arabic Kufi', sans-serif;
color: black;
}
#ifree{
font-size: 15px;
color:black;
}
html {
box-sizing: border-box;
font-size: 10px;
color: black;
}
*, *:before, *:after {
box-sizing: inherit;
}
.display__time-left {
font-weight: 100;
font-size: 5rem;
margin: 12px;
color:white;
text-shadow:4px 4px 0 rgba(0,0,0,0.05);
margin-bottom: -25px;
color: black;
}
.timer {
display:flex;
min-height: 35vh;
flex-direction:column;
direction: rtl;
}
.timer__controls {
display: flex;
}
.timer__controls > * {
flex:1;
}
.timer__controls form {
flex:1;
display:flex;
}
.timer__controls input {
flex:1;
border:0;
padding:2rem;
}
.timer__button {
background:none;
border:0;
cursor: pointer;
color:black;
font-size: 2.5vh;
text-transform: uppercase;
background:rgba(0,0,0,0.1);
border-bottom:3px solid rgba(0,0,0,0.2);
border-right:1px solid rgba(0,0,0,0.2);
padding:1rem;
font-family: 'Droid Arabic Kufi', sans-serif;
}
.timer__leave {
border:0;
cursor: pointer;
color:black;
font-size: 2.5vh;
text-transform: uppercase;
background:rgba(0,0,0,0.1);
border-bottom:3px solid rgba(0,0,0,0.2);
border-right:1px solid rgba(0,0,0,0.2);
padding:1rem;
font-family: 'Droid Arabic Kufi', sans-serif;
}
.timer__button:hover,
.timer__button:focus {
background:rgba(0,0,0,0.2);
outline:0;
}
.display {
flex:1;
display:flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-height: 105px;
}
.display__end-time {
font-size: 3vh;
color:white;
font-family: 'Droid Arabic Kufi', sans-serif;
margin: 12px;
}
#media screen and (min-width: 1200px) {
timer__button {
font-size: 1px;
}
}
<body>
<div class="timer">
<div class="timer__controls">
<button data-time="1800" class="timer__button">30</button>
<button data-time="3600" class="timer__button">60</button>
<button data-time="5400" class="timer__button">90</button>
<button data-time="7200" class="timer__button">120</button>
<button data-time="14400" class="timer__button">240</button>
<button class="timer__leave" id="timer__leave">OFF</button>
<button data-time="0" class="timer__button">X</button>
</div>
<div class="display">
<h1 class="display__time-left" id="itimer"></h1>
<p class="display__end-time" id="ifree"></p>
</div>
</body>
Update the timer function
function timer(seconds) {
// clear any existing timers
clearInterval(countdown);
const now = Date.now();
const then = now + seconds * 1000;
displayTimeLeft(seconds);
displayEndTime(then);
countdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);
// check if we should stop it!
if(secondsLeft < 0) {
document.getElementById('itimer').style.display = 'none'
document.getElementById('ifree').innerHTML = "متاح الآن!";
document.getElementById("ifree").style.fontSize = "3.5rem";
clearInterval(interval);
clearInterval(countdown);
localStorage.removeItem("timeLeft")
return;
}
// display it
localStorage.timeLeft=secondsLeft;
displayTimeLeft(secondsLeft);
}, 1000);
document.getElementById('itimer').style.display = 'unset'
document.getElementById("ifree").style.fontSize = "15px";
}
then add the below condition.
if(localStorage.timeLeft){
timer(localStorage.timeLeft);
}
Maybe use localStorage?
Add 3 additional functions:
function loadTimeLeft() {
return JSON.parse(localStorage.timeLeft)
}
function persistTimeLeft(timeLeft) {
localStorage.timeLeft = JSON.stringify(timeLeft)
}
function clearTimeLeft() {
localStorage.removeItem("timeLeft")
}
Then just plug it in:
window.onload = function() {
const seconds = loadTimeLeft()
if (seconds) {
timer(seconds)
}
}
function timer(seconds) {
....
countdown = setInterval(() => {
if(secondsLeft < 0) {
....
clearTimeLeft() //added at the end of if statement
return
}
displayTimeLeft(secondsLeft)
persistTimeLeft(secondsLeft) //added at the end of callback
}, 1000)
...