Wypróbowałem kilka rozwiązań, ale nie udało mi się. Zastanawiam się, czy istnieje rozwiązanie, najlepiej z łatwym do naśladowania samouczkiem.
Wypróbowałem kilka rozwiązań, ale nie udało mi się. Zastanawiam się, czy istnieje rozwiązanie, najlepiej z łatwym do naśladowania samouczkiem.
Odpowiedzi:
Masz trzy możliwości:
Jest to prosta biblioteka do utrzymywania rozmiaru iFrame zgodnie z zawartością. Używa interfejsów API PostMessage i MutationObserver, z rezerwami dla IE8-10. Zawiera również opcje dla strony zawartości, aby zażądać, aby zawierający element iFrame miał określony rozmiar, a także może zamknąć element iFrame, gdy skończysz.
https://github.com/davidjbradshaw/iframe-resizer
Easy XDM wykorzystuje zbiór sztuczek umożliwiających komunikację między domenami między różnymi oknami w wielu przeglądarkach, a są przykłady użycia go do zmiany rozmiaru elementu 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 działa przy użyciu PostMessage w nowoczesnych przeglądarkach i rozwiązania opartego na Flashu jako rezerwy dla starszych przeglądarek.
Zobacz także ten wątek na Stackoverflow (są też inne, to jest często zadawane pytanie). Wydaje się również, że Facebook stosuje podobne podejście .
Inną opcją byłoby wysłanie wysokości iframe na twój serwer, a następnie sondowanie z tego serwera z nadrzędnej strony internetowej za pomocą JSONP (lub użyj długiej ankiety, jeśli to możliwe).
Mam rozwiązanie umożliwiające dynamiczne ustawianie wysokości elementu iframe na podstawie jego zawartości. Działa to w przypadku treści między domenami. Aby to osiągnąć, należy wykonać kilka kroków.
Załóżmy, że dodano element iframe na stronie internetowej „abc.com/page”
<div>
<iframe id="IframeId" src="http://xyz.pqr/contactpage" style="width:100%;" onload="setIframeHeight(this)"></iframe>
</div>
Następnie musisz powiązać zdarzenie "wiadomość" systemu Windows pod stroną "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);
}
});
Podczas ładowania elementu iframe musisz wysłać wiadomość do zawartości okna iframe z komunikatem „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 }, "*");
}
});
To, co zrobiłem, to porównanie elementu iframe scrollWidth, aż zmienił rozmiar, podczas gdy przyrostowo ustawiłem wysokość IFrame. I dla mnie zadziałało dobrze. Możesz dostosować przyrost według uznania.
<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>
Mam skrypt, który znajduje się w ramce iframe wraz z zawartością. Sprawdza również, czy istnieje element iFrameResizer (wstawia go jako skrypt), a następnie dokonuje zmiany rozmiaru.
Poniżej przedstawię uproszczony przykład.
// /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();
}
}())
Następnie zawartość iframe można wstawić w dowolnym miejscu na innej stronie / witrynie za pomocą następującego skryptu:
<script
id="my-iframe-content-loader-script-tag"
type="text/javascript"
src="/js/embed-iframe-content.js"
></script>
Treść iframe zostanie wstawiona poniżej, gdziekolwiek umieścisz tag script.
Mam nadzieję, że to komuś pomoże. 👍
<script ... data-src="http://google.com">
i wypełniłem nim iframe src.
iframe-resizer@4.2.10
Oto moje proste rozwiązanie na tej stronie. http://lab.ohshiftlabs.com/iframesize/
Oto jak to działa;
Zasadniczo, jeśli możesz edytować stronę w innej domenie, możesz umieścić inną stronę iframe należącą do twojego serwera, która zapisuje wysokość do plików cookie. Z częstotliwością odczytywania plików cookie podczas aktualizacji zaktualizuj wysokość elementu iframe. To wszystko.
Pobieranie; http://lab.ohshiftlabs.com/iframesize/iframesizepost.zip
Edycja: grudzień 2019
Powyższe rozwiązanie zasadniczo wykorzystuje inny element iframe wewnątrz elementu iframe. 3. element iframe należy do domeny głównej strony, którą nazywasz ciągiem zapytania, który zapisuje wartość rozmiaru w pliku cookie, zewnętrzna strona sprawdza to zapytanie z pewnymi odstępami czasu. Ale to nie jest dobre rozwiązanie, więc powinieneś postępować zgodnie z tym:
Na górze strony:
window.addEventListener("message", (m)=>{iframeResizingFunction(m)});
Tutaj możesz sprawdzić, m.origin
skąd pochodzi.
Na stronie z ramką:
window.parent.postMessage({ width: 640, height:480 }, "*")
Chociaż nie zapominaj, że nie jest to tak bezpieczny sposób. Aby była bezpieczna, zaktualizuj * wartość (targetOrigin) z żądaną wartością. Skorzystaj z dokumentacji: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Znalazłem inne rozwiązanie po stronie serwera dla twórców stron internetowych, które używa PHP do uzyskania rozmiaru elementu iframe.
Pierwszy to użycie skryptu serwera PHP do wywołania zewnętrznego za pośrednictwem funkcji wewnętrznej: (jak file_get_contents
with but curl i 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>
Musisz wyświetlić pod div ( iframe_reserve
) kod HTML wygenerowany przez wywołanie funkcji za pomocą prostegoecho curl_get_file_contents("location url iframe","activation proxy")
Po wykonaniu tej czynności funkcja zdarzenia body ładowana za pomocą javascript pobiera wysokość elementu iframe strony tylko za pomocą prostej kontroli zawartości div ( iframe_reserve
)
Więc użyłem divHeight = document.getElementById("iframe_reserve").clientHeight;
wysokości zewnętrznej strony, którą wywołamy po zamaskowaniu kontenera div ( iframe_reserve
). Po tym ładujemy iframe o dobrej wysokości i to wszystko.
Napotkałem ten problem podczas pracy nad czymś w pracy (używając React). Zasadniczo mamy zewnętrzną zawartość HTML, którą zapisujemy w naszej tabeli dokumentów w bazie danych, a następnie wstawiamy na stronę w określonych okolicznościach, gdy jesteś w zestawie danych Dokumenty.
Tak więc, biorąc pod uwagę elementy n
śródliniowe, z których maksymalnie n
może zawierać zewnętrzny kod HTML, musieliśmy opracować system, który będzie automatycznie zmieniał rozmiar elementu iframe każdego elementu wbudowanego po całkowitym załadowaniu zawartości każdego z nich. Po krótkim zakręceniu kołami skończyło się na tym:
message
detektor zdarzeń w indeksie naszej aplikacji React, który sprawdza określony klucz, który ustawimy z elementu iframe nadawcy.<script>
kodu HTML, dołączam tag, który będzie czekał na uruchomienie elementu iframe window.onload
. Po postMessage
uruchomieniu wysyłamy wiadomość do okna nadrzędnego z informacjami o identyfikatorze iframe, obliczonej wysokości itp.id
elementu iframe, który przekazujemy w MessageEvent
obiekcieiframe
, po prostu ustaw wysokość na podstawie wartości, która jest przekazywana z elementu 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"
)
}
}
}}
/>