Як змінити розмір iframe з іншого домену
-Редагувати
Прокрутіть униз, щоб знайти деякі рішення .. або прочитайте, як НЕ робити цього: D
Після багатогодинного злому коду - висновок полягає в тому, що все, що є в iframe, недоступне, навіть смуги прокрутки, які відображаються в моєму домені. Я спробував безліч методів безрезультатно.
Щоб заощадити ваш час, навіть не йдіть цим маршрутом, просто використовуйте sendMessages для міждоменного зв'язку. Є плагіни для HTML <5, якими я користуюсь - Перейдіть до нижнього для гарного прикладу :)
Останні кілька днів я намагався інтегрувати iframe на сайт. Це короткострокове рішення, тоді як інша сторона розробляє та API (може зайняти місяці ...) І оскільки це короткострокове рішення, яке ми зробили, хочемо використовувати easyXDM - я маю доступ до іншого домену, але досить складно просити їх додати заголовок p3p як є .....
3 фрейми
Найближчим рішенням, яке я знайшов, було 3 фрейми - але воно відповідає умовам хрому та сафарі, тому я не можу цим користуватися.
відкрити в хромі
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179
Виміряйте смуги прокрутки
Я знайшов інший допис про те, як використовувати висоту прокрутки, щоб спробувати змінити розмір форми .. теоретично це працює добре, але я не міг застосувати його належним чином, використовуючи висоту прокрутки iframes ..
document.body.scrollHeight
Це чітко використовує висоту тіл (не вдається отримати доступ до цих властивостей на 100% на основі відображення клієнтів canvaz, а не висоти документа x-доменів)
Я спробував використовувати jquery, щоб отримати висоту iframes
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
повертають значення, різні за хромом і тобто - або просто взагалі не мають сенсу. Проблема в тому, що все всередині кадру відмовлено - навіть смуга прокрутки ...
Обчислювальні стилі
Але якщо я перевіряю та в хромірую елемент iframe, він показує мені розміри документів усередині iframe (за допомогою jquery x-domain для отримання iframe.heigh - доступ заборонено) в обчисленому CSS немає нічого
Тепер, як хром обчислює це? (редагувати - браузер повторно відображає сторінку, використовуючи вбудований механізм рендерингу, щоб обчислити всі ці налаштування - але вони ніде не прикріплені, щоб запобігти міждоменному шахрайству .. так ..)
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/
Знову рендеріть сторінку
Я не зайшов так далеко, але є двигуни jscript, які будуть переглядати джерело та повторно відображати сторінку на основі вихідного файлу. але для цього потрібно зламати ці jscripts .. і це не є ідеальною ситуацією для комерційних організацій ... і деякі викликають чисті аплети Java або рендеринг на стороні сервера
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>
Для мене це чудово працює. Якщо ширина не включена, тоді кадр поводиться трохи дивно і kind'of намагається вгадати, якою вона повинна бути .. і не зменшиться, якщо вам це потрібно.
ВАРІАНТ 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 (працює, але не чудово)
Отже, якщо у вас є взаємна угода з іншим доменом, ви можете додати бібліотеку для обробки sendmessage. Якщо у вас немає доступу до іншого домену .. Продовжуйте шукати більше хаків - тому що я не зміг знайти або повністю виправдати їх, які знайшов.
Отже, інший домен включатиме їх у тег 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,8 тис. (765 байт Gzipped) рідної JS, яка не має залежностей і він нічого не робить, доки його не викликає батьківська сторінка. Це означає, що це приємний гість в системах інших людей.
Цей код використовує mutationObserver для виявлення змін DOM, а також звертає увагу на події зміни розміру, так що iFrame залишається розміром до вмісту. Працює в IE8 +.