I'm trying to use the Youtube Iframe API inside a module definded with Require JS. As this API is loaded async and calls a function once is loaded, I used a requireJS plugin called "async", that worked before with google maps api.
However, this time something isn't working. My module starts this way:
define(['text!fmwk/widgets/video/video.html','fmwk/utils/browser','async!http://www.youtube.com/iframe_api'], function (videoTpl,root) { ... });
and chrome console fires this error:
Uncaught Error: Load timeout for modules: async!http://www.youtube.com/iframe_api_unnormalized3,async!http://www.youtube.com/iframe_api
http://requirejs.org/docs/errors.html#timeout
If I don't use async plugin the object YT or its functions are undefinded, and the same happens if I download the API code. The API is loaded sometimes if I put an script tag in the head tag of the html file. All this is expected, but I don't understand because async plugin fails.
Thank you for your attention and help :)
I'm not familiar with the async
requireJS plugin, but here's some sample code (taken from YouTube Direct Lite) that loads the iframe API asynchronously from within a requireJS module named player
. It's using jQuery to do the actual library loading, though.
define(['jquery'], function($) {
var player = {
playVideo: function(container, videoId) {
if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
window.onYouTubeIframeAPIReady = function() {
player.loadPlayer(container, videoId);
};
$.getScript('//www.youtube.com/iframe_api');
} else {
player.loadPlayer(container, videoId);
}
},
loadPlayer: function(container, videoId) {
new YT.Player(container, {
videoId: videoId,
width: 356,
height: 200,
// For a list of all parameters, see:
// https://developers.google.com/youtube/player_parameters
playerVars: {
autoplay: 1,
controls: 0,
modestbranding: 1,
rel: 0,
showinfo: 0
}
});
}
};
return player;
});
After some research and being unstatisfied with the other answers, I have solved this for this exact case plus possible others without the extra fluff, by extending the require async! plugin to support a named callback which then makes sure the module code is only executed once the API is fully loaded.
The core problem seems to be, that YouTube Iframe API does not allow you to configure the callback's name, but dictates it to be "onYouTubeIframeAPIReady" which our small upgrade to the async plugin solves. This solution still uses the global window.YT, but works without jQuery.
require(
['async!//www.youtube.com/iframe_api!undefined:onYouTubeIframeAPIReady'],
function() {
// this codes executes your code once YouTube Iframe API is loaded and ready
player = new YT.Player({ ... });
}
);
Also works with inline require calls:
define([], function () {
// .. some of your other code here
require(['async!//www.youtube.com/iframe_api!undefined:onYouTubeIframeAPIReady'], function () {
// this codes executes your code once YouTube Iframe API is loaded and ready
player = new YT.Player({ ... });
});
});
The code is in my opinion much more clean than any seen before. Also, the performance improvements by loading the API in the very last moment were massive, especially when used with dozens of players. The API will of course only be loaded once and cached as usual.
Upgraded !async plugin: https://github.com/mhrisse/requirejs-plugins/blob/master/src/async.js
Pull request for upgraded !async plugin: https://github.com/millermedeiros/requirejs-plugins/pull/39
The upgrade should be fully backward compatible, that's why there is this rather ugly undefined as the first plugin parameter. Any ideas how to make this more beautiful and simple are very welcome.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With