310 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			310 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!doctype html>
 | |
| <html lang="en">
 | |
| 	<head>
 | |
| 		<meta charset="utf-8">
 | |
| 
 | |
| 		<title>reveal.js - Slide Notes</title>
 | |
| 
 | |
| 		<style>
 | |
| 			body {
 | |
| 				font-family: Helvetica;
 | |
| 			}
 | |
| 
 | |
| 			#notes {
 | |
| 				font-size: 24px;
 | |
| 				width: 640px;
 | |
| 				margin-top: 5px;
 | |
| 				clear: left;
 | |
| 			}
 | |
| 
 | |
| 			#wrap-current-slide {
 | |
| 				width: 640px;
 | |
| 				height: 512px;
 | |
| 				float: left;
 | |
| 				overflow: hidden;
 | |
| 			}
 | |
| 
 | |
| 			#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);
 | |
| 			}
 | |
| 
 | |
| 			#wrap-next-slide {
 | |
| 				width: 448px;
 | |
| 				height: 358px;
 | |
| 				float: left;
 | |
| 				margin: 0 0 0 10px;
 | |
| 				overflow: hidden;
 | |
| 			}
 | |
| 
 | |
| 			#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);
 | |
| 			}
 | |
| 
 | |
| 			.slides span {
 | |
| 				position: absolute;
 | |
| 				top: 3px;
 | |
| 				left: 3px;
 | |
| 				font-weight: bold;
 | |
| 				font-size: 14px;
 | |
| 				z-index: 2;
 | |
| 				color: rgba( 255, 255, 255, 0.9 );
 | |
| 			}
 | |
| 
 | |
| 			.error {
 | |
| 				font-weight: bold;
 | |
| 				color: red;
 | |
| 				font-size: 1.5em;
 | |
| 				text-align: center;
 | |
| 				margin-top: 10%;
 | |
| 			}
 | |
| 
 | |
| 			.error code {
 | |
| 				font-family: monospace;
 | |
| 			}
 | |
| 
 | |
| 			.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;
 | |
| 			}
 | |
| 
 | |
| 			.elapsed,
 | |
| 			.clock {
 | |
| 				color: #333;
 | |
| 				font-size: 2em;
 | |
| 				text-align: center;
 | |
| 				display: inline-block;
 | |
| 				padding: 0.5em;
 | |
| 				background-color: #eee;
 | |
| 				border-radius: 10px;
 | |
| 			}
 | |
| 
 | |
| 			.elapsed h2,
 | |
| 			.clock h2 {
 | |
| 				font-size: 0.8em;
 | |
| 				line-height: 100%;
 | |
| 				margin: 0;
 | |
| 				color: #aaa;
 | |
| 			}
 | |
| 
 | |
| 			.elapsed .mute {
 | |
| 				color: #ddd;
 | |
| 			}
 | |
| 
 | |
| 		</style>
 | |
| 	</head>
 | |
| 
 | |
| 	<body>
 | |
| 
 | |
| 		<div id="wrap-current-slide" class="slides"></div>
 | |
| 		<div id="wrap-next-slide" class="slides"><span>UPCOMING:</span></div>
 | |
| 
 | |
| 		<div class="time">
 | |
| 			<div class="clock">
 | |
| 				<h2>Time</h2>
 | |
| 				<span id="clock">0:00:00 AM</span>
 | |
| 			</div>
 | |
| 			<div class="elapsed">
 | |
| 				<h2>Elapsed</h2>
 | |
| 				<span id="hours">00</span><span id="minutes">:00</span><span id="seconds">:00</span>
 | |
| 			</div>
 | |
| 		</div>
 | |
| 
 | |
| 		<div id="notes"></div>
 | |
| 
 | |
| 		<script src="../../plugin/markdown/marked.js"></script>
 | |
| 		<script>
 | |
| 
 | |
| 			(function() {
 | |
| 
 | |
| 				var notes,
 | |
| 					currentState,
 | |
| 					currentSlide,
 | |
| 					nextSlide,
 | |
| 					connected = false;
 | |
| 
 | |
| 				window.addEventListener( 'message', function( event ) {
 | |
| 
 | |
| 					var data = JSON.parse( event.data );
 | |
| 
 | |
| 					// 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 ]} ), '*' );
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 				} );
 | |
| 
 | |
| 				/**
 | |
| 				 * Called when the main window is trying to establish a
 | |
| 				 * connection.
 | |
| 				 */
 | |
| 				function handleConnectMessage( data ) {
 | |
| 
 | |
| 					if( connected === false ) {
 | |
| 						connected = true;
 | |
| 
 | |
| 						setupIframes( data );
 | |
| 						setupTimer();
 | |
| 					}
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				/**
 | |
| 				 * 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 !== undefined) {
 | |
| 						if( data.markdown ) {
 | |
| 							notes.innerHTML = marked( data.notes );
 | |
| 						}
 | |
| 						else {
 | |
| 							notes.innerHTML = data.notes;
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					// 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' }), '*' );
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				/**
 | |
| 				 * Creates the preview iframes.
 | |
| 				 */
 | |
| 				function setupIframes( data ) {
 | |
| 
 | |
| 					notes = document.getElementById( 'notes' );
 | |
| 
 | |
| 					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( 'id', 'current-slide' );
 | |
| 					currentSlide.setAttribute( 'width', 1280 );
 | |
| 					currentSlide.setAttribute( 'height', 1024 );
 | |
| 					currentSlide.setAttribute( 'src', url + '&postMessageEvents=true' + hash );
 | |
| 					document.querySelector( '#wrap-current-slide' ).appendChild( currentSlide );
 | |
| 
 | |
| 					nextSlide = document.createElement( 'iframe' );
 | |
| 					nextSlide.setAttribute( 'id', 'next-slide' );
 | |
| 					nextSlide.setAttribute( 'width', 640 );
 | |
| 					nextSlide.setAttribute( 'height', 512 );
 | |
| 					nextSlide.setAttribute( 'src', url + '&controls=false' + hash );
 | |
| 					document.querySelector( '#wrap-next-slide' ).appendChild( nextSlide );
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				/**
 | |
| 				 * Create the timer and clock and start updating them
 | |
| 				 * at an interval.
 | |
| 				 */
 | |
| 				function 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' );
 | |
| 
 | |
| 					setInterval( function() {
 | |
| 
 | |
| 						timeEl.style.opacity = 1;
 | |
| 
 | |
| 						var diff, hours, minutes, seconds,
 | |
| 							now = new Date();
 | |
| 
 | |
| 						diff = now.getTime() - start.getTime();
 | |
| 						hours = Math.floor( diff / ( 1000 * 60 * 60 ) );
 | |
| 						minutes = Math.floor( ( diff / ( 1000 * 60 ) ) % 60 );
 | |
| 						seconds = Math.floor( ( diff / 1000 ) % 60 );
 | |
| 
 | |
| 						clockEl.innerHTML = now.toLocaleTimeString();
 | |
| 						hoursEl.innerHTML = zeroPadInteger( hours );
 | |
| 						hoursEl.className = hours > 0 ? '' : 'mute';
 | |
| 						minutesEl.innerHTML = ':' + zeroPadInteger( minutes );
 | |
| 						minutesEl.className = minutes > 0 ? '' : 'mute';
 | |
| 						secondsEl.innerHTML = ':' + zeroPadInteger( seconds );
 | |
| 
 | |
| 					}, 1000 );
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				function zeroPadInteger( num ) {
 | |
| 
 | |
| 					var str = '00' + parseInt( num );
 | |
| 					return str.substring( str.length - 2 );
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 			})();
 | |
| 
 | |
| 		</script>
 | |
| 	</body>
 | |
| </html>
 |