Подтвердить что ты не робот

OnClick внутри расширения Chrome не работает

Это, кажется, самая простая вещь, но она просто не работает. В обычном браузере файлы .html и .js прекрасно работают, но в расширении Chrome функция onClick не выполняет то, что она должна делать.

.js файл:

function hellYeah(text) {
  document.getElementById("text-holder").innerHTML = text;
}

.html файл:

<!doctype html>
<html>
  <head>
    <title>
      Getting Started Extension Popup
    </title>
    <script src="popup.js"></script>
  </head>
  <body>
    <div id="text-holder">
      ha
    </div>
    <br />
    <a onClick=hellYeah("xxx")>
      hyhy
    </a>
  </body>
</html>

Итак, в основном, когда пользователь нажимает "hyhy", "ha" следует изменить на "xxx". И снова - он отлично работает в браузере, но не работает в расширении. Ты знаешь почему? На всякий случай я прикрепляю manifest.json ниже.

Спасибо заранее!

manifest.json:

{
  "name": "My First Extension",
  "version": "1.0",
  "manifest_version": 2,
  "description": "The first extension that I made.",
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "permissions": [
    "http://api.flickr.com/"
  ]
}
4b9b3361

Ответ 1

Расширения Chrome не позволяют иметь встроенный JavaScript (документация). Вам нужно будет сделать что-то похожее на это.

Назначьте идентификатор ссылки (<a onClick=hellYeah("xxx")> станет <a id="link">) и используйте addEventListener для привязки события. Поместите в файл popup.js следующее:

document.addEventListener('DOMContentLoaded', function() {
    var link = document.getElementById('link');
    // onClick logic below:
    link.addEventListener('click', function() {
        hellYeah('xxx');
    });
});

Ответ 2

Причина

Это не работает, потому что Chrome запрещает какой-либо встроенный код в расширениях через политику безопасности контента.

Встроенный JavaScript не будет выполнен. Это ограничение запрещает как встроенные <script> блокирует встроенные обработчики событий и (например, <button onclick="...">).

Как обнаружить

Если это действительно проблема, Chrome создаст следующую ошибку в консоли:

Отказано в выполнении встроенного script, поскольку оно нарушает следующую директиву политики безопасности содержимого: "script -src" self "chrome-extension-resource:". Для включения встроенного выполнения требуется либо ключевое слово "небезопасное-встроенное", либо хэш ( "sha256 -..." ), либо nonce ( "nonce -..." ).

Чтобы получить доступ к всплывающей консоли JavaScript (что полезно для отладки в целом), щелкните правой кнопкой мыши кнопку расширения и выберите "Осмотреть всплывающее окно" в контекстном меню.

Дополнительная информация об отладке всплывающего окна доступна здесь.

Как исправить

Нужно удалить все встроенные JavaScript. В документации Chrome есть .

Предположим, что оригинал выглядит так:

<a onclick="handler()">Click this</a> <!-- Bad -->

Нужно удалить атрибут onclick и дать элементу уникальный идентификатор:

<a id="click-this">Click this</a> <!-- Fixed -->

И затем присоедините слушателя из script (который должен находиться в файле .js, предположим popup.js):

// Pure JS:
document.addEventListener('DOMContentLoaded', function() {
  document.getElementById("click-this").addEventListener("click", handler);
});

// The handler also must go in a .js file
function handler() {
  /* ... */
}

Обратите внимание на обертку в событии DOMContentLoaded. Это гарантирует, что элемент существует во время выполнения. Теперь добавьте тег script, например, в <head> документа:

<script src="popup.js"></script>

Альтернатива, если вы используете jQuery:

// jQuery
$(document).ready(function() {
  $("#click-this").click(handler);
});

Расслабление политики

Q: В этой ошибке упоминаются способы разрешить встроенный код. Я не хочу/не могу изменить свой код, как включить встроенные скрипты?

A: Несмотря на то, что ошибка говорит, не может включить встроенный script:

Нет механизма для ослабления ограничения на выполнение встроенного JavaScript. В частности, установка политики script, которая включает 'unsafe-inline', не будет иметь никакого эффекта.

Обновление: Начиная с Chrome 46, можно выбрать белый список конкретных встроенных блоков кода:

Как и в случае с Chrome 46, встроенные скрипты могут быть добавлены в белый список, указав хэш-код, основанный на base64, в политике. Этот хеш должен быть префикс используемого хэш-алгоритма (sha256, sha384 или sha512). См. Использование хэшей для <script> элементов для примера.

Однако я не вижу причин использовать это, и он не включит встроенные атрибуты, такие как onclick="code".

Ответ 3

У меня была такая же проблема, и я не хотел переписывать код, поэтому я написал функцию для изменения кода и создания встроенных декларируемых событий:

function compile(qSel){
    var matches = [];
    var match = null;
    var c = 0;

    var html = $(qSel).html();
    var pattern = /(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/mg;

    while (match = pattern.exec(html)) {
        var arr = [];
        for (i in match) {
            if (!isNaN(i)) {
                arr.push(match[i]);
            }
        }
        matches.push(arr);
    }
    var items_with_events = [];
    var compiledHtml = html;

    for ( var i in matches ){
        var item_with_event = {
            custom_id : "my_app_identifier_"+i,
            code : matches[i][5],
            on : matches[i][3],
        };
        items_with_events.push(item_with_event);
        compiledHtml = compiledHtml.replace(/(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/m, "<$2 custom_id='"+item_with_event.custom_id+"' $7 $8");
    }

    $(qSel).html(compiledHtml);

    for ( var i in items_with_events ){
        $("[custom_id='"+items_with_events[i].custom_id+"']").bind(items_with_events[i].on, function(){
            eval(items_with_events[i].code);
        });
    }
}

$(document).ready(function(){
    compile('#content');
})

Это должно удалить все встроенные события из выбранного node и заново создать их с помощью jquery.