2012-09-23 19 views
6

Necessario per le funzioni di callback di onStateChange su youtube api //!crea una funzione javascript a livello di programmazione

Voglio creare a livello di codice le funzioni che ascolteranno l'evento "onStateChange" emesso da diversi player di youtube. Aggiungendo l'ascoltatore funziona già:

function onYouTubePlayerReady(playerId) { 
    var ytpStateManager = playerId +"_StateManager"; 
    document.getElementById(playerId).addEventListener("onStateChange", ytpStateManager); 
... 

La funzione Ho bisogno di creare in base alla variabile playerid ("ytp_1", "ytp_2", ...) è

function ytpStateManager(newState) { 
    ytpStateHelper(playerId , newState); 
} 

Così il risultato per la playerid "ytp_1" sarebbe simile a questa:

function ytp_1_StateManager(newState) { 
    ytpStateHelper("ytp_1", newState); 
} 

funziona anche, ma in questo momento ho bisogno di aggiungere manualmente per ogni giocatore, che non è quello che mi serve. Voglio crearli automaticamente quando un nuovo giocatore invia un evento readyState.

Il mio problema è che sembra che queste funzioni debbano essere funzioni globali per funzionare correttamente. Ho provato diverse opzioni per giorni ora. Il mio problema è che non so come (se c'è un modo) per definire una funzione globale, incl. il nome della funzione, a livello di programmazione, basato su un'altra variabile.

È un peccato che l'ytp non emetta un evento che include lo stato AND il giocatore/obiettivo. Renderebbe le cose molto più semplici Tutto questo è fondamentalmente la soluzione perché ho bisogno di tutto per fare cose su tutti gli stati.

Se c'è un modo migliore/più semplice, PER FAVORE fammi sapere :) In caso contrario, una soluzione per questa domanda è altamente gradita.

Forse c'è un modo per reindirizzare l'evento, per renderlo più "accessibile"?

Ho letto nella specifica che .addEventListener accetta anche un oggetto, quindi ho provato a associare l'evento a un oggetto dedicato. Ma di nuovo, non è stato attivato. Si sente come ho provato tutto ...

UPDATE Sono ora di passare al giocatore iframe (da swfobject) perché quella fornisce un evento che comprende playerid e lo stato: D Yeahhh !! Dopo aver passato una settimana con il giocatore sbagliato, questo sembra un grande progresso. Sembra anche che tu voglia che usiamo il player iframe che può usare dinamicamente html5 quando supportato.

risposta

4

Si crea una funzione che restituisce una funzione:

function createStateManager(playerId) { 
    return function (newState) { 
     ytpStateHelper(playerId , newState); 
    } 
} 

Poi si chiama il proprio stabilimento funzione quando si imposta il listener di eventi:

var player = document.getElementById(playerId); 
player.addEventListener("onStateChange", createStateManager(playerId)); 

DEBUGGING

Non sono sicuro del perché non funzioni, ma eccolo qui un suggerimento per il debug. Sospetto che potresti non ricevere il numero playerId sul tuo gestore onYouTubePlayerReady.

function onYouTubePlayerReady(playerId) { 
    console.log('Player ready. The player id is: ' + playerId); 
    var ytpStateManager = playerId +"_StateManager"; 
    var player = document.getElementById(playerId); 
    player.addEventListener("onStateChange", createStateManager(playerId)); 
} 

function createStateManager(playerId) { 
    return function (newState) { 
     console.log('State changed for player ' + playerId + '. New state is ' + newState); 
     ytpStateHelper(playerId , newState); 
    } 
} 

Puoi provare a farlo e pubblicare quello che ricevi da entrambe le chiamate console.log?

+0

Ho provato questo prima e ora di nuovo ma non funziona per me. Il punto è nel momento in cui "createStateManager" è chiamato "playerId" e le variabili "ytpStateHelper" provengono dalla funzione genitore, ma il newState non è definito al momento in quanto questo sarà lo stato ytp quando l'evento si innesca. –

+0

Dovrebbe funzionare ... Hai provato l'ultima versione che ho postato (ho modificato il codice subito dopo la pubblicazione). – bfavaretto

+0

Quando richiamo la fabbrica su una modifica di stato, ciò comporterà molte funzioni, ma nessuna viene attivata. Il callback deve essere un nome di funzione e una funzione con questo nome deve essere creata automaticamente. Altrimenti il ​​trigger non funzionerà come ho fatto per giorni. Testato, non funziona. Ora sto testando sth. in quella direzione –

0
window["foo"+"bar"] = function(){ console.log("foobar is called"); } 
+0

Questo nome lo nomina in modo programmatico, non crea una funzione che ha un comportamento definito a livello di programmazione, che è ciò che il poster sta chiedendo. –

+0

in modo da inserirlo nella funzione! Le risposte non devono essere al 100% di ciò che l'utente chiede. Inoltre, questo metodo non è eccezionale poiché sta invadendo lo spazio dei nomi. In realtà non dovrebbe essere funzioni separate, ma l'unica funzione che può gestire più casi. – epascarello

+0

Come menzionato in un commento per bfavaretto, questo non funzionerà. Per qualche motivo, "addEventListener" non può gestire un riferimento a [variabile] di finestra. Dovrebbe funzionare, ho provato più di due volte, non è così. –

2

1) E 'possibile creare oggetto Function new Function([params], "BODY") Quindi è possibile combinare il corpo della funzione come variabile stringa e messo in come il corpo

Esempio: var twoNumAverage = new Function ("x", " y", "ritorno (x + y)/2") console.log (twoNumAverage (3,7))

2) e di nuovo può creare dinamicamente un nome e CORPO

Esempio

var globalObject ={}; 
var nameFn ='MyNewFunction'; 

var createFn = function(object,functionName, Body){ 
    object[functionName]= new Function(Body); 
} 

createFn(globalObject,nameFn,"return (arguments[0] + arguments[1])/2"); 

È possibile chiamare il vostro nuova funzione:

globalObject[nameFn](10,20); 

Risultato: 15

Si prega di notare che nel corpo vostra funzione è possibile ottenere params tramite raccolta arguments

+0

Grazie per l'idea ma il problema è che ho bisogno di definire a livello di codice la funzione NOME. Basato sulla funzione chiamata, so che ytp ha chiamato. Ho appena controllato l'API di iframe e sembra che uno sia migliore in quanto l'evento fornisce state e playerId, che è ciò di cui avevo bisogno. –

+0

Si prega di consultare l'aggiornamento, spero che questo ti aiuti –

0

Ecco un modo per creare una funzione proxy denominata che esegua un'altra funzione con il contesto fornito dall'utente.

function createNamedProxy(name, fn, context) { 
    var template = [ 
      '(function @name() {', 
      ' @name.fn.apply(@name.context || window, arguments);', 
      '})' 
     ].join('').replace(/@name/g, name), 

    result = eval(template); 
    result.fn = fn; 
    result.context = context; 

    return result; 
} 

// Example Usage 
var anonymous = function() { alert(document === this); }, 
    named = createNamedProxy('Named', anonymous, document); 

// Will alert 'true' 
named(); 

La soluzione di cui sopra crea una funzione che può creare e restituire una funzione denominata che ha eseguito tutto ciò che vuoi. Se non si fornisce il contesto, assumerà l'oggetto finestra proprio come farebbe una normale funzione anonima. Per creare la soluzione che avresti voluto fare:

var varName = 'ytp_1'; 
window[varName + '_StateManager'] = 
    createNamedProxy(varName + '_StateManager', function(newState) { 
     ytpStateHelper(varName, newState); 
    }); 

Dove varName potrebbe essere un qualsiasi prefisso programmatico che desideri. Quando si richiama ytp_1_StateManager() si passa il valore newState e il codice chiama ytpStateHelper con il nome della variabile e il newState.

Spero che questo aiuti.

Problemi correlati