Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong><em>Fiddle Links: <a href="http://jsfiddle.net/g6P5H/214" rel="noreferrer">Source code</a> - <a href="http://jsfiddle.net/g6P5H/214/show/" rel="noreferrer">Preview</a> - <a href="http://jsfiddle.net/8R5y6/" rel="noreferrer" title="Note: The small version does NOT take care of the player&#39;s state!">Small version</a></em></strong><br/> Update: This small function will only execute code in a single direction. If you want full support (eg event listeners / getters), have a look <strong>at <a href="https://stackoverflow.com/a/7988536/938089?listening-for-youtube-event-in-javascript-or-jquery)">Listening for Youtube Event in jQuery</a></strong></p> <p>As a result of a deep code analysis, I've created a function: <code>function callPlayer</code> requests a function call on any framed YouTube video. See the <a href="https://developers.google.com/youtube/js_api_reference#Operations" rel="noreferrer">YouTube Api reference</a> to get a full list of possible function calls. Read the comments at the source code for an explanation.</p> <p>On 17 may 2012, the code size was doubled in order to take care of the player's ready state. If you need a compact function which does not deal with the player's ready state, see <a href="http://jsfiddle.net/8R5y6/" rel="noreferrer">http://jsfiddle.net/8R5y6/</a>.</p> <pre><code>/** * @author Rob W &lt;gwnRob@gmail.com&gt; * @website https://stackoverflow.com/a/7513356/938089 * @version 20131010 * @description Executes function on a framed YouTube video (see website link) * For a full list of possible functions, see: * https://developers.google.com/youtube/js_api_reference * @param String frame_id The id of (the div containing) the frame * @param String func Desired function to call, eg. "playVideo" * (Function) Function to call when the player is ready. * @param Array args (optional) List of arguments to pass to function func*/ function callPlayer(frame_id, func, args) { if (window.jQuery &amp;&amp; frame_id instanceof jQuery) frame_id = frame_id.get(0).id; var iframe = document.getElementById(frame_id); if (iframe &amp;&amp; iframe.tagName.toUpperCase() != 'IFRAME') { iframe = iframe.getElementsByTagName('iframe')[0]; } // When the player is not ready yet, add the event to a queue // Each frame_id is associated with an own queue. // Each queue has three possible states: // undefined = uninitialised / array = queue / 0 = ready if (!callPlayer.queue) callPlayer.queue = {}; var queue = callPlayer.queue[frame_id], domReady = document.readyState == 'complete'; if (domReady &amp;&amp; !iframe) { // DOM is ready and iframe does not exist. Log a message window.console &amp;&amp; console.log('callPlayer: Frame not found; id=' + frame_id); if (queue) clearInterval(queue.poller); } else if (func === 'listening') { // Sending the "listener" message to the frame, to request status updates if (iframe &amp;&amp; iframe.contentWindow) { func = '{"event":"listening","id":' + JSON.stringify(''+frame_id) + '}'; iframe.contentWindow.postMessage(func, '*'); } } else if (!domReady || iframe &amp;&amp; (!iframe.contentWindow || queue &amp;&amp; !queue.ready) || (!queue || !queue.ready) &amp;&amp; typeof func === 'function') { if (!queue) queue = callPlayer.queue[frame_id] = []; queue.push([func, args]); if (!('poller' in queue)) { // keep polling until the document and frame is ready queue.poller = setInterval(function() { callPlayer(frame_id, 'listening'); }, 250); // Add a global "message" event listener, to catch status updates: messageEvent(1, function runOnceReady(e) { if (!iframe) { iframe = document.getElementById(frame_id); if (!iframe) return; if (iframe.tagName.toUpperCase() != 'IFRAME') { iframe = iframe.getElementsByTagName('iframe')[0]; if (!iframe) return; } } if (e.source === iframe.contentWindow) { // Assume that the player is ready if we receive a // message from the iframe clearInterval(queue.poller); queue.ready = true; messageEvent(0, runOnceReady); // .. and release the queue: while (tmp = queue.shift()) { callPlayer(frame_id, tmp[0], tmp[1]); } } }, false); } } else if (iframe &amp;&amp; iframe.contentWindow) { // When a function is supplied, just call it (like "onYouTubePlayerReady") if (func.call) return func(); // Frame exists, send message iframe.contentWindow.postMessage(JSON.stringify({ "event": "command", "func": func, "args": args || [], "id": frame_id }), "*"); } /* IE8 does not support addEventListener... */ function messageEvent(add, listener) { var w3 = add ? window.addEventListener : window.removeEventListener; w3 ? w3('message', listener, !1) : (add ? window.attachEvent : window.detachEvent)('onmessage', listener); } } </code></pre> <p>Usage:</p> <pre><code>callPlayer("whateverID", function() { // This function runs once the player is ready ("onYouTubePlayerReady") callPlayer("whateverID", "playVideo"); }); // When the player is not ready yet, the function will be queued. // When the iframe cannot be found, a message is logged in the console. callPlayer("whateverID", "playVideo"); </code></pre> <h2>Possible questions (&amp; answers):</h2> <p><strong>Q</strong>: It doesn't work!<br> <strong>A</strong>: "Doesn't work" is not a clear description. Do you get any error messages? Please show the relevant code.</p> <p><strong>Q</strong>: I have embedded a YouTube video using <code>&lt;iframe src="http://www.youtube.com/embed/As2rZGPGKDY" /&gt;</code>but the function doesn't execute any function!<br> <strong>A</strong>: You have to add <code>?enablejsapi=1</code> at the end of your URL: <code>/embed/vid_id?enablejsapi=1</code>.</p> <p><strong>Q</strong>: I get error message "An invalid or illegal string was specified". Why?<br> <strong>A</strong>: The API doesn't function properly at a local host (<code>file://</code>). Host your (test) page online, or use <a href="http://jsfiddle.net" rel="noreferrer">JSFiddle</a>. Examples: See the links at the top of this answer.</p> <p><strong>Q</strong>: How did you know this?<br> <strong>A</strong>: I have spent some time to manually interpret the API's source. I concluded that I had to use the <a href="https://developer.mozilla.org/en/DOM/window.postMessage" rel="noreferrer"><code>postMessage</code></a> method. To know which arguments to pass, I created a Chrome extension which intercepts messages. The source code for the extension can be downloaded <a href="https://robwu.nl/postMessage-debugging.zip" rel="noreferrer">here</a>.</p> <p><strong>Q</strong>: What browsers are supported?<br> <strong>A</strong>: Every browser which supports <a href="http://caniuse.com/#feat=json" rel="noreferrer">JSON</a> and <a href="http://caniuse.com/#feat=x-doc-messaging" rel="noreferrer"><code>postMessage</code></a>. </p> <ul> <li>IE 8+</li> <li>Firefox 3.6+ (actually 3.5, but <code>document.readyState</code> was implemented in 3.6)</li> <li>Opera 10.50+</li> <li>Safari 4+</li> <li>Chrome 3+</li> </ul> <p>Related answer / implementation: <a href="https://stackoverflow.com/a/7866323/938089/jquery-fade-in-youtube-iframe-embed">Fade-in a framed video using jQuery</a><br> Full API support: <a href="https://stackoverflow.com/a/7988536/938089?listening-for-youtube-event-in-javascript-or-jquery)">Listening for Youtube Event in jQuery</a><br> Official API: <a href="https://developers.google.com/youtube/iframe_api_reference" rel="noreferrer">https://developers.google.com/youtube/iframe_api_reference</a> </p> <h3>Revision history</h3> <ul> <li>17 may 2012<br> Implemented <code>onYouTubePlayerReady</code>: <code>callPlayer('frame_id', function() { ... })</code>.<br> Functions are automatically queued when the player is not ready yet.</li> <li>24 july 2012<br> Updated and successully tested in the supported browsers (look ahead).</li> <li>10 october 2013 When a function is passed as an argument, <code>callPlayer</code> forces a check of readiness. This is needed, because when <code>callPlayer</code> is called right after the insertion of the iframe while the document is ready, it can't know for sure that the iframe is fully ready. In Internet Explorer and Firefox, this scenario resulted in a too early invocation of <code>postMessage</code>, which was ignored.</li> <li>12 Dec 2013, recommended to add <code>&amp;origin=*</code> in the URL.</li> <li>2 Mar 2014, retracted recommendation to remove <code>&amp;origin=*</code> to the URL.</li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload