فهرست منبع

merge dev into flexbox

Hakim El Hattab 11 سال پیش
والد
کامیت
5bab3c4fa0

+ 3 - 1
.gitignore

@@ -3,4 +3,6 @@
 log/*.log
 tmp/**
 node_modules/
-.sass-cache
+.sass-cache
+css/reveal.min.css
+js/reveal.min.js

+ 3 - 5
README.md

@@ -154,13 +154,13 @@ Reveal.initialize({
 	previewLinks: false,
 
 	// Transition style
-	transition: 'default', // default/cube/page/concave/zoom/linear/fade/none
+	transition: 'default', // none/fade/slide/convex/concave/zoom
 
 	// Transition speed
 	transitionSpeed: 'default', // default/fast/slow
 
 	// Transition style for full page slide backgrounds
-	backgroundTransition: 'default', // default/none/slide/concave/convex/zoom
+	backgroundTransition: 'default', // none/fade/slide/convex/concave/zoom
 
 	// Number of slides away from the current that are visible
 	viewDistance: 3,
@@ -175,8 +175,6 @@ Reveal.initialize({
 });
 ```
 
-Note that the new default vertical centering option will break compatibility with slides that were using transitions with backgrounds (`cube` and `page`). To restore the previous behavior, set `center` to `false`.
-
 
 The configuration can be updated after initialization using the ```configure``` method:
 
@@ -397,7 +395,7 @@ Reveal.initialize({
 	parallaxBackgroundSize: '', // CSS syntax, e.g. "2100px 900px" - currently only pixels are supported (don't use % or auto)
 
 	// This slide transition gives best results:
-	transition: linear
+	transition: 'slide'
 
 });
 ```

+ 71 - 52
css/reveal.css

@@ -710,18 +710,79 @@ body {
 
 
 /*********************************************
- * DEFAULT TRANSITION
+ * SLIDE TRANSITION
+ * Aliased 'linear' for backwards compatibility
+ *********************************************/
+
+.reveal.slide section,
+.reveal.linear section {
+	-webkit-backface-visibility: hidden;
+	   -moz-backface-visibility: hidden;
+	    -ms-backface-visibility: hidden;
+	        backface-visibility: hidden;
+}
+
+.reveal .slides>section[data-transition=slide].past,
+.reveal.slide .slides>section:not([data-transition]).past,
+.reveal .slides>section[data-transition=linear].past,
+.reveal.linear .slides>section:not([data-transition]).past {
+	-webkit-transform: translate(-150%, 0);
+	   -moz-transform: translate(-150%, 0);
+	    -ms-transform: translate(-150%, 0);
+	     -o-transform: translate(-150%, 0);
+	        transform: translate(-150%, 0);
+}
+.reveal .slides>section[data-transition=slide].future,
+.reveal.slide .slides>section:not([data-transition]).future,
+.reveal .slides>section[data-transition=linear].future,
+.reveal.linear .slides>section:not([data-transition]).future {
+	-webkit-transform: translate(150%, 0);
+	   -moz-transform: translate(150%, 0);
+	    -ms-transform: translate(150%, 0);
+	     -o-transform: translate(150%, 0);
+	        transform: translate(150%, 0);
+}
+
+.reveal .slides>section>section[data-transition=slide].past,
+.reveal.slide .slides>section>section:not([data-transition]).past,
+.reveal .slides>section>section[data-transition=linear].past,
+.reveal.linear .slides>section>section:not([data-transition]).past {
+	-webkit-transform: translate(0, -150%);
+	   -moz-transform: translate(0, -150%);
+	    -ms-transform: translate(0, -150%);
+	     -o-transform: translate(0, -150%);
+	        transform: translate(0, -150%);
+}
+.reveal .slides>section>section[data-transition=slide].future,
+.reveal.slide .slides>section>section:not([data-transition]).future,
+.reveal .slides>section>section[data-transition=linear].future,
+.reveal.linear .slides>section>section:not([data-transition]).future {
+	-webkit-transform: translate(0, 150%);
+	   -moz-transform: translate(0, 150%);
+	    -ms-transform: translate(0, 150%);
+	     -o-transform: translate(0, 150%);
+	        transform: translate(0, 150%);
+}
+
+
+/*********************************************
+ * CONVEX TRANSITION
+ * Aliased 'default' for backwards compatibility
  *********************************************/
 
 .reveal .slides>section[data-transition=default].past,
-.reveal.default .slides>section:not([data-transition]).past {
+.reveal.default .slides>section:not([data-transition]).past,
+.reveal .slides>section[data-transition=convex].past,
+.reveal.convex .slides>section:not([data-transition]).past {
 	-webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
 	   -moz-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
 	    -ms-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
 	        transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
 }
 .reveal .slides>section[data-transition=default].future,
-.reveal.default .slides>section:not([data-transition]).future {
+.reveal.default .slides>section:not([data-transition]).future,
+.reveal .slides>section[data-transition=convex].future,
+.reveal.convex .slides>section:not([data-transition]).future {
 	-webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
 	   -moz-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
 	    -ms-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
@@ -729,14 +790,18 @@ body {
 }
 
 .reveal .slides>section>section[data-transition=default].past,
-.reveal.default .slides>section>section:not([data-transition]).past {
+.reveal.default .slides>section>section:not([data-transition]).past,
+.reveal .slides>section>section[data-transition=convex].past,
+.reveal.convex .slides>section>section:not([data-transition]).past {
 	-webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0);
 	   -moz-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0);
 	    -ms-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0);
 	        transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0);
 }
 .reveal .slides>section>section[data-transition=default].future,
-.reveal.default .slides>section>section:not([data-transition]).future {
+.reveal.default .slides>section>section:not([data-transition]).future,
+.reveal .slides>section>section[data-transition=convex].future,
+.reveal.convex .slides>section>section:not([data-transition]).future {
 	-webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0);
 	   -moz-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0);
 	    -ms-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0);
@@ -829,52 +894,6 @@ body {
 }
 
 
-/*********************************************
- * LINEAR TRANSITION
- *********************************************/
-
-.reveal.linear section {
-	-webkit-backface-visibility: hidden;
-	   -moz-backface-visibility: hidden;
-	    -ms-backface-visibility: hidden;
-	        backface-visibility: hidden;
-}
-
-.reveal .slides>section[data-transition=linear].past,
-.reveal.linear .slides>section:not([data-transition]).past {
-	-webkit-transform: translate(-150%, 0);
-	   -moz-transform: translate(-150%, 0);
-	    -ms-transform: translate(-150%, 0);
-	     -o-transform: translate(-150%, 0);
-	        transform: translate(-150%, 0);
-}
-.reveal .slides>section[data-transition=linear].future,
-.reveal.linear .slides>section:not([data-transition]).future {
-	-webkit-transform: translate(150%, 0);
-	   -moz-transform: translate(150%, 0);
-	    -ms-transform: translate(150%, 0);
-	     -o-transform: translate(150%, 0);
-	        transform: translate(150%, 0);
-}
-
-.reveal .slides>section>section[data-transition=linear].past,
-.reveal.linear .slides>section>section:not([data-transition]).past {
-	-webkit-transform: translate(0, -150%);
-	   -moz-transform: translate(0, -150%);
-	    -ms-transform: translate(0, -150%);
-	     -o-transform: translate(0, -150%);
-	        transform: translate(0, -150%);
-}
-.reveal .slides>section>section[data-transition=linear].future,
-.reveal.linear .slides>section>section:not([data-transition]).future {
-	-webkit-transform: translate(0, 150%);
-	   -moz-transform: translate(0, 150%);
-	    -ms-transform: translate(0, 150%);
-	     -o-transform: translate(0, 150%);
-	        transform: translate(0, 150%);
-}
-
-
 /*********************************************
  * CUBE TRANSITION
  *********************************************/
@@ -1386,7 +1405,7 @@ body {
 	        transition: none;
 }
 
-/* 2D slide */
+/* Slide */
 .reveal[data-background-transition=slide]>.backgrounds .slide-background,
 .reveal>.backgrounds .slide-background[data-background-transition=slide] {
 	opacity: 1;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 6
css/reveal.min.css


+ 10 - 12
index.html

@@ -14,7 +14,7 @@
 
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 
-		<link rel="stylesheet" href="css/reveal.min.css">
+		<link rel="stylesheet" href="css/reveal.css">
 		<link rel="stylesheet" href="css/theme/default.css" id="theme">
 
 		<!-- For syntax highlighting -->
@@ -188,14 +188,12 @@
 					<h2>Transition Styles</h2>
 					<p>
 						You can select from different transitions, like: <br>
-						<a href="?transition=cube#/transitions">Cube</a> -
-						<a href="?transition=page#/transitions">Page</a> -
-						<a href="?transition=concave#/transitions">Concave</a> -
-						<a href="?transition=zoom#/transitions">Zoom</a> -
-						<a href="?transition=linear#/transitions">Linear</a> -
-						<a href="?transition=fade#/transitions">Fade</a> -
+						<a href="?#/transitions">Default</a> -
 						<a href="?transition=none#/transitions">None</a> -
-						<a href="?#/transitions">Default</a>
+						<a href="?transition=fade#/transitions">Fade</a> -
+						<a href="?transition=slide#/transitions">Slide</a> -
+						<a href="?transition=concave#/transitions">Concave</a> -
+						<a href="?transition=zoom#/transitions">Zoom</a>
 					</p>
 				</section>
 
@@ -260,14 +258,14 @@ Reveal.addEventListener( 'customevent', function() {
 					</section>
 				</section>
 
-				<section data-transition="linear" data-background="#4d7e65" data-background-transition="slide">
+				<section data-transition="slide" data-background="#4d7e65" data-background-transition="slide">
 					<h2>Background Transitions</h2>
 					<p>
 						Pass reveal.js the <code>backgroundTransition: 'slide'</code> config argument to make backgrounds slide rather than fade.
 					</p>
 				</section>
 
-				<section data-transition="linear" data-background="#8c4738" data-background-transition="slide">
+				<section data-transition="slide" data-background="#8c4738" data-background-transition="slide">
 					<h2>Background Transition Override</h2>
 					<p>
 						You can override background transitions per slide by using <code>data-background-transition="slide"</code>.
@@ -388,7 +386,7 @@ function linkify( selector ) {
 		</div>
 
 		<script src="lib/js/head.min.js"></script>
-		<script src="js/reveal.min.js"></script>
+		<script src="js/reveal.js"></script>
 
 		<script>
 
@@ -401,7 +399,7 @@ function linkify( selector ) {
 				center: true,
 
 				theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
-				transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none
+				transition: Reveal.getQueryHash().transition || 'default', // none/fade/slide/convex/concave/zoom
 
 				// Parallax scrolling
 				// parallaxBackgroundImage: 'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg',

+ 82 - 20
js/reveal.js

@@ -44,6 +44,9 @@ var Reveal = (function(){
 			// Enable keyboard shortcuts for navigation
 			keyboard: true,
 
+			// Optional function that blocks keyboard events when retuning false
+			keyboardCondition: null,
+
 			// Enable the slide overview mode
 			overview: true,
 
@@ -86,6 +89,12 @@ var Reveal = (function(){
 			// Opens links in an iframe preview overlay
 			previewLinks: false,
 
+			// Exposes the reveal.js API through window.postMessage
+			postMessage: true,
+
+			// Dispatches all reveal.js events to the parent window through postMessage
+			postMessageEvents: false,
+
 			// Focuses body when page changes visiblity to ensure keyboard shortcuts work
 			focusBodyOnPageVisiblityChange: true,
 
@@ -93,13 +102,13 @@ var Reveal = (function(){
 			theme: null,
 
 			// Transition style
-			transition: 'default', // default/cube/page/concave/zoom/linear/fade/none
+			transition: 'default', // none/fade/slide/convex/concave/zoom
 
 			// Transition speed
 			transitionSpeed: 'default', // default/fast/slow
 
 			// Transition style for full page slide backgrounds
-			backgroundTransition: 'default', // default/linear/none
+			backgroundTransition: 'default', // none/fade/slide/convex/concave/zoom
 
 			// Parallax background image
 			parallaxBackgroundImage: '', // CSS syntax, e.g. "a.jpg"
@@ -236,7 +245,6 @@ var Reveal = (function(){
 
 	}
 
-
     /**
      * Loads the dependencies of reveal.js. Dependencies are
      * defined via the configuration option 'dependencies'
@@ -310,6 +318,9 @@ var Reveal = (function(){
 		// Make sure we've got all the DOM elements we need
 		setupDOM();
 
+		// Listen to messages posted to this window
+		setupPostMessage();
+
 		// Resets all vertical slides so that only the first is visible
 		resetVerticalSlides();
 
@@ -548,6 +559,31 @@ var Reveal = (function(){
 
 	}
 
+	/**
+	 * Registers a listener to postMessage events, this makes it
+	 * possible to call all reveal.js API methods from another
+	 * window. For example:
+	 *
+	 * revealWindow.postMessage( JSON.stringify({
+	 *   method: 'slide',
+	 *   args: [ 2 ]
+	 * }), '*' );
+	 */
+	function setupPostMessage() {
+
+		if( config.postMessage ) {
+			window.addEventListener( 'message', function ( event ) {
+				var data = JSON.parse( event.data );
+				var method = Reveal[data.method];
+
+				if( typeof method === 'function' ) {
+					method.apply( Reveal, data.args );
+				}
+			}, false );
+		}
+
+	}
+
 	/**
 	 * Applies the configuration settings from the config
 	 * object. May be called multiple times.
@@ -930,13 +966,21 @@ var Reveal = (function(){
 	 * Dispatches an event of the specified type from the
 	 * reveal DOM element.
 	 */
-	function dispatchEvent( type, properties ) {
+	function dispatchEvent( type, args ) {
+
+		console.log('event', type);
 
-		var event = document.createEvent( "HTMLEvents", 1, 2 );
+		var event = document.createEvent( 'HTMLEvents', 1, 2 );
 		event.initEvent( type, true, true );
-		extend( event, properties );
+		extend( event, args );
 		dom.wrapper.dispatchEvent( event );
 
+		// If we're in an iframe, post each reveal.js event to the
+		// parent window. Used by the notes plugin
+		if( config.postMessageEvents && window.parent !== window.self ) {
+			window.parent.postMessage( JSON.stringify({ namespace: 'reveal', eventName: type, state: getState() }), '*' );
+		}
+
 	}
 
 	/**
@@ -1748,6 +1792,8 @@ var Reveal = (function(){
 		var slides = toArray( document.querySelectorAll( selector ) ),
 			slidesLength = slides.length;
 
+		var printMode = isPrintingPDF();
+
 		if( slidesLength ) {
 
 			// Should the index loop?
@@ -1774,6 +1820,17 @@ var Reveal = (function(){
 				// http://www.w3.org/html/wg/drafts/html/master/editing.html#the-hidden-attribute
 				element.setAttribute( 'hidden', '' );
 
+				// If this element contains vertical slides
+				if( element.querySelector( 'section' ) ) {
+					element.classList.add( 'stack' );
+				}
+
+				// If we're printing static slides, all slides are "present"
+				if( printMode ) {
+					element.classList.add( 'present' );
+					continue;
+				}
+
 				if( i < index ) {
 					// Any element previous to index is given the 'past' class
 					element.classList.add( reverse ? 'future' : 'past' );
@@ -1804,11 +1861,6 @@ var Reveal = (function(){
 						}
 					}
 				}
-
-				// If this element contains vertical slides
-				if( element.querySelector( 'section' ) ) {
-					element.classList.add( 'stack' );
-				}
 			}
 
 			// Mark the current slide as present
@@ -2004,7 +2056,7 @@ var Reveal = (function(){
 			}
 
 			if( includeAll || h === indexh ) {
-				toArray( backgroundh.querySelectorAll( 'section' ) ).forEach( function( backgroundv, v ) {
+				toArray( backgroundh.querySelectorAll( '.slide-background' ) ).forEach( function( backgroundv, v ) {
 
 					if( v < indexv ) {
 						backgroundv.className = 'slide-background past';
@@ -2701,21 +2753,25 @@ var Reveal = (function(){
 
 	function pauseAutoSlide() {
 
-		autoSlidePaused = true;
-		dispatchEvent( 'autoslidepaused' );
-		clearTimeout( autoSlideTimeout );
+		if( autoSlide && !autoSlidePaused ) {
+			autoSlidePaused = true;
+			dispatchEvent( 'autoslidepaused' );
+			clearTimeout( autoSlideTimeout );
 
-		if( autoSlidePlayer ) {
-			autoSlidePlayer.setPlaying( false );
+			if( autoSlidePlayer ) {
+				autoSlidePlayer.setPlaying( false );
+			}
 		}
 
 	}
 
 	function resumeAutoSlide() {
 
-		autoSlidePaused = false;
-		dispatchEvent( 'autoslideresumed' );
-		cueAutoSlide();
+		if( autoSlide && autoSlidePaused ) {
+			autoSlidePaused = false;
+			dispatchEvent( 'autoslideresumed' );
+			cueAutoSlide();
+		}
 
 	}
 
@@ -2832,6 +2888,12 @@ var Reveal = (function(){
 	 */
 	function onDocumentKeyDown( event ) {
 
+		// If there's a condition specified and it returns false,
+		// ignore this event
+		if( typeof config.keyboardCondition === 'function' && config.keyboardCondition() === false ) {
+			return true;
+		}
+
 		// Remember if auto-sliding was paused so we can toggle it
 		var autoSlideWasPaused = autoSlidePaused;
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 7
js/reveal.min.js


+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "reveal.js",
-  "version": "2.7.0-dev",
+  "version": "3.0.0-dev",
   "description": "The HTML Presentation Framework",
   "homepage": "http://lab.hakim.se/reveal-js",
   "subdomain": "revealjs",

+ 3 - 2
plugin/markdown/markdown.js

@@ -50,7 +50,7 @@
 			text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
 		}
 		else if( leadingWs > 1 ) {
-			text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
+			text = text.replace( new RegExp('\\n? {' + leadingWs + '}'), '\n' );
 		}
 
 		return text;
@@ -219,7 +219,8 @@
 
 				xhr.onreadystatechange = function() {
 					if( xhr.readyState === 4 ) {
-						if ( xhr.status >= 200 && xhr.status < 300 ) {
+						// file protocol yields status code 0 (useful for local debug, mobile applications etc.)
+						if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {
 
 							section.outerHTML = slidify( xhr.responseText, {
 								separator: section.getAttribute( 'data-separator' ),

+ 247 - 184
plugin/notes/notes.html

@@ -10,127 +10,129 @@
 				font-family: Helvetica;
 			}
 
-			#notes {
-				font-size: 24px;
-				width: 640px;
-				margin-top: 5px;
-				clear: left;
+			#current-slide,
+			#next-slide,
+			#speaker-controls {
+				padding: 6px;
+				box-sizing: border-box;
+				-moz-box-sizing: border-box;
 			}
 
-			#wrap-current-slide {
-				width: 640px;
-				height: 512px;
-				float: left;
-				overflow: hidden;
+			#current-slide iframe,
+			#next-slide iframe {
+				width: 100%;
+				height: 100%;
+				border: 1px solid #ddd;
 			}
 
-			#current-slide {
-				width: 1280px;
-				height: 1024px;
-				border: none;
-
-				-webkit-transform-origin: 0 0;
-				   -moz-transform-origin: 0 0;
-					-ms-transform-origin: 0 0;
-					 -o-transform-origin: 0 0;
-						transform-origin: 0 0;
-
-				-webkit-transform: scale(0.5);
-				   -moz-transform: scale(0.5);
-					-ms-transform: scale(0.5);
-					 -o-transform: scale(0.5);
-						transform: scale(0.5);
+			#current-slide .label,
+			#next-slide .label {
+				position: absolute;
+				top: 10px;
+				left: 10px;
+				font-weight: bold;
+				font-size: 14px;
+				z-index: 2;
+				color: rgba( 255, 255, 255, 0.9 );
 			}
 
-			#wrap-next-slide {
-				width: 448px;
-				height: 358px;
-				float: left;
-				margin: 0 0 0 10px;
-				overflow: hidden;
+			#current-slide {
+				position: absolute;
+				width: 65%;
+				height: 100%;
+				top: 0;
+				left: 0;
+				padding-right: 0;
 			}
 
 			#next-slide {
-				width: 1280px;
-				height: 1024px;
-				border: none;
-
-				-webkit-transform-origin: 0 0;
-				   -moz-transform-origin: 0 0;
-					-ms-transform-origin: 0 0;
-					 -o-transform-origin: 0 0;
-						transform-origin: 0 0;
-
-				-webkit-transform: scale(0.35);
-				   -moz-transform: scale(0.35);
-					-ms-transform: scale(0.35);
-					 -o-transform: scale(0.35);
-						transform: scale(0.35);
-			}
-
-			.slides {
-				position: relative;
-				margin-bottom: 10px;
-				border: 1px solid black;
-				border-radius: 2px;
-				background: rgb(28, 30, 32);
+				position: absolute;
+				width: 35%;
+				height: 40%;
+				right: 0;
+				top: 0;
 			}
 
-			.slides span {
+			#speaker-controls {
 				position: absolute;
-				top: 3px;
-				left: 3px;
-				font-weight: bold;
-				font-size: 14px;
-				color: rgba( 255, 255, 255, 0.9 );
-			}
+				top: 40%;
+				right: 0;
+				width: 35%;
+				height: 60%;
 
-			.error {
-				font-weight: bold;
-				color: red;
-				font-size: 1.5em;
-				text-align: center;
-				margin-top: 10%;
+				font-size: 18px;
 			}
 
-			.error code {
-				font-family: monospace;
-			}
+				.speaker-controls-time.hidden,
+				.speaker-controls-notes.hidden {
+					display: none;
+				}
 
-			.time {
-				width: 448px;
-				margin: 30px 0 0 10px;
-				float: left;
-				text-align: center;
-				opacity: 0;
-
-				-webkit-transition: opacity 0.4s;
-				   -moz-transition: opacity 0.4s;
-				     -o-transition: opacity 0.4s;
-				        transition: opacity 0.4s;
+				.speaker-controls-time .label,
+				.speaker-controls-notes .label {
+					text-transform: uppercase;
+					font-weight: normal;
+					font-size: 0.66em;
+					color: #666;
+					margin: 0;
+				}
+
+				.speaker-controls-time {
+					border-bottom: 1px solid rgba( 200, 200, 200, 0.5 );
+					margin-bottom: 10px;
+					padding: 10px 16px;
+					padding-bottom: 20px;
+				}
+
+				.speaker-controls-time .timer,
+				.speaker-controls-time .clock {
+					width: 50%;
+					font-size: 1.9em;
+				}
+
+				.speaker-controls-time .timer {
+					float: left;
+				}
+
+				.speaker-controls-time .clock {
+					float: right;
+					text-align: right;
+				}
+
+				.speaker-controls-time span.mute {
+					color: #bbb;
+				}
+
+				.speaker-controls-notes {
+					padding: 10px 16px;
+				}
+
+				.speaker-controls-notes .value {
+					margin-top: 5px;
+					line-height: 1.4;
+					font-size: 1.2em;
+				}
+
+			.clear {
+				clear: both;
 			}
 
-			.elapsed,
-			.clock {
-				color: #333;
-				font-size: 2em;
-				text-align: center;
-				display: inline-block;
-				padding: 0.5em;
-				background-color: #eee;
-				border-radius: 10px;
+			@media screen and (max-width: 1080px) {
+				#speaker-controls {
+					font-size: 16px;
+				}
 			}
 
-			.elapsed h2,
-			.clock h2 {
-				font-size: 0.8em;
-				line-height: 100%;
-				margin: 0;
-				color: #aaa;
+			@media screen and (max-width: 900px) {
+				#speaker-controls {
+					font-size: 14px;
+				}
 			}
 
-			.elapsed .mute {
-				color: #ddd;
+			@media screen and (max-width: 800px) {
+				#speaker-controls {
+					font-size: 12px;
+				}
 			}
 
 		</style>
@@ -138,81 +140,156 @@
 
 	<body>
 
-		<script>
-			function getNotesURL( controls ) {
-				return window.opener.location.protocol + '//' + window.opener.location.host + window.opener.location.pathname + '?receiver&controls='+ ( controls || 'false' ) +'&progress=false&overview=false' + window.opener.location.hash;
-			}
-			var notesCurrentSlideURL = getNotesURL( true );
-			var notesNextSlideURL = getNotesURL( false );
-		</script>
-
-		<div id="wrap-current-slide" class="slides">
-			<script>document.write( '<iframe width="1280" height="1024" id="current-slide" src="'+ notesCurrentSlideURL +'"></iframe>' );</script>
-		</div>
-
-		<div id="wrap-next-slide" class="slides">
-			<script>document.write( '<iframe width="640" height="512" id="next-slide" src="'+ notesNextSlideURL +'"></iframe>' );</script>
-			<span>UPCOMING:</span>
-		</div>
-
-		<div class="time">
-			<div class="clock">
-				<h2>Time</h2>
-				<span id="clock">0:00:00 AM</span>
+		<div id="current-slide"></div>
+		<div id="next-slide"><span class="label">UPCOMING:</span></div>
+		<div id="speaker-controls">
+			<div class="speaker-controls-time">
+				<h4 class="label">Time</h4>
+				<div class="clock">
+					<span class="clock-value">0:00 AM</span>
+				</div>
+				<div class="timer">
+					<span class="hours-value">00</span><span class="minutes-value">:00</span><span class="seconds-value">:00</span>
+				</div>
+				<div class="clear"></div>
 			</div>
-			<div class="elapsed">
-				<h2>Elapsed</h2>
-				<span id="hours">00</span><span id="minutes">:00</span><span id="seconds">:00</span>
+
+			<div class="speaker-controls-notes hidden">
+				<h4 class="label">Notes</h4>
+				<div class="value"></div>
 			</div>
 		</div>
 
-		<div id="notes"></div>
-
 		<script src="../../plugin/markdown/marked.js"></script>
 		<script>
 
-			window.addEventListener( 'load', function() {
+			(function() {
 
-				if( window.opener && window.opener.location && window.opener.location.href ) {
+				var notes,
+					notesValue,
+					currentState,
+					currentSlide,
+					nextSlide,
+					connected = false;
 
-					var notes = document.getElementById( 'notes' ),
-						currentSlide = document.getElementById( 'current-slide' ),
-						nextSlide = document.getElementById( 'next-slide' ),
-						silenced = false;
+				window.addEventListener( 'message', function( event ) {
 
-					window.addEventListener( 'message', function( event ) {
-						var data = JSON.parse( event.data );
+					var data = JSON.parse( event.data );
 
-						// No need for updating the notes in case of fragment changes
-						if ( data.notes !== undefined) {
-							if( data.markdown ) {
-								notes.innerHTML = marked( data.notes );
-							}
-							else {
-								notes.innerHTML = data.notes;
-							}
+					// Messages sent by the notes plugin inside of the main window
+					if( data && data.namespace === 'reveal-notes' ) {
+						if( data.type === 'connect' ) {
+							handleConnectMessage( data );
+						}
+						else if( data.type === 'state' ) {
+							handleStateMessage( data );
+						}
+					}
+					// Messages sent by the reveal.js inside of the current slide preview
+					else if( data && data.namespace === 'reveal' ) {
+						if( /ready/.test( data.eventName ) ) {
+							// Send a message back to notify that the handshake is complete
+							window.opener.postMessage( JSON.stringify({ namespace: 'reveal-notes', type: 'connected'} ), '*' );
 						}
+						else if( /slidechanged|fragmentshown|fragmenthidden|overviewshown|overviewhidden|paused|resumed/.test( data.eventName ) && currentState !== JSON.stringify( data.state ) ) {
+							window.opener.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ]} ), '*' );
+						}
+					}
 
-						silenced = true;
+				} );
 
-						// Update the note slides
-						currentSlide.contentWindow.Reveal.slide( data.indexh, data.indexv, data.indexf );
-						nextSlide.contentWindow.Reveal.slide( data.nextindexh, data.nextindexv );
+				/**
+				 * Called when the main window is trying to establish a
+				 * connection.
+				 */
+				function handleConnectMessage( data ) {
 
-						silenced = false;
+					if( connected === false ) {
+						connected = true;
 
-					}, false );
+						setupIframes( data );
+						setupNotes();
+						setupTimer();
+					}
 
-					var start = new Date(),
-						timeEl = document.querySelector( '.time' ),
-						clockEl = document.getElementById( 'clock' ),
-						hoursEl = document.getElementById( 'hours' ),
-						minutesEl = document.getElementById( 'minutes' ),
-						secondsEl = document.getElementById( 'seconds' );
+				}
+
+				/**
+				 * Called when the main window sends an updated state.
+				 */
+				function handleStateMessage( data ) {
+
+					// Store the most recently set state to avoid circular loops
+					// applying the same state
+					currentState = JSON.stringify( data.state );
+
+					// No need for updating the notes in case of fragment changes
+					if ( data.notes ) {
+						notes.classList.remove( 'hidden' );
+						if( data.markdown ) {
+							notesValue.innerHTML = marked( data.notes );
+						}
+						else {
+							notesValue.innerHTML = data.notes;
+						}
+					}
+					else {
+						notes.classList.add( 'hidden' );
+					}
+
+					// Update the note slides
+					currentSlide.contentWindow.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ] }), '*' );
+					nextSlide.contentWindow.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ] }), '*' );
+					nextSlide.contentWindow.postMessage( JSON.stringify({ method: 'next' }), '*' );
+
+				}
 
-					setInterval( function() {
+				/**
+				 * Creates the preview iframes.
+				 */
+				function setupIframes( data ) {
 
-						timeEl.style.opacity = 1;
+					var url = data.url + '?receiver&progress=false&overview=false&history=false';
+					var hash = '#/' + data.state.indexh + '/' + data.state.indexv;
+
+					currentSlide = document.createElement( 'iframe' );
+					currentSlide.setAttribute( 'width', 1280 );
+					currentSlide.setAttribute( 'height', 1024 );
+					currentSlide.setAttribute( 'src', url + '&postMessageEvents=true' + hash );
+					document.querySelector( '#current-slide' ).appendChild( currentSlide );
+
+					nextSlide = document.createElement( 'iframe' );
+					nextSlide.setAttribute( 'width', 640 );
+					nextSlide.setAttribute( 'height', 512 );
+					nextSlide.setAttribute( 'src', url + '&controls=false' + hash );
+					document.querySelector( '#next-slide' ).appendChild( nextSlide );
+
+				}
+
+				/**
+				 * Setup the notes UI.
+				 */
+				function setupNotes() {
+
+					notes = document.querySelector( '.speaker-controls-notes' );
+					notesValue = document.querySelector( '.speaker-controls-notes .value' );
+
+				}
+
+				/**
+				 * Create the timer and clock and start updating them
+				 * at an interval.
+				 */
+				function setupTimer() {
+
+					var start = new Date(),
+						timeEl = document.querySelector( '.speaker-controls-time' ),
+						clockEl = timeEl.querySelector( '.clock-value' ),
+						hoursEl = timeEl.querySelector( '.hours-value' ),
+						minutesEl = timeEl.querySelector( '.minutes-value' ),
+						secondsEl = timeEl.querySelector( '.seconds-value' );
+
+					function _updateTimer() {
 
 						var diff, hours, minutes, seconds,
 							now = new Date();
@@ -222,45 +299,31 @@
 						minutes = Math.floor( ( diff / ( 1000 * 60 ) ) % 60 );
 						seconds = Math.floor( ( diff / 1000 ) % 60 );
 
-						clockEl.innerHTML = now.toLocaleTimeString();
+						clockEl.innerHTML = now.toLocaleTimeString( 'en-US', { hour12: true, hour: '2-digit', minute:'2-digit' } );
 						hoursEl.innerHTML = zeroPadInteger( hours );
-						hoursEl.className = hours > 0 ? "" : "mute";
-						minutesEl.innerHTML = ":" + zeroPadInteger( minutes );
-						minutesEl.className = minutes > 0 ? "" : "mute";
-						secondsEl.innerHTML = ":" + zeroPadInteger( seconds );
-
-					}, 1000 );
-
-					// Broadcasts the state of the notes window to synchronize
-					// the main window
-					function synchronizeMainWindow() {
-
-						if( !silenced ) {
-							var indices = currentSlide.contentWindow.Reveal.getIndices();
-							window.opener.Reveal.slide( indices.h, indices.v, indices.f );
-						}
+						hoursEl.className = hours > 0 ? '' : 'mute';
+						minutesEl.innerHTML = ':' + zeroPadInteger( minutes );
+						minutesEl.className = minutes > 0 ? '' : 'mute';
+						secondsEl.innerHTML = ':' + zeroPadInteger( seconds );
 
 					}
 
-					// Navigate the main window when the notes slide changes
-					currentSlide.contentWindow.Reveal.addEventListener( 'slidechanged', synchronizeMainWindow );
-					currentSlide.contentWindow.Reveal.addEventListener( 'fragmentshown', synchronizeMainWindow );
-					currentSlide.contentWindow.Reveal.addEventListener( 'fragmenthidden', synchronizeMainWindow );
+					// Update once directly
+					_updateTimer();
 
-				}
-				else {
-
-					document.body.innerHTML =  '<p class="error">Unable to access <code>window.opener.location</code>.<br>Make sure the presentation is running on a web server.</p>';
+					// Then update every second
+					setInterval( _updateTimer, 1000 );
 
 				}
 
+				function zeroPadInteger( num ) {
 
-			}, false );
+					var str = '00' + parseInt( num );
+					return str.substring( str.length - 2 );
 
-			function zeroPadInteger( num ) {
-				var str = "00" + parseInt( num );
-				return str.substring( str.length - 2 );
-			}
+				}
+
+			})();
 
 		</script>
 	</body>

+ 59 - 29
plugin/notes/notes.js

@@ -1,6 +1,13 @@
 /**
  * Handles opening of and synchronization with the reveal.js
  * notes window.
+ *
+ * Handshake process:
+ * 1. This window posts 'connect' to notes window
+ *    - Includes URL of presentation to show
+ * 2. Notes window responds with 'connected' when it is available
+ * 3. This window proceeds to send the current presentation state
+ *    to the notes window
  */
 var RevealNotes = (function() {
 
@@ -9,41 +16,46 @@ var RevealNotes = (function() {
 		jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, '');   // the js folder path
 		var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1120,height=850' );
 
-		// Fires when slide is changed
-		Reveal.addEventListener( 'slidechanged', post );
-
-		// Fires when a fragment is shown
-		Reveal.addEventListener( 'fragmentshown', post );
+		/**
+		 * Connect to the notes window through a postmessage handshake.
+		 * Using postmessage enables us to work in situations where the
+		 * origins differ, such as a presentation being opened from the
+		 * file system.
+		 */
+		function connect() {
+			// Keep trying to connect until we get a 'connected' message back
+			var connectInterval = setInterval( function() {
+				notesPopup.postMessage( JSON.stringify( {
+					namespace: 'reveal-notes',
+					type: 'connect',
+					url: window.location.protocol + '//' + window.location.host + window.location.pathname,
+					state: Reveal.getState()
+				} ), '*' );
+			}, 500 );
 
-		// Fires when a fragment is hidden
-		Reveal.addEventListener( 'fragmenthidden', post );
+			window.addEventListener( 'message', function( event ) {
+				var data = JSON.parse( event.data );
+				if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
+					clearInterval( connectInterval );
+					onConnected();
+				}
+			} );
+		}
 
 		/**
 		 * Posts the current slide data to the notes window
 		 */
 		function post() {
+
 			var slideElement = Reveal.getCurrentSlide(),
-				slideIndices = Reveal.getIndices(),
-				notesElement = slideElement.querySelector( 'aside.notes' ),
-				nextindexh,
-				nextindexv;
-
-			if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) {
-				nextindexh = slideIndices.h;
-				nextindexv = slideIndices.v + 1;
-			} else {
-				nextindexh = slideIndices.h + 1;
-				nextindexv = 0;
-			}
+				notesElement = slideElement.querySelector( 'aside.notes' );
 
 			var messageData = {
-				notes : '',
-				indexh : slideIndices.h,
-				indexv : slideIndices.v,
-				indexf : slideIndices.f,
-				nextindexh : nextindexh,
-				nextindexv : nextindexv,
-				markdown : false
+				namespace: 'reveal-notes',
+				type: 'state',
+				notes: '',
+				markdown: false,
+				state: Reveal.getState()
 			};
 
 			// Look for notes defined in a slide attribute
@@ -58,12 +70,30 @@ var RevealNotes = (function() {
 			}
 
 			notesPopup.postMessage( JSON.stringify( messageData ), '*' );
+
 		}
 
-		// Navigate to the current slide when the notes are loaded
-		notesPopup.addEventListener( 'load', function( event ) {
+		/**
+		 * Called once we have established a connection to the notes
+		 * window.
+		 */
+		function onConnected() {
+
+			// Monitor events that trigger a change in state
+			Reveal.addEventListener( 'slidechanged', post );
+			Reveal.addEventListener( 'fragmentshown', post );
+			Reveal.addEventListener( 'fragmenthidden', post );
+			Reveal.addEventListener( 'overviewhidden', post );
+			Reveal.addEventListener( 'overviewshown', post );
+			Reveal.addEventListener( 'paused', post );
+			Reveal.addEventListener( 'resumed', post );
+
+			// Post the initial state
 			post();
-		}, false );
+
+		}
+
+		connect();
 	}
 
 	// If the there's a 'notes' query set, open directly

+ 0 - 39
plugin/postmessage/example.html

@@ -1,39 +0,0 @@
-<html>
-	<body>
-
-		<iframe id="reveal" src="../../index.html" style="border: 0;" width="500" height="500"></iframe>
-
-		<div>
-			<input id="back" type="button" value="go back"/>
-			<input id="ahead" type="button" value="go ahead"/>
-			<input id="slideto" type="button" value="slideto 2-2"/>
-		</div>
-
-		<script>
-
-			(function (){
-
-				var back = document.getElementById( 'back' ),
-						ahead = document.getElementById( 'ahead' ),
-						slideto = document.getElementById( 'slideto' ),
-						reveal =  window.frames[0];
-
-					back.addEventListener( 'click', function () {
-						
-					reveal.postMessage( JSON.stringify({method: 'prev', args: []}), '*' );
-				}, false );
-
-				ahead.addEventListener( 'click', function (){
-					reveal.postMessage( JSON.stringify({method: 'next', args: []}), '*' );
-				}, false );
-
-				slideto.addEventListener( 'click', function (){
-					reveal.postMessage( JSON.stringify({method: 'slide', args: [2,2]}), '*' );
-				}, false );
-
-			}());
-
-		</script>
-
-	</body>
-</html>

+ 0 - 42
plugin/postmessage/postmessage.js

@@ -1,42 +0,0 @@
-/*
-
-	simple postmessage plugin
-
-	Useful when a reveal slideshow is inside an iframe.
-	It allows to call reveal methods from outside.
-
-	Example:
-		 var reveal =  window.frames[0];
-
-		 // Reveal.prev(); 
-		 reveal.postMessage(JSON.stringify({method: 'prev', args: []}), '*');
-		 // Reveal.next(); 
-		 reveal.postMessage(JSON.stringify({method: 'next', args: []}), '*');
-		 // Reveal.slide(2, 2); 
-		 reveal.postMessage(JSON.stringify({method: 'slide', args: [2,2]}), '*');
-
-	Add to the slideshow:
-
-		dependencies: [
-			...
-			{ src: 'plugin/postmessage/postmessage.js', async: true, condition: function() { return !!document.body.classList; } }
-		]
-
-*/
-
-(function (){
-
-	window.addEventListener( "message", function ( event ) {
-		var data = JSON.parse( event.data ),
-				method = data.method,
-				args = data.args;
-
-		if( typeof Reveal[method] === 'function' ) {
-			Reveal[method].apply( Reveal, data.args );
-		}
-	}, false);
-
-}());
-
-
-

+ 2 - 2
test/examples/barebones.html

@@ -6,7 +6,7 @@
 
 		<title>reveal.js - Barebones</title>
 
-		<link rel="stylesheet" href="../../css/reveal.min.css">
+		<link rel="stylesheet" href="../../css/reveal.css">
 	</head>
 
 	<body>
@@ -29,7 +29,7 @@
 
 		</div>
 
-		<script src="../../js/reveal.min.js"></script>
+		<script src="../../js/reveal.js"></script>
 
 		<script>
 

+ 2 - 2
test/examples/embedded-media.html

@@ -8,7 +8,7 @@
 
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 
-		<link rel="stylesheet" href="../../css/reveal.min.css">
+		<link rel="stylesheet" href="../../css/reveal.css">
 		<link rel="stylesheet" href="../../css/theme/default.css" id="theme">
 	</head>
 
@@ -35,7 +35,7 @@
 		</div>
 
 		<script src="../../lib/js/head.min.js"></script>
-		<script src="../../js/reveal.min.js"></script>
+		<script src="../../js/reveal.js"></script>
 
 		<script>
 

+ 2 - 2
test/examples/math.html

@@ -8,7 +8,7 @@
 
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 
-		<link rel="stylesheet" href="../../css/reveal.min.css">
+		<link rel="stylesheet" href="../../css/reveal.css">
 		<link rel="stylesheet" href="../../css/theme/night.css" id="theme">
 	</head>
 
@@ -160,7 +160,7 @@
 		</div>
 
 		<script src="../../lib/js/head.min.js"></script>
-		<script src="../../js/reveal.min.js"></script>
+		<script src="../../js/reveal.js"></script>
 
 		<script>
 

+ 2 - 2
test/examples/slide-backgrounds.html

@@ -8,7 +8,7 @@
 
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 
-		<link rel="stylesheet" href="../../css/reveal.min.css">
+		<link rel="stylesheet" href="../../css/reveal.css">
 		<link rel="stylesheet" href="../../css/theme/serif.css" id="theme">
 	</head>
 
@@ -101,7 +101,7 @@
 		</div>
 
 		<script src="../../lib/js/head.min.js"></script>
-		<script src="../../js/reveal.min.js"></script>
+		<script src="../../js/reveal.js"></script>
 
 		<script>
 

+ 2 - 2
test/test-markdown-element-attributes.html

@@ -6,7 +6,7 @@
 
 		<title>reveal.js - Test Markdown Element Attributes</title>
 
-		<link rel="stylesheet" href="../css/reveal.min.css">
+		<link rel="stylesheet" href="../css/reveal.css">
 		<link rel="stylesheet" href="qunit-1.12.0.css">
 	</head>
 
@@ -123,7 +123,7 @@
 		</div>
 
 		<script src="../lib/js/head.min.js"></script>
-		<script src="../js/reveal.min.js"></script>
+		<script src="../js/reveal.js"></script>
 		<script src="../plugin/markdown/marked.js"></script>
 		<script src="../plugin/markdown/markdown.js"></script>
 		<script src="qunit-1.12.0.js"></script>

+ 2 - 2
test/test-markdown-slide-attributes.html

@@ -6,7 +6,7 @@
 
 		<title>reveal.js - Test Markdown Attributes</title>
 
-		<link rel="stylesheet" href="../css/reveal.min.css">
+		<link rel="stylesheet" href="../css/reveal.css">
 		<link rel="stylesheet" href="qunit-1.12.0.css">
 	</head>
 
@@ -117,7 +117,7 @@
 		</div>
 
 		<script src="../lib/js/head.min.js"></script>
-		<script src="../js/reveal.min.js"></script>
+		<script src="../js/reveal.js"></script>
 		<script src="../plugin/markdown/marked.js"></script>
 		<script src="../plugin/markdown/markdown.js"></script>
 		<script src="qunit-1.12.0.js"></script>

+ 2 - 2
test/test-markdown.html

@@ -6,7 +6,7 @@
 
 		<title>reveal.js - Test Markdown</title>
 
-		<link rel="stylesheet" href="../css/reveal.min.css">
+		<link rel="stylesheet" href="../css/reveal.css">
 		<link rel="stylesheet" href="qunit-1.12.0.css">
 	</head>
 
@@ -41,7 +41,7 @@
 		</div>
 
 		<script src="../lib/js/head.min.js"></script>
-		<script src="../js/reveal.min.js"></script>
+		<script src="../js/reveal.js"></script>
 		<script src="../plugin/markdown/marked.js"></script>
 		<script src="../plugin/markdown/markdown.js"></script>
 		<script src="qunit-1.12.0.js"></script>

+ 2 - 2
test/test.html

@@ -6,7 +6,7 @@
 
 		<title>reveal.js - Tests</title>
 
-		<link rel="stylesheet" href="../css/reveal.min.css">
+		<link rel="stylesheet" href="../css/reveal.css">
 		<link rel="stylesheet" href="qunit-1.12.0.css">
 	</head>
 
@@ -72,7 +72,7 @@
 		</div>
 
 		<script src="../lib/js/head.min.js"></script>
-		<script src="../js/reveal.min.js"></script>
+		<script src="../js/reveal.js"></script>
 		<script src="qunit-1.12.0.js"></script>
 
 		<script src="test.js"></script>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است