Я попробовал несколько решений, но безуспешно. Мне интересно, есть ли решение, желательно с простым для понимания учебником.
Я попробовал несколько решений, но безуспешно. Мне интересно, есть ли решение, желательно с простым для понимания учебником.
Ответы:
У вас есть три альтернативы:
Это простая библиотека для сохранения размеров iFrames в соответствии с их содержимым. Он использует API-интерфейсы PostMessage и MutationObserver с откатом для IE8-10. Он также имеет параметры для страницы содержимого, чтобы запросить содержащий iFrame определенный размер, а также может закрыть iFrame, когда вы закончите с ним.
https://github.com/davidjbradshaw/iframe-resizer
Easy XDM использует набор уловок для обеспечения междоменной связи между различными окнами в ряде браузеров, и есть примеры его использования для изменения размера iframe:
http://easyxdm.net/wp/2010/03/17/resize-iframe-based-on-content/
http://kinsey.no/blog/index.php/2010/02/19/resizing-iframes-using-easyxdm/
Easy XDM работает с использованием PostMessage в современных браузерах и решения на основе Flash в качестве запасного варианта для старых браузеров.
См. Также эту ветку на Stackoverflow (есть и другие, это часто задаваемый вопрос). Кроме того, похоже , что Facebook использует аналогичный подход .
Другой вариант - отправить высоту iframe на ваш сервер, а затем опросить с этого сервера с родительской веб-страницы с помощью JSONP (или, если возможно, использовать длинный опрос).
У меня есть решение для динамической установки высоты iframe в зависимости от его содержимого. Это работает для междоменного контента. Для этого необходимо выполнить несколько шагов.
Предположим, вы добавили iframe на веб-страницу abc.com/page
<div>
<iframe id="IframeId" src="http://xyz.pqr/contactpage" style="width:100%;" onload="setIframeHeight(this)"></iframe>
</div>
Затем вам нужно привязать событие окна "message" к веб-странице "abc.com/page".
window.addEventListener('message', function (event) {
//Here We have to check content of the message event for safety purpose
//event data contains message sent from page added in iframe as shown in step 3
if (event.data.hasOwnProperty("FrameHeight")) {
//Set height of the Iframe
$("#IframeId").css("height", event.data.FrameHeight);
}
});
При загрузке iframe вы должны отправить сообщение содержимому окна iframe с сообщением "FrameHeight":
function setIframeHeight(ifrm) {
var height = ifrm.contentWindow.postMessage("FrameHeight", "*");
}
window.addEventListener('message', function (event) {
// Need to check for safety as we are going to process only our messages
// So Check whether event with data(which contains any object) contains our message here its "FrameHeight"
if (event.data == "FrameHeight") {
//event.source contains parent page window object
//which we are going to use to send message back to main page here "abc.com/page"
//parentSourceWindow = event.source;
//Calculate the maximum height of the page
var body = document.body, html = document.documentElement;
var height = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
// Send height back to parent page "abc.com/page"
event.source.postMessage({ "FrameHeight": height }, "*");
}
});
Я сравнивал scrollWidth iframe до тех пор, пока он не изменил размер, в то время как я постепенно устанавливаю высоту IFrame. И у меня это сработало. Вы можете отрегулировать шаг по своему желанию.
<script type="text/javascript">
function AdjustIFrame(id) {
var frame = document.getElementById(id);
var maxW = frame.scrollWidth;
var minW = maxW;
var FrameH = 100; //IFrame starting height
frame.style.height = FrameH + "px"
while (minW == maxW) {
FrameH = FrameH + 100; //Increment
frame.style.height = FrameH + "px";
minW = frame.scrollWidth;
}
}
</script>
<iframe id="RefFrame" onload="AdjustIFrame('RefFrame');" class="RefFrame"
src="http://www.YourUrl.com"></iframe>
У меня есть сценарий, который помещается в iframe с его содержимым. Он также гарантирует, что iFrameResizer существует (внедряет его как скрипт), а затем изменяет размер.
Ниже я приведу упрощенный пример.
// /js/embed-iframe-content.js
(function(){
// Note the id, we need to set this correctly on the script tag responsible for
// requesting this file.
var me = document.getElementById('my-iframe-content-loader-script-tag');
function loadIFrame() {
var ifrm = document.createElement('iframe');
ifrm.id = 'my-iframe-identifier';
ifrm.setAttribute('src', 'http://www.google.com');
ifrm.style.width = '100%';
ifrm.style.border = 0;
// we initially hide the iframe to avoid seeing the iframe resizing
ifrm.style.opacity = 0;
ifrm.onload = function () {
// this will resize our iframe
iFrameResize({ log: true }, '#my-iframe-identifier');
// make our iframe visible
ifrm.style.opacity = 1;
};
me.insertAdjacentElement('afterend', ifrm);
}
if (!window.iFrameResize) {
// We first need to ensure we inject the js required to resize our iframe.
var resizerScriptTag = document.createElement('script');
resizerScriptTag.type = 'text/javascript';
// IMPORTANT: insert the script tag before attaching the onload and setting the src.
me.insertAdjacentElement('afterend', ifrm);
// IMPORTANT: attach the onload before setting the src.
resizerScriptTag.onload = loadIFrame;
// This a CDN resource to get the iFrameResizer code.
// NOTE: You must have the below "coupled" script hosted by the content that
// is loaded within the iframe:
// https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.contentWindow.min.js
resizerScriptTag.src = 'https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.min.js';
} else {
// Cool, the iFrameResizer exists so we can just load our iframe.
loadIFrame();
}
}())
Затем содержимое iframe можно внедрить в любое место на другой странице / сайте с помощью сценария следующим образом:
<script
id="my-iframe-content-loader-script-tag"
type="text/javascript"
src="/js/embed-iframe-content.js"
></script>
Содержимое iframe будет вставлено ниже, где бы вы ни разместили тег скрипта.
Надеюсь, это кому-то поможет. 👍
<script ... data-src="http://google.com">и заполнил им iframe src.
iframe-resizer@4.2.10
Вот мое простое решение на этой странице. http://lab.ohshiftlabs.com/iframesize/
Вот как это работает;

В основном, если вы можете редактировать страницу в другом домене, вы можете разместить другую страницу iframe, принадлежащую вашему серверу, которая сохраняет высоту для файлов cookie. С интервалом чтения файлов cookie при его обновлении обновите высоту iframe. Вот и все.
Скачать; http://lab.ohshiftlabs.com/iframesize/iframesizepost.zip
Изменить: 2019 декабрь
В приведенном выше решении в основном используется другой iframe внутри iframe. 3-й iframe принадлежит домену верхней страницы, который вы называете этой страницей со строкой запроса, которая сохраняет значение размера в cookie, внешняя страница проверяет этот запрос с некоторым интервалом. Но это не лучшее решение, поэтому вам следует следовать этому:
На верхней странице:
window.addEventListener("message", (m)=>{iframeResizingFunction(m)});
Здесь вы можете проверить, m.originоткуда он.
На странице фрейма:
window.parent.postMessage({ width: 640, height:480 }, "*")
Хотя, пожалуйста, не забывайте, что это не очень безопасный способ. Чтобы сделать его безопасным, обновите значение * (targetOrigin) с желаемым значением. Следуйте документации: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Я нашел еще одно серверное решение для веб-разработчиков, использующее PHP для получения размера iframe.
Сначала используется серверный скрипт PHP для внешнего вызова через внутреннюю функцию: (например, file_get_contentswith, но curl и dom).
function curl_get_file_contents($url,$proxyActivation=false) {
global $proxy;
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7");
curl_setopt($c, CURLOPT_REFERER, $url);
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
if($proxyActivation) {
curl_setopt($c, CURLOPT_PROXY, $proxy);
}
$contents = curl_exec($c);
curl_close($c);
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
@$dom->loadHTML($contents);
$form = $dom->getElementsByTagName("body")->item(0);
if ($contents) //si on a du contenu
return $dom->saveHTML();
else
return FALSE;
}
$url = "http://www.google.com"; //Exernal url test to iframe
<html>
<head>
<script type="text/javascript">
</script>
<style type="text/css">
#iframe_reserve {
width: 560px;
height: 228px
}
</style>
</head>
<body>
<div id="iframe_reserve"><?php echo curl_get_file_contents($url); ?></div>
<iframe id="myiframe" src="http://www.google.com" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" style="overflow:none; width:100%; display:none"></iframe>
<script type="text/javascript">
window.onload = function(){
document.getElementById("iframe_reserve").style.display = "block";
var divHeight = document.getElementById("iframe_reserve").clientHeight;
document.getElementById("iframe_reserve").style.display = "none";
document.getElementById("myiframe").style.display = "block";
document.getElementById("myiframe").style.height = divHeight;
alert(divHeight);
};
</script>
</body>
</html>
Вам нужно отобразить под div ( iframe_reserve) HTML-код, сгенерированный вызовом функции, с помощью простогоecho curl_get_file_contents("location url iframe","activation proxy")
После этого функция события тела при загрузке с помощью javascript принимает высоту iframe страницы просто с помощью простого управления содержимым div ( iframe_reserve)
Итак, я использовал divHeight = document.getElementById("iframe_reserve").clientHeight;высоту внешней страницы, которую мы собираемся вызвать после замаскирования контейнера div ( iframe_reserve). После этого загружаем iframe с его хорошей высотой, вот и все.
Я столкнулся с этой проблемой, когда работал над чем-то на работе (используя React). По сути, у нас есть внешний HTML-контент, который мы сохраняем в нашу таблицу документов в базе данных, а затем вставляем на страницу при определенных обстоятельствах, когда вы находитесь в наборе данных Documents.
Итак, учитывая nвстроенные строки, из которых до nможет содержать внешний html, нам нужно было разработать систему для автоматического изменения размера iframe каждой встроенной строки после полной загрузки содержимого в каждом. Покрутив колеса немного, я сделал это вот как:
messageпрослушиватель событий в индексе нашего приложения React, который проверяет конкретный ключ, который мы установим из iframe отправителя.<script>тег, который будет ждать window.onloadсрабатывания iframe . Как только это сработает, мы postMessageотправляем сообщение в родительское окно с информацией об идентификаторе iframe, вычисленной высоте и т. Д.idiframe, который мы передаем в MessageEventобъектiframe, просто установите высоту из значения, которое передается из iframe postMessage.// index
if (window.postMessage) {
window.addEventListener("message", (messageEvent) => {
if (
messageEvent.data.origin &&
messageEvent.data.origin === "company-name-iframe"
) {
const iframe = document.getElementById(messageEvent.data.id)
// this is the only way to ensure that the height of the iframe container matches its body height
iframe.style.height = `${messageEvent.data.height}px`
// by default, the iframe will not expand to fill the width of its parent
iframe.style.width = "100%"
// the iframe should take precedence over all pointer events of its immediate parent
// (you can still click around the iframe to segue, for example, but all content of the iframe
// will act like it has been directly inserted into the DOM)
iframe.style.pointerEvents = "all"
// by default, iframes have an ugly web-1.0 border
iframe.style.border = "none"
}
})
}
// in component that renders n iframes
<iframe
id={`${props.id}-iframe`}
src={(() => {
const html = [`data:text/html,${encodeURIComponent(props.thirdLineData)}`]
if (window.parent.postMessage) {
html.push(
`
<script>
window.onload = function(event) {
window.parent.postMessage(
{
height: document.body.scrollHeight,
id: "${props.id}-iframe",
origin: "company-name-iframe",
},
"${window.location.origin}"
);
};
</script>
`
)
}
return html.join("\n")
})()}
onLoad={(event) => {
// if the browser does not enforce a cross-origin policy,
// then just access the height directly instead
try {
const { target } = event
const contentDocument = (
target.contentDocument ||
// Earlier versions of IE or IE8+ where !DOCTYPE is not specified
target.contentWindow.document
)
if (contentDocument) {
target.style.height = `${contentDocument.body.scrollHeight}px`
}
} catch (error) {
const expectedError = (
`Blocked a frame with origin "${window.location.origin}" ` +
`from accessing a cross-origin frame.`
)
if (error.message !== expectedError) {
/* eslint-disable no-console */
console.err(
`An error (${error.message}) ocurred while trying to check to see ` +
"if the inner iframe is accessible or not depending " +
"on the browser cross-origin policy"
)
}
}
}}
/>