views:

275

answers:

4

I have a page where I import most of my js in the <head> section. The main page, however, has some inline javascript.

In one of my scripts imported in the <head>, I have $(document).ready... which uses some JS variables defined inline on the page. As far as I can see, this works as I would expect -- $(document).ready doesn't run into any errors using the JS vars defined inline.

However, I have gotten some reports from users that they see " is not defined" error in code inside my $(document).ready where I reference the variable defined inline on the page.

I suspect this is browser specific behavior, but I'm not sure. I didn't find this explicitly in documentation, so can someone confirm that it's OK to use variables defined inline on a page in $(document).ready in JS pulled in from the <head>?

Citing your source would make your answer more credible. :)

Thanks!

+5  A: 

Under the hood: $(document).ready()

As you would expect from John Resig, jQuery’s method for determining when the DOM is ready uses an assortment of optimizations.

For example, if a browser supports the DOMContentLoaded event (as many non-IE browsers do), then it will fire on that event. However, IE can’t safely fire until the document’s readyState reaches “complete”, which is typically later.

If none of those optimizations are available, window.onload will trigger the event

Source: here

gmcalab
What does this mean wrt whether inline JS has been processed or not before the event is fired?
psychotik
+1  A: 

Your inline JS may not be processed before the event fires, as different browsers will work differently. You can assume that your ready function will start as soon as it can, but it is not known exactly when it will start.

You shouldn't assume that the ready function will start quickly, so you may need to write your inline logic to wait until this function has ran.

In javascript, coding to assumptions of when things will happen is risky, just as assuming that the property or function you want to use exists is risky, so you need to code very defensively.

You may want to put the inline javascript into functions and have it called from the ready function, or at least flip some flag to let the inline code know that it is now safe to run.

This will delay you by a tiny bit, most likely, but it will lead to a better user experience, I expect.

James Black
+1  A: 

$(document).ready() uses an assortment of different methods for different browsers. Not too many browsers agree on how to handle this event, so there are a number of ways of testing it. I'm pretty sure the jQuery implementation, at least the IE hack, depends on inserting a fragment and checking it for the doScroll("left") property that should only exist once the DOM is ready. It's an undocumented behavior that could change with newer versions of IE.

The purpose of $(document).ready() is to allow you to run your DOM-dependent JavaScript before the page is finished loading, since window.onload doesn't fire until the entire page has been loaded.

The varying implementations also have varying levels of reliability. It sounds like one of the browsers is firing the script before it finishes loading.

Keep in mind that the order in which inline JavaScript is fired is not necessarily before ready. It sounds to me like you should consolidate your inline scripts into your $(document).ready() callback. jQuery does its best, but it's not perfect.

Andrew Noyes
+2  A: 

Why not place a "script" tag at the end of the "body" tag that starts your app.
By doing this you are sure everything is in place to start (cross browser and cross library).

<html>
  ...
  <script>startApp('param');</script>
</body>
</html>

"startApp" being a function defined anywhere before, either inline or in the "head" tag.

Mic
how does placing this at the end of the body tag help? This sounds like it's the equivalent of defining JS inline, and like others have said there's no guarantees that it'll run before document.ready. Am I not understanding your post correctly, perhaps?
psychotik
@psychotik: I believe @Mic is saying to move the code that is currently inside *document.ready* to a `<script>` tag placed just before the end of the *body* tag. It is then guaranteed to be run after the the variables declared in the earlier inline `<script>` tag you mention.
Roatin Marth
Hmm... that sounds like taking a step backwards. Ideally, you want to throw all your JS in standalong JS files, not add more code to the html itself.
psychotik
Yep, move the code you have in document.ready to a function (startApp in my example) and remove document.ready from your code.
Mic
For the step backward, I think the advantage of a such simple and robust starter is worth an exception to the rule ;)
Mic