Как изменить размер окна iframe из другого домена
-Редактировать
Прокрутите вниз, чтобы узнать о некоторых решениях .. или прочтите, как этого НЕ делать: D
После многих часов взлома кода был сделан вывод, что все, что находится внутри iframe, недоступно, даже полосы прокрутки, которые отображаются в моем домене. Я пробовал много техник, но безуспешно.
Чтобы сэкономить время, даже не идите по этому пути, просто используйте sendMessages для междоменной связи. Есть плагины для HTML <5, которые я использую. Спуститесь вниз, чтобы увидеть хороший пример :)
Последние несколько дней я пытался интегрировать iframe в сайт. Это краткосрочное решение, в то время как другая сторона разрабатывает и API (может занять несколько месяцев ...) И поскольку это краткосрочное решение, мы уже хотим использовать easyXDM - у меня есть доступ к другому домену, но его достаточно сложно попросить их добавить заголовок p3p как есть .....
3 фрейма
Самым близким решением, которое я нашел, были 3 окна iframe, но это связано с хромом и сафари, поэтому я не могу его использовать.
открыть в хроме
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179.
Измерьте полосы прокрутки
Я нашел еще один пост о том, как использовать высоту прокрутки, чтобы попытаться изменить размер формы ... теоретически это работает хорошо, но я не мог правильно применить его, используя высоту прокрутки iframe ..
document.body.scrollHeight
Это явно использует высоту тела (не может получить доступ к этим свойствам. 100% основано на отображении Canvaz клиентов, а не на высоте документа x-доменов)
Я пробовал использовать jquery, чтобы получить высоту фреймов
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
возвращать значения, отличные от chrome и ie - или просто не иметь смысла. Проблема в том, что все внутри кадра запрещено, даже полоса прокрутки ...
Вычисленные стили
Но если я проверяю и элемент в хроме iframe, он показывает мне размеры документов внутри 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/
Повторно отрендерить страницу
Я не заходил так далеко, но есть движки 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 байт в сжатом виде) собственного JS, который не имеет никаких зависимостей. и он ничего не делает, пока не будет вызван родительской страницей. Это означает, что это хороший гость в других системах.
Этот код использует mutationObserver для обнаружения изменений DOM, а также отслеживает события изменения размера, чтобы размер iFrame оставался равным содержимому. Работает в IE8 +.