Я работаю с API iFrame YouTube, чтобы вставлять несколько видео на страницу. Документация здесь: https://developers.google.com/youtube/iframe_api_reference#RequirementsБезопасное определение переменных для общедоступных функций обратного вызова в javascript
Таким образом, вы загрузите API асинхронно, используя следующий фрагмент кода:
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
После загрузки API запускает встроенную функцию обратного вызова onYouTubePlayerAPIReady
.
Дополнительный контекст: Я определяю файл библиотеки для этого в Google Closure. Я предоставляю пространство имен: goog.provide('yt.video');
Затем я использую goog.exportSymbol
, чтобы API мог найти эту функцию. Все работает отлично.
Мой вызов состоит в том, что я хотел бы передать 2 переменные функции обратного вызова. Есть ли способ сделать это без определения этих 2 переменных в контексте объекта window
?
goog.provide('yt.video');
goog.require('goog.dom');
yt.video = function(videos, locales) {
this.videos = videos;
this.captionLocales = locales;
this.init();
};
yt.video.prototype.init = function() {
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
};
/*
* Callback function fired when YT API is ready
* This is exported using goog.exportSymbol in another file and
* is being fired by the API properly.
*/
yt.video.prototype.onPlayerReady = function(videos, locales) {
window.console.log('this :' + this); //logs window
window.console.log('this.videos : ' + this.videos); //logs undefined
/*
* Video settings from Django variable
*/
for(i=0; i<this.videos.length; i++) {
var playerEvents = {};
var embedVars = {};
var el = this.videos[i].el;
var playerVid = this.videos[i].vid;
var playerWidth = this.videos[i].width;
var playerHeight = this.videos[i].height;
var captionLocales = this.videos[i].locales;
if(this.videos[i].playerVars)
var embedVars = this.videos[i].playerVars;
}
if(this.videos[i].events) {
var playerEvents = this.videos[i].events;
}
/*
* Show captions by default
*/
if(goog.array.indexOf(captionLocales, 'es') >= 0) {
embedVars.cc_load_policy = 1;
};
new YT.Player(el, {
height: playerHeight,
width: playerWidth,
videoId: playerVid,
events: playerEvents,
playerVars: embedVars
});
};
};
Чтобы инициализировать это, я в настоящее время с помощью следующих пределов самостоятельного выполнения анонимной функции:
var videos = [
{"vid": "video_id", "el": "player-1", "width": 640, "height": 390, "locales": ["es", "fr"], "events": {"onStateChange": stateChanged}},
{"vid": "video_id", "el": "player-2", "locales": ["es", "fr"], "width": 640, "height": 390}
];
var locales = ['es'];
var videoTemplate = new yt.video(videos, locales);
Спасибо за ваш ответ! Это умная идея. Если бы я хотел избежать изменения окна для этого, можете ли вы придумать какое-либо другое решение? Думаю, я застрял в этом подходе, если API предполагает, что window.onYouTubePlayerAPReady, правильно? – djreed
Да, я думаю, что если API ожидает такого определения, возможно, не будет другого подхода, о котором я могу думать. Если вас беспокоит загрязнение глобального пространства имен (в этом случае окно), вы всегда можете свернуть значение onYouTubePlayerAPIReady после выполнения задания, то есть window.onYouTubePlayerAPIReady = null в качестве последней строки внутри метода onYouTubePlayerAPIReady –