ฉันลองวิธีแก้ปัญหาเล็กน้อย แต่ไม่ประสบความสำเร็จ ฉันสงสัยว่ามีวิธีแก้ปัญหาหรือไม่โดยเฉพาะอย่างยิ่งกับบทช่วยสอนที่ทำตามได้ง่าย
ฉันลองวิธีแก้ปัญหาเล็กน้อย แต่ไม่ประสบความสำเร็จ ฉันสงสัยว่ามีวิธีแก้ปัญหาหรือไม่โดยเฉพาะอย่างยิ่งกับบทช่วยสอนที่ทำตามได้ง่าย
คำตอบ:
คุณมีทางเลือกสามทาง:
นี่คือไลบรารีที่เรียบง่ายสำหรับการรักษาขนาด iFrames ให้เข้ากับเนื้อหา มันใช้ PostMessage และ MutationObserver APIs พร้อมถอยกลับสำหรับ IE8-10 นอกจากนี้ยังมีตัวเลือกสำหรับหน้าเนื้อหาเพื่อขอให้ iFrame มีขนาดที่แน่นอนและยังสามารถปิด iFrame ได้เมื่อคุณทำเสร็จแล้ว
https://github.com/davidjbradshaw/iframe-resizer
Easy XDM ใช้ชุดเทคนิคสำหรับการเปิดใช้งานการสื่อสารข้ามโดเมนระหว่างหน้าต่างต่างๆในเบราว์เซอร์จำนวนมากและมีตัวอย่างสำหรับการใช้สำหรับการปรับขนาด iframe:
http://easyxdm.net/wp/2010/03/17/resize-iframe-based-on-content/
http://kinsey.no/blog/index.php/2010/02/19/resizing-iframes-using-easyxdm/
Easy XDM ทำงานโดยใช้PostMessageบนเบราว์เซอร์สมัยใหม่และโซลูชันที่ใช้ Flash เป็นทางเลือกสำหรับเบราว์เซอร์รุ่นเก่า
ดูหัวข้อนี้ใน Stackoverflow (ยังมีอื่น ๆ อีกด้วยนี่เป็นคำถามที่ถามบ่อย) นอกจากนี้Facebook ก็ดูเหมือนจะใช้วิธีการที่คล้ายกัน
อีกทางเลือกหนึ่งคือการส่งความสูงของ iframe ไปยังเซิร์ฟเวอร์ของคุณจากนั้นทำการสำรวจความคิดเห็นจากเซิร์ฟเวอร์นั้นจากหน้าเว็บหลักด้วย JSONP (หรือใช้แบบสำรวจความยาวหากเป็นไปได้)
ฉันมีวิธีแก้ปัญหาในการตั้งค่าความสูงของ iframe แบบไดนามิกตามเนื้อหา สิ่งนี้ใช้ได้กับเนื้อหาข้ามโดเมน มีบางขั้นตอนในการปฏิบัติตามเพื่อให้บรรลุเป้าหมายนี้
สมมติว่าคุณได้เพิ่ม iframe ในหน้าเว็บ "abc.com/page"
<div>
<iframe id="IframeId" src="http://xyz.pqr/contactpage" style="width:100%;" onload="setIframeHeight(this)"></iframe>
</div>
ถัดไปคุณต้องผูกเหตุการณ์ "ข้อความ" ของ windows ภายใต้หน้าเว็บ "abc.com/page"
window.addEventListener('message', function (event) {
//Here We have to check content of the message event for safety purpose
//event data contains message sent from page added in iframe as shown in step 3
if (event.data.hasOwnProperty("FrameHeight")) {
//Set height of the Iframe
$("#IframeId").css("height", event.data.FrameHeight);
}
});
ในการโหลด iframe คุณต้องส่งข้อความไปยังเนื้อหาหน้าต่าง iframe พร้อมข้อความ "FrameHeight":
function setIframeHeight(ifrm) {
var height = ifrm.contentWindow.postMessage("FrameHeight", "*");
}
window.addEventListener('message', function (event) {
// Need to check for safety as we are going to process only our messages
// So Check whether event with data(which contains any object) contains our message here its "FrameHeight"
if (event.data == "FrameHeight") {
//event.source contains parent page window object
//which we are going to use to send message back to main page here "abc.com/page"
//parentSourceWindow = event.source;
//Calculate the maximum height of the page
var body = document.body, html = document.documentElement;
var height = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
// Send height back to parent page "abc.com/page"
event.source.postMessage({ "FrameHeight": height }, "*");
}
});
สิ่งที่ฉันทำคือเปรียบเทียบ iframe scrollWidth จนกว่าจะเปลี่ยนขนาดในขณะที่ฉันตั้งค่า IFrame Height เพิ่มขึ้น และมันก็ใช้ได้ดีสำหรับฉัน คุณสามารถปรับส่วนเพิ่มตามต้องการได้
<script type="text/javascript">
function AdjustIFrame(id) {
var frame = document.getElementById(id);
var maxW = frame.scrollWidth;
var minW = maxW;
var FrameH = 100; //IFrame starting height
frame.style.height = FrameH + "px"
while (minW == maxW) {
FrameH = FrameH + 100; //Increment
frame.style.height = FrameH + "px";
minW = frame.scrollWidth;
}
}
</script>
<iframe id="RefFrame" onload="AdjustIFrame('RefFrame');" class="RefFrame"
src="http://www.YourUrl.com"></iframe>
ฉันมีสคริปต์ที่ดรอปใน iframe พร้อมกับเนื้อหา นอกจากนี้ยังตรวจสอบให้แน่ใจว่ามี iFrameResizer อยู่ (มันฉีดเป็นสคริปต์) จากนั้นทำการปรับขนาด
ฉันจะปล่อยตัวอย่างง่ายๆด้านล่างนี้
// /js/embed-iframe-content.js
(function(){
// Note the id, we need to set this correctly on the script tag responsible for
// requesting this file.
var me = document.getElementById('my-iframe-content-loader-script-tag');
function loadIFrame() {
var ifrm = document.createElement('iframe');
ifrm.id = 'my-iframe-identifier';
ifrm.setAttribute('src', 'http://www.google.com');
ifrm.style.width = '100%';
ifrm.style.border = 0;
// we initially hide the iframe to avoid seeing the iframe resizing
ifrm.style.opacity = 0;
ifrm.onload = function () {
// this will resize our iframe
iFrameResize({ log: true }, '#my-iframe-identifier');
// make our iframe visible
ifrm.style.opacity = 1;
};
me.insertAdjacentElement('afterend', ifrm);
}
if (!window.iFrameResize) {
// We first need to ensure we inject the js required to resize our iframe.
var resizerScriptTag = document.createElement('script');
resizerScriptTag.type = 'text/javascript';
// IMPORTANT: insert the script tag before attaching the onload and setting the src.
me.insertAdjacentElement('afterend', ifrm);
// IMPORTANT: attach the onload before setting the src.
resizerScriptTag.onload = loadIFrame;
// This a CDN resource to get the iFrameResizer code.
// NOTE: You must have the below "coupled" script hosted by the content that
// is loaded within the iframe:
// https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.contentWindow.min.js
resizerScriptTag.src = 'https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.min.js';
} else {
// Cool, the iFrameResizer exists so we can just load our iframe.
loadIFrame();
}
}())
จากนั้นสามารถแทรกเนื้อหา iframe ที่ใดก็ได้ภายในเพจ / ไซต์อื่นโดยใช้สคริปต์ดังนี้:
<script
id="my-iframe-content-loader-script-tag"
type="text/javascript"
src="/js/embed-iframe-content.js"
></script>
เนื้อหา iframe จะถูกแทรกด้านล่างทุกที่ที่คุณวางแท็กสคริปต์
หวังว่านี่จะเป็นประโยชน์กับใครบางคน 👍
<script ... data-src="http://google.com">
และเติม iframe src ด้วย
iframe-resizer@4.2.10
นี่คือวิธีง่ายๆของฉันที่หน้านี้ http://lab.ohshiftlabs.com/iframesize/
นี่คือวิธีการทำงาน
โดยทั่วไปหากคุณสามารถแก้ไขเพจที่โดเมนอื่นได้คุณสามารถวางเพจ iframe อื่นที่เป็นของเซิร์ฟเวอร์ของคุณซึ่งช่วยประหยัดความสูงให้กับคุกกี้ได้ เมื่อมีการอัปเดตช่วงเวลาอ่านคุกกี้ให้อัปเดตความสูงของ iframe นั้นคือทั้งหมด.
ดาวน์โหลด; http://lab.ohshiftlabs.com/iframesize/iframesizepost.zip
แก้ไข: 2019 ธันวาคม
วิธีแก้ปัญหาข้างต้นโดยทั่วไปจะใช้ iframe อื่นภายใน iframe 3rd iframe ซึ่งเป็นของโดเมนหน้าบนสุดซึ่งคุณเรียกหน้านี้ด้วยสตริงข้อความค้นหาที่บันทึกค่าขนาดลงในคุกกี้หน้านอกจะตรวจสอบข้อความค้นหานี้ด้วยช่วงเวลาบางช่วง แต่ไม่ใช่วิธีแก้ปัญหาที่ดีดังนั้นคุณควรปฏิบัติตามวิธีนี้:
ในหน้าแรก:
window.addEventListener("message", (m)=>{iframeResizingFunction(m)});
คุณสามารถตรวจสอบได้m.origin
ที่นี่ว่ามาจากไหน
ในหน้าเฟรม:
window.parent.postMessage({ width: 640, height:480 }, "*")
แม้ว่าโปรดอย่าลืมว่านี่ไม่ใช่วิธีที่ปลอดภัย เพื่อให้มีการอัปเดตที่ปลอดภัย * ค่า (targetOrigin) ด้วยค่าที่คุณต้องการ โปรดติดตามเอกสาร: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
ฉันพบโซลูชันฝั่งเซิร์ฟเวอร์อื่นสำหรับนักพัฒนาเว็บโดยใช้ PHP เพื่อรับขนาดของ iframe
อันดับแรกคือการใช้สคริปต์เซิร์ฟเวอร์ PHP เพื่อโทรภายนอกผ่านฟังก์ชันภายใน: (เช่น a file_get_contents
with แต่ curl และ dom)
function curl_get_file_contents($url,$proxyActivation=false) {
global $proxy;
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7");
curl_setopt($c, CURLOPT_REFERER, $url);
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
if($proxyActivation) {
curl_setopt($c, CURLOPT_PROXY, $proxy);
}
$contents = curl_exec($c);
curl_close($c);
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
@$dom->loadHTML($contents);
$form = $dom->getElementsByTagName("body")->item(0);
if ($contents) //si on a du contenu
return $dom->saveHTML();
else
return FALSE;
}
$url = "http://www.google.com"; //Exernal url test to iframe
<html>
<head>
<script type="text/javascript">
</script>
<style type="text/css">
#iframe_reserve {
width: 560px;
height: 228px
}
</style>
</head>
<body>
<div id="iframe_reserve"><?php echo curl_get_file_contents($url); ?></div>
<iframe id="myiframe" src="http://www.google.com" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" style="overflow:none; width:100%; display:none"></iframe>
<script type="text/javascript">
window.onload = function(){
document.getElementById("iframe_reserve").style.display = "block";
var divHeight = document.getElementById("iframe_reserve").clientHeight;
document.getElementById("iframe_reserve").style.display = "none";
document.getElementById("myiframe").style.display = "block";
document.getElementById("myiframe").style.height = divHeight;
alert(divHeight);
};
</script>
</body>
</html>
คุณต้องแสดงภายใต้ div ( iframe_reserve
) html ที่สร้างโดยการเรียกใช้ฟังก์ชันโดยใช้ไฟล์echo curl_get_file_contents("location url iframe","activation proxy")
หลังจากทำสิ่งนี้แล้วฟังก์ชัน body event onload ด้วย javascript จะใช้ความสูงของหน้า iframe เพียงแค่ควบคุม div เนื้อหา ( iframe_reserve
)
ดังนั้นฉันใช้divHeight = document.getElementById("iframe_reserve").clientHeight;
เพื่อรับความสูงของหน้าภายนอกที่เราจะเรียกหลังจากมาสก์คอนเทนเนอร์ div ( iframe_reserve
) หลังจากนี้เราโหลด iframe ด้วยความสูงที่ดีนั่นคือทั้งหมด
ฉันพบปัญหานี้ขณะทำงานบางอย่างในที่ทำงาน (โดยใช้ React) โดยทั่วไปเรามีเนื้อหา html ภายนอกที่เราบันทึกลงในตารางเอกสารของเราในฐานข้อมูลจากนั้นแทรกลงในหน้าภายใต้สถานการณ์บางอย่างเมื่อคุณอยู่ในชุดข้อมูลเอกสาร
ดังนั้นเมื่อกำหนดอินไลน์n
ซึ่งn
อาจมี html ภายนอกได้เราจึงจำเป็นต้องคิดค้นระบบเพื่อปรับขนาด iframe ของอินไลน์แต่ละอันโดยอัตโนมัติเมื่อเนื้อหาโหลดเต็มในแต่ละรายการ หลังจากหมุนวงล้อไปสักหน่อยนี่คือวิธีที่ฉันทำมัน:
message
ฟังเหตุการณ์ในดัชนีของแอป React ของเราซึ่งตรวจสอบคีย์เฉพาะที่เราจะตั้งค่าจาก iframe ของผู้ส่ง<script>
แท็กที่จะรอให้ iframe window.onload
เริ่มทำงาน เมื่อไฟเริ่มทำงานเราจะใช้postMessage
เพื่อส่งข้อความไปยังหน้าต่างหลักพร้อมข้อมูลเกี่ยวกับรหัส iframe ความสูงที่คำนวณเป็นต้นid
ของ iframe ที่เราส่งผ่านในMessageEvent
ออบเจ็กต์iframe
เพียงแค่ตั้งค่าความสูงจากค่าที่ส่งผ่านจาก postMessage
iframe// index
if (window.postMessage) {
window.addEventListener("message", (messageEvent) => {
if (
messageEvent.data.origin &&
messageEvent.data.origin === "company-name-iframe"
) {
const iframe = document.getElementById(messageEvent.data.id)
// this is the only way to ensure that the height of the iframe container matches its body height
iframe.style.height = `${messageEvent.data.height}px`
// by default, the iframe will not expand to fill the width of its parent
iframe.style.width = "100%"
// the iframe should take precedence over all pointer events of its immediate parent
// (you can still click around the iframe to segue, for example, but all content of the iframe
// will act like it has been directly inserted into the DOM)
iframe.style.pointerEvents = "all"
// by default, iframes have an ugly web-1.0 border
iframe.style.border = "none"
}
})
}
// in component that renders n iframes
<iframe
id={`${props.id}-iframe`}
src={(() => {
const html = [`data:text/html,${encodeURIComponent(props.thirdLineData)}`]
if (window.parent.postMessage) {
html.push(
`
<script>
window.onload = function(event) {
window.parent.postMessage(
{
height: document.body.scrollHeight,
id: "${props.id}-iframe",
origin: "company-name-iframe",
},
"${window.location.origin}"
);
};
</script>
`
)
}
return html.join("\n")
})()}
onLoad={(event) => {
// if the browser does not enforce a cross-origin policy,
// then just access the height directly instead
try {
const { target } = event
const contentDocument = (
target.contentDocument ||
// Earlier versions of IE or IE8+ where !DOCTYPE is not specified
target.contentWindow.document
)
if (contentDocument) {
target.style.height = `${contentDocument.body.scrollHeight}px`
}
} catch (error) {
const expectedError = (
`Blocked a frame with origin "${window.location.origin}" ` +
`from accessing a cross-origin frame.`
)
if (error.message !== expectedError) {
/* eslint-disable no-console */
console.err(
`An error (${error.message}) ocurred while trying to check to see ` +
"if the inner iframe is accessible or not depending " +
"on the browser cross-origin policy"
)
}
}
}}
/>