From 3624f8b979c3d2d0b7f7ed73dd5a7104af2c26fb Mon Sep 17 00:00:00 2001 From: IguhSoares Date: Wed, 7 Dec 2022 15:21:32 -0300 Subject: [PATCH 1/2] chore: update js-css-animations/ files to reflect changes made in main branch --- js-css-animations/animate.js | 89 ++++++++++++++++++-------- js-css-animations/globals.js | 2 +- js-css-animations/js-css-animations.js | 12 ++-- js-css-animations/resize-parent.js | 7 +- 4 files changed, 77 insertions(+), 33 deletions(-) diff --git a/js-css-animations/animate.js b/js-css-animations/animate.js index e416cc6..1752b34 100644 --- a/js-css-animations/animate.js +++ b/js-css-animations/animate.js @@ -9,7 +9,12 @@ import { CUSTOM_CSS_PROPERTIES, } from './globals.js'; -import { initParentResize, endParentResize } from './resize-parent.js'; +import { + initParentResize, + endParentResize, + setOverflowHidden, + removeOverflowHidden, +} from './resize-parent.js'; import { removeInlineTransition, @@ -32,7 +37,7 @@ const configurations = { staggerDelay: undefined, start: undefined, complete: undefined, - keepSpace: false, + maintainSpace: false, dimensionsTransition: true, widthTransition: undefined, heightTransition: undefined, @@ -147,6 +152,12 @@ const TARGETS_STACK = { stack: {}, }; +/** + * Keeps track of the EventListeners associated to a trigger selector + * @type {{[x: String]: EventListener[]}} + */ +const LISTENERS = {}; + /** * Removes the CSS properties customized by the user * @param {HTMLElement} element - The DOM element with the custom CSS properties @@ -326,10 +337,12 @@ const isEnabled = element => * @returns True if the element has an iteration CSS property set, False otherwise */ const hasIterationProp = element => { + const iterationProperty = element.style.getPropertyValue( + PROPERTY_NAMES.iteration + ); return ( - element.style - .getPropertyValue(PROPERTY_NAMES.iteration) - .match(/^(infinite|\d+)$/) !== null + iterationProperty != '1' && + iterationProperty.match(/^(infinite|\d+)$/) !== null ); }; @@ -343,17 +356,14 @@ const hasIterationProp = element => { * element: HTMLElement, * parentMeasures: Object, * action: string, - * dimension: string | undefined, - * keepSpace: boolean + * dimension: string | undefined * }} args - All the necessary arguments */ const handleVisibilityToggle = (element, args) => { setTimeout(() => { if (args.dimension) setParentMaxMeasures(args); if (args.action === 'show') { - args.keepSpace - ? element.classList.remove(CLASS_NAMES.hidden) - : element.classList.remove(CLASS_NAMES.collapsed); + element.classList.remove(CLASS_NAMES.hidden, CLASS_NAMES.collapsed); } }, 0); }; @@ -366,12 +376,14 @@ const handleVisibilityToggle = (element, args) => { */ const endVisibilityToggle = (element, opts) => { if (opts.action === 'hide') { - opts.keepSpace + opts.maintainSpace ? element.classList.add(CLASS_NAMES.hidden) : element.classList.add(CLASS_NAMES.collapsed); } if (opts.heightTransition || opts.widthTransition) endParentResize(element, opts); + else if (opts.overflowHidden && element.parentElement) + removeOverflowHidden(element.parentElement); }; /** @@ -414,8 +426,8 @@ const animate = (element, action, id, opts = {}) => { trigger, start = CONFIG.start, complete = CONFIG.complete, - keepSpace = CONFIG.keepSpace, - dimensionsTransition = keepSpace || isMotion(animType) + maintainSpace = CONFIG.maintainSpace, + dimensionsTransition = maintainSpace || isMotion(animType) ? false : CONFIG.dimensionsTransition, widthTransition = CONFIG.widthTransition ?? dimensionsTransition, @@ -444,7 +456,8 @@ const animate = (element, action, id, opts = {}) => { heightTransition, overflowHidden, })); - } + } else if (overflowHidden && element.parentElement) + setOverflowHidden(element.parentElement); }, motion: () => { currentTransition = getCurrentTransition(element); @@ -459,7 +472,6 @@ const animate = (element, action, id, opts = {}) => { parentMeasures, action, dimension, - keepSpace, }); }, motion: () => { @@ -473,9 +485,10 @@ const animate = (element, action, id, opts = {}) => { visibility: () => { endVisibilityToggle(element, { action, - keepSpace, + maintainSpace, widthTransition, heightTransition, + overflowHidden, }); if (!hasIterationProp(element)) element.classList.remove(CLASS_NAMES[action][id]); @@ -567,7 +580,7 @@ const preset = (el, args) => { * @param {HTMLElement} el - The DOM element being animated * @param {number} animationId - The ID of the animation in the *_ANIMS_ID * @param {Object} opts - The options passed by the user - * @returns A function to be passed to the addEventListener() as a handler + * @returns {EventListener} A function to be passed to the addEventListener() as a handler * @see {@link module:globals.VISIBILITY_ANIMS_ID} * @see {@link module:globals.MOTION_ANIMS_ID} */ @@ -619,24 +632,48 @@ const init = (animationId, opts = {}) => { btn.setAttribute('target-selector', targetSelector); } + if (!opts.trigger) opts.trigger = trigger; + LISTENERS[trigger] = []; document .querySelectorAll(getTargetSelector(btn)) .forEach((el, i, queryList) => { - btn.addEventListener( - eventType, - // @ts-ignore - eventHandler(el, animationId, { - ...opts, - totalTargets: queryList.length, - queryIndex: i, - }) - ); + // @ts-ignore + const listener = eventHandler(el, animationId, { + ...opts, + totalTargets: queryList.length, + queryIndex: i, + }); + + LISTENERS[trigger].push(listener); + btn.addEventListener(eventType, listener); }); }); }; +/** + * Removes the event listener of all elements represented by the `triggerSelector` + * @param {String|null} triggerSelector - A valid CSS selector for the trigger Element. If ommited, '.${CLASS_NAMES.trigger}' will be used instead. + * @param {String} eventType - The event name. If ommited, 'click' is the default value. + */ +const end = (triggerSelector = null, eventType = 'click') => { + const triggerList = + typeof triggerSelector === 'string' + ? document.querySelectorAll(triggerSelector) + : document.querySelectorAll(`.${CLASS_NAMES.trigger}`); + + triggerList.forEach(trigger => { + LISTENERS[triggerSelector ?? `.${CLASS_NAMES.trigger}`].forEach( + listener => { + trigger.removeEventListener(eventType, listener); + } + ); + }); + delete LISTENERS[triggerSelector ?? `.${CLASS_NAMES.trigger}`]; +}; + export { init, + end, animate, preset, isEnabled, diff --git a/js-css-animations/globals.js b/js-css-animations/globals.js index 90384d2..dc8064d 100644 --- a/js-css-animations/globals.js +++ b/js-css-animations/globals.js @@ -53,7 +53,7 @@ export const MOTION_ANIMS_ID = Object.freeze({ */ export const PROPERTY_NAMES = Object.freeze({ duration: '--js-css-animation--duration', - timingFunction: '--js-css-animation--timing-function', + easing: '--js-css-animation--timing-function', delay: '--js-css-animation--delay', fillMode: '--js-css-animation--fill-mode', cursor: '--js-css-animation--cursor', diff --git a/js-css-animations/js-css-animations.js b/js-css-animations/js-css-animations.js index a869181..d4b83ae 100644 --- a/js-css-animations/js-css-animations.js +++ b/js-css-animations/js-css-animations.js @@ -4,6 +4,7 @@ */ import { init, + end, animate, preset, isEnabled, @@ -98,11 +99,11 @@ const reset = () => { * duration: number|string|undefined, * delay: number|string|undefined, * staggerDelay: number|string|undefined, - * timingFunction: string|undefined, + * easing: string|undefined, * blur: string|undefined, * angle: string|undefined, * iteration: string|undefined, - * keepSpace: boolean|undefined, + * maintainSpace: boolean|undefined, * overflowHidden: boolean|undefined, * dimensionsTransition: boolean|undefined, * widthTransition: boolean|undefined, @@ -115,13 +116,13 @@ const toggle = (selector, animA, animB, opts = {}) => { 'duration', 'delay', 'staggerDelay', - 'timingFunction', + 'easing', 'blur', 'angle', 'iteration', 'direction', 'transfOrigin', - 'keepSpace', + 'maintainSpace', 'overflowHidden', 'dimensionsTransition', 'widthTransition', @@ -181,7 +182,7 @@ const animationFunctions = (function () { [ 'start', 'complete', - 'keepSpace', + 'maintainSpace', 'overflowHidden', 'staggerDelay', 'widthTransition', @@ -337,6 +338,7 @@ const jsCssAnimations = (function () { const animationsHandler = Object.freeze({ config, reset, + end, init: eventAnimations, ...animationFunctions, show: showVisibilityAnim, diff --git a/js-css-animations/resize-parent.js b/js-css-animations/resize-parent.js index 5c2ddec..ced2214 100644 --- a/js-css-animations/resize-parent.js +++ b/js-css-animations/resize-parent.js @@ -127,4 +127,9 @@ const endParentResize = (element, opts) => { removeOverflowHidden(parentElement); }; -export { initParentResize, endParentResize }; +export { + initParentResize, + endParentResize, + setOverflowHidden, + removeOverflowHidden, +}; From 6dcc71f33f5e20fb40afe55fe4057c432749e874 Mon Sep 17 00:00:00 2001 From: IguhSoares Date: Wed, 7 Dec 2022 15:25:42 -0300 Subject: [PATCH 2/2] docs: update documentation --- jsdoc/doc/animate.js.html | 91 +++++-- jsdoc/doc/globals.js.html | 4 +- jsdoc/doc/index.html | 2 +- jsdoc/doc/js-css-animations.js.html | 14 +- jsdoc/doc/measurements.js.html | 2 +- jsdoc/doc/module-animate.html | 319 +++++++++++++++++++++--- jsdoc/doc/module-globals.html | 2 +- jsdoc/doc/module-js-css-animations.html | 30 +-- jsdoc/doc/module-measurements.html | 2 +- jsdoc/doc/module-resize-parent.html | 2 +- jsdoc/doc/module-transitions.html | 2 +- jsdoc/doc/resize-parent.js.html | 9 +- jsdoc/doc/transitions.js.html | 2 +- 13 files changed, 388 insertions(+), 93 deletions(-) diff --git a/jsdoc/doc/animate.js.html b/jsdoc/doc/animate.js.html index fd55d28..32321fc 100644 --- a/jsdoc/doc/animate.js.html +++ b/jsdoc/doc/animate.js.html @@ -37,7 +37,12 @@

Source: animate.js

CUSTOM_CSS_PROPERTIES, } from './globals.js'; -import { initParentResize, endParentResize } from './resize-parent.js'; +import { + initParentResize, + endParentResize, + setOverflowHidden, + removeOverflowHidden, +} from './resize-parent.js'; import { removeInlineTransition, @@ -60,7 +65,7 @@

Source: animate.js

staggerDelay: undefined, start: undefined, complete: undefined, - keepSpace: false, + maintainSpace: false, dimensionsTransition: true, widthTransition: undefined, heightTransition: undefined, @@ -175,6 +180,12 @@

Source: animate.js

stack: {}, }; +/** + * Keeps track of the EventListeners associated to a trigger selector + * @type {{[x: String]: EventListener[]}} + */ +const LISTENERS = {}; + /** * Removes the CSS properties customized by the user * @param {HTMLElement} element - The DOM element with the custom CSS properties @@ -354,10 +365,12 @@

Source: animate.js

* @returns True if the element has an iteration CSS property set, False otherwise */ const hasIterationProp = element => { + const iterationProperty = element.style.getPropertyValue( + PROPERTY_NAMES.iteration + ); return ( - element.style - .getPropertyValue(PROPERTY_NAMES.iteration) - .match(/^(infinite|\d+)$/) !== null + iterationProperty != '1' && + iterationProperty.match(/^(infinite|\d+)$/) !== null ); }; @@ -371,17 +384,14 @@

Source: animate.js

* element: HTMLElement, * parentMeasures: Object, * action: string, - * dimension: string | undefined, - * keepSpace: boolean + * dimension: string | undefined * }} args - All the necessary arguments */ const handleVisibilityToggle = (element, args) => { setTimeout(() => { if (args.dimension) setParentMaxMeasures(args); if (args.action === 'show') { - args.keepSpace - ? element.classList.remove(CLASS_NAMES.hidden) - : element.classList.remove(CLASS_NAMES.collapsed); + element.classList.remove(CLASS_NAMES.hidden, CLASS_NAMES.collapsed); } }, 0); }; @@ -394,12 +404,14 @@

Source: animate.js

*/ const endVisibilityToggle = (element, opts) => { if (opts.action === 'hide') { - opts.keepSpace + opts.maintainSpace ? element.classList.add(CLASS_NAMES.hidden) : element.classList.add(CLASS_NAMES.collapsed); } if (opts.heightTransition || opts.widthTransition) endParentResize(element, opts); + else if (opts.overflowHidden && element.parentElement) + removeOverflowHidden(element.parentElement); }; /** @@ -442,8 +454,8 @@

Source: animate.js

trigger, start = CONFIG.start, complete = CONFIG.complete, - keepSpace = CONFIG.keepSpace, - dimensionsTransition = keepSpace || isMotion(animType) + maintainSpace = CONFIG.maintainSpace, + dimensionsTransition = maintainSpace || isMotion(animType) ? false : CONFIG.dimensionsTransition, widthTransition = CONFIG.widthTransition ?? dimensionsTransition, @@ -472,7 +484,8 @@

Source: animate.js

heightTransition, overflowHidden, })); - } + } else if (overflowHidden && element.parentElement) + setOverflowHidden(element.parentElement); }, motion: () => { currentTransition = getCurrentTransition(element); @@ -487,7 +500,6 @@

Source: animate.js

parentMeasures, action, dimension, - keepSpace, }); }, motion: () => { @@ -501,9 +513,10 @@

Source: animate.js

visibility: () => { endVisibilityToggle(element, { action, - keepSpace, + maintainSpace, widthTransition, heightTransition, + overflowHidden, }); if (!hasIterationProp(element)) element.classList.remove(CLASS_NAMES[action][id]); @@ -595,7 +608,7 @@

Source: animate.js

* @param {HTMLElement} el - The DOM element being animated * @param {number} animationId - The ID of the animation in the *_ANIMS_ID * @param {Object} opts - The options passed by the user - * @returns A function to be passed to the addEventListener() as a handler + * @returns {EventListener} A function to be passed to the addEventListener() as a handler * @see {@link module:globals.VISIBILITY_ANIMS_ID} * @see {@link module:globals.MOTION_ANIMS_ID} */ @@ -647,24 +660,48 @@

Source: animate.js

btn.setAttribute('target-selector', targetSelector); } + if (!opts.trigger) opts.trigger = trigger; + LISTENERS[trigger] = []; document .querySelectorAll(getTargetSelector(btn)) .forEach((el, i, queryList) => { - btn.addEventListener( - eventType, - // @ts-ignore - eventHandler(el, animationId, { - ...opts, - totalTargets: queryList.length, - queryIndex: i, - }) - ); + // @ts-ignore + const listener = eventHandler(el, animationId, { + ...opts, + totalTargets: queryList.length, + queryIndex: i, + }); + + LISTENERS[trigger].push(listener); + btn.addEventListener(eventType, listener); }); }); }; +/** + * Removes the event listener of all elements represented by the `triggerSelector` + * @param {String|null} triggerSelector - A valid CSS selector for the trigger Element. If ommited, '.${CLASS_NAMES.trigger}' will be used instead. + * @param {String} eventType - The event name. If ommited, 'click' is the default value. + */ +const end = (triggerSelector = null, eventType = 'click') => { + const triggerList = + typeof triggerSelector === 'string' + ? document.querySelectorAll(triggerSelector) + : document.querySelectorAll(`.${CLASS_NAMES.trigger}`); + + triggerList.forEach(trigger => { + LISTENERS[triggerSelector ?? `.${CLASS_NAMES.trigger}`].forEach( + listener => { + trigger.removeEventListener(eventType, listener); + } + ); + }); + delete LISTENERS[triggerSelector ?? `.${CLASS_NAMES.trigger}`]; +}; + export { init, + end, animate, preset, isEnabled, @@ -688,7 +725,7 @@

JS-CSS Animations

Modules