fixed showing speaker's view with timings/pacing while serving the presentation from the file system

This commit is contained in:
Martin Jurča 2018-02-18 21:30:17 +01:00
parent 325162692e
commit 8468d82433
3 changed files with 141 additions and 77 deletions

View file

@ -3901,6 +3901,20 @@
} }
function getSlidesMetaInfo() {
var slides = getSlides();
return slides.map( function (slide) {
var meta = {};
for( var i = 0; i < slide.attributes.length; i++ ) {
var attribute = slide.attributes[ i ];
meta[ attribute.name ] = attribute.value;
}
return meta;
} );
}
/** /**
* Retrieves the total number of slides in this presentation. * Retrieves the total number of slides in this presentation.
* *
@ -5252,6 +5266,8 @@
// Returns an Array of all slides // Returns an Array of all slides
getSlides: getSlides, getSlides: getSlides,
getSlidesMetaInfo: getSlidesMetaInfo,
// Returns the total number of slides // Returns the total number of slides
getTotalSlides: getTotalSlides, getTotalSlides: getTotalSlides,

View file

@ -329,6 +329,8 @@
upcomingSlide, upcomingSlide,
layoutLabel, layoutLabel,
layoutDropdown, layoutDropdown,
pendingCalls = {},
lastRevealApiCallId = 0,
connected = false; connected = false;
var SPEAKER_LAYOUTS = { var SPEAKER_LAYOUTS = {
@ -356,6 +358,10 @@
else if( data.type === 'state' ) { else if( data.type === 'state' ) {
handleStateMessage( data ); 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 // Messages sent by the reveal.js inside of the current slide preview
else if( data && data.namespace === 'reveal' ) { else if( data && data.namespace === 'reveal' ) {
@ -372,6 +378,18 @@
} ); } );
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 * Called when the main window is trying to establish a
* connection. * connection.
@ -486,28 +504,34 @@
} }
function getTimings() { function getTimings( callback ) {
var slides = Reveal.getSlides(); callRevealApi( 'getSlidesMetaInfo', [], function ( slides ) {
var defaultTiming = Reveal.getConfig().defaultTiming; callRevealApi( 'getConfig', [], function ( config ) {
if (defaultTiming == null) { var defaultTiming = config.defaultTiming;
return null; if (defaultTiming == null) {
} callback(null);
var timings = []; return;
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;
} }
}
timings.push(timing); var timings = [];
} for ( var i in slides ) {
return timings; var slide = slides[ 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);
}
callback( timings );
} );
} );
} }
@ -515,15 +539,15 @@
* Return the number of seconds allocated for presenting * Return the number of seconds allocated for presenting
* all slides up to and including this one. * all slides up to and including this one.
*/ */
function getTimeAllocated(timings) { function getTimeAllocated( timings, callback ) {
var slides = Reveal.getSlides(); callRevealApi( 'getSlidePastCount', [], function ( currentSlide ) {
var allocated = 0; var allocated = 0;
var currentSlide = Reveal.getSlidePastCount(); for (var i in timings.slice(0, currentSlide + 1)) {
for (var i in slides.slice(0, currentSlide + 1)) { allocated += timings[i];
allocated += timings[i]; }
} callback( allocated );
return allocated; } );
} }
@ -545,12 +569,51 @@
pacingMinutesEl = pacingEl.querySelector( '.minutes-value' ), pacingMinutesEl = pacingEl.querySelector( '.minutes-value' ),
pacingSecondsEl = pacingEl.querySelector( '.seconds-value' ); pacingSecondsEl = pacingEl.querySelector( '.seconds-value' );
var timings = getTimings(); var timings = null;
if (timings !== null) { getTimings( function ( _timings ) {
pacingTitleEl.style.removeProperty('display');
pacingEl.style.removeProperty('display'); 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) { function _displayTime( hrEl, minEl, secEl, time) {
var sign = Math.sign(time) == -1 ? "-" : ""; var sign = Math.sign(time) == -1 ? "-" : "";
@ -592,52 +655,26 @@
function _updatePacing(diff) { function _updatePacing(diff) {
var slideEndTiming = getTimeAllocated(timings) * 1000; getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
var currentSlide = Reveal.getSlidePastCount(); var slideEndTiming = slideEndTimingSeconds * 1000;
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 );
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;
} );
} }
/** /**

View file

@ -21,8 +21,6 @@ var RevealNotes = (function() {
var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' ); var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' );
// Allow popup window access to Reveal API
notesPopup.Reveal = this.Reveal;
/** /**
* Connect to the notes window through a postmessage handshake. * Connect to the notes window through a postmessage handshake.
@ -47,9 +45,22 @@ var RevealNotes = (function() {
clearInterval( connectInterval ); clearInterval( connectInterval );
onConnected(); onConnected();
} }
if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) {
callRevealApi( data.methodName, data.arguments, data.callId );
}
} ); } );
} }
function callRevealApi( methodName, methodArguments, callId ) {
var result = Reveal[methodName].call(Reveal, methodArguments);
notesPopup.postMessage( JSON.stringify( {
namespace: 'reveal-notes',
type: 'return',
result: result,
callId: callId
} ), '*' );
}
/** /**
* Posts the current slide data to the notes window * Posts the current slide data to the notes window
*/ */