it-swarm.com.de

domänenübergreifende Größenänderung von Iframes

Wie kann ich die Größe eines Iframes aus einer anderen Domain ändern

-Bearbeiten

Scrollen Sie nach unten, um einige Lösungen zu finden. Oder lesen Sie weiter, wie Sie dies NICHT tun können: D

Nach vielen Stunden Code-Hacking ist die Schlussfolgerung, dass auf nichts im iframe zugegriffen werden kann, auch nicht auf die Bildlaufleisten, die in meiner Domain gerendert werden. Ich habe viele Techniken ohne Erfolg ausprobiert.

Um Zeit zu sparen, verwenden Sie sendMessages nicht einmal für die domänenübergreifende Kommunikation.Es gibt Plug-Ins für HTML <5, die ich verwende Nettes Beispiel :)


In den letzten Tagen habe ich versucht, einen Iframe in eine Site zu integrieren. Dies ist eine kurzfristige Lösung, während die andere Seite eine API entwickelt (kann Monate dauern ...). Und da dies eine kurzfristige Lösung ist, möchten wir easyXDM verwenden. Ich habe Zugriff auf die andere Domain, aber es ist schwierig genug, sie darum zu bitten Füge den p3p-Header so wie er ist hinzu .....

3 iframes

Die nächste 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 weiteren Beitrag darüber gefunden, wie man die Größe des Formulars mithilfe der Bildlaufhöhe ändern kann. Theoretisch funktioniert es gut, aber ich konnte es mit der iframes-Bildlaufhöhe nicht richtig anwenden.

document.body.scrollHeight

Das obvois verwendet die Körperhöhe (kann nicht auf diese Eigenschaften 100% zugreifen, basiert auf dem Client-Display-Canvaz und nicht auf der x-domains-Dokumenthöhe)

Ich habe versucht, mit jquery die iframes-Höhe zu ermitteln

$('#frameId').Height()

$('#frameId').clientHeight

$('#frameId').scrollHeight

rückgabewerte unterscheiden sich in Chrom und zB - oder ergeben einfach überhaupt keinen Sinn. Das Problem ist, dass alles innerhalb des Rahmens verweigert wird - sogar die Bildlaufleiste ...

Berechnete Stile

Aber wenn ich das iFrame-Element inspiziere und es in Chrom anführe, zeigt mir Bladdy die Dokumentendimensionen innerhalb des iFrames an (mit Hilfe von jquery x-domain wird iframe.heigh abgerufen - Zugriff verweigert). Das berechnete CSS enthält nichts enter image description here

Wie berechnet Chrome das? (Der Bearbeitungsbrowser rendert die Seite mit seiner eingebauten Rendering-Engine neu, um alle diese Einstellungen zu berechnen. Sie sind jedoch nirgendwo angehängt, um domänenübergreifenden Betrug zu verhindern.)

HTML4

Ich habe die Spezifikation von HTML4.x gelesen und dort steht, dass nur lesbare Werte über document.element verfügbar gemacht werden sollten, aber der Zugriff über jquery verweigert wird

Proxy-Frame

Ich ging den Weg des Proxy-Zugriffs auf die Site zurück und berechnete, was in Ordnung ist, bis sich ein Benutzer über den Iframe anmeldet und der Proxy anstelle des eigentlichen Inhalts eine Anmeldeseite erhält. Auch ein zweimaliger Aufruf der Seite ist nicht akzeptabel

http://www.codeproject.com/KB/aspnet/asproxy.aspx

http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/

Seite neu rendern

Ich bin nicht so weit gegangen, aber es gibt JScript-Engines, die den Quellcode untersuchen und die Seite basierend auf der Quelldatei neu rendern. Aber es würde das Hacken dieser J-Skripte erfordern ... und das ist keine ideale Situation für kommerzielle Einheiten ... und einige reine Java-Applets oder serverseitiges Rendern

http://en.wikipedia.org/wiki/Server-side_JavaScript

http://htmlunit.sourceforge.net/ <-Java not jscript

http://maxq.tigris.org/


EDIT 09-2013UPDATE

All dies kann mit HTML5-Sockets durchgeführt werden. Aber easyXDM ist ein großartiger Fallback für nicht HTML5-fähige Beschwerdeseiten.

Lösung 1 Sehr gute Lösung!

EasyXDM verwenden

Auf Ihrem Server richten Sie eine Seite in Form von

<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 Dateien intermiedate_frame html 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 alle Seiten mit Skripten versehen möchten, schauen Sie sich Option 2 an!

Dann können sie einfach ein einfaches jscript an das Ende jeder Seite anfügen, für die die Größenänderung erforderlich ist. Es ist nicht erforderlich, easyxdm in jede dieser Seiten aufzunehmen.

 <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 korrekt funktionieren soll, müssen die Seiten in der anderen Domäne die Breite der Seite in einem Stil enthalten, der ungefähr wie folgt aussieht:

<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 angegeben ist, verhält sich der Rahmen etwas seltsam und versucht zu erraten, wie er sein sollte. Er wird nicht verkleinert, wenn Sie ihn benötigen.

OPTION 2

Ändere den Zwischenrahmen, um nach Änderungen zu suchen

Ihr Zwischenbild 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 prü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 implementieren, können Sie die Abfrage so niedrig wie 50 ms ändern! habe Spaß


Arbeiten Sie browserübergreifend und schnell. Großartige Debugging-Funktionen !!

Excellent Work to  Sean Kinsey  who made the script!!!

Lösung 2 (Funktioniert aber nicht großartig)

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 Hackes, da ich diese nicht finden oder 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ößenanpassungsanrufe gemacht 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 ein nettes Skript haben ...

  //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 nun um eine kleine JS-Bibliothek zum Verwalten der Größenänderung domänenübergreifender iFrames. Es ist jedoch weiterhin erforderlich, dass der iFrame etwas JavaScript enthält. Dies sind jedoch nur 2,8 KB (765 Gzipped Bytes) nativer JS, für die keine Abhängigkeiten bestehen und es tut nichts, bis es von der übergeordneten Seite aufgerufen wird. Das heißt, es ist ein netter Gast auf anderen People-Systemen.

In diesem Code wird mutationObserver zum Erkennen von DOM-Änderungen verwendet. Außerdem wird nach Größenänderungsereignissen gesucht, damit die Größe des iFrames dem Inhalt entspricht. Funktioniert in IE8 +.

https://github.com/davidjbradshaw/iframe-resizer

82
ppumkin

Die Sache ist - es gibt keine andere Möglichkeit, als Cross-Domain Messaging dafür zu verwenden, da Sie die berechnete Höhe von einem Dokument in einer Domäne zu einem Dokument in einer anderen Domäne berechnen müssen.

Entweder machen Sie dies mit postMessage (funktioniert in allen modernen Browsern) oder Sie verbringen 5 Minuten mit der Anpassung des resize-iframe-Beispiels von easyXDM. 

Die andere Partei muss nur ein paar Dateien in ihre Domäne kopieren und ihrem Dokument eine einzige Codezeile hinzufügen.

10
Sean Kinsey

Ähnlich wie bei Sean können Sie postMessage verwenden. Ich habe so viel Zeit damit verbracht, verschiedene Möglichkeiten zur Änderung der Größe von Iframes mit domänenübergreifenden Funktionen auszuprobieren, aber kein Glück, bis ich auf diesen großartigen Blog-Beitrag von David Walsh gestoßen bin: http://davidwalsh.name/window-iframe

Dies ist eine Kombination aus meinem Code und Davids Lösung. Meine Lösung ist speziell auf die Größenänderung von Iframes ausgerichtet.

Suchen Sie auf der untergeordneten Seite die Höhe der Seite und übergeben Sie sie an die übergeordnete Seite (die den iframe enthält). Ersetzen Sie element_id durch Ihre Element-ID (html, body, whatever).

<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

Fügen Sie im übergeordneten Fenster diesen Code hinzu. Ersetzen Sie iframe_id durch Ihre iframe-ID:

<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>

Wenn Sie die Konsole öffnen, wird die Höhe im Konsolenprotokoll angezeigt. Dies wird Ihnen beim Debuggen helfen, weshalb ich es dort belassen habe.

Am besten, Baker

24
Baker Humadi

Nachdem ich mir eine ganze Reihe von Lösungen angesehen hatte, schrieb ich eine einfache kleine Bibliothek, in der verschiedene Anwendungsfälle berücksichtigt wurden. Da ich eine Lösung brauchte, die mehrere von Benutzern generierte iFrames auf einer Portalseite unterstützte, konnte die Größe des Browsers geändert werden und das JavaScript der Host-Seite konnte nach dem iFrame geladen werden. Ich füge auch Unterstützung für die Größenänderung und eine Rückruffunktion hinzu und erlaube das Überschreiben von body.margin, da Sie dies wahrscheinlich auf Null setzen wollen.

https://github.com/davidjbradshaw/iframe-resizer

Der iframe-Code ist nur ein wenig in sich geschlossenes JavaScript, so dass er auf anderen Seiten ein guter Gast ist.

Das Skript wird dann auf der Host-Seite mit den folgenden verfügbaren Optionen initialisiert. 

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
        );
    }
});
6
David Bradshaw

Haben Sie sich die objektorientierten HTML5-Attribute angesehen? Skaliert Videos/Bilder auf den iframe, anstatt den iframe zu skalieren (Nice, wenn Sie ein mittelgroßes Bild mit einer Breite von 5.000 Pixeln erwerben). Die Option "Anpassen" (andere sind "Deckung" und "Füllen") verwendet einen Briefkastenansatz, um die Quelle anzupassen, während die Seitenverhältnisse beibehalten werden. Für die Anzeige durch HTML5-freier gibt es eine Menge Polyfills. Dies ist großartig, aber ein Fehler am Ende von Edge hat es für ungefähr ein Jahr inkompatibel mit Microsofts New Nightmare gehalten, jetzt: https://github.com/anselmh/object-fit

BEARBEITEN: Um domänenübergreifende Probleme zu umgehen, können Sie die Arbeit einfach in einem Chrome-Erweiterungsskript erledigen, da dies der Meinung ist, dass es Teil der Seite ist, auf der Sie Ihren iframe festhalten.

0
sparkholiday

HTTPS ein anderer Link erhält die Höhe von iframe autoheight

https://-a.com Inhalt:

 <!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-inhalt:

<!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>

Arbeitstisch:

xcom http> ycom https ARBEIT

xcom https> ycom https WORK

xcom http> ycom http ARBEIT

xcom https> ycom http WORK

Test Work Screenshot

0
Limitless isa

Heutzutage gibt es nur 4 Lösungen, die ich kenne:

Nur der dritte kann viele Probleme lösen. Zum Beispiel können Sie responsive iFrame erstellen; Schließen Sie es von innen oder Sie können mit ihm kommunizieren. Dafür benötigen Sie iFrame in Iframe und den Workaround "Drittanbieter-Cookies" (optional).

Ich habe dazu einen Artikel mit Beispiel erstellt: Ereignisgesteuerter, domänenübergreifender iFrame

0

Anstelle von scroll = no für den iframe verwende ich ihn in "auto". Dann bekomme ich die Größe des aktuellen Fensters 

$(window).height();

und verwenden Sie dies als iframe height-Attribut.

Nun, das Ergebnis ist ...

Wir werden niemals die "Seite" scrollen, nur die "iframe". Wenn Sie navigieren, ist es egal, wer die Schriftrolle ist. Wichtig ist jedoch, dass es nur 1 gibt.

Nun, es gibt das Problem, dass der Benutzer das Fenster einfach ändert, während er navigiert. Um das zu lösen, verwende ich:

setInterval(getDocHeight, 1);

Haben Sie gedacht, dass diese Lösung Fehler verursachen wird? Es funktioniert für mich und auf dem iFrame hatte ich einen dynamischen Kontakt, der von PHP erzeugt wurde. Ich habe Angst vor zukünftigen Fehlern damit ...

0
Elton Morais