WIZ-CODE.blog

JavaScriptやAjaxをテーマとしたブログです。

*

jQueryプラグイン Text on YouTubeの不具合を訂正しました

   

以前作成した(というよりもう二年近く前なんですけど)YouTube動画を埋め込むjQueryプラグインについて、ユーザーの方から動作しないとのご指摘がありました。実際にデモページを確認してみると、動画自体は削除されていないかぎり読み込まれるものの、コントローラやコメントはまったく表示されず。いつからこんなことになったのかについてはまったく分かりません。 ⇒その件についてのやり取り 原因はプレイヤーのイベントであるonStateChangeが発生したときに、登録したコールバック関数がなぜか動作しないためでした。このプレイヤーオブジェクトのaddEventListenerは、コールバックを登録する第2引数に関数名の文字列しか受け取らない仕様だったのですが、例外的に文字列化したコードでもeval評価して実行していました。プラグインのコードもまたevalされるのを期待して書いていたのですが、それがいつのまにかeval評価しなくなり、関数名の文字列以外受け取らなくなったのです。 jquery.text-on-youtube.js v0.9(従来のバージョン)の566行目あたり
 
/* 第2引数に文字列化したコードを渡している */
yt.player.addEventListener('onStateChange', '(function(state) { youtubeStateObserver(state, "' + videoID + '"); })');
 
こうしなければならなかったのは、onStateChangeイベントが発生したとき、同一ページに複数のプレイヤーが存在したとき、イベントがどのプレイヤーで発生したのか探る手立てがなかったからです。のためその解決のために次のエントリを参考にしていました。⇒youtube javascript API onStateChangeが発生したplayerを特定する方法 しかし、前述のように最近になって、プレイヤーオブジェクトのaddEventListenereval評価しなくなったため、プラグインのコントローラなど多くの機能が停止しました。 その上、addEventListenerに指定する関数はグローバル名前空間になければいけませんでした。つまりwindow.xxxといった形で定義しなければならず、異なるプレイヤーでまったく同じコールバックが呼び出されてしまいます。そして、コールバックに渡される仮引数はプレイヤーの状態を表す数値のみで、プレイヤーIDは渡されません。プレイヤーの特定など元からできないわけです。 試行錯誤の末、下記にあるように各々のプレイヤーが初期化されるタイミングで、それぞれのプレイヤー専用の名前をつけたコールバックを無理やり作成して対策することにしました。 jquery.text-on-youtube.js v0.9.2538行目あたり
 
/* 本当はこんな風にして動的に変数名を決めたいのだけど、このやり方では無理 */
window.'youtubeStateObserver_' + videoID = function (state) {
........
........
/* しかし、ここがJavaScriptの柔軟なところ */
/* 連想配列を作るときのようにすれば、関数の変数名を動的に決められる */
window['youtubeStateObserver_' + videoID] = function (state) {
........
........
/* その後にイベントハンドラで先ほど動的に作った変数名を渡す */
yt.player.addEventListener('onStateChange', 'youtubeStateObserver_' + videoID);
 
ともかく、これでプレイヤーでイベントが発生したとき、プレイヤーごとに対応することができます。 五つあるデモページはすべて修正しました。プラグイン紹介ページの最新バージョン(version 0.9.2)を更新したので、ユーザーの方はご確認ください。 ⇒Text on YouTube – YouTube動画上にテキストを表示するjQueryプラグインデモページ – 複数の動画を埋め込む

 - JavaScript/Ajax , , , ,