Blog

A pattern for extracting JavaScript from HTML

by | Jun 3, 2011 | Software Development, Webapps | 4 comments

When I wrote about separation of concerns in webapps, I said I would consider how to apply separation of concerns in my project.  This post is a progress report!  I have tried this pattern on several pages and so far, all is well.

Step 1 is obvious: just extract all the JavaScript embedded in the page into its own .js file, and then import the new .js file into the old page.  This part is easy.  The only challenging part might be any hard-coded event handlers embedded in your HTML.  Anywhere you have, e.g., <a href=”…” onclick=”clickMe()”/>, you have to remove such explicit event handlers, and add code like this to the .js file: myAnchor.click=clickMe.

Luckily our code doesn’t have anything like this, so Step 1 is purely mechanical (so far, anyway).

Step 2 is more interesting.  Obviously the new JavaScript file has to be completely static: you want it to be cached by the browser; that’s the whole point of what we’re doing.  So you can’t have any page-specific data in the JavaScript file.

Well, in our code base, the JavaScript needs some page-specific stuff.  The JavaScript has to know about the form field values, the ID numbers of the objects displayed on the form, and other odds and ends of data that may be different each time the page is viewed.

The approach I came up with is to encode such needed data in the HTML page, and then have the JavaScript look up the data when the page is done loading.  jQuery makes this dead easy; with jQuery it is very easy to manipulate the browser DOM.

So the only question is where to put this data on the HTML page?  I use HTML5 custom data attributes: attributes whose name starts with “data-“, can be attached to any HTML element, and are ignored by the browser.  I chose to add these attributes to the HTML body element:


<body
data-contextPath=’<%=request.getContextPath()%>’
data-docId=’<c:out value=”${docId}” escapeXml=”false” />’
data-step=’<c:out value=”${step}” />’

Then, in the JavaScript file, it is very easy using jQuery to read these values… Obviously this code has to run after the DOM is ready:

$(document).ready(function()
{
contextPath = $(“body”).attr(“data-contextPath”);
docId = $(“body”).attr(“data-docId”);
step = $(“body”).attr(“data-step”);
….
}

After applying these two steps, I have a clean separation. All my HTML is in an HTML page, and all my JavaScript is in a JavaScript file (and all my CSS is in a CSS file, but that was already true).

This approach may be old hat for you experienced web developers out there.  Hopefully this approach may help a few of you like me: an old server-side grunt tossed into the wild-and-wooly Web side of things!

Categories

Related Posts

4 Comments

  1. olivvv

    why not use javascript to store your data ? accessing the dom is slow…
    myNamespace = {contextPath: , docId: , step:};

    Reply
  2. olivvv

    your blog software ate away the serverside vars in the js object

    Reply
  3. David Miller

    @Olivv: I was trying to remove all the JavaScript from the HTML page; I wanted my HTML to include only HTML, no Javascript. Having JavaScript in the page would defeat the purpose.

    As for the serverside variables, the JavaScript looks OK to me, the ellipsis just means I didn’t show the whole function, only enough to get the idea across. The HTML snippet looks like some quotes were replaced by smart quotes.

    Reply
    • A.J.

      Interesting!

      Reply

Submit a Comment

Your email address will not be published. Required fields are marked *