/**********************************************************************
                         Element shortcuts script
                      By Mark Wilton-Jones 16/6/2005
Version 1.0 designed for use with Opera 8+, Mozilla/FF and Safari 1.3+.
     (Mainly works in Internet Explorer 6, but cannot auto-update)
***********************************************************************

Please see http://www.howtocreate.co.uk/jslibs/ for details and a demo of this script
Please see http://www.howtocreate.co.uk/jslibs/termsOfUse.html for terms of use

Prepares quick shortcuts to all child elements in the DOM tree, for example
document.$html[0].$body[0].$table[4].$tbody[0].$tr[7].$td[3].$img[1].src
Each array will only be created if there are actually some child nodes of that
element type, so if in doubt, check for them before using them:
if( document.$html[0].$body[0].$table && document.$html[0].$body[0].$table[0] )

To use:

Inbetween the <head> tags, put:

	<script src="PATH TO SCRIPT/elementshortcuts.js" type="text/javascript"></script>

Once the page has loaded, you can tell the script to prepare the shortcuts using:
buildChildReferences();
This will normally take as much as 200 ms to initially prepare the shortcuts.

You can also build shortcuts for a subtree using a reference to the parentNode:
buildChildReferences(document.getElementsByTagName('table')[4])

The script does not dynamically update, so after making changes to the DOM, you can
trigger a rebuild of the shortcuts for all or part of the document using the same
commands. Updating can take between 100 ms and 1000 ms to rebuild.

It is also possible to make it automatically update, but this is not recommended.
It will rebuild the relevant fragment after every minor change, such as adding
or removing a new element, or moving an element through the DOM tree. Each little
modification will trigger a rebuild, with the associated delay ( for this reason
it is much better to manually trigger updates to the relevant fragment after making
a series of changes to the document). Additionally, if it auto-updates, the
updating is done asynchronously in a separate thread, so your script may try to use
it before it is ready.

To enable auto updating, use:
switchShortcutAutoUpdating(true);
You can also disable it again:
switchShortcutAutoUpdating(false);

You can also enable automatic updating for only a subtree using a reference to the
parentNode - this is more efficient:
switchShortcutAutoUpdating(true,document.getElementsByTagName('table')[4]);

Auto updating does not work in IE or Opera 7.x and will crash Safari 1.2-.
________________________________________________________________________________*/

function buildChildReferences(oDoc,oExclude) {
	var attachChildRefs = function (oEl) {
		for( var n in oEl['$elRefs$'] ) { delete oEl[n]; }
		oEl['$elRefs$'] = [];
		for( var n = 0, m, t; m = oEl.childNodes[n]; n++ ) {
			if( ( t = m.tagName ) && ( m != oExclude ) ) {
				t = '$' + t.toLowerCase();
				if( !oEl[t] ) { oEl['$elRefs$'][t] = oEl[t] = []; }
				oEl[t][oEl[t].length] = m;
			}
		}
	};
	if( !oDoc ) { oDoc = document; }
	var allEl = oDoc.getElementsByTagName('*');
	for( var i = 0, j; j = allEl[i]; i++ ) { attachChildRefs(j); }
	attachChildRefs(oDoc);
}

window['$autoShrCtFunctns$'] = {};
window['$autoShrCtFunctns$'].nodeAdd = function (e) {
	if( e.target.tagName ) { buildChildReferences(e.relatedNode); }
};
window['$autoShrCtFunctns$'].nodeRem = function (e) {
	if( e.target.tagName ) { buildChildReferences(e.relatedNode,e.target); }
};

function switchShortcutAutoUpdating(oOnOff,oElement) {
	var sc = window['$autoShrCtFunctns$'];
	if( !oElement ) { oElement = document; }
	if( !oElement.addEventListener ) { return; }
	oElement.removeEventListener('DOMNodeInserted',sc.nodeAdd,false);
	oElement.removeEventListener('DOMNodeRemoved',sc.nodeRem,false);
	if( oOnOff ) {
		oElement.addEventListener('DOMNodeInserted',sc.nodeAdd,false);
		oElement.addEventListener('DOMNodeRemoved',sc.nodeRem,false);
	}
}