kalkulator/static/assets/js/calculator-logic.js

166 lines
5.2 KiB
JavaScript
Raw Normal View History

// This file is responsible for all calculator animations and logic.
2024-10-16 22:46:58 +02:00
const buttons = document.querySelectorAll('.button');
const displayText = document.querySelector('.display-text');
let currentInput = '';
let characterSpans = []; // Array to track all spans for proper positioning
let isResultDisplayed = false; // Track if the result is displayed
let resultSpan; // For showing the result
buttons.forEach(button => {
button.addEventListener('click', () => {
const value = button.textContent;
if (value === 'AC') {
resetCalculator();
2024-10-17 09:05:34 +02:00
} else if (value === 'H') {
toggleHistory();
} else if (value === '') {
toggleSettings();
2024-10-16 22:46:58 +02:00
} else if (value === '=') {
calculateResult();
} else {
if (isResultDisplayed) {
resetCalculator(); // Reset after "=" is pressed
}
if (currentInput === 'Error') currentInput = ''; // Clear on error
currentInput += value;
appendCharacter(value); // Append with animation
}
});
});
function appendCharacter(char) {
// Create new span element for the character
const newChar = document.createElement('span');
newChar.textContent = char;
displayText.appendChild(newChar);
characterSpans.push(newChar); // Add the new span to the array
// Move all characters smoothly
updateCharacterPositions();
// Animate the new character in from the right
anime({
targets: newChar,
opacity: [0, 1],
translateY: [0, -25], // Animating into place
scale: [0, 1],
duration: 500,
easing: 'easeOutExpo'
});
}
function updateCharacterPositions() {
const totalWidth = displayText.offsetWidth; // Width of the display
let currentOffset = totalWidth; // Start from the rightmost edge
// Loop through characters in reverse (so newest appears at the right)
for (let i = characterSpans.length - 1; i >= 0; i--) {
const span = characterSpans[i];
const spanWidth = span.offsetWidth; // Get the width of each character
2024-10-17 09:05:34 +02:00
currentOffset -= spanWidth; // Move left by the width of the character + some margin
2024-10-16 22:46:58 +02:00
anime({
targets: span,
right: (totalWidth - currentOffset - spanWidth) + 'px', // Keep them aligned right
duration: 300,
easing: 'easeOutQuint'
});
}
}
function calculateResult() {
const equation = characterSpans.map(span => span.textContent).join('');
let result;
try {
result = eval(equation.replace('÷', '/').replaceAll('×', '*')).toString();
} catch (error) {
result = 'Error';
}
characterSpans.forEach(span => {
span.style.fontSize = '1.5rem';
});
const totalWidth = displayText.offsetWidth; // Width of the display
let currentOffset = totalWidth; // Start from the rightmost edge
// Animate the equation upwards
// Loop through characters in reverse (so newest appears at the right)
for (let i = characterSpans.length - 1; i >= 0; i--) {
const span = characterSpans[i];
const spanWidth = span.offsetWidth; // Get the width of each character
2024-10-17 09:05:34 +02:00
currentOffset -= spanWidth; // Move left by the width of the character + some margin
2024-10-16 22:46:58 +02:00
anime({
targets: span,
translateY: -45,
opacity: [1, 0.4],
right: (totalWidth - currentOffset - spanWidth) + 'px', // Keep them aligned right
duration: 800,
easing: 'easeOutExpo'
});
}
resultSpan = document.createElement('span'); // Create a new span for the result
resultSpan.textContent = `= ${result}`;
displayText.appendChild(resultSpan);
// Animate the result to appear from below
anime({
targets: resultSpan,
opacity: [0, 1],
translateY: [50, -10], // Animating upwards
translateX: -5,
scale: [0, 1],
duration: 500,
easing: 'easeOutExpo'
});
// Set a flag to reset on the next key press
isResultDisplayed = true;
}
2024-10-17 09:05:34 +02:00
function toggleHistory() {
$('body').toggleClass('history-open');
if ($('body').hasClass('history-open')) { // If the history was just opened
// Animate it's elements
anime({
targets: '.history-container span',
translateY: [-100, 0],
opacity: [0, 1],
duration: 400,
delay: anime.stagger(100, { start: 200, direction: 'reverse' }),
easing: 'easeOutQuart'
})
}
}
function toggleSettings() {
$('body').toggleClass('settings-open');
}
2024-10-17 09:05:34 +02:00
$('#history').on('click', toggleHistory);
2024-10-16 22:46:58 +02:00
function clearDisplay() {
// Remove all current characters (spans)
characterSpans.forEach(span => span.remove());
characterSpans = [];
}
function resetCalculator() {
currentInput = '';
characterSpans = [];
displayText.innerHTML = ''; // Clear the display
isResultDisplayed = false; // Reset the result display flag
}
function updateDisplay(value) {
// Clear existing spans and reset positions
displayText.innerHTML = '';
characterSpans = [];
[...value].forEach(char => {
appendCharacter(char); // Append each character
});
}