Как изменить размер окна 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 +.
источник
Ответы:
Дело в том, что для этого нет другого способа, кроме использования междоменного обмена сообщениями, поскольку вам нужно получить вычисленную высоту от документа в одном домене до документа в другом домене.
Итак, либо вы делаете это с помощью
postMessage
(работает во всех современных браузерах), либо вы тратите 5 минут на адаптацию примера изменения размера iframe из easyXDM.Другой стороне действительно нужно просто скопировать несколько файлов в свой домен и добавить одну строку кода в свой документ.
источник
Подобно тому, что упомянул Шон, вы можете использовать postMessage. Я потратил так много времени, пытаясь разными способами изменить размер iframe с помощью междоменного использования, но мне не повезло, пока я не наткнулся на эту замечательную запись в блоге Дэвида Уолша: http://davidwalsh.name/window-iframe
Это комбинация моего кода и решения Дэвида. Мое решение специально предназначено для изменения размеров окон iframe.
На дочерней странице найдите высоту страницы и передайте ее на родительскую страницу (которая содержит iframe). Замените element_id своим идентификатором элемента (html, body, что угодно).
<script> function adjust_iframe_height(){ var actual_height = document.getElementById('element_id).scrollHeight; parent.postMessage(actual_height,"*"); //* allows this to post to any parent iframe regardless of domain } </script> <body onload="adjust_iframe_height();"> //call the function above after the content of the child loads
В родительском окне добавьте этот код. Замените iframe_id своим идентификатором iframe:
<script> // Create IE + others compatible event handler var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; var eventer = window[eventMethod]; var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message"; // Listen to message from child window eventer(messageEvent,function(e) { console.log('parent received message!: ',e.data); document.getElementById('iframe_id').height = e.data + 'px'; },false); </script>
Если вы откроете консоль, вы увидите, что высота напечатана в журнале консоли. Это поможет вам в отладке, поэтому я оставил это там.
С уважением, Бейкер
источник
Посмотрев множество различных решений для этого, я закончил тем, что написал простую небольшую библиотеку, чтобы учесть ряд различных вариантов использования. Поскольку мне нужно было решение, которое поддерживало бы создание iFrames несколькими пользователями на странице портала, поддерживало изменение размера браузера и могло справиться с загрузкой JavaScript на главной странице после iFrame. Я также добавляю поддержку изменения размера по ширине и функцию обратного вызова и разрешаю переопределение body.margin, так как вы, вероятно, захотите, чтобы это значение было установлено на ноль.
https://github.com/davidjbradshaw/iframe-resizer
Код iframe - это всего лишь небольшой автономный JavaScript, поэтому он хорошо подходит для других страниц.
Затем сценарий инициализируется на главной странице со следующими доступными параметрами.
iFrameResize({ log : true, // For development autoResize : true, // Trigering resize on events in iFrame contentWindowBodyMargin: 8, // Set the default browser body margin style (in px) doHeight : true, // Calculates dynamic height doWidth : false, // Calculates dynamic width enablePublicMethods : true, // Enable methods within iframe hosted page interval : 32, // interval in ms to recalculate body height, 0 to disable refreshing scrolling : false, // Enable the scrollbars in the iFrame callback : function(messageData){ // Callback fn when message is received $('p#callback').html( '<b>Frame ID:</b> ' + messageData.iframe.id + ' <b>Height:</b> ' + messageData.height + ' <b>Width:</b> ' + messageData.width + ' <b>Event type:</b> ' + messageData.type ); } });
источник
Вместо использования scroll = no в iframe я меняю его на «auto». Затем я получаю размер фактического окна
$(window).height();
и используйте это как атрибут высоты iframe.
Что ж, результат ...
У нас никогда не будет прокрутки «страницы», только прокрутка «iframe». Когда вы перемещаетесь, не имеет значения, кто является прокруткой, но важно то, что там только 1.
Что ж, проблема заключается в том, что пользователь просто изменяет размер окна во время навигации. Чтобы решить эту проблему, я использую:
setInterval(getDocHeight, 1);
Вы думали, что это решение вызовет какие-либо ошибки? Это работает для меня, и в iFrame у меня был динамический контекст, созданный php. Боюсь ошибок с этим в будущем ...
источник
На сегодняшний день я знаю всего 4 решения:
Только третий может решить многие проблемы. Например, вы можете создать адаптивный iFrame ; закрыть его изнутри или можешь с ним общаться . Но для этого вам понадобится iFrame в Iframe и обходной путь «сторонних файлов cookie» (необязательно).
Я написал об этом статью с примером: междоменный iFrame, управляемый событиями.
источник
Вы изучали "объектно-подходящие" атрибуты HTML5? Масштабирует видео / изображения для iframe, а не масштабирует iframe (хорошо, если вы берете изображение среднего размера, которое в итоге имеет ширину 5000 пикселей). Вариант «подгонка» (другие - «обложка» и «заливка») использует подход типа почтового ящика, чтобы подогнать под источник при сохранении пропорций. Для просмотра пользователями без HTML5, похоже, доступно огромное количество полифиллов. Это здорово, но ошибка на конце Edge держала его несовместимым с New Nightmare от Microsoft около года, а теперь: https://github.com/anselmh/object-fit
РЕДАКТИРОВАТЬ: чтобы обойти междоменные проблемы, вы всегда можете просто выполнить работу в сценарии содержимого расширения Chrome, поскольку он считает, что это часть страницы, на которую вы вставляете свой iframe.
источник
HTTPS другая ссылка получить высоту для автоматической высоты iframe
https://-a.com содержание:
<!DOCTYPE html> <html> <head> <title>Test Page</title> </head> <body> Test Page: <hr/> <iframe id="iframe" src="https://-b.com" style="width:100%;min-height:600px;border:none;" scrolling="no" ></iframe> <script> // browser compatibility: get method for event // addEventListener(FF, Webkit, Opera, IE9+) and attachEvent(IE5-8) var myEventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; // create event listener var myEventListener = window[myEventMethod]; // browser compatibility: attach event uses onmessage var myEventMessage = myEventMethod == "attachEvent" ? "onmessage" : "message"; // register callback function on incoming message myEventListener(myEventMessage, function (e) { // we will get a string (better browser support) and validate // if it is an int - set the height of the iframe #my-iframe-id if (e.data === parseInt(e.data)) document.getElementById('iframe').height = e.data + "px"; }, false); </script> </body> </html>
https://-b.com содержимое iframe:
<!DOCTYPE html> <html> <head> <title>Test Iframe Content</title> <script type="text/javascript"> // all content including images has been loaded window.onload = function() { // post our message to the parent window.parent.postMessage( // get height of the content document.body.scrollHeight // set target domain ,"*" ) }; </script> </head> <body> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>1 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>2 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>3 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>4 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>5 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>6 </body> </html>
Рабочий стол:
xcom http> ycom https РАБОТАЕТ
xcom https> ycom https РАБОТА
xcom http> ycom http РАБОТА
xcom https> ycom http РАБОТА
источник
Хотите узнать высоту страницы, содержащейся в iframe? У меня есть работа с javascript, которая проверяет высоту содержимого iframe, а затем устанавливает высоту iframe на высоту содержимого.
var Height = document.getElementById('iFrameId').contentWindow.document.body.scrollHeight; document.getElementById('iFrameId').height = Height;
Однако это работает, только если страница, которую вы показываете в iframe, находится в том же домене. В противном случае вы не можете получить доступ к необходимой информации. Следовательно, доступ запрещен ошибка.
источник
Чтобы изменить размер окна iframe, воспользуйтесь простым скриптом:
это идет в голову: (это было написано для php скрипта, для html измените 'на "и \" на' ...
<script type='text/javascript'> <!-- function resizeIframe(id){ /* this.obj=obj //this.obj.width=null //this.obj.width=window.frames[\"sizeframe1\"].document.body.scrollWidth this.obj.style.height=\"\" // for Firefox and Opera setTimeout(\"this.obj.style.height=this.obj.contentWindow.document.body.scrollHeight+(notIE?heightOffset:0)\",10) // setTimeout required for Opera */ el=document.getElementById(id) el.style.height='200px' // for Firefox and Opera setTimeout('el.style.height=el.contentWindow.document.body.scrollHeight+\"px\"',1) // setTimeout required for Opera } // --> </script>"
конец головы
это идет в теле (помните, это было написано для скрипта php, для html измените все 'на "и \" на' ...)
<iframe onload='resizeIframe(this.id)' allowTransparency=\"true\" name='ccpaymentwindow' id='sizeframe1' marginwidth='1' marginheight='1' height='700' width='690' border='0' frameborder='1' scrolling='no' src='ccmslink.php?variable1=" . $variable1 . "'></iframe>
бонус: есть несколько подсказок выше. Поскольку он настроен для написания сценариев php, вы можете многое с ним сделать ... чтобы узнать больше, сделать больше ...
ключом к этому является "sizeframe1" .... для нескольких "изменяющих размер" на одной странице скопируйте один и тот же сценарий, но измените идентификатор в iframe и имя в сценарии в заголовке, и альт! у вас есть несколько редакторов размера на одной странице ... работает очень хорошо!
есть phun.
источник