/**
 * TOOL JavaScript light framework, version 1.0.5
 * (c) 2007-2008 Bojan Ristic
 * 
 * TOOL is made for my own purposes and use, and it is free
 */
var TOOL = {
	Version : '1.0.5',
	
	Client: {
	    IE:     !!(window.attachEvent && !window.opera),
	    Opera:  !!window.opera,
		WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
	    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
	},
	
	extend : function(oDestination, oSource)
	{
		for(var property in oSource)
		{
			try{
				oDestination[property] = oSource[property];
			} catch(e) { continue; }
		}
		return oDestination;
	},

	extendElement : function(oDestination, oSource)
	{
		if(!oDestination || !oDestination.tagName || oDestination.nodeType == 3 ||
		oDestination._extended || oDestination == window) return oDestination;
		
		var oSrc = oSource || this.methods;
		
		return TOOL.extend(oDestination, oSrc);
	},
	
	evalScripts : function(vScript)
	{
		/*
		 * this is new implementation end still in development stage
		 * NOTICE:
		 * Only one script element must be contained in the portion 
		 * of code passed to this function (this is about to change)
		 */
		var sScriptElement = '<script[^>]*>([\\S\\s]*?)<\/script>';
		var reScript = new RegExp(sScriptElement, "im");
		var aScripts = reScript.exec(vScript);
		if(aScripts)
		{
			eval(aScripts[1]);
		}
		return this;
	},
	
	getComputedStyle : function(vEle, sProperty, bInt)
	{
		if(!(vEle=$get(vEle))) return null;
		var oStyle, vValue = 'undefined', oDV = document.defaultView;
		
		if(oDV && oDV.getComputedStyle)
		{
			oStyle = oDV.getComputedStyle(vEle, null);
			if (oStyle) vValue = oStyle.getPropertyValue(sProperty);
		}
		else if(vEle.currentStyle)
		{
		    vValue = vEle.currentStyle[TOOL.camelize(sProperty)];
		}
		else return null;
		return bInt ? (parseInt(vValue) || 0) : vValue;
	},
	
	camelize : function(sCssProp)
	{
		var i, c, a = sCssProp.split('-');
		var s = a[0];
		for (i=1; i<a.length; ++i) 
		{
			c = a[i].charAt(0);
			s += a[i].replace(c, c.toUpperCase());
		}
		return s;
	},
	
	methods : {
		serialize : function ()
		{
			if(!this.elements)
			{
				return null;
			}
			var aPairs = [];
			for(var i = 0, len = this.elements.length; i < len; ++i)
			{
				if (!this.elements[i].disabled)
				{
					if(this.elements[i].type && (this.elements[i].type.toLowerCase() == 'radio' || this.elements[i].type.toLowerCase() == 'checkbox'))
					{
						if(this.elements[i].checked)
						{
							aPairs[this.elements[i].name] = this.elements[i].value;
						}
					}
					else
					{
						if(this.elements[i].name) aPairs[this.elements[i].name] = this.elements[i].value;
					}
				}
			}
			return aPairs;
		},
		getElementsByClassName : function (cssClass) {
	 	
		 	var walkTheDOM = function (node, func) {
				func (node);
				node = node.firstChild;
				while (node) {
					walkTheDOM (node, func);
					node = node.nextSibling;
				}
			};
			 
		 	var that = this;
		 	
		 	var a = [];
		 	
		 	var re = new RegExp('(^|\\s)' + cssClass + '(\\s|$)');
		 	
		 	walkTheDOM (that, function(node) {
		 		 if (re.test(node.className)) {
		 		 	a.push(node);
		 		 }
		 	});
		 	
		 	return a;
		},
		addClassName : function(sCssClass)
		{
			return this.className == "" ? this.className = sCssClass : this.className += " " + sCssClass;
		},
		removeClassName : function(sCssClass)
		{
			var aClasses = this.className.split(" ");
			for(var i = 0, len = aClasses.length; i < len; i += 1)
			{
				if(aClasses[i] == sCssClass)
				{
					aClasses.splice(i,1);
				}
			}
			return this.className = aClasses.join(" ");
		},
		setStyle : function(oStyle)
		{
			var oElmStyle = this.style;
			for(var sProp in oStyle) {
				var sCssProp = TOOL.camelize(sProp);
				switch(sCssProp) {
					case 'float':
						oElmStyle['cssFloat'] = oElmStyle['styleFloat'] = oStyle[sProp];
						break;
					case 'opacity':
						oElmStyle.opacity = oStyle[sProp];
						oElmStyle.filter = "alpha(opacity=" + Math.round(oStyle[sProp]*100) + ")"; 
						break;
					case 'className':
						this.className = oStyle[sProp];
						break;
					default:
						if(document.compatMode || sProp != "cursor") { // Nasty Workaround for IE 5.5
							oElmStyle[sCssProp] = oStyle[sProp];
						}		
				}
			}
			return this;
		},
		getOpacity : function()
		{
			var o;
			if(typeof this.style.opacity == 'string') //CSS 3
			{
				o = parseFloat(this.style.opacity);
			}
			else if(this.filters && this.filters.alpha) // IE5.5+
			{
				o = this.filters.alpha.opacity / 100;
			}
			else if(typeof this.style.MozOpacity == 'string') // Gecko
			{
				o = parseFloat(this.style.MozOpacity);
			}
			else if(typeof this.style.KhtmlOpacity == 'string') // Konquerer and Safari
			{
				o = parseFloat(this.style.KhtmlOpacity);
			}
			return isNaN(o) ? 1 : o;
		},
		setOpacity : function(o)
		{
			if(typeof this.style.opacity == 'string') //CSS 3
			{
				this.style.opacity = o + '';
			}
			else if(typeof this.style.filter == 'string') // IE5.5+
			{
				this.style.filter = 'alpha(opacity=' + (100 * o) + ')';
			}
			else if(typeof this.style.MozOpacity == 'string') // Gecko
			{
				this.style.MozOpacity = o + '';
			}
			else if(typeof this.style.KhtmlOpacity == 'string') // Konquerer and Safari
			{
				this.style.KhtmlOpacity = o + '';
			}
			return this;
		},
		appear : function()
		{
			return this.style.display = '';
		},
		hide : function()
		{
			return this.style.display = 'none';
		},
		toggle : function()
		{
			return (this.style.display != 'none') ? this.hide() : this.appear();
		}
	},
	
	dummy : function()
	{
		//
	}
};
/**
 * Returns extended DOM element or null
 * @param {String} eleId The unique identifier for the element.
 * @return {Object} 	 Returns current element.
 */
function $get (e)
{
	if(typeof(e)=='string')
	{
		if(document.getElementById) e = document.getElementById(e);
		else if(document.all) e = document.all[e];
		else e = null;
	}
	return TOOL.extendElement(e);
};
/**
 * Turns collection of objects into array
 * @param {Object} iterable
 * @return {Array}
 */
var toArray = function(iterable)
{
	if (!iterable) return [];
	var results = [];
	for (var i = 0, l = iterable.length; i < l; i++)
	{
		results.push(iterable[i]);
	}
	return results;
};
/**
 * Helper function for classical OOP coding style
 * @return {Function}
 */
var __class__ = function ()
{
	//Blacksmith - when applied to the scope of 'this', 
	//function will first forge the __class__ from the 'this.prototype' objects
	//members and then create new instance of that Class
	var blacksmith = function() 
	{
		//hammer - pull our __construct function out of the prototype object (whitch is our hammer :-)
		var hammer = (this.__construct && typeof this.__construct == "function") ? this.__construct : function(){};
		
		//create new prototype object for 
		//dinamicly created Class (our anvil :)
		var anvil = {};
		
		//place all methods from existing prototype
		//object into new proto object except 
		//the __construct function
		for(var each in this)
		{
			if(this[each] == hammer) continue;
			anvil[each] = this[each];
		}
		/*@cc_on
		if(this.toString !== Object.prototype.toString)
		{
			anvil.toString = this.toString;
		}
		if(this.valueOf !== Object.prototype.valueOf)
		{
			anvil.valueOf = this.valueOf;
		}@*/
		
		/*-----------------------------------------------------------*/
		//we need to add custom method in all instances for determing 
		//if instance is of a particular type
		anvil.instanceOf = function(fnClass)
		{
			//first we have to check if argument passed is of type function
			if (typeof fnClass !== "function") return false;
			
			var proto = fnClass.prototype;
			for (var p in proto)
			{
				if (typeof proto[p] !== "function") continue;
				if (p == "__construct" || p == "parent") continue;
				if (!this[p] || this[p].toString() != proto[p].toString()) return false;
			}
			return true;
		};
		
		// [25/04/08] attempt to implement protected and private functions
		anvil.scope = function()
		{
			if(arguments.length > 1) throw Error('Wrong number of arguments');
			if(!arguments.length || arguments[0] == 'public') return;
			
			// we need to define protected and private scope
			// since we are forging our constructor function
			// we need to add this function to both of scoups
			// as a starting point 
			var aProtectedScope = aPrivateScope = [hammer];
			
			for (var each in this)
			{
				if(each != 'parent')
				{
					aProtectedScope.push(this[each]);
					if(!this.parent[each])
					{
						aPrivateScope.push(this[each]);
					}
				}
			}
			
			if(arguments[0] == 'protected' || arguments[0] == 'private')
			{
				if (aProtectedScope.indexOf(this.scope.caller.caller) == -1)
				{
					throw 'Illegal operation call';
				}
				
				if (arguments[0] == 'private')
				{
					if (aPrivateScope.indexOf(this.scope.caller) == -1)
					{
						throw 'Illegal operation call';
					}
				}
			}
		};
		/*-----------------------------------------------------------*/
		//add new prototype object to the 
		//constructor function - dynamically create 
		//new first class object: Class
		hammer.prototype = anvil;
		
		//create instance of our dinamicly forged Class 
		//punch punch punch 
		hammer.apply(anvil, arguments);
		
		//take the shape of the tool (horseshoe :-)
		var horseshoe = anvil;
		
		//set instances constructor property 
		//to it's actual constructor
		horseshoe.constructor = hammer;
		
		//return instance
		return horseshoe;
	};
	return blacksmith;
};
Function.prototype.inherits = function(f, o)
{
	this.prototype = (typeof f == "function") ? new f() : f;
	this.prototype.parent = (typeof f == "function") ? f.prototype : f;
	this.prototype.constructor = (o.__construct && typeof o.__construct == "function") ? o.__construct : function(){};
	
	for(var each in o)
	{
		if(typeof o[each] == this.prototype.constructor) continue;
		this.prototype[each] = o[each];
	}
	/*@cc_on
	if(o.toString !== Object.prototype.toString)
	{
		this.prototype.toString = o.toString;
	}
	if(o.valueOf !== Object.prototype.valueOf)
	{
		this.prototype.valueOf = o.valueOf;
	}@*/
	return this;
};
Function.prototype.bind = function() {
  var __method = this, args = toArray(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat(toArray(arguments)));
  };
};
Function.prototype.bindToEvent = function(object) {
  var __method = this, args = toArray(arguments), obj = args.shift();
  return function(event) {
    return __method.apply(obj, [event || window.event].concat(args));
  };
};
Array.prototype.indexOf = function(vObj)
{
	var iResult = -1;
	for(var i=0, len = this.length; i<len; ++i)
	{
		if(this[i] == vObj)
		{
			iResult = i;
			break;
		}
	}
	return iResult;
};
Array.prototype.map = function(f, o)
{
	var aResults = [];
	for(var i=0, len=this.length; i<len; i+=1)
	{
		aResults.push(f.call(o, this[i], i, this));
	}
	return aResults;
};
Array.prototype.unique = function() {
	var i, index = 0;
		
	while (index < this.length) {
		for (i = index + 1; i < this.length; i += 1) {
			if (this[index] === this[i]) {
				this.splice(i, 1);
			}
		}
		index += 1;
	}
	return this;
};
// Simulates PHP's date function
Date.prototype.format = function(format) {
	var returnStr = '';
	var replace = Date.replaceChars;
	for (var i = 0; i < format.length; i++) {
		var curChar = format.charAt(i);
		if (replace[curChar]) {
			returnStr += replace[curChar].call(this);
		} else {
			returnStr += curChar;
		}
	}
	return returnStr;
};
Date.replaceChars = {
	shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
	longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
	shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
	longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
	
	// Day
	d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
	D: function() { return Date.replaceChars.shortDays[this.getDay()]; },
	j: function() { return this.getDate(); },
	l: function() { return Date.replaceChars.longDays[this.getDay()]; },
	N: function() { return this.getDay() + 1; },
	S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); },
	w: function() { return this.getDay(); },
	z: function() { return "Not Yet Supported"; },
	// Week
	W: function() { return "Not Yet Supported"; },
	// Month
	F: function() { return Date.replaceChars.longMonths[this.getMonth()]; },
	m: function() { return (this.getMonth() < 9 ? '0' : '') + (this.getMonth() + 1); },
	M: function() { return Date.replaceChars.shortMonths[this.getMonth()]; },
	n: function() { return this.getMonth() + 1; },
	t: function() { return "Not Yet Supported"; },
	// Year
	L: function() { return (((this.getFullYear()%4==0)&&(this.getFullYear()%100 != 0)) || (this.getFullYear()%400==0)) ? '1' : '0'; },
	o: function() { return "Not Supported"; },
	Y: function() { return this.getFullYear(); },
	y: function() { return ('' + this.getFullYear()).substr(2); },
	// Time
	a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
	A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
	B: function() { return "Not Yet Supported"; },
	g: function() { return this.getHours() % 12 || 12; },
	G: function() { return this.getHours(); },
	h: function() { return ((this.getHours() % 12 || 12) < 10 ? '0' : '') + (this.getHours() % 12 || 12); },
	H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
	i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
	s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
	// Timezone
	e: function() { return "Not Yet Supported"; },
	I: function() { return "Not Supported"; },
	O: function() { return (-this.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(this.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() / 60)) + '00'; },
	P: function() { return (-this.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(this.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() / 60)) + ':' + (Math.abs(this.getTimezoneOffset() % 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() % 60)); },
	T: function() { var m = this.getMonth(); this.setMonth(0); var result = this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/, '$1'); this.setMonth(m); return result;},
	Z: function() { return -this.getTimezoneOffset() * 60; },
	// Full Date/Time
	c: function() { return this.format("Y-m-d") + "T" + this.format("H:i:sP"); },
	r: function() { return this.toString(); },
	U: function() { return this.getTime() / 1000; }
};
String.prototype.htmlentities = function () {
	var i, c, l, n = "", str = this;
	for (i = 0, l = str.length; i < l; i += 1) {
		c = str.charCodeAt(i);
		if ((c > 47 && c < 58) || (c > 62 && c < 127)) {
			n += str.charAt(i);
		} else {
			n += "&#" + c + ";";
		}
	}
	return n;
};
String.prototype.htmlentities_decode = function () {
	var re = /&#\d+;/g,
		m = this.match(re) || [],
		i, 
		l,
		n,
		s = this;
	
	m.unique();
	
	for (i = 0, l = m.length; i < l; i += 1) {
		n = parseInt(m[i].toString().replace(/&#/, "").replace(/;/, ""));
		re = new RegExp(m[i], "g");
		s = s.replace(re, String.fromCharCode(n));
	}
	return s;
};
String.prototype.stipTags = function () {
	return this.replace(/<\/?[^>]+>/gi, "");
};
/**
 * Net - Ajax base class
 * @author Bojan Ristic
 */
var Net = {};
Net.Base = function(){};
Net.Base.prototype = {
	connect : function()
	{
		var Request;
		
		if (window.XMLHttpRequest)
		{
			Request = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			Request = new ActiveXObject("Microsoft.XMLHTTP");
		}
		return Request ? Request : null;
	},
	setOptions: function()
	{
		this.method = this.options.method ? this.options.method.toUpperCase() : "GET";
		this.asynchronous = typeof(this.options.asynchronous) !== 'undefined' ? this.options.asynchronous : true;
		this.contentType = this.options.contentType ? this.options.contentType : "application/x-www-form-urlencoded";
		this.encoding = this.options.encoding ? this.options.encoding : "UTF-8";		
		this.parameters = this.options.params || null;
	},
	toQueryString: function(aPairs)
	{
		var sQuery = new String();
		for(var key in aPairs)
		{
			if (aPairs.hasOwnProperty(key))
			{
				if(sQuery == '')
				{
					sQuery = key + '=' + aPairs[key];	
				}
				else
				{
					sQuery+= '&' + key + '=' + aPairs[key];
				}
			}
		}
		return sQuery;
	}
};
/**
 * NetLoader Class
 * @class NetLoader
 * @param {String, Object} sUrl, oOptions
 * @return {Object}
 * @type Object
 * @author Bojan Ristic
 * @version 1.0.3
 * @see Net
 */
Net.Loader = __class__();
Net.Loader.inherits(Net.Base, {
	_complete : false,
	
	__construct: function(sUrl, oOptions)
	{
		//
		this.Events = [
			'Uninitialized', 
			'Loading', 
			'Loaded', 
			'Interactive', 
			'Complete'
		];
		//
		this.options = oOptions || {};
		this.setOptions();
		this.Request = this.connect();		
		this.loadXMLDoc(sUrl);
	},
	setRequestHeaders: function(oXMLHttp)
	{
		var oHeaders = {
      		'X-Requested-With' : 'XMLHttpRequest',
      		'Accept' : 'text/javascript, text/html, application/xml, text/xml, */*'
    	};
		if(this.method == 'POST')
		{
			oHeaders['Content-type'] = this.contentType + (this.encoding ? '; charset=' + this.encoding : '');
			oHeaders['Content-length'] = this.parameters.length;
			oHeaders['Connection'] = 'close'; 
		}
		for(var name in oHeaders)
		{
			oXMLHttp.setRequestHeader(name, oHeaders[name]);
		}
	}, 
	loadXMLDoc: function(sUrl)
	{
		//		
		if (this.Request)
		{
			try {
				if (this.options.onCreate) this.options.onCreate(this.Request);
				
				if(this.method == 'GET')
				{
					sUrl = this.parameters ? sUrl += '?' + this.toQueryString(this.parameters) : sUrl;
				}
				this.Request.open(this.method, sUrl, this.asynchronous);
				this.Request.onreadystatechange = this.onStateChange.bind(this);
				this.setRequestHeaders(this.Request);
				var body = this.method == 'POST' ? this.toQueryString(this.parameters) : null;				
				this.Request.send(body);
			}
			catch (e)
			{
				this.handleException(e);
			}
		}
	},
	onStateChange : function()
	{
		//		
		var iState = this.Request.readyState;
		
		if(iState > -1 && !((iState == 4) && this._complete))
		{
			this.respondToState(this.Request.readyState);
		} 
	},
	respondToState: function(iState)
	{
		var sState = this.Events[iState];
		if(sState == 'Complete')
		{
			try{
				this._complete = true;
				(this.options['on' + this.Request.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')]
				|| TOOL.dummy)(this.Request);
			}
			catch(e)
			{
				this.handleException(e);
			}
		}
		
		try{
			(this.options['on' + this.Events[iState]] || TOOL.dummy)(this.Request);
		}
		catch(e)
		{
			this.handleException(e);
		}
	},
	success : function()
	{
		return !this.Request.status || (this.Request.status >= 200 && this.Request.status < 300);
	},
	handleException: function(e)
	{
		(this.options.onException || TOOL.dummy)(this, e);
	}
	
});
/**
 * NetUpdater Class
 * @class NetUpdater
 * @param {String, String, Object} sDivId, sUrl, oOptions
 * @return {Void}
 * @author Bojan Ristic
 * @since 1.0.3
 * @see NetLoader
 */
Net.Updater = __class__();
Net.Updater.inherits(Net.Loader, {
	__construct : function(sDivId, sUrl, oOptions)
	{
		this._complete = false;
		this.options = oOptions || {};
		this.setOptions();
		this.container = $get(sDivId);
		
		var onComplete = this.options.onComplete || TOOL.dummy;
		
		this.options.onComplete = (function(transport, params){
			this.updateContent();
			onComplete(transport, params);
		}).bind(this);
		
		this.loadXMLDoc(sUrl);
	},
	
	updateContent : function()
	{
		var result = this.Request.responseText;
		
		if(this.container)
		{
			this.container.innerHTML = result;
		}
		
		if(this.success())
		{
			if(this.onComplete)
			{
				setTimeout(this.onComplete.bind(this), 10);
			}
		}
	}
});
/**
 * NetInterval Class
 * @class NetInterval
 * @param {String, String, Object} sDivId, sUrl, oOptions
 * @return {Void}
 * @author Bojan Ristic
 * @since 1.0.3
 * @see NetUpdater
 */
Net.Interval = __class__();
Net.Interval.inherits(Net.Base, {
	__construct : function(sDivId, sUrl, oOptions)
	{
		this.options = oOptions || {};
		this.setOptions();
		this.onComplete = this.options.onComplete;
		
		this.frequency = this.options.frequency || 2;
		this.decay = this.options.decay || 1;
		
		this.updater = {};
		this.container = $get(sDivId);
		this.url = sUrl;
		
		this.start();
	},
	
	start : function()
	{
		this.options.onComplete = this.updateComplete.bind(this);
		this.onInterval();
	},
	
	stop : function()
	{
		this.updater.options.onComplete = undefined;
		clearTimeout(this.timer);
		(this.onComplete || TOOL.dummy).apply(this.arguments); 
	},
	
	updateComplete : function(transport)
	{
		if(this.options.decay)
		{
			this.decay = (transport.responseText == this.lastResult ? 
			this.decay * this.options.decay : 1);
			this.lastResult = transport.responseText;
		} 
		this.timer = setTimeout(this.onInterval.bind(this), this.decay * this.frequency * 1000);
	},
	
	onInterval : function()
	{
		this.updater = new Net.Updater(this.container, this.url, this.options);
	}
});
/**
 * NetUploader Class
 * @class NetUploader
 * @param {String, String, Object} sFormId, sUrl, oOptions
 * @return {Void}
 * @author Bojan Ristic
 */
Net.Uploader = __class__();
Net.Uploader.prototype = {
	
	__construct : function(sFormId, sUrl, oOptions)
	{	
		this.vForm = $get(sFormId);
		this.oOptions = oOptions;
		this.sName = 'frame_' + Math.floor(Math.random() * 99999);
		
		//create object globaly available to manage response
		ResponseHandler = {'manage' : this.frameLoaded};
		
		this.submit(sUrl);
	},
	
	frame : function()
	{
		var vDiv = document.createElement('div');
		vDiv.innerHTML = '<iframe style="display:none" src="about:blank" id="'+this.sName+'" name="'+this.sName+'" onload="ResponseHandler.manage(this)"></iframe>';
		
		document.body.appendChild(vDiv);

		if(this.oOptions && typeof(this.oOptions.onSuccess) == "function")
		{
			$get(this.sName).onSuccess = this.oOptions.onSuccess;
		}

		return true;
	},
	
	form : function(sUrl)
	{
		//set Form attributes
		if (TOOL.Client.IE) { 	// workorund for IE setAttribute enctype
			var enctype = this.vForm.getAttributeNode('enctype');
			enctype.value = 'multipart/form-data';
			var method = this.vForm.getAttributeNode('method');
			method.value = 'post';
		} else {
			this.vForm.setAttribute('enctype', 'multipart/form-data');
			this.vForm.setAttribute('method', 'post');
		}
		this.vForm.action = sUrl;
		this.vForm.target = this.sName;
		
		//add max_file_size input field
		var vSize = document.createElement('input');
		vSize.type = "hidden";
		vSize.name = "max_file_size";
		vSize.value = this.oOptions.maxSize;
		this.vForm.appendChild(vSize);
		
		//submit form
		this.vForm.submit();
	},
	
	submit : function(sUrl)
	{
		if(this.frame()) this.form(sUrl);
		if(this.oOptions && typeof(this.oOptions.onCreate) == "function")
		{
			return this.oOptions.onCreate;
		}
		else
		{
			return true;
		}
	},
	
	frameLoaded : function(oFrame)
	{
		var vDoc;
		
		if (oFrame.contentDocument) {
            vDoc = oFrame.contentDocument;
        } else if (oFrame.contentWindow) {
            vDoc = oFrame.contentWindow.document;
        } else {
            vDoc = window.frames[oFrame.name].document;
        }

        if (vDoc.location.href == "about:blank") {
            return;
        }
        
        if (typeof(oFrame.onSuccess) == 'function') {
        	var oTransport = {
        		responseText : vDoc.body.innerHTML
        	};
            oFrame.onSuccess(oTransport);
        }
        
        //destroy object wich is not needed any more
        ResponseHandler = null;
	}
	
};
/*-----------------------------------------------------------------*/
var EventUtil = {
	addEventHandler : function(oTarget, sEventType, fnHandler)
	{
		if(oTarget.addEventListener) //DOM model
		{
			oTarget.addEventListener(sEventType, fnHandler, false);
		}
		else if(oTarget.attachEvent) //IE model
		{
			oTarget.attachEvent("on" + sEventType, fnHandler);
		}
		else	//all other browsers
		{
			oTarget["on" + sEventType] = fnHandler;
		}
	},
	
	removeEventHandler : function(oTarget, sEventType, fnHandler)
	{
		if(oTarget.removeEventListener) //DOM model
		{
			oTarget.removeEventListener(sEventType, fnHandler, false);
		}
		else if(oTarget.attachEvent) //IE model
		{
			oTarget.detachEvent("on" + sEventType, fnHandler);
		}
		else	//all other browsers
		{
			oTarget["on" + sEventType] = null;
		}
	},
	
	formatEvent : function(e)
	{
	    var oEvent = e || window.event;
	    
		if(TOOL.Client.IE)
		{
			oEvent.charCode = oEvent.which = (oEvent.type === "keypress") ? oEvent.keyCode : 0;
			oEvent.eventPhase = 2;
			oEvent.isChar = (oEvent.charCode > 0);
			oEvent.pageX = oEvent.clientX + document.body.scrollLeft;
			oEvent.pageY = oEvent.clientY + document.body.scrollTop;
			oEvent.preventDefault = function()
			{
				this.returnValue = false;
			};
			
			if(oEvent.type == "mousout")
			{
				oEvent.relatedTarget = oEvent.toElement;
			}
			else if(oEvent.type == "mouseover")
			{
				oEvent.relatedTarget = oEvent.fromElement;
			}
			
			oEvent.stopPropagation = function()
			{
				this.cancelBubble = true;
			};
			
			oEvent.target = oEvent.srcElement;
			oEvent.time = (new Date).getTime();
		}
		return oEvent;
	},
	
	// deprecated - arguments is no longer property of the Function - since JS 1.5
	getEvent : function()
	{
		if(window.event)
		{
			return this.formatEvent(window.event);
		}
		else
		{
			return this.getEvent.caller.arguments[0];
		}
	},
	
	domLoadListeners : [],
	
	addDomLoadListener : function(fnListener)
	{
		this.domLoadListeners.push(fnListener);
	},
	
	domLoaded : function() {
		if (arguments.callee.done) return;
		arguments.callee.done = true;
		for (var i = 0, len = EventUtil.domLoadListeners.length; i < len; ++i)
		{
			var fnListener = EventUtil.domLoadListeners[i];
			fnListener.call();
		}
	},
	
	registerOnLoad : function() {
		if (document.addEventListener) {
			document.addEventListener("DOMContentLoaded", EventUtil.domLoaded, null);
		}
		/*@cc_on @*/
		/*@if (@_win32)
			var proto = "src='javascript:void(0)'";
			if (location.protocol == "https:") proto = "src=//0";
			document.write("<scr"+"ipt id=__ie_on_load defer " + proto + "><\/scr"+"ipt>");
			var script = document.getElementById("__ie_on_load");
			script.onreadystatechange = function() {
			    if (this.readyState == "complete") {
			        EventUtil.domLoaded();
			    }
			};
		/*@end @*/
	    window.onload = EventUtil.domLoaded;
	},

	eventReg : function (o) {
        var handler = {};
        o.on = function (type, method, parameters) {
            var e = {
                method : method,
                parameters : parameters
            };
            if(handler[type]) {
                handler[type].push(e);
            } else {
                handler[type] = [e];
            }
            return o;
        };
        
        o.fire = function(event) {
            var e, f, i, h = handler[event.type];
            if(h)  {
                for (i=0; e=h[i]; i+=1) {
                    f = e.method;
                    if(typeof(f) === 'String') {
                        f = o[f];
                    }
                    f.apply(this, e.parameters || [event]);
                }
            }
            return o;
        };
        
        o.off = function (type, method) {
            if(handler[type]) {
                handler[type].splice(handler[type].indexOf(method), 1);
            }
        };
        
        return o;
    }
};
/**
 * Timer
 * 
 * @param {Integer} delay
 * @param {Integer} repeatCount
 * @return {Object}
 */
var Timer = function(/*Integer*/delay, /*Integer*/repeatCount) {
    
    var timer = EventUtil.eventReg({});
    
    var oInterval;
    
    var dispatch = function(){
        timer.fire({type:Timer.TIMER});
        timer.currentCount += 1;
        if(timer.repeatCount && timer.repeatCount === timer.currentCount)
        {
        	timer.reset();
            timer.fire({type:Timer.COMPLETE});
        }
    };
    
    var start = function ( ) {
    	timer.running = true;
        oInterval = setInterval(dispatch, delay);
    };
    
    var stop = function ( ) {
    	timer.running = false;
        clearInterval(oInterval);
    };
    
    var reset = function ( ) {
        stop();
        timer.currentCount = 0;
    };
    
    // properties
    timer.delay = delay;
    
    timer.repeatCount = repeatCount || 0;
    
    timer.currentCount = 0;
    
    timer.running = false;
    
    // methods
    timer.start = start;
    
    timer.stop = stop;
    
    timer.reset = reset;
    
    return timer;
};
Timer.TIMER = 'timer';
Timer.COMPLETE = 'complete';