web-dev-qa-db-fra.com

Redimensionner dynamiquement iframe

Situation: Je travaille sur une conception réactive qui comprend le combo HTML/CSS typique. Tout fonctionne bien sauf dans un cas où il y a un iframe à l'intérieur d'un div. L'iframe devrait s'ajuster automatiquement à la taille de la div parente. Une solution purement css ne s'est pas présentée, alors je vais utiliser une approche JQuery. Cela fonctionne bien, sauf dans un scénario, lors du redimensionnement d'une largeur plus petite à un écran plus large.

HTML:

<div class="container">
    <iframe class="iframe-class" src="http://www.cnn.com/"></iframe>
</div>

CSS:

.container {
    width: 100%;
    height: 250px;
}
.iframe-class {
    width: 100%;
    height: 100%;
    border: 1px solid red;
    overflow: auto;
}

Javascript:

$(function () {
    setIFrameSize();
    $(window).resize(function () {
        setIFrameSize();
    });
});

function setIFrameSize() {
    var ogWidth = 700;
    var ogHeight = 600;
    var ogRatio = ogWidth / ogHeight;

    var windowWidth = $(window).width();
    if (windowWidth < 480) {
        var parentDivWidth = $(".iframe-class").parent().width();
        var newHeight = (parentDivWidth / ogRatio);
        $(".iframe-class").addClass("iframe-class-resize");
        $(".iframe-class-resize").css("width", parentDivWidth);
        $(".iframe-class-resize").css("height", newHeight);
    } else {
        // $(".iframe-class-resize").removeAttr("width");
        // $(".iframe-class-resize").removeAttr("height");
        $(".iframe-class").removeClass("iframe-class-resize");
    }
}

http://jsfiddle.net/TBJ83/

Problème: Lorsque la fenêtre est redimensionnée plus petite, elle vérifie en permanence la largeur de la fenêtre et dès qu'elle atteint <480 px, le code ajoute une classe appelée iframe-class-resize et définit la largeur et la hauteur de cette classe. Lorsque la fenêtre est redimensionnée plus grande, la classe est supprimée dès que la taille atteint 480 px. Le problème est que la définition des attributs width et height les ajoute directement à l'élément et non à la classe elle-même. Par conséquent, la suppression de la classe ne supprime pas les nouvelles largeurs et hauteurs. J'ai essayé de forcer la suppression des attributs en utilisant removeAttr() (commenté ci-dessus) mais cela n'a pas fonctionné.

Quelqu'un voit où le code ci-dessus a mal tourné? Ou des suggestions sur la façon d'obtenir un iframe réactif plus efficacement? L'essentiel est que l'iframe soit à l'intérieur du <div></div> et que la div ne puisse pas nécessairement avoir une largeur ou une hauteur définie. Idéalement, la largeur et la hauteur de la div parent devraient être définies explicitement, mais la façon dont ce site est actuellement configuré ne sera pas toujours possible.

Supplémentaire: Si ce qui précède n’est pas assez clair, essayez ce qui suit pour reproduire le problème:

  • Ouvrez un navigateur sur un ordinateur de bureau. J'utilise Chrome sur une machine Windows. Ne maximisez pas le navigateur.
  • Ouvrez le jsfiddle ci-dessus ( http://jsfiddle.net/TBJ83/ ). Vous remarquerez que le contenu de l'iframe s'étend sur toute la largeur du panneau Aperçu.
  • Redimensionnez manuellement la largeur jusqu'à ce que la fenêtre entière atteigne <480px. À ce stade, le contenu de l'iframe sera plutôt petit.
  • Redimensionnez manuellement la largeur jusqu'à la fenêtre entière >> 480px. Le but est que ce contenu iframe reprenne toute la largeur du panneau Aperçu. Au lieu de cela, le contenu conserve la largeur et la hauteur redimensionnées, car la fonction .css() applique les modifications CSS directement aux éléments plutôt qu'aux classes.

Merci d'avance!

8
jiminy

Vous pouvez le faire dans environ 30 caractères. Changement:

$(".iframe-class").removeClass("iframe-class-resize")

à:

$(".iframe-class").removeClass("iframe-class-resize").css({ width : '', height : '' })

Cela réinitialisera la largeur/hauteur que vous avez appliquée à l'élément. Lorsque vous utilisez .css(), vous ajoutez ce que vous transmettez à l'attribut style de l'élément. Lorsque vous transmettez une valeur vide, jQuery supprime cette propriété de l'attribut style de l'élément.

Voici un violon mis à jour: http://jsfiddle.net/TBJ83/3/

MODIFIER

OK, voici quelque chose de peaufiné pour la performance (et juste quelques autres façons de faire les choses):

$(function () {

    //setup these vars only once since they are static
    var $myIFRAME   = $(".iframe-class"),//unless this collection of elements changes over time, you only need to select them once
        ogWidth     = 700,
        ogHeight    = 600,
        ogRatio     = ogWidth / ogHeight,
        windowWidth = 0,//store windowWidth here, this is just a different way to store this data
        resizeTimer = null;

    function setIFrameSize() {
        if (windowWidth < 480) {

            var parentDivWidth = $myIFRAME.parent().width(),//be aware this will still only get the height of the first element in this set of elements, you'll have to loop over them if you want to support more than one iframe on a page
                newHeight      = (parentDivWidth / ogRatio);

            $myIFRAME.addClass("iframe-class-resize").css({ height : newHeight, width : parentDivWidth });
        } else {
            $myIFRAME.removeClass("iframe-class-resize").css({ width : '', height : '' });
        }
    }

    $(window).resize(function () {

        //only run this once per resize event, if a user drags the window to a different size, this will wait until they finish, then run the resize function
        //this way you don't blow up someone's browser with your resize function running hundreds of times a second
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(function () {
            //make sure to update windowWidth before calling resize function
            windowWidth = $(window).width();

            setIFrameSize();

        }, 75);

    }).trigger("click");//run this once initially, just a different way to initialize
});
8
Jasper

Voici comment je le ferais, le code est beaucoup plus court: http://jsfiddle.net/TBJ83/2/

<div class="container">
    <iframe id="myframe" src="http://www.cnn.com/"></iframe>
</div>

<script>
$(function () {
    setIFrameSize();
    $(window).resize(function () {
        setIFrameSize();
    });
});

function setIFrameSize() {
    var parentDivWidth = $("#myframe").parent().width();
    var parentDivHeight = $("#myframe").parent().height();
    $("#myframe")[0].setAttribute("width", parentDivWidth);
    $("#myframe")[0].setAttribute("height", parentDivHeight);
}
</script>

Je l’ai fait de cette façon en lecture-capacité, mais vous pourriez le rendre encore plus court et plus rapide ...

function setIFrameSize() {
    f = $("#myframe");
    f[0].setAttribute("width", f.parent().width());
    f[0].setAttribute("height", f.parent().height());
}

Un sélecteur, de sorte que vous ne parcourez le DOM qu'une seule fois au lieu de plusieurs fois.

1
gfrobenius

Cela peut être fait en utilisant du CSS pur comme ci-dessous:

iframe {
  height: 300px;
  width: 300px;
  resize: both;
  overflow: auto;
}

Réglez la hauteur et la largeur sur la taille minimale souhaitée, elle semble seulement grossir, pas rétrécir.

0
Abhi Andhariya

Pour ceux qui utilisent Prestashop, voici comment j'ai utilisé le code.

Dans le fichier cms.tpl, j'ai ajouté le code ci-dessous:

{if $cms->id==2}
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'></script>
<script type="text/javascript" src='../themes/myheme/js/formj.js'></script>
<div style="width: 100%; height: 800px;">
<iframe style=" width: 100%; height: 100%; border: overflow: auto;" src="https://cnn.com"></iframe>
</div>
{/if}

Puis créé un nouveau fichier js: formj.js et ajouté le code ci-dessous:

$(function () {

    //setup these vars only once since they are static
    var $myIFRAME   = $(".iframe-class"),//unless this collection of elements changes over time, you only need to select them once
        ogWidth     = 970,
        ogHeight    = 800,
        ogRatio     = ogWidth / ogHeight,
        windowWidth = 0,//store windowWidth here, this is just a different way to store this data
        resizeTimer = null;

    function setIFrameSize() {
        if (windowWidth < 480) {

            var parentDivWidth = $myIFRAME.parent().width(),//be aware this will still only get the height of the first element in this set of elements, you'll have to loop over them if you want to support more than one iframe on a page
                newHeight      = (parentDivWidth / ogRatio);

            $myIFRAME.addClass("iframe-class-resize").css({ height : newHeight, width : parentDivWidth });
        } else {
            $myIFRAME.removeClass("iframe-class-resize").css({ width : '', height : '' });
        }
    }

    $(window).resize(function () {

        //only run this once per resize event, if a user drags the window to a different size, this will wait until they finish, then run the resize function
        //this way you don't blow up someone's browser with your resize function running hundreds of times a second
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(function () {
            //make sure to update windowWidth before calling resize function
            windowWidth = $(window).width();

            setIFrameSize();

        }, 75);

    }).trigger("click");//run this once initially, just a different way to initialize
});
0
keylawnzo