ฉันจะปรับขนาด iframe จากโดเมนอื่นได้อย่างไร
- แก้ไข
เลื่อนลงเพื่อดูวิธีแก้ปัญหา .. หรืออ่านวิธีการไม่ทำสิ่งนี้
หลังจากแฮ็กโค้ดหลายชั่วโมงข้อสรุปก็คือไม่สามารถเข้าถึงสิ่งใด ๆ ภายใน iframe ได้แม้แต่แถบเลื่อนที่แสดงผลบนโดเมนของฉัน ฉันได้ลองใช้เทคนิคมากมายแล้วก็ไม่เกิดประโยชน์
เพื่อช่วยคุณประหยัดเวลาอย่าแม้แต่ไปตามเส้นทางนี้เพียงแค่ใช้ sendMessages สำหรับการสื่อสารข้ามโดเมน มีปลั๊กอินสำหรับ HTML <5 ที่ฉันใช้ - ไปที่ด้านล่างเพื่อดูตัวอย่างที่ดี :)
ไม่กี่วันที่ผ่านมาฉันพยายามรวม iframe เข้ากับไซต์ นี่เป็นวิธีแก้ปัญหาระยะสั้นในขณะที่อีกด้านหนึ่งพัฒนาและ API (อาจใช้เวลาหลายเดือน ... ) และเนื่องจากนี่เป็นวิธีการแก้ปัญหาระยะสั้นที่เราต้องการใช้ easyXDM - ฉันสามารถเข้าถึงโดเมนอื่นได้ แต่ก็ยากพอที่จะขอให้พวกเขา เพิ่ม p3p header ตามที่เป็น .....
3 iframe
ทางออกที่ใกล้เคียงที่สุดที่ฉันพบคือ 3 iframes - แต่มันเป็นไปในแง่ของ Chrome และ Safari ดังนั้นฉันจึงไม่สามารถใช้สิ่งนั้น
เปิดใน chrome
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179
วัดแถบเลื่อน
ฉันพบโพสต์อื่นเกี่ยวกับวิธีใช้ scrollheight เพื่อลองและปรับขนาดฟอร์ม .. ในทางทฤษฎีมันใช้ได้ดี แต่ฉันไม่สามารถใช้มันอย่างถูกต้องโดยใช้ความสูงของการเลื่อน iframe
document.body.scrollHeight
สิ่งนั้นใช้ความสูงของร่างกายอย่างไม่เหมาะสม (ไม่สามารถเข้าถึงคุณสมบัติเหล่านี้ได้ 100% ขึ้นอยู่กับ canvaz ที่ไคลเอ็นต์แสดงและไม่ใช่ความสูงของเอกสาร x-domains)
ฉันลองใช้ jquery เพื่อรับความสูงของ iframe
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
ส่งคืนค่าที่แตกต่างกันใน chrome และ ie - หรือไม่สมเหตุสมผลเลย ปัญหาคือทุกอย่างในเฟรมถูกปฏิเสธแม้กระทั่งแถบเลื่อน ...
รูปแบบการคำนวณ
แต่ถ้าฉันตรวจสอบและองค์ประกอบในโครเมี่ยมของ iframe มัน bladdy แสดงขนาดเอกสารภายใน iframe (โดยใช้ jquery x-domain เพื่อรับ iframe.heigh - การเข้าถึงถูกปฏิเสธ) ไม่มีอะไรใน CSS ที่คำนวณ
ตอนนี้ Chrome คำนวณได้อย่างไร? (แก้ไข - เบราว์เซอร์แสดงผลหน้าเว็บอีกครั้งโดยใช้บิลด์ในเอ็นจิ้นการเรนเดอร์เพื่อคำนวณการตั้งค่าเหล่านี้ทั้งหมด - แต่ไม่ได้เชื่อมต่อที่ใดก็ได้เพื่อป้องกันการฉ้อโกงข้ามโดเมน .. ดังนั้น .. )
HTML4
ฉันอ่านข้อกำหนดของ HTML4.x และมันบอกว่าควรมีค่าอ่านอย่างเดียวที่เปิดเผยผ่าน document.element แต่การเข้าถึงถูกปฏิเสธผ่าน jquery
กรอบพร็อกซี
ฉันเดินไปตามเส้นทางของการพร็อกซีไซต์กลับและคำนวณว่าตกลง .. จนกว่าผู้ใช้จะเข้าสู่ระบบผ่าน iframe และพร็อกซีจะได้รับหน้าเข้าสู่ระบบแทนเนื้อหาจริง นอกจากนี้สำหรับบางคนที่เรียกหน้าสองครั้งก็ไม่เป็นที่ยอมรับ
http://www.codeproject.com/KB/aspnet/asproxy.aspx
http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/
Re-Render หน้า
ฉันไม่ได้ไปไกลขนาดนี้ แต่มีเอ็นจิ้น jscript อยู่ที่นั่นซึ่งจะดูแหล่งที่มาและแสดงผลหน้าเว็บอีกครั้งตามไฟล์ต้นฉบับ แต่มันจะต้องมีการแฮ็ก jscripts เหล่านั้น .. และนั่นไม่ใช่สถานการณ์ที่เหมาะสำหรับเอนทิตีเชิงพาณิชย์ ...
http://en.wikipedia.org/wiki/Server-side_JavaScript
http://htmlunit.sourceforge.net/ <-java ไม่ใช่ jscript
แก้ไข 09-2013 อัพเดท
ทั้งหมดนี้สามารถทำได้ด้วยซ็อกเก็ต HTML5 แต่ easyXDM เป็นทางเลือกที่ดีสำหรับหน้าร้องเรียนที่ไม่ใช่ HTML5
โซลูชันที่ 1 ทางออกที่ยอดเยี่ยมมาก!
ใช้ easyXDM
บนเซิร์ฟเวอร์ของคุณคุณตั้งค่าเพจในรูปแบบ
<html>
<head>
<script src="scripts/easyXDM.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
var transport = new easyXDM.Socket(/** The configuration */{
remote: "http://www.OTHERDOMAIN.com/resize_intermediate.html?url=testpages/resized_iframe_1.html",
//ID of the element to attach the inline frame to
container: "embedded",
onMessage: function (message, origin) {
var settings = message.split(",");
//Use jquery on a masterpage.
//$('iframe').height(settings[0]);
//$('iframe').width(settings[1]);
//The normal solution without jquery if not using any complex pages (default)
this.container.getElementsByTagName("iframe")[0].style.height = settings[0];
this.container.getElementsByTagName("iframe")[0].style.width = settings[1];
}
});
</script>
</head>
<body>
<div id="embedded"></div>
</body>
และบนโดเมนผู้โทรพวกเขาเพียงแค่ต้องเพิ่ม intermiedate_frame html และ easyXDM.js ในที่เดียวกัน เช่นเดียวกับโฟลเดอร์หลักคุณสามารถเข้าถึงไดเร็กทอรีสัมพัทธ์หรือโฟลเดอร์ที่มีอยู่สำหรับคุณโดยเฉพาะ
ตัวเลือกที่ 1
หากคุณไม่ต้องการเพิ่มสคริปต์ในทุกหน้าให้ดูที่ตัวเลือกที่ 2!
จากนั้นพวกเขาสามารถเพิ่ม jscript แบบธรรมดาที่ส่วนท้ายของแต่ละหน้าที่คุณต้องการให้การปรับขนาดเกิดขึ้น ไม่จำเป็นต้องรวม easyxdm ไว้ในแต่ละหน้า
<script type="text/javascript">
window.onload = function(){ parent.socket.postMessage( (parseInt(document.body.clientHeight)) + "," + ( document.body.clientWidth ) ); };
</script>
ฉันได้แก้ไขพารามิเตอร์ที่ส่งไป หากคุณต้องการให้ความกว้างทำงานได้อย่างถูกต้องหน้าในโดเมนอื่นจะต้องมีความกว้างของหน้าในลักษณะที่มีลักษณะคล้ายกับ:
<style type="text/css">
html, body {
overflow: hidden;
margin: 0px;
padding: 0px;
background-color: rgb(75,0,85);
color:white;
width:660px
}
a {
color:white;
visited:white;
}
</style>
สิ่งนี้ใช้ได้ดีสำหรับฉัน หากไม่รวมความกว้างเฟรมจะทำงานแปลก ๆ เล็กน้อยและพยายามเดาว่ามันควรจะเป็นอะไร .. และจะไม่ย่อขนาดลงหากคุณต้องการ
ตัวเลือก 2
แก้ไขกรอบกลางเพื่อสำรวจความเปลี่ยนแปลง
กรอบกลางของคุณควรมีลักษณะดังนี้ ..
<!doctype html>
<html>
<head>
<title>Frame</title>
<script type="text/javascript" src="easyXDM.js">
</script>
<script type="text/javascript">
var iframe;
var socket = new easyXDM.Socket({
//This is a fallback- not needed in many cases
swf: "easyxdm.swf",
onReady: function(){
iframe = document.createElement("iframe");
iframe.frameBorder = 0;
document.body.appendChild(iframe);
iframe.src = "THE HOST FRAME";
iframe.onchange = messageBack();
},
onMessage: function(url, origin){
iframe.src = url;
}
});
//Probe child.frame for dimensions.
function messageBack(){
socket.postMessage ( iframe.contentDocument.body.clientHeight + "," + iframe.contentDocument.body.clientWidth);
};
//Poll for changes on children every 500ms.
setInterval("messageBack()",500);
</script>
<style type="text/css">
html, body {
overflow: hidden;
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
iframe {
width: 100%;
height: 100%;
border: 0px;
}
</style>
</head>
<body>
</body>
</html>
ช่วงเวลาสามารถทำให้มีประสิทธิภาพมากขึ้นในการกำหนดขนาดหากขนาดมีการเปลี่ยนแปลงและส่งเฉพาะในกรณีที่มิติเปลี่ยนแปลงไม่ใช่การโพสต์ข้อความทุกๆ 500 มิลลิวินาที หากคุณใช้การตรวจสอบนี้คุณสามารถเปลี่ยนการสำรวจต่ำสุด 50 มิลลิวินาทีได้! มีความสุข
ทำงานบนเบราว์เซอร์และรวดเร็ว คุณสมบัติการแก้จุดบกพร่องที่ยอดเยี่ยม !!
Excellent Work to Sean Kinsey who made the script!!!
โซลูชันที่ 2 (ใช้งานได้ แต่ไม่ดี)
ดังนั้นโดยพื้นฐานแล้วหากคุณมีข้อตกลงร่วมกันกับโดเมนอื่นคุณสามารถเพิ่มไลบรารีเพื่อจัดการการส่งข้อความได้ หากคุณไม่สามารถเข้าถึงโดเมนอื่นได้ .. มองหาแฮ็กเพิ่มเติมต่อไปเพราะฉันไม่สามารถหาหรือแก้ไขสิ่งเหล่านี้ได้ทั้งหมด
ดังนั้นโดเมนอื่นจะรวมสิ่งเหล่านี้ไว้ในแท็ก Head ด้วย
<script src="scripts/jquery-1.5.2.min.js" type="text/javascript"></script>
<script src="scripts/jquery.postmessage.min.js" type="text/javascript"></script>
<script src="scripts/club.js" type="text/javascript"></script>
ใน club.js เป็นเพียงการโทรที่กำหนดเองบางส่วนที่ฉันสร้างขึ้นเพื่อปรับขนาดการโทรและมี ..
$(document).ready(function () {
var parent_url = decodeURIComponent( document.location.hash.replace( /^#/, '' ) ),link;
//Add source url hash to each url to authorise callback when navigating inside the frame.Without this clicking any links will break the communication and no messages will be received
$('a[href]').each(function(){
this.href = this.href + document.location.hash ;
});
//Get the dimensions and send back to calling page.
var h1 = document.body.scrollHeight;
var w1 = document.body.scrollWidth;
$.postMessage({ if_height: h1, if_width: w1 }, parent_url, parent );
});
และเพจของคุณจะทำงานอย่างเต็มที่และมีสคริปต์ที่ดี ...
//This is almost like request.querystring used to get the iframe data
function querySt(param, e) {
gy = e.split("&");
for (i = 0; i < gy.length; i++) {
ft = gy[i].split("=");
if (ft[0] == param) {
return ft[1];
}
}
}
$(function () {
// Keep track of the iframe dimensions.
var if_height;
var if_width;
// Pass the parent page URL into the Iframe in a meaningful way (this URL could be
// passed via query string or hard coded into the child page, it depends on your needs).
src = 'http://www.OTHERDOAMIN.co.uk/OTHERSTARTPAGE.htm' + '#' + encodeURIComponent(document.location.href),
// Append the Iframe into the DOM.
iframe = $('<iframe " src="' + src + '" width="100%" height="100%" scrolling="no" frameborder="0"><\/iframe>').appendTo('#iframe');
// Setup a callback to handle the dispatched MessageEvent event. In cases where
// window.postMessage is supported, the passed event will have .data, .origin and
// .source properties. Otherwise, this will only have the .data property.
$.receiveMessage(function (e) {
// Get the height from the passsed data.
//var h = Number(e.data.replace(/.*if_height=(\d+)(?:&|$)/, '$1'));
var h = querySt("if_height", e.data);
var w = querySt("if_width", e.data);
if (!isNaN(h) && h > 0 && h !== if_height) {
// Height has changed, update the iframe.
iframe.height(if_height = h);
}
if (!isNaN(w) && w > 0 && w !== if_width) {
// Height has changed, update the iframe.
iframe.width(if_width = w);
}
//For debugging only really- can remove the next line if you want
$('body').prepend("Recieved" + h + "hX" + w + "w .. ");
// An optional origin URL (Ignored where window.postMessage is unsupported).
//Here you must put the other domain.com name only! This is like an authentication to prevent spoofing and xss attacks!
}, 'http://www.OTHERDOMAIN.co.uk');
});
ตัวเลือก 3
ตอนนี้เป็นไลบรารี JS ขนาดเล็กสำหรับจัดการการปรับขนาด iFrames ข้ามโดเมน แต่ยังต้องใช้ iFrame เพื่อให้มี JavaScript อยู่เล็กน้อยอย่างไรก็ตามนี่เป็นเพียง 2.8k (765 bytes Gzipped) ของ JS ดั้งเดิมที่ไม่มีการพึ่งพาใด ๆ และจะไม่ทำอะไรจนกว่าเพจหลักจะเรียก ซึ่งหมายความว่าเป็นแขกที่ดีในระบบของคนอื่น
รหัสนี้ใช้ mutationObserver เพื่อตรวจจับการเปลี่ยนแปลงของ DOM และยังมองหาการปรับขนาดเหตุการณ์เพื่อให้ iFrame ยังคงปรับขนาดให้เข้ากับเนื้อหา ทำงานใน IE8 +