Mad Ads
May 7th, 2009What does this advertisement say to you? The answer depends not only on your personal point of view, but also on the browser you use to view it!
Why? Because if an included Javascript module “A” uses document.write to write a Javascript include of module “B”, then the order in which the code in “B” is executed relative to the code in “A” depends on the browser.
To clarify: a Javascript include is a script block having a src attribute, like so:
<script type="text/javascript" src="A.js"></script>
The content of “A.js” is a Javascript module.
(By the way, if your browser does not have Javascript enabled, you’re probably wondering “What advertisement?”)
Why would anyone care about this? I do because I’m a web geek and the product I’m working on - Allurent On Demand - depends on nested document.writes to embed content served by Allurent into a customer’s page. (This is a fairly standard practice for ad services - more generally, services that involve embedding content from one site into another.) To achieve consistent behavior across browsers, I had to work around a discrepancy.
The top two browsers in the Windows world differ in how they deal with nested document.write()s. Suppose Javascript module
“A” is organized as follows:
x {B} y
Where x is some Javascript code, y is some more Javascript code, and {B} is the document.write of the include of module “B”.
Mozilla Firefox executes the code in the order in which it appears: x, B, y.
Microsoft IE executes the code in this order: x, y, B
(I’m curious to know how other browsers behave. Is this another case of everyone vs. IE?)
Both behaviors make sense. Execution in order of appearance is certainly intuitive. But document.write is specified to insert at the current “read” position in the HTML document. All Javascript blocks are read and parsed entirely before any execution, so the “read” position at the time of execution is just beyond the end of the block. This explains the IE behavior.
The downside of this discrepancy for code monkeys like me is that the code in “y” can’t depend on some change in state, such as a variable setting, made in “B”!
As you may have guessed by now, the phony ad above is formed by a bunch of nested Javascript modules. Each Javascript statement writes a word or phrase into the page. Nested document.writes are involved! View source to see for yourself. (Imagine a web version of Mad Libs. The user inputs a plural noun, two adjectives, and one of {NO, ALL or SOME} and out pops a proposition - one of two propositions, that is, depending on the browser. Mad Ads!)
How to work around this issue? The order of execution of the “B” and “y” blocks differs among browsers. But replace “y” with an include of a new module “C” that includes the code in y, and the order of execution is the same in both browsers. In general, avoid placing JS code in the section following a document.write of another JS module.