Come ridimensiono un iframe da un altro dominio
-Modificare
Scorri verso il basso per alcune soluzioni .. o leggi come NON farlo: D
Dopo molte ore di hacking del codice, la conclusione è che qualsiasi cosa all'interno dell'iframe non è accessibile, anche le barre di scorrimento che vengono visualizzate sul mio dominio. Ho provato molte tecniche senza alcun risultato.
Per risparmiare tempo, non seguire nemmeno questa strada, usa sendMessages per le comunicazioni tra domini. Ci sono plug-in per HTML <5 che uso - Vai in fondo per un bell'esempio :)
Negli ultimi giorni ho provato a integrare un iframe in un sito. Questa è una soluzione a breve termine mentre l'altro lato sviluppa e API (potrebbe richiedere mesi ...) E poiché questa è una soluzione a breve termine, abbiamo voluto usare easyXDM- Ho accesso all'altro dominio ma è abbastanza difficile chiedergli di farlo aggiungi l'intestazione p3p così com'è .....
3 iframe
La soluzione più vicina che ho trovato sono stati i 3 iframe, ma funziona mentalmente con Chrome e Safari, quindi non posso usarlo.
aperto in cromo
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179
Misura le barre di scorrimento
Ho trovato un altro post su come usare lo scrollheight per provare a ridimensionare il form .. in teoria funziona bene ma non ho potuto applicarlo correttamente usando l'altezza di scroll iframe ..
document.body.scrollHeight
Ovviamente utilizza l'altezza del corpo (non è possibile accedere a queste proprietà al 100% si basa sul client di visualizzazione canvaz e non sull'altezza del documento x-domains)
Ho provato a usare jquery per ottenere l'altezza degli iframe
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
restituisce valori diversi in chrome e ie - o semplicemente non ha alcun senso. Il problema è che tutto all'interno del frame è negato, anche la barra di scorrimento ...
Stili calcolati
Ma se ispeziono un elemento in chrome dell'iframe, bladdy mi mostra le dimensioni dei documenti all'interno dell'iframe (usando jquery x-domain per ottenere iframe.heigh - accesso negato) Non c'è niente nel CSS calcolato
Ora come lo calcola Chrome? (modifica: il browser esegue nuovamente il rendering della pagina utilizzando il suo motore di rendering integrato per calcolare tutte queste impostazioni, ma non sono allegati da nessuna parte per prevenire frodi interdominio .. quindi ..)
HTML4
Ho letto le specifiche di HTML4.x e dice che dovrebbero esserci valori di sola lettura esposti tramite document.element ma l'accesso è negato tramite jquery
Frame proxy
Ho seguito il percorso per eseguire il proxy del sito e calcolare quale è OK .. finché un utente non accede tramite l'iframe e il proxy ottiene una pagina di accesso invece del contenuto effettivo. Anche per alcuni chiamare la pagina due volte non è accettabile
http://www.codeproject.com/KB/aspnet/asproxy.aspx
http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/
Renderizza la pagina
Non sono andato così lontano ma ci sono motori jscript là fuori che guarderanno l'origine e renderanno nuovamente la pagina in base al file sorgente. ma richiederebbe l'hacking di quei jscripts .. e questa non è una situazione ideale per entità commerciali ... e alcuni invocano applet java pure o rendering lato server
http://en.wikipedia.org/wiki/Server-side_JavaScript
http://htmlunit.sourceforge.net/ <-java non jscript
EDIT 09-2013 AGGIORNAMENTO
Tutto questo può essere fatto con i socket HTML5. Ma easyXDM è un ottimo fallback per le pagine di reclamo non HTML5.
Soluzione 1 Ottima soluzione!
Utilizzando easyXDM
Sul tuo server hai impostato una pagina sotto forma di
<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>
e sul dominio del chiamante devono solo aggiungere intermiedate_frame html e easyXDM.js nello stesso posto. Come una cartella principale, puoi accedere alle directory relative oa una cartella contenuta solo per te.
OPZIONE 1
Se non vuoi aggiungere script a tutte le pagine guarda l'opzione 2!
Quindi possono semplicemente aggiungere un semplice jscript alla fine di ciascuna delle pagine di cui hai bisogno per il ridimensionamento. Non è necessario includere easyxdm in ciascuna di queste pagine.
<script type="text/javascript">
window.onload = function(){ parent.socket.postMessage( (parseInt(document.body.clientHeight)) + "," + ( document.body.clientWidth ) ); };
</script>
Ho modificato i parametri che invia. Se vuoi che la larghezza funzioni correttamente, le pagine sull'altro dominio devono includere la larghezza della pagina in uno stile che assomigli a qualcosa di simile a:
<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>
Questo funziona alla grande per me. Se la larghezza non è inclusa, la cornice si comporta in modo un po 'strano e cerca di indovinare cosa dovrebbe essere .. e non si restringe se ne hai bisogno.
OPZIONE 2
Modificare il frame intermedio per eseguire il polling delle modifiche
Il tuo frame intermedio dovrebbe assomigliare a questo ..
<!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>
L'intervallo potrebbe essere reso più efficiente per verificare se le dimensioni sono cambiate e inviare solo se le dimensioni cambiano senza inviare messaggi ogni 500 ms. Se si implementa questo controllo, è possibile modificare il polling fino a 50 ms! divertiti
Funziona su tutti i browser ed è veloce. Ottime funzionalità di debug !!
Excellent Work to Sean Kinsey who made the script!!!
Soluzione 2 (funziona ma non eccezionale)
Quindi, in pratica, se hai un accordo reciproco con l'altro dominio, puoi aggiungere una libreria per gestire sendmessage. Se non hai alcun accesso all'altro dominio .. Continua a cercare altri hack, perché non sono riuscito a trovarli o a giustificarli completamente che ho trovato.
Quindi l'altro dominio includerà questi nel tag 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>
Nel club.js ci sono solo alcune chiamate personalizzate che ho fatto per ridimensionare le chiamate e contiene ..
$(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 );
});
E la tua pagina farà tutto il lavoro duro e ha una bella sceneggiatura ...
//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');
});
OPZIONE 3
La loro ora è una piccola libreria JS per la gestione del ridimensionamento di iFrame interdominio, richiede ancora che l'iFrame contenga un po 'di JavaScript, tuttavia, questo è solo 2.8k (765 byte compressi con Gzip) di JS nativo che non ha dipendenze e non fa nulla finché non viene chiamato dalla pagina genitore. Ciò significa che è un buon ospite sui sistemi di altre persone.
Questo codice utilizza mutationObserver per rilevare le modifiche del DOM e controlla anche gli eventi di ridimensionamento, in modo che l'iFrame rimanga dimensionato in base al contenuto. Funziona in IE8 +.