2009-04-24 11 views
20

Próbuję obecnie korzystać z interfejsu API YouTube jako części wtyczki jQuery i mam do czynienia z pewnym problemem.Używanie javascript API Youtube z jQuery

Sposób działania apletu YT polega na tym, że ładujesz odtwarzacz flash i, gdy będzie gotowy, wyśle ​​połączenie do globalnej funkcji o nazwie onYouTubePlayerReady(playerId). Następnie możesz użyć tego identyfikatora w połączeniu z getElementById(playerId) do wysyłania wywołań javascript do Flash Playera (np. player.playVideo();).

Możesz dołączyć detektor zdarzeń do odtwarzacza z player.addEventListener('onStateChange', 'playerState');, który wyśle ​​wszelkie zmiany stanu do innej funkcji globalnej (w tym przypadku playerState).

Problem polega na tym, że nie jestem pewien, jak powiązać zmianę stanu z konkretnym graczem. Moja wtyczka jQuery może z powodzeniem dołączać więcej niż jeden film do selektora i dołączać zdarzenia do każdego z nich, ale w momencie, w którym stan rzeczywiście się zmienia, tracę informację o tym, który z graczy się wydarzył.

Mam nadzieję, że przykładowy kod może spowodować rzeczy nieco jaśniejsze. Poniższy kod powinien działać poprawnie w dowolnym pliku 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> 

Zobaczysz console.log() outputtin informacji o zmianach stanu, ale, jak już mówiłem, nie wiem jak to powiedzieć, który z graczy jest to związane z.

Ktoś ma jakieś przemyślenia na ten temat?

EDIT: Niestety, muszę również wspomnieć, że próbowałem owijania wywołanie zdarzenia w zamknięciu. W takim przypadku playerState nigdy nie zostanie wywołana. Co jest ekstra frustrujące.

Odpowiedz

23

Edit:

Widocznie nazywając addEventListener na obiekcie player wywołuje skrypt do wykorzystania jako ciąg we właściwości XML, który jest przekazywany do obiektu Flash - to wyklucza zamknięcia i tym podobne, więc jest czas na old-school brzydki Hack:

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); 
} 

Testowany & działa!

+0

To była moja pierwsza myśl też, ale faktycznie nie działa tutaj. playerState nie wydaje się nigdy być wywoływany. – Steerpike

+0

Przetestowałem Twój kod i opublikowałem go w serwisie YouTube. PlayerReady nigdy nie jest nazywane – Greg

+0

Filmy grają OK, ale – Greg

5

Im Używanie wtyczki jQuery SWFObject, SWFobject

Jest ważne, aby dodać & enablejsapi = 1 na końcu filmu

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 musi znajdować się poza $ (dokument).Gotowy (funkcja() do zwolnienia

+0

Dobre połączenie z wtyczką! – grant

+1

"onYouTubePlayerReady musi znajdować się poza $ (dokument) .ready (funkcja(), aby zostać zwolnionym" - uratowałeś mi życie – Mustafa

+4

Jedna mała uwaga: kod funkcji onYouTubePlayerReady() może być * w * $ (dokumencie) .ready , ale musi być * ograniczone * do okna/obiektu globalnego poza jQuery, więc funkcja musiałaby zostać zdefiniowana jako: window.onYouTubePlayerReady (playerId) {} ​​ – TimKlimowicz

1

Miałem ten sam problem i próbowałem akceptowanej odpowiedzi.Nie to działało dla mnie, funkcja playerState() nigdy nie była wywoływana, jednak ustawiła mnie na właściwej ścieżce. Co skończyło się robić to w ten sposób:.

// 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); 
} 

to dość przykre, ale tak jest obecny stan API YouTube JavaScript


Oto niektóre inne przydatne/code paskudny jeśli używasz wszelkiego rodzaju zaawansowane prototypy prototypów, co pozwala w zasadzie odzyskać "klasę" postawa z YouTube player ID:

// 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

Nie było to dla mnie zbyt jasne. zdobyć "klasę" mediaController? – Volomike

+0

@Volomike to po prostu samookreślony obiekt JavaScript używany do kontrolowania elementu YouTube. – JoshNaro

0

Jak o czymś tak:

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) 
})); 
Powiązane problemy