From a16b71a981e9385627959273bb4e910e1d502c92 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Tue, 23 Apr 2019 10:52:45 +0200 Subject: [PATCH] the postMessage API now works for getter methods --- README.md | 24 ++++++++++++++++++++++-- js/reveal.js | 25 +++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 33956e9..65f9332 100644 --- a/README.md +++ b/README.md @@ -1065,18 +1065,38 @@ The framework has a built-in postMessage API that can be used when communicating .postMessage( JSON.stringify({ method: 'slide', args: [ 2 ] }), '*' ); ``` +#### postMessage Events + When reveal.js runs inside of an iframe it can optionally bubble all of its events to the parent. Bubbled events are stringified JSON with three fields: namespace, eventName and state. Here's how you subscribe to them from the parent window: ```javascript window.addEventListener( 'message', function( event ) { var data = JSON.parse( event.data ); - if( data.namespace === 'reveal' && data.eventName ==='slidechanged' ) { + if( data.namespace === 'reveal' && data.eventName === 'slidechanged' ) { // Slide changed, see data.state for slide number } } ); ``` -This cross-window messaging can be toggled on or off using configuration flags. +#### postMessage Callbacks + +When you call any method via the postMessage API, reveal.js will dispatch a message with the return value. This is done so that you can call a getter method and see what the result is. Check out this example: + +```javascript +.postMessage( JSON.stringify({ method: 'getTotalSlides' }), '*' ); + +window.addEventListener( 'message', function( event ) { + var data = JSON.parse( event.data ); + // `data.method`` is the method that we invoked + if( data.namespace === 'reveal' && data.eventName === 'callback' && data.method === 'getTotalSlides' ) { + data.result // = the total number of slides + } +} ); +``` + +#### Turning postMessage on/off + +This cross-window messaging can be toggled on or off using configuration flags. These are the default values. ```javascript Reveal.initialize({ diff --git a/js/reveal.js b/js/reveal.js index 20a967a..91e7396 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -1276,7 +1276,11 @@ // Check if the requested method can be found if( data.method && typeof Reveal[data.method] === 'function' ) { - Reveal[data.method].apply( Reveal, data.args ); + var result = Reveal[data.method].apply( Reveal, data.args ); + + // Dispatch a postMessage event with the returned value from + // our method invocation for getter functions + dispatchPostMessage( 'callback', { method: data.method, result: result } ); } } }, false ); @@ -1981,8 +1985,25 @@ // If we're in an iframe, post each reveal.js event to the // parent window. Used by the notes plugin + dispatchPostMessage( type ); + + } + + /** + * Dispatched a postMessage of the given type from our window. + */ + function dispatchPostMessage( type, data ) { + if( config.postMessageEvents && window.parent !== window.self ) { - window.parent.postMessage( JSON.stringify({ namespace: 'reveal', eventName: type, state: getState() }), '*' ); + var message = { + namespace: 'reveal', + eventName: type, + state: getState() + }; + + extend( message, data ); + + window.parent.postMessage( JSON.stringify( message ), '*' ); } }