diff options
Diffstat (limited to 'plugin/notes/notes.html')
-rw-r--r-- | plugin/notes/notes.html | 220 |
1 files changed, 144 insertions, 76 deletions
diff --git a/plugin/notes/notes.html b/plugin/notes/notes.html index 5b75d73..9e0b230 100644 --- a/plugin/notes/notes.html +++ b/plugin/notes/notes.html @@ -34,6 +34,22 @@ z-index: 2; } + #connection-status { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 20; + padding: 30% 20% 20% 20%; + font-size: 18px; + color: #222; + background: #fff; + text-align: center; + box-sizing: border-box; + line-height: 1.4; + } + .overlay-element { height: 34px; line-height: 34px; @@ -288,6 +304,8 @@ <body> + <div id="connection-status">Loading speaker view...</div> + <div id="current-slide"></div> <div id="upcoming-slide"><span class="overlay-element label">Upcoming</span></div> <div id="speaker-controls"> @@ -329,6 +347,8 @@ upcomingSlide, layoutLabel, layoutDropdown, + pendingCalls = {}, + lastRevealApiCallId = 0, connected = false; var SPEAKER_LAYOUTS = { @@ -340,8 +360,16 @@ setupLayout(); + var connectionStatus = document.querySelector( '#connection-status' ); + var connectionTimeout = setTimeout( function() { + connectionStatus.innerHTML = 'Error connecting to main window.<br>Please try closing and reopening the speaker view.'; + }, 5000 ); + window.addEventListener( 'message', function( event ) { + clearTimeout( connectionTimeout ); + connectionStatus.style.display = 'none'; + var data = JSON.parse( event.data ); // The overview mode is only useful to the reveal.js instance @@ -356,6 +384,10 @@ else if( data.type === 'state' ) { handleStateMessage( data ); } + else if( data.type === 'return' ) { + pendingCalls[data.callId](data.result); + delete pendingCalls[data.callId]; + } } // Messages sent by the reveal.js inside of the current slide preview else if( data && data.namespace === 'reveal' ) { @@ -373,6 +405,23 @@ } ); /** + * Asynchronously calls the Reveal.js API of the main frame. + */ + function callRevealApi( methodName, methodArguments, callback ) { + + var callId = ++lastRevealApiCallId; + pendingCalls[callId] = callback; + window.opener.postMessage( JSON.stringify( { + namespace: 'reveal-notes', + type: 'call', + callId: callId, + methodName: methodName, + arguments: methodArguments + } ), '*' ); + + } + + /** * Called when the main window is trying to establish a * connection. */ @@ -486,28 +535,34 @@ } - function getTimings() { + function getTimings( callback ) { - var slides = Reveal.getSlides(); - var defaultTiming = Reveal.getConfig().defaultTiming; - if (defaultTiming == null) { - return null; - } - var timings = []; - for ( var i in slides ) { - var slide = slides[i]; - var timing = defaultTiming; - if( slide.hasAttribute( 'data-timing' )) { - var t = slide.getAttribute( 'data-timing' ); - timing = parseInt(t); - if( isNaN(timing) ) { - console.warn("Could not parse timing '" + t + "' of slide " + i + "; using default of " + defaultTiming); - timing = defaultTiming; + callRevealApi( 'getSlidesAttributes', [], function ( slideAttributes ) { + callRevealApi( 'getConfig', [], function ( config ) { + var defaultTiming = config.defaultTiming; + if (defaultTiming == null) { + callback(null); + return; + } + + var timings = []; + for ( var i in slideAttributes ) { + var slide = slideAttributes[ i ]; + var timing = defaultTiming; + if( slide.hasOwnProperty( 'data-timing' )) { + var t = slide[ 'data-timing' ]; + timing = parseInt(t); + if( isNaN(timing) ) { + console.warn("Could not parse timing '" + t + "' of slide " + i + "; using default of " + defaultTiming); + timing = defaultTiming; + } + } + timings.push(timing); } - } - timings.push(timing); - } - return timings; + + callback( timings ); + } ); + } ); } @@ -515,15 +570,15 @@ * Return the number of seconds allocated for presenting * all slides up to and including this one. */ - function getTimeAllocated(timings) { + function getTimeAllocated( timings, callback ) { - var slides = Reveal.getSlides(); - var allocated = 0; - var currentSlide = Reveal.getSlidePastCount(); - for (var i in slides.slice(0, currentSlide + 1)) { - allocated += timings[i]; - } - return allocated; + callRevealApi( 'getSlidePastCount', [], function ( currentSlide ) { + var allocated = 0; + for (var i in timings.slice(0, currentSlide + 1)) { + allocated += timings[i]; + } + callback( allocated ); + } ); } @@ -545,12 +600,51 @@ pacingMinutesEl = pacingEl.querySelector( '.minutes-value' ), pacingSecondsEl = pacingEl.querySelector( '.seconds-value' ); - var timings = getTimings(); - if (timings !== null) { - pacingTitleEl.style.removeProperty('display'); - pacingEl.style.removeProperty('display'); + var timings = null; + getTimings( function ( _timings ) { + + timings = _timings; + if (_timings !== null) { + pacingTitleEl.style.removeProperty('display'); + pacingEl.style.removeProperty('display'); + } + + // Update once directly + _updateTimer(); + + // Then update every second + setInterval( _updateTimer, 1000 ); + + } ); + + + function _resetTimer() { + + if (timings == null) { + start = new Date(); + _updateTimer(); + } + else { + // Reset timer to beginning of current slide + getTimeAllocated( timings, function ( slideEndTimingSeconds ) { + var slideEndTiming = slideEndTimingSeconds * 1000; + callRevealApi( 'getSlidePastCount', [], function ( currentSlide ) { + var currentSlideTiming = timings[currentSlide] * 1000; + var previousSlidesTiming = slideEndTiming - currentSlideTiming; + var now = new Date(); + start = new Date(now.getTime() - previousSlidesTiming); + _updateTimer(); + } ); + } ); + } + } + timeEl.addEventListener( 'click', function() { + _resetTimer(); + return false; + } ); + function _displayTime( hrEl, minEl, secEl, time) { var sign = Math.sign(time) == -1 ? "-" : ""; @@ -592,52 +686,26 @@ function _updatePacing(diff) { - var slideEndTiming = getTimeAllocated(timings) * 1000; - var currentSlide = Reveal.getSlidePastCount(); - var currentSlideTiming = timings[currentSlide] * 1000; - var timeLeftCurrentSlide = slideEndTiming - diff; - if (timeLeftCurrentSlide < 0) { - pacingEl.className = 'pacing behind'; - } - else if (timeLeftCurrentSlide < currentSlideTiming) { - pacingEl.className = 'pacing on-track'; - } - else { - pacingEl.className = 'pacing ahead'; - } - _displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide ); - + getTimeAllocated( timings, function ( slideEndTimingSeconds ) { + var slideEndTiming = slideEndTimingSeconds * 1000; + + callRevealApi( 'getSlidePastCount', [], function ( currentSlide ) { + var currentSlideTiming = timings[currentSlide] * 1000; + var timeLeftCurrentSlide = slideEndTiming - diff; + if (timeLeftCurrentSlide < 0) { + pacingEl.className = 'pacing behind'; + } + else if (timeLeftCurrentSlide < currentSlideTiming) { + pacingEl.className = 'pacing on-track'; + } + else { + pacingEl.className = 'pacing ahead'; + } + _displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide ); + } ); + } ); } - // Update once directly - _updateTimer(); - - // Then update every second - setInterval( _updateTimer, 1000 ); - - function _resetTimer() { - - if (timings == null) { - start = new Date(); - } - else { - // Reset timer to beginning of current slide - var slideEndTiming = getTimeAllocated(timings) * 1000; - var currentSlide = Reveal.getSlidePastCount(); - var currentSlideTiming = timings[currentSlide] * 1000; - var previousSlidesTiming = slideEndTiming - currentSlideTiming; - var now = new Date(); - start = new Date(now.getTime() - previousSlidesTiming); - } - _updateTimer(); - - } - - timeEl.addEventListener( 'click', function() { - _resetTimer(); - return false; - } ); - } /** |