web-dev-qa-db-fra.com

Redimensionner la hauteur de l'iframe en fonction de la hauteur du contenu

J'ouvre ma page de blog sur mon site web. Le problème est que je peux donner une largeur à un iframe, mais la hauteur doit être dynamique pour qu'il n'y ait pas de barre de défilement dans l'iframe, et cela ressemble à une seule page.

J'ai essayé divers codes JavaScript pour calculer la hauteur du contenu, mais ils donnent tous une erreur accès refusé et ne sont d'aucune utilité.

<iframe src="http://bagtheplanet.blogspot.com/" name="ifrm" id="ifrm" width="1024px" ></iframe>

Pouvons-nous utiliser Ajax pour calculer la hauteur ou peut-être en utilisant PHP?

68
chinmay

Pour répondre directement à vos deux sous-questions: Non, vous ne pouvez pas le faire avec Ajax, ni le calculer avec PHP.

Par le passé, j'ai utilisé un déclencheur de la page iframe'd dans window.onload (NOT domready, car le chargement des images peut prendre un certain temps) pour transmettre la hauteur du corps de la page au parent.

<body onload='parent.resizeIframe(document.body.scrollHeight)'>

Alors le parent.resizeIframe ressemble à ceci:

function resizeIframe(newHeight)
{
    document.getElementById('blogIframe').style.height = parseInt(newHeight,10) + 10 + 'px';
}

Et voila, vous avez un redimensionneur robuste qui se déclenche une fois que la page est entièrement restituée sans désagréable désagrément contentdocument vs contentWindow :)

Bien sûr, maintenant les gens verront votre iframe à la hauteur par défaut en premier, mais cela peut être facilement traité en cachant votre iframe au début et en affichant simplement une image de «chargement». Ensuite, lorsque la fonction resizeIframe démarre, insérez deux lignes supplémentaires qui masqueront l'image de chargement et afficheront le iframe correspondant à ce faux aspect Ajax.

Bien sûr, cela ne fonctionne que dans le même domaine, vous pouvez donc avoir un script de proxy PHP pour intégrer ce contenu, et une fois que vous y êtes allé, vous pouvez également intégrer le flux RSS de votre blog directement sur votre site. avec PHP.

60
SchizoDuckie

Vous pouvez le faire avec JavaScript.

document.getElementById('foo').height = document.getElementById('foo').contentWindow.document.body.scrollHeight + "px";
8
Anders S

Adapter le contenu d'IFRAME est une chose facile à trouver sur Google . Voici une solution :

<script type="text/javascript">
    function autoIframe(frameId) {
       try {
          frame = document.getElementById(frameId);
          innerDoc = (frame.contentDocument) ? frame.contentDocument : frame.contentWindow.document;
          objToResize = (frame.style) ? frame.style : frame;
          objToResize.height = innerDoc.body.scrollHeight + 10;
       }
       catch(err) {
          window.status = err.message;
       }
    }
</script>

Bien entendu, cela ne résout pas le problème inter-domaines que vous rencontrez ... Paramétrer document.domain pourrait aider si ces sites sont au même endroit. Je ne pense pas qu'il y ait une solution si vous utilisez des sites aléatoires.

4
Scott Evernden

Voici ma solution au problème en utilisant MooTools qui fonctionne dans Firefox 3.6, Safari 4.0.4 et Internet Explorer 7: 

var iframe_container = $('iframe_container_id');
var iframe_style = {
    height: 300,
    width: '100%'
};
if (!Browser.Engine.trident) {
    // IE has hasLayout issues if iframe display is none, so don't use the loading class
    iframe_container.addClass('loading');
    iframe_style.display = 'none';
}
this.iframe = new IFrame({
    frameBorder: 0,
    src: "http://www.youriframeurl.com/",
    styles: iframe_style,
    events: {
        'load': function() {
            var innerDoc = (this.contentDocument) ? this.contentDocument : this.contentWindow.document;
            var h = this.measure(function(){
                return innerDoc.body.scrollHeight;
            });            
            this.setStyles({
                height: h.toInt(),
                display: 'block'
            });
            if (!Browser.Engine.trident) {
                iframe_container.removeClass('loading');
            }
        }
    }
}).inject(iframe_container);

Style la classe "loading" pour afficher un graphique de chargement Ajax au milieu du conteneur iframe. Ensuite, pour les navigateurs autres qu'Internet Explorer, il affichera l'IFRAME de hauteur complète une fois le chargement de son contenu terminé et supprimera le graphique de chargement.

2
Truman Leung

L'astuce consiste à acquérir tous les événements iframe nécessaires à partir d'un script externe. Par exemple, vous avez un script qui crée l'iFrame à l'aide de document.createElement; dans ce même script, vous avez temporairement accès au contenu de l'iFrame.

var dFrame = document.createElement("iframe");
dFrame.src = "http://www.example.com";
// Acquire onload and resize the iframe
dFrame.onload = function()
{
    // Setting the content window's resize function tells us when we've changed the height of the internal document
    // It also only needs to do what onload does, so just have it call onload
    dFrame.contentWindow.onresize = function() { dFrame.onload() };
    dFrame.style.height = dFrame.contentWindow.document.body.scrollHeight + "px";
}
window.onresize = function() {
    dFrame.onload();
}

Cela fonctionne car dFrame reste dans la portée de ces fonctions, ce qui vous donne accès à l'élément iFrame externe à partir de la portée du cadre, ce qui vous permet de voir la hauteur réelle du document et de l'étendre si nécessaire. Cet exemple fonctionnera dans Firefox mais nulle part ailleurs; Je pourrais vous donner les solutions de contournement, mais vous pouvez trouver le reste;)

0
Soup d'Campbells

Je viens de passer la plus grande partie des 3 jours à lutter contre ça. Je travaille sur une application qui charge d'autres applications tout en maintenant un en-tête et un pied de page fixes. Voici ce que je suis venu avec. (J'ai également utilisé EasyXDM, avec succès, mais je l'ai retiré plus tard pour utiliser cette solution.)

Veillez à exécuter ce code APRÈS que le <iframe> existe dans le DOM. Placez-le dans la page qui affiche l'iframe (le parent).

// get the iframe
var theFrame = $("#myIframe");
// set its height to the height of the window minus the combined height of fixed header and footer
theFrame.height(Number($(window).height()) - 80);

function resizeIframe() {
    theFrame.height(Number($(window).height()) - 80);
}

// setup a resize method to fire off resizeIframe.
// use timeout to filter out unnecessary firing.
var TO = false;
$(window).resize(function() {
    if (TO !== false) clearTimeout(TO);
    TO = setTimeout(resizeIframe, 500); //500 is time in miliseconds
});
0
Stone

Ci-dessous, mon gestionnaire d'événements onload.

J'utilise un IFRAME dans une boîte de dialogue jQuery UI . Différents usages nécessiteront quelques ajustements ..__ Cela semble faire l'affaire pour moi (pour le moment) dans Internet Explorer 8 et Firefox 3.5 . Cela pourrait nécessiter quelques ajustements supplémentaires, mais l'idée générale devrait être claire.

    function onLoadDialog(frame) {
    try {
        var body = frame.contentDocument.body;
        var $body = $(body);
        var $frame = $(frame);
        var contentDiv = frame.parentNode;
        var $contentDiv = $(contentDiv);

        var savedShow = $contentDiv.dialog('option', 'show');
        var position = $contentDiv.dialog('option', 'position');
        // disable show effect to enable re-positioning (UI bug?)
        $contentDiv.dialog('option', 'show', null);
        // show dialog, otherwise sizing won't work
        $contentDiv.dialog('open');

        // Maximize frame width in order to determine minimal scrollHeight
        $frame.css('width', $contentDiv.dialog('option', 'maxWidth') -
                contentDiv.offsetWidth + frame.offsetWidth);

        var minScrollHeight = body.scrollHeight;
        var maxWidth = body.offsetWidth;
        var minWidth = 0;
        // decrease frame width until scrollHeight starts to grow (wrapping)
        while (Math.abs(maxWidth - minWidth) > 10) {
            var width = minWidth + Math.ceil((maxWidth - minWidth) / 2);
            $body.css('width', width);
            if (body.scrollHeight > minScrollHeight) {
                minWidth = width;
            } else {
                maxWidth = width;
            }
        }
        $frame.css('width', maxWidth);
        // use maximum height to avoid vertical scrollbar (if possible)
        var maxHeight = $contentDiv.dialog('option', 'maxHeight')
        $frame.css('height', maxHeight);
        $body.css('width', '');
        // correct for vertical scrollbar (if necessary)
        while (body.clientWidth < maxWidth) {
            $frame.css('width', maxWidth + (maxWidth - body.clientWidth));
        }

        var minScrollWidth = body.scrollWidth;
        var minHeight = Math.min(minScrollHeight, maxHeight);
        // descrease frame height until scrollWidth decreases (wrapping)
        while (Math.abs(maxHeight - minHeight) > 10) {
            var height = minHeight + Math.ceil((maxHeight - minHeight) / 2);
            $body.css('height', height);
            if (body.scrollWidth < minScrollWidth) {
                minHeight = height;
            } else {
                maxHeight = height;
            }
        }
        $frame.css('height', maxHeight);
        $body.css('height', '');

        // reset widths to 'auto' where possible
        $contentDiv.css('width', 'auto');
        $contentDiv.css('height', 'auto');
        $contentDiv.dialog('option', 'width', 'auto');

        // re-position the dialog
        $contentDiv.dialog('option', 'position', position);

        // hide dialog
        $contentDiv.dialog('close');
        // restore show effect
        $contentDiv.dialog('option', 'show', savedShow);
        // open using show effect
        $contentDiv.dialog('open');
        // remove show effect for consecutive requests
        $contentDiv.dialog('option', 'show', null);

        return;
    }

    //An error is raised if the IFrame domain != its container's domain
    catch (e) {
        window.status = 'Error: ' + e.number + '; ' + e.description;
        alert('Error: ' + e.number + '; ' + e.description);
    }
};
0
nelis

Essayez ceci, vous pouvez changer même quand vous voulez. Cet exemple utilise jQuery.

$('#iframe').live('mousemove', function (event) {   
    var theFrame = $(this, parent.document.body);
    this.height($(document.body).height() - 350);           
});
0
Idham Perdameian

La réponse de @ SchizoDuckie est très élégante et légère, mais en raison du manque d'implémentation de Webkit pour scrollHeight (voir ici ), elle ne fonctionne pas sur les navigateurs Webkit (Safari, Chrome, etc.).

Pour que cette idée de base fonctionne sur Webkit avec les navigateurs Gecko et Trident, il suffit de remplacer

<body onload='parent.resizeIframe(document.body.scrollHeight)'>

avec 

<body onload='parent.resizeIframe(document.body.offsetHeight)'>

Tant que tout est sur le même domaine, cela fonctionne assez bien.

0
nomadkbro