From 19b67aab1314818b71ea39323c74308c6073f52d Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Fri, 4 May 2012 00:01:20 -0400 Subject: [PATCH] 'slidechanged' event, added Reveal.addEventListener/Reveal.removeEventListener api methods --- README.md | 18 +++++++++-- index.html | 10 ++++-- js/reveal.js | 47 ++++++++++++++++++++-------- js/reveal.min.js | 80 ++++++++++++++++++++++++------------------------ 4 files changed, 99 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 20965a9c..12ca7e40 100644 --- a/README.md +++ b/README.md @@ -68,16 +68,27 @@ The Reveal class provides a minimal JavaScript API for controlling its navigatio ### States -If you set ``data-state="someState"`` on a slide ``
``, "someState" will be applied as a class on the document element when that slide is opened. This allows you to apply broad style changes to the page based on the active slide. +If you set ``data-state="somestate"`` on a slide ``
``, "somestate" will be applied as a class on the document element when that slide is opened. This allows you to apply broad style changes to the page based on the active slide. Furthermore you can also listen to these changes in state via JavaScript: ``` -document.addEventListener( 'someState', function() { +Reveal.addEventListener( 'somestate', function() { // TODO: Sprinkle magic }, false ); ``` +### Slide change event + +An 'slidechanged' event is fired each time the slide is changed (regardless of state). The event object holds the index of the current slide. + +``` +Reveal.addEventListener( 'slidechanged', function( event ) { + // event.indexh & event.indexv +} ); +``` + + ## Examples * http://lab.hakim.se/reveal-js/ (original) @@ -104,6 +115,9 @@ document.addEventListener( 'someState', function() { #### 1.3 (master) - Revised keyboard shortcuts, including ESC for overview, N for next, P for previous. Thanks [mahemoff](https://github.com/mahemoff) - Added support for looped presentations via config +- Fixed IE9 fallback +- Added event binding methods (Reveal.addEventListener, Reveal.removeEventListener) +- Added 'slidechanged' event #### 1.2 diff --git a/index.html b/index.html index 7f291cf2..f314cdb5 100644 --- a/index.html +++ b/index.html @@ -148,7 +148,7 @@

Additionally custom events can be triggered on a per slide basis by binding to the data-state name.

-
document.addEventListener( 'customevent', function() {
+					
Reveal.addEventListener( 'customevent', function() {
 	alert( '"customevent" has fired' );
 } );
 					
@@ -261,10 +261,16 @@ linkify( 'a' ); query[ a.split( '=' ).shift() ] = a.split( '=' ).pop(); } ); - document.addEventListener( 'customevent', function() { + // Fires when a slide with data-state=customevent is activated + Reveal.addEventListener( 'customevent', function() { alert( '"customevent" has fired' ); } ); + // Fires each time a new slide is activated + Reveal.addEventListener( 'slidechanged', function( event ) { + // event.indexh & event.indexv + } ); + Reveal.initialize({ // Display controls in the bottom right corner controls: true, diff --git a/js/reveal.js b/js/reveal.js index 4761595f..5b985b59 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -78,13 +78,13 @@ var Reveal = (function(){ 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); + 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 ); // Copy options over to our config object extend( config, options ); @@ -504,10 +504,8 @@ var Reveal = (function(){ document.documentElement.classList.add( state[i] ); - // Dispatch custom event - var event = document.createEvent( "HTMLEvents" ); - event.initEvent( state[i], true, true ); - document.dispatchEvent( event ); + // Dispatch custom event matching the state's name + dispatchEvent( state[i] ); } // Clean up the remaints of the previous state @@ -529,6 +527,12 @@ var Reveal = (function(){ clearTimeout( writeURLTimeout ); writeURLTimeout = setTimeout( writeURL, 1500 ); + + // Dispatch an event notifying observers of the change in slide + dispatchEvent( 'slidechanged', { + 'indexh': indexh, + 'indexv': indexv + } ); } /** @@ -596,6 +600,17 @@ var Reveal = (function(){ } } + /** + * Dispatches an event of the specified type from the + * #reveal DOM element. + */ + function dispatchEvent( type, properties ) { + var event = document.createEvent( "HTMLEvents", 1, 2 ); + event.initEvent( type, true, true ); + extend( event, properties ); + dom.wrapper.dispatchEvent( event ); + } + /** * Navigate to the next slide fragment. * @@ -736,7 +751,15 @@ var Reveal = (function(){ navigateLeft: navigateLeft, navigateRight: navigateRight, navigateUp: navigateUp, - navigateDown: navigateDown + navigateDown: navigateDown, + + // Forward event binding to the reveal DOM element + 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 ); + } }; })(); diff --git a/js/reveal.min.js b/js/reveal.min.js index b0551241..d26ad76e 100644 --- a/js/reveal.min.js +++ b/js/reveal.min.js @@ -5,45 +5,45 @@ * * Copyright (C) 2012 Hakim El Hattab, http://hakim.se */ -var Reveal=(function(){var i="#reveal .slides>section",a="#reveal .slides>section.present>section",j=0,c=0,E={controls:false,progress:false,history:false,loop:false,mouseWheel:true,rollingLinks:true,transition:"default",theme:"default"},K=[],d={},F=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,k=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,t=0,w=0; -function g(M){if(!k&&!F){document.body.setAttribute("class","no-transforms");return;}d.wrapper=document.querySelector("#reveal");d.progress=document.querySelector("#reveal .progress"); +var Reveal=(function(){var i="#reveal .slides>section",a="#reveal .slides>section.present>section",j=0,c=0,F={controls:false,progress:false,history:false,loop:false,mouseWheel:true,rollingLinks:true,transition:"default",theme:"default"},L=[],d={},G=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,k=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,u=0,x=0; +function g(N){if(!k&&!G){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",J,false);document.addEventListener("touchstart",u,false);window.addEventListener("hashchange",r,false);d.controlsLeft.addEventListener("click",m(v),false); -d.controlsRight.addEventListener("click",m(h),false);d.controlsUp.addEventListener("click",m(p),false);d.controlsDown.addEventListener("click",m(y),false); -o(E,M);if(F===false){E.transition="linear";}if(E.controls){d.controls.style.display="block";}if(E.progress){d.progress.style.display="block";}if(E.transition!=="default"){d.wrapper.classList.add(E.transition); -}if(E.theme!=="default"){d.wrapper.classList.add(E.theme);}if(E.mouseWheel){document.addEventListener("DOMMouseScroll",l,false);document.addEventListener("mousewheel",l,false); -}if(E.rollingLinks){B();}A();}function o(N,M){for(var O in M){N[O]=M[O];}}function m(M){return function(N){N.preventDefault();M.call();};}function J(N){if(N.target.contentEditable!="inherit"||N.shiftKey||N.altKey||N.ctrlKey||N.metaKey){return; -}var M=false;switch(N.keyCode){case 80:case 33:G();M=true;break;case 78:case 32:case 34:s();M=true;break;case 72:case 37:v();M=true;break;case 76:case 39:h(); -M=true;break;case 75:case 38:p();M=true;break;case 74:case 40:y();M=true;break;}if(M){N.preventDefault();}else{if(N.keyCode===27&&F){if(H()){I();}else{z(); -}N.preventDefault();}}}function u(P){if(P.touches.length===1){if(P.target.tagName.toLowerCase()==="a"||P.target.tagName.toLowerCase()==="img"){return;}P.preventDefault(); -var N={x:P.touches[0].clientX,y:P.touches[0].clientY};var M=window.innerWidth*0.3;var O=window.innerHeight*0.3;if(N.xwindow.innerWidth-M){h(); -}else{if(N.ywindow.innerHeight-O){y();}}}}b();}}function l(M){clearTimeout(t);t=setTimeout(function(){var N=M.detail||-M.wheelDelta; -if(N>0){s();}else{G();}},100);}function r(M){A();}function B(){if(F){var N=document.querySelectorAll("#reveal .slides section a:not(.image)");for(var O=0,M=N.length; -O'+P.innerHTML+""; -}}}}function z(){d.wrapper.classList.add("overview");var M=Array.prototype.slice.call(document.querySelectorAll(i));for(var R=0,P=M.length;R3?"none":"block"; -}R[Q].classList.remove("past");R[Q].classList.remove("present");R[Q].classList.remove("future");if(QP){R[Q].classList.add("future"); -}}if(M.querySelector("section")){R[Q].classList.add("stack");}}R[P].classList.add("present");var O=R[P].getAttribute("data-state");if(O){K=K.concat(O.split(" ")); -}}else{P=0;}return P;}function b(){var Q=K.concat();K.length=0;j=L(i,j);c=L(a,c);stateLoop:for(var O=0,M=K.length;O0,right:j0,down:c0||c>0){M+=j; -}if(c>0){M+="/"+c;}window.location.hash=M;}}function q(){if(document.querySelector(a+".present")){var N=document.querySelectorAll(a+".present .fragment:not(.visible)"); -if(N.length){N[0].classList.add("visible");return true;}}else{var M=document.querySelectorAll(i+".present .fragment:not(.visible)");if(M.length){M[0].classList.add("visible"); -return true;}}return false;}function D(){if(document.querySelector(a+".present")){var N=document.querySelectorAll(a+".present .fragment.visible");if(N.length){N[N.length-1].classList.remove("visible"); -return true;}}else{var M=document.querySelectorAll(i+".present .fragment.visible");if(M.length){M[M.length-1].classList.remove("visible");return true;}}return false; -}function C(N,M){j=N===undefined?j:N;c=M===undefined?c:M;b();}function v(){if(H()||D()===false){j--;c=0;b();}}function h(){if(H()||q()===false){j++;c=0; -b();}}function p(){if(H()||D()===false){c--;b();}}function y(){if(H()||q()===false){c++;b();}}function G(){if(D()===false){if(e().up){p();}else{var M=document.querySelector("#reveal .slides>section.past:nth-child("+j+")"); -if(M){c=(M.querySelectorAll("section").length+1)||0;j--;b();}}}}function s(){if(q()===false){e().down?y():h();}}return{initialize:g,navigateTo:C,navigateLeft:v,navigateRight:h,navigateUp:p,navigateDown:y}; -})(); \ No newline at end of file +document.addEventListener("keydown",K,false);document.addEventListener("touchstart",v,false);window.addEventListener("hashchange",s,false);d.controlsLeft.addEventListener("click",m(w),false); +d.controlsRight.addEventListener("click",m(h),false);d.controlsUp.addEventListener("click",m(q),false);d.controlsDown.addEventListener("click",m(z),false); +p(F,N);if(G===false){F.transition="linear";}if(F.controls){d.controls.style.display="block";}if(F.progress){d.progress.style.display="block";}if(F.transition!=="default"){d.wrapper.classList.add(F.transition); +}if(F.theme!=="default"){d.wrapper.classList.add(F.theme);}if(F.mouseWheel){document.addEventListener("DOMMouseScroll",l,false);document.addEventListener("mousewheel",l,false); +}if(F.rollingLinks){C();}B();}function p(O,N){for(var P in N){O[P]=N[P];}}function m(N){return function(O){O.preventDefault();N.call();};}function K(O){if(O.target.contentEditable!="inherit"||O.shiftKey||O.altKey||O.ctrlKey||O.metaKey){return; +}var N=false;switch(O.keyCode){case 80:case 33:H();N=true;break;case 78:case 32:case 34:t();N=true;break;case 72:case 37:w();N=true;break;case 76:case 39:h(); +N=true;break;case 75:case 38:q();N=true;break;case 74:case 40:z();N=true;break;}if(N){O.preventDefault();}else{if(O.keyCode===27&&G){if(I()){J();}else{A(); +}O.preventDefault();}}}function v(Q){if(Q.touches.length===1){if(Q.target.tagName.toLowerCase()==="a"||Q.target.tagName.toLowerCase()==="img"){return;}Q.preventDefault(); +var O={x:Q.touches[0].clientX,y:Q.touches[0].clientY};var N=window.innerWidth*0.3;var P=window.innerHeight*0.3;if(O.xwindow.innerWidth-N){h(); +}else{if(O.ywindow.innerHeight-P){z();}}}}b();}}function l(N){clearTimeout(u);u=setTimeout(function(){var O=N.detail||-N.wheelDelta; +if(O>0){t();}else{H();}},100);}function s(N){B();}function C(){if(G){var O=document.querySelectorAll("#reveal .slides section a:not(.image)");for(var P=0,N=O.length; +P'+Q.innerHTML+""; +}}}}function A(){d.wrapper.classList.add("overview");var N=Array.prototype.slice.call(document.querySelectorAll(i));for(var S=0,Q=N.length;S3?"none":"block"; +}S[R].classList.remove("past");S[R].classList.remove("present");S[R].classList.remove("future");if(RQ){S[R].classList.add("future"); +}}if(N.querySelector("section")){S[R].classList.add("stack");}}S[Q].classList.add("present");var P=S[Q].getAttribute("data-state");if(P){L=L.concat(P.split(" ")); +}}else{Q=0;}return Q;}function b(){var Q=L.concat();L.length=0;j=M(i,j);c=M(a,c);stateLoop:for(var P=0,N=L.length;P0,right:j0,down:c0||c>0){N+=j; +}if(c>0){N+="/"+c;}window.location.hash=N;}}function n(O,N){var P=document.createEvent("HTMLEvents",1,2);P.initEvent(O,true,true);p(P,N);d.wrapper.dispatchEvent(P); +}function r(){if(document.querySelector(a+".present")){var O=document.querySelectorAll(a+".present .fragment:not(.visible)");if(O.length){O[0].classList.add("visible"); +return true;}}else{var N=document.querySelectorAll(i+".present .fragment:not(.visible)");if(N.length){N[0].classList.add("visible");return true;}}return false; +}function E(){if(document.querySelector(a+".present")){var O=document.querySelectorAll(a+".present .fragment.visible");if(O.length){O[O.length-1].classList.remove("visible"); +return true;}}else{var N=document.querySelectorAll(i+".present .fragment.visible");if(N.length){N[N.length-1].classList.remove("visible");return true;}}return false; +}function D(O,N){j=O===undefined?j:O;c=N===undefined?c:N;b();}function w(){if(I()||E()===false){j--;c=0;b();}}function h(){if(I()||r()===false){j++;c=0; +b();}}function q(){if(I()||E()===false){c--;b();}}function z(){if(I()||r()===false){c++;b();}}function H(){if(E()===false){if(e().up){q();}else{var N=document.querySelector("#reveal .slides>section.past:nth-child("+j+")"); +if(N){c=(N.querySelectorAll("section").length+1)||0;j--;b();}}}}function t(){if(r()===false){e().down?z():h();}}return{initialize:g,navigateTo:D,navigateLeft:w,navigateRight:h,navigateUp:q,navigateDown:z,addEventListener:function(O,P,N){(d.wrapper||document.querySelector("#reveal")).addEventListener(O,P,N); +},removeEventListener:function(O,P,N){(d.wrapper||document.querySelector("#reveal")).removeEventListener(O,P,N);}};})(); \ No newline at end of file