X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/1ee3e779e4b9b0a92f701a72f21a72c83cb1ce68..refs/pull/2023/head:/resources/js/services/animations.js diff --git a/resources/js/services/animations.js b/resources/js/services/animations.js index 8a3e9a57b..278a765d5 100644 --- a/resources/js/services/animations.js +++ b/resources/js/services/animations.js @@ -1,3 +1,26 @@ +/** + * Used in the function below to store references of clean-up functions. + * Used to ensure only one transitionend function exists at any time. + * @type {WeakMap} + */ +const animateStylesCleanupMap = new WeakMap(); + +/** + * Fade in the given element. + * @param {Element} element + * @param {Number} animTime + * @param {Function|null} onComplete + */ +export function fadeIn(element, animTime = 400, onComplete = null) { + cleanupExistingElementAnimation(element); + element.style.display = 'block'; + animateStyles(element, { + opacity: ['0', '1'] + }, animTime, () => { + if (onComplete) onComplete(); + }); +} + /** * Fade out the given element. * @param {Element} element @@ -5,6 +28,7 @@ * @param {Function|null} onComplete */ export function fadeOut(element, animTime = 400, onComplete = null) { + cleanupExistingElementAnimation(element); animateStyles(element, { opacity: ['1', '0'] }, animTime, () => { @@ -19,6 +43,7 @@ export function fadeOut(element, animTime = 400, onComplete = null) { * @param {Number} animTime */ export function slideUp(element, animTime = 400) { + cleanupExistingElementAnimation(element); const currentHeight = element.getBoundingClientRect().height; const computedStyles = getComputedStyle(element); const currentPaddingTop = computedStyles.getPropertyValue('padding-top'); @@ -41,6 +66,7 @@ export function slideUp(element, animTime = 400) { * @param {Number} animTime - Animation time in ms */ export function slideDown(element, animTime = 400) { + cleanupExistingElementAnimation(element); element.style.display = 'block'; const targetHeight = element.getBoundingClientRect().height; const computedStyles = getComputedStyle(element); @@ -56,13 +82,6 @@ export function slideDown(element, animTime = 400) { animateStyles(element, animStyles, animTime); } -/** - * Used in the function below to store references of clean-up functions. - * Used to ensure only one transitionend function exists at any time. - * @type {WeakMap} - */ -const animateStylesCleanupMap = new WeakMap(); - /** * Animate the css styles of an element using FLIP animation techniques. * Styles must be an object where the keys are style properties, camelcase, and the values @@ -84,23 +103,28 @@ function animateStyles(element, styles, animTime = 400, onComplete = null) { } element.style.transition = null; element.removeEventListener('transitionend', cleanup); + animateStylesCleanupMap.delete(element); if (onComplete) onComplete(); }; setTimeout(() => { - requestAnimationFrame(() => { - element.style.transition = `all ease-in-out ${animTime}ms`; - for (let style of styleNames) { - element.style[style] = styles[style][1]; - } + element.style.transition = `all ease-in-out ${animTime}ms`; + for (let style of styleNames) { + element.style[style] = styles[style][1]; + } - if (animateStylesCleanupMap.has(element)) { - const oldCleanup = animateStylesCleanupMap.get(element); - element.removeEventListener('transitionend', oldCleanup); - } + element.addEventListener('transitionend', cleanup); + animateStylesCleanupMap.set(element, cleanup); + }, 15); +} - element.addEventListener('transitionend', cleanup); - animateStylesCleanupMap.set(element, cleanup); - }); - }, 10); +/** + * Run the active cleanup action for the given element. + * @param {Element} element + */ +function cleanupExistingElementAnimation(element) { + if (animateStylesCleanupMap.has(element)) { + const oldCleanup = animateStylesCleanupMap.get(element); + oldCleanup(); + } } \ No newline at end of file