जावास्क्रिप्ट का उपयोग करके एक अलग मूल iFrame के साथ बातचीत करना संभव नहीं है ताकि इसका आकार प्राप्त कर सके; यह करने के लिए एक ही रास्ता का उपयोग करना है window.postMessage
के साथ targetOrigin
अपने डोमेन के लिए सेट या wildchar *
iFrame स्रोत से। आप विभिन्न मूल साइटों और उपयोग की सामग्रियों को प्रॉक्सी कर सकते हैं srcdoc
, लेकिन इसे हैक माना जाता है और यह एसपीए और कई अन्य अधिक गतिशील पृष्ठों के साथ काम नहीं करेगा।
एक ही मूल iFrame आकार
मान लें कि हमारे पास दो समान मूल iFrames हैं, एक छोटी ऊंचाई और निश्चित चौड़ाई:
<!-- iframe-short.html -->
<head>
<style type="text/css">
html, body { margin: 0 }
body {
width: 300px;
}
</style>
</head>
<body>
<div>This is an iFrame</div>
<span id="val">(val)</span>
</body>
और एक लंबी ऊंचाई iFrame:
<!-- iframe-long.html -->
<head>
<style type="text/css">
html, body { margin: 0 }
#expander {
height: 1200px;
}
</style>
</head>
<body>
<div>This is a long height iFrame Start</div>
<span id="val">(val)</span>
<div id="expander"></div>
<div>This is a long height iFrame End</div>
<span id="val">(val)</span>
</body>
हम load
इवेंट पर iFrame का आकार प्राप्त कर सकते हैं, iframe.contentWindow.document
जिसका उपयोग करके हम मूल विंडो पर भेजेंगे postMessage
:
<div>
<iframe id="iframe-local" src="iframe-short.html"></iframe>
</div>
<div>
<iframe id="iframe-long" src="iframe-long.html"></iframe>
</div>
<script>
function iframeLoad() {
window.top.postMessage({
iframeWidth: this.contentWindow.document.body.scrollWidth,
iframeHeight: this.contentWindow.document.body.scrollHeight,
params: {
id: this.getAttribute('id')
}
});
}
window.addEventListener('message', ({
data: {
iframeWidth,
iframeHeight,
params: {
id
} = {}
}
}) => {
// We add 6 pixels because we have "border-width: 3px" for all the iframes
if (iframeWidth) {
document.getElementById(id).style.width = `${iframeWidth + 6}px`;
}
if (iframeHeight) {
document.getElementById(id).style.height = `${iframeHeight + 6}px`;
}
}, false);
document.getElementById('iframe-local').addEventListener('load', iframeLoad);
document.getElementById('iframe-long').addEventListener('load', iframeLoad);
</script>
हम दोनों iFrames के लिए उचित चौड़ाई और ऊंचाई प्राप्त करेंगे; आप इसे यहाँ ऑनलाइन देख सकते हैं और यहाँ स्क्रीनशॉट देख सकते हैं ।
अलग मूल iFrame आकार हैक (पुनः नहीं मिला )
यहां वर्णित विधि एक हैक है और इसका उपयोग किया जाना चाहिए यदि यह बिल्कुल आवश्यक है और आसपास कोई अन्य तरीका नहीं है; यह सबसे गतिशील उत्पन्न पृष्ठों और एसपीए के लिए काम नहीं करेगा । विधि पृष्ठ HTML स्रोत कोड को एक प्रॉक्सी का उपयोग करके CORS पॉलिसी को बायपास करती है ( cors-anywhere
यह एक सरल CORS प्रॉक्सी सर्वर बनाने का एक आसान तरीका है और इसका ऑनलाइन डेमो हैhttps://cors-anywhere.herokuapp.com
) यह JS कोड को उस HTML में उपयोग करने postMessage
और आकार भेजने के लिए इंजेक्ट करता है। मूल दस्तावेज़ में iFrame। यहां तक कि यह iFrame resize
( iFrame के साथ संयुक्तwidth: 100%
) घटना को संभालता है और iFrame के आकार को वापस माता-पिता को पोस्ट करता है।
patchIframeHtml
:
एक समारोह iFrame HTML कोड और इंजेक्षन कस्टम जावास्क्रिप्ट का उपयोग करेगा पैच करने के लिए postMessage
पर माता-पिता में iFrame आकार भेजने के लिए load
और पर resize
। यदि origin
पैरामीटर के लिए कोई मान है , तो <base/>
उस मूल URL का उपयोग करके एक HTML तत्व को सिर पर रखा जाएगा, इस प्रकार, HTML यूआरआई जैसे /some/resource/file.ext
iFrame के अंदर मूल URL द्वारा ठीक से प्राप्त किया जाएगा।
function patchIframeHtml(html, origin, params = {}) {
// Create a DOM parser
const parser = new DOMParser();
// Create a document parsing the HTML as "text/html"
const doc = parser.parseFromString(html, 'text/html');
// Create the script element that will be injected to the iFrame
const script = doc.createElement('script');
// Set the script code
script.textContent = `
window.addEventListener('load', () => {
// Set iFrame document "height: auto" and "overlow-y: auto",
// so to get auto height. We set "overlow-y: auto" for demontration
// and in usage it should be "overlow-y: hidden"
document.body.style.height = 'auto';
document.body.style.overflowY = 'auto';
poseResizeMessage();
});
window.addEventListener('resize', poseResizeMessage);
function poseResizeMessage() {
window.top.postMessage({
// iframeWidth: document.body.scrollWidth,
iframeHeight: document.body.scrollHeight,
// pass the params as encoded URI JSON string
// and decode them back inside iFrame
params: JSON.parse(decodeURIComponent('${encodeURIComponent(JSON.stringify(params))}'))
}, '*');
}
`;
// Append the custom script element to the iFrame body
doc.body.appendChild(script);
// If we have an origin URL,
// create a base tag using that origin
// and prepend it to the head
if (origin) {
const base = doc.createElement('base');
base.setAttribute('href', origin);
doc.head.prepend(base);
}
// Return the document altered HTML that contains the injected script
return doc.documentElement.outerHTML;
}
getIframeHtml
:
एक पृष्ठ HTML पाने के लिए एक फ़ंक्शन यदि useProxy
पैराम सेट किया गया है तो प्रॉक्सी का उपयोग करके कोर को बायपास करें । अतिरिक्त पैरामीटर हो सकते हैं जो postMessage
आकार डेटा भेजते समय पारित हो जाएंगे ।
function getIframeHtml(url, useProxy = false, params = {}) {
return new Promise(resolve => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
// If we use a proxy,
// set the origin so it will be placed on a base tag inside iFrame head
let origin = useProxy && (new URL(url)).origin;
const patchedHtml = patchIframeHtml(xhr.responseText, origin, params);
resolve(patchedHtml);
}
}
// Use cors-anywhere proxy if useProxy is set
xhr.open('GET', useProxy ? `https://cors-anywhere.herokuapp.com/${url}` : url, true);
xhr.send();
});
}
संदेश ईवेंट हैंडलर फ़ंक्शन "समान मूल iFrame आकार" के समान है ।
अब हम अपने कस्टम JS कोड के साथ iFrame के अंदर एक क्रॉस ओरिजिनल डोमेन लोड कर सकते हैं:
<!-- It's important that the iFrame must have a 100% width
for the resize event to work -->
<iframe id="iframe-cross" style="width: 100%"></iframe>
<script>
window.addEventListener('DOMContentLoaded', async () => {
const crossDomainHtml = await getIframeHtml(
'https://en.wikipedia.org/wiki/HTML', true /* useProxy */, { id: 'iframe-cross' }
);
// We use srcdoc attribute to set the iFrame HTML instead of a src URL
document.getElementById('iframe-cross').setAttribute('srcdoc', crossDomainHtml);
});
</script>
और हम iFrame को आकार देने के लिए इसे पूरी ऊंचाई तक बिना किसी लंबवत स्क्रॉलिंग के उपयोग overflow-y: auto
करेंगे, यहां तक कि iFrame बॉडी के लिए भी इसका उपयोग कर सकते हैं ( ऐसा होना चाहिए overflow-y: hidden
कि हमें स्क्रॉलबार को आकार बदलने पर फ़्लिकर न मिले )।
आप इसे यहाँ ऑनलाइन देख सकते हैं ।
फिर से ध्यान दें कि यह एक हैक है और इसे टाला जाना चाहिए ; हम क्रॉस-ऑरिजिन iFrame डॉक्यूमेंट को एक्सेस नहीं कर सकते हैं और न ही किसी तरह की चीजों को इंजेक्ट कर सकते हैं।