Question

Nous utilisons jQuery thickbox pour afficher de manière dynamique un iframe lorsque quelqu'un clique sur une image. Dans cette iframe, nous utilisons une galleria une bibliothèque JavaScript pour afficher plusieurs images.

Le problème semble être que $ (document) .ready dans l'iframe semble être déclenché trop tôt et que le contenu de l'iframe n'est pas encore chargé, le code galleria n'est donc pas appliqué correctement. les éléments DOM. $ (document) .ready semble utiliser l'état prêt de l'iframe parent pour décider si l'iframe est prêt.

Si nous extrayons la fonction appelée par document ready dans une fonction distincte et l’appelons après un délai d’attente de 100 & nbsp; ms. Cela fonctionne, mais nous ne pouvons pas prendre de risque en production avec un ordinateur lent.

$(document).ready(function() { setTimeout(ApplyGalleria, 100); });

Ma question: à quel événement jQuery devrions-nous nous lier pour pouvoir exécuter notre code lorsque l'iframe dynamique est prêt et pas seulement un parent?

Était-ce utile?

La solution

J'ai répondu à une question similaire (voir rappel Javascript après le chargement de l'IFRAME? ). Vous pouvez obtenir le contrôle de l'événement de chargement iframe avec le code suivant:

function callIframe(url, callback) {
    $(document.body).append('<IFRAME id="myId" ...>');
    $('iframe#myId').attr('src', url);

    $('iframe#myId').load(function() {
        callback(this);
    });
}

En traitant des iframes, j’ai trouvé assez bon pour utiliser les événements load au lieu de l'événement document ready.

Autres conseils

Avec jQuery 1.3.2, les éléments suivants ont fonctionné pour moi:

$('iframe').ready(function() {
  $('body', $('iframe').contents()).html('Hello World!');
});

REVISION:! En réalité, le code ci-dessus semble parfois fonctionner dans Firefox, jamais dans Opera.

Au lieu de cela, j’ai implémenté une solution de vote par appel. Simplifié, cela ressemble à ceci:

$(function() {
  function manipIframe() {
    el = $('body', $('iframe').contents());
    if (el.length != 1) {
      setTimeout(manipIframe, 100);
      return;
    }
    el.html('Hello World!');
  }
  manipIframe();
});

Cela ne nécessite pas de code dans les pages iframe appelées. Tout le code réside et s’exécute à partir du cadre / de la fenêtre parent.

Dans IFrames, je résous généralement ce problème en mettant un petit script à la fin du bloc:

<body>
The content of your IFrame
<script type="text/javascript">
//<![CDATA[
   fireOnReadyEvent();
   parent.IFrameLoaded();
//]]>
</script>
</body>

Cela fonctionne la plupart du temps pour moi. Parfois, la solution la plus simple et la plus naïve est la plus appropriée.

Suivant l’idée du Dr Jokepu et de David Murdoch, j’ai mis en place une version plus complète. Il faut que jQuery soit placé sur le parent, l’iframe et l’iframe pour être sous votre contrôle.

code iframe:

var iframe = window.frameElement;

if (iframe){
    iframe.contentDocument = document;//normalization: some browsers don't set the contentDocument, only the contentWindow

    var parent = window.parent;
    $(parent.document).ready(function(){//wait for parent to make sure it has jQuery ready
        var parent$ = parent.jQuery;

        parent$(iframe).trigger("iframeloading");

        $(function(){
            parent$(iframe).trigger("iframeready");
        });

        $(window).load(function(){//kind of unnecessary, but here for completion
            parent$(iframe).trigger("iframeloaded");
        });

        $(window).unload(function(e){//not possible to prevent default
            parent$(iframe).trigger("iframeunloaded");
        });

        $(window).on("beforeunload",function(){
            parent$(iframe).trigger("iframebeforeunload");
        });
    });
}

code de test parent:

$(function(){
    $("iframe").on("iframeloading iframeready iframeloaded iframebeforeunload iframeunloaded", function(e){
        console.log(e.type);
    });
});

Trouvez la solution au problème.

Lorsque vous cliquez sur un lien "heavy box" ouvrant un iframe, celui-ci insère un iframe avec un identifiant TB_iframeContent.

Au lieu de compter sur l'événement $ (document) .ready dans le code iframe, il me suffit de faire un lien vers l'événement de chargement de l'iframe dans le document parent:

$('#TB_iframeContent', top.document).load(ApplyGalleria);

Ce code est dans l'iframe mais se lie à un événement d'un contrôle dans le document parent. Cela fonctionne dans FireFox et IE.

Essayez ceci,

<iframe id="testframe" src="about:blank" onload="if (testframe.location.href != 'about:blank') testframe_loaded()"></iframe>

Il vous suffit ensuite de créer la fonction JavaScript testframe_loaded ().

Je charge le fichier PDF avec jQuery ajax dans le cache du navigateur. Ensuite, je crée un élément incorporé avec des données déjà dans le cache du navigateur. Je suppose que cela fonctionnera aussi avec iframe.


var url = "http://example.com/my.pdf";
// show spinner
$.mobile.showPageLoadingMsg('b', note, false);
$.ajax({
    url: url,
    cache: true,
    mimeType: 'application/pdf',
    success: function () {
        // display cached data
        $(scroller).append('<embed type="application/pdf" src="' + url + '" />');
        // hide spinner
        $.mobile.hidePageLoadingMsg();
    }
});

Vous devez également définir correctement vos en-têtes http.


HttpContext.Response.Expires = 1;
HttpContext.Response.Cache.SetNoServerCaching();
HttpContext.Response.Cache.SetAllowResponseInBrowserHistory(false);
HttpContext.Response.CacheControl = "Private";

En gros ce que d’autres ont déjà publié mais à mon humble avis un peu plus propre:

$('<iframe/>', {
    src: 'https://example.com/',
    load: function() {
        alert("loaded")
    }
}).appendTo('body');

C’est le problème que j’ai rencontré avec notre client. J'ai créé un petit plugin jquery qui semble fonctionner pour la préparation à l'iframe. Il utilise polling pour vérifier si le document iframe readyState est associé à l’URL du document interne et au source de l’iframe afin de s’assurer que l’iframe est bien "prêt".

Le problème avec " onload " c’est que vous avez besoin d’avoir accès au iframe réel ajouté au DOM, sinon vous devez essayer d’attraper le chargement de l’iframe qui, s’il est mis en cache, ne le permet pas. Ce dont j'avais besoin était un script qui puisse être appelé à tout moment et déterminer si l'iframe était "prêt" ou non. ou pas.

Voici la question:

Saint Graal pour déterminer si oui ou non l'iframe local a été chargé

et voici le jsfiddle je suis finalement venu avec.

https://jsfiddle.net/q0smjkh5/10/

Dans le scénario ci-dessus, j'attends que onload ajoute un iframe au dom, puis vérifie l'état prêt du document interne d'iframe - ce qui devrait être interdomaine car il pointe sur wikipedia - mais Chrome semble indiquer "complet". La méthode iready du plug-in est appelée lorsque l'iframe est prête. Le rappel tente de vérifier à nouveau l'état de préparation du document interne - en signalant cette fois une requête interdomaine (ce qui est correct) - de toute façon, il semble fonctionner pour ce dont j'ai besoin et espère que cela aidera les autres.

<script>
  (function($, document, undefined) {
    $.fn["iready"] = function(callback) {
      var ifr = this.filter("iframe"),
          arg = arguments,
          src = this,
          clc = null, // collection
          lng = 50,   // length of time to wait between intervals
          ivl = -1,   // interval id
          chk = function(ifr) {
            try {
              var cnt = ifr.contents(),
                  doc = cnt[0],
                  src = ifr.attr("src"),
                  url = doc.URL;
              switch (doc.readyState) {
                case "complete":
                  if (!src || src === "about:blank") {
                    // we don't care about empty iframes
                    ifr.data("ready", "true");
                  } else if (!url || url === "about:blank") {
                    // empty document still needs loaded
                    ifr.data("ready", undefined);
                  } else {
                    // not an empty iframe and not an empty src
                    // should be loaded
                    ifr.data("ready", true);
                  }

                  break;
                case "interactive":
                  ifr.data("ready", "true");
                  break;
                case "loading":
                default:
                  // still loading
                  break;   
              }
            } catch (ignore) {
              // as far as we're concerned the iframe is ready
              // since we won't be able to access it cross domain
              ifr.data("ready", "true");
            }

            return ifr.data("ready") === "true";
          };

      if (ifr.length) {
        ifr.each(function() {
          if (!$(this).data("ready")) {
            // add to collection
            clc = (clc) ? clc.add($(this)) : $(this);
          }
        });
        if (clc) {
          ivl = setInterval(function() {
            var rd = true;
            clc.each(function() {
              if (!$(this).data("ready")) {
                if (!chk($(this))) {
                  rd = false;
                }
              }
            });

            if (rd) {
              clearInterval(ivl);
              clc = null;
              callback.apply(src, arg);
            }
          }, lng);
        } else {
          clc = null;
          callback.apply(src, arg);
        }
      } else {
        clc = null;
        callback.apply(this, arguments);
      }
      return this;
    };
  }(jQuery, document));
</script>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top