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

85

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

Вот функция:

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

В spanтеге onclickвызывает эту функцию:

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

Каждый раз, когда я нажимаю кнопку с onclickатрибутом, я получаю эту ошибку:

Uncaught ReferenceError: функция не определена.

Любая помощь будет оценена.

Спасибо!

Обновить

Я пробовал использовать:

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

Но у меня undefinedошибка.

Вот сценарий .

Я попытался сделать это, чтобы проверить, работают ли слушатели, а они нет для меня:

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
источник
2
Размещайте только соответствующий код. Прочтите правила.
alt
1
Ссылка на ваш полный сценарий всегда уместна и приветствуется в дополнение к соответствующим фрагментам кода, которые должны быть в вашем сообщении.
Брок Адамс,

Ответы:

131

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

Причина в том, что пользовательские сценарии работают в изолированной программной среде («изолированном мире»), 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, вы удаляете все обработчики событий на затронутых узлах. Если вы используете этот метод, остерегайтесь этого факта.
Брок Адамс
источник
1
Я получаю эту ошибку: Uncaught TypeError: у объекта 3 нет метода addEventListener
ECMAScript
Значит, вы делаете это неправильно. Ссылка на полный сценарий, вызвавший эту ошибку, И ссылку на целевую страницу, на которой он выполняется.
Брок Адамс
2
Исправлено я использовал: btnreset.onclick = function () {resetEmotes (); }; Благодаря!
ECMAScript
Рад, что у вас это работает, но этот метод будет работать только в некоторых условиях и не является портативным.
Брок Адамс
Мой код действительно плохо запрограммирован, поэтому я все перекодирую и использую jQuery. Благодаря!
ECMAScript
3

Я получал ошибку (я использую Vue), я переключился onclick="someFunction()"на, @click="someFunction"и теперь они работают.

nbixler
источник
вопрос не связан с Vue
Дэйв Мануэль
0

Убедитесь, что вы используете модуль Javascript или нет ?! при использовании модулей js6 ваши атрибуты событий html не будут работать. в этом случае вы должны перенести свою функцию из глобальной области в область видимости модуля. Просто добавьте это в свой файл javascript: window.functionName= functionName;

пример:

<h1 onClick="functionName">some thing</h1>
Мохаммад реза хедаят ния
источник
0

Я думаю, вы поместили функцию в $ (document) .ready ....... Функции всегда предоставляются в $ (document) .ready .......

Mouhcine Mtg
источник
0

Я разрешил это в angular с (click) = "someFuncionName()"помощью файла .html для конкретного компонента.

Альферд Нобель
источник
-2

Если функция не определена при использовании этой функции в html, например onclick = 'function ()', это означает, что функция находится в обратном вызове, в моем случае это 'DOMContentLoaded'.

Vũ Đức Vĩ
источник
1
Это не ответ. Вы можете опубликовать его в качестве комментария (создав хорошую репутацию). Прочтите, пожалуйста, Как мне написать хороший ответ?
EhsanT