Как изменить размер iframe из другого домена
-Edit
Прокрутите вниз для некоторых решений .. или прочитайте, как НЕ делать этого: D
После многих часов взлома кода - вывод состоит в том, что что-то внутри iframe недоступно, даже полосы прокрутки, которые отображаются на моем домене. Я перепробовал много техник безрезультатно.
Чтобы сэкономить время, даже не идите по этому маршруту, просто используйте sendMessages для междоменной связи.
Есть плагины для HTML <5, которые я использую - перейдите к нижней части для хорошего примера:) </p>
Последние несколько дней я пытался интегрировать iframe в сайт. Это краткосрочное решение, в то время как другая сторона разрабатывает и API (может занять месяцы ...)
И поскольку это краткосрочное решение, которое мы действительно хотим использовать easyXDM, у меня есть доступ к другому домену, но довольно сложно попросить их добавить заголовок p3p, как есть .....
3 фрейма
Самым близким решением, которое я нашел, было 3 фрейма, но оно напоминает хром и сафари, поэтому я не могу его использовать.
открыть в хроме
http://css -tricks.com / примеры / iFrameResize / crossdomain.php # frameId = кадр один и высота = * 1030 тысяча сто семьдесят-девять *
Измерение полос прокрутки
Я нашел еще один пост о том, как использовать высоту прокрутки, чтобы попытаться изменить размер формы ... теоретически это работает хорошо, но я не мог применить его должным образом, используя высоту прокрутки iframes.
document.body.scrollHeight
То, что obvoisly использует высоту тел (не может получить доступ к этим свойствам, 100% основано на отображении клиентов, а не на высоте документа x-domains)
Я пытался использовать jquery для получения высоты iframes
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
возвращает значения, отличающиеся по хрому и т. Д. - или просто не имеют смысла вообще.
Проблема в том, что все внутри фрейма запрещено - даже полоса прокрутки ...
Компьютерные стили
Но если я проверяю и вставляю элемент chrome в iframe, он показывает мне размеры документов внутри iframe (используя jquery x-domain для получения iframe.heigh - доступ запрещен)
В вычисленном CSS нет ничего
Теперь, как chrome это вычисляет? (edit-browser повторно отображает страницу, используя встроенный движок рендеринга, чтобы вычислить все эти настройки - но нигде не прикреплен, чтобы предотвратить междоменное мошенничество .. итак ..)
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 </p>
http://maxq.tigris.org/
РЕДАКТИРОВАТЬ 09-2013
UPDATE
Все это можно сделать с помощью сокетов 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 +.
https://github.com/davidjbradshaw/iframe-resizer