/**
 * a library containing (HTML)node methods 
 * (c) 2004 - 2007  Leen Besslink and Jan Vermaat 
 * version 1.4 - februari 2007
 *
 * Licence: GNU LESSER GENERAL PUBLIC LICENSE (http://www.gnu.org/copyleft/lesser.html)
 *
 *  methods 
 * down (el[object], condition[string], deepChild[bool])
 * childNodeBy (el[object], condition[string], deepChild[bool])
 *	return: het gewenste child-object of false
 *
 * childNodesBy (el[object], condition[string], deepChild[bool])
 *	return: een array met child-object's of false
 *
 * up (el[object], condition[string])
 * parentNodeBy (el[object], condition[string])
 *	return: het gewenste parentobject of false
 * 
 * getPreviousSibling (el[object], condition[string])
 * 	return: het gewenste previous sibling object of false
 *
 * getNextSibling (el[object], condition[string])
 *	return: het gewenste next sibling object of false
 *
 * onload (this[object], functionname[string], arg1, arg2, arg3....)
 *	return : nothing
 *
 * create () : create a new node
 * 
 * hasChildNodes ()
 *	return : true of false
 *
 * up () and down () , aliasses
 *
 * node () : shorthand for document.getElementById
 *	
 * properties ===================================== //
 *
 * version // version number like 1.3
 *
 * hasChildren // true of false
 *
 */

var nodes = {
	version:'1.5',
	__n:0,
	_onload_timeout:5,
	_onload_max_timeout:600,
	
	childNodeBy:function (el, condition, deepChild) {
		return this.childNodesBy (el, condition, deepChild, false);
	},

	childNodesBy:function (el, condition, deepChild, _list) {
		if (this.is_node (el) == false)
			return false;

		if (typeof _list == 'undefined')
			_list = true;

		if (_list === true)
			var retval = [];

		if (condition == false)
			return false;

		if (typeof el == 'undefined' || typeof el == 'function')
			return false;

		if (!el.hasChildNodes ())
			return false;

		for (var el2 in el.childNodes)
			if (el2 != 'length') {
				var el3 = el.childNodes [el2];

				if (this.check_condition (el3, condition)) {
					if (_list === true)
						retval [retval.length] = el3;
					else
						return el3;
				}

				var el4 = this.childNodesBy (el3, condition, deepChild, _list);

				if (el4 !== false) {
					if (_list === true) {
						if (deepChild === true)
							var retval = [].concat (retval, el4);
						else // TODO ?: you'll get duplicates !!
							retval [retval.length] = el3;
					} else {
						if (deepChild === true)
							return el4;
						else
							return el3;
					}
				}
			}
		if (_list === true)
			return retval;

		return false;
	},

	parentNodeBy:function (el, condition) {
		if (typeof condition != 'string')
			condition = false;
	
		while (true) {
			if (el == null)
				return false;
				
			if (typeof el.parentNode == 'undefined') 
				return false;
	
			if (condition == false) 
				return el.parentNode;
	
			if (this.check_condition (el.parentNode, condition)) 
				return el.parentNode;
	
			var el = el.parentNode;
		}
		return false;
	},
	cccounter:0,
	check_condition:function (el, condition) {

		if (typeof condition != 'string')
			return false;
		
		if (!el)
			return false;
	
		var arr = condition.split ('=', 2);
	
		if (arr.length == 1)
			arr [1] = '';
	
		if (typeof arr.length != 'undefined' && arr.length == 2) {
			var negative = arr [0].replace (/\!$/, '');
			if (negative == arr [0]) {
				negative = false;
			} else {
				arr [0] = negative;
				negative = true;
			}
			try {
				if (negative) {
					if (el.getAttribute)
						if (nodes.make_string (el.getAttribute (arr [0])) != arr [1])
							return true;
	
					if (nodes.make_string (el [arr [0]]) != arr [1])
						return true;
				} else {
					if (el.getAttribute)
						if (nodes.make_string (el.getAttribute (arr [0])) == arr [1])
							return true;
	
					if (nodes.make_string (el [arr [0]]) == arr [1])
						return true;
				}
			} catch (e) {
			}
		}
		return false;
	},
	
	make_string:function (val) {
		switch (typeof val) {
		case 'undefined':
		case 'null':
			return '';
		case 'object':
			if (val === null)
				return '';
		}
		return val;
	},
	
	is_node:function (node) {
	/**
	 *	nodeType:
	 *	3 == text-node (space, tab, newline)
	 *	8 == comment
	 */
		if (node != null && typeof node != 'undefined')
			if (typeof node.nodeType != 'undefined') {
				var nodeType = node.nodeType.toString ();
				if (nodeType !== '3' && nodeType !=='8')
					return true;
			}
		return false;
	},
	
	getPreviousSibling:function (p, cond) {
		var s = p.previousSibling;
		if (s === null)
			return false;
	
		if (typeof cond != 'undefined') {
			if (this.check_condition (s, cond))
				return s;
			else
				return this.getPreviousSibling (s, cond);
		}
	
		if (!this.is_node (s))
			return this.getPreviousSibling (s, cond);
		else
			return s;
	},
	
	getNextSibling:function (p, cond) {
		var s = p.nextSibling;
		if (s === null)
			return false;
	
		if (typeof cond != 'undefined') {
			if (this.check_condition (s))
				return s;
			else
				return this.getNextSibling (s, cond);
		}
	
		if (!this.is_node (s))
			return this.getNextSibling (s, cond);
		else
			return s;
	},
	/**
	 * 3 functions for the dom.onload
	 * api : dom.onload(objFunction, strArgument, strArgumant, strArgument.....)
	 * or : dom.onload(obj, ObjFunction, strArgumant, strArgument,...)
	 * dom.onload()
	 * helper functions: _onload, _onReady and hasChildNodes
	 * dom.onload is based on based on domReady.js
	 * http://www.brothercake.com/scripts/domready/domReady.js
	 * *****************************************************
	 * DOM scripting by brothercake -- http://www.brothercake.com/
	 * GNU Lesser General Public License -- http://www.gnu.org/licenses/lgpl.html
	 *******************************************************
	 */
	onload:function () {
		if (typeof document.getElementsByTagName == 'undefined' || arguments.length < 1)
			return false;
	
		var iStart = typeof arguments [0] == 'object'? 2: 1;
	
		this.readyList = this.readyList? this.readyList: [];
		var args = [{type:'load'}];
	
		for (var i=iStart ; i< arguments.length; i++) 
			args[i-iStart] = arguments[i];
	
		if (iStart==2 && typeof arguments [1] == 'function')
			this.readyList [this.readyList.length] = {'func':arguments[1], 'args':args, 'obj':arguments [0]};
		else
			this.readyList [this.readyList.length] = {'func':arguments[0], 'args':args};	
	
		this.hasChildren? this._onReady (): this._onload ();
	},
	
	_onload:function () {
		if ( this.hasChildNodes () )
			return this._onReady ();
	
		if (this.__n >= this._onload_max_timeout)
			return alert ('A timeout error has occurred in DOM-nodes');
	
		if(this.__n++ < this._onload_max_timeout)
			setTimeout('nodes._onload()', this._onload_timeout);
			
	},
	
	_onReady:function () { 
		for (var el in this.readyList)
			if (typeof this.readyList [el].obj == 'undefined')
				this.readyList [el].func.apply (window, this.readyList [el].args );
			else
				this.readyList [el].func.apply (this.readyList [el].obj, this.readyList [el].args );
		
		this.readyList = [];
	},
	
	hasChildNodes:function () {
		if (typeof document.getElementsByTagName != 'undefined' && (document.getElementsByTagName('body')[0] != null || document.body != null)) 
			this.hasChildren = true;
		
		return this.hasChildren;
	},
	
	/**
	 * create a DOM element
	 * @param object args: an object with all of the attributes: like this
	 * {
	 * 	nodeName: INPUT,
	 *  id:test,
	 *  value:foo
	 * }
	 */
	create: function (args) {

		if (typeof args=='undefined' || typeof args !='object')
			return document.createElement ('DIV');
		
		if (typeof args['nodeName']!='string') 
			args['nodeName'] = 'DIV'
		
		var el =  document.createElement (args['nodeName']);
		delete args['nodeName'];
		
		if (args['class']) {
			el.className = args['class'];
			delete args['class'];
		}
		
		for (var elm in args)
			el.setAttribute (elm, args[elm]);
		
		
		return el;
	},
	
	/**
	 * alias for  parentNodeBy()
	 */
	up : function (e, c) {	return this.parentNodeBy (e, c) },
	
	/**
	 * alias for  childNodeBy()
	 */
	down : function (e, c, d) {d = d || true; return this.childNodeBy (e, c, d) },

	/**
	 * alias for  childNodesBy()
	 */
	downAll : function (e, c, d) {d = d || true; return this.childNodesBy (e, c, d) },
	
	/**
	 * shorthand for document.getElementById
	 */
	node: function (id) { return document.getElementById(id) }
}

/** 
 * dom is a alias of node; it is dom-scripting isn't it?
 */
var dom = nodes;
