2010-11-22 15 views
26

Quiero agregar algo de HTML al final de cada enlace de YouTube para abrir el reproductor en un litebox. Este es mi código hasta ahora:Función que no llama dentro de un evento onclick

$(document).ready(function() { 
    var valid_url = new RegExp('youtube\.com\/.*v=([a-zA-Z0-9_-]+)'); 
    var image_data = 'base64 encoded image'; 

    init(); 

    function init() { 
    $('a').each(function() { 
     if (valid_url.test($(this).attr('href'))) { 
     $(this).after(' <img src="' + image_data + '" onclick="open_litebox(\'hi\');" />'); 
     } 
    }); 
    } 

    function open_litebox(param) { 
    alert(param); 
    } 
}); 

Funciona hasta el punto en que inyecta algo de HTML después de que el enlace de youtube, así:

<img src="base 64 data" onclick="open_litebox('hi')"> 

Pero cuando hago clic en este la función open_litebox() no lo hace ser llamado. Al buscar en la consola de error, puedo ver un error que dice open_litebox is not defined, pero lo he definido.

No tengo ni idea de qué está pasando aquí, ¿podría alguien echarnos una mano?

Gracias.

Respuesta

43

Este es un problema común cuando comienza a trabajar con jQuery. El problema aquí es que ha definido la función dentro del alcance de jQuery, lo que significa que no se puede acceder simplemente llamándola como una función normal. Una solución a su problema es mover el definición de función fuera de la función lista anónima que escrito, así:

$(document).ready(function() { 

    // do your stuff here 

}); 

// define your functions here 
function my_func() { 

} 

Ah, y yo sugeriría que hacer lo mismo para las variables que se han definido. Muévelos fuera de tu función de listo también, porque tendrás los mismos problemas que con tus funciones.

+0

** Mucho ** mejor que ** no ** hacer que la función sea global, y conectarla con un manejo de eventos moderno, no controladores de 'onxyz'-attribute. –

10

Su función open_litebox está en el alcance de otra función, por lo que no es visible a nivel mundial. En lugar de lo que está haciendo, tratar de usar .click():

Algo a lo largo de estas líneas:

$(this).after(' <img src="' + image_data + '" id='abc' />'); 
$('#abc').click(open_litebox); 

que tendría que generar identificadores separados para cada uno de los enlaces que utilizan este Así, otra forma es hacer que cada una de las etiquetas <img> tenga un atributo conocido class y luego seleccionarlo usando $('.abc') (si la clase es abc) en lugar de $('#abc') y hacerlo en un solo paso (es decir como una llamada separada después de su $('a').each).

2

La razón es que open_litebox() se declara dentro de la función document.ready y, por lo tanto, no se puede acceder desde un ámbito global.

Puede mover la función fuera de document.ready, o bien, modificar el código para fijar el manejador onclick usando jQuery (que hace referencia a la función directamente):

var link = $(' <img src="' + image_data + '" />').click(function() { 
    open_litebox('hi'); 
}); 
$(this).after(link); 
0

Hay una cantidad más limpio y más forma jQuery para asignar la acción de hacer clic

function init() { 
    $('a').each(function() { 
     if(valid_url.test($(this).attr('href'))){ 
      $(this).click(function() { open_litebox('hi'); }); 
     } 
    }); 
} 

Esto resuelve el problema de alcance como se describe en las otras respuestas. Si necesita llamar a open_litebox() con parámetros, envuélvalo dentro de una función anónima como yo lo hice, o de lo contrario se llamará a la función y luego se pasará el valor de retorno a la acción de hacer clic.De lo contrario, sin parámetros para pasar, la asignación es más simple:

$(this).click(open_litebox); 
10

Las otras respuestas son correctas en que se mueve su declaración my_func fuera del $(document).ready() va a resolver su problema, pero me gustaría aclarar el razonamiento, porque no tiene nada que ver con jQuery en particular.

$(document).ready() es un controlador de eventos al que se le pasa una función anónima como una devolución de llamada que debe ejecutarse cuando el navegador le notifica que el documento está listo.

Dado que ha definido my_func dentro de la función de devolución de llamada, no es visible desde el alcance global y, por lo tanto, no puede invocarse desde la propiedad del elemento img de su página.

En JavaScript, el alcance está en el nivel de función. Todo lo que no está dentro de una función se agrupa en el alcance global.

Cuestiones relacionadas