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();
|
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
|
|
|
|
|
console.log('a')
|
|
|
|
|
anime({
|
|
|
|
|
targets: '.history-container span',
|
|
|
|
|
translateY: [-100, 0],
|
|
|
|
|
opacity: [0, 1],
|
|
|
|
|
duration: 400,
|
|
|
|
|
delay: anime.stagger(100, { start: 200, direction: 'reverse' }),
|
|
|
|
|
easing: 'easeOutQuart'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$('#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
|
|
|
|
|
});
|
|
|
|
|
}
|