var isIE = false;
if (document.attachEvent && !window.opera)
  isIE = true;

/* Cross-browser event handler */
if (typeof document.addEventListener == "function")
  var registerEventHandler = function(node, event, handler) {
    node.addEventListener(event, handler, false);
  };
else
  var registerEventHandler = function(node, event, handler) {
    node.attachEvent("on" + event, handler);
  };

function normaliseEvent(event) {
  if (!event.stopPropagation) {
    event.stopPropagation = function() {this.cancelBubble = true;};
    event.preventDefault = function() {this.returnValue = false;};
  }
  if (!event.stop) {
    event.stop = function() {
      this.stopPropagation();
      this.preventDefault();
    };
  }

  if (event.srcElement && !event.target)
    event.target = event.srcElement;
  if ((event.toElement || event.fromElement) && !event.relatedTarget)
    event.relatedTarget = event.toElement || event.fromElement;
  if (event.clientX != undefined && event.pageX == undefined) {
    event.pageX = event.clientX + document.body.scrollLeft;
    event.pageY = event.clientY + document.body.scrollTop;
  }
  if (event.type == "keypress") {
    if (event.charCode === 0 || event.charCode == undefined)
      event.character = String.fromCharCode(event.keyCode);
    else
      event.character = String.fromCharCode(event.charCode);
  }

  return event;
};

function addHandler(node, type, handler) {
  	function wrapHandler(event) {
    	handler(normaliseEvent(event || window.event));
  	};
  	registerEventHandler(node, type, wrapHandler);
  	return {node: node, type: type, handler: wrapHandler};
};

function removeHandler(node, event, handler) {
  	if (typeof node.removeEventListener == "function")
    	node.removeEventListener(event, handler, false);
  	else
    	node.detachEvent("on" + event, handler);
}

/* Augmenting array.prototype with 'functional-style' and miscellaneous methods */
if (!Array.prototype.map) { 
  Array.prototype.map = function(func, scope) { 
    scope = scope || this; 
    var list = []; 
    for (var i = 0, l = this.length; i < l; i++) 
      list.push(func.call(scope, this[i], i, this)); 
      return list; 
    } 
}
if (!Array.prototype.filter) {
  Array.prototype.filter = function(func, scope) {
    scope = scope || this;
    var list = [];
    for (var i=0, l=this.length; i<l; i++) {
      if (func.call(scope, this[i], i, this)==true)
        list.push(this[i]); 
    }
    return list; 
  } 
}
if (!Array.prototype.forEach) { 
  Array.prototype.forEach = function(func, scope) { 
    scope = scope || this; 
    for (var i=0, l=this.length; i<l; i++) 
      func.call(scope, this[i], i, this); 
    } 
}
if (!Array.prototype.fold) {
  Array.prototype.fold = function (func, initialValue, scope) {
    scope = scope || this;
    var folded = initialValue;
    for (var i=0, l=this.length; i<l; i++) {
      folded = func.call(scope, folded, this[i], i);
    }
    return folded;
  }
}

swtUtils = {};

swtDOMBuilder = { 
	create : function (tag, attrs, children) { 
		attrs = attrs || {}; 
		children = children || []; 
		var el = document.createElement(tag);                            
		for (var attr in attrs) {
			if (attr == 'className')
				el.setAttribute('class', attrs[attr].toString());
			else if (isIE && attr == 'style') {
				var parts = attrs[attr].split (';');
				parts.forEach (function (p) {
					var kv = p.split (':');
					if (kv.length > 1) {
						el.style[dashesToCamel($.trim(kv[0]))] = $.trim(kv[1]);
					}
				});
			} else
				el.setAttribute(attr, attrs[attr].toString());
		}

		for (var i=0; i < children.length; i++) {
			if (typeof children[i] == 'string')
				children[i] = document.createTextNode(children[i]);
			el.appendChild(children[i]);
		}

		return el;
    },
	tagFunc : function (tag) { 
		return function () { 
			var attrs, children; 
			if (arguments.length > 0) {
				if (arguments[0].nodeName || typeof arguments[0] == "string") 
					children = arguments;  
				else { 
					attrs = arguments[0]; 
					children = Array.prototype.slice.call(arguments, 1); 
				}; 
			} 
			return swtDOMBuilder.create(tag, attrs, children); 
		}; 
	}
};

function dashesToCamel (str) {	
	var pieces = str.split ('-');
	var resStr = pieces[0];
	for (var i = 1, l = pieces.length; i < l; i++) {
		resStr += pieces[i].charAt (0).toUpperCase () + pieces[i].substring (1, pieces[i].length);
	}
	return resStr;
}

/* Fast DOM elements creation */
(function() 
{
var els = ("p|div|span|strong|em|img|table|tr|td|th|thead|" + "tbody|tfoot|pre|code|h1|h2|h3|h4|h5|h6|ul|ol|li|form|input|" + "textarea|legend|fieldset|select|option|blockquote|cite|br|hr|" + "dd|dl|dt|address|a|button|abbr|acronym|script|link|style|bdo|" + "ins|del|object|param|col|colgroup|optgroup|caption|label|dfn|" + "kbd|samp|var").split("|");
var el, i=0;

while (el = els[i++]) 
	window['$' + el] = swtDOMBuilder.tagFunc(el);
})();

E = function (id) {
	return document.getElementById(id);
};

swtUtils.stringToNum = function (str, returnInfo, noNegative, noFloat) {
	if (typeof str == 'number')
		return str;
	var l = str.length;
	
	if (l == 0)
		if (returnInfo == 0)
			return 0;
		else
			return {completion: 1, value: 0};
	
	var num = 0;
	var power = 1;
	var digitEncountered = 0;
	var pointEncountered = -1;
	var symbolsUsed = 0;
	for (var i = l-1; i >= 0; i--) {
		var code = str.charCodeAt (i);
		if (!noFloat && digitEncountered && pointEncountered == -1 && str.charAt(i) == '.') {
			symbolsUsed++;
			pointEncountered = power;		
		}
		if (!noNegative && digitEncountered && code == 45) {
			num = -num;
			symbolsUsed++;
			break;
		}
		if (code >= 48 && code <= 57) {
			num += (code - 48) * power;
			power *= 10;
			symbolsUsed++;
			digitEncountered = 1;
		}	
	}
	
	if (pointEncountered > 0)
		num /= pointEncountered;
	
	if (!returnInfo)
		return num;
	else
		return {value: num, completion: symbolsUsed/l};
};

function hide (elem) {
	elem.style.display = 'none';
};

function show (elem) {
	elem.style.display = 'block';
};