Domanda

Stiamo usando jQuery thickbox per visualizzare dinamicamente un iframe quando qualcuno fa clic su un'immagine. In questo iframe, stiamo utilizzando galleria una libreria javascript per visualizzare più immagini.

Il problema sembra essere che $ (document) .ready nell'iframe sembra essere stato lanciato troppo presto e il contenuto dell'iframe non è stato ancora caricato, quindi il codice della galleria non viene applicato correttamente su gli elementi DOM. $ (document) .ready sembra utilizzare lo stato pronto parent iframe per decidere se iframe è pronto.

Se estraiamo la funzione chiamata dal documento pronto in una funzione separata e la chiamiamo dopo un timeout di 100 & nbsp; ms. Funziona, ma non possiamo correre il rischio in produzione con un computer lento.

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

La mia domanda: a quale evento jQuery dovremmo legarci per poter eseguire il nostro codice quando l'iframe dinamico è pronto e non è solo un genitore?

È stato utile?

Soluzione

Ho risposto a una domanda simile (vedi Richiamata Javascript al termine del caricamento di IFRAME? ). Puoi ottenere il controllo dell'evento di caricamento iframe con il seguente codice:

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

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

Nel trattare con iframe ho trovato abbastanza buono da usare l'evento load invece dell'evento pronto per il documento.

Altri suggerimenti

Usando jQuery 1.3.2 per me ha funzionato:

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

REVISIONE :! In realtà il codice sopra a volte sembra funzionare in Firefox, non sembra mai funzionare in Opera.

Invece ho implementato una soluzione di polling per i miei scopi. Semplificato, sembra così:

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

Questo non richiede codice nelle pagine iframe chiamate. Tutto il codice risiede ed esegue dal frame / dalla finestra padre.

In IFrames di solito risolvo questo problema mettendo un piccolo script alla fine del blocco:

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

Questo lavoro per la maggior parte del tempo per me. A volte la soluzione più semplice e ingenua è la più appropriata.

Seguendo l'idea di DrJokepu e David Murdoch ho implementato una versione più completa. richiede jQuery sia sul genitore che sull'iframe e l'iframe per essere sotto il tuo controllo.

codice 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");
        });
    });
}

codice test genitore:

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

Trovato la soluzione al problema.

Quando fai clic su un link thickbox che apre un iframe, inserisce un iframe con un ID di TB_iframeContent.

Invece di fare affidamento sull'evento $ (document) .ready nel codice iframe, devo solo collegarmi all'evento di caricamento dell'iframe nel documento principale:

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

Questo codice si trova nell'iframe ma si lega a un evento di un controllo nel documento principale. Funziona in FireFox e IE.

Prova questo

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

Tutto ciò che devi fare è creare la funzione JavaScript testframe_loaded ().

Sto caricando il PDF con jQuery ajax nella cache del browser. Quindi creo un elemento incorporato con i dati già nella cache del browser. Immagino che funzionerà anche con 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();
    }
});

Devi impostare correttamente anche le intestazioni http.


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

Fondamentalmente quello che altri hanno già pubblicato ma IMHO un po 'più pulito:

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

Questo è stato esattamente il problema che ho riscontrato con il nostro cliente. Ho creato un piccolo plugin jquery che sembra funzionare per la prontezza di iframe. Utilizza il polling per verificare il documento iframe readyState combinato con l'URL del documento interno combinato con l'origine iframe per assicurarsi che l'iframe sia effettivamente "pronto".

Il problema con " onload " è che è necessario accedere all'iframe effettivo che viene aggiunto al DOM, in caso contrario è necessario provare a rilevare il caricamento dell'iframe che, se viene memorizzato nella cache, non è possibile. Ciò di cui avevo bisogno era uno script che potesse essere chiamato in qualsiasi momento e determinare se l'iframe fosse "pronto" o meno; o no.

Ecco la domanda:

Santo Graal per determinare se iframe locale è stato caricato

ed ecco il jsfiddle che alla fine mi è venuto in mente.

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

Nel jsfiddle sopra, sto aspettando che onload aggiunga un iframe al dom, quindi controllo lo stato pronto del documento interno di iframe - che dovrebbe essere interdominio perché è indicato su Wikipedia - ma Chrome sembra riportare " complete " ;. Il metodo iready del plug-in viene quindi chiamato quando l'iframe è effettivamente pronto. Il callback tenta di controllare di nuovo lo stato pronto del documento interno - questa volta riportando una richiesta tra domini (che è corretta) - comunque sembra funzionare per quello che mi serve e spero che aiuti gli altri.

<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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top