Incapaz ReferenceError: a function não está definida com onclick

Eu estou tentando fazer um userscript para um site para adicionar emoticons personalizados. No entanto, tenho recebido muitos erros.

Aqui está a function:

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 += ''; } else { alert("The maximum emote(" + EmoteNameLines[i] + ") size is (36x36)"); } } } else { alert("You have an unbalanced amount of emote parameters."); } } 

O onclick da tag de span chama essa function:

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

Toda vez que clico em um botão que tem um atributo onclick , recebo este erro:

Incapaz ReferenceError: a function não está definida.

Qualquer ajuda seria apreciada.

Obrigado!

Atualizar

Eu tentei usar:

 emoteTab[2].innerHTML += ''; document.getElementById(EmoteNameLines[i]).addEventListener("click", appendEmote(EmoteUsageLines[i]), false); 

Mas eu tenho um erro undefined .

Aqui está o roteiro .

Eu tentei fazer isso para testar se os ouvintes funcionam e eles não funcionam para mim:

 emoteTab[2].innerHTML = 'Custom Icons
Smilies
Popup
'; document.getElementById("togglemenu").addEventListener("click", changedisplay,false);

    Nunca use .onclick() ou semelhantes de um userscript! (Também é uma prática ruim em uma página da web normal ).

    A razão é que os userscripts operam em um sandbox (“mundo isolado”), e o onclick opera no escopo da página de destino e não pode ver nenhuma function criada pelo seu script.

    Sempre use addEventListener() Doc (ou uma function de biblioteca equivalente, como jQuery .on () ).

    Então, ao invés de código como:

     something.outerHTML += '' 

    Você usaria:

     something.outerHTML += '' document.getElementById ("btnsave").addEventListener ("click", resetEmotes, false); 

    Para o loop, você não pode transmitir dados para um ouvinte de evento como esse Consulte o documento . Além disso, toda vez que você altera innerHTML dessa forma, você destrói os ouvintes de events anteriores!

    Sem refatorar muito seu código, você pode passar dados com atributos de dados. Então use 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 += '' + '' ; } 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); } 

    Onde appendEmote é 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; } 

    ADVERTÊNCIAS:

    • Seu código reutiliza o mesmo id para vários elementos. Não faça isso, é inválido. Um determinado ID deve ocorrer apenas uma vez por página.
    • Toda vez que você usa .outerHTML ou .innerHTML , você .innerHTML todos os manipuladores de events nos nós afetados. Se você usar esse método, tenha cuidado com esse fato.