I am doing something like this:
var samePath = "http://www.example.com";
function iframeLoaded(){
console.log( iframe.contentDocument.innerHTML );
iframe.src = samePath;
}
iframe.onload = loaded;
Unfortunately, this is really slow: the loading process waits that everything attached to the iframe has actually loaded.
Now:
I cannot use DOMContentLoaded, because once I've set iframe.src, it takes "a little while" for Chrome to create a new iframe.contentDocument object, and I cannot reliably attach events to it (unless I start polling... which would be even worse).
I cannot use DOMFrameContentLoaded because Chrome doesn't fire it (ugh): https://bugs.webkit.org/show_bug.cgi?id=33604 It's a bug, but nobody has tackled it for nearly a year
I cannot use Object.defineProperty() on iframe.contentWindow.document (javascript won't allow it)
I don't think polling for iframe.contentWindow.document is a sane way to go about it (is it?)
So... what is there a way I didn't think about that I could/should follow?
The only other way I thought about is to make an AJAX call and then do document.write() on the iframe. But then, all links to Javascript, CSS etc. will be broken -- unless you can point out a way to make it work without using RegExp...?
NOTE: Please ignore ANY comments about iframe security etc., as that is not the point of this question. Also, I am not able to change the viewed page...
Related
Explanation
For reasons which I appreciate, as of jQuery 1.8, the load event has been deprecated, however, it was still possible to detect whether an image was loaded (even if it was in the cache) just by using certain workarounds. Therefore, the deprecation of the event is actually quite irritating as it posed as a starting point at the very least for detecting when an image has finished loading onto the page.
Nevertheless, it has been deprecated, and I am therefore asking this question with the hope that I will find an answer, thus, help me and potentially others that may soon be running into the same issue.
An Example (before jQuery 1.8)
Without using a plugin (as this should be able to be done in very little code, so a plugin is unnecessary), I would like to call a function when each image on my page is loaded.
Something like this (this will not work due to the deprecation):
$('#mn_content .column').on('load','img',function(){
console.log('loaded');
})
My Question
Is anybody aware of how to achieve this now that the load event does not exist?
Please note: If the only way to achieve this (now), is to use the Javascript new Image objects, then please do not waste your time helping me as others need your help more than I do. I am able to write this code, it just seems a bit long winded for something so basic.
I have simply asked this question to ensure there is not a way of achieving this without the use of the Javascript image objects
I will of course be very grateful for any help, I just don't want you spending much time on me when there are others that need your help more. :-)
The load event still exists, you just can't bind to it using .load anymore. Your event delegation example should continue to work on into 1.9 and 2.0 (if the browser you're testing in supports bubbling of the load event)
I personally would still use the new Image method because i don't trust that all browsers will always bubble the load event properly.
Edit: Sorry if i wasn't clear, the point i was making is that the load event is still there, you just have to properly bind to it. Since the load event doesn't bubble in all browsers (if in any browser?), you must bind the event directly to the image. I'd suggest using the method that you asked us not to provide you an example of.
This code below runs with jaavascript error in IE 8 browser after window.open('','','width=200,height=100') line of code gets executed. New window gets open but it runs with error "jQuery is undefined". Here I do not use jQuery at all, but sure, I use it all across the site.
var newWindow = window.open('','','width=200,height=100')
newWindow.document.write(someHmtlAsString);
newWindow.document.close();
newWindow.focus();
Does anyone have suggestion why is this so, or is there some bug in IE (hack for IE) which would eliminate javascript error while page renders?
Thanks
It looks like someHmtlAsString that you insert contains some <script> tag that tries to use jQuery. Inspect its content and if that's the case, add tag to load jQuery to it or change code not to use it.
You should set the source of new windows and iframes to about:blank if you want control over them.
You also want to use newWindow.contentDocument || newWindow.contentWindow.document
And it might be a good idea to open() the document before you write() to it.
Update: forgot this:
If you open the window about:blank, it needs time to load..
So you cannot write to it at once!!
So either check if it is loaded (onload), then have it write the source (I prefer this).
OR set timeout of about 50ms (usually) and then write to the new window/iframe.
also note that xhtml does not support document.write!!
Good luck!
So, I'm trying to find an answer to why this problem is happening; I've fixed the problem, but I want to know why it happened.
TL;DR
Google-provided conversion tracking code that injected an iframe using document.write suddenly caused the page to cease to execute in all versions of Internet Explorer, but was remedied by injecting the same iframe using a non-document.write method.
The Story:
Doubleclick is an advertising network that provides a JavaScript snippet to track conversions from ads.
The snippet they give looks like this:
<SCRIPT language="JavaScript">
var axel = Math.random()+"";
var a = axel * 10000000000000;
document.write('<IFRAME SRC="https://fls.doubleclick.net/activityi;src=143;type=donat01;cat=indir4;ord=1;num='+ a + '?" WIDTH=10 HEIGHT=10 FRAMEBORDER=0></IFRAME>');
</SCRIPT>
<NOSCRIPT>
<IFRAME SRC="https://fls.doubleclick.net/activityi;src=143;type=donat01;cat=indir4;ord=1;num=1?"
WIDTH=1 HEIGHT=1 FRAMEBORDER=0></IFRAME>
</NOSCRIPT>
Now, I know that, for all sorts of reasons, document.write is hazardous and should be avoided. But, Google is giving me this code, so, I figured I could trust it.
It suddenly started breaking all of our pages for all users using Internet Explorer. As in, the page would stop rendering entirely once it hit the document.write. This was crazy: One of the largest third party advertisers on the internet had given me JavaScript that had LITERALLY broken my purchase pages for 25% of my traffic!
As triage, I quickly substituted in the same code using the injection technique found in Google Analytics:
var iframe = document.createElement('iframe');
iframe.src = //the URL;
iframe.width = 0;
iframe.height = 0;
iframe.frameborder = 0;
var ref = document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(iframe, ref);
This resolved the problem, without actually explaining:
Why does a nearly empty iframe, injected using document.write, break Internet Explorer, but this method above doesn't?
I've solved the problem; it turns out that it had nothing to do with the contents of the <iframe>.
It turns out the page is served by a framework that began using a backend DOM parser that, for reasons likely related to the presence of </ within a <script> tag within the document.write, completely removes the </iframe> closing tag from the generated page, even though it preserves it in the backend. (It's probably trying to enforce ETAGO rules).
The reason I was able to reproduce it was because I was copying the generated document.write code, not the original code, and never noticed the missing </iframe>. (And my "functioning" document.write code didn't have the stripped out </iframe> tag, leading me to believe that the problem was the contents of the iframe.)
As a result, browsers parsed an unclosed <iframe> tag on the page, which Internet Explorer didn't know how to handle, and died part way through the parsing of the iframe (I'm still not totally sure why).
document.write() blocks further page rendering until it finishes. I assume that the remote script was taking a while to load, and thus blocking the rest of the page from loading.
I also assume that Math.Random() function doesn't help matters.
Also...Google's tracking codes scare me...they tend to be ugly hacks of javascript.
There is 2 reasons why the first method should be slow.
document.write() blocks until it is actually performed
the window’s onload event doesn’t fire until all its iframes, and all the resources in these iframes, have fully loaded
Your solution works because the iframe it creates does not request the remote url until after the onload event. Having a set timeout on the first code, you would also get the page to load, then the request to the remote url to fire.
As to why the change of code broke the site, I can not seem to find any speed differences transferring between the two. Maybe it seemed faster because it was cached.
I don't know about the structure of your site, but normally the first script tag is in the <head>. An iframe in the <head> wouldn't be rendered. I'll wager if you did document.body.getElementsByTagName('script')[0] you would probably have similar issues to the one you described above.
Seems you're having a similar problem that I had several months back. The document.write triggers, and overwrites the page. Just use the iframe directly, and everything should be kosher.
I tried replicating your issue but couldn't on IE9.
Either I don't have the right test setup or it seems IE prior to IE 9 had some bug. Firefox had a simialr bug: https://bugzilla.mozilla.org/show_bug.cgi?id=293633
Maybe its a combination of unclosed iframe and something inside the page that's being rendered.
I'm looking for a way to "inject" some events into a flash movie running on a browser. I know about ActionScript's ExternalInterface.addCallback function, however I'm trying to achieve this with any "random" flash from the web. Eg. send a "SPACE" keyboard event to a youtube video.
You can't do this to any random swf on any website because of security limitations. You need to have access to the DOM, which can only be done by Javascript Injections, unless you are the one with the swf embedded in the site, with allowScriptAccess="always" in the html template. MySpace, for example, allows you to add any random swf to the html page, but you can't do that javascript stuff because they force allowScriptAccess to always be false (among other things) to prevent any javascript/dom access.
If this is just for you to make your own life easier while browsing, you can use Firebug for Firefox. Check out this JQuerify Bookmarklet and Video, Hacking Digg with Firebug and JQuery. It shows you how to dynamically modify the webpage your on using javascript, and save those commands as shortcuts! Super cool.
So you could save a JQuerify command like:
$("#youtube_player").play();
...or whatever the api is for starting a youtube video in their html page, if that's even possible.
Hope that helps,
Lance
I tried creating a (WebKit) DOM event and sending it to the Flash OBJECT element. I also tried all of the child nodes of that element to be sure.
function fireEvent(target) {
var evt = document.createEvent("Events");
evt.initEvent("keypress", true, true);
evt.view = window;
evt.altKey = false;
evt.ctrlKey = false;
evt.shiftKey = false;
evt.metaKey = false;
evt.keyCode = 32;
evt.charCode = ' ';
target.dispatchEvent(evt);
}
It didn't work. My answer is: no. You can't do this, at least not from Javascript.
If you really want to do it, I think you'll have to create an application with an embedded browser control (WebKit, Gecko, etc.). Then you could call the plugin API directly to synthesize the user input events. This is how Boxee appears to works, for example.
Unless Flash is configured to listen for the events you're trying to send it, my guess is that what you want to do isn't possible. But, as my wife will surely tell you, I'm wrong a lot.
EDIT: as this problem is now "solved" to the point of working, I am looking to have the information on why. For the fix, see my comment below.
I have an web application which repeatedly downloads wav files dynamically (after a timeout or as instructed by the user) into an iframe in order to trigger the a default audio player to play them. The application targets only FF 2 or 3. In order to determine when the file is downloaded completely, I am hoping to use the window.onload handler for the iframe. Based on this stackoverflow.com answer I am creating a new iframe each time. As long as firebug is enabled on the browser using the application, everything works great. Without firebug, the onload never fires. The version of firebug is 1.3.1, while I've tested Firefox 2.0.0.19 and 3.0.7. Any ideas how I can get the onload from the iframe to reliably trigger when the wav file has downloaded? Or is there another way to signal the completion of the download? Here's the pertinent code:
HTML (hidden's only attribute is display:none;):
<div id="audioContainer" class="hidden">
</div>
JavaScript (could also use jQuery, but innerHTML is faster than html() from what I've read):
waitingForFile = true; // (declared at the beginning of closure)
$("#loading").removeClass("hidden");
var content = "<iframe id='audioPlayer' name='audioPlayer' src='" +
/path/to/file.wav + "' onload='notifyLoaded()'></iframe>";
document.getElementById("audioContainer").innerHTML = content;
And the content of notifyLoaded:
function notifyLoaded() {
waitingForFile = false; // (declared at beginning of the closure)
$("#loading").addClass("hidden");
}
I have also tried creating the iframe via document.createElement, but I found the same behavior. The onload triggered each time with firebug enabled and never without it.
EDIT:
Fixed the information on how the iframe is being declared and added the callback function code. No, no console.log calls here.
Old question but for future reference:
As far as my experience onLoad is not called for file downloads. A way to solve it is to use cookies like they do here http://gruffcode.com/2010/10/28/detecting-the-file-download-dialog-in-the-browser/
Here's an example that works for me, without Firebug open (tested in FF 3.6.2 Mac): http://www.jsfiddle.net/Kukry/
I'm using the jQuery .load() event instead of onload.
var iframe = $("<iframe/>").load(function () {
alert("loaded");
}).attr({
src: "http://code.jquery.com/jquery-1.4.2.min.js"
}).appendTo($("#thediv"));
Note that I'm loading a JavaScript file, not an audio file, so that might make a difference.
Maybe you call some Firebug internal function, like console.log(), somewhere? In that case, Firefox will threw an exception which can stop the execution if Firebug is not active.