javascript - Holy grail for determining whether or not local iframe has loaded -
firstly, see question asked few times no answers seem satisfactory. looking able call script @ anytime , determine whether or not iframe has loaded - , not limit script require being added iframe tag in onload property.
here's background: have been working on unobtrusive script try , determine whether or not local iframes in dom have loaded, because 1 of our clients includes forms on website in iframes , many of them open in lightboxes - dynamically add iframes dom @ time. can attach open event of lightbox, hit or miss whether can "catch" iframe before has loaded.
let me explain little more.
in testing i've determined onload event fire once - , if bound before iframe loads. example: page should alert "added iframe tag" , listener attached afterward not fire - me makes sense. (i'm using iframe onload property simple example).
https://jsfiddle.net/g1bkd3u1/2/
<script> function loaded () { alert ("added iframe tag"); $("#test").load(function(){ alert("added after load finished"); }); }; </script> <iframe onload="loaded()" id="test" src="https://en.wikipedia.org/wiki/html_element#frames"></iframe>
my next approach check document ready state of iframe seems work in of testing except chrome reports "complete" - expecting "access denied" cross domain request. i'm ok cross domain error because can disregard iframe since interested in local iframes - firefox reports "unintialized" i'm ok because know can attach onload event.
please open in chrome: https://jsfiddle.net/g1bkd3u1/
<iframe id="test" src="https://en.wikipedia.org/wiki/html_element#frames"></iframe> <script> alert($("#test").contents()[0].readystate); </script>
i've found if wait 100ms - iframe seems report expected (a cross domain security exception - want - don't want have wait arbitrary length).
https://jsfiddle.net/g1bkd3u1/4/
<iframe id="test" src="https://en.wikipedia.org/wiki/html_element#frames"></iframe> <script> settimeout(function () { try { alert($("#test").contents()[0].readystate); } catch (ignore) { alert("cross domain request"); } }, 100); </script>
my current workaround / solution add onload event handler, detach iframe dom, insert dom in same place - onload event trigger. here's example waits 3 seconds (hoping thats enough time iframe load) show detaching , re-attaching causes iframe onload event fire.
https://jsfiddle.net/g1bkd3u1/5/
<iframe id="test" src="https://en.wikipedia.org/wiki/html_element#frames"></iframe> <script> settimeout(function(){ var placeholder = $("<span>"); $("#test").load(function(){ alert("i know frame has loaded now"); }).after(placeholder).detach().insertafter(placeholder); placeholder.detach(); }, 3000); </script>
while works leaves me wondering if there better more elegant techniques checking iframe load (unobtrusively)?
thank time.
today ran bug removing , re-inserting of iframes breaking wysiwyg editor on website. created start of small jquery plugin check iframe readiness. not production ready , have not tested much, should provide nicer alternative detaching , re-attaching iframe - use polling if needs to, should remove setinterval when iframe ready.
it can used like:
$("iframe").iready(function() { ... });
https://jsfiddle.net/q0smjkh5/10/
<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 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") { // don't care empty iframes ifr.data("ready", "true"); } else if (!url || url === "about:blank") { // empty document still needs loaded ifr.data("ready", undefined); } else { // not empty iframe , not empty src // should loaded ifr.data("ready", true); } break; case "interactive": ifr.data("ready", "true"); break; case "loading": default: // still loading break; } } catch (ignore) { // far we're concerned iframe ready // since won't able access cross domain ifr.data("ready", "true"); } return ifr.data("ready") === "true"; }; if (ifr.length) { ifr.each(function() { if (!$(this).data("ready")) { // add 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>
the example waits until window has loaded dynamically add iframe dom, alerts document's readystate - in chrome displays "complete", incorrectly. iready function should called after , attempt output document's readystate proves cross domain exception - again has not been thoroughly tested works need.
Comments
Post a Comment