2009-04-24 7 views
20

J'essaie actuellement d'utiliser l'API YouTube dans le cadre d'un plugin jQuery et j'ai rencontré un problème. De la façon dont l'API YT fonctionne, vous chargez le lecteur Flash et, quand il est prêt, il renvoie un appel à une fonction globale appelée onYouTubePlayerReady(playerId). Vous pouvez ensuite utiliser cet identifiant combiné avec getElementById(playerId) pour envoyer des appels javascript dans le lecteur flash (par exemple, player.playVideo();).Utilisation de l'API JavaScript de javascript avec jQuery

Vous pouvez attacher un écouteur d'événement au lecteur avec player.addEventListener('onStateChange', 'playerState'); qui enverra les modifications d'état à une autre fonction globale (dans ce cas, playerState). Le problème est que je ne suis pas sûr de savoir comment associer un changement d'état à un lecteur spécifique. Mon plugin jQuery peut heureusement attacher plus d'une vidéo à un sélecteur et attacher des événements à chacun, mais au moment où un état change, je perds la trace du joueur dans lequel il s'est produit.

J'espère que quelques exemples de code peuvent faire les choses un peu plus claires. Le code ci-dessous devrait fonctionner correctement dans n'importe quel fichier 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> 

Vous verrez le console.log() outputtin informations sur les changements d'état, mais, comme je l'ai dit, je ne sais pas comment dire quel joueur il est associé.

Quelqu'un a des idées pour contourner cela?

EDIT: Désolé, je devrais également mentionné que j'ai essayé d'encapsuler l'appel d'événement dans une fermeture. Dans cette situation, playerState ne reçoit jamais d'appel. Ce qui est très frustrant.

Répondre

23

Edit:

Apparemment appeler addEventListener sur l'objet player provoque le script à utiliser comme une chaîne dans une propriété XML qui est passé à l'objet flash - ce qui exclut les fermetures et autres, il est donc temps pour un old-school bidouille horrible:

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

Testé & travail!

+0

Ce fut ma première pensée aussi, mais cela ne fonctionne pas vraiment ici. playerState ne semble jamais être appelé. – Steerpike

+0

J'ai testé votre code comme-posté et onYouTubePlayerReady n'est jamais appelé – Greg

+0

Les vidéos jouent OK si – Greg

5

Im utilisant le plugin Jquery swfobject, SWFobject

Il est important d'ajouter & enablejsapi = 1 à la fin de la vidéo

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 doit être en dehors de $ (document).ready (function() pour se faire virer

+0

Bon appel sur le plugin! – grant

+1

"onYouTubePlayerReady doit être en dehors de $ (document) .ready (fonction() pour se faire virer" - vous m'avez sauvé la vie – Mustafa

+4

Une petite note: le code de fonction onYouTubePlayerReady() peut être * dans * le $ (document) .ready , mais il doit être * étendu * à la fenêtre/objet global en dehors de jQuery, donc la fonction devrait plutôt être définie comme telle: window.onYouTubePlayerReady (playerId) {} ​​ – TimKlimowicz

1

J'ai eu le même problème et j'ai essayé la réponse acceptée, cela n'a pas fonctionné pour moi, la fonction playerState() n'a jamais été appelée, mais elle m'a mis sur la bonne voie. ce que je fini par faire était le suivant:.

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

Il est assez méchant, mais il en est de l'état actuel de l'API JavaScript YouTube


Voici quelques autres codes utiles/méchant si vous utilisez n'importe quel type de modèle de prototypage avancé, ce qui vous permet de récupérer une "classe" la position de l'ID du lecteur 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

Ce n'était pas très clair pour moi. obtenir un mediaController "class"? – Volomike

+0

@Volomike c'est juste un objet JavaScript auto-défini utilisé pour aider à contrôler l'élément YouTube. – JoshNaro

0

Que diriez-vous quelque chose comme ceci:

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