{"id":2811,"date":"2014-02-17T11:17:25","date_gmt":"2014-02-17T11:17:25","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/02\/17\/youtube-iframe-api-how-do-i-control-a-iframe-player-thats-already-in-the-html-collection-of-common-programming-errors\/"},"modified":"2014-02-17T11:17:25","modified_gmt":"2014-02-17T11:17:25","slug":"youtube-iframe-api-how-do-i-control-a-iframe-player-thats-already-in-the-html-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/02\/17\/youtube-iframe-api-how-do-i-control-a-iframe-player-thats-already-in-the-html-collection-of-common-programming-errors\/","title":{"rendered":"YouTube iframe API: how do I control a iframe player that&#39;s already in the HTML?-Collection of common programming errors"},"content":{"rendered":"<p><em><strong>Fiddle Links: Source code &#8211; Preview &#8211; Small version<\/strong><\/em><br \/>\nUpdate: 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 Listening for Youtube Event in jQuery<\/strong><\/p>\n<p>As a result of a deep code analysis, I&#8217;ve created a function: <code>function callPlayer<\/code> requests a function call on any framed YouTube video. See the YouTube Api reference to get a full list of possible function calls. Read the comments at the source code for an explanation.<\/p>\n<p>On 17 may 2012, the code size was doubled in order to take care of the player&#8217;s ready state. If you need a compact function which does not deal with the player&#8217;s ready state, see http:\/\/jsfiddle.net\/8R5y6\/.<\/p>\n<pre><code>\/**\n * @author       Rob W \n * @website      http:\/\/stackoverflow.com\/a\/7513356\/938089\n * @version      20120724\n * @description  Executes function on a framed YouTube video (see website link)\n *               For a full list of possible functions, see:\n *               https:\/\/developers.google.com\/youtube\/js_api_reference\n * @param String frame_id The id of (the div containing) the frame\n * @param String func     Desired function to call, eg. \"playVideo\"\n *        (Function)      Function to call when the player is ready.\n * @param Array  args     (optional) List of arguments to pass to function func*\/\nfunction callPlayer(frame_id, func, args) {\n    if (window.jQuery &amp;&amp; frame_id instanceof jQuery) frame_id = frame_id.get(0).id;\n    var iframe = document.getElementById(frame_id);\n    if (iframe &amp;&amp; iframe.tagName.toUpperCase() != 'IFRAME') {\n        iframe = iframe.getElementsByTagName('iframe')[0];\n    }\n\n    \/\/ When the player is not ready yet, add the event to a queue\n    \/\/ Each frame_id is associated with an own queue.\n    \/\/ Each queue has three possible states:\n    \/\/  undefined = uninitialised \/ array = queue \/ 0 = ready\n    if (!callPlayer.queue) callPlayer.queue = {};\n    var queue = callPlayer.queue[frame_id],\n        domReady = document.readyState == 'complete';\n\n    if (domReady &amp;&amp; !iframe) {\n        \/\/ DOM is ready and iframe does not exist. Log a message\n        window.console &amp;&amp; console.log('callPlayer: Frame not found; id=' + frame_id);\n        if (queue) clearInterval(queue.poller);\n    } else if (func === 'listening') {\n        \/\/ Sending the \"listener\" message to the frame, to request status updates\n        if (iframe &amp;&amp; iframe.contentWindow) {\n            func = '{\"event\":\"listening\",\"id\":' + JSON.stringify(''+frame_id) + '}';\n            iframe.contentWindow.postMessage(func, '*');\n        }\n    } else if (!domReady || iframe &amp;&amp; (!iframe.contentWindow || queue &amp;&amp; !queue.ready)) {\n        if (!queue) queue = callPlayer.queue[frame_id] = [];\n        queue.push([func, args]);\n        if (!('poller' in queue)) {\n            \/\/ keep polling until the document and frame is ready\n            queue.poller = setInterval(function() {\n                callPlayer(frame_id, 'listening');\n            }, 250);\n            \/\/ Add a global \"message\" event listener, to catch status updates:\n            messageEvent(1, function runOnceReady(e) {\n                var tmp = JSON.parse(e.data);\n                if (tmp &amp;&amp; tmp.id == frame_id &amp;&amp; tmp.event == 'onReady') {\n                    \/\/ YT Player says that they're ready, so mark the player as ready\n                    clearInterval(queue.poller);\n                    queue.ready = true;\n                    messageEvent(0, runOnceReady);\n                    \/\/ .. and release the queue:\n                    while (tmp = queue.shift()) {\n                        callPlayer(frame_id, tmp[0], tmp[1]);\n                    }\n                }\n            }, false);\n        }\n    } else if (iframe &amp;&amp; iframe.contentWindow) {\n        \/\/ When a function is supplied, just call it (like \"onYouTubePlayerReady\")\n        if (func.call) return func();\n        \/\/ Frame exists, send message\n        iframe.contentWindow.postMessage(JSON.stringify({\n            \"event\": \"command\",\n            \"func\": func,\n            \"args\": args || [],\n            \"id\": frame_id\n        }), \"*\");\n    }\n    \/* IE8 does not support addEventListener... *\/\n    function messageEvent(add, listener) {\n        var w3 = add ? window.addEventListener : window.removeEventListener;\n        w3 ?\n            w3('message', listener, !1)\n        :\n            (add ? window.attachEvent : window.detachEvent)('onmessage', listener);\n    }\n}\n<\/code><\/pre>\n<p>Usage:<\/p>\n<pre><code>callPlayer(\"whateverID\", function() {\n    \/\/ This function runs once the player is ready (\"onYouTubePlayerReady\")\n    callPlayer(\"whateverID\", \"playVideo\");\n});\n\/\/ When the player is not ready yet, the function will be queued.\n\/\/ When the iframe cannot be found, a message is logged in the console.\ncallPlayer(\"whateverID\", \"playVideo\");\n<\/code><\/pre>\n<h2>Possible questions (&amp; answers):<\/h2>\n<p><strong>Q<\/strong>: It doesn&#8217;t work!<br \/>\n<strong>A<\/strong>: &#8220;Doesn&#8217;t work&#8221; is not a clear description. Do you get any error messages? Please show the relevant code.<\/p>\n<p><strong>Q<\/strong>: I have embedded a YouTube video using but the function doesn&#8217;t execute any function!<br \/>\n<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>\n<p><strong>Q<\/strong>: I get error message &#8220;An invalid or illegal string was specified&#8221;. Why?<br \/>\n<strong>A<\/strong>: The API doesn&#8217;t function properly at a local host (<code>file:\/\/<\/code>). Host your (test) page online, or use JSFiddle. Examples: See the links at the top of this answer.<\/p>\n<p><strong>Q<\/strong>: How did you know this?<br \/>\n<strong>A<\/strong>: I have spent some time to manually interpret the API&#8217;s source. I concluded that I had to use the <code>postMessage<\/code> method. To know which arguments to pass, I created a Chrome extension which intercepts messages. The source code for the extension can be downloaded here.<\/p>\n<p><strong>Q<\/strong>: What browsers are supported?<br \/>\n<strong>A<\/strong>: Every browser which supports JSON and <code>postMessage<\/code>.<\/p>\n<ul>\n<li>IE 8+<\/li>\n<li>Firefox 3.6+ (actually 3.5, but <code>document.readyState<\/code> was implemented in 3.6)<\/li>\n<li>Opera 10.50+<\/li>\n<li>Safari 4+<\/li>\n<li>Chrome 3+<\/li>\n<\/ul>\n<p>Related answer \/ implementation: Fade-in a framed video using jQuery<br \/>\nFull API support: Listening for Youtube Event in jQuery<\/p>\n<h3>Revision history<\/h3>\n<ul>\n<li>17 may 2012<br \/>\nImplemented <code>onYouTubePlayerReady<\/code>: <code>callPlayer('frame_id', function() { ... })<\/code>.<br \/>\nFunctions are automatically queued when the player is not ready yet.<\/li>\n<li>24 july 2012<br \/>\nUpdated and successully tested in the supported browsers (look ahead).<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Fiddle Links: Source code &#8211; Preview &#8211; Small version Update: This small function will only execute code in a single direction. If you want full support (eg event listeners \/ getters), have a look at Listening for Youtube Event in jQuery As a result of a deep code analysis, I&#8217;ve created a function: function callPlayer [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2811","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/2811","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=2811"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/2811\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=2811"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=2811"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=2811"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}