JavaScript - управление точкой вставки для document.write - PullRequest
17 голосов
/ 08 октября 2009

Я хотел бы создать страницу, которая запускает сторонний скрипт, включающий document.write после того, как DOM уже был полностью загружен.

Моя страница не XHTML. Моя проблема в том, что document.write перезаписывает мою собственную страницу. (что и происходит после загрузки DOM).

Я попытался переопределить функцию document.write (в некотором роде http://ejohn.org/blog/xhtml-documentwrite-and-adsense/), но это не касается случаев, когда document.write содержит частичные теги.

Пример, который может нарушить вышеуказанный код:

document.write("<"+"div");
document.write(">"+"Done here<"+"/");
document.write("div>");

Есть ли способ изменить точку вставки document.write через JavaScript? У кого-нибудь есть идеи как это сделать?

Ответы [ 7 ]

11 голосов
/ 29 декабря 2009

Если вы имеете дело со сторонними сценариями, просто заменить document.write, чтобы захватить выходные данные и вставить их в нужное место, недостаточно, поскольку они могут изменить сценарий, и ваш сайт сломается. *

writeCapture.js делает то, что вам нужно (полное раскрытие: я автор). По сути, он переписывает теги сценария, чтобы каждый из них записывал свой собственный вывод document.write и помещал его в правильное место. Использование (с использованием jQuery) будет примерно таким:

$(document.body).writeCapture().append('<script type="text/javascript" src="http://3rdparty.com/foo.js"></script>');

Здесь я предполагаю, что вы хотите присоединить к концу тела. Все селекторы jQuery и методы манипуляции будут работать с плагином, так что вы можете внедрить его где угодно и как угодно. Его также можно использовать без jQuery, если это проблема.

4 голосов
/ 11 июня 2012

Возможно переопределить метод document.write. Таким образом, вы можете буферизовать строки, отправленные в document.write, и вывести буфер в любое удобное для вас место. Однако изменение сценария с синхронного на асинхронный может привести к ошибкам, если не обрабатывается правильно. Вот пример:

Упрощенная замена document.write

(function() {
    // WARNING: This is just a simplified example
    // to illustrate a problem.
    // Do NOT use this code!

    var buffer = [];
    document.write = function(str) {
        // Every time document.write is called push
        // the data into buffer. document.write can
        // be called from anywhere, so we also need
        // a mechanism for multiple positions if
        // that's needed.
        buffer.push(str);
    };

    function flushBuffer() {
        // Join everything in the buffer to one string and put
        // inside the element we want the output.
        var output = buffer.join('');
        document.getElementById("ad-position-1").innerHTML = output;
    }

    // Inject the thid-party script dynamically and
    // call flushBuffer when the script is loaded
    // (and executed).
    var script = document.createElement("script");
    script.onload = flushBuffer;
    script.src = "http://someadserver.com/example.js";

})();

Содержание http://someadserver.com/example.js

var flashAdObject = "<object>...</object>";
document.write("<div id='example'></div>");

// Since we buffer the data the getElementById will fail
var example = document.getElementById("example");
example.innerHTML = flashAdObject; // ReferenceError: example is not defined

Я задокументировал различные проблемы, с которыми я столкнулся при написании и использовании замены document.write: https://github.com/gregersrygg/crapLoader/wiki/What-to-think-about-when-replacing-document.write

Но опасность замены document.write - все неизвестные проблемы, которые могут возникнуть. Некоторым даже невозможно обойти.

document.write("<scr"+"ipt src='http://someadserver.com/adLib.js'></scr"+"ipt>");
adLib.doSomething(); // ReferenceError: adLib is not defined

К счастью, я не сталкивался с вышеуказанной проблемой в дикой природе, но это не гарантирует, что этого не произойдет;)

Все еще хотите попробовать? Попробуйте crapLoader (мой) или writeCapture :

Вы также должны проверить дружественных фреймов . По сути, он создает iframe с тем же доменом и загружает все, а не в ваш документ. К сожалению, я не нашел хороших библиотек для этого.

3 голосов
/ 23 ноября 2009

Вас может заинтересовать библиотека Javascript, которую я разработал , которая позволяет загружать сторонние скрипты, используя document.write после window.onload. Внутри библиотека переопределяет document.write, динамически добавляя элементы DOM, выполняя любые включенные сценарии, которые также могут использовать document.write.

В отличие от решения Джона Ресига (которое послужило источником вдохновения для моего собственного кода), разработанный мной модуль поддерживает частичную запись, например, пример, который вы приводите с помощью div:

document.write("<"+"div");
document.write(">"+"Done here<"+"/");
document.write("div>");

Моя библиотека будет ждать конца сценария, прежде чем анализировать и обрабатывать разметку. В приведенном выше примере он будет выполняться один раз с полной строкой "<div>Done here</div>" вместо 3 раз с частичной разметкой.

Я настроил демонстрацию, в которой я загружаю 3 объявления Google, виджет Amazon и Google Analytics динамически .

3 голосов
/ 08 октября 2009

Оригинальный ответ перед редактированием:


В основном проблема document.write в том, что он не работает в документах XHTML . Тогда самое широкое решение (как бы жестко это ни казалось) состоит в том, чтобы не использовать XHTML / xml для своей страницы. Из-за IE + XHTML и проблемы mimetype , взлома Google Adsense (может быть, неплохо :) и общего сдвига в сторону HTML5, я не думаю, что это так плохо, как кажется.

Однако, если вы действительно хотите 1010 * использовать XHTML для своей страницы, то сценарий Джона, на который вы ссылаетесь, - лучший, который у вас есть на данный момент. Просто нюхайте IE на сервере. Если запрос от IE, ничего не делайте (а не обслуживает application/xhtml+xml mimetype!). В противном случае поместите его на <head> вашей страницы, и вы отправитесь в гонки.

Перечитывая ваш вопрос, есть ли у вас особая проблема со сценарием Джона? Известно, что в Safari 2.0 происходит сбой, но это все.

1 голос
/ 31 января 2013

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

0 голосов
/ 12 октября 2009

Есть лучшие способы сделать это. 2 способа

1) Добавить

<html><head>
<script>
  window.onload = function () {
    var el = document.createTextNode('hello world');
    document.body.appendChild(el);
  }
</script></head><body></body></html>

2) InnerHTML

<html><head><script>
  window.onload = function () {
    document.body.innerHTML = 'hello world';
  }
</script></head><body></body></html>
0 голосов
/ 10 октября 2009

Чтобы изменить содержимое страницы после рендеринга DOM, вам нужно либо использовать библиотеку javascript для добавления HTML или текста в определенные моменты (jQuery, mootools, prototype, ...) или просто использовать свойство innerHTML каждого элемента DOM, чтобы изменить / добавить текст к нему. Это работает кроссбраузер и не требует каких-либо библиотек.

...