Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Saturday, October 6, 2007

Simple Deferred DOM Access

One of the common Framework features that I like is the ability to defer the execution a Function until the DOM is stable. For example, YUI has the Function “YAHOO.util.Event.onDOMReady” which you can use in place of “window.onload”. Any Function passed to “onDOMReady” will be executed when the page HTML content has loaded, but before images and other binary data. This allows more or all of your initialization JavaScript to execute before the user feels the page has loaded.

I am mostly a standard purist and until recently, I have always put my JavaScript into the header of the page. Therefore, to reference HTMLElements by ID that were not yet loaded, I used “onDOMReady” religiously to initialize my scripts. However, after the release of YSlow, I did some research, realizing that it was more efficient and acceptable to include your JavaScript content as the last elements of the Body Tag. This mostly eliminated the need for deferred DOM loading.

However, while messing around with the Lazy Function Definition Pattern (which I had a lot of fun playing with this week), I realized a simple way to test if the DOM is ready. Consider the following:

var isDOMReady = function() { var bd = document.getElementsByTagName('body')[0]; if (! bd) { return false; } bd.appendChild(createElement('div')); isDOMReady = function() {return true;} } var checkDOM = function() { if (isDOMReady()) { alert('ready'); } else { setTimeout(checkDOM, 250); } } checkDOM();

The “checkDOM” Function is a runner thread that polls “isDOMReady”, until there is a Body Tag found using the “getElementsByTagName” method on the document. This returns the Body Tag only after the body has completly loaded. We use the Lazy Function Definition Pattern to overwrite the implementation of “isDOMReady” on the assumption that once the DOM is ready, it will always be ready, so no need to keep testing. “checkDOM” then fires an alert saying that the DOM is ready.

Obviously, this is only a semi-functional test example, but you get the idea. If you replace the alert with a CustomEvent, or another equivalent event system (that different Functions can subscribe to), then you would fire it now, completing your onDOMReady system.

posted by Matt Snider at 12:30 am  

Wednesday, October 3, 2007

Lazy Function Definition Pattern

I am a little busy this week and did not make my regularly scheduled Tuesday post. To make up for it, today we will be discussing an interesting JavaScript pattern that you probably have not seen before, called Lazy Function Definition (as coined by Peter Michaux). Since everything in JavaScript is an Object, including Functions, you have the power to change and/or rewrite functions while executing inside their scope. Basically, you can update a Functions definition, on the fly, from the inside its scope. So if you have a repeating operation, such as a browser test, inside of a Function (foo) that is always the same for the current user and has to be repeated each time ‘foo’ executes, then you can instead overload ‘foo’ with the appropriate code the first that ‘foo’ executes. Then each subsequent call, will not have the overhead of your browser test.

A simple example might be:

var getStartTime = function() { var t = new Date(); getStartTime = function() { return t; } return getStartTime(); }

Assume, the Function “getStartTime” is used to determine the time a process begins, such as once your JavaScript has started on a page. The first time you call it, the following happens:

  1. The variable ‘t’ is set to the time that the function is first executed
  2. The global (window) scoped “getStartTime” is then overloaded with a closure that returns the variable ‘t’; this does not conflict with the currently executing scope
  3. “getStartTime” is re-executed inside of itself, but now it will return the value of ‘t’, from the closure

Then any future time you call “getStartTime” you will always get the value of ‘t’ as the closure is now the definition of the Function. This pattern is incredibly powerful when tuning your JavaScript, as: you do not need to define variables unless they are needed, those variables can exists as scoped (private) variables, and future calls to Functions using this pattern will be faster. We can apply this to “attachEvent” Function from last Friday’s article, Xbrowser Event Handling:

var detachFunc = function(); var attachFunc = function(el, eType, fn, capture) { if (window.addEventListener) { attachFunc = function(el, eType, fn, capture) { el.addEventListener(eType, fn, (capture)); }; detachFunc = function (el, eType, fn, capture) { el.removeEventListener(eType, fn, capture); }; } else if (window.attachEvent) { attachFunc = function(el, eType, fn, capture) { el.attachEvent(”on” + eType, fn, capture); }; detachFunc = function (el, eType, fn, capture) { el.detachEvent(”on” + eType, fn, capture); }; } else { attachFunc = function(); } attachFunc(el, eType, fn, capture); }

It is mostly safe to create the detach Function lazily along with the attach Function, because there are no events to detach if you have never attached any events. However, we have set “detachFunc” to an empty function, just in case your code accidentally tries to detach an event before it attaches it.

For another example, Dustin Diaz, recently used the Lazy Function Definition Pattern to illustrate how to improve his getXHR() method (the backbone of an AJAX system), in his article:

Faster Ajax

posted by Matt Snider at 8:37 pm  

Monday, October 1, 2007

Web Development News 10.01.07

1) Dustin Diaz, writes about improving your “getXHR” Function. Using his code will create a very robust Function that finds the appropriate XHR Object, then overloads the executing Function so that you do not have to find the Object each time you call “getXHR”. Thus, removing the cost of a constant operation from your getXHR Function and improving the performance.

http://www.dustindiaz.com/faster-ajax/

2) Website-Performance.org goes live. This site is dedicated to providing good information, tools, and techniques for improving the performance of your website.

http://website-performance.org/

3) YUI is showcased by a design magazine, Smashing Magazine.

http://feeds.feedburner.com/~r/SmashingMagazine/~3/163652967/

posted by Matt Snider at 10:37 am  
« Previous Page

Powered by WordPress