Skip to content

Commit

Permalink
By popular request: substep plugin!
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikingo committed Apr 17, 2017
1 parent ebe8d3a commit 674ce0a
Show file tree
Hide file tree
Showing 10 changed files with 278 additions and 21 deletions.
1 change: 1 addition & 0 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ buildify()
'src/plugins/resize/resize.js',
'src/plugins/skip/skip.js',
'src/plugins/stop/stop.js',
'src/plugins/substep/substep.js',
'src/plugins/touch/touch.js',
'src/plugins/toolbar/toolbar.js'])
.save('js/impress.js')
Expand Down
11 changes: 11 additions & 0 deletions examples/classic-slides/css/classic-slides.css
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,17 @@ body.impress-mouse-timeout {
padding-right: 1em;
}

/* Substep plugin */

#impress .step .substep {
opacity: 0;
}

#impress .step .substep.substep-visible {
opacity: 1;
transition: opacity 1s;
}

/*
Styles for specific slides.
*/
Expand Down
10 changes: 6 additions & 4 deletions examples/classic-slides/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@ <h1>Impress.js plugins</h1>
<li>A new <a href="https://github.com/henrikingo/impress.js/blob/myfork/src/plugins/README.md">plugin framework</a> allows for rich extensibility,
without bloating the core rendering library.
<ul>
<li>Press 'P' to open a presenter console.</li>
<li>When you move the mouse, navigation controls are visible on your bottom left</li>
<li>Autoplay makes the slides advance after a timeout</li>
<li>Relative positioning plugin is often a more convenient way to position your slides when editing. (<a href="https://github.com/henrikingo/impress.js/blob/myfork/examples/classic-slides/index.html">See html for this presentation.</a>)</li>
<li class="substep">Press 'P' to open a presenter console.</li>
<li class="substep">When you move the mouse, navigation controls are visible on your bottom left</li>
<li class="substep">Autoplay makes the slides advance after a timeout</li>
<li class="substep">Relative positioning plugin is often a more convenient way to position your slides when editing. (<a href="https://github.com/henrikingo/impress.js/blob/myfork/examples/classic-slides/index.html">See html for this presentation.</a>)</li>
</ul>
</li>
</ul>
Expand All @@ -258,6 +258,8 @@ <h1>Impress.js plugins</h1>

<p>If you pressed P only now, this is the first time you see these notes. In fact, there has been notes on preceding slides as well.
You can use the navigation controls at the bottom of the impress console to browse back to them.</p>

<p>And did you notice how those bullet points appear one by one as you press space/arrow? That's another plugin, called substeps.</p>
</div>
</div>

Expand Down
112 changes: 104 additions & 8 deletions js/impress.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,11 @@
event.detail.next = el;
event.detail.transitionDuration = duration;
event.detail.reason = reason;
execPreStepLeavePlugins(event);
if( execPreStepLeavePlugins(event) === false ) {
// preStepLeave plugins are allowed to abort the transition altogether, by returning false.
// see stop and substep plugins for an example of doing just that
return false;
}
// Plugins are allowed to change the detail values
el = event.detail.next;
step = stepsData["impress-" + el.id];
Expand Down Expand Up @@ -659,6 +663,7 @@
if( Math.abs(pct) > 1 ) return;
// Prepare & execute the preStepLeave event
var event = { target: activeStep, detail : {} };
event.detail.swipe = pct;
// Will be ignored within swipe animation, but just in case a plugin wants to read this, humor them
event.detail.transitionDuration = config.transitionDuration;
if (pct < 0) {
Expand All @@ -673,7 +678,11 @@
// No move
return;
}
execPreStepLeavePlugins(event);
if( execPreStepLeavePlugins(event) === false ) {
// If a preStepLeave plugin wants to abort the transition, don't animate a swipe
// For stop, this is probably ok. For substep, the plugin it self might want to do some animation, but that's not the current implementation.
return false;
}
var nextElement = event.detail.next;

var nextStep = stepsData['impress-' + nextElement.id];
Expand Down Expand Up @@ -870,7 +879,10 @@
var thisLevel = preStepLeavePlugins[i];
if( thisLevel !== undefined ) {
for( var j = 0; j < thisLevel.length; j++ ) {
thisLevel[j](event);
if ( thisLevel[j](event) === false ) {
// If a plugin returns false, the stepleave event (and related transition) is aborted
return false;
}
}
}
}
Expand Down Expand Up @@ -1168,7 +1180,7 @@

// If default autoplay time was defined in the presentation root, or
// in this step, set timeout.
document.addEventListener("impress:stepenter", function (event) {
var reloadTimeout = function ( event ) {
var step = event.target;
currentStepTimeout = toNumber( step.dataset.autoplay, autoplayDefault );
if (status=="paused") {
Expand All @@ -1177,6 +1189,14 @@
else {
setAutoplayTimeout(currentStepTimeout);
}
};

document.addEventListener("impress:stepenter", function (event) {
reloadTimeout(event);
}, false);

document.addEventListener("impress:substep:stepleaveaborted", function (event) {
reloadTimeout(event);
}, false);

/**
Expand Down Expand Up @@ -2479,7 +2499,7 @@
* <!-- Stop at this slide.
* (For example, when used on the last slide, this prevents the
* presentation from wrapping back to the beginning.) -->
* <div class="step" data-stop="true">
* <div class="step stop">
*
* Copyright 2016 Henrik Ingo (@henrikingo)
* Released under the MIT license.
Expand All @@ -2493,14 +2513,90 @@

if ( event.target.classList.contains("stop") ) {
if ( event.detail.reason == "next" )
event.detail.next = event.target;
return false;
}
};

// Register the plugin to be called in pre-stepleave phase
// The weight makes this plugin run fairly late.
impress.addPreStepLeavePlugin( stop, 20 );
// The weight makes this plugin run fairly early.
impress.addPreStepLeavePlugin( stop, 2 );

})(document, window);


/**
* Substep Plugin
*
* Copyright 2017 Henrik Ingo (@henrikingo)
* Released under the MIT license.
*/
(function ( document, window ) {
'use strict';

// Copied from core impress.js. Good candidate for moving to a utilities collection.
var triggerEvent = function (el, eventName, detail) {
var event = document.createEvent("CustomEvent");
event.initCustomEvent(eventName, true, true, detail);
el.dispatchEvent(event);
};

var substep = function(event) {
if ( (!event) || (!event.target) )
return;

// Get array of substeps, if any
var step = event.target;
var substeps = step.querySelectorAll(".substep");
// Get the subset of steps that are currently visible
var visible = step.querySelectorAll(".substep-visible");
if ( substeps.length > 0 ) {
if ( event.detail.reason == "next" ) {
var el = showSubstep(substeps, visible);
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(el, "impress:substep:stepleaveaborted", { reason: "next" } );
// Returning false aborts the stepleave event
return false;
}
}
if ( event.detail.reason == "prev" ) {
var el = hideSubstep(visible);
if ( el ) {
triggerEvent(el, "impress:substep:stepleaveaborted", { reason: "prev" } );
return false;
}
}
}
};

var showSubstep = function (substeps, visible) {
if ( visible.length < substeps.length ) {
var el = substeps[visible.length];
el.classList.add("substep-visible");
return el;
}
};

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.
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);
})(document, window);


Expand Down
18 changes: 15 additions & 3 deletions src/impress.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,11 @@
event.detail.next = el;
event.detail.transitionDuration = duration;
event.detail.reason = reason;
execPreStepLeavePlugins(event);
if( execPreStepLeavePlugins(event) === false ) {
// preStepLeave plugins are allowed to abort the transition altogether, by returning false.
// see stop and substep plugins for an example of doing just that
return false;
}
// Plugins are allowed to change the detail values
el = event.detail.next;
step = stepsData["impress-" + el.id];
Expand Down Expand Up @@ -659,6 +663,7 @@
if( Math.abs(pct) > 1 ) return;
// Prepare & execute the preStepLeave event
var event = { target: activeStep, detail : {} };
event.detail.swipe = pct;
// Will be ignored within swipe animation, but just in case a plugin wants to read this, humor them
event.detail.transitionDuration = config.transitionDuration;
if (pct < 0) {
Expand All @@ -673,7 +678,11 @@
// No move
return;
}
execPreStepLeavePlugins(event);
if( execPreStepLeavePlugins(event) === false ) {
// If a preStepLeave plugin wants to abort the transition, don't animate a swipe
// For stop, this is probably ok. For substep, the plugin it self might want to do some animation, but that's not the current implementation.
return false;
}
var nextElement = event.detail.next;

var nextStep = stepsData['impress-' + nextElement.id];
Expand Down Expand Up @@ -870,7 +879,10 @@
var thisLevel = preStepLeavePlugins[i];
if( thisLevel !== undefined ) {
for( var j = 0; j < thisLevel.length; j++ ) {
thisLevel[j](event);
if ( thisLevel[j](event) === false ) {
// If a plugin returns false, the stepleave event (and related transition) is aborted
return false;
}
}
}
}
Expand Down
17 changes: 16 additions & 1 deletion src/plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,14 @@ plugins that you may want to use or adapt.
data-autoplay="15"
data-rel-x="1000"
data-rel-y="1000">
Slide content...

<h1>Slide content</h1>
<ul>
<li class="substep">Point 1</li>
<li class="substep">Point 2</li>
</ul>

<div class="notes">
Speaker notes are shown in the impressConsole.
</div>
Expand All @@ -79,6 +85,15 @@ plugins that you may want to use or adapt.

### Sample CSS related to plugins and extra addons

/* Using the substep plugin, hide bullet points at first, then show them one by one. */
#impress .step .substep {
opacity: 0;
}

#impress .step .substep.substep-visible {
opacity: 1;
transition: opacity 1s;
}
/*
Speaker notes allow you to write comments within the steps, that will not
be displayed as part of the presentation. However, they will be picked up
Expand Down
10 changes: 9 additions & 1 deletion src/plugins/autoplay/autoplay.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

// If default autoplay time was defined in the presentation root, or
// in this step, set timeout.
document.addEventListener("impress:stepenter", function (event) {
var reloadTimeout = function ( event ) {
var step = event.target;
currentStepTimeout = toNumber( step.dataset.autoplay, autoplayDefault );
if (status=="paused") {
Expand All @@ -59,6 +59,14 @@
else {
setAutoplayTimeout(currentStepTimeout);
}
};

document.addEventListener("impress:stepenter", function (event) {
reloadTimeout(event);
}, false);

document.addEventListener("impress:substep:stepleaveaborted", function (event) {
reloadTimeout(event);
}, false);

/**
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/stop/stop.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* <!-- Stop at this slide.
* (For example, when used on the last slide, this prevents the
* presentation from wrapping back to the beginning.) -->
* <div class="step" data-stop="true">
* <div class="step stop">
*
* Copyright 2016 Henrik Ingo (@henrikingo)
* Released under the MIT license.
Expand All @@ -20,13 +20,13 @@

if ( event.target.classList.contains("stop") ) {
if ( event.detail.reason == "next" )
event.detail.next = event.target;
return false;
}
};

// Register the plugin to be called in pre-stepleave phase
// The weight makes this plugin run fairly late.
impress.addPreStepLeavePlugin( stop, 20 );
// The weight makes this plugin run fairly early.
impress.addPreStepLeavePlugin( stop, 2 );

})(document, window);

37 changes: 37 additions & 0 deletions src/plugins/substep/README.md
Original file line number Diff line number Diff line change
@@ -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.

Loading

0 comments on commit 674ce0a

Please sign in to comment.