Uncaught ReferenceError: функция не определена с помощью onclick


Я пытаюсь сделать userscript для веб-сайта, чтобы добавить пользовательские эмоции. Тем не менее, я получаю много ошибок.

вот функция:

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 тега!--5-- > вызывает эту функцию:

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

каждый раз, когда я нажимаю кнопку, которая имеет

1 55

1 ответ:

никогда не используйте .onclick(), или аналогичные атрибуты из пользовательского скрипта! (кроме плохая практика в обычной веб-странице).

причина в том, что userscripts работают в песочнице ("изолированный мир"), и onclick работает в области целевой страницы и не может видеть никаких функций, создаваемых вашим скриптом.

всегда использовать addEventListener() Doc (или эквивалентная библиотечная функция, например jQuery .on ()).

поэтому вместо кода типа:

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


Вы бы использовали:

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

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

для цикла вы не можете передавать данные в прослушиватель событий, как это см. док. Плюс каждый раз, когда вы меняете innerHTML таким образом, вы уничтожаете предыдущих слушателей событий!

без рефакторинга кода много, вы можете передавать данные с атрибутами данных. Так что используйте код это:

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

где 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;
}


предупреждения:

  • ваш код использует один и тот же идентификатор для нескольких элементов. Не делай этого, это недопустимо. Данный идентификатор должен встречаться только один раз на странице.
  • каждый раз, когда вы используете .outerHTML или .innerHTML, вы уничтожаете любые обработчики событий на затронутых узлах. Если вы используете этот метод остерегайтесь этого факта.