
//===========================================================/ HTML /=
// A toolkit to facilitate the creation and alteration of HTML
// elements in an non-implementation-specific manner.

HTML = {

//--------------------------------------------------/ Miscellaneous /-

	body: function () {
		return document.getElementsByTagName ('body')[0];
	},

	// create a HTML element of the specified type
	create: function (type, classes) {
		var elt = document.createElement (type);
		if (classes) {
			HTML.setClass (elt, classes);
		}
		return elt;
	},

	// get the element with the specified ID
	getElementById: function (id) {
		return document.getElementById (id);
	},

	// set the CSS class(es) for the specified element
	setClass: function (elt, classes) {
		if (classes) {
			elt.setAttribute ('class', classes);
			elt.setAttribute ('className', classes);
		} else {
			elt.removeAttribute ('class');
			elt.removeAttribute ('className');
		}
	},

	// set the attribute to the specified value on an element
	setAttribute: function (elt, attr, value) {
		elt.setAttribute (attr, value);
		elt[attr] = value;
	},

	// fetch the specified attribute from the given element
	getAttribute: function (elt, attr) {
		return elt[attr];
	},

	// remove the specfied attribute from a given element
	removeAttribute: function (elt, attr) {
		elt.removeAttribute (attr);
	},

	// add a list of DOM-nodes to the base-node. Returns the base-node
	// ex: add (divnode, pnode, brnode)   =>   <div><p /><br /></div>
	add: function (base) {
		for (var i = 1; i < arguments.length; i++) {
			if (arguments[i]) {
				base.appendChild (arguments[i]);
			}
		}
		return base;
	},

	// nests a list of DOM-nodes inside each other and returns the root-node
	// ex: nest (divnode, pnode, brnode)   =>   <div><p><br /></p></div>
	nest: function (base) {
		for (var i = arguments.length - 1; i > 0; i--) {
			arguments[i - 1].appendChild (arguments[i]);
		}
		return base;
	},

	// remove the specified element from the base-element's children
	remove: function (base, elt) {
		base.removeChild (elt);
	},

	// replace the specified element with another element
	replace: function (base, oldelt, newelt) {
		base.replaceChild (newelt, oldelt);
	},

	insert: function (base, newelt, refelt) {
		base.insertBefore (newelt, refelt);
	},
	
	clear: function (elt) {
		var child;
		child = elt.firstChild;
		while (child) {
			elt.removeChild (child);
			child = elt.firstChild;
		};
	},

	// hide the specified element
	hide: function (elt) {
		elt.style.display = 'none';
	},

	// show the specified element
	show: function (elt) {
		elt.style.display = '';
	},

	// disable the specified element
	disable: function (elt) {
		HTML.setAttribute (elt, 'disabled', 'true');
	},

	readonly: function (elt, readonly) {
		readonly ? HTML.setAttribute (elt, 'readOnly', 'true') : HTML.removeAttribute (elt, 'readOnly');
	},

	// enable the specified element
	enable: function (elt) {
		HTML.removeAttribute (elt, 'disabled');
	},

	setSource: function (elt, source) {
		HTML.setAttribute (elt, 'src', source);
	},
	
	getMousePositionFromEvent: function (ev) {
		var x = 0;
		var y = 0;
		if (ev.pageX || ev.pageY) {
			x = ev.pageX;
			y = ev.pageY;
		} else if (ev.clientX || ev.clientY) {
			x = ev.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			y = ev.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		}
		return {'x': x, 'y': y};
	},

	getElementData: function (elt) {
		var x = elt.offsetLeft;
		var y = elt.offsetTop;
		var w = elt.offsetWidth;
		var h = elt.offsetHeight;
	
		// deal with elements inside tables and such
		while (elt.offsetParent) {
			elt = elt.offsetParent;
			x += elt.offsetLeft;
			y += elt.offsetTop;
		}
		return {'x': x, 'y': y, 'width': w, 'height': h};
	},

	setStyles: function (elt, styles) {
		for (var idx in styles) {
			elt.style[idx] = styles[idx];
		}
	},


//-------------------------------------------------------/ TextNode /-

	// create a text-node element with the given content
	createTextNode: function (content) {
		return document.createTextNode (content);
	},

	// set the content of a text-node to the given value
	setTextContent: function (elt, content) {
		elt.nodeValue = content;
	},

	// get the content of a given text-node
	getTextContent: function (elt) {
		return elt.nodeValue;
	},


//----------------------------------------------------------/ Lists /-

	createUnorderedList: function (classes) {
		return HTML.create ('ul', classes);
	},
	
	createListItem: function (classes) {
		return HTML.create ('li', classes);
	},


//---------------------------------------------------------/ Blocks /-

	createDiv: function (classes) {
		return HTML.create ('div', classes);
	},

	createSpan: function (classes) {
		return HTML.create ('span', classes);
	},

	createHeading1: function (classes) {
		return HTML.create ('h1', classes);
	},

	createParagraph: function (classes) {
		return HTML.create ('p', classes);
	},

	createBreak: function (classes) {
		return HTML.create ('br', classes);
	},

	createImage: function (classes, source) {
		var elt = HTML.create ('img', classes);
		if (source) {
			HTML.setAttribute (elt, 'src', source);
		}
		return elt;
	},

	createIcon: function (classes, source, optional, size) {
		if (optional && Framework.getIE6Mode ()) {
			return null;
		} else {
			var elt = HTML.createImage (classes, source);
			HTML.setAttribute (elt, 'width', size || 16);
			HTML.setAttribute (elt, 'height', size || 16);
			return elt;
		}
	},

	createAnchor: function (classes, href) {
		var elt = HTML.create ('a', classes);
		HTML.setAttribute (elt, 'href', href);
		return elt;
	},


//---------------------------------------------------------/ Tables /-

	createTable: function (classes) {
		return HTML.create ('table', classes);
	},

	createTableBody: function (classes) {
		return HTML.create ('tbody', classes);
	},

	createTableHead: function (classes) {
		return HTML.create ('thead', classes);
	},

	createTableRow: function (classes) {
		return HTML.create ('tr', classes);
	},

	createTableHeaderCell: function (classes) {
		return HTML.create ('th', classes);
	},

	createTableCell: function (classes) {
		return HTML.create ('td', classes);
	},


//----------------------------------------------------------/ Forms /-

	createForm: function (classes) {
		return HTML.create ('form', classes);
	},

	createLabel: function (classes) {
		return HTML.create ('label', classes);
	},

	createTextInput: function (classes) {
		var elt = HTML.create ('input', classes);
		HTML.setAttribute (elt, 'type', 'text');
		return elt;
	},

	createFileInput: function (classes) {
		var elt = HTML.create ('input', classes);
		HTML.setAttribute (elt, 'type', 'file');
		return elt;
	},

	createPasswordInput: function (classes) {
		var elt = HTML.create ('input', classes);
		HTML.setAttribute (elt, 'type', 'password');
		return elt;
	},

	createCheckboxInput: function (classes) {
		var elt = HTML.create ('input', classes);
		HTML.setAttribute (elt, 'type', 'checkbox');
		return elt;
	},
	
	createRadioButtonInput: function (classes) {
		var elt = HTML.create ('input', classes);
		HTML.setAttribute (elt, 'type', 'radio');
		return elt;
	},

	createButtonInput: function (classes, label) {
		var elt = HTML.create ('input', classes);
		HTML.setAttribute (elt, 'type', 'button');
		HTML.setAttribute (elt, 'value', label);
		return elt;
	},

	createImageInput: function (classes, href) {
		var elt = HTML.create ('input', classes);
		HTML.setAttribute (elt, 'type', 'image');
		HTML.setAttribute (elt, 'src', href);
		return elt;
	},

	createSubmitInput: function (classes, label) {
		var elt = HTML.create ('input', classes);
		HTML.setAttribute (elt, 'type', 'submit');
		HTML.setAttribute (elt, 'value', label);
		return elt;
	},

	createSelectInput: function (classes) {
		return HTML.create ('select', classes);
	},

	createSelectOption: function () {
		return HTML.create ('option');
	},

	createTextArea: function (classes) {
		return HTML.create ('textarea', classes);
	},

	createFieldSet: function (classes) {
		return HTML.create ('fieldset', classes);
	},

	createLegend: function (classes) {
		return HTML.create ('legend', classes);
	},

	setCursorAtEnd: function (input) {
		if (input.setSelectionRange) {
			var len = input.value.length;
			input.setSelectionRange (len, len);
		} else if (input.createTextRange) {
			var range = input.createTextRange ();
			range.collapse (false);
			range.select ();
		}
	}
};


//--------------------------------------------------/ Eventhandlers /-

(function () {
	// separate createEventHandler instead of inlining it in createAddHandler to
	// ensure that the event-callback does not have its element in its scope as well.
	var createEventHandler = function (object, hname) {
		return function (ev) {
			if (object[hname]) {
				ev = ev || window.event;
				return object[hname] (ev);
			}
		};
	};

	var createAddHandler = function (event) {
		return function (elt, object, hname) {
			elt['on' + event] = createEventHandler (object, hname);
		}
	};

	var createRemoveHandler = function (event) {
		return function (elt) {
			elt['on' + event] = null;
		} 
	};

	var handlers = {
		'Click': 'click',
		'MouseDown': 'mousedown',
		'MouseUp': 'mouseup',
		'MouseMove': 'mousemove',
		'MouseOver': 'mouseover',
		'MouseOut': 'mouseout',
		'Change': 'change',
		'KeyUp': 'keyup',
		'Focus': 'focus',
		'Blur': 'blur'
	};

	for (var idx in handlers) {
		HTML['addOn' + idx +'Handler'] = createAddHandler (handlers[idx]);
		HTML['removeOn' + idx + 'Handler'] = createRemoveHandler (handlers[idx]);
	}
}) ();

