diff --git a/.gitignore b/.gitignore
index 7a3a95d..b27ac9d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
+/js/impress.min.js
/node_modules
/npm-debug.log
diff --git a/.jshintrc b/.jshintrc
index 8f8436d..4159bce 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -3,6 +3,7 @@
"module": true
},
"boss": true,
+ "browser": true,
"curly": true,
"eqeqeq": true,
"eqnull": true,
diff --git a/build.js b/build.js
new file mode 100644
index 0000000..34cf484
--- /dev/null
+++ b/build.js
@@ -0,0 +1,12 @@
+var buildify = require('buildify');
+
+buildify()
+ .load('src/impress.js')
+ .concat(['src/plugins/navigation/navigation.js',
+ 'src/plugins/resize/resize.js'])
+ .save('js/impress.js');
+/*
+ * Disabled until uglify supports ES6: https://github.com/mishoo/UglifyJS2/issues/448
+ .uglify()
+ .save('js/impress.min.js');
+*/
\ No newline at end of file
diff --git a/js/impress.js b/js/impress.js
index 25e8996..af1f448 100644
--- a/js/impress.js
+++ b/js/impress.js
@@ -16,9 +16,6 @@
* source: http://github.com/bartaz/impress.js/
*/
-/*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, latedef:true, newcap:true,
- noarg:true, noempty:true, undef:true, strict:true, browser:true */
-
// You are one of those who like to know how things work inside?
// Let me show you the cogs that make impress.js run...
( function( document, window ) {
@@ -213,7 +210,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 +416,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 +492,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 +521,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 +537,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 +659,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 +709,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 +722,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 +795,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 +823,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 +833,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 +885,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.
diff --git a/karma.conf.js b/karma.conf.js
index 4d42e54..4251687 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -18,10 +18,8 @@ module.exports = function( config ) {
// The QUnit tests
"test/helpers.js",
"test/core_tests.js",
- "test/navigation_tests.js",
+ "src/plugins/navigation/navigation_tests.js",
// Presentation files, for the iframe
- //"test/core_tests_presentation.html"
- //{pattern: "test/core_tests_presentation.html", watched: true, served: true, included: false}
{pattern: "test/*.html", watched: true, served: true, included: false},
{pattern: "test/plugins/*/*.html", watched: true, served: true, included: false},
// JS files for iframe
diff --git a/package.json b/package.json
index 1b377eb..60be279 100644
--- a/package.json
+++ b/package.json
@@ -19,15 +19,17 @@
"author": "Bartek Szopka",
"license": "MIT",
"bugs": {
- "url": "https://github.com/bartaz/impress.js/issues"
+ "url": "https://github.com/impress/impress.js/issues"
},
"scripts": {
- "lint": "jshint js/impress.js test/*.js && jscs js/impress.js test/*.js",
+ "build": "node build.js",
+ "lint": "jshint src test/*.js && jscs src test/*.js",
"test": "karma start --single-run",
"test:dev": "karma start",
"test:sauce": "karma start karma.conf-sauce.js"
},
"devDependencies": {
+ "buildify": "*",
"chrome": "0.1.0",
"firefox": "0.0.1",
"jscs": "2.11.0",
diff --git a/qunit_test_runner.html b/qunit_test_runner.html
index 92f24d6..2087e23 100644
--- a/qunit_test_runner.html
+++ b/qunit_test_runner.html
@@ -20,7 +20,7 @@
-
+