Почему этот JavaScript (с использованием document.open и document.write) не работает в Internet Explorer или Opera? - PullRequest
7 голосов
/ 15 ноября 2009

Мне очень нужна помощь в этом.

Я создал , который тесно связан и воспроизводит проблему другого, более сложного , который я написал в другом месте.

Вот что он делает:

  • создает
  • создает и добавляет к этому документу
  • последний внешний скрипт - это просто вызов функции обратного вызова, которая вызывает функцию, которая создает документ и добавляет его к

Три файла:

Это все работает в Firefox, Safari и Chrome. Где это ломается в Internet Explorer и Opera. Что происходит, так это то, что функция render () в main.js выполняется, и все три предупреждения запускаются, но документ в

Если я добавлю отладочный код (например, console.log (document)) в начало функции render (), работающие браузеры, похоже, получат указатель на существующий документ

Может ли это быть проблемой объема? Может быть, я неправильно использую методы document.write (), document.open () или document.close (), а Firefox и несколько других браузеров просто позволяют мне сойти с рук?

Одна возможная подсказка: если я вытащу из себя функции функции render (), то есть просто добавлю их после load () в main.js), это работает нормально. Это наводит меня на мысль, что дело не в том, как я использую document.open () и т. Д., А в том, что к моменту выполнения функции callback () объект документа недоступен или вышел из области видимости, или что-то в этом роде.

Это поставило меня в тупик, и это для очень важного проекта с приближающимся сроком. Я не выше взлома или обходного пути, если это вытащит меня из этого варенья. Любая помощь или понимание будут чрезвычайно признательны!

console.log () перечисляет свойства документа:

ATTRIBUTE_NODE: 2
CDATA_SECTION_NODE: 4
COMMENT_NODE: 8
DOCUMENT_FRAGMENT_NODE: 11
DOCUMENT_NODE: 9
DOCUMENT_POSITION_CONTAINED_BY: 16
DOCUMENT_POSITION_CONTAINS: 8
DOCUMENT_POSITION_DISCONNECTED: 1
DOCUMENT_POSITION_FOLLOWING: 4
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32
DOCUMENT_POSITION_PRECEDING: 2
DOCUMENT_TYPE_NODE: 10
ELEMENT_NODE: 1
ENTITY_NODE: 6
ENTITY_REFERENCE_NODE: 5
NOTATION_NODE: 12
PROCESSING_INSTRUCTION_NODE: 7
TEXT_NODE: 3
URL: "http://localhost/projects/test/ajax_loader/document_write/index.html"
activeElement: HTMLBodyElement
addEventListener: function addEventListener() {
adoptNode: function adoptNode() {
alinkColor: ""
all: HTMLCollection
anchors: HTMLCollection
appendChild: function appendChild() {
applets: HTMLCollection
attributes: null
baseURI: "http://localhost/projects/test/ajax_loader/document_write/index.html"
bgColor: ""
body: HTMLBodyElement
captureEvents: function captureEvents() {
characterSet: "UTF-8"
charset: "UTF-8"
childNodes: NodeList
clear: function clear() {
cloneNode: function cloneNode() {
close: function close() {
compareDocumentPosition: function compareDocumentPosition() {
compatMode: "BackCompat"
cookie: "__gads=ID=62bb88ab20ac9451:T=1256683145:S=ALNI_Mbso-nFjAvRzYhCSwhiuaDh84G8CA"
createAttribute: function createAttribute() {
createAttributeNS: function createAttributeNS() {
createCDATASection: function createCDATASection() {
createComment: function createComment() {
createDocumentFragment: function createDocumentFragment() {
createElement: function createElement() {
createElementNS: function createElementNS() {
createEntityReference: function createEntityReference() {
createEvent: function createEvent() {
createExpression: function createExpression() {
createNSResolver: function createNSResolver() {
createNodeIterator: function createNodeIterator() {
createProcessingInstruction: function createProcessingInstruction() {
createRange: function createRange() {
createTextNode: function createTextNode() {
createTreeWalker: function createTreeWalker() {
defaultCharset: "iso-8859-1"
defaultView: DOMWindow
designMode: "off"
dir: ""
dispatchEvent: function dispatchEvent() {
doctype: null
documentElement: HTMLHtmlElement
documentURI: "http://localhost/projects/test/ajax_loader/document_write/index.html"
domain: "localhost"
elementFromPoint: function elementFromPoint() {
embeds: HTMLCollection
evaluate: function evaluate() {
execCommand: function execCommand() {
fgColor: ""
firstChild: HTMLHtmlElement
forms: HTMLCollection
getCSSCanvasContext: function getCSSCanvasContext() {
getElementById: function getElementById() {
getElementsByClassName: function getElementsByClassName() {
getElementsByName: function getElementsByName() {
getElementsByTagName: function getElementsByTagName() {
getElementsByTagNameNS: function getElementsByTagNameNS() {
getOverrideStyle: function getOverrideStyle() {
getSelection: function getSelection() {
hasAttributes: function hasAttributes() {
hasChildNodes: function hasChildNodes() {
hasFocus: function hasFocus() {
height: 150
images: HTMLCollection
implementation: DOMImplementation
importNode: function importNode() {
inputEncoding: "UTF-8"
insertBefore: function insertBefore() {
isDefaultNamespace: function isDefaultNamespace() {
isEqualNode: function isEqualNode() {
isSameNode: function isSameNode() {
isSupported: function isSupported() {
jQuery1258269389622: 2
lastChild: HTMLHtmlElement
lastModified: ""
linkColor: ""
links: HTMLCollection
localName: null
location: Location
lookupNamespaceURI: function lookupNamespaceURI() {
lookupPrefix: function lookupPrefix() {
namespaceURI: null
nextSibling: null
nodeName: "#document"
nodeType: 9
nodeValue: null
normalize: function normalize() {
open: function open() {
ownerDocument: null
parentElement: null
parentNode: null
plugins: HTMLCollection
preferredStylesheetSet: null
prefix: null
previousSibling: null
queryCommandEnabled: function queryCommandEnabled() {
queryCommandIndeterm: function queryCommandIndeterm() {
queryCommandState: function queryCommandState() {
queryCommandSupported: function queryCommandSupported() {
queryCommandValue: function queryCommandValue() {
querySelector: function querySelector() {
querySelectorAll: function querySelectorAll() {
readyState: "complete"
referrer: "http://localhost/projects/test/ajax_loader/document_write/index.html"
releaseEvents: function releaseEvents() {
removeChild: function removeChild() {
removeEventListener: function removeEventListener() {
replaceChild: function replaceChild() {
scripts: HTMLCollection
selectedStylesheetSet: null
styleSheets: StyleSheetList
textContent: null
title: " Page"
vlinkColor: ""
width: 300
write: function write() {
writeln: function writeln() {
xmlEncoding: null
xmlStandalone: false
xmlVersion: null

Ответы [ 6 ]

11 голосов
/ 16 ноября 2009

если я возьму все функции функции render () (т.е. просто поместу их после load () в main.js), это будет нормально.

Не для меня в IE8. Если я полностью потеряю AJAX-вызов и просто вызову render() в main.js, я получу тот же результат. На самом деле, даже если я заменю весь main.js просто:

document.write('hello!');

с открытием документа или без него, привет никогда не появляется!

Если я установлю какое-либо время ожидания (даже 0) для вызова render в main.js, это сработает. С другой стороны, время ожидания для родительского документа, похоже, ничего не делает.

Эта чрезвычайная странность вызвана тем, что jQuery использует временно вставленный тег <script> для выполнения кода, возвращаемого в jsonp.js. Если вы просто вызываете eval для возвращаемого значения вместо того, чтобы jQuery его выполнял, это работает нормально.

Схожая проблема, которую я обнаружил, сужая привет, демонстрируется index.html:

<body>
<iframe name="foo"></iframe>
<script>
    var idoc= frames['foo'].document;
    idoc.open();
    idoc.write('<body><script src="main.js"><\/script>');
    idoc.close();
</script>

с main.js, содержащим:

document.write('foo');

Фу не написано. (С другой стороны, встроенный скрипт был в порядке.)

Если idoc.close был опущен, это сработало. Если был добавлен дополнительный idoc.write('bar'), bar был записан до foo только в IE. Если я добавил и bar, и close вызов, IE упал.

Итак, подведем итог: глубокие проблемы с использованием document.write изнутри документа, который сам был написан document.write! Старайтесь избегать этого, если это вообще возможно. document.open может быть полезным для заполнения iframe из родительского документа, но вам не нужно его использовать внутри дочернего документа, где вы можете использовать методы DOM для себя.

4 голосов
/ 16 августа 2013

Как уже рассказывало большинство людей, у IE возникают серьезные проблемы при попытке сделать что-то простое, например:

var doc = window.frames['your_frame'].document;
doc.open();
doc.write('<body><script src="external_resource.js"><\/script>');
doc.close();

После исчерпывающего поиска я нашел эту запись , которая предлагает использовать схему URI javascript: для вставки содержимого в документ iframe. Я лично тестировал это решение в текущих версиях FF, Chrome и Safari, а также в IE 7/8/9 / 10.

Заимствуя из его примеров, вместо моего примера сработало бы следующее, и его можно использовать для достижения цели:

var iframe = window.frames['your_frame'];
var content = '<body><script src="external_resource.js"><\/script>';
iframe.contentWindow.contents = content;
iframe.src = 'javascript:window["contents"]';

Я слышал, что в старых версиях Safari не очень хорошо работает схема javascript: URI, но я не смог найти способ подтвердить это, поскольку все, кто использует Safari, регулярно обновляются. Я также не знаю, сталкивается ли это с проблемами ограничения символов для URI в IE (поскольку он меньше, чем у любого другого браузера), но стоит обратить внимание на тех из вас, кто страдает от аналогичной проблемы.

2 голосов
/ 25 ноября 2009

Основная проблема в том, что в IE вы не можете сделать

iframe_document.open();
iframe_document.write('<script src="foo.js"><\/script>');
iframe_document.close();

Как только document.close () вызывается в iframe, IE, кажется, останавливает все выполнение javascript там. Поток js выполняет этот document.close (), в то время как http-запрос для foo.js является ожидающим, поэтому файл загружается, но никогда не выполняется.

Я не нашел способа для родительской страницы узнать, что сценарий, выполняющийся в iframe, полностью завершен. Один из обходных путей - сделать foo.js ответственным за сам вызов метода document.close () - не очень приятно, но если вы не возражаете против изменения вызываемого скрипта, это поможет.

Примечание: вы не должны напрямую копировать document.write ('document.close ()') в iframe: , что приводит к зависанию IE. Но setTimeout (function () {document.close ()}, 0) кажется невосприимчивым - как и document.close () внутри загруженного скрипта иногда . Тьфу.

1 голос
/ 15 ноября 2009

Вы должны загрузить содержимое iframe с атрибутом "src": тело iframe используется браузерами, которые не поддерживают его для отображения альтернативного сообщения. Вместо этого вы вставляете в iframe полный встроенный HTML-документ, и некоторым браузерам это не понравится. Подробнее здесь .

Если вы хотите отправлять сообщения в iframe из основного документа, в блоге Джона Резига .

есть хороший учебник
0 голосов
/ 19 марта 2010

Это странно, и Майкл Клебер ошибается: все предупреждения появляются нормально, поэтому проблема не в том, что скрипт не выполняется. Это выполняет.

Обратите внимание на следующие изменения в main.js:

$(document).ready(function() {

  // note that render() has to be moved into the window scope
  window.render = function(data) {
    document.open();
    alert('opened');
    document.write(data);
    alert('written');
    document.close();
    alert('closed');
  }

  function load() {
    $.ajax({
      url: 'jsonp.js',
      dataType: 'script'
    });
  }

  window.callback = function(data) {
    // does not work
    render(data);

    // works
    window.data = data;
    var t = setTimeout("render(data)", 0);
  }

  load();

});
0 голосов
/ 16 ноября 2009

Будет что-то простое, как:

function render(data) {
    document.body.innerHTML = data;
}

Решить свои проблемы? Работает в IE8 / Win7.

...