未捕获的ReferenceError:函数没有使用onclick定义

时间:2022-11-05 08:35:40

I'm trying to make a userscript for a website to add custom emotes. However, I've been getting a lot of errors.

我正在尝试为一个网站制作一个用户脚本来添加自定义的表情符号。然而,我有很多错误。

Here is the 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 += '<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.");
    }
}

The span tag's onclick calls this function:

span标记的onclick调用此函数:

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

Every time I click a button that has an onclick attribute, I get this error:

每当我点击一个带有onclick属性的按钮时,就会出现以下错误:

Uncaught ReferenceError: function is not defined.

未捕获的ReferenceError:函数未定义。

Any help would be appreciated.

如有任何帮助,我们将不胜感激。

Thank you!

谢谢你!

Update

I tried using:

我试着使用:

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

But I got an undefined error.

但是我得到了一个未定义的错误。

Here is the script.

这是脚本。

I tried doing this to test if listeners work and they don't for me:

我试着做这个测试,看看听众是否对我有效,而他们对我却没有效果:

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

1 个解决方案

#1


85  

Never use .onclick(), or similar attributes from a userscript! (It's also poor practice in a regular web page).

不要使用.onclick()或userscript中的类似属性!(在普通的网页上,这也是不好的做法)。

The reason is that userscripts operate in a sandbox ("isolated world"), and onclick operates in the target-page scope and cannot see any functions your script creates.

原因是userscripts在沙箱(“隔离的世界”)中操作,而onclick在目标页面范围中操作,无法看到脚本创建的任何函数。

Always use addEventListener()Doc (or an equivalent library function, like jQuery .on()).

始终使用addEventListener()Doc(或等效的库函数,如jQuery .on()))。

So instead of code like:

所以不是像这样的代码:

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


You would use:

你会使用:

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

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

For the loop, you can't pass data to an event listener like that See the doc. Plus every time you change innerHTML like that, you destroy the previous event listeners!

对于循环,您不能将数据传递给事件监听器,比如doc。另外,每当您这样更改innerHTML时,您就会破坏以前的事件监听器!

Without refactoring your code much, you can pass data with data attributes. So use code like this:

如果不重构您的代码,您可以通过数据属性传递数据。使用如下代码:

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

Where appendEmote is like:

appendEmote在哪里:

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


WARNINGS:

  • Your code reuses the same id for several elements. Don't do this, it's invalid. A given ID should occur only once per page.
  • 您的代码对几个元素重用相同的id。别这样,这是无效的。给定的ID应该只在每页中出现一次。
  • Every time you use .outerHTML or .innerHTML, you trash any event handlers on the affected nodes. If you use this method beware of that fact.
  • 每次使用. outerhtml或. innerhtml时,都会在受影响的节点上销毁任何事件处理程序。如果你使用这个方法,就要注意这个事实。

#1


85  

Never use .onclick(), or similar attributes from a userscript! (It's also poor practice in a regular web page).

不要使用.onclick()或userscript中的类似属性!(在普通的网页上,这也是不好的做法)。

The reason is that userscripts operate in a sandbox ("isolated world"), and onclick operates in the target-page scope and cannot see any functions your script creates.

原因是userscripts在沙箱(“隔离的世界”)中操作,而onclick在目标页面范围中操作,无法看到脚本创建的任何函数。

Always use addEventListener()Doc (or an equivalent library function, like jQuery .on()).

始终使用addEventListener()Doc(或等效的库函数,如jQuery .on()))。

So instead of code like:

所以不是像这样的代码:

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


You would use:

你会使用:

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

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

For the loop, you can't pass data to an event listener like that See the doc. Plus every time you change innerHTML like that, you destroy the previous event listeners!

对于循环,您不能将数据传递给事件监听器,比如doc。另外,每当您这样更改innerHTML时,您就会破坏以前的事件监听器!

Without refactoring your code much, you can pass data with data attributes. So use code like this:

如果不重构您的代码,您可以通过数据属性传递数据。使用如下代码:

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

Where appendEmote is like:

appendEmote在哪里:

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


WARNINGS:

  • Your code reuses the same id for several elements. Don't do this, it's invalid. A given ID should occur only once per page.
  • 您的代码对几个元素重用相同的id。别这样,这是无效的。给定的ID应该只在每页中出现一次。
  • Every time you use .outerHTML or .innerHTML, you trash any event handlers on the affected nodes. If you use this method beware of that fact.
  • 每次使用. outerhtml或. innerhtml时,都会在受影响的节点上销毁任何事件处理程序。如果你使用这个方法,就要注意这个事实。