Wie ändere ich die Größe eines Iframes aus einer anderen Domain?
-Bearbeiten
Scrollen Sie nach unten, um einige Lösungen zu finden. Oder lesen Sie, wie Sie dies NICHT tun können: D.
Nach vielen Stunden Code-Hacking ist die Schlussfolgerung, dass auf alles im Iframe nicht zugegriffen werden kann, selbst auf die Bildlaufleisten, die auf meiner Domain gerendert werden. Ich habe viele Techniken ohne Erfolg ausprobiert.
Um Zeit zu sparen, gehen Sie nicht einmal diesen Weg, sondern verwenden Sie sendMessages für die domänenübergreifende Kommunikation. Es gibt Plug-Ins für HTML <5, die ich benutze. Ein schönes Beispiel finden Sie unten :)
In den letzten Tagen habe ich versucht, einen Iframe in eine Site zu integrieren. Dies ist eine kurzfristige Lösung, während sich die andere Seite entwickelt und eine API (kann Monate dauern ...). Und da dies eine kurzfristige Lösung ist, die wir gemacht haben, möchten wir easyXDM verwenden. Ich habe Zugriff auf die andere Domain, aber es ist schwierig genug, sie darum zu bitten Fügen Sie den p3p-Header so hinzu, wie er ist .....
3 iframes
Die naheliegendste Lösung, die ich gefunden habe, waren die 3 Iframes - aber es geht um Chrom und Safari, also kann ich das nicht verwenden.
offen in Chrom
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179
Messen Sie die Bildlaufleisten
Ich habe einen anderen Beitrag darüber gefunden, wie man die Bildlaufhöhe verwendet, um die Größe des Formulars zu ändern. Theoretisch funktioniert es gut, aber ich konnte es mit der Bildlaufhöhe des Iframes nicht richtig anwenden.
document.body.scrollHeight
Das verwendet offensichtlich die Körperhöhe (kann nicht zu 100% auf diese Eigenschaften zugreifen, basiert auf der Anzeige von canvaz des Clients und nicht auf der Höhe des X-Domains-Dokuments).
Ich habe versucht, mit jquery die Höhe des Iframes zu ermitteln
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
Rückgabewerte, die sich in Chrom und dh unterscheiden - oder überhaupt keinen Sinn ergeben. Das Problem ist, dass alles im Rahmen verweigert wird - sogar die Bildlaufleiste ...
Berechnete Stile
Aber wenn ich den Iframe inspiziere und in Chrom verteile, zeigt mir bladdy die Dokumentabmessungen innerhalb des Iframes (unter Verwendung der jquery x-domain, um iframe.heigh zu erhalten - Zugriff verweigert). Das berechnete CSS enthält nichts
Wie berechnet Chrom das? (Der Bearbeitungsbrowser rendert die Seite mithilfe der integrierten Rendering-Engine neu, um alle diese Einstellungen zu berechnen. Sie werden jedoch nirgendwo angehängt, um domänenübergreifenden Betrug zu verhindern. Also.)
HTML4
Ich habe die Spezifikation von HTML4.x gelesen und dort steht, dass schreibgeschützte Werte über document.element verfügbar gemacht werden sollen, der Zugriff jedoch über jquery verweigert wird
Proxy-Frame
Ich bin den Weg gegangen, die Site zurückzusenden und zu berechnen, was in Ordnung ist. Bis sich ein Benutzer über den Iframe anmeldet und der Proxy anstelle des eigentlichen Inhalts eine Anmeldeseite erhält. Auch für manche ist es nicht akzeptabel, die Seite zweimal aufzurufen
http://www.codeproject.com/KB/aspnet/asproxy.aspx
http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/
Rendern Sie die Seite erneut
Ich bin nicht so weit gegangen, aber es gibt JScript-Engines, die sich die Quelle ansehen und die Seite basierend auf der Quelldatei neu rendern. Aber es würde das Hacken dieser JSkripte erfordern ... und das ist keine ideale Situation für kommerzielle Einheiten ... und einige greifen reine Java-Applets oder serverseitiges Rendering ein
http://en.wikipedia.org/wiki/Server-side_JavaScript
http://htmlunit.sourceforge.net/ <-java nicht jscript
EDIT 09-2013 UPDATE
All dies kann mit HTML5-Sockets durchgeführt werden. EasyXDM ist jedoch ein großartiger Fallback für Nicht-HTML5-Beschwerdeseiten.
Lösung 1 Sehr gute Lösung!
Mit easyXDM
Auf Ihrem Server richten Sie eine Seite in Form von ein
<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>
und in der Anruferdomäne müssen sie nur die HTML-Dateien intermiedate_frame und easyXDM.js an derselben Stelle hinzufügen. Wie ein übergeordneter Ordner - dann können Sie nur für Sie auf relative Verzeichnisse oder einen enthaltenen Ordner zugreifen.
OPTION 1
Wenn Sie nicht allen Seiten Skripte hinzufügen möchten, sehen Sie sich Option 2 an!
Dann können sie einfach ein einfaches jscript am Ende jeder Seite hinzufügen, für die die Größenänderung erforderlich ist. Das easyxdm muss nicht in jede dieser Seiten aufgenommen werden.
<script type="text/javascript">
window.onload = function(){ parent.socket.postMessage( (parseInt(document.body.clientHeight)) + "," + ( document.body.clientWidth ) ); };
</script>
Ich habe die gesendeten Parameter geändert. Wenn die Breite ordnungsgemäß funktionieren soll, müssen die Seiten in der anderen Domäne die Breite der Seite in einem Stil enthalten, der ungefähr so aussieht wie:
<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>
Das funktioniert gut für mich. Wenn die Breite nicht enthalten ist, verhält sich der Rahmen etwas seltsam und versucht zu erraten, was er sein soll. Er wird nicht verkleinert, wenn Sie es brauchen.
OPTION 2
Ändern Sie den Zwischenrahmen, um nach Änderungen zu suchen
Ihr Zwischenrahmen sollte ungefähr so aussehen.
<!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>
Das Intervall könnte effizienter gestaltet werden, um zu überprüfen, ob sich die Größe geändert hat, und nur dann zu senden, wenn sich die Abmessungen ändern, anstatt alle 500 ms Nachrichten zu veröffentlichen. Wenn Sie diese Prüfung durchführen, können Sie die Abfrage auf nur 50 ms ändern! habe Spaß
Arbeiten Sie browserübergreifend und schnell. Tolle Debugging-Funktionen !!
Excellent Work to Sean Kinsey who made the script!!!
Lösung 2 (funktioniert aber nicht so gut)
Wenn Sie also eine gegenseitige Vereinbarung mit der anderen Domain haben, können Sie eine Bibliothek hinzufügen, um sendmessage zu verarbeiten. Wenn Sie keinen Zugriff auf die andere Domain haben, suchen Sie weiter nach weiteren Hacks, da ich diese gefunden oder nicht vollständig rechtfertigen konnte.
Die andere Domain wird diese also in das Head-Tag aufnehmen
<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>
In der club.js sind nur einige benutzerdefinierte Anrufe, die ich für Größenänderungsanrufe getätigt habe und enthält ..
$(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 );
});
Und Ihre Seite wird die ganze harte Arbeit erledigen und hat ein schönes Skript ...
//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');
});
OPTION 3
Es handelt sich jetzt um eine kleine JS-Bibliothek zum Verwalten der Größenänderung domänenübergreifender iFrames. Der iFrame muss weiterhin über etwas JavaScript verfügen. Dies sind jedoch nur 2,8 KB (765 Byte Gzipped) nativer JS, die keine Abhängigkeiten aufweisen und es macht nichts, bis es von der übergeordneten Seite aufgerufen wird. Dies bedeutet, dass es ein netter Gast auf anderen Personensystemen ist.
Dieser Code verwendet mutationsObserver, um DOM-Änderungen zu erkennen, und sucht auch nach Größenänderungsereignissen, damit der iFrame an den Inhalt angepasst bleibt. Funktioniert in IE8 +.