Pregunta

Estamos utilizando jQuery thickbox para mostrar dinámicamente un iframe cuando alguien hace clic en una imagen. En este marco, estamos usando galleria una biblioteca de javascript para mostrar varias imágenes.

El problema parece ser que $ (document) .ready en el iframe parece haberse activado demasiado pronto y el contenido del iframe aún no se ha cargado, por lo que el código galleria no se aplica correctamente en los elementos DOM. $ (document) .ready parece utilizar el estado de estado primario de iframe para decidir si el iframe está listo.

Si extraemos la función llamada por documento listo en una función separada y la llamamos después de un tiempo de espera de 100 & nbsp; ms. Funciona, pero no podemos arriesgarnos en la producción con una computadora lenta.

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

Mi pregunta: ¿a qué evento jQuery deberíamos vincularnos para poder ejecutar nuestro código cuando el iframe dinámico esté listo y no solo sea un padre?

¿Fue útil?

Solución

Respondí una pregunta similar (consulte devolución de llamada de Javascript cuando el IFRAME haya terminado de cargarse. ). Puede obtener control sobre el evento de carga de iframe con el siguiente código:

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

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

Al tratar con los iframes, encontré lo suficientemente bueno para usar el evento load en lugar del evento preparado para documentos.

Otros consejos

Usando jQuery 1.3.2, lo siguiente funcionó para mí:

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

REVISION :! En realidad, el código anterior a veces parece que funciona en Firefox, nunca parece que funcione en Opera.

En cambio, implementé una solución de sondeo para mis propósitos. Simplificado, se ve así:

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

Esto no requiere código en las páginas iframe llamadas. Todo el código reside y se ejecuta desde el marco / ventana principal.

En IFrames, generalmente resuelvo este problema poniendo una pequeña secuencia de comandos al final del bloque:

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

Este trabajo la mayor parte del tiempo para mí. A veces, la solución más simple e ingenua es la más apropiada.

Siguiendo la idea de DrJokepu y David Murdoch, implementé una versión más completa. requiere jQuery tanto en el padre como en el iframe y el iframe para estar bajo su control.

código 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");
        });
    });
}

código de prueba principal:

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

Encontré la solución al problema.

Al hacer clic en el enlace de una caja de datos que abre un iframe, inserta un iframe con un id de TB_iframeContent.

En lugar de confiar en el evento $ (document) .ready en el código del iframe, solo tengo que enlazar el evento de carga del iframe en el documento principal:

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

Este código está en el iframe pero se enlaza con un evento de un control en el documento principal. Funciona en Firefox y IE.

Prueba esto,

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

Todo lo que necesitas hacer es crear la función JavaScript testframe_loaded ().

Estoy cargando el PDF con jQuery ajax en el caché del navegador. Entonces creo elementos incrustados con datos ya en caché del navegador. Supongo que también funcionará 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();
    }
});

También debes configurar los encabezados http correctamente.


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

Básicamente, lo que otros ya han publicado, pero en mi humilde opinión un poco más limpio:

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

Este fue el problema exacto que encontré con nuestro cliente. Creé un pequeño plugin de jquery que parece funcionar para la preparación de iframe. Utiliza el sondeo para verificar el documento iframe readyState combinado con la dirección URL interna del documento combinada con la fuente del iframe para asegurarse de que el iframe esté, de hecho, "listo".

El problema con " onload " es que necesita acceso al iframe real que se está agregando al DOM, si no lo hace, debe intentar capturar el iframe que se carga, y si no se almacena en caché, puede que no. Lo que necesitaba era un script que pudiera llamarse en cualquier momento, y determinar si el iframe estaba " listo " o no.

Aquí está la pregunta:

Santo Grial para determinar si es o no iframe local se ha cargado

y aquí está el jsfiddle que finalmente se me ocurrió.

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

En el jsfiddle anterior, estoy esperando a que onload agregue un iframe al dom, luego verifico el estado de preparación del documento interno de iframe, que debería ser de dominio cruzado porque está apuntado a wikipedia, pero Chrome parece informar "completo". El método iready del complemento se llama cuando el iframe está listo. La devolución de llamada intenta verificar el estado de preparación del documento interno nuevamente, esta vez informando una solicitud de dominio cruzado (lo cual es correcto); de todos modos, parece funcionar para lo que necesito y espero que ayude a otros.

<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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top