From 452f62286b5d61f0f8ddb7e5e59b9bc351a5fcc7 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Mon, 3 Feb 2020 11:13:47 +0100 Subject: [PATCH] auto-match animatable targets by their contents --- js/reveal.js | 88 ++++++++++++++++++++++++++++----- test/examples/auto-animate.html | 28 ++++++----- 2 files changed, 92 insertions(+), 24 deletions(-) diff --git a/js/reveal.js b/js/reveal.js index 087d9ca1..7eb8f50d 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -3836,17 +3836,8 @@ options.duration = parseFloat( toSlide.getAttribute( 'data-auto-animate-duration' ) ); } - var fromTargets = {}; - - toArray( fromSlide.querySelectorAll( '[data-id]' ) ).forEach( function( fromElement ) { - fromTargets[ fromElement.getAttribute( 'data-id' ) ] = fromElement; - } ); - - toArray( toSlide.querySelectorAll( '[data-id]' ) ).forEach( function( toElement ) { - var fromElement = fromTargets[ toElement.getAttribute( 'data-id' ) ]; - if( fromElement ) { - autoAnimateElement( fromElement, toElement, options ); - } + getAutoAnimatableElements( fromSlide, toSlide ).forEach( function( elements ) { + autoAnimateElement( elements[0], elements[1], options ); } ); } @@ -3947,6 +3938,81 @@ } + /** + * [getAutoAnimatableElements description] + * @param {HTMLElement} fromSlide + * @param {HTMLElement} toSlide + * + * @return {Array} Each value is an array where [0] is + * the element we're animating from and [1] is the + * element we're animating to + */ + function getAutoAnimatableElements( fromSlide, toSlide ) { + + var pairs = findImplicitAutoAnimatePairs( fromSlide, toSlide ) + .concat( findExplicitAutoAnimatePairs( fromSlide, toSlide ) ); + + // Remove duplicate pairs + pairs = pairs.filter( function( pair, index ) { + return index === pairs.findIndex( function( comparePair ) { + return pair[0] === comparePair[0] && pair[1] === comparePair[1]; + } ); + } ); + + return pairs; + + } + + /** + * Returns an array of auto-animate element pairs + * discovered through implicing means such as matching + * text content. + */ + function findImplicitAutoAnimatePairs( fromSlide, toSlide ) { + + var textSelector = 'h1, h2, h3, h4, h5, h6, p, li, span'; + + var pairs = []; + var fromHash = {}; + + toArray( fromSlide.querySelectorAll( textSelector ) ).forEach( function( element ) { + fromHash[ element.nodeName+':::'+element.textContent ] = element; + } ); + + toArray( toSlide.querySelectorAll( textSelector ) ).forEach( function( element ) { + var fromElement = fromHash[ element.nodeName+':::'+element.textContent ]; + if( fromElement ) { + pairs.push([ fromElement, element ]); + } + } ); + + return pairs; + + } + + /** + * Returns explicitly ID-matched auto-animate elements. + */ + function findExplicitAutoAnimatePairs( fromSlide, toSlide ) { + + var pairs = []; + var fromHash = {}; + + toArray( fromSlide.querySelectorAll( '[data-id]' ) ).forEach( function( fromElement ) { + fromHash[ fromElement.getAttribute( 'data-id' ) ] = fromElement; + } ); + + toArray( toSlide.querySelectorAll( '[data-id]' ) ).forEach( function( toElement ) { + var fromElement = fromHash[ toElement.getAttribute( 'data-id' ) ]; + if( fromElement ) { + pairs.push([ fromElement, toElement ]); + } + } ); + + return pairs; + + } + /** * Should the given element be preloaded? * Decides based on local element attributes and global config. diff --git a/test/examples/auto-animate.html b/test/examples/auto-animate.html index 3b5a96be..a3a21e33 100644 --- a/test/examples/auto-animate.html +++ b/test/examples/auto-animate.html @@ -19,12 +19,14 @@
-

Fade and slide

-

Opacity 1.0

+

Auto-Matched Content (no IDs)

+

This will fade out

+
-

Fade and slide

-

Opacity 0.2

+

Auto-Matched Content (no IDs)

+

This will fade out

+
@@ -37,25 +39,25 @@

Swapping list items

    -
  • One
  • -
  • Two
  • -
  • Three
  • +
  • One
  • +
  • Two
  • +
  • Three

Swapping list items

    -
  • Two
  • -
  • One
  • -
  • Three
  • +
  • Two
  • +
  • One
  • +
  • Three

Swapping list items

    -
  • Two
  • -
  • Three
  • -
  • One
  • +
  • Two
  • +
  • Three
  • +
  • One