165 lines
5.1 KiB
JavaScript
165 lines
5.1 KiB
JavaScript
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();
|
||
} else if (value === 'H') {
|
||
toggleHistory();
|
||
} else if (value === '') {
|
||
toggleSettings();
|
||
} 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
|
||
currentOffset -= spanWidth; // Move left by the width of the character + some margin
|
||
|
||
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
|
||
currentOffset -= spanWidth; // Move left by the width of the character + some margin
|
||
|
||
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;
|
||
}
|
||
|
||
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'
|
||
})
|
||
}
|
||
}
|
||
|
||
function toggleSettings() {
|
||
$('body').toggleClass('settings-open');
|
||
}
|
||
|
||
$('#history').on('click', toggleHistory);
|
||
|
||
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
|
||
});
|
||
} |