Introduce plugin framework
* Source files are under src/ * js/impress.js is now generated, but remains part of the repo (so it just works) * npm run build * build.js uses buildify node module * Break out navigation and resize plugins from core src/impress.js file
This commit is contained in:
251
js/impress.js
251
js/impress.js
@@ -18,6 +18,7 @@
|
||||
|
||||
/*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, latedef:true, newcap:true,
|
||||
noarg:true, noempty:true, undef:true, strict:true, browser:true */
|
||||
/*global window*/
|
||||
|
||||
// You are one of those who like to know how things work inside?
|
||||
// Let me show you the cogs that make impress.js run...
|
||||
@@ -213,7 +214,7 @@
|
||||
|
||||
// And that's where interesting things will start to happen.
|
||||
// It's the core `impress` function that returns the impress.js API
|
||||
// for a presentation based on the element with given id ('impress'
|
||||
// for a presentation based on the element with given id ("impress"
|
||||
// by default).
|
||||
var impress = window.impress = function( rootId ) {
|
||||
|
||||
@@ -419,9 +420,8 @@
|
||||
// Used to reset timeout for `impress:stepenter` event
|
||||
var stepEnterTimeout = null;
|
||||
|
||||
// `goto` API function that moves to step given with `el` parameter
|
||||
// (by index, id or element), with a transition `duration` optionally
|
||||
// given as second parameter.
|
||||
// `goto` API function that moves to step given as `el` parameter (by index, id or element).
|
||||
// `duration` optionally given as second parameter, is the transition duration in css.
|
||||
var goto = function( el, duration ) {
|
||||
|
||||
if ( !initialized || !( el = getStep( el ) ) ) {
|
||||
@@ -496,16 +496,15 @@
|
||||
// being animated separately:
|
||||
// `root` is used for scaling and `canvas` for translate and rotations.
|
||||
// Transitions on them are triggered with different delays (to make
|
||||
// visually nice and 'natural' looking transitions), so we need to know
|
||||
// visually nice and "natural" looking transitions), so we need to know
|
||||
// that both of them are finished.
|
||||
css( root, {
|
||||
|
||||
// To keep the perspective look similar for different scales
|
||||
// we need to "scale" the perspective, too
|
||||
// For IE 11 support we must specify perspective independent
|
||||
// of transform.
|
||||
perspective: ( config.perspective / targetScale ) + "px",
|
||||
|
||||
// To keep the perspective look similar for different scales
|
||||
// we need to 'scale' the perspective, too
|
||||
transform: scale( targetScale ),
|
||||
transitionDuration: duration + "ms",
|
||||
transitionDelay: ( zoomin ? delay : 0 ) + "ms"
|
||||
@@ -526,8 +525,7 @@
|
||||
// account.
|
||||
//
|
||||
// I know that this `if` statement looks scary, but it's pretty simple when you know
|
||||
// what is going on
|
||||
// - it's simply comparing all the values.
|
||||
// what is going on - it's simply comparing all the values.
|
||||
if ( currentState.scale === target.scale ||
|
||||
( currentState.rotate.x === target.rotate.x &&
|
||||
currentState.rotate.y === target.rotate.y &&
|
||||
@@ -543,22 +541,20 @@
|
||||
activeStep = el;
|
||||
|
||||
// And here is where we trigger `impress:stepenter` event.
|
||||
// We simply set up a timeout to fire it taking transition duration
|
||||
// (and possible delay) into account.
|
||||
// We simply set up a timeout to fire it taking transition duration (and possible delay)
|
||||
// into account.
|
||||
//
|
||||
// I really wanted to make it in more elegant way. The `transitionend` event seemed to
|
||||
// be the best way to do it, but the fact that I'm using transitions on two separate
|
||||
// elements and that the `transitionend` event is only triggered when there was a
|
||||
// transition (change in the values) caused some bugs and made the code really
|
||||
// complicated, cause I had to handle all the conditions separately. And it still
|
||||
// needed a `setTimeout` fallback for the situations when there is no transition at
|
||||
// all.
|
||||
// needed a `setTimeout` fallback for the situations when there is no transition at all.
|
||||
// So I decided that I'd rather make the code simpler than use shiny new
|
||||
// `transitionend`.
|
||||
//
|
||||
// If you want learn something interesting and see how it was done with `transitionend`
|
||||
// go back to
|
||||
// version 0.5.2 of impress.js:
|
||||
// go back to version 0.5.2 of impress.js:
|
||||
// http://github.com/bartaz/impress.js/blob/0.5.2/js/impress.js
|
||||
window.clearTimeout( stepEnterTimeout );
|
||||
stepEnterTimeout = window.setTimeout( function() {
|
||||
@@ -667,28 +663,45 @@
|
||||
|
||||
} )( document, window );
|
||||
|
||||
// NAVIGATION EVENTS
|
||||
|
||||
// As you can see this part is separate from the impress.js core code.
|
||||
// It's because these navigation actions only need what impress.js provides with
|
||||
// its simple API.
|
||||
// THAT'S ALL FOLKS!
|
||||
//
|
||||
// In future I think about moving it to make them optional, move to separate files
|
||||
// and treat more like a 'plugins'.
|
||||
( function( document, window ) {
|
||||
// Thanks for reading it all.
|
||||
// Or thanks for scrolling down and reading the last part.
|
||||
//
|
||||
// I've learnt a lot when building impress.js and I hope this code and comments
|
||||
// will help somebody learn at least some part of it.
|
||||
|
||||
/**
|
||||
* Navigation events plugin
|
||||
*
|
||||
* As you can see this part is separate from the impress.js core code.
|
||||
* It's because these navigation actions only need what impress.js provides with
|
||||
* its simple API.
|
||||
*
|
||||
* This plugin is what we call an _init plugin_. It's a simple kind of
|
||||
* impress.js plugin. When loaded, it starts listening to the `impress:init`
|
||||
* event. That event listener initializes the plugin functionality - in this
|
||||
* case we listen to some keypress and mouse events. The only dependencies on
|
||||
* core impress.js functionality is the `impress:init` method, as well as using
|
||||
* the public api `next(), prev(),` etc when keys are pressed.
|
||||
*
|
||||
* Copyright 2011-2012 Bartek Szopka (@bartaz)
|
||||
* Released under the MIT license.
|
||||
* ------------------------------------------------
|
||||
* author: Bartek Szopka
|
||||
* version: 0.5.3
|
||||
* url: http://bartaz.github.com/impress.js/
|
||||
* source: http://github.com/bartaz/impress.js/
|
||||
*
|
||||
*/
|
||||
/* global document */
|
||||
( function( document ) {
|
||||
"use strict";
|
||||
|
||||
// Throttling function calls, by Remy Sharp
|
||||
// http://remysharp.com/2010/07/21/throttling-function-calls/
|
||||
var throttle = function( fn, delay ) {
|
||||
var timer = null;
|
||||
return function() {
|
||||
var context = this, args = arguments;
|
||||
clearTimeout( timer );
|
||||
timer = setTimeout( function() {
|
||||
fn.apply( context, args );
|
||||
}, delay );
|
||||
};
|
||||
var triggerEvent = function( el, eventName, detail ) {
|
||||
var event = document.createEvent( "CustomEvent" );
|
||||
event.initCustomEvent( eventName, true, true, detail );
|
||||
el.dispatchEvent( event );
|
||||
};
|
||||
|
||||
// Wait for impress.js to be initialized
|
||||
@@ -700,19 +713,6 @@
|
||||
// need to control the presentation that was just initialized.
|
||||
var api = event.detail.api;
|
||||
|
||||
// KEYBOARD NAVIGATION HANDLERS
|
||||
|
||||
// Prevent default keydown action when one of supported key is pressed.
|
||||
document.addEventListener( "keydown", function( event ) {
|
||||
if ( event.keyCode === 9 ||
|
||||
( event.keyCode >= 32 && event.keyCode <= 34 ) ||
|
||||
( event.keyCode >= 37 && event.keyCode <= 40 ) ) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}, false );
|
||||
|
||||
// Trigger impress action (next or prev) on keyup.
|
||||
|
||||
// Supported keys are:
|
||||
// [space] - quite common in presentation software to move forward
|
||||
// [up] [right] / [down] [left] - again common and natural addition,
|
||||
@@ -726,30 +726,71 @@
|
||||
// positioning. I didn't want to just prevent this default action, so I used [tab]
|
||||
// as another way to moving to next step... And yes, I know that for the sake of
|
||||
// consistency I should add [shift+tab] as opposite action...
|
||||
document.addEventListener( "keyup", function( event ) {
|
||||
var isNavigationEvent = function( event ) {
|
||||
|
||||
if ( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) {
|
||||
return;
|
||||
// Don't trigger navigation for example when user returns to browser window with ALT+TAB
|
||||
if ( event.altKey || event.ctrlKey || event.metaKey ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( event.keyCode === 9 ||
|
||||
( event.keyCode >= 32 && event.keyCode <= 34 ) ||
|
||||
( event.keyCode >= 37 && event.keyCode <= 40 ) ) {
|
||||
switch ( event.keyCode ) {
|
||||
case 33: // Page up
|
||||
case 37: // Left
|
||||
case 38: // Up
|
||||
api.prev();
|
||||
break;
|
||||
case 9: // Tab
|
||||
case 32: // Space
|
||||
case 34: // Page down
|
||||
case 39: // Right
|
||||
case 40: // Down
|
||||
api.next();
|
||||
break;
|
||||
}
|
||||
// In the case of TAB, we force step navigation always, overriding the browser
|
||||
// navigation between input elements, buttons and links.
|
||||
if ( event.keyCode === 9 ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// With the sole exception of TAB, we also ignore keys pressed if shift is down.
|
||||
if ( event.shiftKey ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For arrows, etc, check that event target is html or body element. This is to allow
|
||||
// presentations to have, for example, forms with input elements where user can type
|
||||
// text, including space, and not move to next step.
|
||||
if ( event.target.nodeName !== "BODY" && event.target.nodeName !== "HTML" ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ( event.keyCode >= 32 && event.keyCode <= 34 ) ||
|
||||
( event.keyCode >= 37 && event.keyCode <= 40 ) ) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// KEYBOARD NAVIGATION HANDLERS
|
||||
|
||||
// Prevent default keydown action when one of supported key is pressed.
|
||||
document.addEventListener( "keydown", function( event ) {
|
||||
if ( isNavigationEvent( event ) ) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}, false );
|
||||
|
||||
// Trigger impress action (next or prev) on keyup.
|
||||
document.addEventListener( "keyup", function( event ) {
|
||||
if ( isNavigationEvent( event ) ) {
|
||||
if ( event.shiftKey ) {
|
||||
switch ( event.keyCode ) {
|
||||
case 9: // Shift+tab
|
||||
api.prev();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch ( event.keyCode ) {
|
||||
case 33: // Pg up
|
||||
case 37: // Left
|
||||
case 38: // Up
|
||||
api.prev( event );
|
||||
break;
|
||||
case 9: // Tab
|
||||
case 32: // Space
|
||||
case 34: // Pg down
|
||||
case 39: // Right
|
||||
case 40: // Down
|
||||
api.next( event );
|
||||
break;
|
||||
}
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
}, false );
|
||||
@@ -758,7 +799,7 @@
|
||||
document.addEventListener( "click", function( event ) {
|
||||
|
||||
// Event delegation with "bubbling"
|
||||
// Check if event target (or any of its parents is a link)
|
||||
// check if event target (or any of its parents is a link)
|
||||
var target = event.target;
|
||||
while ( ( target.tagName !== "A" ) &&
|
||||
( target !== document.documentElement ) ) {
|
||||
@@ -786,8 +827,8 @@
|
||||
|
||||
// Find closest step element that is not active
|
||||
while ( !( target.classList.contains( "step" ) &&
|
||||
!target.classList.contains( "active" ) ) &&
|
||||
( target !== document.documentElement ) ) {
|
||||
!target.classList.contains( "active" ) ) &&
|
||||
( target !== document.documentElement ) ) {
|
||||
target = target.parentNode;
|
||||
}
|
||||
|
||||
@@ -796,25 +837,51 @@
|
||||
}
|
||||
}, false );
|
||||
|
||||
// Touch handler to detect taps on the left and right side of the screen
|
||||
// based on awesome work of @hakimel: https://github.com/hakimel/reveal.js
|
||||
document.addEventListener( "touchstart", function( event ) {
|
||||
if ( event.touches.length === 1 ) {
|
||||
var x = event.touches[ 0 ].clientX,
|
||||
width = window.innerWidth * 0.3,
|
||||
result = null;
|
||||
// Add a line to the help popup
|
||||
triggerEvent( document, "impress:help:add",
|
||||
{ command: "Left & Right", text: "Previous & Next step", row: 1 } );
|
||||
|
||||
if ( x < width ) {
|
||||
result = api.prev();
|
||||
} else if ( x > window.innerWidth - width ) {
|
||||
result = api.next();
|
||||
}
|
||||
}, false );
|
||||
|
||||
if ( result ) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}, false );
|
||||
} )( document );
|
||||
|
||||
|
||||
/**
|
||||
* Resize plugin
|
||||
*
|
||||
* Rescale the presentation after a window resize.
|
||||
*
|
||||
* Copyright 2011-2012 Bartek Szopka (@bartaz)
|
||||
* Released under the MIT license.
|
||||
* ------------------------------------------------
|
||||
* author: Bartek Szopka
|
||||
* version: 0.5.3
|
||||
* url: http://bartaz.github.com/impress.js/
|
||||
* source: http://github.com/bartaz/impress.js/
|
||||
*
|
||||
*/
|
||||
|
||||
/* global document, window */
|
||||
|
||||
( function( document, window ) {
|
||||
"use strict";
|
||||
|
||||
// Throttling function calls, by Remy Sharp
|
||||
// http://remysharp.com/2010/07/21/throttling-function-calls/
|
||||
var throttle = function( fn, delay ) {
|
||||
var timer = null;
|
||||
return function() {
|
||||
var context = this, args = arguments;
|
||||
window.clearTimeout( timer );
|
||||
timer = window.setTimeout( function() {
|
||||
fn.apply( context, args );
|
||||
}, delay );
|
||||
};
|
||||
};
|
||||
|
||||
// Wait for impress.js to be initialized
|
||||
document.addEventListener( "impress:init", function( event ) {
|
||||
var api = event.detail.api;
|
||||
|
||||
// Rescale presentation when window is resized
|
||||
window.addEventListener( "resize", throttle( function() {
|
||||
@@ -822,15 +889,7 @@
|
||||
// Force going to active step again, to trigger rescaling
|
||||
api.goto( document.querySelector( ".step.active" ), 500 );
|
||||
}, 250 ), false );
|
||||
|
||||
}, false );
|
||||
|
||||
} )( document, window );
|
||||
|
||||
// THAT'S ALL FOLKS!
|
||||
//
|
||||
// Thanks for reading it all.
|
||||
// Or thanks for scrolling down and reading the last part.
|
||||
//
|
||||
// I've learnt a lot when building impress.js and I hope this code and comments
|
||||
// will help somebody learn at least some part of it.
|
||||
|
||||
Reference in New Issue
Block a user