Presentation Receiver API Sample

Available in Chrome 59+ | View on GitHub | Browse Samples

Background

This sample illustrates the use of Presentation API, which gives the ability to access external presentation-type displays and use them for presenting Web content. The PresentationRequest object is associated with a request to initiate or reconnect to a presentation made by a controlling browsing context and it takes in a presentation request URL when constructed. A presentation can be started by calling the start() method on the PresentationRequest object.

Live Output


Controller

const presentationRequest = new PresentationRequest(['receiver/index.html']);

// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;

let presentationConnection;

document.querySelector('#start').addEventListener('click', function() {
  log('Starting presentation request...');
  presentationRequest.start()
  .then(connection => {
    log('> Connected to ' + connection.url + ', id: ' + connection.id);
  })
  .catch(error => {
    log('> ' + error.name + ': ' + error.message);
  });
});

presentationRequest.addEventListener('connectionavailable', function(event) {
  presentationConnection = event.connection;
  presentationConnection.addEventListener('close', function() {
    log('> Connection closed.');
  });
  presentationConnection.addEventListener('terminate', function() {
    log('> Connection terminated.');
  });
  presentationConnection.addEventListener('message', function(event) {
    log('> ' + event.data);
  });
});

document.querySelector('#sendMessage').addEventListener('click', function() {
  const message = document.querySelector('#message').value.trim();
  const lang = document.body.lang || 'en-US';

  log('Sending "' + message + '"...');
  presentationConnection.send(JSON.stringify({message, lang}));
});

document.querySelector('#close').addEventListener('click', function() {
  log('Closing connection...');
  presentationConnection.close();
});

document.querySelector('#terminate').addEventListener('click', function() {
  log('Terminating connection...');
  presentationConnection.terminate();
});

document.querySelector('#reconnect').addEventListener('click', () => {
  const presentationId = document.querySelector('#presentationId').value.trim();

  presentationRequest.reconnect(presentationId)
  .then(connection => {
    log('Reconnected to ' + connection.id);
  })
  .catch(error => {
    log('Presentation.reconnect() error, ' + error.name + ': ' + error.message);
  });
});

/* Availability monitoring */

presentationRequest.getAvailability()
.then(availability => {
  log('Available presentation displays: ' + availability.value);
  availability.addEventListener('change', function() {
    log('> Available presentation displays: ' + availability.value);
  });
})
.catch(error => {
  log('Presentation availability not supported, ' + error.name + ': ' +
      error.message);
});

Receiver

let connectionIdx = 0;
let messageIdx = 0;

if (navigator.presentation.receiver) {
  navigator.presentation.receiver.connectionList
  .then(list => {
    list.connections.map(connection => addConnection(connection));
    list.addEventListener('connectionavailable', function(event) {
      addConnection(event.connection);
    });
  });
}

function addConnection(connection) {
  connection.connectionId = ++connectionIdx;
  addMessage('New connection #' + connectionIdx);

  connection.addEventListener('message', function(event) {
    messageIdx++;
    const data = JSON.parse(event.data);
    const logString = 'Message ' + messageIdx + ' from connection #' +
        connection.connectionId + ': ' + data.message;
    addMessage(logString, data.lang);
    maybeSetFruit(data.message);
    connection.send('Received message ' + messageIdx);
  });

  connection.addEventListener('close', function(event) {
    addMessage('Connection #' + connection.connectionId + ' closed, reason = ' +
        event.reason + ', message = ' + event.message);
  });
};

/* Utils */

const fruitEmoji = {
  'grapes':      '\u{1F347}',
  'watermelon':  '\u{1F349}',
  'melon':       '\u{1F348}',
  'tangerine':   '\u{1F34A}',
  'lemon':       '\u{1F34B}',
  'banana':      '\u{1F34C}',
  'pineapple':   '\u{1F34D}',
  'green apple': '\u{1F35F}',
  'apple':       '\u{1F34E}',
  'pear':        '\u{1F350}',
  'peach':       '\u{1F351}',
  'cherries':    '\u{1F352}',
  'strawberry':  '\u{1F353}'
};

function addMessage(content, language) {
  const listItem = document.createElement("li");
  if (language) {
    listItem.lang = language;
  }
  listItem.textContent = content;
  document.querySelector("#message-list").appendChild(listItem);
};

function maybeSetFruit(message) {
  const fruit = message.toLowerCase();
  if (fruit in fruitEmoji) {
    document.querySelector('#main').textContent = fruitEmoji[fruit];
  }
};