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/"
]
}
Ответы
Ответ 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.