Как изменить размер iframe из другого домена
-Edit
Прокрутите вниз для некоторых решений.. или прочитайте, как НЕ делать это: D
После многих часов кода hacking- вывод заключается в том, что все, что находится внутри iframe, недоступно, даже полосы прокрутки, которые отображаются в моем домене. Я пробовал много методов безрезультатно.
Чтобы сэкономить ваше время, даже не спускайтесь по этому маршруту, просто используйте sendMessages для междоменной связи. Есть плагины для HTML <5, что я use- Перейти к нижней части для приятного примера :)
Последние несколько дней я пытался интегрировать iframe в сайт. Это краткосрочное решение, в то время как другая сторона развивается, и API (может занять месяцы...) И поскольку это как краткосрочное решение, которое мы хотели использовать easyXDM-, у меня есть доступ к другому домену, но его достаточно сложно спросить их добавить заголовок p3p, как есть.....
3 фрейма
Самое близкое решение, которое я нашел, было 3 iframes-, но оно имеет умный хром и сафари, поэтому я не могу использовать это.
открытый в хромированном состоянии
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179
Измерение полос прокрутки
Я нашел еще одно сообщение о том, как использовать scrollheight, чтобы попытаться изменить размер формы. Теоретически это работает хорошо, но я не смог применить его правильно, используя высоту прокрутки iframes.
document.body.scrollHeight
То, что obvoisly использует высоту тела (не может получить доступ к этим свойствам, 100% основывается на клиентском отображении canvaz, а не на высоте документа x-domains)
Я попытался использовать jquery, чтобы получить высоту iframes
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
возвращаемые значения отличаются по хром и т.д. - или просто не имеют смысла вообще. Проблема в том, что все внутри рамки denied- даже полоса прокрутки...
Вычислительные стили
Но если я проверю и элемент в chrome iframe, он bladdy показывает мне размеры документов внутри iframe (используя jquery x-domain, чтобы получить iframe.heigh - доступ запрещен). В вычисленном CSS ничего нет,
Теперь, как хром вычислил это? (edit- браузер повторно отображает страницу с помощью своей сборки в механизме рендеринга для вычисления всех этих параметров - но они не привязаны нигде, чтобы предотвратить междоменное мошенничество.. так..)
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.. и это не идеальная ситуация для коммерческих лиц... и некоторые invoke чистые java-апплеты или серверная визуализация
http://en.wikipedia.org/wiki/Server-side_JavaScript
http://htmlunit.sourceforge.net/ <-java не jscript
EDIT 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>
Интервал может быть более эффективным для chaeck, если размер изменился и отправляется только в том случае, если изменения размеров являются отправкой сообщений каждые 500 мс. Если вы выполните эту проверку, вы можете изменить опрос до 50 мс! повеселись
Работайте в браузерах и быстро. Отличные функции отладки!
Excellent Work to Sean Kinsey who made the script!!!
Решение 2 (работает, но не очень хорошо)
Поэтому, если у вас есть взаимное согласие с другим доменом, вы можете добавить библиотеку для обработки sendmessage. Если у вас нет доступа к другому домену, продолжайте искать больше hacks-, потому что я не смог найти или полностью оправдать их, которые я нашел.
Таким образом, в другой домен будут включены теги Head tag
<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 байт Gzipped) встроенного JS, который не имеет никаких зависимостей и он ничего не делает, пока не будет вызван родительской страницей. Это означает, что это хороший гость в других людях.
Этот код использует mutationObserver для обнаружения изменений DOM, а также ищет события изменения размера, так что iFrame остается размером с содержимым. Работает в IE8+.