summaryrefslogtreecommitdiffhomepage
path: root/js/reveal.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/reveal.js')
-rw-r--r--js/reveal.js202
1 files changed, 124 insertions, 78 deletions
diff --git a/js/reveal.js b/js/reveal.js
index a4881e0..33b58cf 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -25,8 +25,7 @@ var Reveal = (function(){
mouseWheel: true,
rollingLinks: true,
transition: 'default',
- theme: 'default',
- swipeDist: 40
+ theme: 'default'
},
// Slides may hold a data-state attribute which we pick up and apply
@@ -54,8 +53,17 @@ var Reveal = (function(){
mouseWheelTimeout = 0,
// Delays updates to the URL due to a Chrome thumbnailer bug
- writeURLTimeout = 0;
-
+ writeURLTimeout = 0,
+
+ // Holds information about the currently ongoing touch input
+ touch = {
+ startX: 0,
+ startY: 0,
+ startSpan: 0,
+ startCount: 0,
+ handled: false,
+ threshold: 40
+ };
/**
@@ -82,7 +90,7 @@ var Reveal = (function(){
dom.controlsUp = document.querySelector( '#reveal .controls .up' );
dom.controlsDown = document.querySelector( '#reveal .controls .down' );
- addEvents();
+ addEventListeners();
// Copy options over to our config object
extend( config, options );
@@ -133,8 +141,8 @@ var Reveal = (function(){
}
}
- function addEvents() {
- // Bind all view events
+
+ function addEventListeners() {
document.addEventListener( 'keydown', onDocumentKeyDown, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
@@ -146,8 +154,8 @@ var Reveal = (function(){
dom.controlsUp.addEventListener( 'click', preventAndForward( navigateUp ), false );
dom.controlsDown.addEventListener( 'click', preventAndForward( navigateDown ), false );
}
- function removeEvents(){
- // Bind all view events
+
+ function removeEventListeners() {
document.removeEventListener( 'keydown', onDocumentKeyDown, false );
document.removeEventListener( 'touchstart', onDocumentTouchStart, false );
document.removeEventListener( 'touchmove', onDocumentTouchMove, false );
@@ -159,6 +167,7 @@ var Reveal = (function(){
dom.controlsUp.removeEventListener( 'click', preventAndForward( navigateUp ), false );
dom.controlsDown.removeEventListener( 'click', preventAndForward( navigateDown ), false );
}
+
/**
* Extend object a with the properties of object b.
* If there's a conflict, object b takes precedence.
@@ -169,6 +178,13 @@ var Reveal = (function(){
}
}
+ function distanceBetween( a, b ) {
+ var dx = a.x - b.x,
+ dy = a.y - b.y;
+
+ return Math.sqrt( dx*dx + dy*dy );
+ }
+
/**
* Prevents an events defaults behavior calls the
* specified delegate.
@@ -246,81 +262,97 @@ var Reveal = (function(){
}
}
+
/**
- * Handler for the document level 'touchstart' event.
- *
- * This enables very basic tap interaction for touch
- * devices. Added mainly for performance testing of 3D
- * transforms on iOS but was so happily surprised with
- * how smoothly it runs so I left it in here. Apple +1
- *
- * @param {Object} event
+ * Handler for the document level 'touchstart' event,
+ * enables support for swipe and pinch gestures.
*/
- var touchStart = {}
- var gesture = false;
function onDocumentTouchStart( event ) {
-
- touchStart = {
- x: event.touches[0].clientX,
- y: event.touches[0].clientY
- };
- if( event.target.tagName.toLowerCase() === 'a' || event.target.tagName.toLowerCase() === 'img' ) {
- } else {
- event.preventDefault();
- }
+ touch.startX = event.touches[0].clientX;
+ touch.startY = event.touches[0].clientY;
+ touch.startCount = event.touches.length;
+
+ // If there's two touches we need to memorize the distance
+ // between those two points to detect pinching
+ if( event.touches.length === 2 ) {
+ touch.startSpan = distanceBetween( {
+ x: event.touches[1].clientX,
+ y: event.touches[1].clientY
+ }, {
+ x: touch.startX,
+ y: touch.startY
+ } );
+ }
}
+ /**
+ * Handler for the document level 'touchmove' event.
+ */
function onDocumentTouchMove( event ) {
-
- event.preventDefault();
-
- if(!gesture) {
- var touch = {
- x: event.touches[0].clientX,
- y: event.touches[0].clientY
- };
- if((touch.x - touchStart.x) > config.swipeDist){
- gesture = true;
- navigateLeft();
- } else if((touch.x - touchStart.x) < -config.swipeDist){
- gesture = true;
- navigateRight();
- } else if((touch.y - touchStart.y) > config.swipeDist){
- gesture = true;
- navigateUp();
- } else if((touch.y - touchStart.y) < -config.swipeDist){
- gesture = true;
- navigateDown();
+ // Each touch should only trigger one action
+ if( !touch.handled ) {
+ var currentX = event.touches[0].clientX;
+ var currentY = event.touches[0].clientY;
+
+ // If the touch started off with two points and still has
+ // two active touches; test for the pinch gesture
+ if( event.touches.length === 2 && touch.startCount === 2 ) {
+
+ // The current distance in pixels between the two touch points
+ var currentSpan = distanceBetween( {
+ x: event.touches[1].clientX,
+ y: event.touches[1].clientY
+ }, {
+ x: touch.startX,
+ y: touch.startY
+ } );
+
+ // If the span is larger than the desire amount we've got
+ // ourselves a pinch
+ if( Math.abs( touch.startSpan - currentSpan ) > touch.threshold ) {
+ touch.handled = true;
+
+ if( currentSpan < touch.startSpan ) {
+ activateOverview();
+ }
+ else {
+ deactivateOverview();
+ }
+ }
+
}
+ // There was only one touch point, look for a swipe
+ else if( event.touches.length === 1 ) {
+ var deltaX = currentX - touch.startX,
+ deltaY = currentY - touch.startY;
+
+ if( deltaX > touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
+ touch.handled = true;
+ navigateLeft();
+ }
+ else if( deltaX < -touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
+ touch.handled = true;
+ navigateRight();
+ }
+ else if( deltaY > touch.threshold ) {
+ touch.handled = true;
+ navigateUp();
+ }
+ else if( deltaY < -touch.threshold ) {
+ touch.handled = true;
+ navigateDown();
+ }
+ }
+
+ event.preventDefault();
}
}
+
+ /**
+ * Handler for the document level 'touchend' event.
+ */
function onDocumentTouchEnd( event ) {
- if(!gesture){
- // Never prevent taps on anchors and images
- if( event.target.tagName.toLowerCase() === 'a' || event.target.tagName.toLowerCase() === 'img' ) {
- return;
- }
-
- // Define the extent of the areas that may be tapped
- // to navigate
- var wt = window.innerWidth * 0.3;
- var ht = window.innerHeight * 0.3;
-
- if( touchStart.x < wt ) {
- navigateLeft();
- }
- else if( touchStart.x > window.innerWidth - wt ) {
- navigateRight();
- }
- else if( touchStart.y < ht ) {
- navigateUp();
- }
- else if( touchStart.y > window.innerHeight - ht ) {
- navigateDown();
- }
- }
- gesture = false;
- event.preventDefault();
+ touch.handled = false;
}
/**
@@ -706,6 +738,9 @@ var Reveal = (function(){
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
if( verticalFragments.length ) {
verticalFragments[0].classList.add( 'visible' );
+
+ // Notify subscribers of the change
+ dispatchEvent( 'fragmentshown', { fragment: verticalFragments[0] } );
return true;
}
}
@@ -714,6 +749,9 @@ var Reveal = (function(){
var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
if( horizontalFragments.length ) {
horizontalFragments[0].classList.add( 'visible' );
+
+ // Notify subscribers of the change
+ dispatchEvent( 'fragmentshown', { fragment: horizontalFragments[0] } );
return true;
}
}
@@ -733,6 +771,9 @@ var Reveal = (function(){
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' );
if( verticalFragments.length ) {
verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' );
+
+ // Notify subscribers of the change
+ dispatchEvent( 'fragmenthidden', { fragment: verticalFragments[0] } );
return true;
}
}
@@ -741,6 +782,9 @@ var Reveal = (function(){
var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment.visible' );
if( horizontalFragments.length ) {
horizontalFragments[ horizontalFragments.length - 1 ].classList.remove( 'visible' );
+
+ // Notify subscribers of the change
+ dispatchEvent( 'fragmenthidden', { fragment: horizontalFragments[0] } );
return true;
}
}
@@ -826,7 +870,11 @@ var Reveal = (function(){
availableRoutes().down ? navigateDown() : navigateRight();
}
}
- function overviewToggle (){
+
+ /**
+ * Toggles the slide overview mode on and off.
+ */
+ function toggleOverview() {
if( overviewIsActive() ) {
deactivateOverview();
}
@@ -843,9 +891,7 @@ var Reveal = (function(){
navigateRight: navigateRight,
navigateUp: navigateUp,
navigateDown: navigateDown,
- overviewToggle: overviewToggle,
- addEvents: addEvents,
- removeEvents: removeEvents,
+ toggleOverview: toggleOverview,
// Forward event binding to the reveal DOM element
addEventListener: function( type, listener, useCapture ) {