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

Динамическая вставка javascript в HTML, который использует document.write

В настоящее время я загружаю всплывающее окно в стиле лайтбокса, которое загружает HTML-код из вызова XHR. Затем это содержимое отображается во всплывающем окне "modal", используя element.innerHTML = content. Это работает как прелесть.

В другом разделе этого сайта я использую значок Flickr '(http://www.elliotswan.com/2006/08/06/custom-flickr-badge-api-documentation/), чтобы динамически загружать изображения flickr. Это делается, включая тег script, который загружает javascript flickr, который, в свою очередь, делает некоторые статусы document.write.

Оба они отлично работают, когда включены в HTML. Только при загрузке кода значка flickr внутри лайтбокса содержимое вообще не отображается. Похоже, что использование innerHTML для написания операторов document.write делает это слишком далеко, но я не могу найти никакой подсказки в реализациях javascript (FF2 & 3, IE6 & 7) этого поведения.

Может ли кто-нибудь уточнить, должно ли это работать или не должно работать? Спасибо.

4b9b3361

Ответ 1

В общем случае теги script не выполняются при использовании innerHTML. В вашем случае это хорошо, потому что вызов document.write уничтожит все, что уже на странице. Однако это оставляет вас без добавления HTML document.write.

jQuery Методы манипуляции HTML будут выполнять скрипты в HTML для вас, трюк затем захватывает вызовы document.write и получает HTML в нужном месте. Если это достаточно просто, то что-то вроде этого будет делать:

var content = '';
document.write = function(s) {
    content += s;
};
// execute the script
$('#foo').html(markupWithScriptInIt);
$('#foo .whereverTheDocumentWriteContentGoes').html(content);

Все усложняется. Если script находится в другом домене, он будет загружен асинхронно, поэтому вам придется подождать, пока это не будет сделано для получения содержимого. Кроме того, что, если он просто записывает HTML в середину фрагмента без элемента оболочки, который вы можете легко выбрать? writeCapture.js (полное раскрытие: я написал) обрабатывает все эти проблемы. Я бы рекомендовал просто использовать его, но, по крайней мере, вы можете посмотреть на код, чтобы увидеть, как он обрабатывает все.

EDIT: страница, показывающая, что похоже на эффект, который вы хотите.

Ответ 2

Я создал простую тестовую страницу, которая иллюстрирует проблему:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <title>Document Write Testcase</title>
    </head>
    <body>
        <div id="container">
        </div>
        <div id="container2">
        </div>

        <script>
            // This doesn't work!
            var container = document.getElementById('container');
            container.innerHTML = "<script type='text/javascript'>alert('foo');document.write('bar');<\/script>";

            // This does!
            var container2 = document.getElementById('container2');
            var script = document.createElement("script");
            script.type = 'text/javascript';
            script.innerHTML = "alert('bar');document.write('foo');";
            container.appendChild(script);
        </script>
    </body>
</html>

Эта страница предупреждает "бар" и печатает "foo", в то время как я ожидал, что он также предупредит "foo" и напечатает "bar". Но, к сожалению, поскольку тег script является частью большей HTML-страницы, я не могу выделить этот тег и добавить его, как в примере выше. Ну, я могу, но для этого потребуется сканировать innerHTML контент для тегов script и заменить их в строке заполнителями, а затем вставить их с помощью DOM. Звучит не так тривиально.

Ответ 3

Использовать document.writeln(content); вместо document.write(content).

Тем не менее, лучший способ - использовать конкатенацию innerHTML, например так:

element.innerHTML += content;

element.innerHTML = content; Метод заменит старый контент новым, который перезапишет ваш элемент innerHTML!

Принимая во внимание, что использование оператора += в element.innerHTML += content добавит ваш текст после старого содержимого. (аналогично тому, что делает document.write.)

Ответ 4

document.write примерно так же устарел, как и они. Благодаря чудесам JavaScript вы можете просто назначить свою собственную функцию методу write объекта document, который использует innerHTML для выбранного вами элемента, чтобы добавить поставляемый контент.

Ответ 5

Могу ли я получить некоторое разъяснение, чтобы убедиться, что у меня проблема?

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

Поэтому для того, чтобы это работало во всех операциях Flickr document.write, необходимо будет быть частью content в element.innerHTML = content. Это определенно так?

Вы можете быстро проверить, должно ли это вообще работать, добавив единственный и простой вызов document.write в контент, который установлен как innerHTML, и посмотрите, что он делает:

<script>
  var content = "<p>1st para</p><script>document.write('<p>2nd para</p>');</script>"
  element.innerHTML = content;
</script>

Если это работает, концепция document.write, работающая в содержимом, установленном как innerHTML элемента, может просто работать.

У меня такое чувство, что это не сработает, но для проверки концепции должно быть довольно просто.

Ответ 6

Итак, вы используете метод DOM для создания элемента script и добавляете его к существующему элементу, и это приводит к тому, что содержимое добавляемого элемента script выполняется? Это звучит хорошо.

Вы говорите, что тег script является частью большей HTML-страницы и поэтому не может быть выделен. Можете ли вы дать тегу script идентификатор и настроить его? Я, вероятно, не вижу здесь ничего очевидного.

Ответ 7

В теории, да, я могу выделить тег script таким образом. Проблема в том, что у нас потенциально есть десятки ситуаций, когда это происходит, поэтому я пытаюсь найти какую-то причину или документацию по этому поведению.

Кроме того, тег script, по-видимому, не является частью DOM после его загрузки. В нашей среде мой div container остается пустым, поэтому я не могу получить тег script. Это должно сработать, потому что в моем примере выше script не выполняется, но все еще является частью DOM.