Как запустить greasemonkey script до отображения содержимого страницы?
Я пишу плагин для Firefox и использую greasemonkey script для этого (я скомпилирую пользователя script с помощью этого инструмента http://arantius.com/misc/greasemonkey/script-compiler).
Проблема заключается в том, что script запускается после полной загрузки страницы. Это означает, что пользователь увидит просматриваемую страницу в ее первоначальной форме, а затем script применит сделанные мной изменения. Мой вопрос: есть ли способ запустить пользователя script до того, как содержимое страницы будет отображаться пользователю, так что пользователь будет только окончательной версией веб-сайта?
Ответы
Ответ 1
EDIT: этот пост был создан до реализации ключа @run-at
в Greasemonkey - как отмечено Blaise, из Greasemonkey 0.9.8 вы можете теперь выполнить script, как только страница начнет загружаться.
@run-at document-start
описывается в wiki следующим образом:
Старт новый, начиная с версии 0.9.8. script будет запускаться до документ начинает загрузку, поэтому перед запуском любого скрипта или загрузки изображений.
Обратите внимание, что это означает, что выполнение script выполняется (потенциально) до создания DOM и может привести к некорректному/необычному поведению. Вам понадобится (немного) больше, чем просто однострочное вхождение.
В Greaseemonkey Wiki есть еще несколько деталей:
http://wiki.greasespot.net/Metadata_Block#.40run-at
Боковое примечание. Информация, которую я должен передать, специально связана с Greasemonkey в браузере. Я не уверен, что @run-at document-start
хорошо работает с компилятором script - я предлагаю жить опасно.. Протестируйте его и узнайте!;]
В настоящее время невозможно запустить пользователя script до загрузки страницы.
Чтобы остановить мерцание, используя текущие версии Greasemonkey, вы можете попробовать добавить пользовательский стиль в свой профиль Firefox (который затем отменяется с помощью script), как описано в Greasemonkey wiki, но это также потребует от каждого из ваших пользователей сделать то же самое, чтобы извлечь выгоду из этого.
Это то, что было давно желательным, и просмотрев issue # 1103 на сайте Greasemonkey Github, кажется, что был создан рабочий прототип (но нет времени для его добавления в выпускную версию afaik).
Ответ 2
Используя @run-at document-start
, как было предложено в ответе @kwah, мой script, выполненный до того, как содержимое, которое я хотел обработать, было в теле документа. В качестве обхода я установил интервал, выполняющий мой script 5 раз/сек до document.readyState == "complete"
(или до 20 секунд).
Это хорошо сработало для моего случая:
// ==UserScript==
// ...
// @run-at document-start
// ==/UserScript==
var greasemonkeyInterval = setInterval(greasemonkey, 200);
var greasemonkeyStart = (new Date()).getTime();
function greasemonkey() {
// ...
// waiting for readyState (or timeout)
if (
(new Date()).getTime() - greasemonkeyStart > 20000
|| document.readyState == "complete"
) {
clearInterval(greasemonkeyInterval);
}
};
Если вы более уверены в том, что контент будет там в документе, я думаю, что что-то вроде этого было бы более предпочтительным:
function greasemonkey() {
if (
document.readyState != "interactive"
&& document.readyState != "complete"
) {
return;
}
// ...
clearInterval(greasemonkeyInterval);
}
Ответ 3
В дополнение к предыдущим ответам я нашел решение, которое работает безупречно, как и предыдущие версии Firefox и GreaseMonkey.
Прежде всего, запуск должен быть установлен в самый ранний момент, поэтому начало документа:
// @run-at document-start
Поскольку DOM, вероятно, еще не загружен, дождитесь, когда документ получит готовое состояние интерактивного интерфейса:
document.onreadystatechange = function () {
if (document.readyState === "interactive") {
// Do something
}
}
В то время как Greasemonkey реализует более или менее то же самое с концом документа, я заметил, что вышеприведенная техника работает быстрее.
Используя это, я разрешил все проблемы, которые у меня были в Firefox, с мигающими/прыгающими экранами на страницах, когда изменения DOM пнули и загрузили страницу, как это было запланировано, с помощью usercript.