गतिशील रूप से दिए गए HTML के साथ एक iframe बनाना


148

मैं जावास्क्रिप्ट से एक iframe बनाने और मनमाने ढंग से HTML के साथ भरने की कोशिश कर रहा हूँ, जैसे:

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

मुझे अपेक्षा होगी iframe तब एक वैध खिड़की और दस्तावेज़ को शामिल करने की । हालाँकि, यह मामला नहीं है:

> कंसोल.लॉग (iframe.contentWindow);
शून्य

इसे अपने लिए आजमाएँ: http://jsfiddle.net/TrevorBurnham/9k9Pe/

मैं क्या देख रहा हूँ?


9
ध्यान दें कि HTML5 ने स्वचालित रूप से ऐसा करने वाला एक नया पैरामीटर पेश किया है: w3schools.com/tags/att_iframe_srcdoc.asp एकमात्र समस्या ब्राउज़र अनुकूलता है ...
विंसेंट औडबर्ट

जवाबों:


121

जावास्क्रिप्ट में 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 का उत्तर देखें।


3
IE10 में भी काम नहीं करता है। @ mschr का उत्तर IE7 + में निश्चित रूप से, शायद पुराने संस्करणों के लिए भी काम करता है।
जेम्स एम। ग्रीन

6
उनका सवाल था "मैं क्या देख रहा हूँ?" और यह तथ्य था कि iframe को दस्तावेज़ में जोड़ा नहीं गया था। मैंने कभी दावा नहीं किया कि यह क्रॉस ब्राउज़र था और यह केवल एक साल से अधिक समय के बाद मैंने उत्तर दिया कि किसी ने वास्तव में शिकायत की थी। नहीं यह क्रॉस ब्राउज़र नहीं है। लेकिन अगर आप कोड गुणवत्ता चाहते हैं तो ईमानदार रहें क्योंकि पहली जगह में एक आइफ्रेम का उपयोग करने की तुलना में शायद बहुत अधिक क्लीनर समाधान है :)
गिलेस्क

1
ध्यान दें कि encodeURI(...)सभी वर्णों को एन्कोड नहीं किया गया है, इसलिए यदि आपके HTML में विशेष वर्ण हैं #, तो यह टूट जाएगा। encodeURIComponent(...)इन पात्रों को एनकोड करता है। इसका जवाब
रयान मोरलोक

237

हालांकि आपका 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();

चूंकि इसमें कोई एक्स-डोमेन प्रतिबंध नहीं है और पूरी तरह से iframeसंभाल के माध्यम से किया जाता है , आप बाद में फ्रेम की सामग्री तक पहुंच और हेरफेर कर सकते हैं। आपको यह सुनिश्चित करने की आवश्यकता है कि सामग्री को प्रदान किया गया है, जो (ब्राउज़र प्रकार के आधार पर) .write कमांड जारी होने के दौरान / बाद में शुरू होता है - लेकिन जब close()इसे कहा जाता है, तब ऐसा नहीं किया जाता है।

कॉलबैक करने का 100% संगत तरीका यह तरीका हो सकता है:

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

इफ्रेम्स में हालांकि ओन्डलोड घटना है। यहाँ आंतरिक html को DOM (js) के रूप में एक्सेस करने का तरीका दिया गया है:

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

दिलचस्प; मैंने इस तकनीक को पहले नहीं देखा था। मुझे पता है कि यूआरआई एन्कोडिंग / डिकोडिंग एक प्रदर्शन हिट जोड़ता है, फिर भी मैंने इसे पर्यावरण में एकमात्र विकल्प के रूप में वर्णित देखा है जो srcdocसंपत्ति का समर्थन नहीं करते हैं । वहाँ document.writeदृष्टिकोण के लिए एक नकारात्मक पहलू है ?
ट्रेवर बर्नहैम

1
@mschr क्या यह विधि पूर्ण HTML पृष्ठ कोड का समर्थन करती है जिसमें शामिल हैं और स्टाइलशीट भी भरी हुई हैं? देखें stackoverflow.com/questions/19871886
1.21 गीगावाट

2
मूल रूप से, हाँ, मेरा मानना ​​है कि यह बीमार होना चाहिए। तकनीक मूल रूप से एक इनपुटटेक्स्टस्ट खोलती है जिसे आप डॉक्यूमेंट.राइट के माध्यम से लिख सकते हैं। बदले में, एक सामान्य लोडिंग वेबपेज एक वेबसोकेट-स्ट्रीम के माध्यम से इसे पुनः प्राप्त करता है।
mschr 21

2
यह Internet Explorer में काम करता है! यह आसान है क्योंकि डेटा URI को IE के किसी भी संस्करण में iframe स्रोतों के रूप में उपयोग नहीं किया जा सकता है। caniuse.com/#feat=datauri
जेसी

2
दिलचस्प है कि इसके document.body.appendChild(iframe)लिए काम करना आवश्यक है।
पॉल

14

आपके महान प्रश्न के लिए धन्यवाद, इसने मुझे कुछ बार पकड़ा है। डेटा स्रोत 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 " मूल के साथ एक फ्रेम को ब्लॉक किया गया ।


12

एक iframe बनाने के लिए एक विकल्प है जिसकी सामग्री HTML का एक स्ट्रिंग है: srcdoc विशेषता । यह पुराने ब्राउज़रों में समर्थित नहीं है (उनमें से प्रमुख: इंटरनेट एक्सप्लोरर, और संभवतः सफारी ?), लेकिन इस व्यवहार के लिए एक पॉलीफ़िल है, जिसे आप IE के लिए सशर्त टिप्पणियों में डाल सकते हैं, या हैज़ की तरह कुछ का उपयोग कर सकते हैं। सशर्त रूप से आलसी होने के लिए। इसे लोड करें।


2
इसके लिए समर्थन अब बहुत मुख्यधारा है (आईई बचाओ)। और यह निश्चित रूप से सीधे contentDocument तक पहुँचने के लिए बेहतर है - खासकर जब से सैंडबॉक्स विशेषता के साथ संयोजन में उपयोग किया जाता है, तो आप contentDocument तक नहीं पहुँच सकते।
कैम्ब्रिजमाइक

1

मुझे पता है कि यह एक पुराना प्रश्न है, लेकिन मुझे लगा कि मैं इस 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);


1

URL का दृष्टिकोण केवल छोटे HTML फ्रेजमेंट के लिए काम करेगा। अधिक ठोस दृष्टिकोण एक ऑब्जेक्ट 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);

0

यह करो

...
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;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.