web-dev-qa-db-fra.com

Fonction n'appelant pas dans un événement onclick

Je veux ajouter du code HTML à la fin de chaque lien youtube pour ouvrir le lecteur dans une litebox. C'est mon code jusqu'à présent:

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

Il fonctionne au point d'injecter du code HTML après le lien youtube, comme suit:

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

Mais lorsque je clique sur cette fonction, la fonction open_litebox() ne s'appelle pas. En regardant dans la console d'erreur, je peux voir une erreur qui dit open_litebox is not defined, mais je l'ai définie.

Je ne sais pas trop ce qui ne va pas ici, quelqu'un pourrait-il me donner un coup de main?

Merci.

27
Wen

C'est un problème courant lorsque vous commencez à utiliser jQuery. Le problème ici est que vous avez défini la fonction dans la portée de jQuery, ce qui signifie qu’elle n’est pas accessible simplement en l’appelant comme une fonction normale. Une solution à votre problème consiste à déplacer la définition de votre fonction en dehors de la fonction prête anonyme que vous avez écrite, comme suit:

$(document).ready(function() {

    // do your stuff here

});

// define your functions here 
function my_func() {

}

Oh, et je suggérerais de faire la même chose pour vos variables que vous avez définies. Déplacez-les également hors de votre fonction prête, car vous aurez les mêmes problèmes que vous avez rencontrés avec vos fonctions.

45
Simon H

Votre fonction open_litebox est dans la portée d'une autre fonction et n'est donc pas visible de manière globale. Au lieu de ce que vous faites, essayez d'utiliser .click():

Quelque chose dans ce sens:

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

De cette manière, vous devez générer des identifiants distincts pour chacun des liens. Vous pouvez également attribuer à chaque balise <img> un attribut class connu, puis le sélectionner à l'aide de $('.abc') (si la classe est abc) au lieu de $('#abc') et le faire en une étape (c.-à-d. en tant qu'appel séparé après votre $('a').each).

10
icyrock.com

Les autres réponses sont correctes: déplacer votre déclaration my_func en dehors de $(document).ready() résoudra votre problème, mais j'aimerais clarifier le raisonnement, car cela n'a rien à voir avec jQuery en particulier.

$(document).ready() est un gestionnaire d'événements auquel vous transmettez une fonction anonyme en tant que rappel à exécuter lorsque le navigateur vous informe que le document est prêt. 

Comme vous avez défini my_func dans la fonction de rappel, il n'est pas visible depuis la portée globale et ne peut donc pas être appelé depuis la propriété onclick de l'élément img de votre page.

En JavaScript, la portée est au niveau de la fonction. Tout ce qui ne fait pas partie d'une fonction est regroupé dans la portée globale.

10
Rob Sobers

La raison en est que open_litebox() est déclaré dans la fonction document.ready et n'est donc pas accessible à partir d'une étendue globale.

Vous pouvez déplacer la fonction en dehors de document.ready ou modifier le code pour attacher le gestionnaire onclick à l'aide de jQuery (qui référence directement la fonction):

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

Il existe un moyen beaucoup plus propre et plus jQuery d'attribuer l'action de clic.

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

Cela résout le problème de la portée décrit dans les autres réponses. Si vous devez appeler open_litebox () avec des paramètres, placez-le dans une fonction anonyme, comme je l'ai fait, sinon la fonction sera appelée et la valeur de retour sera transmise à l'action click. Sinon, sans paramètre à passer, l’affectation est plus simple:

$(this).click( open_litebox );
0
Surreal Dreams