Connecting across iframes
Usually, scripts on different pages are allowed to access each other if and only if the scripts originate from the same website (protocol, port number and host) as the pages they’ll run on. So, if we cannot use external scripts, how can we communicate with embedded video players hosted on YouTube’s external servers?
For a long time sending messages between windows was only possible if the windows used the same protocol, port, and host (known as the “same-origin policy” or CORS policy) to prevent malicious cross-site scripting (XSS) attacks. The
postMessage() method lifts this restriction by providing a way to securely pass messages across domains.
All modern browsers support
postMessage(), though (very) old Internet Explorer versions (older than IE 8) did not support the communication feature. The
postMessage() method safely enables cross-origin communication between
window objects; e.g., between a page and a pop-up that it spawned, or between a page and an IFrame embedded within it.
The Youtube IFrame API
Youtube makes use of
postMessage() to enable cross-domain, event-driven communication between a Web page and the video players embedded in it.
Normally, this function is used to create the player objects that you want to display when the page loads. To get notified of other video events, you have to create the event handlers yourself and add them to the “events” property of the YT.player constructor call. You can also customize the play by using the player parameters (the same as the ones used in the embedded video URLs)
Reacting to Events
The Youtube IFrame API fires events to notify your application of changes to the embedded player. The following list defines the events that the API fires:
- onReady: This event fires whenever a player has finished loading and is ready to begin receiving API calls. Your application should implement this function if you want to perform some action as soon as the player is ready.
- onStateChange: This event fires whenever the player’s state changes. The data property of the event object that the API passes to your event listener function will specify an integer that corresponds to the new player state.
- onPlaybackQualityChange: This event fires whenever the video playback quality changes. The data property value of the event object that the API passes to the event listener function will be a string that identifies the new playback quality.
- onPlaybackRateChange: This event fires whenever the video playback rate changes. The data property value of the event object that the API passes to the event listener function will be a number that identifies the new playback rate.
- onError: This event fires if an error occurs in the player. The API will pass an event object to the event listener function. That object’s data property will specify an integer that identifies the type of error that occurred.
- onApiChange: This event fires when the player has loaded (or unloaded) a module with exposed API methods. Currently, the only module that you can set options for is the “captions” module, which handles closed captioning in the player.
- Queuing functions: Allow you to load and play a video, a playlist, or another list of videos.
- Playback controls and player settings: Allow you to play, pause, seek and stop videos. They also allow you to control volume, playback rate and playlist behavior (shuffle, loop).
- Playback status: Provide information on the player state (playing, paused, etc.) and the video’s current time (elapsed time in seconds since the video started playing).
- Playback quality: Provide information and allow to control video playback quality (highres, hd1080, hd720, large, medium and small).
- Retrieving video information: Provide information about the current video’s URLs, duration and embed code.
- Retrieving playlist information: Provide information about a playlist’s video IDs and the current video’s index inside the playlist.
- Adding or removing an event listener
- Accessing and modifying DOM nodes
In order to interact with the video, must first get a reference to the player (a YT.Player object) you wish to control. Normally, developers save the reference to a global variable when creating the player and then use it wherever they need to manage the player.
In the example below, you can see a very simple player, developed using the Youtube IFrame API and a few buttons. Each button has handlers to catch clicks (I used jQuery but for simplicity) and inside each handler, there’s a call to the matching API call. If you click on the “Result” tab, you will be able to play with a live example and control the video.