Использование JavaScript API JavaScript с jQuery - PullRequest
20 голосов
/ 24 апреля 2009

В настоящее время я пытаюсь использовать API YouTube как часть плагина jQuery, и у меня возникла небольшая проблема.

Способ работы YT API заключается в том, что вы загружаете флеш-плеер и, когда он будет готов, он отправит вызов глобальной функции с именем onYouTubePlayerReady(playerId). Затем вы можете использовать этот идентификатор в сочетании с getElementById(playerId) для отправки вызовов javascript во флэш-плеер (т. Е. player.playVideo();).

Вы можете прикрепить прослушиватель событий к проигрывателю с помощью player.addEventListener('onStateChange', 'playerState');, который будет отправлять любые изменения состояния в другую глобальную функцию (в данном случае playerState).

Проблема в том, что я не уверен, как связать изменение состояния с конкретным игроком. Мой плагин jQuery может с радостью присоединять несколько селекторов к селектору и прикреплять события к каждому, но в тот момент, когда состояние действительно меняется, я теряю информацию о том, с каким плеером это произошло.

Я надеюсь, что пример кода может немного прояснить ситуацию. Приведенный ниже код должен нормально работать в любом html-файле.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="application/text+html;utf-8"/>

  <title>Sandbox</title>

  <link type="text/css" href="http://jqueryui.com/latest/themes/base/ui.all.css" rel="stylesheet" />
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
    google.load("jquery", "1.3.2");
    google.load("jqueryui", "1.7.0");
</script>
<script type="text/javascript" src="http://swfobject.googlecode.com/svn/tags/rc3/swfobject/src/swfobject.js"></script>
<script type="text/javascript">
(function($) {
    $.fn.simplified = function() {
        return this.each(function(i) {
            var params = { allowScriptAccess: "always" };
            var atts = { id: "ytplayer"+i };
            $div = $('<div />').attr('id', "containerplayer"+i);
            swfobject.embedSWF("http://www.youtube.com/v/QTQfGd3G6dg&enablejsapi=1&playerapiid=ytplayer"+i, 
                               "containerplayer"+i, "425", "356", "8", null, null, params, atts);
            $(this).append($div);
        });
    }
})(jQuery);
function onYouTubePlayerReady(playerId) {
    var player = $('#'+playerId)[0];
    player.addEventListener('onStateChange', 'playerState');
}
function playerState(state) {
    console.log(state);
}

$(document).ready(function() {
    $('.secondary').simplified();
});
</script>
</head>
<body>
    <div id="container">
        <div class="secondary">

        </div>
        <div class="secondary">

        </div>
        <div class="secondary">

        </div>
        <div class="secondary">

        </div>

    </div>
</body>

</html>

Вы увидите, что console.log () выводит информацию об изменениях состояния, но, как я уже сказал, я не знаю, как определить, с каким проигрывателем он связан.

У кого-нибудь есть мысли по поводу этого?

EDIT: Извините, я должен также упомянуть, что попытался обернуть вызов события в замыкание.

function onYouTubePlayerReady(playerId) {
    var player = $('#'+playerId)[0];
    player.addEventListener('onStateChange', function(state) { 
    return playerState(state, playerId, player); } );
}

function playerState(state, playerId, player) {
    console.log(state);
    console.log(playerId);
}

В этой ситуации playerState никогда не вызывается. Что очень расстраивает.

Ответы [ 5 ]

23 голосов
/ 24 апреля 2009

Edit:

Видимый вызов addEventListener для объекта player приводит к тому, что скрипт используется в качестве строки в свойстве XML, которое передается во флэш-объект - это исключает замыкания и тому подобное, поэтому пришло время для старой школы безобразный хак:

function onYouTubePlayerReady(playerId) {
    var player = $('#'+playerId)[0];

    player.addEventListener('onStateChange', '(function(state) { return playerState(state, "' + playerId + '"); })' );
}

function playerState(state, playerId) {
    console.log(state);
    console.log(playerId);
}

Проверено и работает!

5 голосов
/ 22 сентября 2009

Я использую плагин Jquery SWFobject, SWFobject

Важно добавить & enablejsapi = 1 в конце видео

HTML:

<div id="embedSWF"></div>

Jquery:

             $('#embedSWF').flash({ 
                swf: 'http://www.youtube.com/watch/v/siBoLc9vxac',
                params: { allowScriptAccess: "always"},   
                flashvars: {enablejsapi: '1', autoplay: '0', allowScriptAccess: "always", id: 'ytPlayer' },   
                height: 450,   width: 385 });

function onYouTubePlayerReady(playerId) {
                $('#embedSWF').flash(function(){this.addEventListener("onStateChange", "onPlayerStateChange")});
            }
function onPlayerStateChange(newState) {
                   alert(newState);
                 }

onYouTubePlayerReady должно быть за пределами $ (document) .ready (function () для запуска

1 голос
/ 08 июля 2010

У меня была такая же проблема, и я попробовал принятый ответ. Это не сработало для меня; функция playerState () никогда не вызывалась. Тем не менее, это поставило меня на правильный путь. Я закончил тем, что сделал:

// Within my mediaController "class"
window["dynamicYouTubeEventHandler" + playerID] = function(state) { onYouTubePlayerStateChange(state, playerID); }
  embedElement.addEventListener("onStateChange", "dynamicYouTubeEventHandler" + playerID);
// End mediaController class

// Global YouTube event handler
function onYouTubePlayerStateChange(state, playerID) {
  var mediaController = GetMediaControllerFromYouTubeEmbedID(playerID);
  mediaController.OnYouTubePlayerStateChange(state);
}

Это довольно неприятно, но и текущее состояние JavaScript API YouTube.


Вот еще один полезный / неприятный код, если вы используете какие-либо сложные шаблоны прототипирования. По сути, это позволяет вам получить экземпляр «класса» из идентификатора игрока YouTube:

// Within my mediaController "class"
// The containerJQElement is the jQuery wrapped parent element of the player ID
// Its ID is the same as the player ID minus "YouTubeEmbed".
var _self = this;
containerJQElement.data('mediaController', _self);
// End mediaController class

// Global YouTube specific functions
function GetMediaControllerFromYouTubeEmbedID(embedID) {      
  var containerID = embedID.replace('YouTubeEmbed', '');
  var containerJQObject = $("#" + containerID);
  return containerJQObject.data('mediaController');      
}

function onYouTubePlayerReady(playerId) {
  var mediaController = GetMediaControllerFromYouTubeEmbedID(playerId);
  mediaController.OnYouTubeAPIReady();
}
0 голосов
/ 07 октября 2011

Как насчет примерно так:

var closureFaker = function (func, scope) {
    var functionName = 'closureFake_' + (((1+Math.random())*0x10000000)|0).toString(16);
    window[functionName] = function () {
        func.apply(scope || window, arguments);
    };
    console.log('created function:', functionName, window[functionName]);
    return functionName;
};

ytplayer.addEventListener("onStateChange", closureFaker(function () {
    //place your logic here
    console.log('state change', arguments)
}));
0 голосов
/ 19 июня 2009

Вот хорошая статья, в которой рассказывается о создании класса для обёртывания отдельного игрока, включая отправку событий отдельным объектам, используя подход, аналогичный описанному в предыдущем ответе.

http://blog.jcoglan.com/2008/05/22/dispatching-youtube-api-events-to-individual-javascript-objects/

...