From ea295796eab7661c1e2050d3442e53a44d02ad88 Mon Sep 17 00:00:00 2001
From: Hakim El Hattab <hakim.elhattab@gmail.com>
Date: Tue, 11 Feb 2020 15:31:17 +0100
Subject: [PATCH] refactoring and fixed auto-animate test exception

---
 README.md                       | 11 ++++++++
 js/reveal.js                    | 33 ++++++++++++------------
 test/examples/auto-animate.html |  2 +-
 test/test-auto-animate.html     | 45 ++++++++++++++++++---------------
 4 files changed, 53 insertions(+), 38 deletions(-)

diff --git a/README.md b/README.md
index 7f78d97d..fd35581c 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@ reveal.js comes with a broad range of features including [nested slides](https:/
 - [Vertical Slide Navigation](#vertical-slide-navigation)
 - [Touch Navigation](#touch-navigation)
 - [Lazy Loading](#lazy-loading)
+- [Auto-Animate](#auto-animate)
 - [API](#api)
   - [Custom Key Bindings](#custom-key-bindings)
   - [Slide Changed Event](#slide-changed-event)
@@ -543,6 +544,16 @@ Reveal.configure({
 });
 ```
 
+### Auto-Animate
+
+TBD
+
+#### Slide & Element Specific Settings
+TBD. How to use data-attributes to override transition settings.
+
+#### Custom Element Matcher
+TBD. How to implement your own element matcher.
+
 ### Vertical Slide Navigation
 
 Slides can be nested within other slides to create vertical stacks (see [Markup](#markup)). When presenting, you use the left/right arrows to step through the main (horizontal) slides. When you arrive at a vertical stack you can optionally press the up/down arrows to view the vertical slides or skip past them by pressing the right arrow. Here's an example showing a bird's-eye view of what this looks like in action:
diff --git a/js/reveal.js b/js/reveal.js
index f44b36fe..2943619c 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -3854,7 +3854,7 @@
 			delete element.dataset.autoAnimateTarget;
 		} );
 
-		var animationOptions = getAutoAnimateOptions( toSlide, {
+		var slideOptions = getAutoAnimateOptions( toSlide, {
 
 			// If our slides are centered vertically, we need to
 			// account for their difference in position when
@@ -3869,7 +3869,7 @@
 
 		// Inject our auto-animate styles for this transition
 		autoAnimateStyleSheet.innerHTML = getAutoAnimatableElements( fromSlide, toSlide ).map( function( elements ) {
-			return getAutoAnimateCSS( elements[0], elements[1], elements[2] || {}, animationOptions, autoAnimateCounter++ );
+			return getAutoAnimateCSS( elements[0], elements[1], elements[2] || {}, slideOptions, autoAnimateCounter++ );
 		} ).join( '' );
 
 		// Start the animation next cycle
@@ -3920,11 +3920,11 @@
 	 * @param {HTMLElement} from
 	 * @param {HTMLElement} to
 	 * @param {Object} elementOptions Options for this element pair
-	 * @param {Object} animationOptions Options for all elements in
+	 * @param {Object} slideOptions Options set at the slide level
 	 * @param {String} id Unique ID that we can use to identify this
 	 * auto-animate element in the DOM
 	 */
-	function getAutoAnimateCSS( from, to, elementOptions, animationOptions, id ) {
+	function getAutoAnimateCSS( from, to, elementOptions, slideOptions, id ) {
 
 		// 'from' elements are given a data-auto-animate-target with no value,
 		// 'to' elements are are given a data-auto-animate-target with an ID
@@ -3933,13 +3933,13 @@
 
 		// Each element may override any of the auto-animate options
 		// like transition easing, duration and delay
-		animationOptions = getAutoAnimateOptions( to, animationOptions );
+		var options = getAutoAnimateOptions( to, slideOptions );
 
 		// Individual transition settings can be overridden via
 		// element options
-		if( typeof elementOptions.delay !== 'undefined' ) animationOptions.delay = elementOptions.delay;
-		if( typeof elementOptions.duration !== 'undefined' ) animationOptions.duration = elementOptions.duration;
-		if( typeof elementOptions.easing !== 'undefined' ) animationOptions.easing = elementOptions.easing;
+		if( typeof elementOptions.delay !== 'undefined' ) options.delay = elementOptions.delay;
+		if( typeof elementOptions.duration !== 'undefined' ) options.duration = elementOptions.duration;
+		if( typeof elementOptions.easing !== 'undefined' ) options.easing = elementOptions.easing;
 
 		var fromProps = getAutoAnimatableProperties( 'from', from, elementOptions ),
 			toProps = getAutoAnimatableProperties( 'to', to, elementOptions );
@@ -3948,7 +3948,7 @@
 		fromProps.styles['transition'] = 'none';
 
 		// transition to the 'to' state
-		toProps.styles['transition'] = 'all '+ animationOptions.duration +'s '+ animationOptions.easing + ' ' + animationOptions.delay + 's';
+		toProps.styles['transition'] = 'all '+ options.duration +'s '+ options.easing + ' ' + options.delay + 's';
 
 		// If translation and/or scalin are enabled, offset the
 		// 'to' element so that it starts out at the same position
@@ -3957,7 +3957,7 @@
 
 			var delta = {
 				x: fromProps.x - toProps.x,
-				y: fromProps.y - toProps.y + animationOptions.offsetY,
+				y: fromProps.y - toProps.y + options.offsetY,
 				scaleX: fromProps.width / toProps.width,
 				scaleY: fromProps.height / toProps.height
 			};
@@ -3999,12 +3999,12 @@
 	 * that can be auto-animated for the given element
 	 * and their respective values.
 	 */
-	function getAutoAnimatableProperties( direction, element, options ) {
+	function getAutoAnimatableProperties( direction, element, elementOptions ) {
 
 		var properties = { styles: [] };
 
 		// Position and size
-		if( options.translate !== false || options.scale !== false ) {
+		if( elementOptions.translate !== false || elementOptions.scale !== false ) {
 			properties.x = element.offsetLeft;
 			properties.y = element.offsetTop;
 			properties.width = element.offsetWidth;
@@ -4014,7 +4014,7 @@
 		var computedStyles = window.getComputedStyle( element );
 
 		// CSS styles
-		( options.styles || config.autoAnimateStyles ).forEach( function( style ) {
+		( elementOptions.styles || config.autoAnimateStyles ).forEach( function( style ) {
 			var value;
 
 			// `style` is either the property name directly, or an object
@@ -4067,9 +4067,10 @@
 	}
 
 	/**
-	 * Identifies matching elements between slides. You can specify
-	 * a custom matcher function by using the autoAnimateMatcher
-	 * config option.
+	 * Identifies matching elements between slides.
+	 *
+	 * You can specify a custom matcher function by using
+	 * the autoAnimateMatcher config option.
 	 */
 	function findAutoAnimatePairs( fromSlide, toSlide ) {
 
diff --git a/test/examples/auto-animate.html b/test/examples/auto-animate.html
index 7603ecb2..b8fca80a 100644
--- a/test/examples/auto-animate.html
+++ b/test/examples/auto-animate.html
@@ -30,7 +30,7 @@ function Example() {
 					</code></pre>
 				</section>
 				<section data-auto-animate data-auto-animate-unmatched="fade">
-					<h3 data-auto-animate-delay="1">Auto-Matched Content (no IDs)</h3>
+					<h3>Auto-Matched Content (no IDs)</h3>
 					<p style="opacity: 0.2; margin-top: 200px;">This will fade out</p>
 					<p>This element is unmatched</p>
 					<img src="assets/image1.png" style="height: 100px;">
diff --git a/test/test-auto-animate.html b/test/test-auto-animate.html
index 2d757101..6e3080d2 100644
--- a/test/test-auto-animate.html
+++ b/test/test-auto-animate.html
@@ -45,20 +45,19 @@
 		<script src="qunit-2.5.0.js"></script>
 
 		<script>
-			window.externalScriptSequence = '';
+
+			const slides = [].slice.call( document.querySelectorAll( '.slides section' ) ).map( slide => {
+				return {
+					h1: slide.querySelector( 'h1' ),
+					h2: slide.querySelector( 'h2' ),
+					h3: slide.querySelector( 'h3' )
+				};
+			} );
 
 			Reveal.addEventListener( 'ready', () => {
 
 				QUnit.module( 'Auto-Animate' );
 
-				const slides = [].slice.call( document.querySelectorAll( '.slides section' ) ).map( slide => {
-					return {
-						h1: slide.querySelector( 'h1' ),
-						h2: slide.querySelector( 'h2' ),
-						h3: slide.querySelector( 'h3' )
-					};
-				} );
-
 				QUnit.test( 'Adds data-auto-animate-target', assert => {
 					Reveal.slide(1);
 					assert.strictEqual( slides[0].h1.getAttribute( 'data-auto-animate-target' ), '', 'From elements have blank data-auto-animate-target' );
@@ -72,27 +71,31 @@
 				});
 
 				QUnit.test( 'Slide specific data-auto-animate-duration', assert => {
-					assert.timeout( 350 );
-					var done = assert.async();
+					assert.timeout( 400 );
+					let done = assert.async();
+					let callback = () => {
+						slides[2].h3.removeEventListener( 'transitionend', callback );
+						assert.ok( true, 'Transition ended within time window' );
+						done();
+					}
 
 					Reveal.slide(2);
 
-					slides[2].h3.addEventListener( 'transitionend', function() {
-						assert.ok( true, 'Transition ended within time window' );
-						done();
-					} );
+					slides[2].h3.addEventListener( 'transitionend', callback );
 				});
 
 				QUnit.test( 'Element specific data-auto-animate-duration', assert => {
-					assert.timeout( 350 );
-					var done = assert.async();
+					assert.timeout( 400 );
+					let done = assert.async();
+					let callback = () => {
+						slides[1].h1.removeEventListener( 'transitionend', callback );
+						assert.ok( true, 'Transition ended within time window' );
+						done();
+					}
 
 					Reveal.slide(1);
 
-					slides[1].h1.addEventListener( 'transitionend', function() {
-						assert.ok( true, 'Transition ended within time window' );
-						done();
-					} );
+					slides[1].h1.addEventListener( 'transitionend', callback );
 				});
 
 			} );
-- 
GitLab