Skip to content

Just add JavaScript

shawnbot edited this page Jun 22, 2012 · 7 revisions

Including scripts

JavaScript scripts are either included via external URLs in an empty <script> tag's "src" attribute:

<script type="text/javascript" src="path/to/script.js"></script>

...or they are declared inline, as the contents of the <script> tag:

<script type="text/javascript">
var foo = document.getElementById("foo");
</script>

Types of Scripts

I lump JavaScript files into three distinct categories: library, utility, and site scripts.

Library scripts

Library scripts define functionality without modifying the browser API or document, such as jQuery and d3. These should go into the <head> of your HTML document:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="path/to/library.js"></script>
  </body>
  </head>
  <body>...</body>
</html>

NB: Remember to include scripts with dependencies after the script(s) they depend on. For instance, jQuery UI needs to be included after jQuery.

Utility scripts

Utility scripts, sometimes referred to as "shims" or "polyfills", augment browsers (typically older and/or known buggy ones) with features found in modern browsers. (aight, for instance, "fixes" the browser APIs in IE8 to make the browser work with d3.) These also belong in the <head> of your HTML document, and should be placed before any library (or other utility) scripts that might rely on the APIs augmented.

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="js/vendor/aight.min.js"></script>
    <script type="text/javascript" src="js/vendor/d3.v2.min.js"></script>
  </body>
  </head>
  <body>...</body>
</html>

Site scripts

Site scripts provide page-specific functionality, and typically modify the document. Anything that you would call a client-side "app" is a site script. The most bulletproof method for including a site script (and guaranteeing that it has access to the full DOM when it executes) is to put it at the end of the <body> with a "defer" attribute:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="js/vendor/jquery.min.js"></script>
  </head>
  <body>
    <h1>This heading will be red</h1>
    <script type="text/javascript">
      $("h1").css("color", "red");
    </script>
  </body>
</html>

Execution Order

Scripts execute in the order that they're declared in the document, with one major caveat:

Deferred Scripts

The <script> tag's "defer" attribute tells the browser to defer its execution until all other resources are loaded. Multiple scripts with a "defer" attribute will be executed in the order that they appear in the document, but only after all other scripts without "defer". The rules dictating execution order are actually more complicated than that, but in at least as far back as IE8 it's safe to assume that deferred scripts will always be executed after non-deferred ones.

DOM Ready events

jQuery popularized a method for queueing up functions to call once the DOM is "ready", which means that you can place your <script> anywhere you want (including the <head>, as long as it's after jQuery) and the execution of the enclosed function will be deferred until jQuery knows for sure that the DOM is ready. It looks like this:

$(document).ready(function() {
  $("#bar").addClass("ready");
});

There's also domready, which you can use standalone or with Ender if you have an aversion to jQuery, or simply can't use it (e.g., because a client uses another DOM library, such as Prototype or YUI (both of which likely have their own equivalent functions built in).

Caching and Testing

Remember that while you're testing your site (whether locally via a file:/// URL, or on a remote server) your browser will be caching scripts. Holding shift while refreshing will force a reload of all the resources on your page (bypassing the cache) in most browsers, but to be safe you should occasionally clear your entire browser cache. This will ensure that scripts are executed in the order they're listed on your page, and it's the only bulletproof way to be sure that deferred scripts execute in the intended order.