Динамическая вставка JavaScript в HTML, который использует document.write - PullRequest
17 голосов
/ 10 сентября 2008

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

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

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

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

Ответы [ 7 ]

14 голосов
/ 08 декабря 2009

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

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

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

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

РЕДАКТИРОВАТЬ: Вот страница , демонстрирующая, как звучит эффект, который вы хотите.

4 голосов
/ 10 сентября 2008

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

<!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>

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

3 голосов
/ 24 августа 2011

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

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

element.innerHTML += content;

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

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

1 голос
/ 10 сентября 2008

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

0 голосов
/ 10 сентября 2008

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

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

0 голосов
/ 10 сентября 2008

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

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

0 голосов
/ 10 сентября 2008

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

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 элемента, может просто работать.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...