diff options
Diffstat (limited to 'plugin/notes')
-rw-r--r-- | plugin/notes/notes.html | 194 | ||||
-rw-r--r-- | plugin/notes/notes.js | 61 |
2 files changed, 164 insertions, 91 deletions
diff --git a/plugin/notes/notes.html b/plugin/notes/notes.html index 0c4eca5..9e0b230 100644 --- a/plugin/notes/notes.html +++ b/plugin/notes/notes.html @@ -347,6 +347,8 @@ upcomingSlide, layoutLabel, layoutDropdown, + pendingCalls = {}, + lastRevealApiCallId = 0, connected = false; var SPEAKER_LAYOUTS = { @@ -382,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' ) { @@ -399,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. */ @@ -512,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 ); + } ); + } ); } @@ -541,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 ); + } ); } @@ -571,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 ? "-" : ""; @@ -618,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 ); - - } - - // 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(); - + 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 ); + } ); + } ); } - timeEl.addEventListener( 'click', function() { - _resetTimer(); - return false; - } ); - } /** diff --git a/plugin/notes/notes.js b/plugin/notes/notes.js index a5b15b4..3d5eac4 100644 --- a/plugin/notes/notes.js +++ b/plugin/notes/notes.js @@ -11,24 +11,28 @@ */ var RevealNotes = (function() { + var notesPopup = null; + function openNotes( notesFilePath ) { + if (notesPopup && !notesPopup.closed) { + notesPopup.focus(); + return; + } + if( !notesFilePath ) { var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path notesFilePath = jsFileLocation + 'notes.html'; } - var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' ); + notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' ); if( !notesPopup ) { alert( 'Speaker view popup failed to open. Please make sure popups are allowed and reopen the speaker view.' ); return; } - // Allow popup window access to Reveal API - notesPopup.Reveal = window.Reveal; - /** * Connect to the notes window through a postmessage handshake. * Using postmessage enables us to work in situations where the @@ -52,10 +56,29 @@ var RevealNotes = (function() { clearInterval( connectInterval ); onConnected(); } + if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) { + callRevealApi( data.methodName, data.arguments, data.callId ); + } } ); } /** + * Calls the specified Reveal.js method with the provided argument + * and then pushes the result to the notes frame. + */ + function callRevealApi( methodName, methodArguments, callId ) { + + var result = Reveal[methodName].apply( Reveal, methodArguments ); + notesPopup.postMessage( JSON.stringify( { + namespace: 'reveal-notes', + type: 'return', + result: result, + callId: callId + } ), '*' ); + + } + + /** * Posts the current slide data to the notes window */ function post( event ) { @@ -128,20 +151,28 @@ var RevealNotes = (function() { } - if( !/receiver/i.test( window.location.search ) ) { + return { + init: function() { - // If the there's a 'notes' query set, open directly - if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) { - openNotes(); - } + if( !/receiver/i.test( window.location.search ) ) { - // Open the notes when the 's' key is hit - Reveal.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() { - openNotes(); - } ); + // If the there's a 'notes' query set, open directly + if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) { + openNotes(); + } - } + // Open the notes when the 's' key is hit + Reveal.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() { + openNotes(); + } ); - return { open: openNotes }; + } + + }, + + open: openNotes + }; })(); + +Reveal.registerPlugin( 'notes', RevealNotes ); |