115 votes

Uncaught ReferenceError : la fonction n'est pas définie avec onclick

J'essaie de faire un usercript pour un site web permettant d'ajouter des émoticônes personnalisées. Cependant, je reçois beaucoup d'erreurs.

Voici la fonction :

function saveEmotes() {
    removeLineBreaks();
    EmoteNameLines = EmoteName.value.split("\n");
    EmoteURLLines = EmoteURL.value.split("\n");
    EmoteUsageLines = EmoteUsage.value.split("\n");

    if (EmoteNameLines.length == EmoteURLLines.length && EmoteURLLines.length == EmoteUsageLines.length) {
        for (i = 0; i < EmoteURLLines.length; i++) {
            if (checkIMG(EmoteURLLines[i])) {
                localStorage.setItem("nameEmotes", JSON.stringify(EmoteNameLines));
                localStorage.setItem("urlEmotes", JSON.stringify(EmoteURLLines));
                localStorage.setItem("usageEmotes", JSON.stringify(EmoteUsageLines));
                if (i == 0) {
                    console.log(resetSlot());
                }
                emoteTab[2].innerHTML += '<span style="cursor:pointer;" onclick="appendEmote(\'' + EmoteUsageLines[i] + '\')"><img src="' + EmoteURLLines[i] + '" /></span>';
            } else {
                alert("The maximum emote(" + EmoteNameLines[i] + ") size is (36x36)");
            }
        }
    } else {
        alert("You have an unbalanced amount of emote parameters.");
    }
}

Le site span de l'étiquette onclick appelle cette fonction :

function appendEmote(em) {
    shoutdata.value += em;
}

Chaque fois que je clique sur un bouton qui a un onclick j'obtiens cette erreur :

Uncaught ReferenceError : la fonction n'est pas définie.

Mise à jour

J'ai essayé d'utiliser :

emoteTab[2].innerHTML += '<span style="cursor:pointer;" id="'+ EmoteNameLines[i] +'"><img src="' + EmoteURLLines[i] + '" /></span>';
document.getElementById(EmoteNameLines[i]).addEventListener("click", appendEmote(EmoteUsageLines[i]), false);

Mais j'ai eu un undefined erreur.

Voici le script .

J'ai essayé de faire cela pour tester si les écouteurs fonctionnent et ils ne le font pas pour moi :

emoteTab[2].innerHTML = '<td class="trow1" width="12%" align="center"><a id="togglemenu" style="cursor: pointer;">Custom Icons</a></br><a style="cursor: pointer;" id="smilies" onclick=\'window.open("misc.php?action=smilies&amp;popup=true&amp;editor=clickableEditor","Smilies","scrollbars=yes, menubar=no,width=460,height=360,toolbar=no");\' original-title="">Smilies</a><br><a style="cursor: pointer;" onclick=\'window.open("shoutbox.php","Shoutbox","scrollbars=yes, menubar=no,width=825,height=449,toolbar=no");\' original-title="">Popup</a></td></br>';
document.getElementById("togglemenu").addEventListener("click", changedisplay,false);

167voto

Brock Adams Points 36841

Ne jamais utiliser .onclick() ou des attributs similaires à partir d'un script utilisateur ! (C'est aussi mauvaise pratique dans une page web régulière ).

La raison en est que les scripts utilisateurs opèrent dans un bac à sable ("monde isolé"), et que onclick opère dans la portée de la page cible et ne peut pas voir les fonctions que votre script crée.

Utilisez toujours addEventListener() Doc (ou une fonction de bibliothèque équivalente, comme jQuery .on() ).

Donc au lieu d'un code comme :

something.outerHTML += '<input onclick="resetEmotes()" id="btnsave" ...>'

Vous utiliseriez :

something.outerHTML += '<input id="btnsave" ...>'

document.getElementById ("btnsave").addEventListener ("click", resetEmotes, false);

Pour la boucle, vous ne pouvez pas passer des données à un écouteur d'événement comme ça See le doc . De plus, chaque fois que vous changez innerHTML comme ça, vous détruisez les écouteurs d'événements précédents !

Sans refactoriser beaucoup votre code, vous pouvez passer des données avec des attributs de données. Utilisez donc un code comme celui-ci :

for (i = 0; i < EmoteURLLines.length; i++) {
    if (checkIMG (EmoteURLLines[i])) {
        localStorage.setItem ("nameEmotes", JSON.stringify (EmoteNameLines));
        localStorage.setItem ("urlEmotes", JSON.stringify (EmoteURLLines));
        localStorage.setItem ("usageEmotes", JSON.stringify (EmoteUsageLines));
        if (i == 0) {
            console.log (resetSlot ());
        }
        emoteTab[2].innerHTML  += '<span style="cursor:pointer;" id="' 
                                + EmoteNameLines[i] 
                                + '" data-usage="' + EmoteUsageLines[i] + '">'
                                + '<img src="' + EmoteURLLines[i] + '" /></span>'
                                ;
    } else {
        alert ("The maximum emote (" + EmoteNameLines[i] + ") size is (36x36)");
    }
}
//-- Only add events when innerHTML overwrites are done.
var targetSpans = emoteTab[2].querySelectorAll ("span[data-usage]");
for (var J in targetSpans) {
    targetSpans[J].addEventListener ("click", appendEmote, false);
}

Où appendEmote est comme :

function appendEmote (zEvent) {
    //-- this and the parameter are special in event handlers.  see the linked doc.
    var emoteUsage  = this.getAttribute ("data-usage");
    shoutdata.value += emoteUsage;
}

AVERTISSEMENTS :

  • Votre code réutilise le même id pour plusieurs éléments. Ne faites pas cela, c'est invalide. Un ID donné ne doit apparaître qu'une seule fois par page.
  • Chaque fois que vous utilisez .outerHTML o .innerHTML Si vous n'êtes pas en mesure de le faire, vous pouvez détruire tous les gestionnaires d'événements sur les nœuds concernés. Si vous utilisez cette méthode, prenez garde à ce fait.

16voto

Assurez-vous que vous utilisez le module Javascript ou non ! si vous utilisez des modules js6, vos attributs d'événements html ne fonctionneront pas. Dans ce cas, vous devez faire passer votre fonction de la portée globale à la portée du module. Ajoutez simplement ceci à votre fichier javascript : window.functionName= functionName;

exemple :

<h1 onClick="functionName">some thing</h1>

6voto

Alferd Nobel Points 336

J'ai résolu ce problème dans angular avec (click) = "someFuncionName()" dans le fichier .html pour le composant spécifique.

5voto

Mouhcine Mtg Points 51

Je pense que vous avez mis la fonction dans le $(document).ready....... Les fonctions sont toujours fournies en dehors du $(document).ready........

0voto

nbixler Points 458

J'ai résolu ce problème dans Vue en changeant mon onclick="someFunction()" à @click="someFunction" .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X