By popular request: substep plugin!

References:
https://github.com/impress/impress.js/issues/81
https://github.com/impress/impress.js/issues/600
This commit is contained in:
Henrik Ingo
2017-10-23 23:35:38 +03:00
parent b0ee19950e
commit 156da0bb3f
2 changed files with 148 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
Substep Plugin
===============
Reveal each substep (such as a bullet point) of the step separately. Just like in PowerPoint!
If the current step contains html elements with `class="substep"` then this plugin will prevent a
`prev()` / `next()` call to leave the slide, and instead reveal the next substep (for `next()`) or
alternatively hide one (for `prev()`). Only once all substeps are shown, will a call to `next()`
actually move to the next step, and only when all are hidden will a call to `prev()` move to the
previous one.
Calls to `goto()` will be ignored by this plugin, i.e. `goto()` will transition to whichever step is
the target.
In practice what happens is that when each substep is stepped through via `next()` calls, a
`class="substep-visible"` class is added to the element. It is up to the presentation author to
use the appropriate CSS to make the substeps hidden and visible.
Example:
<style type="text/css">
.substep { opacity: 0; }
.substep.substep-visible { opacity: 1; transition: opacity 1s; }
</style>
<div class="step">
<h1>Fruits</h1>
<p class="substep">Orange</p>
<p class="substep">Apple</p>
</div>
Author
------
Copyright 2017 Henrik Ingo (@henrikingo)
Released under the MIT license.

View File

@@ -0,0 +1,111 @@
/**
* Substep Plugin
*
* Copyright 2017 Henrik Ingo (@henrikingo)
* Released under the MIT license.
*/
/* global document, window */
( function( document, window ) {
"use strict";
// Copied from core impress.js. Good candidate for moving to src/lib/util.js.
var triggerEvent = function( el, eventName, detail ) {
var event = document.createEvent( "CustomEvent" );
event.initCustomEvent( eventName, true, true, detail );
el.dispatchEvent( event );
};
var activeStep = null;
document.addEventListener( "impress:stepenter", function( event ) {
activeStep = event.target;
}, false );
var substep = function( event ) {
if ( ( !event ) || ( !event.target ) ) {
return;
}
var step = event.target;
var el; // Needed by jshint
if ( event.detail.reason === "next" ) {
el = showSubstepIfAny( step );
if ( el ) {
// Send a message to others, that we aborted a stepleave event.
// Autoplay will reload itself from this, as there won't be a stepenter event now.
triggerEvent( step, "impress:substep:stepleaveaborted",
{ reason: "next", substep: el } );
// Returning false aborts the stepleave event
return false;
}
}
if ( event.detail.reason === "prev" ) {
el = hideSubstepIfAny( step );
if ( el ) {
triggerEvent( step, "impress:substep:stepleaveaborted",
{ reason: "prev", substep: el } );
return false;
}
}
};
var showSubstepIfAny = function( step ) {
var substeps = step.querySelectorAll( ".substep" );
var visible = step.querySelectorAll( ".substep-visible" );
if ( substeps.length > 0 ) {
return showSubstep( substeps, visible );
}
};
var showSubstep = function( substeps, visible ) {
if ( visible.length < substeps.length ) {
var el = substeps[ visible.length ];
el.classList.add( "substep-visible" );
return el;
}
};
var hideSubstepIfAny = function( step ) {
var substeps = step.querySelectorAll( ".substep" );
var visible = step.querySelectorAll( ".substep-visible" );
if ( substeps.length > 0 ) {
return hideSubstep( visible );
}
};
var hideSubstep = function( visible ) {
if ( visible.length > 0 ) {
var el = visible[ visible.length - 1 ];
el.classList.remove( "substep-visible" );
return el;
}
};
// Register the plugin to be called in pre-stepleave phase.
// The weight makes this plugin run before other preStepLeave plugins.
window.impress.addPreStepLeavePlugin( substep, 1 );
// When entering a step, in particular when re-entering, make sure that all substeps are hidden
// at first
document.addEventListener( "impress:stepenter", function( event ) {
var step = event.target;
var visible = step.querySelectorAll( ".substep-visible" );
for ( var i = 0; i < visible.length; i++ ) {
visible[ i ].classList.remove( "substep-visible" );
}
}, false );
// API for others to reveal/hide next substep ////////////////////////////////////////////////
document.addEventListener( "impress:substep:show", function() {
showSubstepIfAny( activeStep );
}, false );
document.addEventListener( "impress:substep:hide", function() {
hideSubstepIfAny( activeStep );
}, false );
} )( document, window );