Add rel goto and skip plugins to build.js too

This commit is contained in:
Henrik Ingo
2017-10-21 13:22:19 +03:00
parent 5645849079
commit 10632c2ebc
3 changed files with 404 additions and 10 deletions

View File

@@ -1110,6 +1110,181 @@
} )( document, window );
/**
* Goto Plugin
*
* The goto plugin is a pre-stepleave plugin. It is executed before impress:stepleave,
* and will alter the destination where to transition next.
*
* Example:
*
* <!-- When leaving this step, go directly to "step-5" -->
* <div class="step" data-goto="step-5">
*
* <!-- When leaving this step with next(), go directly to "step-5", instead of next step.
* If moving backwards to previous step - e.g. prev() instead of next() -
* then go to "step-1". -->
* <div class="step" data-goto-next="step-5" data-goto-prev="step-1">
*
* <!-- data-goto-key-list and data-goto-next-list allow you to build advanced non-linear
* navigation. -->
* <div class="step"
* data-goto-key-list="ArrowUp ArrowDown ArrowRight ArrowLeft"
* data-goto-next-list="step-4 step-3 step-2 step-5">
*
* See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values for a table
* of what strings to use for each key.
*
* Copyright 2016-2017 Henrik Ingo (@henrikingo)
* Released under the MIT license.
*/
/* global window, document, impress */
( function( document, window ) {
"use strict";
var lib;
var isNumber = function( numeric ) {
return !isNaN( numeric );
};
var goto = function( event ) {
if ( ( !event ) || ( !event.target ) ) {
return;
}
var data = event.target.dataset;
var steps = document.querySelectorAll( ".step" );
// Data-goto-key-list="" & data-goto-next-list="" //////////////////////////////////////////
if ( data.gotoKeyList !== undefined &&
data.gotoNextList !== undefined &&
event.origEvent !== undefined &&
event.origEvent.key !== undefined ) {
var keylist = data.gotoKeyList.split( " " );
var nextlist = data.gotoNextList.split( " " );
if ( keylist.length !== nextlist.length ) {
window.console.log(
"impress goto plugin: data-goto-key-list and data-goto-next-list don't match:"
);
window.console.log( keylist );
window.console.log( nextlist );
// Don't return, allow the other categories to work despite this error
} else {
var index = keylist.indexOf( event.origEvent.key );
if ( index >= 0 ) {
var next = nextlist[ index ];
if ( isNumber( next ) ) {
event.detail.next = steps[ next ];
// If the new next element has its own transitionDuration, we're responsible
// for setting that on the event as well
event.detail.transitionDuration = lib.util.toNumber(
event.detail.next.dataset.transitionDuration,
event.detail.transitionDuration
);
return;
} else {
var newTarget = document.getElementById( next );
if ( newTarget && newTarget.classList.contains( "step" ) ) {
event.detail.next = newTarget;
event.detail.transitionDuration = lib.util.toNumber(
event.detail.next.dataset.transitionDuration,
event.detail.transitionDuration
);
return;
} else {
window.console.log( "impress goto plugin: " + next +
" is not a step in this impress presentation." );
}
}
}
}
}
// Data-goto-next="" & data-goto-prev="" ///////////////////////////////////////////////////
// Handle event.target data-goto-next attribute
if ( isNumber( data.gotoNext ) && event.detail.reason === "next" ) {
event.detail.next = steps[ data.gotoNext ];
// If the new next element has its own transitionDuration, we're responsible for setting
// that on the event as well
event.detail.transitionDuration = lib.util.toNumber(
event.detail.next.dataset.transitionDuration, event.detail.transitionDuration
);
return;
}
if ( data.gotoNext && event.detail.reason === "next" ) {
var newTarget = document.getElementById( data.gotoNext ); // jshint ignore:line
if ( newTarget && newTarget.classList.contains( "step" ) ) {
event.detail.next = newTarget;
event.detail.transitionDuration = lib.util.toNumber(
event.detail.next.dataset.transitionDuration,
event.detail.transitionDuration
);
return;
} else {
window.console.log( "impress goto plugin: " + data.gotoNext +
" is not a step in this impress presentation." );
}
}
// Handle event.target data-goto-prev attribute
if ( isNumber( data.gotoPrev ) && event.detail.reason === "prev" ) {
event.detail.next = steps[ data.gotoPrev ];
event.detail.transitionDuration = lib.util.toNumber(
event.detail.next.dataset.transitionDuration, event.detail.transitionDuration
);
return;
}
if ( data.gotoPrev && event.detail.reason === "prev" ) {
var newTarget = document.getElementById( data.gotoPrev ); // jshint ignore:line
if ( newTarget && newTarget.classList.contains( "step" ) ) {
event.detail.next = newTarget;
event.detail.transitionDuration = lib.util.toNumber(
event.detail.next.dataset.transitionDuration, event.detail.transitionDuration
);
return;
} else {
window.console.log( "impress goto plugin: " + data.gotoPrev +
" is not a step in this impress presentation." );
}
}
// Data-goto="" ///////////////////////////////////////////////////////////////////////////
// Handle event.target data-goto attribute
if ( isNumber( data.goto ) ) {
event.detail.next = steps[ data.goto ];
event.detail.transitionDuration = lib.util.toNumber(
event.detail.next.dataset.transitionDuration, event.detail.transitionDuration
);
return;
}
if ( data.goto ) {
var newTarget = document.getElementById( data.goto ); // jshint ignore:line
if ( newTarget && newTarget.classList.contains( "step" ) ) {
event.detail.next = newTarget;
event.detail.transitionDuration = lib.util.toNumber(
event.detail.next.dataset.transitionDuration, event.detail.transitionDuration
);
return;
} else {
window.console.log( "impress goto plugin: " + data.goto +
" is not a step in this impress presentation." );
}
}
};
// Register the plugin to be called in pre-stepleave phase
impress.addPreStepLeavePlugin( goto );
} )( document, window );
/**
* Navigation events plugin
*
@@ -1282,6 +1457,180 @@
} )( document );
/**
* Relative Positioning Plugin
*
* This plugin provides support for defining the coordinates of a step relative
* to the previous step. This is often more convenient when creating presentations,
* since as you add, remove or move steps, you may not need to edit the positions
* as much as is the case with the absolute coordinates supported by impress.js
* core.
*
* Example:
*
* <!-- Position step 1000 px to the right and 500 px up from the previous step. -->
* <div class="step" data-rel-x="1000" data-rel-y="500">
*
* Following html attributes are supported for step elements:
*
* data-rel-x
* data-rel-y
* data-rel-z
*
* These values are also inherited from the previous step. This makes it easy to
* create a boring presentation where each slide shifts for example 1000px down
* from the previous.
*
* In addition to plain numbers, which are pixel values, it is also possible to
* define relative positions as a multiple of screen height and width, using
* a unit of "h" and "w", respectively, appended to the number.
*
* Example:
*
* <div class="step" data-rel-x="1.5w" data-rel-y="1.5h">
*
* This plugin is a *pre-init plugin*. It is called synchronously from impress.js
* core at the beginning of `impress().init()`. This allows it to process its own
* data attributes first, and possibly alter the data-x, data-y and data-z attributes
* that will then be processed by `impress().init()`.
*
* (Another name for this kind of plugin might be called a *filter plugin*, but
* *pre-init plugin* is more generic, as a plugin might do whatever it wants in
* the pre-init stage.)
*
* Copyright 2016 Henrik Ingo (@henrikingo)
* Released under the MIT license.
*/
/* global document, window */
( function( document, window ) {
"use strict";
var startingState = {};
/**
* Copied from core impress.js. We currently lack a library mechanism to
* to share utility functions like this.
*/
var toNumber = function( numeric, fallback ) {
return isNaN( numeric ) ? ( fallback || 0 ) : Number( numeric );
};
/**
* Extends toNumber() to correctly compute also relative-to-screen-size values 5w and 5h.
*
* Returns the computed value in pixels with w/h postfix removed.
*/
var toNumberAdvanced = function( numeric, fallback ) {
if ( typeof numeric !== "string" ) {
return toNumber( numeric, fallback );
}
var ratio = numeric.match( /^([+-]*[\d\.]+)([wh])$/ );
if ( ratio == null ) {
return toNumber( numeric, fallback );
} else {
var value = parseFloat( ratio[ 1 ] );
var multiplier = ratio[ 2 ] === "w" ? window.innerWidth : window.innerHeight;
return value * multiplier;
}
};
var computeRelativePositions = function( el, prev ) {
var data = el.dataset;
if ( !prev ) {
// For the first step, inherit these defaults
prev = { x:0, y:0, z:0, relative: { x:0, y:0, z:0 } };
}
var step = {
x: toNumber( data.x, prev.x ),
y: toNumber( data.y, prev.y ),
z: toNumber( data.z, prev.z ),
relative: {
x: toNumberAdvanced( data.relX, prev.relative.x ),
y: toNumberAdvanced( data.relY, prev.relative.y ),
z: toNumberAdvanced( data.relZ, prev.relative.z )
}
};
// Relative position is ignored/zero if absolute is given.
// Note that this also has the effect of resetting any inherited relative values.
if ( data.x !== undefined ) {
step.relative.x = 0;
}
if ( data.y !== undefined ) {
step.relative.y = 0;
}
if ( data.z !== undefined ) {
step.relative.z = 0;
}
// Apply relative position to absolute position, if non-zero
// Note that at this point, the relative values contain a number value of pixels.
step.x = step.x + step.relative.x;
step.y = step.y + step.relative.y;
step.z = step.z + step.relative.z;
return step;
};
var rel = function( root ) {
var steps = root.querySelectorAll( ".step" );
var prev;
startingState[ root.id ] = [];
for ( var i = 0; i < steps.length; i++ ) {
var el = steps[ i ];
startingState[ root.id ].push( {
el: el,
x: el.getAttribute( "data-x" ),
y: el.getAttribute( "data-y" ),
z: el.getAttribute( "data-z" )
} );
var step = computeRelativePositions( el, prev );
// Apply relative position (if non-zero)
el.setAttribute( "data-x", step.x );
el.setAttribute( "data-y", step.y );
el.setAttribute( "data-z", step.z );
prev = step;
}
};
// Register the plugin to be called in pre-init phase
window.impress.addPreInitPlugin( rel );
// Register teardown callback to reset the data.x, .y, .z values.
document.addEventListener( "impress:init", function( event ) {
var root = event.target;
event.detail.api.lib.gc.addCallback( function() {
var steps = startingState[ root.id ];
var step;
while ( step = steps.pop() ) {
if ( step.x === null ) {
step.el.removeAttribute( "data-x" );
} else {
step.el.setAttribute( "data-x", step.x );
}
if ( step.y === null ) {
step.el.removeAttribute( "data-y" );
} else {
step.el.setAttribute( "data-y", step.y );
}
if ( step.z === null ) {
step.el.removeAttribute( "data-z" );
} else {
step.el.setAttribute( "data-z", step.z );
}
}
delete startingState[ root.id ];
} );
}, false );
} )( document, window );
/**
* Resize plugin
*
@@ -1316,3 +1665,39 @@
} )( document, window );
/**
* Stop Plugin
*
* Example:
*
* <!-- 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 stop">
*
* Copyright 2016 Henrik Ingo (@henrikingo)
* Released under the MIT license.
*/
/* global document, window */
( function( document, window ) {
"use strict";
var stop = function( event ) {
if ( ( !event ) || ( !event.target ) ) {
return;
}
if ( event.target.classList.contains( "stop" ) ) {
if ( event.detail.reason === "next" ) {
return false;
}
}
};
// Register the plugin to be called in pre-stepleave phase
// The weight makes this plugin run fairly early.
window.impress.addPreStepLeavePlugin( stop, 2 );
} )( document, window );