I've built a simple calculator using JS for the sake of practice. However, I am unable to achieve the following:
After my calculator displays the result and when I click on the keys to enter a new value, the new values keep concatenating with the result. How do I reset the display value?
How do I restrict decimal point from being entered more than ones.
Source code:
const calculator = document.querySelector(".calculator");
const displayScreen = document.querySelector(".calculatorDisplay");
const numberKeys = document.querySelectorAll(".numKeys");
const operatorKeys = document.querySelectorAll(".operator");
const equalsButton = document.querySelector(".equals");
const allClear = document.querySelector(".allClear");
const decimalButton = document.querySelector(".decimalButton");
// variables
var firstOperand;
var secondOperand;
var operator;
for(var i=0; i<numberKeys.length; i++){
numberKeys[i].addEventListener("click", e=>{
const firstValue = e.target.textContent;
displayScreen.value+= firstValue;
});
}
for(var i=0; i<operatorKeys.length; i++){
operatorKeys[i].addEventListener("click", e=>{
firstOperand = displayScreen.value;
displayScreen.value = "";
operator = e.target.textContent;
});
}
equalsButton.addEventListener("click", function(){
secondOperand = displayScreen.value;
displayScreen.value = mathOperations();
});
allClear.addEventListener("click", function(){
displayScreen.value ="";
});
decimalButton.addEventListener("click", e=>{
displayScreen.value=displayScreen.value + "."
});
function mathOperations(){
let operandOne = parseFloat(firstOperand);
let operandTwo = parseFloat(secondOperand);
if(operator==="+"){
return (operandOne + operandTwo);
}
if(operator==="-"){
return (operandOne - operandTwo);
}
if(operator==="*"){
return (operandOne * operandTwo);
}
if(operator==="/"){
return (operandOne / operandTwo);
}
}
You need to declare currentValue as a global variable (next to operator for example). Then, when user clicks on equalsButton, you set currentValue to true. Then, in numberKeys handler, add a check if currentValue is true, clear displayScreen.
numberKeys[i].addEventListener("click", e => {
if (currentValue) {
displayScreen.value = '';
currentValue = false;
}
displayScreen.value += e.target.textContent;
});
I thought by mistake that displayScreen is a string, but it's the input, so the check should be displayScreen.value.length
if (displayScreen.value.charAt(displayScreen.value.length - 1) !== '.') {
const calculator = document.querySelector(".calculator");
const displayScreen = document.querySelector(".calculatorDisplay");
const numberKeys = document.querySelectorAll(".numKeys");
const operatorKeys = document.querySelectorAll(".operator");
const equalsButton = document.querySelector(".equals");
const allClear = document.querySelector(".allClear");
const decimalButton = document.querySelector(".decimalButton");
let firstOperand;
let secondOperand;
let operator;
let currentValue = false;
enterNumbers();
for (var i = 0; i < operatorKeys.length; i++) {
operatorKeys[i].addEventListener("click", e => {
firstOperand = displayScreen.value;
displayScreen.value = "";
operator = e.target.textContent;
});
}
decimalButton.addEventListener("click", e => {
if (displayScreen.value.charAt(displayScreen.value.length - 1) !== '.') {
displayScreen.value=displayScreen.value + ".";
}
});
equalsButton.addEventListener("click", function() {
currentValue = true;
secondOperand = displayScreen.value;
displayScreen.value = mathOperations();
});
allClear.addEventListener("click", function() {
displayScreen.value = "";
});
function mathOperations() {
let operandOne = parseFloat(firstOperand);
let operandTwo = parseFloat(secondOperand);
if (operator === "+") {
return operandOne + operandTwo;
}
if (operator === "-") {
return operandOne - operandTwo;
}
if (operator === "*") {
return operandOne * operandTwo;
}
if (operator === "/") {
return operandOne / operandTwo;
}
}
function enterNumbers() {
for (var i = 0; i < numberKeys.length; i++) {
numberKeys[i].addEventListener("click", e => {
if (currentValue) {
displayScreen.value = '';
currentValue = false;
}
displayScreen.value += e.target.textContent;
});
}
}
/* Code from freshman.tech by Ayooluwa Isaiah */
html {
font-size: 62.5%;
box-sizing: border-box;
}
h1 {
text-align: center;
}
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: inherit;
}
.calculator {
border: 1px solid black;
border-radius: 25px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
}
.calculatorDisplay {
text-align: right;
font-size: 5rem;
width: 100%;
height: 80px;
border: none;
background-color: #252525;
color: #fff;
text-align: right;
padding-right: 20px;
padding-left: 10px;
}
button {
height: 60px;
border-radius: 3px;
border: 1px solid #c4c4c4;
background-color: transparent;
font-size: 2rem;
color: #333;
background-image: linear-gradient(
to bottom,
transparent,
transparent 50%,
rgba(0, 0, 0, 0.04)
);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05),
inset 0 1px 0 0 rgba(255, 255, 255, 0.45),
inset 0 -1px 0 0 rgba(255, 255, 255, 0.15),
0 1px 0 0 rgba(255, 255, 255, 0.15);
text-shadow: 0 1px rgba(255, 255, 255, 0.4);
}
button:hover {
background-color: #eaeaea;
}
.operator {
color: #337cac;
}
.allClear {
background-color: #f0595f;
border-color: #b0353a;
color: #fff;
}
.allClear:hover {
background-color: #f17377;
}
.equals {
background-color: #2e86c0;
border-color: #337cac;
color: #fff;
height: 100%;
grid-area: 2 / 4 / 6 / 5;
}
.equals:hover {
background-color: #4e9ed4;
}
.calculatorKeys {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 20px;
padding: 20px;
}
<!DOCTYPE html>
<html>
<head>
<title>Calculator</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>My Calculator</h1>
<div class="calculator">
<input type="text" name="display" class="calculatorDisplay">
<div class=calculatorKeys>
<!-- operators -->
<button class="operator">+</button>
<button class="operator">-</button>
<button class="operator">*</button>
<button class="operator">/</button>
<button class="numKeys">7</button>
<button class="numKeys">8</button>
<button class="numKeys">9</button>
<button class="numKeys">4</button>
<button class="numKeys">5</button>
<button class="numKeys">6</button>
<button class="numKeys">1</button>
<button class="numKeys">2</button>
<button class="numKeys">3</button>
<button class="numKeys">0</button>
<!-- decimal-->
<button class="decimalButton">.</button>
<!-- All clear -->
<button class="allClear">AC</button>
<!-- result -->
<button class="equals">=</button>
</div>
<script type="text/javascript" src="cal.js"></script>
</div>
</body>
</html>
https://codepen.io/moshfeu/pen/RwPQKJV?editors=1000
Related
I am trying to make a calculator but I have the following problem:
When I type 5 + 3 = .... I get 8. That works.
However when I type - 2 = .... I get 1.
The problem happenes in the dataOperators and especially in the code "disNum2 = disNum1;"
The first time I run dataOperators.forEach the calcultae works correct.
Then I hit the equal sign and the result is correct.
After the result is calculated I press another operator followed by a number.
Then I press the equal sign again and now the variable disNum2 contains disNum1 instead of the result.
I hope that you could give me some advice.
Thanks in advance!
const myInput = document.querySelector('#result');
const myOperator = document.querySelector('#operator');
const dataNumbers = document.querySelectorAll('.dataNumber');
const dataOperators = document.querySelectorAll('.dataOperator');
const dataEquals = document.querySelector('.dataEquals');
const dataClear = document.querySelector('.dataClear');
let disNum1 = '';
let disNum2 = '';
let result = '';
let hasDot = false;
let hasZero = false;
let lastOperation = '';
dataNumbers.forEach((number) => {
number.addEventListener('click',(e) => {
const clickedNum = e.target.innerText;
if (clickedNum === '.' && !hasDot) {
hasDot = true;
} else if (clickedNum === '.' && hasDot) {
return;
}
if (clickedNum === '.' && !hasZero) {
hasZero = true;
} else if (clickedNum === '.' && hasZero) {
return;
}
disNum1 += clickedNum;
myInput.value = disNum1;
})
})
dataOperators.forEach((operation) => {
operation.addEventListener('click', (e) => {
hasDot = false;
hasZero = false;
const clickedOp = e.target.innerText
lastOperation = clickedOp;
myOperator.value = clickedOp;
disNum2 = disNum1;
disNum1 = '';
})
})
function mathOperation() {
if (lastOperation === 'x') {
result = parseFloat(disNum2) * parseFloat(disNum1);
} else if (lastOperation === "+") {
result = parseFloat(disNum2) + parseFloat(disNum1);
} else if (lastOperation === "-") {
result = parseFloat(disNum2) - parseFloat(disNum1);
} else if (lastOperation === "/") {
result = parseFloat(disNum2) / parseFloat(disNum1);
} else if (lastOperation === "%") {
result = parseFloat(disNum2) % parseFloat(disNum1);
}
}
dataEquals.addEventListener("click", () => {
hasDot = false;
hasZero = false;
mathOperation();
myInput.value = result;
})
* {
box-sizing: border-box;
}
#calculator {
width: 500px;
}
#keys {
display: flex;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
}
#numbers {
display: flex;
flex-wrap: wrap;
width: 75%;
justify-content: center;
}
#operators {
width: 25%;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
#numbers div,
#operators div {
background-color: #f1f1f1;
width: 100px;
margin: 10px;
text-align: center;
padding: 20px 0;
font-size: 30px;
cursor: pointer;
box-shadow: -1px -1px 4px rgba(0, 0, 0, 0.6) inset;
}
#numbers div {
padding: 30px 0 0 0;
}
#numbers div:active,
#operators div:active {
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6) inset;
}
#screen {
margin: 18px;
width: calc(100% - 30px);
box-shadow: 3px 3px 4px rgba(0, 0, 0, 0.6) inset;
background-color: rgba(239, 239, 239, 0.3);
display: flex;
}
#result,
#operator {
width: 100%;
height: 100px;
padding: 20px;
font-family: 'Courier New', Courier, monospace;
font-size: 42px;
text-align: right;
border: none;
}
#operator {
width: 20%;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Calculator</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="calculator">
<div id="screen">
<input type="text" id="result" placeholder="0" value="" disabled>
<input type="text" id="operator" disabled>
</div>
<div id="keys">
<div id="numbers">
<div class="dataNumber">7</div>
<div class="dataNumber">8</div>
<div class="dataNumber">9</div>
<div class="dataNumber">4</div>
<div class="dataNumber">5</div>
<div class="dataNumber">6</div>
<div class="dataNumber">1</div>
<div class="dataNumber">2</div>
<div class="dataNumber">3</div>
<div class="dataNumber">.</div>
<div class="dataNumber">0</div>
<div class="dataEquals">=</div>
</div>
<div id="operators">
<div class="dataClear">C</div>
<div class="dataOperator">+</div>
<div class="dataOperator">-</div>
<div class="dataOperator">x</div>
<div class="dataOperator">/</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
When you calculate the result, you probably just need to copy the result into disNum2, see the last line of the JS:
const myInput = document.querySelector('#result');
const myOperator = document.querySelector('#operator');
const dataNumbers = document.querySelectorAll('.dataNumber');
const dataOperators = document.querySelectorAll('.dataOperator');
const dataEquals = document.querySelector('.dataEquals');
const dataClear = document.querySelector('.dataClear');
let disNum1 = '';
let disNum2 = '';
let result = '';
let hasDot = false;
let hasZero = false;
let lastOperation = '';
dataNumbers.forEach((number) => {
number.addEventListener('click',(e) => {
const clickedNum = e.target.innerText;
if (clickedNum === '.' && !hasDot) {
hasDot = true;
} else if (clickedNum === '.' && hasDot) {
return;
}
if (clickedNum === '.' && !hasZero) {
hasZero = true;
} else if (clickedNum === '.' && hasZero) {
return;
}
disNum1 += clickedNum;
myInput.value = disNum1;
})
})
dataOperators.forEach((operation) => {
operation.addEventListener('click', (e) => {
hasDot = false;
hasZero = false;
const clickedOp = e.target.innerText
lastOperation = clickedOp;
myOperator.value = clickedOp;
disNum2 = disNum1;
disNum1 = '';
})
})
function mathOperation() {
if (lastOperation === 'x') {
result = parseFloat(disNum2) * parseFloat(disNum1);
} else if (lastOperation === "+") {
result = parseFloat(disNum2) + parseFloat(disNum1);
} else if (lastOperation === "-") {
result = parseFloat(disNum2) - parseFloat(disNum1);
} else if (lastOperation === "/") {
result = parseFloat(disNum2) / parseFloat(disNum1);
} else if (lastOperation === "%") {
result = parseFloat(disNum2) % parseFloat(disNum1);
}
}
dataEquals.addEventListener("click", () => {
hasDot = false;
hasZero = false;
mathOperation();
myInput.value = result;
disNum2 = result; // Your result is now also the 2nd number.
})
* {
box-sizing: border-box;
}
#calculator {
width: 500px;
}
#keys {
display: flex;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
}
#numbers {
display: flex;
flex-wrap: wrap;
width: 75%;
justify-content: center;
}
#operators {
width: 25%;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
#numbers div,
#operators div {
background-color: #f1f1f1;
width: 100px;
margin: 10px;
text-align: center;
padding: 20px 0;
font-size: 30px;
cursor: pointer;
box-shadow: -1px -1px 4px rgba(0, 0, 0, 0.6) inset;
}
#numbers div {
padding: 30px 0 0 0;
}
#numbers div:active,
#operators div:active {
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6) inset;
}
#screen {
margin: 18px;
width: calc(100% - 30px);
box-shadow: 3px 3px 4px rgba(0, 0, 0, 0.6) inset;
background-color: rgba(239, 239, 239, 0.3);
display: flex;
}
#result,
#operator {
width: 100%;
height: 100px;
padding: 20px;
font-family: 'Courier New', Courier, monospace;
font-size: 42px;
text-align: right;
border: none;
}
#operator {
width: 20%;
}
<div id="calculator">
<div id="screen">
<input type="text" id="result" placeholder="0" value="" disabled>
<input type="text" id="operator" disabled>
</div>
<div id="keys">
<div id="numbers">
<div class="dataNumber">7</div>
<div class="dataNumber">8</div>
<div class="dataNumber">9</div>
<div class="dataNumber">4</div>
<div class="dataNumber">5</div>
<div class="dataNumber">6</div>
<div class="dataNumber">1</div>
<div class="dataNumber">2</div>
<div class="dataNumber">3</div>
<div class="dataNumber">.</div>
<div class="dataNumber">0</div>
<div class="dataEquals">=</div>
</div>
<div id="operators">
<div class="dataClear">C</div>
<div class="dataOperator">+</div>
<div class="dataOperator">-</div>
<div class="dataOperator">x</div>
<div class="dataOperator">/</div>
</div>
</div>
</div>
And here is a delegation version
I also simplified your 0 and dot code
const myInput = document.getElementById('result');
const keys = document.getElementById("keys");
const myOperator = document.getElementById('operator');
const dataEquals = document.querySelector('.dataEquals');
const dataClear = document.querySelector('.dataClear');
let disNum1 = '';
let disNum2 = '';
let result = '';
let hasDot = false;
let hasZero = false;
let lastOperation = '';
keys.addEventListener('click', (e) => {
const tgt = e.target;
if (tgt.closest("#numbers")) {
const clickedNum = tgt.textContent;
if (clickedNum === '.') {
if (hasDot) return
else hasDot = true;
if (hasZero) return
else hasZero = true;
}
disNum1 += clickedNum;
myInput.value = disNum1;
return;
}
if (tgt.closest("#operators")) {
hasDot = false;
hasZero = false;
const clickedOp = tgt.textContent;
if (clickedOp === "C") {
myInput.value = "";
myOperator.value = "";
disNum1 = disNum2 = '';
return
}
lastOperation = clickedOp;
myOperator.value = clickedOp;
disNum2 = disNum1;
disNum1 = '';
}
})
function mathOperation() {
if (lastOperation === 'x') {
result = parseFloat(disNum2) * parseFloat(disNum1);
} else if (lastOperation === "+") {
result = parseFloat(disNum2) + parseFloat(disNum1);
} else if (lastOperation === "-") {
result = parseFloat(disNum2) - parseFloat(disNum1);
} else if (lastOperation === "/") {
result = parseFloat(disNum2) / parseFloat(disNum1);
} else if (lastOperation === "%") {
result = parseFloat(disNum2) % parseFloat(disNum1);
}
}
dataEquals.addEventListener("click", () => {
hasDot = false;
hasZero = false;
mathOperation();
myInput.value = result;
disNum2 = result; // Your result is now also the 2nd number.
})
* {
box-sizing: border-box;
}
#calculator {
width: 500px;
}
#keys {
display: flex;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
}
#numbers {
display: flex;
flex-wrap: wrap;
width: 75%;
justify-content: center;
}
#operators {
width: 25%;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
#numbers div,
#operators div {
background-color: #f1f1f1;
width: 100px;
margin: 10px;
text-align: center;
padding: 20px 0;
font-size: 30px;
cursor: pointer;
box-shadow: -1px -1px 4px rgba(0, 0, 0, 0.6) inset;
}
#numbers div {
padding: 30px 0 0 0;
}
#numbers div:active,
#operators div:active {
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6) inset;
}
#screen {
margin: 18px;
width: calc(100% - 30px);
box-shadow: 3px 3px 4px rgba(0, 0, 0, 0.6) inset;
background-color: rgba(239, 239, 239, 0.3);
display: flex;
}
#result,
#operator {
width: 100%;
height: 100px;
padding: 20px;
font-family: 'Courier New', Courier, monospace;
font-size: 42px;
text-align: right;
border: none;
}
#operator {
width: 20%;
}
<div id="calculator">
<div id="screen">
<input type="text" id="result" placeholder="0" value="" disabled>
<input type="text" id="operator" disabled>
</div>
<div id="keys">
<div id="numbers">
<div class="dataNumber">7</div>
<div class="dataNumber">8</div>
<div class="dataNumber">9</div>
<div class="dataNumber">4</div>
<div class="dataNumber">5</div>
<div class="dataNumber">6</div>
<div class="dataNumber">1</div>
<div class="dataNumber">2</div>
<div class="dataNumber">3</div>
<div class="dataNumber">.</div>
<div class="dataNumber">0</div>
<div class="dataEquals">=</div>
</div>
<div id="operators">
<div class="dataClear">C</div>
<div class="dataOperator">+</div>
<div class="dataOperator">-</div>
<div class="dataOperator">x</div>
<div class="dataOperator">/</div>
</div>
</div>
</div>
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 am trying to make a simple calculator and am almost done with it except I cannot fix its screen height. When I enter the data, the height of the calculator screen changes. To reproduce the problem, you can try adding 1 + 2. I have been attempting adding min-height and max-height but to no avail. I can fix its height with js, but I want a pure CSS solution. Here is the code:
let screen = document.getElementById("screen");
let firstArg = document.querySelector(".firstArg");
let operator = document.querySelector(".operator");
let secondArg = document.querySelector(".secondArg");
let numberBtns = document.querySelectorAll(".data-number");
let acBtn = document.querySelector(".ac");
let clearBtn = document.querySelector(".clear");
let backBtn = document.querySelector(".back");
let decimalBtn = document.querySelector(".decimal");
let equalBtn = document.querySelector(".equal");
let operationBtn = document.querySelectorAll(".operation");
let regex = /[+-/*]/;
let digits = /[0-9]/;
numberBtns.forEach(n => n.addEventListener("click", e => {
if (firstArg.innerHTML === "0") {
firstArg.innerHTML = "";
}
if (operator.textContent === "" && firstArg.clientWidth + 40 < screen.offsetWidth) {
firstArg.append(n.textContent);
} else if (operator.textContent && secondArg.clientWidth + 40 < screen.offsetWidth) {
secondArg.append(n.textContent);
}
}));
decimalBtn.addEventListener("click", e => {
if (!firstArg.textContent.includes(".") && operator.textContent === "") {
firstArg.append(decimalBtn.textContent);
} else if (!secondArg.textContent.includes(".") && operator.textContent) {
secondArg.append(decimalBtn.textContent);
}
});
operationBtn.forEach(n => n.addEventListener("click", e => {
if (!regex.test(operator.textContent)) {
operator.append(n.textContent);
firstArg.append(" ");
firstArg.append(operator.textContent);
}
}))
equalBtn.addEventListener("click", e => {
let firstParam = firstArg.textContent.split(" ")[0];
let oper = operator.textContent;
let secondParam = secondArg.textContent;
if (secondParam == "") return;
solve(firstParam, oper, secondParam);
})
document.addEventListener("keydown", e => {
if (e.key == "+") {
if (!regex.test(operator.textContent)) {
operator.append(e.key);
firstArg.append(" ");
firstArg.append(operator.textContent);
}
}
if (e.key == "/") {
if (!regex.test(operator.textContent)) {
operator.append(e.key);
firstArg.append(" ");
firstArg.append(operator.textContent);
}
}
if (e.key == "-") {
if (!regex.test(operator.textContent)) {
operator.append(e.key);
firstArg.append(" ");
firstArg.append(operator.textContent);
}
}
if (e.key == "*") {
if (!regex.test(operator.textContent)) {
operator.append(e.key);
firstArg.append(" ");
firstArg.append(operator.textContent);
}
}
if (digits.test(e.key)) {
if (firstArg.innerHTML === "0") {
firstArg.innerHTML = "";
}
if (operator.textContent === "" && firstArg.clientWidth + 40 < screen.offsetWidth) {
firstArg.append(e.key);
} else if (operator.textContent && secondArg.clientWidth + 40 < screen.offsetWidth) {
secondArg.append(e.key);
}
}
if (e.code === "Enter") {
let firstParam = firstArg.textContent.split(" ")[0];
let oper = operator.textContent;
let secondParam = secondArg.textContent;
if (secondParam == "") return;
solve(firstParam, oper, secondParam);
}
})
function solve(first, oper, second) {
switch (oper) {
case "-":
firstArg.innerHTML = `${((Number(first) * 10 - Number(second) * 10) / 10).toFixed(1)}`;
operator.textContent = "";
secondArg.textContent = "";
break;
case "+":
firstArg.innerHTML = `${((Number(first) * 10 + Number(second) * 10) / 10).toFixed(1)}`;
operator.textContent = "";
secondArg.textContent = "";
break;
case "/":
firstArg.innerHTML = `${((Number(first) * 10 / Number(second) * 10) / 10).toFixed(1)}`;
operator.textContent = "";
secondArg.textContent = "";
break;
case "*":
firstArg.innerHTML = `${((Number(first) * 10 * Number(second) * 10) / 10).toFixed(1)}`;
operator.textContent = "";
secondArg.textContent = "";
break;
}
}
backBtn.addEventListener("click", e => {
if ((operator.textContent || firstArg.textContent.length > 1) && secondArg.textContent == "") {
operator.innerHTML = "";
let remaining = firstArg.textContent.slice(0, firstArg.textContent.length - 1).trim();
firstArg.innerHTML = "";
firstArg.innerHTML = remaining;
} else if (firstArg.textContent.length === 1 && secondArg.textContent == "") {
firstArg.innerHTML = "0";
} else if (secondArg.textContent) {
let remaining = secondArg.textContent.slice(0, secondArg.textContent.length - 1).trim();
secondArg.innerHTML = "";
secondArg.innerHTML = remaining;
}
})
window.onload = function() {
firstArg.innerHTML = 0;
}
acBtn.addEventListener("click", function() {
firstArg.innerHTML = 0;
secondArg.innerHTML = "";
operator.textContent = "";
})
.claculator {
display: grid;
grid-template-rows: 70px 1fr;
grid-gap: 35px 0;
margin: 0 auto;
border: 2px solid black;
width: 350px;
height: 370px;
border-radius: 27px;
padding: 12px 9px;
align-items: center;
background-color: #191a1c;
}
#screen {
background-color: #ffffff;
border-radius: 5px;
min-height: 70px;
min-width: 200px;
margin-top: 20px;
}
#funBtns {
display: grid;
grid-template-columns: repeat(4, 50px);
grid-template-rows: repeat(5, 30px);
grid-gap: 20px 40px;
justify-content: center;
}
button {
background-color: #191a1c;
color: white;
border: none;
border: 1px solid white;
border-radius: 5px;
width: 100%;
}
button:hover {
transform: translateY(-5px);
transition: 200ms ease-out;
background-color: white;
color: black;
}
.button-plus {
grid-row: span 2;
}
#screen {
display: flex;
flex-direction: column;
align-items: flex-end;
row-gap: 25px;
padding-top: 10px;
padding-right: 10px;
}
.firstArg {
float: right;
font-size: 20px;
font-weight: 500;
color: rgb(0, 0, 0);
text-overflow: clip;
}
.secondArg {
float: right;
font-size: 25px;
font-weight: 900;
color: rgb(24, 22, 22);
}
.operator {
display: none;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Calculator</title>
<link rel="stylesheet" href="style.css">
<script src="calculator.js" defer></script>
</head>
<body>
<div class="claculator">
<div id="screen">
<span class="firstArg"></span>
<span class="operator"></span>
<span class="secondArg"></span>
</div>
<div id="funBtns">
<button class="button ac">AC</button>
<button class="button clear">Clear</button>
<button class="button back">Back</button>
<button class="operation">/</button>
<button class="data-number">1</button>
<button class="data-number">2</button>
<button class="data-number">3</button>
<button class="operation">*</button>
<button class="data-number">4</button>
<button class="data-number">5</button>
<button class="data-number">6</button>
<button class="operation">-</button>
<button class="data-number">7</button>
<button class="data-number">8</button>
<button class="data-number">9</button>
<button class="operation button-plus">+</button>
<button class="button decimal">.</button>
<button class="data-number">0</button>
<button class="button equal">=</button>
</div>
</div>
</body>
</html>
change the font size to 1 rem
.secondArg {
float: right;
font-size: 1rem;
font-weight: 900;
color: rgb(24, 22, 22)}
Make the font-size for #screen equal to 1rem
then height to 1rem(if you want screen to be one line high) or 2rem(for two line high)
1rem = :root font-size in pixel.
Since you have added padding(and apparently there are two #screen), add padding height in terms of rem to height as well.
Total screen height= height(in rem) + padding(in rem)
Link for rem to pixel conversion: http://www.standardista.com/px-to-rem-conversion-if-root-font-size-is-16px/.
Try setting the css value for max-height to the div's class or id.
So, I made a calculator, and I want to add a square root function, but I know there is no already made function that finds the square root of numbers. So what elements can I combine to find the square root of a number?
const screen = document.querySelector("#screen");
const clearButton = document.querySelector("#clear");
const equalsButton = document.querySelector("#equals");
const decimalButton = document.querySelector("#decimal");
let isFloat = false;
let signOn = false;
let firstNumber = "";
let operator = "";
let secondNumber = "";
let result = "";
const allClear = () => {
isFloat = false;
signOn = false;
firstNumber = "";
operator = "";
secondNumber = "";
result = "";
screen.value = "0";
};
const calculate = () => {
if (operator && result === "" && ![" ", "+", "-", "."].includes(screen.value[screen.value.length - 1])) {
secondNumber = screen.value.substring(firstNumber.length + 3);
switch (operator) {
case "+":
result = Number((Number(firstNumber) + Number(secondNumber)).toFixed(3));
break;
case "-":
result = Number((Number(firstNumber) - Number(secondNumber)).toFixed(3));
break;
case "*":
result = Number((Number(firstNumber) * Number(secondNumber)).toFixed(3));
break;
case "/":
result = Number((Number(firstNumber) / Number(secondNumber)).toFixed(3));
break;
default:
}
screen.value = result;
}
};
clear.addEventListener("click", allClear);
document.querySelectorAll(".number").forEach((numberButton) => {
numberButton.addEventListener("click", () => {
if (screen.value === "0") {
screen.value = numberButton.textContent;
} else if ([" 0", "+0", "-0"].includes(screen.value.substring(screen.value.length - 2))
&& numberButton.textContent === "0") {
} else if ([" 0", "+0", "-0"].includes(screen.value.substring(screen.value.length - 2))
&& numberButton.textContent !== "0") {
screen.value = screen.value.substring(0, screen.value.length - 1) + numberButton.textContent;
} else if (result || result === 0) {
allClear();
screen.value = numberButton.textContent;
} else {
screen.value += numberButton.textContent;
}
});
});
decimalButton.addEventListener("click", () => {
if (result || result === 0) {
allClear();
isFloat = true;
screen.value += ".";
} else if (!isFloat) {
isFloat = true;
if ([" ", "+", "-"].includes(screen.value[screen.value.length - 1])) {
screen.value += "0.";
} else {
screen.value += ".";
}
}
});
document.querySelectorAll(".operator").forEach((operatorButton) => {
operatorButton.addEventListener("click", () => {
if (result || result === 0) {
isFloat = false;
signOn = false;
firstNumber = String(result);
operator = operatorButton.dataset.operator;
result = "";
screen.value = `${firstNumber} ${operatorButton.textContent} `;
} else if (operator && ![" ", "+", "-", "."].includes(screen.value[screen.value.length - 1])) {
calculate();
isFloat = false;
signOn = false;
firstNumber = String(result);
operator = operatorButton.dataset.operator;
result = "";
screen.value = `${firstNumber} ${operatorButton.textContent} `;
} else if (!operator) {
isFloat = false;
firstNumber = screen.value;
operator = operatorButton.dataset.operator;
screen.value += ` ${operatorButton.textContent} `;
} else if (!signOn
&& !["*", "/"].includes(operatorButton.dataset.operator)
&& screen.value[screen.value.length - 1] === " ") {
signOn = true;
screen.value += operatorButton.textContent;
}
});
});
equalsButton.addEventListener("click", calculate);
* {
box-sizing: border-box;
font-family: 'Roboto', sans-serif;
font-weight: 300;
margin: 0;
padding: 0;
}
body {
background-color: #222;
height: 100vh;
}
header {
background-color: #333;
padding: 40px 0;
}
header h1 {
-webkit-background-clip: text;
background-clip: text;
background-image: linear-gradient(to right bottom, #fff, #777);
color: transparent;
font-size: 40px;
letter-spacing: 2px;
text-align: center;
text-transform: uppercase;
}
main {
background-color: #222;
display: flex;
justify-content: center;
padding: 60px 0;
}
main #container {
background-color: #333;
box-shadow: 0 5px 5px #111;
padding: 20px;
}
.clearfix:after {
clear: both;
content: " ";
display: block;
font-size: 0;
height: 0;
visibility: hidden;
}
#container .row:not(:last-child) {
margin-bottom: 9px;
}
#container input,
#container button {
float: left;
}
#container input:focus,
#container button:focus {
outline: none;
}
#container input {
background-color: #222;
border: 1px solid #999;
border-right-width: 0;
color: #999;
font-size: 22px;
font-weight: 300;
height: 80px;
padding-right: 14px;
text-align: right;
width: 261px;
}
#container button {
background-color: #222;
border: none;
box-shadow: 0 3px 0 #111;
color: #999;
font-size: 20px;
height: 80px;
margin-right: 7px;
width: 80px;
}
#container button:active {
box-shadow: 0 2px 0 #111;
transform: translateY(1px);
}
#container #clear,
#container .operator,
#container #equals {
color: #111;
}
#container #clear,
#container .operator {
margin-right: 0;
}
#container #clear {
background-color: #e95a4b;
border: 1px solid #999;
border-left-width: 0;
box-shadow: none;
cursor: pointer;
}
#container #clear:active {
box-shadow: none;
transform: none;
}
#container .operator {
background-color: #999;
box-shadow: 0 3px 0 #555;
}
#container .operator:active {
box-shadow: 0 2px 0 #555;
}
#container #equals {
background-color: #2ecc71;
box-shadow: 0 3px 0 #155d34;
}
#container #equals:active {
box-shadow: 0 2px 0 #155d34;
}
#media only screen and (max-width: 400px) {
header {
padding: 28px 0;
}
header h1 {
font-size: 36px;
}
main {
padding: 40px 0;
}
main #container {
padding: 16px;
}
#container .row:not(:last-child) {
margin-bottom: 7px;
}
#container input {
font-size: 18px;
height: 60px;
padding-right: 10px;
width: 195px;
}
#container button {
font-size: 16px;
height: 60px;
margin-right: 5px;
width: 60px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Calculator</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
<link href="Project 1.css" rel="stylesheet">
</head>
<body>
<header>
<h1>Calculator</h1>
</header>
<main>
<div id="container">
<div class="row clearfix">
<input id="screen" value="0" disabled type="text">
<button id="clear">AC</button>
</div>
<div class="row clearfix">
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button data-operator="+" class="operator">+</button>
</div>
<div class="row clearfix">
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button data-operator="-" class="operator">-</button>
</div>
<div class="row clearfix">
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button data-operator="*" class="operator">×</button>
</div>
<div class="row clearfix">
<button id="decimal">.</button>
<button class="number">0</button>
<button id="equals">=</button>
<button data-operator="/" class="operator">÷</button>
</div>
</div>
</main>
<script src="Project 1.js"></script>
</body>
</html>
This is the code for the calc.. Feel free to edit it and explain to me what you did.
There is already one.
The Math.sqrt() function returns the square root of a number, that is, ∀x≥0,Math.sqrt(x)=x
=the uniquey≥0such thaty2=x
MDN Docs
You can use javascript built in
Math.sqrt(number)
I am trying to manipulate my HTML elements. I am trying to use dom selectors to change the values of the elements on my page but I keep getting
Uncaught TypeError: Cannot set property 'innerHTML' of null
Checking in the browser console to check what the issue is, I found out the logic I was using in dynamically selecting my elements was what was causing the trouble but when I use the same logic to pick up the element, it works well...
Can I please get an explanation of why I am getting this behaviour...
Below is a snippet
let timerObj = {
minutes: 0,
seconds: 0,
timerId: 0
}
const soundAlarm = () => {
let amount = 3;
let audio = new Audio('Timer_Sound_Effect.mp3');
const playSound = () => {
audio.pause();
audio.currentTime = 0;
audio.play();
}
for (let i = 0; i < amount; i++) {
setTimeout(playSound, 1200 * i);
}
}
const updateValue = ((key, value) => {
if (value < 0) value = 0;
console.log('Positive Numbers');
if (key === 'seconds') {
if (value < 10) value = '0' + value;
}
let keySelect = document.getElementById(key);
keySelect.innerHTML = value || 0
timerObj[key] = value;
console.log(keySelect);
console.log('mins', timerObj.minutes);
console.log('secs', timerObj.seconds);
})
(function detectChanges(key) {
console.log('detectChanges');
let input = document.getElementById(`${key}-input`);
input.addEventListener('change', () => {
updateValue(key, input.value);
})
input.addEventListener('keyup', () => {
updateValue(key, input.value);
})
return arguments.callee;
})('minutes')('seconds');
body, input, button {
font-family: 'Montserrat', sans-serif;
}
body {
margin: 72px 140px 0;
}
#header {
font-weight: 800;
font-size: 74px;
}
#controls {
display: inline-block;
width: 46%;
border-right: 1px solid rgba(0, 0, 0, .5);
padding-right: 42px;
padding-bottom: 42px;
}
.input-group {
margin: 26px 0;
}
label {
display: inline-block;
width: 24%;
font-weight: 200;
font-size: 30px;
padding: 12px;
}
input {
width: 60%;
font-size: 30px;
border: none;
border-bottom: 1px solid rgba(0, 0, 0, .5);
padding-left: 6px;
font-weight: 200;
outline: none;
}
input:disabled {
background-color: white;
opacity: .6;
}
button {
color: white;
border: none;
outline: none;
padding: 12px 62px;
background-color: #222;
}
button:disabled {
opacity: .2;
}
button:hover {
opacity: .5;
}
h2 {
display: inline-block;
vertical-align: top;
font-weight: 200;
font-size: 144px;
margin: 12px 0;
padding-left: 100px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#200;400;800&display=swap" rel="stylesheet">
<title>Clockworks</title>
</head>
<body>
<h1 id="header">Clockworks</h1>
<section id="controls">
<div class="input-group">
<label for="minutes-input">Minutes</label>
<input type="number" id="minutes-input" placeholder="0" max="480" min="0">
</div>
<div class="input-group">
<label for="seconds-input">Seconds</label>
<input type="number" id="seconds-input" placeholder="0" max="59" min="0" step="5">
</div>
<button type="button" id="start-btn">Start</button>
<button type="button" id="pause-btn" disabled>Pause</button>
<button type="button" id="stop-btn" disabled>Stop</button>
</section>
<h2><span id="minutes">0</span> : <span id="seconds">00</span></h2>
<script src="main.js"></script>
</body>
</html>
You just need to add semicolon to updateValue function
const updateValue = ((key, value) => {
if (value < 0) value = 0;
console.log('Positive Numbers');
if (key === 'seconds') {
if (value < 10) value = '0' + value;
}
let keySelect = document.getElementById(key);
keySelect.innerHTML = value || 0
timerObj[key] = value;
console.log(keySelect);
console.log('mins', timerObj.minutes);
console.log('secs', timerObj.seconds);
});
Error is here:
document.getElementById(key)
Should be clear since thats the element you are assigning keySelect to that
Change it to document.getElementBy(${key}-input)
I had to remove the backticks because of formatting so remember to re-add them
or change the detectChanges function
(function detectChanges(key) {
console.log('detectChanges');
const modified = key + "-input";
let input = document.getElementById(modified);
input.addEventListener('change', () => {
updateValue(modified, input.value);
})
input.addEventListener('keyup', () => {
updateValue(modified, input.value);
})
return arguments.callee;
})('minutes')('seconds');
have you checked the value of key when keySelect is being set ?