I copied some code from here.
The following code has some errors when the value reaches the minFontSize or maxFontSize.
I don't know how to fix this...
const decreaseFontSizeBtn = document.querySelector(".fontsize-via-btn #decrease");
const increaseFontSizeBtn = document.querySelector(".fontsize-via-btn #increase");
const fontSizeDisplay = document.querySelector(".fontsize-via-btn .current-fontsize");
const defaultFontSize = 20;
const minFontSize = 16;
const maxFontSize = 40;
let currentFontSize = defaultFontSize;
var timeout, interval;
[decreaseFontSizeBtn, increaseFontSizeBtn].forEach(btn => {
btn.addEventListener("mousedown", () => {
if (btn.id === "decrease") {
decreaseFontSize();
hold(decreaseFontSize);
}
if (btn.id === "increase") {
increaseFontSize();
hold(increaseFontSize);
}
saveFontSize();
})
btn.addEventListener("mouseup", clearTimers);
btn.addEventListener("mouseleave", clearTimers);
function clearTimers() {
clearTimeout(timeout);
clearInterval(interval);
}
})
function hold(func) {
timeout = setTimeout(() => {
interval = setInterval(() => {
func();
saveFontSize();
}, 50)
}, 300)
}
function decreaseFontSize() {
if (currentFontSize > minFontSize) {
currentFontSize -= 2;
}
if (currentFontSize === minFontSize) {
decreaseFontSizeBtn.disabled = true;
} else {
increaseFontSizeBtn.disabled = false;
}
}
function increaseFontSize() {
if (currentFontSize < maxFontSize) {
currentFontSize += 2;
}
if (currentFontSize === maxFontSize) {
increaseFontSizeBtn.disabled = true;
} else {
decreaseFontSizeBtn.disabled = false;
}
}
function saveFontSize() {
fontSizeDisplay.textContent = currentFontSize;
// localStorage ...
}
.fontsize-via-btn {
width: 100px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
font-size: 2rem;
}
<div class="fontsize-via-btn">
<button id="decrease">A-</button>
<div class="current-fontsize">20</div>
<button id="increase">A+</button>
</div>
Your timers are not cleared when you hit the minimum or maximum because (as #timmmmmb already said) disabled buttons don't trigger mouse events. Thus, when you try to go in the other direction, the original timer is again executed.
The simplest would probably be, calling clearTimers also when you hit the end of the range
const decreaseFontSizeBtn = document.querySelector(".fontsize-via-btn #decrease");
const increaseFontSizeBtn = document.querySelector(".fontsize-via-btn #increase");
const fontSizeDisplay = document.querySelector(".fontsize-via-btn .current-fontsize");
const defaultFontSize = 20;
const minFontSize = 16;
const maxFontSize = 40;
let currentFontSize = defaultFontSize;
var timeout, interval;
function clearTimers() {
clearTimeout(timeout);
clearInterval(interval);
}
[decreaseFontSizeBtn, increaseFontSizeBtn].forEach(btn => {
btn.addEventListener("mousedown", () => {
if (btn.id === "decrease") {
decreaseFontSize();
hold(decreaseFontSize);
}
if (btn.id === "increase") {
increaseFontSize();
hold(increaseFontSize);
}
saveFontSize();
})
btn.addEventListener("mouseup", clearTimers);
btn.addEventListener("mouseleave", clearTimers);
})
function hold(func) {
timeout = setTimeout(() => {
interval = setInterval(() => {
func();
saveFontSize();
}, 50)
}, 300)
}
function decreaseFontSize() {
if (currentFontSize > minFontSize) {
currentFontSize -= 2;
}
if (currentFontSize === minFontSize) {
decreaseFontSizeBtn.disabled = true;
clearTimers();
} else {
increaseFontSizeBtn.disabled = false;
}
}
function increaseFontSize() {
if (currentFontSize < maxFontSize) {
currentFontSize += 2;
}
if (currentFontSize === maxFontSize) {
clearTimers();
increaseFontSizeBtn.disabled = true;
} else {
decreaseFontSizeBtn.disabled = false;
}
}
function saveFontSize() {
fontSizeDisplay.textContent = currentFontSize;
// localStorage ...
}
.fontsize-via-btn {
width: 100px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
font-size: 2rem;
}
<div class="fontsize-via-btn">
<button id="decrease">A-</button>
<div class="current-fontsize">20</div>
<button id="increase">A+</button>
</div>
I think the problem is, that when you reach the max Fontsize you disable the button and that means your mouseup event will not be triggerd. I moved the mouseup event away from the buttons and on the container and i think it works now.
const decreaseFontSizeBtn = document.querySelector(".fontsize-via-btn #decrease");
const increaseFontSizeBtn = document.querySelector(".fontsize-via-btn #increase");
const fontSizeDisplay = document.querySelector(".fontsize-via-btn .current-fontsize");
const fontSizeContainer = document.querySelector(".fontsize-via-btn");
const defaultFontSize = 20;
const minFontSize = 16;
const maxFontSize = 40;
let currentFontSize = defaultFontSize;
var timeout, interval;
fontSizeContainer.addEventListener("mouseup", clearTimers);
fontSizeContainer.addEventListener("mouseleave", clearTimers);
function clearTimers() {
clearTimeout(timeout);
clearInterval(interval);
}
[decreaseFontSizeBtn, increaseFontSizeBtn].forEach(btn => {
btn.addEventListener("mousedown", () => {
if (btn.id === "decrease") {
decreaseFontSize();
hold(decreaseFontSize);
}
if (btn.id === "increase") {
increaseFontSize();
hold(increaseFontSize);
}
saveFontSize();
})
})
function hold(func) {
timeout = setTimeout(() => {
interval = setInterval(() => {
func();
saveFontSize();
}, 50)
}, 300)
}
function decreaseFontSize() {
if (currentFontSize > minFontSize) {
currentFontSize -= 2;
}
if (currentFontSize === minFontSize) {
decreaseFontSizeBtn.disabled = true;
} else {
increaseFontSizeBtn.disabled = false;
}
}
function increaseFontSize() {
if (currentFontSize < maxFontSize) {
currentFontSize += 2;
}
if (currentFontSize === maxFontSize) {
increaseFontSizeBtn.disabled = true;
} else {
decreaseFontSizeBtn.disabled = false;
}
}
function saveFontSize() {
fontSizeDisplay.textContent = currentFontSize;
// localStorage ...
}
.fontsize-via-btn {
width: 100px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
font-size: 2rem;
}
<div class="fontsize-via-btn">
<button id="decrease">A-</button>
<div class="current-fontsize">20</div>
<button id="increase">A+</button>
</div>
Discrepancies
"mouseup" and "mouseleave" needs to be registered on each button or the events must be delegated to the buttons. Right now the mouse events only affect the <div> which doesn't have any functions firing off on it. So that's why the buttons get stuck -- they are consantly repeating themselves even after the user releases the mousebutton.
The example below has separate event handlers for each button. Normally I prefer to use one event handler to control everything through
event delegation, but because of the need to use set\clearInterval() as event handlers, the event object gets lost. I could solve that problem with a closure, but your code was close enough that a radical change wouldn't be to your benifet.
Saving with localStorage (I know it's not part of the question) is omitted from this version since this site blocks it's use. I wrote another version that saves the current font-size and loads it as well, to review that one go to this Plunker.
const io = document.forms.UI.elements;
let current = 1.5;
let repeatInc = null;
let repeatDec = null;
function holdInc(e) {
if (repeatInc === null) {
repeatInc = setInterval(incFontSize, 100);
}
};
function releaseInc(e) {
if (repeatInc != null) {
clearInterval(repeatInc);
repeatInc = null;
}
};
function incFontSize() {
const io = document.forms.UI.elements;
const max = 4;
if (current < max) {
current += 0.25;
io.dec.disabled = false;
}
if (current == max) {
io.inc.disabled = true;
releaseInc();
}
io.fSize.value = current.toFixed(2);
io.text.style.fontSize = `${current}rem`
};
function holdDec(e) {
if (repeatDec == null) {
repeatDec = setInterval(decFontSize, 100);
}
};
function releaseDec(e) {
if (repeatDec != null) {
clearInterval(repeatDec);
repeatDec = null;
}
};
function decFontSize() {
const io = document.forms.UI.elements;
const min = 1;
if (current > min) {
current -= 0.25;
io.inc.disabled = false;
}
if (current == min) {
io.dec.disabled = true;
releaseDec()
}
io.fSize.value = current.toFixed(2);
io.text.style.fontSize = `${current}rem`
};
io.inc.addEventListener('mousedown', holdInc);
io.inc.addEventListener('mouseup', releaseInc);
io.inc.addEventListener('mousemove', releaseInc);
io.dec.addEventListener('mousedown', holdDec);
io.dec.addEventListener('mouseup', releaseDec);
io.dec.addEventListener('mouseleave', releaseDec);
:root {
font: 2ch/1 'Segoe UI'
}
body {
font-size: 1ch;
}
.ctrl {
display: flex;
align-items: center;
justify-content: flex-start;
font-size: 1rem;
padding: 5px;
}
#fSize {
display: block;
width: 5ch;
margin: 0 4px;
font-family: Consolas;
text-align: center;
}
button {
display: block;
width: max-content;
font: inherit;
cursor: pointer;
}
label {
display: block;
width: max-content;
margin: 0 8px;
font-size: 1rem;
}
.text {
min-height: 50px;
font-size: 1.25rem;
}
<form id='UI'>
<fieldset name='ctrl' class='ctrl'>
<button id="dec" type='button'>🗛-</button>
<output id="fSize">1.50</output>
<button id="inc" type='button'>🗚+</button>
<label>Scale: 1ch => 1rem</label>
</fieldset>
<fieldset name='text' class='text' contenteditable>
This test area has editable content
</fieldset>
</form>
Related
I want to change the paragraph text when the next arrow is clicked. I can change it once but if I want to change it to a third option, it's not working. Can someone explain why this is the case?
I have made a Codepen with the issue: Conditional statement problem
<div class="tutNavigation">
<div class="flexNavigation">
<div id="back"><i id="arrow-left"><-</i></div>
<div class="tutorialText">
<p></p>
</div>
<div id="next"><i id="arrow-right">-></i></div>
</div>
</div>
let text = document.querySelector("p");
text.textContent = "text1";
let backLeft = document.getElementById("back");
let arrowBack = document.getElementById("arrow-left");
let nextRight = document.getElementById("next");
let arrowNext = document.getElementById("arrow-right");
if ((text.textContent = "text1")) {
arrowBack.classList.add("hidden");
nextRight.addEventListener("click", () => {
arrowBack.classList.remove("hidden");
text.textContent = "text2";
});
backLeft.addEventListener("click", () => {
arrowBack.classList.add("hidden");
text.textContent = "text1";
});
} else if ((text.textcontent = "text2")) {
nextRight.addEventListener("click", () => {
text.textContent = "text3";
});
backLeft.addEventListener("click", () => {
text.textContent = "text2";
});
} else {
text.textContent = "none";
}
Conditions need to be added in the event listener and based on the conditions, hide or show elements
let text = document.querySelector("p");
text.textContent = "text1";
let backLeft = document.getElementById("back");
let arrowBack = document.getElementById("arrow-left");
let nextRight = document.getElementById("next");
let arrowNext = document.getElementById("arrow-right");
arrowBack.classList.add("hidden");
nextRight.addEventListener("click", () => {
arrowBack.classList.remove("hidden");
if (text.textContent === "text1") {
text.textContent = "text2";
} else if (text.textContent === "text2") {
text.textContent = "text3";
}
});
backLeft.addEventListener("click", () => {
if (text.textContent === "text3") {
text.textContent = "text2";
} else if (text.textContent === "text2") {
text.textContent = "text1";
arrowBack.classList.add("hidden");
}
});
body {
background-color: black;
}
.tutNavigation {
display: flex;
padding: 3rem 2rem;
box-shadow: 0px -4px 4px rgba(0, 0, 0, 0.25);
flex-direction: column;
flex-wrap: nowrap;
align-content: center;
gap: 1rem;
}
.tutNavigation.flexNavigation {
display: flex;
align-items: center;
justify-content: space-evenly;
flex-wrap: nowrap;
gap: 1rem;
flex-direction: row;
}
.flexNavigation.tutorialText {
text-align: center;
max-width: 500px;
}
p {
color: white;
font-size: 16px;
line-height: 1.3rem;
}
#back,
#next {
padding: 1rem;
cursor: pointer;
border-radius: 5px;
width: 72px;
}
i {
font-size: 40px;
color: white;
}
.hidden {
display: none;
}
<div class="tutNavigation">
<div class="flexNavigation">
<div id="back"><i id="arrow-left"><-</i></div>
<div class="tutorialText">
<p></p>
</div>
<div id="next"><i id="arrow-right">-></i></div>
</div>
</div>
You should pull out the eventListerens form the conditions!
Beacouse you want to do something if you clicking on the arrows!
And inside the eventListeners you should write the logic.
const text = document.querySelector("p");
const possiblities = ["text1", "text2", "text3", "text4"];
let index = 0;
let backLeft = document.getElementById("back");
let arrowBack = document.getElementById("arrow-left");
let nextRight = document.getElementById("next");
let arrowNext = document.getElementById("arrow-right");
const checkAndHideArrows = () => {
if (index >= possiblities.length - 1) {
nextRight.classList.add("hidden");
arrowNext.classList.add("hidden");
console.log("hide right");
} else {
nextRight.classList.remove("hidden")
arrowNext.classList.remove("hidden")
console.log("show right");
}
if (index <= 0) {
backLeft.classList.add("hidden");
arrowBack.classList.add("hidden");
console.log("hide left");
} else {
backLeft.classList.remove("hidden");
arrowBack.classList.remove("hidden");
console.log("show left");
}
}
const setText = () => {
text.textContent = possiblities[index];
console.log(possiblities[index]);
checkAndHideArrows();
};
const next = () => {
if (index++ >= possiblities.length - 1) {
index = possiblities.length - 1;
}
};
const prev = () => {
if (index-- <= 0) {
index = 0;
}
};
setText();
nextRight.addEventListener("click", () => {
next();
console.log(index);
setText();
});
backLeft.addEventListener("click", () => {
prev();
console.log(index);
setText();
});
.hidden {
color: transparent;
}
<div class="tutNavigation">
<div class="flexNavigation">
<div id="back"><i id="arrow-left"><-</i></div>
<div class="tutorialText">
<p></p>
</div>
<div id="next"><i id="arrow-right">-></i></div>
</div>
</div>
I need a small help.
I'm at the beginning of my way with programming in Javascript. I'm trying do a calculator. I have a problem with '='. Don't show me a score, when I've clicked on it. Please, tell me, where I do a mistake?
here is my git: https://github.com/madzikowael/calculator/blob/main/script.js
const calculate = () => {
let action;
if(!previousOperation || !actualOperation) {
return
}
const previous = parseFloat(previousOperation)
const actual = parseFloat(actualOperation)
if(isNaN(previous) || isNan(actual)){
return
}
switch (operation) {
case '+':
action = previous + actual
break
case '-':
action = previous - actual
break
case '×':
action = previous * actual
break
case '÷':
if(actual === 0) {
deleteScore()
return
}
action = previous / actual
break
case '^':
action = Math.pow(previous, actual)
break
case '√':
action = Math.pow(previous, 1 / actual)
break
case '%':
action = previous / 100 * actual
break
case 'log':
action = Math.log(previous) / Math.log(actual)
break
default:
return
}
actualOperation = action
operation = undefined
previousOperation = ''
}
const chooseOperation = (operator) => {
if(actualOperation === '') {
return
}
if(previousOperation !== '') {
const previous = previousOperation.innerText
if(actualOperation.toString() === '0' && previous[previous.length - 1] === '÷') {
deleteScore()
return
}
calculate()
}
operation = operator;
previousOperation = actualOperation;
actualOperation = '';
}
const updateScore = () => {
actualScore.innerText = actualOperation;
if(operation != null) {
previousScore.innerText = previousOperation + operation
} else {
previousScore.innerText = ''
}
}
numbers.forEach((numb) => {
numb.addEventListener('click', () => {
addNumber(numb.innerText);
updateScore();
})
})
del.addEventListener('click', () => {
deleteNumber();
updateScore();
})
operators.forEach((operator) => {
operator.addEventListener('click', () => {
chooseOperation(operator.innerText);
updateScore();
})
})
total.addEventListener('click', () => {
calculate();
updateScore();
})
clean.addEventListener('click', () => {
deleteScore();
updateScore();
})
It's because of this line:
if(isNaN(previous) || isNan(actual)){
return
}
the function isNan() does not exist. Therefore an error is thrown and the calculate() function is aborted.
Replace it by:
if(isNaN(previous) || isNaN(actual)){
return
}
I see it's just a typo, change isNan(actual) to isNaN(actual).
As i'm unable to edit the actual question, added code snippets here.
const numbers = document.querySelectorAll('.number');
const operators = document.querySelectorAll('.operator');
const clean = document.querySelector('.clean');
const del = document.querySelector('.delete');
const total = document.querySelector('.total');
const previousScore = document.querySelector('.previous-operation');
const actualScore = document.querySelector('.actual-operation');
let actualOperation = '';
let operation = undefined;
let previousOperation = '';
const calculate = () => {
let action;
if(!previousOperation || !actualOperation) {
return
}
const previous = parseFloat(previousOperation)
const actual = parseFloat(actualOperation)
if(isNaN(previous) || isNaN(actual)){
return
}
switch (operation) {
case '+':
action = previous + actual
break
case '-':
action = previous - actual
break
case '×':
action = previous * actual
break
case '÷':
if(actual === 0) {
deleteScore()
return
}
action = previous / actual
break
case '^':
action = Math.pow(previous, actual)
break
case '√':
action = Math.pow(previous, 1 / actual)
break
case '%':
action = previous / 100 * actual
break
case 'log':
action = Math.log(previous) / Math.log(actual)
break
default:
return
}
actualOperation = action
operation = undefined
previousOperation = ''
}
const chooseOperation = (operator) => {
if(actualOperation === '') {
return
}
if(previousOperation !== '') {
const previous = previousOperation.innerText
if(actualOperation.toString() === '0' && previous[previous.length - 1] === '÷') {
deleteScore()
return
}
calculate()
}
operation = operator;
previousOperation = actualOperation;
actualOperation = '';
}
const addNumber = (numb) => {
if(numb === '.') {
if(actualOperation.includes('.')) {
return
}
numb = '.'
}
actualOperation = actualOperation.toString() + numb.toString();
}
const deleteNumber = () => {
actualOperation = actualOperation.toString().slice(0, -1)
}
const updateScore = () => {
actualScore.innerText = actualOperation;
if(operation != null) {
previousScore.innerText = previousOperation + operation
} else {
previousScore.innerText = ''
}
}
const deleteScore = () => {
actualOperation = ''
operation = undefined
previousOperation = ''
}
numbers.forEach((numb) => {
numb.addEventListener('click', () => {
addNumber(numb.innerText);
updateScore();
})
})
del.addEventListener('click', () => {
deleteNumber();
updateScore();
})
operators.forEach((operator) => {
operator.addEventListener('click', () => {
chooseOperation(operator.innerText);
updateScore();
})
})
total.addEventListener('click', () => {
calculate();
updateScore();
})
clean.addEventListener('click', () => {
deleteScore();
updateScore();
})
#import url('https://fonts.googleapis.com/css2?family=Dela+Gothic+One&display=swap');
*, *::after, *::before {
box-sizing: border-box;
font-family: 'Dela Gothic One', sans-serif;
font-size: 22px;
font-weight: 500;
color: white;
}
body {
padding: 0;
margin: 0;
background: #6c757d;
}
.calculator {
margin: 25px;
display: grid;
justify-content: center;
align-content: center;
grid-template-columns: repeat(5, 80px);
grid-template-rows: minmax(120px, auto) repeat(5, 80px);
min-height: 70vh;
}
.score {
grid-column: 1 / -1;
background-color: #333533;
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: space-between;
padding: 20px;
box-shadow: 0px 4px 25px -10px rgba(0, 0, 0, 0.75);
word-wrap: break-word;
word-break: break-all;
}
.previous-operation {
font-size: 16px;
font-weight: 400;
color: rgba(255, 255, 255, .8);
}
.actual-operation {
font-size: 30px;
}
button {
cursor: pointer;
border: 1px solid #333533;
background: #242423;
outline: none;
}
button:hover, button:focus {
background: rgba(36, 36, 35, .95);
}
.col-two {
grid-column: span 2;
}
.row-two {
grid-row: span 2;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width-device-width, initial-scale=1.0">
<title>Najlepszy kalkulator</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body>
<div class="calculator">
<div class="score">
<div class="previous-operation"></div>
<div class="actual-operation"></div>
</div>
<button class="clean col-two">AC</button>
<button class="delete">DEL</button>
<button class="operator">√</button>
<button class="operator">÷</button>
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button class="operator">^</button>
<button class="operator">×</button>
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button class="operator">%</button>
<button class="operator">-</button>
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button class="operator">log</button>
<button class="operator row-two">+</button>
<button class="number">.</button>
<button class="number">0</button>
<button class="total col-two">=</button>
</div>
</body>
</html>
I have this function which will deal a card to a player, then to a dealer, then to a player and then to a dealer.
I have tried to use setTimeout(function, milliseconds); but it doesn't work. For example, if I set 2 seconds, it will wait for 4 seconds, then deal the 2 cards to the player and then straight away to dealer 2 cards or it will wait for 8 seconds, then in one batch deal all the cards out.
Here are my methods:
const dealOneCardToPlayer = () => {
// Take a card from the top deck to be assigned to tempcard.
tempCard = deck.cards.splice(0, 1);
//console.log(tempCard);
player.cards.push(tempCard);
if (player.cards.length === 5) {
player.canHit = false;
}
if (player.canHit) {
$("#btnHit").show();
} else {
$("#btnHit").hide();
}
player.handValue = countHandValue(player.cards);
makeCardPlayer(tempCard[0]);
}
const dealOneCardToDealer = (holeCard) => {
// Take a card from the top deck to be assigned to tempcard.
tempCard = deck.cards.splice(0, 1);
dealer.cards.push(tempCard);
if (dealer.cards.length === 5) {
dealer.canHit = false;
}
if (dealer.canHit) {
$("#btnHit").show();
} else {
$("#btnHit").hide();
}
dealer.handValue = countHandValue(dealer.cards);
makeCardDealer(tempCard[0],holeCard);
}
const deal = () => {
debugger;
newDeck();
// Option: to burn first card before deal a card
// to the first player
burnOneCard;
dealOneCardToPlayer();
dealOneCardToDealer(false);
dealOneCardToPlayer();
// true for hole card
dealOneCardToDealer(true);
showGameButtons(true);
checkEndGame1();
checkGameOver();
}
<link href="check.css" rel="stylesheet" />
<style>
body{
font-size: 2em;
}
h3, h5 {
text-align: center;
}
h5{
margin-top:-40px;
}
/*debugging purpose*/
div#oneDeck {
border: 1px solid green;
margin: 10px;
padding: 10px;
}
/*debugging purpose*/
div#playerCards {
border: 1px solid blue;
margin: 10px;
padding: 10px;
}
/*debugging purpose*/
div#dealerCards {
border: 1px solid red;
margin: 10px;
padding: 10px;
}
#mainContainer {
max-width: 600px;
margin: 0 auto;
}
fieldset {
margin-top: 30px;
border: 1px solid #999;
border-radius: 8px;
box-shadow: 0 0 10px #999;
}
legend {
background: #fff;
}
#cardContainerPlayer {
display: flex;
flex-wrap: wrap;
}
.card {
display: inline-block;
vertical-align: top; /*float: left;*/
text-align: center;
margin: 5px;
padding: 10px;
width: 70px;
height: 100px;
font-size: 26px;
background-color: black;
border: solid 1px black;
color: white;
border-radius: 10px;
}
.holeCard {
/*visibility: hidden;*/
border: solid 1px black;
background: repeating-linear-gradient( 45deg, #606dbc, #606dbc 10px, #465298 10px, #465298 20px );
}
.red {
background-color: red;
border: solid 1px #8C001A;
}
.templatePlayer, .templateDealer {
display: none;
}
#btnGame {
margin: 10px;
}
.winner {
border: solid 5px #7ac142;
}
.btnGame {
background-color: dodgerblue; /* Green */
border: none;
color: white;
padding: 15px 32px;
/*border-radius:10px;*/
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
cursor: pointer;
-webkit-transition-duration: 0.4s; /* Safari */
transition-duration: 0.4s;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
}
#btnHit {
margin-right: 20px;
}
.flex-container {
padding: 0;
margin: 0;
display: flex;
justify-content: space-between;
max-width: 100%;
overflow: auto;
/*border: 1px solid red*/
}
</style>
<h3>Simple Javascript BlackJack Game</h3>
<h5>developed by Steve Ngai</h5>
<div id="mainContainer">
<div id="btnDevelopment">
<input type='button' value='Create new Deck' onclick='newDeck();' />
<input type='button' value='Burn a card' onclick='burnOneCard();' />
<input type='button' value='Refresh Deck' onclick='showDeck();' />
<input type='button' value='Deal a card to Player' onclick='dealOneCardToPlayer();' />
<input type='button' value='Deal a card to Dealer' onclick='dealOneCardToDealer();' />
<input type='button' value='Show hand value' onclick='showHandValue();' />
<input type='button' value='Check end game' onclick='checkEndGame();' />
<input type='button' value='Refresh deck remaining cards count' onclick='getDeckCardCount();' />
</div>
<fieldset id="deck">
<legend>Remaining cards in the Deck: <span id="deckCardCount"></span></legend>
<div id="oneDeck"></div>
</fieldset>
<fieldset id="containerDealer">
<legend>Dealer (Hand Value: <span id="handValueDealer"></span>)</legend>
<div style="width:30px">
<svg class="checkmarkDealer" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" />
<path class="checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8" />
</svg>
</div>
<div id="dealerCards"></div>
<div id="cardContainerDealer">
<div class="card templateDealer">
<span class="dealerCardFace"></span>
<span class="dealerCardSuit"></span>
</div>
</div>
<div id="dealerCardsHandValue"></div>
</fieldset>
<div id="btnGame">
<div class="flex-container">
<div class="btn">
<input type='button' class="btnGame" id="btnDeal" value='Deal' onclick='deal();' />
</div>
<div class="btn">
<input type='button' class="btnGame" id="btnHit" value='Hit' onclick='hit();' />
<input type='button' class="btnGame" id="btnStand" value='Stand' onclick='stand();' />
</div>
</div>
</div>
<fieldset id="containerPlayer">
<legend>Player (Hand Value: <span id="handValuePlayer"></span>)</legend>
<div style="width:30px">
<svg class="checkmarkPlayer" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" />
<path class="checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8" />
</svg>
</div>
<div id="playerCards"></div>
<div id="cardContainerPlayer">
<div class="card templatePlayer">
<span class="playerCardFace"></span>
<span class="playerCardSuit"></span>
</div>
</div>
<div id="playerCardsHandValue"></div>
</fieldset>
<fieldset id="result">
<legend>Game Result</legend>
<div id="gameResult"></div>
</fieldset>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
"use strict";
// Variable/Object declaration and initialization - Start
const isDebug = false;
const DELAY = 2000;
var gameOver = false;
const deck = {
cards: []
}
var tempCard;
const player = {
cards: [],
handValue: 0,
isWinner: false,
canHit: true
}
const dealer = {
cards: [],
handValue: 0,
isWinner: false,
canHit: true
}
var result = document.getElementById("gameResult");
const cardSuit = ["hearts", "diams", "clubs", "spades"];
const cardFace = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"];
$(".checkmarkDealer").hide();
$(".checkmarkPlayer").hide();
$("#handValueDealer").hide();
//Variable/Object declaration and initialization - End
if (!isDebug) {
document.getElementById("btnDevelopment").style.display = "none";
document.getElementById("deck").style.display = "none";
document.getElementById("oneDeck").style.display = "none";
document.getElementById("playerCards").style.display = "none";
document.getElementById("dealerCards").style.display = "none";
//document.getElementById("result").style.display = "none";
} else {
document.getElementById("btnDevelopment").style.display = "block";
document.getElementById("deck").style.display = "block";
document.getElementById("oneDeck").style.display = "block";
document.getElementById("playerCards").style.display = "block";
document.getElementById("dealerCards").style.display = "block";
//document.getElementById("result").style.display = "block";
}
const showGameButtons = (cardDealt) => {
if (cardDealt) {
$("#btnDeal").hide();
$("#btnHit").show();
$("#btnStand").show();
//document.getElementById("btnDeal").disabled = true;
//document.getElementById("btnHit").disabled = false;
//document.getElementById("btnStand").disabled = false;
} else {
$("#btnDeal").show();
$("#btnHit").hide();
$("#btnStand").hide();
//document.getElementById("btnDeal").disabled = false;
//document.getElementById("btnHit").disabled = true;
//document.getElementById("btnStand").disabled = true;
}
if (player.isWinner === true) {
document.getElementById("containerDealer").classList.remove("winner");
document.getElementById("containerPlayer").classList.add("winner");
$("#handValueDealer").show();
$(".checkmarkPlayer").show();
$(".checkmarkDealer").hide();
} else if (dealer.isWinner === true) {
document.getElementById("containerPlayer").classList.remove("winner");
document.getElementById("containerDealer").classList.add("winner");
$("#handValueDealer").show();
$(".checkmarkPlayer").hide();
$(".checkmarkDealer").show();
} else {
}
}
showGameButtons(false);
// In JavaScript, functions are objects.
// You can work with functions as if they were objects.
function card(suit, face) {
this.suit = suit;
this.face = face;
switch (face) {
case "A":
this.faceValue = 11;
break;
case "J":
case "Q":
case "K":
this.faceValue = 10;
break;
default:
this.faceValue = parseInt(face);
break;
}
};
const createDeck = () => {
deck.cards = [];
deck.cards.length = 0;
cardSuit.forEach(function (suit) {
cardFace.forEach(function (face) {
deck.cards.push(new card(suit, face));
});
});
}
const shuffleDeck = () => {
// Fisher–Yates shuffle algorithm
let temp, i, rnd;
for (i = 0; i < deck.cards.length; i++) {
rnd = Math.floor(Math.random() * deck.cards.length);
temp = deck.cards[i];
deck.cards[i] = deck.cards[rnd];
deck.cards[rnd] = temp;
}
}
const newDeck = () => {
createDeck();
shuffleDeck();
document.getElementById("oneDeck").innerHTML = "";
player.cards = [];
player.handValue = 0;
dealer.cards = [];
dealer.handValue = 0;
var myNode = document.getElementById("cardContainerPlayer");
var fc = myNode.firstChild.firstChild;
while (fc) {
myNode.removeChild(fc);
fc = myNode.firstChild;
}
var myNodeDealer = document.getElementById("cardContainerDealer");
var fcDealer = myNodeDealer.firstChild.firstChild;
while (fcDealer) {
myNodeDealer.removeChild(fcDealer);
fcDealer = myNodeDealer.firstChild;
}
document.getElementById("playerCards").innerHTML = "";
document.getElementById("dealerCards").innerHTML = "";
document.getElementById("oneDeck").innerHTML = JSON.stringify(deck);
}
const burnOneCard = () => {
// Remove the top deck to burn
deck.cards.splice(0, 1);
}
const showDeck = () => {
document.getElementById("oneDeck").innerHTML = JSON.stringify(deck);
}
const dealOneCardToPlayer = () => {
return new Promise(function (resolve) {
setTimeout(function () {
// Take a card from the top deck to be assigned to tempcard.
tempCard = deck.cards.splice(0, 1);
//console.log(tempCard);
player.cards.push(tempCard);
if (player.cards.length === 5) {
player.canHit = false;
}
if (player.canHit) {
$("#btnHit").show();
} else {
$("#btnHit").hide();
}
//player.cards.push(new card("Spades","A"));
//player.cards.push(new card("Spades","10"));
document.getElementById("playerCards").innerHTML = JSON.stringify(player);
player.handValue = countHandValue(player.cards);
document.getElementById("handValuePlayer").innerHTML = player.handValue;
makeCardPlayer(tempCard[0]);
resolve();
}, DELAY);
});
}
const dealOneCardToDealer = (holeCard) => {
return new Promise(function (resolve) {
setTimeout(function () {
// Take a card from the top deck to be assigned to tempcard.
tempCard = deck.cards.splice(0, 1);
dealer.cards.push(tempCard);
if (dealer.cards.length === 5) {
dealer.canHit = false;
}
if (dealer.canHit) {
$("#btnHit").show();
} else {
$("#btnHit").hide();
}
document.getElementById("dealerCards").innerHTML = JSON.stringify(dealer);
dealer.handValue = countHandValue(dealer.cards);
document.getElementById("handValueDealer").innerHTML = dealer.handValue;
makeCardDealer(tempCard[0], holeCard);
resolve();
}, DELAY);
});
}
const hasAceInHand = (cardsOnHand) => {
for (let key in cardsOnHand) {
let arr = cardsOnHand[key];
for (let i = 0; i < arr.length; i++) {
let obj = arr[i];
for (let prop in obj) {
if (prop === "face") {
if (obj[prop] === "A") {
return true;
}
}
}
}
}
return false;
}
const countHandValue = (cardsOnHand) => {
//console.log(hasAceInHand(cardsOnHand));
let sum = 0;
for (let key in cardsOnHand) {
let arr = cardsOnHand[key];
for (let i = 0; i < arr.length; i++) {
let obj = arr[i];
for (let prop in obj) {
if (prop === "faceValue") {
//console.log(prop + " = " + obj[prop]);
sum = sum + obj[prop];
debugger;
if (sum > 21 && hasAceInHand(cardsOnHand)) {
// Transfer Ace's face value from 11 to 1
sum = sum - 11;
sum = sum + 1;
}
}
}
}
}
return sum;
}
const showHandValue = () => {
document.getElementById("playerCardsHandValue").innerHTML = player.handValue;
document.getElementById("dealerCardsHandValue").innerHTML = dealer.handValue;
}
const getDeckCardCount = () => {
document.getElementById("deckCardCount").innerHTML = deck.cards.length;
}
const checkGameOver = () => {
if (gameOver) {
$(".holeCard > :nth-child(1)").show();
$(".holeCard > :nth-child(2)").show();
$(".holeCard").removeClass("holeCard");
$("#handValueDealer").show();
showGameButtons(false);
}
}
const checkEndGame1 = () => {
gameOver = true;
if (player.handValue === 21 && dealer.handValue !== 21) {
result.innerHTML = "BlackJack! Player won.";
player.isWinner = true;
} else if (player.handValue !== 21 && dealer.handValue === 21) {
result.innerHTML = "BlackJack! Dealer won.";
dealer.isWinner = true;
} else if (player.handValue === 21 && dealer.handValue === 21) {
result.innerHTML = "Push.";
} else {
gameOver = false;
}
}
const checkEndGame2 = () => {
if (player.cards.length <= 5 && player.handValue > 21) {
result.innerHTML = "Bust! Dealer won.";
dealer.isWinner = true;
gameOver = true;
}
}
const checkEndGame3 = () => {
if (player.cards.length <= 5 && dealer.cards.length <= 5) {
// Check bust
if (player.handValue <= 21 && dealer.handValue > 21) {
result.innerHTML = "Bust! Player won.";
player.isWinner = true;
} else if (player.handValue === 21 && dealer.handValue !== 21) {
result.innerHTML = "BlackJack! Player won.";
player.isWinner = true;
} else if (player.handValue !== 21 && dealer.handValue === 21) {
result.innerHTML = "BlackJack! Dealer won.";
dealer.isWinner = true;
} else if (player.handValue === dealer.handValue) {
result.innerHTML = "Push.";
} else if (player.handValue > dealer.handValue) {
result.innerHTML = "Player won.";
player.isWinner = true;
} else if (player.handValue < dealer.handValue) {
result.innerHTML = "Dealer won.";
dealer.isWinner = true;
} else {
result.innerHTML = "Error";
}
} else {
result.innerHTML = "Error";
}
gameOver = true;
}
// This function use JQuery lib
function makeCardPlayer(_card) {
// .card is created in the template card css class
var card = $(".card.templatePlayer").clone();
card.removeClass("templatePlayer");
// .cardFace is created in the template card css class
// It will search for this css class and add the content aka innerHTML
card.find(".playerCardFace").html(_card.face);
// .suit is created in the template card css class
// It will search for this css class and add the content aka innerHTML
card.find(".playerCardSuit").html("&" + _card.suit + ";");
// ♠-> ♠, ♣ -> ♣, ♥ -> ♥, ♦ -> ♦
// more char, https://www.w3schools.com/charsets/ref_utf_symbols.asp
// hearts and diamonds are red color. otherwise, default black color.
if (_card.suit === "hearts" || _card.suit === "diams") {
card.addClass("red");
}
// option: replace previous card with new card (show one card all the time)
$("#cardContainerPlayer").append(card);
}
// This function use JQuery lib
function makeCardDealer(_card, _holeCard) {
// .card is created in the template card css class
var card = $(".card.templateDealer").clone();
card.removeClass("templateDealer");
// .cardFace is created in the template card css class
// It will search for this css class and add the content aka innerHTML
card.find(".dealerCardFace").html(_card.face);
// .suit is created in the template card css class
// It will search for this css class and add the content aka innerHTML
card.find(".dealerCardSuit").html("&" + _card.suit + ";");
// ♠-> ♠, ♣ -> ♣, ♥ -> ♥, ♦ -> ♦
// more char, https://www.w3schools.com/charsets/ref_utf_symbols.asp
// hearts and diamonds are red color. otherwise, default black color.
if (_card.suit === "hearts" || _card.suit === "diams") {
card.addClass("red");
}
if (_holeCard) {
card.addClass("holeCard");
}
// option: replace previous card with new card (show one card all the time)
$("#cardContainerDealer").append(card);
$(".holeCard > :nth-child(1)").hide();
$(".holeCard > :nth-child(2)").hide();
}
const deal = () => {
debugger;
newDeck();
// Option: to burn first card before deal a card
// to the first player
burnOneCard;
dealOneCardToPlayer()
.then(dealOneCardToDealer)
.then(dealOneCardToPlayer)
.then(dealOneCardToDealer(true));
//dealOneCardToPlayer();
//dealOneCardToDealer(false);
//dealOneCardToPlayer();
//// true for hole card
//dealOneCardToDealer(true);
showGameButtons(true);
checkEndGame1();
checkGameOver();
}
const hit = () => {
dealOneCardToPlayer();
checkEndGame2();
checkGameOver();
}
const stand = () => {
// Recalculate dealer's hand value
//dealer.handValue = countHandValue(dealer.cards);
debugger;
// Simple AI to automate dealer's decision to hit or stand
if (dealer.handValue >= 17) {
checkEndGame3();
} else {
// Hit until dealer's hand value is more than 16
while (dealer.handValue < 17) {
dealOneCardToDealer();
checkEndGame3();
}
}
checkGameOver();
}
</script>
I think the right way to approach is with promises:
const DELAY = 2000;
function dealCardToPlayer() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log('Dealing card to player');
resolve();
}, DELAY);
});
}
function dealCardToDealer() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log('Dealing card to dealer');
resolve();
}, DELAY);
});
}
dealCardToPlayer()
.then(dealCardToDealer)
.then(dealCardToPlayer)
.then(dealCardToDealer);
I'm trying to make a count-down that counts down from 200 to 0 in steps of 10.
This timer can be stopped and should then be reset to 200, however, I need also the value of the moment is stopped. The countdown fills the div #log with innerHTML. Whenever I "stop" the timer, I take the value of #log and place it in #price and I hide #log. The problem here is that the timer continues in the background, while I want it to reset so it can be started again by clicking on start. However, it just continues counting down and only after it's done, I can start it again.
In the example, it doesn't take so long for it to reach 0, but in the end, it'll take 15-20 seconds to reach 0, which'll be too long to wait for.
So in short: Countdown 200-0, but on click of Start-button or spacebar, it should stop the function running at the moment, so it can be started again.
See this PEN
If you have any suggestions on how to approach it completely different, you're very welcome to share!
HTML
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>
JS
var log = document.getElementById("log");
var btn = document.getElementById("btn");
var price = document.getElementById("price");
var counting = false;
var btnClassName = btn.getAttribute("class");
function start(count) {
if (!counting) {
counting = true;
log.innerHTML = count;
var timer = setInterval(function() {
if (count >= 0) {
log.innerHTML = count;
count -= 10;
} else {
clearInterval(timer);
count = arguments[0];
counting = false;
btn.className = "normal";
}
}, 150);
};
};
btn.onclick = function() {
if (btnClassName == "normal") {
start(200);
price.style.display = 'none';
log.style.display = 'block';
btn.className = "counting";
log.innerHTML = "";
} else {
}
};
document.body.onkeyup = function(e){
if(e.keyCode == 32){
price.innerHTML = log.innerHTML;
price.style.display = 'block';
log.style.display = 'none';
}
}
I "re-code" your code because there are several issues there.
Just read the code and tell me if that's you are looking for or if you have any questions..
var log = document.getElementById("log");
var btn = document.getElementById("btn");
var price = document.getElementById("price");
var counting = false;
var timer;
var c = 0;
function start(count) {
btn.blur();
if (!counting) {
c = count;
counting = true;
log.innerHTML = count;
timer = setInterval(tick, 1500);
tick();
};
};
function tick() {
if (c >= 0) {
log.innerHTML = c;
c -= 10;
}
else {
clearInterval(timer);
c = arguments[0];
counting = false;
btn.className = "normal";
}
}
btn.onclick = function() {
resetTimer();
var btnClassName = btn.getAttribute("class");
if (btnClassName == "normal") {
price.style.display = 'none';
log.style.display = 'block';
btn.className = "counting";
log.innerHTML = "";
start(200);
} else {
pause();
}
};
document.body.onkeyup = function(e) {
if(e.keyCode == 32) {
e.preventDefault();
pause();
}
}
function pause() {
resetTimer();
price.innerHTML = log.innerHTML;
price.style.display = 'block';
log.style.display = 'none';
btn.className = 'normal';
counting = false;
}
function resetTimer() {
clearInterval(timer);
}
body { font: 100% "Helvetica Neue", sans-serif; text-align: center; }
/*#outer {
width: 400px;
height: 400px;
border-radius: 100%;
background: #ced899;
margin: auto;
}
#inner {
width: 350px;
height: 350px;
border-radius: 100%;
background: #398dba;
margin: auto;
}*/
#log, #price {
font-size: 500%;
font-weight: bold;
}
<div id="outer">
<div id="inner">
<div id="arrow">
</div>
</div>
</div>
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>
Though you have already got your answer, you can try something like this:
Also I have taken liberty to reformat your code, and for demonstration purpose, have kept delay for interval as 1000
JSFiddle
function Counter(obj) {
var _initialVaue = obj.initialValue || 0;
var _interval = null;
var status = "Stopped";
var start = function() {
this.status = "Started";
if (!_interval) {
_interval = setInterval(obj.callback, obj.delay);
}
}
var reset = function() {
stop();
start();
}
var stop = function() {
if (_interval) {
this.status = "Stopped";
window.clearInterval(_interval);
_interval = null;
}
}
return {
start: start,
reset: reset,
stop: stop,
status: status
}
}
function init() {
var counterOption = {}
var count = 200;
counterOption.callback = function() {
if (count >= 0) {
printLog(count);
count -= 10;
} else {
counter.stop();
}
};
counterOption.delay = 1000;
counterOption.initialValue = 200
var counter = new Counter(counterOption);
function registerEvents() {
document.getElementById("btn").onclick = function() {
if (counter.status === "Stopped") {
count = counterOption.initialValue;
counter.start();
printLog("")
toggleDivs(counter.status)
}
};
document.onkeyup = function(e) {
if (e.keyCode === 32) {
printLog(counterOption.initialValue);
counter.stop();
toggleDivs(counter.status)
printPrice(count);
}
}
}
function printLog(str) {
document.getElementById("log").innerHTML = str;
}
function printPrice(str) {
document.getElementById("price").innerHTML = str;
}
function toggleDivs(status) {
document.getElementById("log").className = "";
document.getElementById("price").className = "";
var hideID = (status === "Started") ? "price" : "log";
document.getElementById(hideID).className = "hide";
}
registerEvents();
}
init();
body {
font: 100% "Helvetica Neue", sans-serif;
text-align: center;
}
.hide{
display: none;
}
#log,
#price {
font-size: 500%;
font-weight: bold;
}
<div id="outer">
<div id="inner">
<div id="arrow">
</div>
</div>
</div>
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>
Hope it helps!
I've been wanting to create a timer for my website that countsup, and displays alerts at certain intervals. So like, it starts from 0 and counts upwards when the user pushes a button. From there, it will display a a custom alert at certain intervals... (4 minutes for example)... 45 seconds before that interval, I need the number to change to yellow and 10 seconds before that interval, I need it to change to red... then back to the normal color when it passes that interval.
I've got a basic timer code but I am not sure how to do the rest. I am quite new to this. Any help? Thanks so much in advance.
var pad = function(n) { return (''+n).length<4?pad('0'+n):n; };
jQuery.fn.timer = function() {
var t = this, i = 0;
setInterval(function() {
t.text(pad(i++));
}, 1000);
};
$('#timer').timer();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
You could do something like this
var pad = function (n) {
return ('' + n).length < 4 ? pad('0' + n) : n;
};
jQuery.fn.timer = function () {
var t = this,
i = 0;
setInterval(function () {
t.text(pad(i++));
checkTime(i, t);
}, 1000);
};
$('#timer').timer();
checkTime = function (time, t) {
switch (time -1) {
case 10:
t.css('color','red');
break;
case 20:
t.css('color','yellow');
break;
case 30:
t.css('color','green');
break;
case 40:
t.css('color','black');
break;
default:
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
Something like this should work:
Here is a jsFiddle DEMO
jQuery
$.fn.timer = function (complete, warning, danger) {
var $this = $(this);
var total = 0;
$this.text(total);
var intervalComplete = parseInt(complete, 10);
var intervalWarning = parseInt(intervalComplete - warning, 10);
var intervalDanger = parseInt(intervalComplete - danger, 10);
var clock = setInterval(function () {
total += 1;
$this.text(total);
if (intervalWarning === total) {
// set to YELLOW:
$this.addClass('yellow');
}
if (intervalDanger === total) {
// set to RED:
$this.removeClass('yellow').addClass('red');
}
if (intervalComplete === total) {
// reset:
clearInterval(clock);
$this.removeClass();
alert('COMPLETE!');
}
}, 1000);
};
$(function () {
$('#timer').timer(240, 45, 10);
});
CSS
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
An additional point:
You should place some error validation within the function to ensure your counter completion time is greater than both the warning and danger time intervals.
You can try something like this:
JSFiddle
This is a pure JS timer code. Also for popup you can use something like Bootbox.js.
Code
function timer() {
var time = {
sec: 00,
min: 00,
hr: 00
};
var finalLimit = null,
warnLimit = null,
errorLimit = null;
var max = 59;
var interval = null;
function init(_hr, _min, _sec) {
time["hr"] = _hr ? _hr : 0;
time["min"] = _min ? _min : 0;
time["sec"] = _sec ? _sec : 0;
printAll();
}
function setLimit(fLimit, wLimit, eLimit) {
finalLimit = fLimit;
warnLimit = wLimit;
errorLimit = eLimit;
}
function printAll() {
print("sec");
print("min");
print("hr");
}
function update(str) {
time[str] ++;
time[str] = time[str] % 60;
if (time[str] == 0) {
str == "sec" ? update("min") : update("hr");
}
print(str);
}
function print(str) {
var _time = time[str].toString().length == 1 ? "0" + time[str] : time[str];
document.getElementById("lbl" + str).innerHTML = _time;
}
function validateTimer() {
var c = "";
var secs = time.sec + (time.min * 60) + (time.hr * 60 * 60);
console.log(secs, finalLimit)
if (secs >= finalLimit) {
stopTimer();
} else if (secs >= errorLimit) {
c = "error";
} else if (secs >= warnLimit) {
c = "warn";
} else {
c = "";
}
var element = document.getElementsByTagName("span");
console.log(element, c)
document.getElementById("lblsec").className = c;
}
function startTimer() {
init();
if (interval) stopTimer();
interval = setInterval(function() {
update("sec");
validateTimer();
}, 1000);
}
function stopTimer() {
window.clearInterval(interval);
}
function resetInterval() {
stopTimer();
time["sec"] = time["min"] = time["hr"] = 0;
printAll();
startTimer();
}
return {
'start': startTimer,
'stop': stopTimer,
'reset': resetInterval,
'init': init,
'setLimit': setLimit
}
};
var time = new timer();
function initTimer() {
time.init(0, 0, 0);
}
function startTimer() {
time.start();
time.setLimit(10, 5, 8);
}
function endTimer() {
time.stop();
}
function resetTimer() {
time.reset();
}
span {
border: 1px solid gray;
padding: 5px;
border-radius: 4px;
background: #fff;
}
.timer {
padding: 2px;
margin: 10px;
}
.main {
background: #eee;
padding: 5px;
width: 200px;
text-align: center;
}
.btn {
-webkit-border-radius: 6;
-moz-border-radius: 6;
border-radius: 6px;
color: #ffffff;
font-size: 14px;
background: #2980b9;
text-decoration: none;
transition: 0.4s;
}
.btn:hover {
background: #3cb0fd;
text-decoration: none;
transition: 0.4s;
}
.warn {
background: yellow;
}
.error {
background: red;
}
<div class="main">
<div class="timer"> <span id="lblhr">00</span>
: <span id="lblmin">00</span>
: <span id="lblsec">00</span>
</div>
<button class="btn" onclick="startTimer()">Start</button>
<button class="btn" onclick="endTimer()">Stop</button>
<button class="btn" onclick="resetTimer()">Reset</button>
</div>
Hope it helps!