215 | `;
216 | break;
217 | }
218 | display.textContent = displayNumber;
219 | displayRawData();
220 | }
221 |
222 | function resetDisplayNumber() {
223 | if (rawDataResult != 0) {
224 | displayNumber = '';
225 | rawDataResult = '';
226 | }
227 | }
228 |
229 | // BOOLEAN CHECKS:
230 |
231 | // Limits the number of digits that can be entered at one time
232 | function exceedsDisplay() {
233 | if (displayNumber.length >= 12 || rawData.length >= 45) {
234 | warning.textContent = `The numbers have reached the limit of the display.`
235 | return true;
236 | } else {
237 | return false;
238 | }
239 | }
240 |
241 | // Check to see if user clicks two math operators back to back - exception: factorial (!) and period (.)
242 | function hasPreviousOperator() {
243 | if (displayNumber.length != 0 || (rawData.charAt(rawData.length - 1).match(/[\d!\.]/))) {
244 | return false;
245 | } else {
246 | return true;
247 | }
248 | }
249 |
250 | // Checks to see if user inputs number after factorial (for example: 3!4)
251 | function hasPreviousFactorial() {
252 | if (rawData.charAt(rawData.length - 1).match(/!/)) {
253 | warning.textContent = `Please enter a math operator after using a factorial.`;
254 | return true;
255 | } else {
256 | return false;
257 | }
258 | }
259 |
260 | // Factorials can increase too quickly, so I limited it to 2 digits
261 | function hasTwoDigitsMax() {
262 | if (displayNumber.length <= 2) {
263 | return true;
264 | } else {
265 | warning.textContent = `The max for a factorial is 2 digits on this calculator.`;
266 | return false;
267 | }
268 | }
269 |
270 | // Check to see if a user is trying to divide by 0, but still let user divide by 10 (for example: 32 / 0)
271 | function hasDivision() {
272 | if (rawData.charAt(rawData.length - 2).match(/\//) && displayNumber.length == 0) {
273 | warning.textContent = `This calculator will not divide by 0. I'm sure in your infinite wisdom you already know the answer to ${rawData} 0.`;
274 | return true;
275 | } else {
276 | return false;
277 | }
278 | }
279 |
280 | // Check to see if user clicked on period twice in the same number (for example: 3.14.159)
281 | function hasPreviousPeriod() {
282 | if (displayNumber.match(/\./)) {
283 | warning.textContent = `You can not have a decimal point in a exponent, factorial, or if there is already a decimal point.`;
284 | return true;
285 | } else {
286 | return false;
287 | }
288 | }
289 |
290 | // Check for an exponent in number, before adding a decimal point.
291 | function hasExponent() {
292 | if (displayNumber.match(/\^/)) {
293 | warning.textContent = `You can not use a decimal point in an exponent on this calculator`;
294 | return true;
295 | } else {
296 | return false;
297 | }
298 | }
299 |
300 | // Check to see if there is a number preceding for factorial and exponent
301 | function hasPreviousNumber() {
302 | if (displayNumber.charAt(displayNumber.length - 1).match(/\d/)) {
303 | return true;
304 | } else {
305 | warning.textContent = `You must enter a number before using a factorial or exponent`;
306 | return false;
307 | }
308 | }
309 |
310 | // CALCULATOR FUNCTIONALITY
311 |
312 | // Backspace 1 space in Display Number, or 1-3 spaces in Raw Data
313 | function backspaceNumberOrOperator() {
314 | // If there is a display number, delete from it first
315 | if (displayNumber.length >= 1) {
316 | let displayArray = displayNumber.split('');
317 | displayArray.pop();
318 | let displayString = displayArray.join('');
319 | displayNumber = displayString;
320 | } else {
321 | let rawDataArray = rawData.split('');
322 | // If the array has an empty string at the end (for example, from ' + ')
323 | if (rawDataArray.length >= 1 && rawDataArray[rawDataArray.length-1].match(/\s/)) {
324 | rawDataArray.pop();
325 | rawDataArray.pop();
326 | rawDataArray.pop();
327 | } else {
328 | rawDataArray.pop();
329 | }
330 | let rawDataString = rawDataArray.join('');
331 | rawData = rawDataString;
332 | }
333 | }
334 |
335 | // Add or remove negative sign from display number
336 | function switchPositiveNegative() {
337 | // If there is not a display number, it will start with '-'
338 | if (displayNumber.length == 0) {
339 | displayNumber = '-';
340 | } else {
341 | let displayArray = displayNumber.split('');
342 | // If the display number is already negative, delete the '-'
343 | if (displayArray[0].match(/-/)) {
344 | displayArray.shift();
345 | let displayString = displayArray.join('');
346 | displayNumber = displayString;
347 | } else {
348 | // If the dislay number is positive, add a "-" to the begining of the array
349 | displayArray.unshift('-');
350 | let displayString = displayArray.join('');
351 | displayNumber = displayString;
352 | }
353 | }
354 | }
355 |
356 | // Add displayNumber to the end of rawData string
357 | function addDisplayToRaw() {
358 | if (rawDataResult.length == 0) {
359 | rawData = rawData + displayNumber;
360 | } else {
361 | rawData = displayNumber;
362 | rawDataResult = '';
363 | }
364 | }
365 |
366 | // Must clear rawDataResult, to use exponents on the product on previous equation
367 | function clearRawDataResult() {
368 | if (rawDataResult.length != 0) {
369 | rawDataResult = '';
370 | }
371 | }
372 |
373 | // Must valiate equation, so it does not end with +_*? - The last thing should be a digit or factorial
374 | function validEquation() {
375 | if (rawData.charAt(rawData.length - 1).match(/!|\d/)) {
376 | return true;
377 | } else {
378 | return false;
379 | }
380 | }
381 |
382 | // Make a copy of rawData to be able to display after calculateData
383 | function copyRawDataToCalculate() {
384 | let rawDataArray = rawData.split(' ');
385 | rawDataResult = rawDataArray.join(' ');
386 | calculateData();
387 | }
388 |
389 | // Main function that processes the rawData to rawDataResult
390 | function calculateData() {
391 | if (rawDataResult.match(/\d+!/)) {
392 | solveFactorial();
393 | } else if (rawDataResult.match(/\d+\^\d+/)) {
394 | solveExponent();
395 | } else if (rawDataResult.match(/\*|\//)) {
396 | solveMultiplicationOrDivison();
397 | } else if ((rawDataResult.match(/[\s][\+|-][\s]/))) {
398 | solveAdditionOrSubtraction();
399 | } else {
400 | if (rawDataResult.length > 12) {
401 | // This formatting is not scientific
402 | formatRawDataResults();
403 | return rawDataResult;
404 | } else {
405 | return rawDataResult;
406 | }
407 | }
408 | }
409 |
410 | function solveFactorial() {
411 | let factorialMatch = rawDataResult.match(/\d+!/)[0];
412 | // Remove the '!' before running factorial function
413 | let factorialArray = factorialMatch.split('');
414 | factorialArray.pop();
415 | factorialNumber = factorialArray.join('');
416 | let factorialResult = factorial(factorialNumber);
417 | // Replace the rawDataResult with the factorialResult
418 | let factoralRawData = /\d+!/[Symbol.replace](rawDataResult, factorialResult);
419 | rawDataResult = factoralRawData;
420 | calculateData();
421 | }
422 |
423 | function solveExponent() {
424 | let exponentRegExp = /\d+\^\d+/;
425 | let exponentMatch = rawDataResult.match(exponentRegExp)[0];
426 | // Find the whole and exponent to run exponent function
427 | let wholeNumber = exponentMatch.match(/^\d+/)[0];
428 | let exponentNumber = exponentMatch.match(/\d+$/)[0];
429 | let exponentResult = exponent(wholeNumber, exponentNumber);
430 | // replace rawDataResult with the exponentResult
431 | let exponentRawData = exponentRegExp[Symbol.replace](rawDataResult, exponentResult);
432 | rawDataResult = exponentRawData;
433 | calculateData();
434 | }
435 |
436 | function solveMultiplicationOrDivison() {
437 | let multiplicationDivisionRegExp = /(\-?)[\d]+(\.?)[\d]*[\s][\*|\/][\s](\-?)[\d]+(\.?)[\d]*/;
438 | let multiplicationDivisionMatch = rawDataResult.match(multiplicationDivisionRegExp)[0];
439 | let isMultiplicationOrDivision = multiplicationDivisionMatch.match(/\*|\//)[0];
440 | // Find the two numbers to run multiplication or division function
441 | let numberRegExp = /(\-?)[\d]+(\.?)[\d]*/g;
442 | let firstNumber = multiplicationDivisionMatch.match(numberRegExp)[0];
443 | let secondNumber = multiplicationDivisionMatch.match(numberRegExp)[1];
444 | if (isMultiplicationOrDivision == '*') {
445 | let multiplicationResult = multiply(firstNumber, secondNumber);
446 | // Replace rawDataResult with multiplicationResult
447 | let multiplicationRawData = multiplicationDivisionRegExp[Symbol.replace](rawDataResult, multiplicationResult);
448 | rawDataResult = multiplicationRawData;
449 | } else {
450 | let divisionResult = divide(firstNumber, secondNumber);
451 | // Replace rawDataResult with divisionResult
452 | let divisionRawData = multiplicationDivisionRegExp[Symbol.replace](rawDataResult, divisionResult);
453 | rawDataResult = divisionRawData;
454 | }
455 | calculateData();
456 | }
457 |
458 | function solveAdditionOrSubtraction() {
459 | // Need to go from left to right finding all of the + or - symbols
460 | const additionSubtractionRegExp = /(\-?)[\d]+(\.?)[\d]*[\s][\+|-][\s](\-?)[\d]+(\.?)[\d]*/;
461 | let additionSubtractionMatch = rawDataResult.match(additionSubtractionRegExp)[0];
462 | let isAdditionOrSubtraction = additionSubtractionMatch.match(/[\s][\+|-][\s]/)[0];
463 | let numberRegExp = /(\-?)[\d]+(\.?)[\d]*/g;
464 | let firstNumber = Number(additionSubtractionMatch.match(numberRegExp)[0]);
465 | let secondNumber = Number(additionSubtractionMatch.match(numberRegExp)[1]);
466 | if (isAdditionOrSubtraction == ' + ') {
467 | let additionResult = add(firstNumber, secondNumber);
468 | let additionRawData = additionSubtractionRegExp[Symbol.replace](rawDataResult, additionResult);
469 | rawDataResult = additionRawData;
470 | } else {
471 | let subtractionResult = subtract(firstNumber, secondNumber);
472 | let subtractionsRawData = additionSubtractionRegExp[Symbol.replace](rawDataResult, subtractionResult);
473 | rawDataResult = subtractionsRawData;
474 | }
475 | calculateData()
476 | }
477 |
478 | // Re-sets the rawData after the equal sign has been used
479 | function displayRawData() {
480 | if (rawDataResult.length == 0) {
481 | rawDisplay.textContent = rawData;
482 | } else {
483 | rawDisplay.textContent = rawData;
484 | rawData = '';
485 | }
486 | }
487 |
488 | // This is not a REAL scientific notation calculation - This is simply gives an illusion that it is to keep calculator within 12 digit limit
489 | function formatRawDataResults() {
490 | removeDigits = (rawDataResult.length - 10);
491 | formattedRawDataArray = rawDataResult.split('');
492 | let notationRegExp = /e\+*\d+/;
493 | let decimalRegExp = /\./;
494 | // Find if there is scientific notation & if so, get length & remove 'n'
495 | if (rawDataResult.match(notationRegExp)) {
496 | rawDataMatch = rawDataResult.match(notationRegExp)[0];
497 | oldNotation = rawDataMatch.length - 1;
498 | rawDataResult = /e\+*/[Symbol.replace](rawDataResult, 0);
499 | addNotation(oldNotation);
500 | // If the number is less then 1 million & has a decimal point, only remove digits.
501 | } else if (rawDataResult < 1000000000 && rawDataResult.match(decimalRegExp)) {
502 | for (i = 1; i <= removeDigits - 2; i++) {
503 | formattedRawDataArray.pop();
504 | }
505 | let formattedRawData = formattedRawDataArray.join('');
506 | rawDataResult = formattedRawData;
507 |
508 | } else {
509 | addNotation(0);
510 | }
511 | warning.textContent = `The result has been formatted to fit in the display area`;
512 | }
513 |
514 | // Need to either remove enough places for single or double digits in scientific notation
515 | function addNotation(oldNotation) {
516 | if ((removeDigits + oldNotation) >= 10) {
517 | for (i = 0; i <= removeDigits; i++) {
518 | formattedRawDataArray.pop();
519 | }
520 | } else {
521 | for (i = 1; i <= removeDigits; i++) {
522 | formattedRawDataArray.pop();
523 | }
524 | }
525 | let formattedRawData = formattedRawDataArray.join('') + `e${removeDigits + oldNotation}`;
526 | rawDataResult = formattedRawData;
527 | }
528 |
529 | // Footer Hover
530 |
531 | function grayIcon() {
532 | footerIcon.src = "img/github-gray.svg";
533 | }
534 |
535 | function whiteIcon() {
536 | footerIcon.src = "img/github-white.svg";
537 | }
538 |
539 | calcButtons.forEach(calcButton => calcButton.addEventListener('click', collectData))
540 | window.addEventListener('keydown', collectData);
541 | footerIcon.addEventListener('mouseenter', grayIcon);
542 | footerIcon.addEventListener('mouseleave', whiteIcon);
543 |
--------------------------------------------------------------------------------