Presentation API

Presentation concepts and usage

The Presentation API is developed to effectively display web content through large scale presentation devices such as projectors and connected TVs. The relevant multimedia devices include wired displays, such as HDMI, DVI, or similar, and wireless technologies like Miracast, Chromecast, DLNA, or AirPlay.

 

Basically, a web page which uses PresentationRequest can be defined as a controller page. The content to be displayed in those devices is represented as separate pages. With the PresentationRequest, a controller page describes the location of the to-be-displayed content, then asks the browser to provide a presentation device to pass the content using PresentationRequest.start() and stops content passing with PresentationConnection.terminate().

Interfaces

Presentation
In controlling browsing context, the Presentation interface provides a mechanism to override the browser default behavior of launching presentation to external screen. In receiving browsing context, Presentation interface provides the access to the available presentation connections.
PresentationRequest
Being associated with a request, a PresentationRequest object is used to initiate or reconnect to a presentation made by a controlling browsing context.
PresentationAvailability
A PresentationAvailability object is associated with available presentation displays and represents the presentation display availability for a presentation request.
PresentationConnectionAvailableEvent
The PresentationConnectionAvailableEvent is fired on a PresentationRequest when a connection associated with the object is created.
PresentationConnection
Each presentation connection is represented by a PresentationConnection object.
PresentationConnectionCloseEvent
A PresentationConnectionCloseEvent is fired when a presentation connection enters a closed state.
PresentationReceiver
The PresentationReceiver allows a receiving browsing context to access the controlling browsing contexts and communicate with them.
PresentationConnectionList
PresentationConnectionList represents the collection of non-terminated presentation connections. It is also a monitor for the event of new available presentation connection.

Example

Example codes below highlight the usage of main features of the Presentation API: controller.html implements the controller and presentation.html implements the presentation. Both pages are served from the domain http://example.org (http://example.org/controller.html and http://example.org/presentation.html). These examples assume that the controlling page is managing one presentation at a time. Please refer to the comments in the code examples for further details.

Monitor availability of presentation displays

<!-- controller.html -->
<button id="presentBtn" style="display: none;">Present</button>
<script>
  // The Present button is visible if at least one presentation display is available
  var presentBtn = document.getElementById("presentBtn");
  // It is also possible to use relative presentation URL e.g. "presentation.html"
  var presUrls = ["http://example.com/presentation.html",
                  "http://example.net/alternate.html"];
  // show or hide present button depending on display availability
  var handleAvailabilityChange = function(available) {
    presentBtn.style.display = available ? "inline" : "none";
  };
  // Promise is resolved as soon as the presentation display availability is
  // known.
  var request = new PresentationRequest(presUrls);
  request.getAvailability().then(function(availability) {
    // availability.value may be kept up-to-date by the controlling UA as long
    // as the availability object is alive. It is advised for the web developers
    // to discard the object as soon as it's not needed.
    handleAvailabilityChange(availability.value);
    availability.onchange = function() { handleAvailabilityChange(this.value); };
  }).catch(function() {
    // Availability monitoring is not supported by the platform, so discovery of
    // presentation displays will happen only after request.start() is called.
    // Pretend the devices are available for simplicity; or, one could implement
    // a third state for the button.
    handleAvailabilityChange(true);
  });
</script>

Starting a new presentation

<!-- controller.html -->
<script>
  presentBtn.onclick = function () {
    // Start new presentation.
    request.start()
      // The connection to the presentation will be passed to setConnection on
      // success.
      .then(setConnection);
      // Otherwise, the user canceled the selection dialog or no screens were
      // found.
  };
</script>

Reconnect to a presentation

<!-- controller.html -->
<button id="reconnectBtn" style="display: none;">Reconnect</button>
<script>
  var reconnect = function () {
    // read presId from localStorage if exists
    var presId = localStorage["presId"];
    // presId is mandatory when reconnecting to a presentation.
    if (!!presId) {
      request.reconnect(presId)
        // The new connection to the presentation will be passed to
        // setConnection on success.
        .then(setConnection);
        // No connection found for presUrl and presId, or an error occurred.
    }
  };
  // On navigation of the controller, reconnect automatically.
  document.addEventListener("DOMContentLoaded", reconnect);
  // Or allow manual reconnection.
  reconnectBtn.onclick = reconnect;
</script>

Presentation initiation by the controlling UA

<!-- controller.html -->
<!-- Setting presentation.defaultRequest allows the page to specify the
     PresentationRequest to use when the controlling UA initiates a
     presentation. -->
<script>
  navigator.presentation.defaultRequest = new PresentationRequest(presUrls);
  navigator.presentation.defaultRequest.onconnectionavailable = function(evt) {
    setConnection(evt.connection);
  };
</script>

Monitor connection's state and exchange data

<!-- controller.html -->
<button id="disconnectBtn" style="display: none;">Disconnect</button>
<button id="stopBtn" style="display: none;">Stop</button>
<button id="reconnectBtn" style="display: none;">Reconnect</button>
<script>
  let connection;

  // The Disconnect and Stop buttons are visible if there is a connected presentation
  const stopBtn = document.querySelector("#stopBtn");
  const reconnectBtn = document.querySelector("#reconnectBtn");
  const disconnectBtn = document.querySelector("#disconnectBtn");

  stopBtn.onclick = _ => {
    connection && connection.terminate();
  };

  disconnectBtn.onclick = _ => {
    connection && connection.close();
  };

  function setConnection(newConnection) {
    // Disconnect from existing presentation, if not attempting to reconnect
    if (connection && connection != newConnection && connection.state != 'closed') {
      connection.onclosed = undefined;
      connection.close();
    }

    // Set the new connection and save the presentation ID
    connection = newConnection;
    localStorage["presId"] = connection.id;

    function showConnectedUI() {
      // Allow the user to disconnect from or terminate the presentation
      stopBtn.style.display = "inline";
      disconnectBtn.style.display = "inline";
      reconnectBtn.style.display = "none";
    }

    function showDisconnectedUI() {
      disconnectBtn.style.display = "none";
      stopBtn.style.display = "none";
      reconnectBtn.style.display = localStorage["presId"] ? "inline" : "none";
    }

    // Monitor the connection state
    connection.onconnect = _ => {
      showConnectedUI();

      // Register message handler
      connection.onmessage = message => {
        console.log(`Received message: ${message.data}`);
      };

      // Send initial message to presentation page
      connection.send("Say hello");
    };

    connection.onclose = _ => {
      connection = null;
      showDisconnectedUI();
    };

    connection.onterminate = _ => {
      // Remove presId from localStorage if exists
      delete localStorage["presId"];
      connection = null;
      showDisconnectedUI();
    };
  };
</script>

Monitor available connection(s) and say hello

<!-- presentation.html -->
<script>
  var addConnection = function(connection) {
    this.onmessage = function (message) {
      if (message.data == "say hello")
        this.send("hello");
    };
  };

  navigator.presentation.receiver.connectionList.then(function (list) {
    list.connections.map(function (connection) {
      addConnection(connection);
    });
    list.onconnectionavailable = function (evt) {
      addConnection(evt.connection);
    };
  });
</script>

Passing locale information with a message

<!-- controller.html -->
<script>
  connection.send("{string: '你好,世界!', lang: 'zh-CN'}");
  connection.send("{string: 'こんにちは、世界!', lang: 'ja'}");
  connection.send("{string: '안녕하세요, 세계!', lang: 'ko'}");
  connection.send("{string: 'Hello, world!', lang: 'en-US'}");
</script>

<!-- presentation.html -->
<script>
  connection.onmessage = function (message) {
    var messageObj = JSON.parse(message.data);
    var spanElt = document.createElement("SPAN");
    spanElt.lang = messageObj.lang;
    spanElt.textContent = messageObj.string;
    document.appendChild(spanElt);
  };
</script>

 

Specifications

Specification Status Comment
Presentation API Candidate Recommendation Initial definition.

Browser Compatibility

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support

48.0

? ? ? ?
Feature Android Android Webview Firefox Mobile (Gecko) Firefox OS IE Mobile Opera Mobile Safari Mobile Chrome for Android
Basic support No support No support ? ? ? ? ? 48.0

 

See also

Presentation API polyfill contains a JavaScript polyfill of the Presentation API specification under standardisation within the Second Screen Working Group at W3C. The polyfill is mostly intended for exploring how the Presentation API may be implemented on top of different presentation mechanisms.

Document Tags and Contributors

 Contributors to this page: MashKao, teoli, rolfedh, jpmedley
 Last updated by: MashKao,