<iframe src="//slides.com/news/make-better-presentations/embed?postMessageEvents=true" width="460" height="340" scrolling="no" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>

<div class="controls">
  <div class="status state"></div>
  <div class="status callback"></div>
  <button class="random-slide">Go to random slide</button>
  <button class="get-total-slides">getTotalSlides</button>
  <button class="is-first-slide">isFirstSlide</button>
  <button class="is-last-slide">isLastSlide</button>
</div>
.controls {
  display: inline-block;
  vertical-align: top;
  padding: 10px;
  font-family: sans-serif;
  max-width: 240px;
}

.status {
  display: none;
  margin-bottom: 20px;
}

.status.state:before {
  display: block;
  content: "State";
  font-weight: bold;
}

.status:not(:empty) {
  display: block;
}

button {
  display: block;
  margin-bottom: 5px;
}

/**
 * Example showing how to receive events from the presentation
 * when the current slide changes. Note that you need to include
 * 'postMessageEvents=true' in the query string portion of the
 * presentation URL for this to work.
 */
window.addEventListener( 'message', function( event ) {
  var data = JSON.parse( event.data );
  
  // Make sure we're talking to a presentation
  if( data.namespace === 'reveal' ) {
    
    // We only care about the slide changing. The 'ready' event
    // is sent in place of a 'slidechanged' for the very first
    // slide when the presentation loads.
    if( data.eventName === 'slidechanged' || data.eventName === 'ready' ) {

      // Dig out the presentation state, key properties:
      //   indexh: The index of the current horizontal slide
      //   indexv: The index of the current vertical slide (if any)
      //   indexf: The index of the current fragment (if any)
      var state = data.state;

      document.querySelector( '.status.state' ).innerHTML = 'indexh: ' + state.indexh + '<br>' +
                                                            'indexv: ' + state.indexv;

    }
    else if( data.eventName === 'callback' ) {
      document.querySelector( '.status.callback' ).innerHTML = 'Callback from <strong>'+data.method+'</strong> is <strong>'+data.result+'</strong>';
    }

  }
} );

/**
 * Example of sending messages into the presentation frame.
 * In this example we're sending a message for navigating
 * to a random slide, however you can find a full list of
 * what functions there are available here:
 * https://github.com/hakimel/reveal.js#api
 */
document.querySelector( '.random-slide' ).addEventListener( 'click', function( event ) {
  // Find our presentation iframe
  var frame = document.querySelector( 'iframe' );
  
  // Post a message into the frame
  frame.contentWindow.postMessage( JSON.stringify({
    method: 'slide',
    args: [ Math.ceil( Math.random() * 10  ) ]
  }), '*' );
} );

document.querySelector( '.get-total-slides' ).addEventListener( 'click', function( event ) {
  document.querySelector( 'iframe' ).contentWindow.postMessage( JSON.stringify({
    method: 'getTotalSlides'
  }), '*' );
} );

document.querySelector( '.is-first-slide' ).addEventListener( 'click', function( event ) {
  document.querySelector( 'iframe' ).contentWindow.postMessage( JSON.stringify({
    method: 'isFirstSlide'
  }), '*' );
} );

document.querySelector( '.is-last-slide' ).addEventListener( 'click', function( event ) {
  document.querySelector( 'iframe' ).contentWindow.postMessage( JSON.stringify({
    method: 'isLastSlide'
  }), '*' );
} );

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.