Làm cách nào để thay đổi kích thước iframe từ một miền khác
-Biên tập
Cuộn xuống để biết một số giải pháp .. hoặc đọc về cách KHÔNG làm điều này: D
Sau nhiều giờ hack mã - kết luận là không thể truy cập bất kỳ thứ gì bên trong iframe, ngay cả các thanh cuộn hiển thị trên miền của tôi. Tôi đã thử nhiều kỹ thuật nhưng không có kết quả.
Để giúp bạn tiết kiệm thời gian, thậm chí không cần phải đi xuống tuyến đường này, chỉ cần sử dụng sendMessages để liên lạc giữa các miền. Có những plug-in cho HTML <5 mà tôi sử dụng- Hãy xem phần dưới cùng để biết một ví dụ hay :)
Trong vài ngày qua, tôi đã cố gắng tích hợp iframe vào một trang web. Đây là một giải pháp ngắn hạn trong khi bên kia phát triển và API (có thể mất vài tháng ...) Và bởi vì đây là giải pháp ngắn hạn mà chúng tôi đã thực hiện muốn sử dụng easyXDM- Tôi có quyền truy cập vào miền khác nhưng nó đủ khó yêu cầu họ thêm tiêu đề p3p như hiện tại .....
3 iframe
Giải pháp gần nhất mà tôi tìm thấy là 3 iframe - nhưng nó phù hợp với chrome và safari nên tôi không thể sử dụng nó.
mở trong chrome
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179
Đo các thanh cuộn
Tôi đã tìm thấy một bài đăng khác về cách sử dụng scrollheight để thử và thay đổi kích thước biểu mẫu .. về lý thuyết, nó hoạt động tốt nhưng tôi không thể áp dụng nó đúng cách bằng cách sử dụng chiều cao cuộn iframes ..
document.body.scrollHeight
Obvoisly đó sử dụng chiều cao phần thân (không thể truy cập các thuộc tính này 100% dựa trên canvaz hiển thị ứng dụng khách chứ không phải chiều cao tài liệu x-domain)
Tôi đã thử sử dụng jquery để lấy chiều cao iframe
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
trả về các giá trị khác nhau trong chrome và tức là - hoặc hoàn toàn không có ý nghĩa. Vấn đề là mọi thứ bên trong khung đều bị từ chối - ngay cả thanh cuộn ...
Kiểu tính toán
Nhưng nếu tôi kiểm tra và thành phần trong chrome của iframe, nó sẽ hiển thị cho tôi kích thước tài liệu bên trong iframe (sử dụng jquery x-domain để lấy iframe.heigh - quyền truy cập bị từ chối) Không có gì trong CSS được tính toán
Bây giờ chrome tính toán điều đó như thế nào? (chỉnh sửa- trình duyệt kết xuất trang bằng cách sử dụng công cụ kết xuất tích hợp của nó để calcualte tất cả các cài đặt này - nhưng không được đính kèm ở bất kỳ đâu để ngăn gian lận giữa nhiều miền .. vì vậy ..)
HTML4
Tôi đã đọc đặc tả của HTML4.x và nó nói rằng ở đó nên có các giá trị chỉ đọc được hiển thị qua document.element nhưng quyền truy cập của nó bị từ chối thông qua jquery
Khung proxy
Tôi đã đi xuống lộ trình proxy trang web trở lại và tính toán xem điều nào là OK .. cho đến khi người dùng đăng nhập thông qua iframe và proxy nhận được trang đăng nhập thay vì nội dung thực. Ngoài ra đối với một số người gọi trang hai lần là không thể chấp nhận được
http://www.codeproject.com/KB/aspnet/asproxy.aspx
http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/
Re-Render trang
Tôi đã không đi xa đến mức này nhưng có các công cụ jscript ở đó sẽ xem xét nguồn và kết xuất lại trang dựa trên tệp nguồn. nhưng nó sẽ yêu cầu hack các jscripts đó .. và đó không phải là một tình huống lý tưởng cho các thực thể thương mại ... và một số applet java thuần túy không xâm nhập hoặc kết xuất phía máy chủ
http://en.wikipedia.org/wiki/Server-side_JavaScript
http://htmlunit.sourceforge.net/ <-java không phải jscript
CHỈNH SỬA CẬP NHẬT 09-2013
Tất cả điều này có thể làm được với các socket HTML5. Nhưng easyXDM là dự phòng tuyệt vời cho các trang khiếu nại không phải HTML5.
Giải pháp 1 Giải pháp rất tuyệt vời!
Sử dụng easyXDM
Trên máy chủ của bạn, bạn thiết lập một trang ở dạng
<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>
và trên miền người gọi, họ chỉ cần thêm html intermiedate_frame và easyXDM.js vào cùng một nơi. Giống như một thư mục mẹ - sau đó bạn có thể truy cập các thư mục tương đối hoặc một thư mục chứa chỉ dành cho bạn.
LỰA CHỌN 1
Nếu bạn không muốn thêm tập lệnh vào tất cả các trang, hãy xem tùy chọn 2!
Sau đó, họ có thể chỉ cần thêm một jscript đơn giản vào cuối mỗi trang mà bạn cần thay đổi kích thước. Không cần bao gồm easyxdm trong mỗi trang này.
<script type="text/javascript">
window.onload = function(){ parent.socket.postMessage( (parseInt(document.body.clientHeight)) + "," + ( document.body.clientWidth ) ); };
</script>
Tôi đã sửa đổi các thông số mà nó gửi. Nếu bạn muốn chiều rộng hoạt động bình thường thì các trang trên tên miền khác cần phải bao gồm chiều rộng của trang theo một phong cách sao cho giống với:
<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>
Điều này làm việc tuyệt vời cho tôi. Nếu chiều rộng không được bao gồm thì khung hoạt động hơi lạ và đại loại là cố gắng đoán xem nó phải như thế nào .. và sẽ không thu nhỏ lại nếu bạn cần.
LỰA CHỌN 2
Sửa đổi khung trung gian để thăm dò ý kiến các thay đổi
Khung trung gian của bạn sẽ trông giống như thế này ..
<!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>
Khoảng thời gian có thể được thực hiện hiệu quả hơn để theo dõi nếu kích thước thay đổi và chỉ gửi nếu kích thước thay đổi thay vì đăng tin nhắn sau mỗi 500ms. Nếu bạn thực hiện kiểm tra này thì bạn có thể thay đổi mức bỏ phiếu thấp nhất là 50ms! chúc vui vẻ
Làm việc trên nhiều trình duyệt và nhanh chóng. Tính năng gỡ lỗi tuyệt vời !!
Excellent Work to Sean Kinsey who made the script!!!
Giải pháp 2 (Hoạt động nhưng không tốt)
Vì vậy, về cơ bản nếu bạn có thỏa thuận chung với miền khác thì bạn có thể thêm thư viện để xử lý sendmessage. Nếu bạn không có bất kỳ quyền truy cập nào vào miền khác .. Hãy tiếp tục tìm kiếm thêm các bản hack- bởi vì tôi không thể tìm thấy hoặc giải thích đầy đủ cho những bản hack này mà tôi đã tìm thấy.
Vì vậy, miền khác sẽ bao gồm những thứ này trong thẻ 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>
Trong club.js chỉ là một số cuộc gọi tùy chỉnh mà tôi đã thực hiện cho các cuộc gọi thay đổi kích thước và chứa ..
$(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 );
});
Và trang của bạn sẽ làm tất cả công việc khó khăn và có một tập lệnh đẹp ...
//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');
});
LỰA CHỌN 3
Hiện tại, thư viện JS của họ là một thư viện JS nhỏ để quản lý thay đổi kích thước iFrame miền chéo, nó vẫn yêu cầu iFrame phải có một chút JavaScript trong đó, tuy nhiên, đây chỉ là 2,8 nghìn (765 byte được Gzipped) của JS gốc không có bất kỳ phụ thuộc nào. và nó không làm bất cứ điều gì cho đến khi được gọi bởi trang mẹ. Điều này có nghĩa đó là một vị khách tốt trên các hệ thống của người khác.
Mã này sử dụng mutObserver để phát hiện các thay đổi DOM và cũng tìm ra các sự kiện thay đổi kích thước, để iFrame vẫn có kích thước phù hợp với nội dung. Hoạt động trong IE8 +.