Внедрение вызова document.write из скрипта Greasemonkey ничего не загружает

Следующая инъекция отлично работает в Chrome, однако в последней версии Firefox (версия 21) документы остаются «Подключение ...» навсегда, и даже такие элементы, как <img>, не загружаются. (Но если вы нажмете перезагрузить их, они появятся нормально...)

Снимок экрана:
Снимок экрана с проблемой

Скрипт:

// ==UserScript==
// @name            Test
// @namespace       Test
// @author          Owyn
// @match           http://*
// ==/UserScript==

function inject(func) {
    var source = func.toString();
    var script = document.createElement('script');
    script.innerHTML = "("+ source +")()";
    document.body.appendChild(script);
}

function myf() {
  document.write('<html>TEST</html>');
}

inject(myf);

Любые исправления, какие-либо обходные пути? Должен ли я связаться с Mozilla по поводу ошибки?

P.S. - Я использую document.write для удаления всех прослушивателей событий (неизвестных мне) и пока не нашел ему альтернативы.


person Owyn    schedule 03.06.2013    source источник


Ответы (1)


Самое умное/лучшее (лучшее) — это избегать document.write(). Используйте методы DOM. Вот полный сценарий:

// ==UserScript==
// @name     _Replace a target page using DOM techniques
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/
var D       = document;
var newDoc  = D.implementation.createHTMLDocument ("");

D.replaceChild (
    D.importNode (newDoc.documentElement, true),
    D.documentElement
);

D.body.innerHTML = '<h1>TEST</h1>'



Обычно Greasemonkey срабатывает на DOMContentLoaded, не когда страница полностью загрузилась. Chrome срабатывает позже, по умолчанию.

Во всяком случае, на DOMContentLoaded в Firefox; что-то становится осиротевшим, когда вы уничтожаете текущий документ. Следовательно, «throbber» никогда не останавливается, и, вероятно, пропускается какая-то другая очистка.

Вероятно, это ошибка, но вы все равно не должны использовать document.write(). Кроме того, в соответствии с документом вам следует вызвать document.close()

Грязный обходной путь — дождаться загрузки страницы перед запуском. Итак, вместо того, чтобы вызывать inject(myf); напрямую, вызовите его так:

function myf () {
  document.write ('<html>TEST</html>');
  document.close ();
}

window.addEventListener ("load", function () { inject(myf); }, false);


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

person Brock Adams    schedule 03.06.2013
comment
загрузка события, кажется, исправляет это, но теперь он ждет, пока все будет слишком долго, что может занять очень много времени, нет ли способа исправить это, чтобы он работал так же, как в Chrome? (страница просто открывается, и document.write работает сразу, без зависания соединения...) - person Owyn; 03.06.2013
comment
Да, используйте метод DOM. Это работает в обоих браузерах и не требует ожидания события load. - person Brock Adams; 03.06.2013
comment
Какой метод DOM? DOMContentLoaded, который в FireFox искажает страницу для бесконечной загрузки и разрыва изображений? - person Owyn; 03.06.2013
comment
Используйте полный рабочий сценарий, который я дал в 1-й половине ответа. Не используйте document.write вообще. - person Brock Adams; 03.06.2013
comment
реализация не удаляет все прослушиватели событий, в отличие от document.write, поэтому она не служит цели, вместо этого я мог бы просто сделать document.body.innerHTML = TEST; - person Owyn; 03.06.2013
comment
Я только что протестировал его, и в окне, и в document.head он оставляет слушатели, а также тестировал с document.write - все слушатели были удалены. Я спрашивал об ошибке вечной загрузки document.write, которую вы только что дали случайной функции, которая делает то же самое, что и document.body.innerHTML = ; и ничего более. Извини. Текущий ответ вызывает window.stop(), а затем с помощью setTimeout снова редактирует документ, чтобы добавить изображения, которые будут отображаться нормально (за исключением того, что функция перезагрузки все равно будет работать плохо или не будет работать вообще) - person Owyn; 03.06.2013
comment
Действительно? Предоставьте тестовую страницу, демонстрирующую это поведение событий. Обратите также внимание на то, что этого требования к событию не было в вопросе, и оно относится к последующим действиям. И нет, мой код совсем не совпадает с document.body.innerHTML =, и он никак не оставляет ничего в заголовке документа. Наконец, это не все, что я дал. Я указываю причину, по которой ваш исходный код не работал, И работающий обходной путь. И я пытался сказать вам, что вы не должны использовать такие плохие методы, даже если они работают (на данный момент) в Chrome. - person Brock Adams; 03.06.2013
comment
document.addEventListener (щелчок, функция () { предупреждение (Hi3); }, ложь); - это остается после реализации, которую вы опубликовали, но исчезает после document.write (протестировано как Chrome, так и FireFox) (не голова да, но почти то же самое, протестировано некоторое время назад и запутало такие мелкие детали). P.S. - вы сказали не использовать document.write, но на данный момент я не нашел альтернативы. - person Owyn; 03.06.2013