[javascript] 주어진 HTML로 동적으로 iframe 만들기

JavaScript에서 iframe을 만들고 임의의 HTML로 채우려 고합니다.

var html = '<body>Foo</body>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);

iframe그런 다음 유효한 창과 문서가 포함될 것으로 기대 합니다. 그러나 이것은 사실이 아닙니다.

> console.log (iframe.contentWindow);
없는

직접 사용해보십시오 : http://jsfiddle.net/TrevorBurnham/9k9Pe/

내가 무엇을 간과하고 있습니까?



답변

src새로 작성된 iframe자바 스크립트로 설정하면 요소가 문서에 삽입 될 때까지 HTML 파서가 트리거되지 않습니다. 그런 다음 HTML이 업데이트되고 HTML 파서가 호출되고 속성이 예상대로 처리됩니다.

http://jsfiddle.net/9k9Pe/2/

var iframe = document.createElement('iframe');
var html = '<body>Foo</body>';
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
document.body.appendChild(iframe);
console.log('iframe.contentWindow =', iframe.contentWindow);

또한 귀하의 질문에 대한 답변입니다.이 접근법은 일부 브라우저와의 호환성 문제가 있음을 유의해야합니다. 크로스 브라우저 솔루션에 대한 @mschr의 답변을 참조하십시오.


답변

당신 src = encodeURI이 일해야하지만, 나는 다른 길을 갔을 것입니다 :

var iframe = document.createElement('iframe');
var html = '<body>Foo</body>';
document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();

여기에는 x- 도메인 구속이없고 iframe핸들을 통해 완전히 수행되므로 나중에 프레임의 내용에 액세스하고 조작 할 수 있습니다. .write 명령이 실행되는 동안 / 이후에 (브라우저 유형에 따라) 컨텐츠가 렌더링되는지 확인해야 하지만close() 호출이 불필요하게 완료되지는 않습니다 .

콜백을 수행하는 100 % 호환 가능한 방법은 다음과 같습니다.

<html><body onload="parent.myCallbackFunc(this.window)"></body></html>

그러나 iframe에는 onload 이벤트가 있습니다. 내부 HTML을 DOM (js)으로 액세스하는 방법은 다음과 같습니다.

iframe.onload = function() {
   var div=iframe.contentWindow.document.getElementById('mydiv');
};


답변

당신의 큰 질문에 감사드립니다. dataURI HTML 소스를 사용할 때 완전한 HTML 문서를 정의해야한다는 것을 알게되었습니다.

아래 수정 된 예를 참조하십시오.

var html = '<html><head></head><body>Foo</body></html>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);

<html>태그와 iframe.src문자열로 싸인 html 컨텐츠를 기록하십시오 .

구문 분석하려면 iframe 요소를 DOM 트리에 추가해야합니다.

document.body.appendChild(iframe);

브라우저에서 확인 iframe.contentDocument하지 않으면 검사 할 수 없습니다 disable-web-security. 당신은 메시지가 나타납니다

DOMException : ‘HTMLIFrameElement’에서 ‘contentDocument’속성을 읽지 못했습니다 : 출처가 ” http : // localhost : 7357 “인 프레임이 교차 출처 프레임에 액세스하지 못하도록 차단했습니다.


답변

내용이 HTML 문자열 인 iframe을 만드는 대안이 있습니다 : srcdoc attribute . 이것은 오래된 브라우저 (주로 Internet Explorer 및 아마도 Safari ?)에서 지원되지 않지만 이 동작에 대한 polyfill 이 있습니다 .IE에 대한 조건부 주석을 넣거나 has.js와 같은 것을 사용하여 조건부 게으른 그것을로드하십시오.


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 srcdoc이것이 현재 널리 지원 되고 있으며 이것은 종종 질문으로 여겨 지기 때문에 속성을 사용하는 예제를 제공 할 것이라고 생각했습니다 .

srcdoc속성을 사용하여 삽입 할 인라인 HTML을 제공 할 수 있습니다. src지원되는 경우 속성을 대체합니다 . src지원되지 않는 경우 브라우저는 속성으로 대체됩니다.

sandbox프레임의 내용에 추가 제한을 적용하기 위해 속성을 사용하는 것이 좋습니다 . HTML이 자신의 것이 아닌 경우에 특히 중요합니다.

const iframe = document.createElement('iframe');
const html = '<body>Foo</body>';
iframe.srcdoc = html;
iframe.sandbox = '';
document.body.appendChild(iframe);

이전 브라우저를 지원해야하는 경우 지원 여부를 확인 srcdoc하고 다른 답변에서 다른 방법 중 하나로 대체 할 수 있습니다 .

function setIframeHTML(iframe, html) {
  if (typeof iframe.srcdoc !== 'undefined') {
    iframe.srcdoc = html;
  } else {
    iframe.sandbox = 'allow-same-origin';
    iframe.contentWindow.document.open();
    iframe.contentWindow.document.write(html);
    iframe.contentWindow.document.close();
  }
}

var iframe = document.createElement('iframe');
iframe.sandbox = '';
var html = '<body>Foo</body>';

document.body.appendChild(iframe);
setIframeHTML(iframe, html);


답변

URL 접근 방식은 작은 HTML 조각에 대해서만 작동합니다. 보다 확실한 접근 방법은 Blob에서 객체 URL을 생성하여 동적 iframe의 소스로 사용하는 것입니다.

const html = '<html>...</html>';
const iframe = document.createElement('iframe');
const blob = new Blob([html], {type: 'text/html'});
iframe.src = window.URL.createObjectURL(blob);
document.body.appendChild(iframe);


답변

이 작업을 수행

...
var el = document.getElementById('targetFrame');

var frame_win = getIframeWindow(el);

console.log(frame_win);
...

getIframeWindow 가 여기에 정의되어 있습니다.

function getIframeWindow(iframe_object) {
  var doc;

  if (iframe_object.contentWindow) {
    return iframe_object.contentWindow;
  }

  if (iframe_object.window) {
    return iframe_object.window;
  }

  if (!doc && iframe_object.contentDocument) {
    doc = iframe_object.contentDocument;
  }

  if (!doc && iframe_object.document) {
    doc = iframe_object.document;
  }

  if (doc && doc.defaultView) {
   return doc.defaultView;
  }

  if (doc && doc.parentWindow) {
    return doc.parentWindow;
  }

  return undefined;
}