IE fails, when calling functions from external javascript? - javascript

I have a piece of code that can be simplified to this:
var s='' ;
s += "<"+"script type=\"text/javascript\" src=\"http://somehost.com/scripts/FooFunctions.js\">\n";
s += "<"+"/script>" ;
s += "<"+"script type=\"text/javascript\">\n";
s += "FooFunction(42, 'i love cats');\n";
s += "<"+"/script>" ;
document.write(s) ;
In all browsers except IE, this executes as you'd expect - functions from somehost.com/scripts/FooFunctions.js work as expected.
In Internet Explorer, this fails.
Googling this seems difficult. I've found the occasional post witht the same problem, but no solution.
(There is a valid reason that the external file needs to be included from javascript this way, and that the pgae can not have a <script src="http://somehost.com/scripts/FooFunctions.js"> inserted in it.)
To be clear, the question is: How can I make the above piece of code function the same in Internet Explorer as it does in e.g. FireFox?

Try this, it works in IE
function addJsFile(jsFileLocation){
var script=document.createElement('script');
script.type='text/javascript';
script.src=jsFileLocation;
document.getElementsByTagName("head")[0].appendChild(script);
}
addJsFile("http://code.jquery.com/jquery-latest.pack.js");
setTimeout(function(){alert(jQuery);},1000);

It looks like IE is calling FooFunction before the script is loaded. You can test this by using setTimeout("FooFunction(42, 'i love cats')", 1000); assuming one second is enough time for the script to load, this call will succeed.
If you can't use a framework like jQuery to load the scripts, which will provide you with a callback when the script loads, you might be able to hack your own with setInterval, checking for FooFunction

As soon as the document.write call is complete it will run the function in the second script tag. Regardless of whether or not the external script has loaded yet. This should not just be an IE problem but should effect all browsers. Are you sure that it is not effecting other browsers as they have the external script cached? What happens when you clear your cache and try again in another browser?
Anyways, in an ideal world you should just be able to use .onload on the script tag but I'm 99% sure that there is problems with onload not firing on script tags in IE6 so we need to resort to using onload on the window element instead. This will event will not fire until all scripts have been downloaded including external js files like above.

Related

JavaScript document write in IE8

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!

Why does this document.write iframe ads code completely break Internet Explorer?

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.

Hard to debug situation (or bug) in Opera

Ok, I'll do my best.
There's this page http://tiu.ru/image/tmp/test_2.html , which looks differently in Opera then in Chrome and Firefox (maybe others).
It evaluates a javascript code inside <div></div>, that does document.write("") of a piece of another HTML code with <script>, that evaluates JS code that asks Google Ads to write ads.
Google Ads writes it's container and container's content (which loads advertising from Yandex) ((maybe you'll need to disable adblock to see ads, but you can just view the screenshot)).
And the problem is that in Opera it writes that content outside the original div somehow.
Screenshot of result for Chrome:
Screenshot of result for Opera:
If you take that code inside document.write() and put it just as usual HTML code -- everything works well. See http://tiu.ru/image/tmp/test_3.html
I can't figure out how to debug that google ads code, that's why I ask for help. Thank you.
p.s.: you can save page to localhost somewhere and open it, ads won't be loaded, but DOM tree will be the same wrong.
Thank you very much!
Well, you add a script tag with document.write() that does document.write() to add the one that calls GA_googleFillSlot, which itself does document.write() to add a SCRIPT with SRC set to a doubleclick.net URL which calls back into google_ads.js to trigger another document.write() that adds an inline SCRIPT containing another document.write() call to add another external script, this time loading context.js from an.yandex.ru, and it looks like context.js also contains code to add yet two more external scripts to the document. But at this point the damage already happened: although a loading external script inserted with document.write() should block parsing, something odd happens when the doubleclick.net script loads and calls back into google_ads.js that makes Opera close the parent DIV.
Let's see what the DOM looks like the moment DoubleClick calls back to google_ads - by setting a breakpoint in GA_googleSetAdContentsBySlotForSync and using Opera Dragonfly. There we go: on entering this script, the DOM is still OK, the DIV is not closed - but when this script thread does document.write() to add <div id=google_ads_div_ru__context_informers_addon_360x90_ad_container> with comments, markup and scripts inside, something about that new content makes Opera believe it needs to close the former document.write()-inserted DIV. It's a parsing bug deep inside the handling of multiple nested document.write()s, I guess.
This will work fine with Opera's upcoming HTML5 parser. If at all possible for you, don't worry about it and wait until Opera 12 sorts it all out.
Opera has a strict XHTML parser. Try wrapping your javascript in CDATA tags so the parser will ignore the < and & characters as well as any other illegal characters in your script:
<script type="text/javascript">
/* <![CDATA[ */
// put your js code here
/* ]]> */
</script>

Browser-independant workaround for onload event -- making sense?

I have recently found myself playing around with events, and as there is no standard for the event indicating that a page has been loaded (like onload vs. pageshow) I wondered whether something speaks against simply putting some JavaScript at the end of the page. This code would then be executed when the page is loaded.
In this example I would add a keyUp listener to the (input) element identified by iText and assign it to the function updateText(event) (the event object will be passed on to this function).
<html><head></head><body>
<!-- content -->
<script type="text/javascript">
document.getElementById('iText').onkeyup = updateText;
</script>
</body>
</html>
Sample page here:
http://kb.granjow.net/JavaScript/onload.html
Tested in Firefox 3.5, Opera 10.10, IE 6, IE 8, working everywhere.
So, is this good or did I miss something?
Looking forward to your answers.
This would be fine for basic pages. However, if your script dealt with images that hadn't finished downloading or results from ajax requests you might run into trouble. If you're handcoding things, something like this should work:
function registerEvent(el, event, func, bCapture)
{
if (el.attachEvent)
el.attachEvent('on'+event, func);
else if (el.addEventListener)
el.addEventListener(event, func, bCapture);
}
Otherwise, the various JS libraries each have their own implementation such as jQuery's $(document).ready().
That sounds good. There's no reason to not do it that way, as long as your script is at the end of the page. As a matter of fact, ASP.NET uses this method to load it's scripts.

Dynamically created iframe used to download file triggers onload with firebug but not without

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.

Categories

Resources