From a41bf288b3ad79c8a10497ab5851fe408ecd3449 Mon Sep 17 00:00:00 2001 From: 7PH Date: Thu, 30 May 2024 23:51:17 +0200 Subject: [PATCH] #26 Make glitch(.) idempotent to allow successive glitch calls on the same query selector --- src/index.ts | 14 +++++++++++++- test/powerglitch.test.ts | 41 +++++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8ed1616..735f485 100644 --- a/src/index.ts +++ b/src/index.ts @@ -448,6 +448,7 @@ const glitchElement = (element: HTMLElement, layers: LayerDefinition[], options: // Base layer const baseLayer = glitched.cloneNode(true) as HTMLElement; + baseLayer.dataset.islayer = 'true'; // Stack this layer baseLayer.style.gridArea = '1/1/-1/-1'; baseLayer.style.userSelect = 'none'; @@ -564,7 +565,18 @@ const glitch = (elOrSelector: GlitchableElement = '.powerglitch', userOptions: G const layers = generateLayers(options); // Animate each div element - const entries = elements.map(element => glitchElement(element, layers, options)); + const entries = elements + /** + * When calling glitch(..) multiple times on the same element, user may attempt to mistakenly glitch all the layers, + * since the query selector will match all the layers. We filter out non-root glitch layers so only the base element is glitched. + */ + .filter(element => ! element.dataset.islayer) + /** + * Glitch each element with the same layer definitions + */ + .map((element) => + glitchElement(element, layers, options) + ); // Return list of containers and glitch control functions return { diff --git a/test/powerglitch.test.ts b/test/powerglitch.test.ts index d39f546..804a2ca 100644 --- a/test/powerglitch.test.ts +++ b/test/powerglitch.test.ts @@ -122,17 +122,36 @@ describe('Given one or multiple element(s) to glitch', () => { }); describe('Given glitching more than once the same element', () => { - /** - * Glitching twice an element should reset its animation - */ - testAllElementTypes('overrides glitch on second call', async elementType => { - const { element } = init(ELEMENTS[elementType]); - const { containers: containers1 } = PowerGlitch.glitch(element, { ...baseOptions, slice: { count: 10 } }); - expect(containers1.length).toBe(1); - expect(containers1[0].firstElementChild?.children.length).toBe(11); - const { containers: containers2 } = PowerGlitch.glitch(element, { ...baseOptions, slice: { count: 20 } }); - expect(containers2.length).toBe(1); - expect(containers2[0].firstElementChild?.children.length).toBe(21); + describe('overrides options on successive call', () => { + testAllElementTypes('using element reference', async elementType => { + const { element } = init(ELEMENTS[elementType]); + const { containers: containers1 } = PowerGlitch.glitch(element, { ...baseOptions, slice: { count: 10 } }); + expect(containers1.length).toBe(1); + expect(containers1[0].firstElementChild?.children.length).toBe(11); + + const { containers: containers2 } = PowerGlitch.glitch(element, { ...baseOptions, slice: { count: 20 } }); + expect(containers2.length).toBe(1); + expect(containers2[0].firstElementChild?.children.length).toBe(21); + + const { containers: containers3 } = PowerGlitch.glitch(element, { ...baseOptions, slice: { count: 15 } }); + expect(containers3.length).toBe(1); + expect(containers3[0].firstElementChild?.children.length).toBe(16); + }); + + testAllElementTypes('using query selector', async elementType => { + init(ELEMENTS[elementType]); + const { containers: containers1 } = PowerGlitch.glitch('.glitch', { ...baseOptions, slice: { count: 10 } }); + expect(containers1.length).toBe(1); + expect(containers1[0].firstElementChild?.children.length).toBe(11); + + const { containers: containers2 } = PowerGlitch.glitch('.glitch', { ...baseOptions, slice: { count: 20 } }); + expect(containers2.length).toBe(1); + expect(containers2[0].firstElementChild?.children.length).toBe(21); + + const { containers: containers3 } = PowerGlitch.glitch('.glitch', { ...baseOptions, slice: { count: 15 } }); + expect(containers3.length).toBe(1); + expect(containers3[0].firstElementChild?.children.length).toBe(16); + }); }); });