Pages

Monday, January 18, 2010

Separating javascript from HTML (and automatically running it)

In the old days I wrote event handlers inline *shudder*, then I was enlightened by jQuery and separated event handlers from HTML. I still had a problem though, most of my javascript was still included in my HTML templates, just in a <script> block, like this:

<script>
$(document).ready(function() {
$('div.fancy_widget').click(some function here);
});
</script>
<div class="fancy_widget">
Something fancy that needs to be clicked here
</div>


This is better, but still leaves JS mixed in our templates. A common solution is to put all your code in an external JS file (good) and run it for every page. jQuery is fast so for most part this doesn't cause problems but it doesn't seem right to me. Why would I want to try to bind an event to div.fancy_widget if that only appears on a few pages?

This is my solution:
Separate page / widget specific code into individual classes in an external file.

external.js

function fancy_widget()
{
}

fancy_widget.ready = function()
{
    $('div.fancy_widget').click(some function here);
}


In your HTML file, add "fancy_widget" as the class on your body tag:

<body class="fancy_widget">


Run this code snippet (also in external.js)

$(document).ready(function() {
    // check the class of the body and try to execute the prep functions if there is a class defined for that
    $.each($("body").attr('class').split(" "), function() {
        if (this == '') {
            return
        }
        if (eval("typeof " + this) !== "undefined" && eval("typeof " + this + '.ready') == 'function') {
            eval(this + '.ready()');
        }
    });
});



This will cause fancy_widget.ready() to be called on any page with a body class of "fancy_widget". I also use this for page specific functionality.


I am sure this can be improved and extended but though I would go ahead and publish it.

No comments:

Post a Comment