Hard to debug situation (or bug) in Opera - javascript

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>

Related

Create a <noscript> element with content fails on IE7 and IE8 (jQuery)

I've seen several threads about reading contents, but nothing on writing to noscript.
$('body').append('<noscript><div></div></noscript>');
In Chrome and IE9 I get a noscript-element with a empty div inside like I expect, but in IE7 and IE8 I just get a empty noscript-element without the div inside.
Example: http://jsfiddle.net/cEMNS/
Is there a way to add HTML inside the noscript-tag that works in all browsers? What I need is to add some tracking code into a noscript-element at the end of the page, but the info I need isn't available until after document ready.
Edit: I'm getting a lot of comments on "why". It's some poorly done tracking library that requires this. We don't have access to the code to change it. Regardless, I find it interesting that it works in some browsers and not in others since jQuery was supposed to work equally in all browsers. Is it simply a bug?
Edit2: (2 years later) Adding a noscript on the browser doesn't make sense, I know. My only excuse not the question the task I had was because of lack of sleep, like everyone else in the project. But my rationale was that jQuery should behave the same on all browsers and someone might want to do this on the server.
Regardless of the tracking code, what you are doing (or are required to do) makes no sense!
Why? There are two cases possible here:
user has JavaScript enabled in which case the NOSCRIPT get's inserted into the DOM but is ignored by the browser (does nothing)
user does not have JavaScript enabled, NOSCRIPT does not get inserted and does not "execute"
The end result of both cases is that nothing actually happens.
Just an idea: You could try giving your noscript tag an ID, and then try to use native js.
for example:
$('body').append('<noscript id="myTestNoScript"></noscript>');
document.getElementById('myTestNoScript').innerHTML = '<div></div>';
I would claim that if it does not work with native js, it will not work with any library (feel free to correct me on this one).
I tried following simple HTML code:
<html>
<body>
<noscript>I'm a noscript tag.</noscript>
</body>
</html>
Then I did analyse this with IE8 (in IE7 mode) and his integrated code insprector. Apparently the IE7 checks are script allowed. If so he declared it as empty. And empty tags will be ignored. Unfortunatly I could not try that with disabled script option, because only the Systemadministrator can change the settings (here at my work).
What I can assure you, the noscript does exists. If you add
alert($('noscript').size());
after the creation, the result will be 1.

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.

JavaScript error in Safari, only sometimes

I have a webpage that is using jQuery to hide divs on the page load and show them later based on user interactions.
In my $(document).ready() I execute a bunch of code to hide these divs and to bind a function to the click() handler from jQuery for the regions that trigger showing these divs. It also grabs some values out of the HTML to be used by scripts later. The latter is what's causing an issue.
This code works fine in Firefox and Chrome/Chromium (we're still working on the CSS for IE, but the JS works as far as I can tell). In Safari, it works flawlessly about 70% of the time. Every few page loads however, a line in my $(document).ready() gives me an error and stops the JS from executing, also halting the drawing of HTML for the rest of the page.
the line is:
var itemCount = document.getElementById('itemCount').innerHTML;
The debug console in Safari says "Null Value". The thing is, I see the following in my HTML (from the "view source" of the page after it failed to load right):
<div id="itemCount" style="display:inline">0</div>
and it is the only item with this id (obviously.)
I'm thinking that somehow the JS is getting run before the document is actually ready, and was thinking I'd try testing to see if document.getElementById('itemCount') returns null and wait for a bit if it does, but I don't know if this would work, or if there is a less ugly solution.
Let me know if I'm missing something obvious, or being dumb some other way.
From the way your code is written, I think there must be some other error on the page that is causing this. Your first code block should be:
var itemCount = $('#itemCount').html();
...and the second:
<span id="itemCount">0</span>
A <div> set to be displayed inline is a <span>. A <span> set to be a block-level element is a <div>. That's the only reason there are the two tags. They're otherwise identical. Use the right one for the task.
Not that I expect either of these changes to change your symptom. I just suspect you have other...questionable things on your page, and that's what's really causing the problem. Wild guess: move the <script> block containing the ready() handler to the bottom of the document's <body>.
If you're not already using Safari 4, by all means do so. Turn on the Develop menu in the advanced preferences, then say Develop > Show Web Inspector before loading your page. If there are errors, it will do a better job of showing you why than Safari 3.
Seems to be an old bug. See ticket 1319 and ticket 4187.
See this potential workaround:
After some experimenting and deleting 99% of this post :) - adding an empty style tag dinamically magically fixes the problem:
(function(){
if (!/WebKit/i.test(navigator.userAgent)) return;
var el = document.createElement("style");
el.type = "text/css";
el.media = "screen, projection";
document.getElementsByTagName("head")[0].appendChild(el);
el.appendChild(document.createTextNode("_safari {}"));
})();

TinyMCE not working with Chrome when I dynamically setContent

I have a site that I put:
<body onload="ajaxLoad()" >
I have a Javascript function that then inserts data from my database into the text editor by using the setContent Javascript method of the textarea. It seems fine in Firefox and IE but in Chrome sometimes nothing shows up. There is no error, just a blank editor.
In the body section I have:
<textarea id="elm1" name="elm1" rows="40" cols="60" style="width: 100%">
</textarea>
In the head section I have:
function ajaxLoad() {
var ed = tinyMCE.get('elm1');
ed.setProgressState(1); // Show progress
window.setTimeout(function() {
ed.setProgressState(0); // Hide progress
ed.setContent('<p style="text-align: center;"><strong><br /><span style="font-size: small;">General Manager's Corner</span></strong></p><p style="text-align: center;">August 2009</p><p>It’s been 15<sup>th</sup> and so have a Steak Night (Saturday, 15<sup>th</sup>) and a shore Dinner planned (Saturday, 22<sup>nd</sup>) this month. urday, September 5<sup>th</sup>. e a can’t missed evening, shas extended it one additional week. The last clinic will be the week of August 11<sup>th</sup>. </p><p> Alt (Tuesday through Thursday) </p><p> I wouClub.</p><p> </p><p> </p><p> </p><p> <strong></strong></p>');
}, 1);
}
I am not sure if its some of the formatting that Chrome is rejecting but it seems like if TinyMCE can parse it in one browser, it should be able to do it in any browser, so I am confused.
Any suggestions?
Background:
For various reasons onload() is not considered the proper approach for loading Javascript, see for example Launching Code on Document Ready, with the most important/noticeable one being that Javascript code isn't run until the page has finished downloading entirely, including images and the like, which might take an eternity therefore (e.g. if an external banner ad server is down etc.).
Instead it is recommended to load Javascript as soon as the DOM is ready, but unfortunately there is no cross browser compatible native solution for this, see Getting notified when the page DOM has loaded (but before window.onload); please note that my entire answer is based upon the most excellent Javascript library jQuery, which offers a cross browser solution for this problem, consequently I'd definitely favor the two higher voted answers over the accepted solution myself.
Likely cause:
Your issue seems to be caused by the opposite behavior though: Chrome facilitates the WebKit rendering engine, just like Safari, and for the latter onload() is discussed to behave differently, see section When does onload fire? in Is Safari faster?. Another description of this problem specific to Chrome can be found in window.onload not working correctly in Chrome, without an explanation though.
In conclusion I suspect onload() to fire before the DOM is actually loaded completely, at least concerning the requirements of TinyMCE, which is notoriously fragile regarding issues like this and simply ceases to load.
Possible solution:
Just facilitating attribute defer on the script tag as outlined in window.onload not working correctly in Chrome is again not cross browser compatible, hence I'd simply go with the widely deployed and proven approach of using the already mentioned jQuery cross browser solution for the onload() problem, which is good practice anyway and should in principle take care of your inverse issue as well.
Update:
There are indeed some bugs filed against WebKit which could back my conclusion (no matter whether this behavior actually constitutes a bug or is intentional), see:
onload sometimes fired before all resources are loaded
window.onload fires before all subresources loaded
Window.onload is firing before image resources are loaded
I had a similar problem (editor not showing in chrome) and read in some forum, that if tinyMCE is unable to locate some files, it just stops loading. Try tracking down if everything is found using firebug's net tab (clear your cache first).
First of all; see to it that you have the latest version of TinyMCE.
I could not reproduce your problem given the information you provides. It seems just fine ( with the faked ajaxload ).
You could always try to go the "back entrance" in;
var myed = document.getElementById('elm1_ifr');
myed.contentDocument.getElementById('tinymce').innerHTML="<p style=\"text-align: center;\"><strong>hacking <span style=\"font-size: small;\">my</span> way in.</strong></p>";
Hope you good luck!
SOLUTION:
Ive been struggling with the TinyMCE toolbar not appearing in all kinds of secnarios....it would work in one user's IE browser, but not another. It would not work in Firefox or Chrome, etc.
Turns out if in the newest 3.3 version there are STILL bugs they have not fixed. This one occurs when in your webpage JavaScript code, where you instantiate the TinyMCE, if you added code for the plugin part where you load up two specific plugins, the toolbar fails to appear and you see HTML:
plugins:
"safari,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,
inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,
fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template,**imagemanager,filemanager**",
Remove all references to imagemanager and filemanager in your web page, then refresh your browser...
When you do, retest in Chrome and Firefox and IE and the TinyMCE suddenly appears! Wow....a miracle, huh?
Turns out their "main developer" hasn't fixed the issue but does explain it as such, if you want to try and still use those plugins and yet fix the problem. His quote is as follows:
"If the ImageManager/FileManager are old they might not use the new
scriptloader api. And the new 3.3 version will load all dependent
scripts async instead of sync. - Spocke - Main developer of TinyMCE"
There are a few ways to set content in a TinyMCE editor. If you want the content to be there when the page first loads, you can just put it between the tags.
Otherwise, you can do this through script in the following way:
window.onload = function() {
tinyMCE.getInstanceById("ProfileText").setContent('test');
};
I have wrapped the code in a window.onload block. If you have other functions that set content dynamically through this way after the TinyMCE editor has already loaded, then you do not need that.
There is an option oninit for the function tinyMCE.init(), put your method there:
tinyMCE.init({
oninit: function(){
tinyMCE.activeEditor.setContent('blah');
}
});
It works this way.
The editor is not fully loaded on document load event, as it the editor loader will post-load a bunch of files.
same problem here, ie needs
var ed = tinyMCE.get('content');
ed.setContent('zzz');
other browsers
document.getElementById("content").innerHTML="zzz";
i am quite disapointed
will need to check browser in javascript to get it working properly, thats suxx

IE fails, when calling functions from external 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.

Categories

Resources