-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
249 lines (231 loc) · 8.54 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
//Global variables and DOM Elements
// NOTE: Throughout the code calculationDisplay refers to the top part of the display while resultDisplay refers to its bottom part
const date = new Date();
let operator = null;
const time = document.querySelector(".time");
const main = document.querySelector(".main");
const audio = document.querySelector("audio");
const calculationDisplay = document.querySelector(".calculation");
const resultDisplay = document.querySelector(".result");
const equalsBtn = document.querySelector(".equals");
const keyOperations = ["/", "-", "+", "*"];
const decimalBtn = document.querySelector(".decimal-btn");
const darkThemeBtn = document.querySelector(".dark-toggle");
const lightThemeBtn = document.querySelector(".light-toggle");
// Integrating keyboard support
// Add keydown event listener to window
window.addEventListener("keydown", (e) => {
// If the decimal key is pressed
if (e.key === ".") {
// Call addDecimal()
addDecimal();
// If the backspace key is pressed
} else if (e.key === "Backspace") {
// Call removeLast
removeLast();
} else if (e.key === "Escape") {
removeAll();
}
// If keyOperations contains e.key (i.e. /,*,+,-)
else if (keyOperations.includes(e.key)) {
// Call setOperation on changeIntoOperation with e.key as an argument
setOperation(changeIntoOperation(e.key));
// Reset resultDisplay's textContent
resultDisplay.textContent = "";
// If the enter key is pressed
} else if (e.key === "Enter") {
// Call displayResult()
displayResult();
// If Number(e.key) isn't NaN(i.e. e.key is a number)
} else if (!isNaN(Number(e.key))) {
// Add e.key to resultDisplay's value
resultDisplay.textContent += e.key;
}
});
// Adding click event listener to darkThemeBtn(moon icon)
darkThemeBtn.addEventListener("click", () => {
// Removing light-theme class and adding dark-theme class to body
document.body.classList.add("dark-theme");
document.body.classList.remove("light-theme");
});
// Adding click event listener to lightThemeBtn(sun icon)
lightThemeBtn.addEventListener("click", () => {
// Removing dark-theme class and adding light-theme class to body
document.body.classList.add("light-theme");
document.body.classList.remove("dark-theme");
});
// Displaying time on the calculator
time.textContent = getTime();
// Function to display the local time
function getTime() {
// If the minutes are less than 10 i.e. 9,8 etc
if (date.getMinutes() <= 10) {
// Then make the time display a 0 before them i.e. 09,08 etc
return `${date.getHours()}:0${date.getMinutes()}`;
// Otherwise display the time normally
} else {
return `${date.getHours()}:${date.getMinutes()}`;
}
}
// Adding onclick event listener to the calculator
main.addEventListener("click", (e) => {
// Playing click sound if button is clicked
if (e.target.classList.contains("btn")) {
audio.play();
}
// If negate button(+/-) is clicked, then return the negative of the displayed number
if (e.target.classList.contains("negate-btn")) {
if (!isNaN(Number(resultDisplay.textContent))) {
resultDisplay.textContent = negate(resultDisplay.textContent);
}
}
// If event is fired on btn which is not a function(AC,C etc), not the equals button, not an operation or a decimal
if (
e.target.classList.contains("btn") &&
!e.target.classList.contains("function") &&
!e.target.classList.contains("operation") &&
!e.target.classList.contains("equals") &&
!e.target.classList.contains("decimal-btn")
) {
// Add the value of button to the value of resultDisplay
resultDisplay.textContent += e.target.textContent;
}
// If decimal button is clicked, call addDecimal()
if (e.target.classList.contains("decimal-btn")) {
addDecimal();
}
// If an operation is clicked
if (e.target.classList.contains("operation")) {
// Call setOperation on its value and pass in the value of the target(the operator)
setOperation(e.target.textContent);
// Set the value of resultDisplay to blank
resultDisplay.textContent = "";
}
// If equals is clicked, call displayResult()
if (e.target.classList.contains("equals")) {
displayResult();
}
});
// Fetching clearAll from the DOM
const clearAll = document.querySelector(".clear-all");
// Adding onclick event listener to clearAll which calls removeAll()
clearAll.addEventListener("click", removeAll);
function removeAll() {
// setting the value of both displays to blank
calculationDisplay.textContent = "";
resultDisplay.textContent = "";
}
// Fetching clearLast from the DOM
const clearLast = document.querySelector(".clear-last");
// Adding onclick event listener to clearLast which calls removeLast()
clearLast.addEventListener("click", removeLast);
function removeLast() {
// Storing the value of resultDisplay in a variable
let value = resultDisplay.textContent;
// Removing the last character from value
value = value.slice(0, -1);
// Reassigning value to resultDisplay's value
resultDisplay.textContent = value;
}
// Function to set resultDisplay's value to the answer of the expression
function displayResult() {
// Adding resultDisplay's value to calculationDisplay
calculationDisplay.textContent += resultDisplay.textContent;
// Storing calculationDisplay's value in a variable
let value = calculationDisplay.textContent;
// Removing all whitespaces
value = value.replace(/\s+/g, "");
// Converting into character array named valueArray
let valueArray = value.split("");
// For each instance of valueArray
for (let i in valueArray) {
// If Number(that instance) is NAN(i.e. its a string(referring to an operator)) and its index isn't 0
if (isNaN(Number(valueArray[i])) && value.indexOf(valueArray[i]) !== 0) {
// Storing the value of that instance(the operator) in a variable
operator = valueArray[i];
// Getting its index
let operatorIndex = valueArray.indexOf(operator);
// Slicing array from start to its index to get firstNumber
let firstNumber = value.slice(0, operatorIndex);
// Slicing array from operatorIndex + 1 to the end to get secondNumber
let secondNumber = value.slice(operatorIndex + 1, value.length);
// Setting resultDisplay's value to the result
resultDisplay.textContent = operate(operator, firstNumber, secondNumber);
// If resultDisplay isn't zero
if (+resultDisplay.textContent !== 0) {
// Rounding resultDisplay's value to 0, and then converting it to Number so that for non-decimal numbers, the decimals don't show
resultDisplay.textContent = +parseFloat(
resultDisplay.textContent
).toFixed(3);
}
// Setting calculationDisplay's value to an appropriate one
calculationDisplay.textContent = `${firstNumber} ${operator} ${secondNumber} =`;
// Setting global variable operator to null
operator = null;
}
}
}
// Function to evaluate expression
function operate(operator, a, b) {
// Checking if operator is division and we are dividing by 0
if (operator === "÷" && +b === 0) {
// If so displaying an appropriate error message
alert("Can't divide by 0");
// If statements to return the value of various operations
} else {
if (operator === "+") {
return add(+a, +b);
} else if (operator === "-") {
return subtract(+a, +b);
} else if (operator === "÷") {
return divide(+a, +b);
} else if (operator === "x") {
return multiply(+a, +b);
}
}
}
// Calculation Functions
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function multiply(a, b) {
return a * b;
}
function divide(a, b) {
return a / b;
}
function negate(a) {
return -a;
}
// Function to add decimals
function addDecimal() {
// If resultDisplay already contains a decimal then return
if (resultDisplay.textContent.includes(".")) return;
else {
// Otherwise add a decimal to it
resultDisplay.textContent += ".";
}
}
// Function to display proper content when an operator is clicked
function setOperation(operation) {
// If operator isn't null, then call displayResult
if (operator !== null) displayResult();
// Getting firstNumber from resultDisplay's value
firstNumber = resultDisplay.textContent;
// Setting the value of operator to the function argument
operator = operation;
// Setting calulationDisplay to firstNumber + the operator
calculationDisplay.textContent = `${firstNumber} ${operator}`;
}
const changeIntoOperation = (a) => {
if (a === "/") {
return "÷";
} else if (a === "*") {
return "x";
} else {
return a;
}
};