From: Hakim El Hattab Date: Sat, 2 Jun 2012 21:45:06 +0000 (-0400) Subject: support for swipe and pinch gestures #48 X-Git-Tag: 1.3.0~1 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=4f08e2aeb08010bb0b78ad3ce871958383336e10;p=reveal.js.git support for swipe and pinch gestures #48 --- 4f08e2aeb08010bb0b78ad3ce871958383336e10 diff --cc js/reveal.js index d6c5b5b,a4881e0..33b58cf --- a/js/reveal.js +++ b/js/reveal.js @@@ -53,7 -54,9 +53,18 @@@ 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 ++ }; + /** * Starts up the slideshow by applying configuration @@@ -79,14 -82,7 +90,7 @@@ dom.controlsUp = document.querySelector( '#reveal .controls .up' ); dom.controlsDown = document.querySelector( '#reveal .controls .down' ); - // Bind all view events - document.addEventListener( 'keydown', onDocumentKeyDown, false ); - document.addEventListener( 'touchstart', onDocumentTouchStart, false ); - window.addEventListener( 'hashchange', onWindowHashChange, false ); - dom.controlsLeft.addEventListener( 'click', preventAndForward( navigateLeft ), false ); - dom.controlsRight.addEventListener( 'click', preventAndForward( navigateRight ), false ); - dom.controlsUp.addEventListener( 'click', preventAndForward( navigateUp ), false ); - dom.controlsDown.addEventListener( 'click', preventAndForward( navigateDown ), false ); - addEvents(); ++ addEventListeners(); // Copy options over to our config object extend( config, options ); @@@ -135,8 -131,34 +139,35 @@@ window.addEventListener( 'load', removeAddressBar, false ); window.addEventListener( 'orientationchange', removeAddressBar, false ); } + + } - function addEvents() { - // Bind all view events ++ ++ function addEventListeners() { + document.addEventListener( 'keydown', onDocumentKeyDown, false ); + document.addEventListener( 'touchstart', onDocumentTouchStart, false ); + document.addEventListener( 'touchmove', onDocumentTouchMove, false ); + document.addEventListener( 'touchend', onDocumentTouchEnd, false ); + window.addEventListener( 'hashchange', onWindowHashChange, false ); + + dom.controlsLeft.addEventListener( 'click', preventAndForward( navigateLeft ), false ); + dom.controlsRight.addEventListener( 'click', preventAndForward( navigateRight ), false ); + 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 ); + document.removeEventListener( 'touchend', onDocumentTouchEnd, false ); + window.removeEventListener( 'hashchange', onWindowHashChange, false ); + + dom.controlsLeft.removeEventListener( 'click', preventAndForward( navigateLeft ), false ); + dom.controlsRight.removeEventListener( 'click', preventAndForward( navigateRight ), false ); + 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. @@@ -147,6 -169,6 +178,13 @@@ } } ++ 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. @@@ -224,54 -246,82 +262,98 @@@ } } - ++ /** -- * 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 ) { - // We're only interested in one point taps - if (event.touches.length === 1) { - // Never prevent taps on anchors and images - if( event.target.tagName.toLowerCase() === 'a' || event.target.tagName.toLowerCase() === 'img' ) { - return; - } - - event.preventDefault(); - - var point = { - x: event.touches[0].clientX, - y: event.touches[0].clientY - }; - - // 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( point.x < wt ) { - navigateLeft(); - } - else if( point.x > window.innerWidth - wt ) { - navigateRight(); - 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(); -- } - else if( point.y < ht ) { - navigateUp(); ++ 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(); ++ } ++ } ++ } - else if( point.y > window.innerHeight - ht ) { - navigateDown(); ++ // 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(); ++ } + } - - slide(); ++ ++ 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; + } /** * Handles mouse wheel scrolling, throttled to avoid @@@ -786,6 -826,14 +870,18 @@@ availableRoutes().down ? navigateDown() : navigateRight(); } } - function overviewToggle (){ ++ ++ /** ++ * Toggles the slide overview mode on and off. ++ */ ++ function toggleOverview() { + if( overviewIsActive() ) { + deactivateOverview(); + } + else { + activateOverview(); + } + } // Expose some methods publicly return { @@@ -795,6 -843,9 +891,7 @@@ 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 ) { diff --cc js/reveal.min.js index 08b8a97,7977da4..41f9347 --- a/js/reveal.min.js +++ b/js/reveal.min.js @@@ -1,52 -1,7 +1,60 @@@ /*! - reveal.js 1.3 - http://lab.hakim.se/reveal-js - MIT licensed - - Copyright (C) 2012 Hakim El Hattab, http://hakim.se - */var Reveal=(function(){var HORIZONTAL_SLIDES_SELECTOR='#reveal .slides>section',VERTICAL_SLIDES_SELECTOR='#reveal .slides>section.present>section',IS_TOUCH_DEVICE=!!('ontouchstart'in window),indexh=0,indexv=0,config={controls:false,progress:false,history:false,loop:false,mouseWheel:true,rollingLinks:true,transition:'default',theme:'default',swipeDist:40},state=[],dom={},supports3DTransforms=document.body.style['perspectiveProperty']!==undefined||document.body.style['WebkitPerspective']!==undefined||document.body.style['MozPerspective']!==undefined||document.body.style['msPerspective']!==undefined||document.body.style['OPerspective']!==undefined,supports2DTransforms=document.body.style['transformProperty']!==undefined||document.body.style['WebkitTransform']!==undefined||document.body.style['MozTransform']!==undefined||document.body.style['msTransform']!==undefined||document.body.style['OTransform']!==undefined,mouseWheelTimeout=0,writeURLTimeout=0;function initialize(options){if(!supports2DTransforms&&!supports3DTransforms){document.body.setAttribute('class','no-transforms');return;}dom.wrapper=document.querySelector('#reveal');dom.progress=document.querySelector('#reveal .progress');dom.progressbar=document.querySelector('#reveal .progress span');dom.controls=document.querySelector('#reveal .controls');dom.controlsLeft=document.querySelector('#reveal .controls .left');dom.controlsRight=document.querySelector('#reveal .controls .right');dom.controlsUp=document.querySelector('#reveal .controls .up');dom.controlsDown=document.querySelector('#reveal .controls .down');addEvents();extend(config,options);if(supports3DTransforms===false){config.transition='linear';}if(config.controls){dom.controls.style.display='block';}if(config.progress){dom.progress.style.display='block';}if(config.transition!=='default'){dom.wrapper.classList.add(config.transition);}if(config.theme!=='default'){dom.wrapper.classList.add(config.theme);}if(config.mouseWheel){document.addEventListener('DOMMouseScroll',onDocumentMouseScroll,false);document.addEventListener('mousewheel',onDocumentMouseScroll,false);}if(config.rollingLinks){linkify();}readURL();if(navigator.userAgent.match(/(iphone|ipod|android)/i)){document.documentElement.style.overflow='scroll';document.body.style.height='120%';window.addEventListener('load',removeAddressBar,false);window.addEventListener('orientationchange',removeAddressBar,false);}}function addEvents(){document.addEventListener('keydown',onDocumentKeyDown,false);document.addEventListener('touchstart',onDocumentTouchStart,false);document.addEventListener('touchmove',onDocumentTouchMove,false);document.addEventListener('touchend',onDocumentTouchEnd,false);window.addEventListener('hashchange',onWindowHashChange,false);dom.controlsLeft.addEventListener('click',preventAndForward(navigateLeft),false);dom.controlsRight.addEventListener('click',preventAndForward(navigateRight),false);dom.controlsUp.addEventListener('click',preventAndForward(navigateUp),false);dom.controlsDown.addEventListener('click',preventAndForward(navigateDown),false);}function removeEvents(){document.removeEventListener('keydown',onDocumentKeyDown,false);document.removeEventListener('touchstart',onDocumentTouchStart,false);document.removeEventListener('touchmove',onDocumentTouchMove,false);document.removeEventListener('touchend',onDocumentTouchEnd,false);window.removeEventListener('hashchange',onWindowHashChange,false);dom.controlsLeft.removeEventListener('click',preventAndForward(navigateLeft),false);dom.controlsRight.removeEventListener('click',preventAndForward(navigateRight),false);dom.controlsUp.removeEventListener('click',preventAndForward(navigateUp),false);dom.controlsDown.removeEventListener('click',preventAndForward(navigateDown),false);}function extend(a,b){for(var i in b){a[i]=b[i];}}function preventAndForward(delegate){return function(event){event.preventDefault();delegate.call();}}function removeAddressBar(){setTimeout(function(){window.scrollTo(0,1);},0);}function onDocumentKeyDown(event){if(event.target.contentEditable!='inherit'||event.shiftKey||event.altKey||event.ctrlKey||event.metaKey)return;var triggered=false;switch(event.keyCode){case 80:case 33:navigatePrev();triggered=true;break;case 78:case 34:navigateNext();triggered=true;break;case 72:case 37:navigateLeft();triggered=true;break;case 76:case 39:navigateRight();triggered=true;break;case 75:case 38:navigateUp();triggered=true;break;case 74:case 40:navigateDown();triggered=true;break;case 36:navigateTo(0);triggered=true;break;case 35:navigateTo(Number.MAX_VALUE);triggered=true;break;case 32:overviewIsActive()?deactivateOverview():navigateNext();triggered=true;break;case 13:if(overviewIsActive()){deactivateOverview();triggered=true;}break;}if(triggered){event.preventDefault();}else if(event.keyCode===27&&supports3DTransforms){if(overviewIsActive()){deactivateOverview();}else{activateOverview();}event.preventDefault();}}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();}}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();}}}function onDocumentTouchEnd(event){if(!gesture){if(event.target.tagName.toLowerCase()==='a'||event.target.tagName.toLowerCase()==='img'){return;}var wt=window.innerWidth*0.3;var ht=window.innerHeight*0.3;if(touchStart.xwindow.innerWidth-wt){navigateRight();}else if(touchStart.ywindow.innerHeight-ht){navigateDown();}}gesture=false;event.preventDefault();}function onDocumentMouseScroll(event){clearTimeout(mouseWheelTimeout);mouseWheelTimeout=setTimeout(function(){var delta=event.detail||-event.wheelDelta;if(delta>0){navigateNext();}else{navigatePrev();}},100);}function onWindowHashChange(event){readURL();}function linkify(){if(supports3DTransforms){var nodes=document.querySelectorAll('#reveal .slides section a:not(.image)');for(var i=0,len=nodes.length;i'+node.innerHTML+'';}};}}function activateOverview(){dom.wrapper.classList.add('overview');var horizontalSlides=Array.prototype.slice.call(document.querySelectorAll(HORIZONTAL_SLIDES_SELECTOR));for(var i=0,len1=horizontalSlides.length;i3?'none':'block';}slides[i].classList.remove('past');slides[i].classList.remove('present');slides[i].classList.remove('future');if(iindex){slides[i].classList.add('future');}if(slide.querySelector('section')){slides[i].classList.add('stack');}}slides[index].classList.add('present');var slideState=slides[index].getAttribute('data-state');if(slideState){state=state.concat(slideState.split(' '));}}else{index=0;}return index;}function slide(){var stateBefore=state.concat();state.length=0;indexh=updateSlides(HORIZONTAL_SLIDES_SELECTOR,indexh);indexv=updateSlides(VERTICAL_SLIDES_SELECTOR,indexv);stateLoop:for(var i=0,len=state.length;i0,right:indexh0,down:indexv0||indexv>0)url+=indexh;if(indexv>0)url+='/'+indexv;window.location.hash=url;}}function dispatchEvent(type,properties){var event=document.createEvent("HTMLEvents",1,2);event.initEvent(type,true,true);extend(event,properties);dom.wrapper.dispatchEvent(event);}function nextFragment(){if(document.querySelector(VERTICAL_SLIDES_SELECTOR+'.present')){var verticalFragments=document.querySelectorAll(VERTICAL_SLIDES_SELECTOR+'.present .fragment:not(.visible)');if(verticalFragments.length){verticalFragments[0].classList.add('visible');return true;}}else{var horizontalFragments=document.querySelectorAll(HORIZONTAL_SLIDES_SELECTOR+'.present .fragment:not(.visible)');if(horizontalFragments.length){horizontalFragments[0].classList.add('visible');return true;}}return false;}function previousFragment(){if(document.querySelector(VERTICAL_SLIDES_SELECTOR+'.present')){var verticalFragments=document.querySelectorAll(VERTICAL_SLIDES_SELECTOR+'.present .fragment.visible');if(verticalFragments.length){verticalFragments[verticalFragments.length-1].classList.remove('visible');return true;}}else{var horizontalFragments=document.querySelectorAll(HORIZONTAL_SLIDES_SELECTOR+'.present .fragment.visible');if(horizontalFragments.length){horizontalFragments[horizontalFragments.length-1].classList.remove('visible');return true;}}return false;}function navigateTo(h,v){indexh=h===undefined?indexh:h;indexv=v===undefined?indexv:v;slide();}function navigateLeft(){if(overviewIsActive()||previousFragment()===false){indexh--;indexv=0;slide();}}function navigateRight(){if(overviewIsActive()||nextFragment()===false){indexh++;indexv=0;slide();}}function navigateUp(){if(overviewIsActive()||previousFragment()===false){indexv--;slide();}}function navigateDown(){if(overviewIsActive()||nextFragment()===false){indexv++;slide();}}function navigatePrev(){if(previousFragment()===false){if(availableRoutes().up){navigateUp();}else{var previousSlide=document.querySelector('#reveal .slides>section.past:nth-child('+indexh+')');if(previousSlide){indexv=(previousSlide.querySelectorAll('section').length+1)||0;indexh--;slide();}}}}function navigateNext(){if(nextFragment()===false){availableRoutes().down?navigateDown():navigateRight();}}function overviewToggle(){if(overviewIsActive()){deactivateOverview();}else{activateOverview();}}return{initialize:initialize,navigateTo:navigateTo,navigateLeft:navigateLeft,navigateRight:navigateRight,navigateUp:navigateUp,navigateDown:navigateDown,overviewToggle:overviewToggle,addEvents:addEvents,removeEvents:removeEvents,addEventListener:function(type,listener,useCapture){(dom.wrapper||document.querySelector('#reveal')).addEventListener(type,listener,useCapture);},removeEventListener:function(type,listener,useCapture){(dom.wrapper||document.querySelector('#reveal')).removeEventListener(type,listener,useCapture);}};})(); + * reveal.js 1.3 + * http://lab.hakim.se/reveal-js + * MIT licensed + * + * Copyright (C) 2012 Hakim El Hattab, http://hakim.se + */ - var Reveal=(function(){var j="#reveal .slides>section",a="#reveal .slides>section.present>section",e=!!("ontouchstart" in window),k=0,c=0,G={controls:false,progress:false,history:false,loop:false,mouseWheel:true,rollingLinks:true,transition:"default",theme:"default"},N=[],d={},H=document.body.style.perspectiveProperty!==undefined||document.body.style.WebkitPerspective!==undefined||document.body.style.MozPerspective!==undefined||document.body.style.msPerspective!==undefined||document.body.style.OPerspective!==undefined,l=document.body.style.transformProperty!==undefined||document.body.style.WebkitTransform!==undefined||document.body.style.MozTransform!==undefined||document.body.style.msTransform!==undefined||document.body.style.OTransform!==undefined,v=0,y=0; - function h(P){if(!l&&!H){document.body.setAttribute("class","no-transforms");return;}d.wrapper=document.querySelector("#reveal");d.progress=document.querySelector("#reveal .progress"); ++var Reveal=(function(){var j="#reveal .slides>section",a="#reveal .slides>section.present>section",e=!!("ontouchstart" in window),k=0,c=0,H={controls:false,progress:false,history:false,loop:false,mouseWheel:true,rollingLinks:true,transition:"default",theme:"default"},U=[],d={},J=document.body.style.perspectiveProperty!==undefined||document.body.style.WebkitPerspective!==undefined||document.body.style.MozPerspective!==undefined||document.body.style.msPerspective!==undefined||document.body.style.OPerspective!==undefined,l=document.body.style.transformProperty!==undefined||document.body.style.WebkitTransform!==undefined||document.body.style.MozTransform!==undefined||document.body.style.msTransform!==undefined||document.body.style.OTransform!==undefined,v=0,y=0,P={startX:0,startY:0,startSpan:0,startCount:0,handled:false,threshold:40}; ++function h(W){if(!l&&!J){document.body.setAttribute("class","no-transforms");return;}d.wrapper=document.querySelector("#reveal");d.progress=document.querySelector("#reveal .progress"); +d.progressbar=document.querySelector("#reveal .progress span");d.controls=document.querySelector("#reveal .controls");d.controlsLeft=document.querySelector("#reveal .controls .left"); +d.controlsRight=document.querySelector("#reveal .controls .right");d.controlsUp=document.querySelector("#reveal .controls .up");d.controlsDown=document.querySelector("#reveal .controls .down"); - document.addEventListener("keydown",M,false);document.addEventListener("touchstart",w,false);window.addEventListener("hashchange",t,false);d.controlsLeft.addEventListener("click",n(x),false); - d.controlsRight.addEventListener("click",n(i),false);d.controlsUp.addEventListener("click",n(r),false);d.controlsDown.addEventListener("click",n(A),false); - q(G,P);if(H===false){G.transition="linear";}if(G.controls){d.controls.style.display="block";}if(G.progress){d.progress.style.display="block";}if(G.transition!=="default"){d.wrapper.classList.add(G.transition); - }if(G.theme!=="default"){d.wrapper.classList.add(G.theme);}if(G.mouseWheel){document.addEventListener("DOMMouseScroll",m,false);document.addEventListener("mousewheel",m,false); - }if(G.rollingLinks){D();}C();if(navigator.userAgent.match(/(iphone|ipod|android)/i)){document.documentElement.style.overflow="scroll";document.body.style.height="120%"; - window.addEventListener("load",K,false);window.addEventListener("orientationchange",K,false);}}function q(Q,P){for(var R in P){Q[R]=P[R];}}function n(P){return function(Q){Q.preventDefault(); - P.call();};}function K(){setTimeout(function(){window.scrollTo(0,1);},0);}function M(Q){if(Q.target.contentEditable!="inherit"||Q.shiftKey||Q.altKey||Q.ctrlKey||Q.metaKey){return; - }var P=false;switch(Q.keyCode){case 80:case 33:I();P=true;break;case 78:case 34:u();P=true;break;case 72:case 37:x();P=true;break;case 76:case 39:i();P=true; - break;case 75:case 38:r();P=true;break;case 74:case 40:A();P=true;break;case 36:E(0);P=true;break;case 35:E(Number.MAX_VALUE);P=true;break;case 32:J()?L():u(); - P=true;break;case 13:if(J()){L();P=true;}break;}if(P){Q.preventDefault();}else{if(Q.keyCode===27&&H){if(J()){L();}else{B();}Q.preventDefault();}}}function w(S){if(S.touches.length===1){if(S.target.tagName.toLowerCase()==="a"||S.target.tagName.toLowerCase()==="img"){return; - }S.preventDefault();var Q={x:S.touches[0].clientX,y:S.touches[0].clientY};var P=window.innerWidth*0.3;var R=window.innerHeight*0.3;if(Q.xwindow.innerWidth-P){i(); - }else{if(Q.ywindow.innerHeight-R){A();}}}}b();}}function m(P){clearTimeout(v);v=setTimeout(function(){var Q=P.detail||-P.wheelDelta; - if(Q>0){u();}else{I();}},100);}function t(P){C();}function D(){if(H){var Q=document.querySelectorAll("#reveal .slides section a:not(.image)");for(var R=0,P=Q.length; - R'+S.innerHTML+""; - }}}}function B(){d.wrapper.classList.add("overview");var P=Array.prototype.slice.call(document.querySelectorAll(j));for(var U=0,S=P.length;U3?"none":"block"; - }U[T].classList.remove("past");U[T].classList.remove("present");U[T].classList.remove("future");if(TS){U[T].classList.add("future"); - }}if(P.querySelector("section")){U[T].classList.add("stack");}}U[S].classList.add("present");var R=U[S].getAttribute("data-state");if(R){N=N.concat(R.split(" ")); - }}else{S=0;}return S;}function b(){var S=N.concat();N.length=0;k=O(j,k);c=O(a,c);stateLoop:for(var R=0,P=N.length;R0,right:k0,down:c0||c>0){P+=k; - }if(c>0){P+="/"+c;}window.location.hash=P;}}function o(Q,P){var R=document.createEvent("HTMLEvents",1,2);R.initEvent(Q,true,true);q(R,P);d.wrapper.dispatchEvent(R); - }function s(){if(document.querySelector(a+".present")){var Q=document.querySelectorAll(a+".present .fragment:not(.visible)");if(Q.length){Q[0].classList.add("visible"); - o("fragmentshown",{fragment:Q[0]});return true;}}else{var P=document.querySelectorAll(j+".present .fragment:not(.visible)");if(P.length){P[0].classList.add("visible"); - o("fragmentshown",{fragment:P[0]});return true;}}return false;}function F(){if(document.querySelector(a+".present")){var Q=document.querySelectorAll(a+".present .fragment.visible"); - if(Q.length){Q[Q.length-1].classList.remove("visible");o("fragmenthidden",{fragment:Q[0]});return true;}}else{var P=document.querySelectorAll(j+".present .fragment.visible"); - if(P.length){P[P.length-1].classList.remove("visible");o("fragmenthidden",{fragment:P[0]});return true;}}return false;}function E(Q,P){k=Q===undefined?k:Q; - c=P===undefined?c:P;b();}function x(){if(J()||F()===false){k--;c=0;b();}}function i(){if(J()||s()===false){k++;c=0;b();}}function r(){if(J()||F()===false){c--; - b();}}function A(){if(J()||s()===false){c++;b();}}function I(){if(F()===false){if(f().up){r();}else{var P=document.querySelector("#reveal .slides>section.past:nth-child("+k+")"); - if(P){c=(P.querySelectorAll("section").length+1)||0;k--;b();}}}}function u(){if(s()===false){f().down?A():i();}}return{initialize:h,navigateTo:E,navigateLeft:x,navigateRight:i,navigateUp:r,navigateDown:A,addEventListener:function(Q,R,P){(d.wrapper||document.querySelector("#reveal")).addEventListener(Q,R,P); - },removeEventListener:function(Q,R,P){(d.wrapper||document.querySelector("#reveal")).removeEventListener(Q,R,P);}};})(); ++A();q(H,W);if(J===false){H.transition="linear";}if(H.controls){d.controls.style.display="block";}if(H.progress){d.progress.style.display="block";}if(H.transition!=="default"){d.wrapper.classList.add(H.transition); ++}if(H.theme!=="default"){d.wrapper.classList.add(H.theme);}if(H.mouseWheel){document.addEventListener("DOMMouseScroll",m,false);document.addEventListener("mousewheel",m,false); ++}if(H.rollingLinks){E();}D();if(navigator.userAgent.match(/(iphone|ipod|android)/i)){document.documentElement.style.overflow="scroll";document.body.style.height="120%"; ++window.addEventListener("load",Q,false);window.addEventListener("orientationchange",Q,false);}}function A(){document.addEventListener("keydown",T,false); ++document.addEventListener("touchstart",w,false);document.addEventListener("touchmove",S,false);document.addEventListener("touchend",L,false);window.addEventListener("hashchange",t,false); ++d.controlsLeft.addEventListener("click",n(x),false);d.controlsRight.addEventListener("click",n(i),false);d.controlsUp.addEventListener("click",n(r),false); ++d.controlsDown.addEventListener("click",n(B),false);}function K(){document.removeEventListener("keydown",T,false);document.removeEventListener("touchstart",w,false); ++document.removeEventListener("touchmove",S,false);document.removeEventListener("touchend",L,false);window.removeEventListener("hashchange",t,false);d.controlsLeft.removeEventListener("click",n(x),false); ++d.controlsRight.removeEventListener("click",n(i),false);d.controlsUp.removeEventListener("click",n(r),false);d.controlsDown.removeEventListener("click",n(B),false); ++}function q(X,W){for(var Y in W){X[Y]=W[Y];}}function I(Y,W){var Z=Y.x-W.x,X=Y.y-W.y;return Math.sqrt(Z*Z+X*X);}function n(W){return function(X){X.preventDefault(); ++W.call();};}function Q(){setTimeout(function(){window.scrollTo(0,1);},0);}function T(X){if(X.target.contentEditable!="inherit"||X.shiftKey||X.altKey||X.ctrlKey||X.metaKey){return; ++}var W=false;switch(X.keyCode){case 80:case 33:N();W=true;break;case 78:case 34:u();W=true;break;case 72:case 37:x();W=true;break;case 76:case 39:i();W=true; ++break;case 75:case 38:r();W=true;break;case 74:case 40:B();W=true;break;case 36:F(0);W=true;break;case 35:F(Number.MAX_VALUE);W=true;break;case 32:O()?R():u(); ++W=true;break;case 13:if(O()){R();W=true;}break;}if(W){X.preventDefault();}else{if(X.keyCode===27&&J){if(O()){R();}else{C();}X.preventDefault();}}}function w(W){P.startX=W.touches[0].clientX; ++P.startY=W.touches[0].clientY;P.startCount=W.touches.length;if(W.touches.length===2){P.startSpan=I({x:W.touches[1].clientX,y:W.touches[1].clientY},{x:P.startX,y:P.startY}); ++}}function S(ab){if(!P.handled){var Z=ab.touches[0].clientX;var Y=ab.touches[0].clientY;if(ab.touches.length===2&&P.startCount===2){var aa=I({x:ab.touches[1].clientX,y:ab.touches[1].clientY},{x:P.startX,y:P.startY}); ++if(Math.abs(P.startSpan-aa)>P.threshold){P.handled=true;if(aaP.threshold&&Math.abs(X)>Math.abs(W)){P.handled=true;x();}else{if(X<-P.threshold&&Math.abs(X)>Math.abs(W)){P.handled=true;i();}else{if(W>P.threshold){P.handled=true; ++r();}else{if(W<-P.threshold){P.handled=true;B();}}}}}}ab.preventDefault();}}function L(W){P.handled=false;}function m(W){clearTimeout(v);v=setTimeout(function(){var X=W.detail||-W.wheelDelta; ++if(X>0){u();}else{N();}},100);}function t(W){D();}function E(){if(J){var X=document.querySelectorAll("#reveal .slides section a:not(.image)");for(var Y=0,W=X.length; ++Y'+Z.innerHTML+""; ++}}}}function C(){d.wrapper.classList.add("overview");var W=Array.prototype.slice.call(document.querySelectorAll(j));for(var ab=0,Z=W.length;ab3?"none":"block";}ab[aa].classList.remove("past"); ++ab[aa].classList.remove("present");ab[aa].classList.remove("future");if(aaZ){ab[aa].classList.add("future"); ++}}if(W.querySelector("section")){ab[aa].classList.add("stack");}}ab[Z].classList.add("present");var Y=ab[Z].getAttribute("data-state");if(Y){U=U.concat(Y.split(" ")); ++}}else{Z=0;}return Z;}function b(){var Z=U.concat();U.length=0;k=V(j,k);c=V(a,c);stateLoop:for(var Y=0,W=U.length;Y0,right:k0,down:c0||c>0){W+=k; ++}if(c>0){W+="/"+c;}window.location.hash=W;}}function o(X,W){var Y=document.createEvent("HTMLEvents",1,2);Y.initEvent(X,true,true);q(Y,W);d.wrapper.dispatchEvent(Y); ++}function s(){if(document.querySelector(a+".present")){var X=document.querySelectorAll(a+".present .fragment:not(.visible)");if(X.length){X[0].classList.add("visible"); ++o("fragmentshown",{fragment:X[0]});return true;}}else{var W=document.querySelectorAll(j+".present .fragment:not(.visible)");if(W.length){W[0].classList.add("visible"); ++o("fragmentshown",{fragment:W[0]});return true;}}return false;}function G(){if(document.querySelector(a+".present")){var X=document.querySelectorAll(a+".present .fragment.visible"); ++if(X.length){X[X.length-1].classList.remove("visible");o("fragmenthidden",{fragment:X[0]});return true;}}else{var W=document.querySelectorAll(j+".present .fragment.visible"); ++if(W.length){W[W.length-1].classList.remove("visible");o("fragmenthidden",{fragment:W[0]});return true;}}return false;}function F(X,W){k=X===undefined?k:X; ++c=W===undefined?c:W;b();}function x(){if(O()||G()===false){k--;c=0;b();}}function i(){if(O()||s()===false){k++;c=0;b();}}function r(){if(O()||G()===false){c--; ++b();}}function B(){if(O()||s()===false){c++;b();}}function N(){if(G()===false){if(f().up){r();}else{var W=document.querySelector("#reveal .slides>section.past:nth-child("+k+")"); ++if(W){c=(W.querySelectorAll("section").length+1)||0;k--;b();}}}}function u(){if(s()===false){f().down?B():i();}}function M(){if(O()){R();}else{C();}}return{initialize:h,navigateTo:F,navigateLeft:x,navigateRight:i,navigateUp:r,navigateDown:B,toggleOverview:M,addEventListener:function(X,Y,W){(d.wrapper||document.querySelector("#reveal")).addEventListener(X,Y,W); ++},removeEventListener:function(X,Y,W){(d.wrapper||document.querySelector("#reveal")).removeEventListener(X,Y,W);}};})();