Error de referencia no detectado: la función no está definida con onclick

84

Estoy tratando de hacer un script de usuario para un sitio web para agregar emoticones personalizados. Sin embargo, he tenido muchos errores.

Aquí está la función:

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

La spanetiqueta onclickllama a esta función:

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

Cada vez que hago clic en un botón que tiene un onclickatributo, aparece este error:

Error de referencia no detectado: la función no está definida.

Cualquier ayuda sería apreciada.

¡Gracias!

Actualizar

Intenté usar:

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

Pero tengo un undefinederror.

Aquí está el guión .

Intenté hacer esto para probar si los oyentes funcionan y no para mí:

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);
ECMAScript
fuente
1
Publicar solo el código relevante. Lee las reglas.
alt
1
El enlace a su script completo siempre es apropiado y apreciado, además de los fragmentos de código relevantes que deberían estar en su publicación.
Brock Adams

Respuestas:

131

¡Nunca use .onclick(), o atributos similares de un script de usuario! (También es una mala práctica en una página web normal ).

La razón es que los scripts de usuario operan en una caja de arena ("mundo aislado"), y onclickoperan en el ámbito de la página de destino y no pueden ver las funciones que crea el script.

Siempre usa addEventListener() Doc (o una función de biblioteca equivalente, como jQuery .on () ).

Entonces, en lugar de código como:

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


Usarías:

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

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

Para el ciclo, no puede pasar datos a un detector de eventos como ese. Consulte el documento . Además, cada vez que cambias innerHTMLasí, ¡destruyes a los oyentes de eventos anteriores!

Sin refactorizar mucho su código, puede pasar datos con atributos de datos. Entonces usa un código como este:

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

Donde appendEmote es como:

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


ADVERTENCIAS:

  • Su código reutiliza la misma identificación para varios elementos. No hagas esto, no es válido. Un ID determinado debe aparecer solo una vez por página.
  • Cada vez que usa .outerHTMLo .innerHTML, elimina los controladores de eventos en los nodos afectados. Si usa este método, tenga cuidado con ese hecho.
Brock Adams
fuente
1
Recibo este error: Error de tipo no detectado: el objeto 3 no tiene el método 'addEventListener'
ECMAScript
Entonces lo estás haciendo mal. Enlace a la secuencia de comandos completa que dio ese error Y enlace a la página de destino en la que se ejecuta.
Brock Adams
2
Lo arreglé que usé: btnreset.onclick = function () {resetEmotes (); }; ¡Gracias!
ECMAScript
Me alegro de que haya funcionado, pero esa técnica solo funcionará en algunas condiciones y no es portátil.
Brock Adams
Mi código está muy mal codificado, así que estoy volviendo a codificar todo y usando jQuery. ¡Gracias!
ECMAScript
3

Que estaba recibiendo el error (estoy usando Vue) y cambié mi onclick="someFunction()"para @click="someFunction"y ahora se está trabajando.

nbixler
fuente
la pregunta no está relacionada con Vue
Dave Manuel
-2

Si la función no está definida cuando se usa esa función en html, como onclick = 'function ()', significa que la función está en una devolución de llamada, en mi caso es 'DOMContentLoaded'.

Vũ Đức Vĩ
fuente
1
Esta no es una respuesta. Puede publicarlo como un comentario (construyendo una reputación adecuada). Por favor lea ¿Cómo escribo una buena respuesta?
EhsanT