/***********************************************************
* SYSTEM CLASS
*	Must be included everytime
*	Designed & developed by Dima Svirid, 2007
*	Class: system.js
************************************************************/
var $WI = {
	Class: function(cls) {
		var F = function(){};
				F.prototype = cls;
				if($WI.Class.Browser) F = $WI.extend(F, $WI.Class.Browser);
				if($WI.Class.DOM) F = $WI.extend(F, $WI.Class.DOM);
		return F;
	},
	CFG: {},//configuration container
	REG: {Buttons: {}},//system registry
	Method: {},
	Object: {},
	Variables: {
		imagesURL: (window.imagesURL)?imagesURL:'src/images/'		//URL to images reqiered by the library
	},
	init: function() {
		this._GLOBAL();
		this.DOM = new $WI.Class.DOM;
		this.Event = this.DOM;
		this.KeyEvent = {};
		//Initialize onDOMLoad event
		this.Event._initLoadDOM();
		//Initialize keypress handler
		this.Event.AddDOMEvent({obj: D, type: 'keydown', onevent: this.Event._keyEvent});
		this.Event.AddDOMEvent({obj: D, type: 'keyup', onevent: this.Event._keyEvent});
		//preload requested before libraries
		if(window.GLOBAL_SYSTEM_PRELOAD_LIBS&&GLOBAL_SYSTEM_PRELOAD_LIBS.length>0)
			for(var i=0;i<GLOBAL_SYSTEM_PRELOAD_LIBS.length;i++)
				this.DOM.LoadJS({src: GLOBAL_SYSTEM_PRELOAD_LIBS[i]});
		//Handle all the errors with the tracer
		//window.onerror = this.trace;
	},
	trace: function(message) {
		if(!window._LOGGER) {
			_LOGGER = new $WI.Class.Logger;
			_LOGGER._initLogger();
		}
		_LOGGER.Write(message);
	},
	extend: function(subClass, superClass) {
		if(subClass==superClass) return subClass;
		for (var i in superClass.prototype) subClass.prototype[i] = superClass.prototype[i];
		subClass.prototype.superClass = superClass.prototype;
	  return subClass;
	},
	_extend: function(subClass, overrides) {
		for(var i in overrides)
			subClass.prototype[i] = overrides[i];
	},
	_append: function(main, overrides, overwrite) {
		for(var i in overrides)
			if($_VAR(overwrite, true)||!main[i])
				main[i] = overrides[i];
	},
	_GLOBAL: function() {
		D = document;
		DH = document.getElementsByTagName("head")[0];
		if(window.ActiveXObject&&navigator.userAgent.toLowerCase().indexOf('msie 7')==-1)	//FIX IE6 BUG
			try	{document.execCommand("BackgroundImageCache", false, true);} catch(e){}
	}
};


var $E = function(V) {
  var results = [], element;
  for (var i = 0; i < arguments.length; i++) {
    element = arguments[i];
    if (typeof element == 'string')
      element = D.getElementById(element);
    results.push(element);
  }
  if(results.length>1) return results;
	else return results[0];
};
var $V = function(element, value) {
 		element = $E(element);
		if(!element) return '';
		//Read form element value
		if((/input|textarea|button|select|radio|checkbox/i).test(element.tagName)) {
			var method = element.tagName.toLowerCase();
			if(value) {
				$WI.Method.Form[method](element, value);
			} else {
				var parameter = $WI.Method.Form[method](element);
	    	if (parameter) return parameter[1];
			}
		} else { //Read DOM element value
			if(value) element.innerHTML = value;
			else return element.innerHTML;
		}
};
var now = function(){
	return new Date();
};
var $_VAR = function(variable, def) {
	return (variable!=undefined)?variable:def;
};

/*********************************************************
*		PROTOTYPING RESERVED JAVASCRIPT CLASSES
*********************************************************/
$WI._extend(Array, {
	inArray: function(value) {
		for (var i=0; i < this.length; i++)
			if (this[i] === value)
				return true;
		return false;
	},
	isArray: function() {
		return true;
	},
	Search: function(value, key) {
		for (var i=0; i < this.length; i++) {
			if (!key && this[i] == value)
				return i;
			else if (key && this[i][key] && this[i][key] == value)
				return i;
		}
		return -1;
	},
	Remove: function(value) {
		var num = this.Search(value);
		if(num!=-1) this.splice(num, 1);
	}
});
$WI._extend(Function, {
	Apply: function() {
		var obj = this;var args = arguments;
		var F = function() {
			return obj.apply(args[0], (args[1]) ? args[1] : []);//added [1] not to pass main object
  	};
		F.__Function = this;
		return F;
	}
});


/*********************************************************
*		BROWSER CLASS
*********************************************************/
$WI.Class.Browser = new $WI.Class({
	_isIE: function() {
		return (window.ActiveXObject);
	},
	_isIE6: function() {
		return (window.ActiveXObject&&!this._isIE7());
	},
	_isIE7: function() {
		return (navigator.userAgent.toLowerCase().indexOf('msie 7')>-1);
	},
	_isIE8: function() {
		return (navigator.userAgent.toLowerCase().indexOf('msie 8')>-1);
	},
	_isOpera: function() {
		return (navigator.userAgent.toLowerCase().indexOf('opera')>-1);
	},
	_isChrome: function() {
		return (navigator.userAgent.toLowerCase().indexOf('chrome')>-1);
	},
	_isSafari: function() {
		return (navigator.userAgent.toLowerCase().indexOf('webkit')>-1&&!this._isChrome());
	},
	_isSafari2: function() {
		return false;
		return (this._isSafari()&&!this._isSafari3());
	},
	_isSafari3: function() {
		return (this._isSafari()&&(navigator.userAgent.toLowerCase().indexOf('version/3.')>-1||
														   navigator.userAgent.toLowerCase().indexOf('version/4.')>-1));
	},
	_isFF: function(){
		return (navigator.userAgent.indexOf("Firefox")!=-1);
	},
	_isMac: function() {
		return (navigator.userAgent.toLowerCase().indexOf("macintosh")!= -1);
	},
	_isWindows: function() {
		if(navigator.userAgent.toLowerCase().indexOf("windows")!=-1||navigator.userAgent.toLowerCase().indexOf("win32")!=-1) return true;
		else return false;
	},
	_isFlash: function(version) {
		return (!$WI.Class.Flash || (new $WI.Class.Flash()._getVersion().split(',').shift() >= parseInt(version))) ? true : false;
	},
	PopUp: function(url, winname, options) {
		/*	options: status|toolbar|location|menubar|directories|resizable|scrollbars|height|width|top|left  */
		if(!winname) var winname = "POPUP_" + $WI.System.Random();
		var mywin = window.open(url, winname, options);
		if(mywin)	mywin.focus();
		else	alert("Please turn off PopUp Blocker!");
	}
});
/*********************************************************
*		VARIABLES
*********************************************************/
$WI.Variables.VARS = {
	Attr: function(tag) {
		var tags = /^(?:id|class|cellSpacing|cellPadding|onmouseover|onmouseout|src|type|frameBorder|onload|name|href|rel|media|alt|value|align|vAlign|colSpan|rowSpan)$/i;
		return tags.test(tag);
	},
	Javascript: function(tag) {
		var tags = /^(?:onselectstart|basefont|of)$/i;
		return tags.test(tag);
	},
	EmptyConfig: function(tag) {
		var tags = /^(?:objType|objClass|objWin|objDoc|html)$/i;
		return tags.test(tag);
	},
	DOMEvents: function(ev) {
		var domevents = /^(?:submit|change|select|mousewheel|DOMMouseScroll|mouseup|mousedown|mousemove|click|dblclick|mouseover|mouseout|keypress|keyup|keydown|scroll|resize|load|unload|focus|blur|error|contextmenu)$/i;
		return domevents.test(ev);
	}
};

/*********************************************************
*		FORM ELEMENTS
*********************************************************/
$WI.Method.Form = {
  ToString: function(frm) {
		if(!frm) return null;
		var str = "";
		for(var i=0;i<frm.elements.length;i++)
			if(frm.elements[i]&&frm.elements[i].type&&frm.elements[i].name)
				str += "&" + frm.elements[i].name + "=" + $V(frm.elements[i]);
		return str;
	},
	Get: function(frm, val) {
		var str = [];
		for(var i=0;i<frm.elements.length;i++)
			if(frm.elements[i]&&frm.elements[i].type&&frm.elements[i].name)
				if(frm.elements[i].name == val)
					str.push(frm.elements[i]);
		if(str.length==1)	return str[0];
		else if(str.length>1)	return str;
		else return null;
	},
	isEmail: function(email) {
		var filter=/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
		if (filter.test(email)) return true;
		else return false;
	},
	input: function(element, value) {
    if(value) {
			switch (element.type.toLowerCase()) {
	      case 'checkbox':
					if(element.value==value)
						element.checked = true;
					break;
	      case 'radio':
				 	var radios = element.form[element.name];
				 	if(!radios) radios = element.form.elements;
					if(radios) {
					for(var r=0;r<radios.length;r++)
						if(radios[r].type == 'radio' && radios[r].name == element.name && radios[r].value == value) {
							radios[r].checked = true;
							break;
						}
				 break;
				 }
   	 	}
		}
		switch (element.type.toLowerCase()) {
      case 'checkbox':
				return $WI.Method.Form.inputSelector(element);
      case 'radio':
       	var radios = element.form[element.name];
       	if(!radios) radios = element.form.elements;
       	if(radios) {
					for(var r=0;r<radios.length;r++){
						if(radios[r].type == 'radio' && radios[r].name == element.name && radios[r].checked)
							return [radios[r].name, radios[r].value];
					}
				}
				return '';
			default:
        return $WI.Method.Form.textarea(element, value);
    }
    return false;
  },
  inputSelector: function(element) {
    if (element.checked)
      return [element.name, element.value];
		else
			return [element.name, 0];
  },
  textarea: function(element, value) {
    if(value)	element.value = value;
		return [element.name, element.value];
  },
  select: function(element, value) {
    if(value)	element.value = value;
		return $WI.Method.Form[element.type=='select-one'?'selectOne':'selectMany'](element);
  },
  selectOne: function(element, value) {
    if(value)	element.value = value;
		var value = '', opt, index = element.selectedIndex;
    if (index >= 0) {
      opt = element.options[index];
      value = opt.value;
    }
    return [element.name, value];
  },
  selectMany: function(element, value) {
    if(value)	element.value = value;
		var value = [];
    for (var i = 0; i < element.length; i++) {
      var opt = element.options[i];
      if (opt.selected)
        value.push(opt.value.replace(/,/g, "$comma;"));
    }
    return [element.name, value];
  }
};

/*********************************************************
*		DOM CLASS
*********************************************************/
$WI.Class.DOM = new $WI.Class({
	LoadJS: function(options){
		var _func;
		var objName = '_temp';
		if(!options || options.src == undefined || options.src == '') return;
		if(!options.objDoc) options.objDoc = D;
		var assignTo = options.objDoc.getElementsByTagName('head')[0];
		var file_name = '/' + $WI.System.GetFileName(options.src);
		//check if current script is not included yet
		if(options.include_once) {
			var children = assignTo.getElementsByTagName('script');
			if(children.length>0)
				for(var c=0;c<children.length;c++)
					if(children[c].src)
						if(children[c].src.match(file_name)) {
							if(options.onload)
								setTimeout(options.onload.Apply(this), 100);
							return false;
						}
		}

		var _jslib = this._insertDOM(null, {objDoc: options.objDoc, objType: 'script', type: 'text/javascript', src: options.src});

		//init class when done
		if(options.uuid) objName = "$WI.Object['" + options.uuid + "']";
		if(options.Class) {
			_func = new Function("e", objName + " = new $WI.Class." + options.Class + "();" + objName +".__construct();");
		} else if(options.onload)
			_func = options.onload;

		if(_func)
			if(this._isSafari2())	//safari 2 fix
				setTimeout(function(){_func}.Apply(this), 2000);
			else
				this.AddDOMEvent({obj: _jslib, type: 'load', onevent: _func});

		//fixing bug in Opera first assign event then append node to the head
		assignTo.appendChild(_jslib);

		return _jslib;
	},
	LoadCSS: function(options){
		if(!options) return;
		if(!options.objDoc) options.objDoc = D;
		var assignTo = options.objDoc.getElementsByTagName('head')[0];
		var file_name = $WI.System.GetFileName(options.href);
		//check if current css is not included yet
		if(options.include_once) {
			var children = assignTo.getElementsByTagName('link');
			if(children.length>0)
				for(var c=0;c<children.length;c++)
					if(children[c].href)
						if(children[c].href.match(file_name)) {
							if(options.onload)
								setTimeout(options.onload.Apply(this), 100);
							return false;
						}
		}

		var _csslib = this._insertDOM(null, {objDoc: options.objDoc, objType: 'link', type: 'text/css', href: options.href, media: 'screen', rel: 'stylesheet'});
		options.objDoc.getElementsByTagName('head')[0].appendChild(_csslib);

		if(options.onload)
			setTimeout(options.onload.Apply(this), 100);

		return _csslib;
	},
	CreateDOM: function(options, parentNode){
		return this._createDOM(options, parentNode);
	},
	InsertDOM: function(el, options, where, returnElement){
		return this._insertDOM(el, options, where, returnElement);
	},
	AppendHTML: function(el, html){
		return this._appendHTML(el, html);
	},
	RemoveDOM: function(el){
		return this._removeDOM(el);
	},
	Set: function(what, where){
		this._insertDOM($E(where), {newNode: this[what]}, 'insertinto');
	},
	Effect: function(options) {
		return this._Animation(options);
	},
	isDisplayed: function(el) {
		if(typeof el == 'string') var el = $E(el);
		if(!el) return;
		if(this._getStyle(el,'display')=='none'||this._getStyle(el,'visible')=='hidden') return false;
		else return true;
	},
	CreateStyleRule: function (selector, declaration, F) {
		if (!document.getElementsByTagName || !(document.createElement || document.createElementNS)) return;
		var agt = navigator.userAgent.toLowerCase();
		var is_ie = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
		var is_iewin = (is_ie && (agt.indexOf("win") != -1));
		var is_iemac = (is_ie && (agt.indexOf("mac") != -1));
		if (is_iemac) return; // script doesn't work properly in IE/Mac
		if(F)	var head = F.getElementsByTagName("head")[0];
		else var head = document.getElementsByTagName("head")[0];
		var style = (typeof document.createElementNS != "undefined") ?  document.createElementNS("http://www.w3.org/1999/xhtml", "style") : document.createElement("style");
		if (!is_iewin) {
			var styleRule = document.createTextNode(selector + " {" + declaration + "}");
			style.appendChild(styleRule); // bugs in IE/Win
		}
		style.setAttribute("type", "text/css");
		style.setAttribute("media", "screen");
		head.appendChild(style);
		if (is_iewin && document.styleSheets && document.styleSheets.length > 0) {
			var lastStyle = document.styleSheets[document.styleSheets.length - 1];
			if (typeof lastStyle.addRule == "object") { // bugs in IE/Mac and Safari
				lastStyle.addRule(selector, declaration);
			}
		}
	},
	_createDOM: function(options, parentNode) {
		if(options.objDoc) var doc = options.objDoc;
		else  var doc = D;
		//fix for IE
		if(this._isIE()&&options.objType=='input'&&!this._isIE8())
			var el = doc.createElement("<input type='" + options.type + "' name='" + options.name + "'>");
		else if(this._isIE()&&options.name&&options.name!='') {
			var el = doc.createElement("<" + options.objType + " name='" + options.name + "' />");
		} else
			var el = doc.createElement(options.objType);

		this._applyConfig(el, options);

		//addons for table
		if(options.objType=='table') {
			el.tbody = doc.createElement('tbody');
			el.appendChild(el.tbody);
			el.tr = doc.createElement('tr');
			el.tbody.appendChild(el.tr);
		//fix for IE LEGEND element,
		} else if(options.objType=='fieldset'&&this._isIE()) {
			var prevMar = this._getStyleInt(el, 'marginTop');
			if(prevMar)el.style.marginTop = this._fixPx(prevMar - 10);
			else el.style.marginTop = '0px';
			var prevMar = this._getStyleInt(el, 'marginBottom');
			if(prevMar)el.style.marginBottom = this._fixPx(prevMar - 10);
			else el.style.marginBottom = '0px';
		} else if(options.objType=='fieldset'&&!this._isIE()) {
			var padMar = this._getStyleInt(el, 'paddingTop');
			if(padMar)el.style.paddingTop = this._fixPx(padMar - 7);
		}

		//insert HTML
  	if(options.html) el.innerHTML = options.html;
		//insert text
		else if(options.text) {
			var _text = document.createTextNode(options.text);
			el.appendChild(_text);
		}

		if(parentNode) parentNode.appendChild(el);
		return el;
	},
	_removeDOM: function(el) {
		if(el&&typeof el=='string') var el = $E(el);
		if(el&&el.parentNode) el.parentNode.removeChild(el);
	},
	_findParent: function(el) {
		if(!el) var el = this.obj;
		var p = el.parentNode;
		var previousP = el;
		while(p&&p.tagName.toLowerCase()!='body')	{
			previousP = p;p = p.parentNode;
		}
		return previousP;
	},
	_insertDOM: function(el, options, where, returnElement) {
		var newNode;
		if(el&&$E(el))el = $E(el);
		else {
			if(options&&options.objDoc) el = options.objDoc.body;
			else el = document.body;
		}
		if(options&&options.newNode) newNode = options.newNode;
		else if(options&&typeof options=='object') newNode = this._createDOM(options);
		else newNode = this.obj;
		if(!where) return returnElement?$E(newNode):newNode;
		if(!newNode._construct)newNode._construct = this;
		switch(where)	{
			case 'insertafter':
				el.parentNode.insertBefore(newNode, el.nextSibling);
				break;
			case 'insertfirst':
				el.insertBefore(newNode, el.firstChild);
				break;
			case 'insertlast':
				el.appendChild(newNode, el.lastChild);
				break;
			case 'insertbefore':
				el.parentNode.insertBefore(newNode, el);
				break;
			case 'insertinto':
				el.appendChild(newNode);
				break;
			case 'moveto':
			case 'replaceAppend':
				el.parentNode.replaceChild(newNode, el);
				newNode.appendChild(el);
				break;
			case 'replace':
				el.parentNode.replaceChild(newNode, el);
				break;
			case 'insertHTML':
				el.innerHTML = options;
				break;
		}
		return returnElement?$E(newNode):newNode;
	},
	_appendHTML: function(el, html) {
		var	fragObj = document.createElement('span');
				fragObj.innerHTML = html;
		return el.appendChild(fragObj);
	},
	_isVisible: function(el, mode) {
		if(typeof el == 'string') var el = $E(el);
		if(!el) return;
		this._isVisibility(el, mode);
		this._isDisplay(el, mode);
	},
	_isVisibility: function(el, mode) {
		if(typeof el == 'string') var el = $E(el);
		if(!el) return;
		if(mode&&this._getStyle(el,'visibility')=='hidden') this._setStyle(el, 'visibility', 'visible');
		else if(!mode&&this._getStyle(el,'visibility')!='hidden') this._setStyle(el, 'visibility', 'hidden');
	},
	_isDisplay: function(el, mode) {
		if(typeof el == 'string') var el = $E(el);
		if(!el) return;
		if(mode&&this._getStyle(el,'display')=='none') {var _css = 'block';
			if(this._isIE()) var _css = 'block';
			else var _css = (el.tagName.toUpperCase()=='TABLE')?'table':(el.tagName.toUpperCase()=='TR')?'table-row':(el.tagName.toUpperCase()=='TD')?'table-cell':'block';
		this._setStyle(el, 'display', _css);
		}
		else if(!mode&&this._getStyle(el,'display')!='none') this._setStyle(el, 'display', 'none');
	},
	MaxZ: function(el) {
		if(!el&&this.obj) var el = this.obj;
		else if(!el&&!this.obj) return false;
		var doc = el.parentNode.childNodes;
		var maxZ = this._getStyleInt(el, 'zIndex'), _maxZ = 1;
		if(!$WI.System.isNumeric(maxZ)) maxZ = 1;
		var totalel = parseInt(doc.length);

		for (var i = 0; i < totalel; i++){
		   if(doc[i].nodeType!=1) continue;
			 _maxZ = this._getStyleInt(doc[i], 'zIndex');
			 if($WI.System.isNumeric(_maxZ))
			 	 maxZ = Math.max(maxZ, _maxZ);
		}
		this._setStyle(el, 'zIndex', maxZ+3);
		//return maxZ+1;
		//if(this._getStyleInt(el, 'zIndex')!=$WI.zIndex||!this._getStyleInt(el, 'zIndex'))
	},
	_convertP$Px: function(p$, total) {
		return parseInt(parseInt(p$)*parseInt(total)/100);
	},
	_fixPx: function(data) {
		try{
			var _data = parseInt(data);
			if(isNaN(_data)) return null;
			else return parseInt(data) + 'px';
		} catch (err) {
			return null;
		}
	},
	_fixP$: function(data) {
		if(typeof data=='object'&&data.length>0){
			for(var i=0;i<data.length;i++)data[i]=parseInt(data[i]) + '%';
			return data.toString().replace(/,/g,' ');
		}
		else return parseInt(data) + '%';
	},
	_toCamelCase: function (sInput) {
    var oStringList = sInput.split('-');
    if(oStringList.length == 1)
        return oStringList[0];
    var ret = sInput.indexOf("-") == 0 ?
       oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0];
    for(var i = 1, len = oStringList.length; i < len; i++){
        var s = oStringList[i];
        ret += s.charAt(0).toUpperCase() + s.substring(1)
    }
    return ret;
	},
	_resizeDOM: function(el, options) {
		if(!el) var el = this.obj;
		el._previousWidth = this._getWidth();
		el._previousHeight = this._getHeight();
		this._applyConfig(el, options);
	},
	_getWidth: function(el) {
		if(!el) var el = this.obj;
		return (el.clientWidth) ? parseInt(el.clientWidth) : parseInt(el.offsetWidth);
	},
	_getHeight: function(el) {
		if(!el) var el = this.obj;
		return (el.clientHeight) ? parseInt(el.clientHeight) : parseInt(el.offsetHeight);
	},
	_getXY: function(el, relative)	{
		if(!el) var el = this.obj;
		if(!el||el.parentNode === null||el.offsetParent === null||this._getStyle(el, 'display')=='none')
			return false;
		var parentNode = null;
		var pos = [];
		var box;
		pos = [el.offsetLeft, el.offsetTop];
		parentNode = el.offsetParent;

		if(parentNode!= el&&!relative) {
			while(parentNode) {
				pos[0] += parentNode.offsetLeft;
				pos[1] += parentNode.offsetTop;
				parentNode = parentNode.offsetParent;
			}
		}
		//depricated by Dima, while working with custom select box
		//if(this._getStyle(el,'position')!='absolute') {
			//pos[0] -= document.body.offsetLeft;
			//pos[1] -= document.body.offsetTop;
		//}

		if(el.parentNode) parentNode = el.parentNode;
		else parentNode = null;

		while(parentNode&&!relative&&parentNode.tagName.toUpperCase()!='BODY'&&parentNode.tagName.toUpperCase()!='HTML')	{
			if(this._getStyle(parentNode, 'display') != 'inline')	{
				pos[0] -= parentNode.scrollLeft;
				pos[1] -= parentNode.scrollTop;
			}
			if(parentNode.parentNode) parentNode = parentNode.parentNode;
			else parentNode = null;
		}
		return {x: pos[0], y: pos[1]};
	},
	_getMouseXY: function(event){
		var event = event || window.event;
		var xy = this._getScrollXY();
		if(event.pageX || event.pageY)
			return {x:event.pageX, y:event.pageY};
		return {
			x:event.clientX + xy.x - document.body.clientLeft,
			y:event.clientY + xy.y  - document.body.clientTop
		}
	},
	_getScreenWH: function() {
		return {w: screen.width, h: screen.height};
	},
	_getClientWH: function() {
			var w = (window.innerWidth!=null) ? window.innerWidth : (document.documentElement&&document.documentElement.clientWidth) ? document.documentElement.clientWidth : (document.body!=null) ? document.body.clientWidth:null;
			var h = (window.innerHeight!=null)? window.innerHeight : (document.documentElement&&document.documentElement.clientHeight) ? document.documentElement.clientHeight:(document.body!= null)?document.body.clientHeight:null;
		return {w: w, h: h};
	},
	_getScrollXY: function(el){
		if(!el||!$E(el)) {
			return {x: (typeof(window.pageXOffset)=='number')?window.pageXOffset:(document.documentElement.scrollLeft)?document.documentElement.scrollLeft:document.body.scrollLeft, y: (typeof(window.pageYOffset)=='number')?window.pageYOffset:(document.documentElement.scrollTop)?document.documentElement.scrollTop:document.body.scrollTop};
		} else
			return {x: el.scrollLeft, y: el.scrollTop};
	},
	_getPageWH: function(){
		var xScroll, yScroll, windowWidth, windowHeight;
		if (window.innerHeight && window.scrollMaxY) {
			xScroll = window.innerWidth + window.scrollMaxX;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if (document.body.scrollHeight > document.body.offsetHeight){
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else {
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}
		if (self.innerHeight) {
			if(document.documentElement.clientWidth){
				windowWidth = document.documentElement.clientWidth;
			} else {
				windowWidth = self.innerWidth;
			}
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) {
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) {
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}
		if(yScroll < windowHeight)pageHeight = windowHeight;
		else pageHeight = yScroll;
		if(xScroll < windowWidth)pageWidth = xScroll;
		else pageWidth = windowWidth;
		return {pageW: pageWidth, pageH: pageHeight, winW: windowWidth, winH: windowHeight};
	},
	_getStyleInt: function(el, st, doc) {
		if(!el) var el = this.obj;
		var valret = parseInt(this._getStyle(el, st, doc));
		return isNaN(valret)?0:valret;
	},
	_getStyle: function(el, property, doc) {
		var val = null;
		var doc;
		if(!doc) doc = document;
		if(doc.defaultView&&doc.defaultView.getComputedStyle)
			try{
				val = doc.defaultView.getComputedStyle(el, null)[property];
			} catch(err) {
				return el.style[property];
			}
		else if(el.currentStyle)
			val = el.currentStyle[property];
		if(el.style&&(!val||val==''))
			val = el.style[property];
		try{
			val = val.replace(/\'/g, "");
			val = val.replace(/\"/g, "");
		} catch(e){}
		if (/^(?:background-position|backgroundPosition)$/i.test(property)) {
			val = val.split(' ');
			for(var i=0;i<val.length;i++)val[i] = parseInt(val[i]);
				return val;
		}
		else
			return val;
	},
	_getAttributes: function(where) {
		var attrlen = where.attributes.length;
		var attribs = [];
		var aname;
		if(attrlen>0)
			for(var a=0; a<attrlen; a++) {
				aname = where.attributes[a].name;
				if(this._getAttribute(where, aname))
					attribs[aname] = this._getAttribute(where, aname);
			}
		return attribs;
	},
	_getAttribute: function(where, attr) {
		var attrnode = where.attributes.getNamedItem(attr);
		if(attrnode) return attrnode.value;
		else return false;
	},
	_getParentByTagName: function(el, tag, ifnull, breakon) {
		var i;
		for(i = el.parentNode; i; i = i.parentNode) {
			if(i.nodeType != 1) continue;
			if(breakon && i.tagName.toLowerCase() == breakon.toLowerCase()) break;
			if(i.tagName && i.tagName.toLowerCase() == tag.toLowerCase())
				return i;
		}
		return (ifnull)?null:el;
	},
	_getParentByClassName: function(el, cls, exact, ifnull) {
		var i, a = [];
		for(i = el.parentNode; i; i = i.parentNode) {
			if(i.nodeType != 1) continue;
			if(this._hasClass(i, cls)&&!exact||exact&&cls==i.className)
				return i;
		}
		return (ifnull)?null:el;
	},
	_getParentsByClassName: function(el, cls, exact) {
		var parents = [];
		var _el;
		for(i = el; i; i = i.parentNode) {
			_el = this._getParentByClassName(i, cls, exact);
			if(_el!=i)
				parents.unshift(_el);
		}
		return parents;
	},
	_getChildrenByTagName: function(el, tagName) {
		if(!el) var el = this.obj;
		var ce = [];
		for(var t = 0; t < tagName.length; t++) {
			var children = el.getElementsByTagName(tagName[t]);
			for(var i = 0; i < children.length; ++i)
				ce[i] = $E(children[i]);
  	}
		return ce;
	},
	_getChildrenByHTMLTagName: function(el, tag) {
		var i, a = [];
		if(tag) tag = tag.toLowerCase();
		for(i = el.firstChild; i; i = i.nextSibling) {
			if(i.nodeType != 1) continue;
			if(!tag || tag == i.tagName.toLowerCase())
				a[a.length] = i;
		}
		return a;
	},
	_getChildrenByClassName: function(el, cls) {
		var i, a = [];
		for(i = el.firstChild; i; i = i.nextSibling) {
			if(i.nodeType != 1) continue;
			if(!cls||this._hasClass(i, cls)==true)
				a.push(i);
		}
		return a;
	},
	_getChildren: function(el)	{
		var i, a = [];
		for(i = el.firstChild; i; i = i.nextSibling) {
			if(i.nodeType != 1) continue;
			a[a.length] = i;
		}
		return a;
	},
	_getDescendents: function(el, a)	{
		if(!a) var a = [];
		var el = $E(el);
		if(!el) return [];
    a.push(el);
		var children = el.childNodes;
    for(var i = 0; i < children.length; i++) a.concat(this._getDescendents(children[i], a));

		return a;
	},
	_getDescendents2: function(el, a)	{
		if(!a) var a = [];
		var el = $E(el);
		if(!el) return [];
    a.push(el);
		var children = el.childNodes;
    for(var i = 0; i < children.length; i++) a.concat(this._getDescendents(children[i], a));
		return a;
	},
	_getTarget: function(event) {
		var t = event.target || event.srcElement;
		return this._resolveTextNode(t);
	},
	_resolveTextNode: function(node) {
		if(node&&node.nodeType==3)
			return node.parentNode;
		else
			return node;
	},
	_applyConfig: function(el, options) {
		for(var attr in options) {
			//disregard all the undefined urls for the backgrounds
			if(attr=='backgroundImage'&&(/undefined/).test(options[attr])) continue;

			if(attr=='objClass')	{
				if(this._isIE7()) options['objClass'] = options['objClass'].replace(/png/, '');
				el.className = options['objClass'];
			}
			else if(attr=='config')	this._applyConfig(el, options[attr]);
			//else if($WI.Variables.VARS.Javascript(attr)) el.onselectstart = function(){return false;};
			else if(attr=='onload')	this.AddDOMEvent({obj: el, type: 'load', onevent: options[attr]});
			else if(attr=='onerror') el.onerror = options[attr];
			else if(this._isIE()&&!this._isIE7()&&attr=='backgroundImage'&&(/.png/).test(options[attr])) {
				options[attr] = options[attr].replace(/url\(/, '').replace(/\)/, '').replace(/;/, '');
				el.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + options[attr] + "', sizingMethod='scale')";
				//$WI.trace(options[attr]);
			}
			else if($WI.Variables.VARS.Attr(attr)) el.setAttribute(attr, options[attr]);
			else if(!$WI.Variables.VARS.EmptyConfig(attr))  this._setStyle(el, attr, options[attr]);
		}
	},
	_setStyle: function(el, property, val) {
		if(!el||!val) return;
		if(this._isIE()) {
			switch(property) {
				case 'scrollTop' :
				case 'scrollLeft' :
					el[property] = parseInt(val);
					break;
				case 'opacity' :
					if(typeof el.style.filter == 'string') {
						el.style.filter = 'alpha(opacity=' + val * 100 + ')';
						el.style.zoom = 1;
						el.style.opacity =val;
					}
					break;
				default:
					try{
						el.style.setProperty(property, val, '');
					}
					catch(ex){
						el.style[property] = val;
					}
			}
		}
		else {
			//Fix an issue if object is inside the scollable div, only for PX
			if((property=='left'||property=='top')&&val.type=='string'&&val.indexOf('%')==-1)
				this._setScrollStyle(el, property, val);
			else if(property=='scrollTop'||property=='scrollLeft')
				el[property] = parseInt(val);
			else {
				try{
					el.style.setProperty(property, val, '');
				}
				catch(ex){}
			}
		}
	},
	_setScrollStyle: function(el, property, val) {
		var val = parseInt(val);
		//calculate properly if div scrolled
		if(property=='left'||property=='top') {
			var parentNode;
			if(el.parentNode) parentNode = el.parentNode;
			else parentNode = null;
			while(parentNode&&parentNode.tagName.toUpperCase()!='BODY'&&parentNode.tagName.toUpperCase()!='HTML')	{
				if(this._getStyle(parentNode, 'display') != 'inline')	{
					switch(property) {
						case 'left':
						val += parentNode.scrollLeft;
						break;
						case 'top':
						val += parentNode.scrollTop;
						break;
					}
				}
			if(parentNode.parentNode) parentNode = parentNode.parentNode;
			else parentNode = null;
			}
			el.style[property] = this._fixPx(val);
		}
	},
	_hasClass: function(el, Cls) {
		var re = new RegExp('(?:^|\\s+)' + Cls + '(?:\\s+|$)');
		return re.test(el['className']);
	},
	_addClass: function(el, Cls) {
		if(!this._hasClass(el, Cls)) el.className = el.className + ' ' + Cls;
	},
	_removeClass: function(el, Cls) {
 		var cl = el.className.split(' ');
		var test = cl.Search(Cls);
		cl.splice(test, 1);
		if(test!=-1) el.className = cl.toString().replace(/,/g, ' ');
	},
	_createClass: function(obj, parentCls) {
		var before, after;
		if(typeof parentCls=='object') {
			if(parentCls.before)before=parentCls.before;
			if(parentCls.after)after=parentCls.after;
			parentCls = parentCls.main;
		}
		var clsReturn = (parentCls)?parentCls:'';
		if(before) clsReturn = before + ' ' + clsReturn;
		for(var i = 0; i < obj.length; i++) {
			if(parentCls) clsReturn += ' ' + parentCls;
			clsReturn += obj;
		}
		if(after) clsReturn =  clsReturn + ' ' + after;
		return clsReturn;
	},
	_createProxy: function(config) {
		if(!config) var config = {};
		if(!config.objDoc) config.objDoc = document;
		this.proxy = config.objDoc.createElement("div");
		this._applyConfig(this.proxy, {opacity: .5});
		if(config.objClass) this.proxy.className = config.objClass;
		if(config.obj) {
			var obj = config.obj;
			var xy = this._getXY(obj);
			this._applyConfig(this.proxy, {width: this._fixPx(this._getWidth(obj)-1), height: this._fixPx(this._getHeight(obj)-1), top:  this._fixPx(xy.y), left:  this._fixPx(xy.x)});
		}
		if(config) this._applyConfig(this.proxy, config);
		this._insertDOM((config.parent)?config.parent:config.objDoc.body, {newNode: this.proxy, objDoc: config.objDoc}, 'insertfirst');
	},
	_showElements: function() {
		 if(!this.hiddenElements || this.hiddenElements.length==0) return;
		 for( i = 0; i < this.hiddenElements.length; i++ )
		 	this.hiddenElements[i].style.visibility = "visible";
		 delete this.hiddenElements;
	},
	_hideElements: function(tag, overDiv) {
    if(this._isIE6() || tag.toUpperCase() == 'OBJECT') {
			if(!this.hiddenElements) this.hiddenElements = [];
			var elementshide = document.getElementsByTagName(tag);
      for( i = 0; i < elementshide.length; i++ ) {
        obj = elementshide[i];
        if(overDiv) {
					if( !obj || !obj.offsetParent )
	          continue;
					objLeft   = obj.offsetLeft;
	        objTop    = obj.offsetTop;
	        objParent = obj.offsetParent;

	        while( objParent.tagName.toUpperCase() != "BODY" ) {
	          objLeft  += objParent.offsetLeft;
	          objTop   += objParent.offsetTop;
	          objParent = objParent.offsetParent;
	        }
	        objHeight = obj.offsetHeight;
	        objWidth = obj.offsetWidth;

	        if(( overDiv.offsetLeft + overDiv.offsetWidth ) <= objLeft );
	        else if(( overDiv.offsetTop + overDiv.offsetHeight ) <= objTop );
	        else if( overDiv.offsetTop >= ( objTop + objHeight ));
	        else if( overDiv.offsetLeft >= ( objLeft + objWidth ));
	        else obj.style.visibility = "hidden";
				} else
					 obj.style.visibility = "hidden";

				this.hiddenElements.push(obj);
			}
    }
  }
});


/*********************************************************
*		Event Manager
*********************************************************/
$WI.Class.EventManager = new $WI.Class({
	AddEvent: function(config) {
		if(!config||!config.obj||(!config.onevent&&!config.onfire&&!config.onfirebefore&&!config.oneventbefore)||!config.type) return false;
		var obj = config.obj;
		var type = config.type;
		var fireEvent = this.Fire;
		if(!obj.regEvents) obj.regEvents = [];
		if(!obj.regEventsBefore) obj.regEventsBefore = [];
		if(!obj.regEventsAfter) obj.regEventsAfter = [];
		config._this = this;
		if(config.onfirebefore) config.onfire = config.onfirebefore;
		if(config.oneventbefore) config.onevent = config.oneventbefore;
		if(config.onfireafter) config.onfire = config.onfireafter;
		if(config.oneventafter) config.onevent = config.oneventafter;
		if(config.onfire) {
			if(!config.onfire.obj._this) config.onfire.obj._this = this;
			if(!config.onfire.obj._construct) config.onfire.obj._construct = this;
			if(!config.obj._this) config.obj._this = this;
			//if(!config.onfire.fire) config.onfire.fire = type;
			config.onevent = function(event){fireEvent(event, config.onfire.fire, config.onfire.obj)};
		} else if(config.onevent&&typeof config.onevent!= 'function') {
			obj = config.onevent.obj;
			config.onevent = config.onevent.onevent;
		}


		if(!obj.regEvents[type]) obj.regEvents[type] = [];
		if(!obj.regEventsBefore[type]) obj.regEventsBefore[type] = [];
		if(!obj.regEventsAfter[type]) obj.regEventsAfter[type] = [];

		if(config.onfirebefore||config.oneventbefore)	obj.regEventsBefore[type].push(config);
		else if(config.onfireafter||config.oneventafter)	obj.regEventsAfter[type].push(config);
		else obj.regEvents[type].push(config);

		if($WI.Variables.VARS.DOMEvents(type)) this._addEvent(obj, type, config.onevent);

		return;
	},
	RemoveEvent: function(config) {
		if(!config||!config.obj||!config.type) return false;
		var obj = config.obj;
		var type = config.type;
		var register = (obj.regEvents)?obj.regEvents[type]:null;
		if(register&&obj.regEventsBefore[type]&&obj.regEventsBefore[type].length>0) register = register.concat(obj.regEventsBefore[type]);
		if(register&&obj.regEventsAfter[type]&&obj.regEventsAfter[type].length>0) register = register.concat(obj.regEventsAfter[type]);
		if(register)	{	//remove registered events
			for(var e=0;e<register.length;e++) {
				//remove registered fired events
				if(config.onfire&&register[e].onevent&&register[e].onfire&&register[e].onfire.obj==config.onfire.obj)
					var eventRemove = register[e].onevent;
				//remove registered standard events
				else if(config.onevent&&register[e].onevent&&config.onevent==register[e].onevent)
					var eventRemove = register[e].onevent;
				//remove fired events
				else if(config.type&&register[e]&&config.obj) {
					register[e] = null;
					return;
				}
				//no events
				else return false;


				//$WI.trace(type + '/' + obj.className)

				if($WI.Variables.VARS.DOMEvents(type)&&eventRemove) this._removeEvent(obj, type, eventRemove);
				register.splice(e,1);
			}
		} else if($WI.Variables.VARS.DOMEvents(type)&&config.onevent) {	//remove standard events
				this._removeEvent(obj, type, config.onevent);
		}
		return;
	},
	//_target is optional in case event does not exists
	Fire: function(event, fire, obj, _target) {
		var type, obj, _target;
		if(!event) event = fire;
		if(typeof event!='string') _target = obj._construct._getTarget(event);

		//try{$WI.trace(obj.className + '/' + fire + '/' + event)}catch(e){}
		(fire)?type=fire:type=event.type;
		//
		if(!obj.regEvents||!obj.regEvents[type]||obj.regEvents[type].length==0) {
			//$WI.trace("No events registered for " + type);
			return false;//no events registered
		}

		arguments[0].fire = type;arguments[1] = _target;

		//$WI.trace(fire + '/' + _target.className)

		if(obj.regEventsBefore[type].length>0) {
			for(var e=0;e<obj.regEventsBefore[type].length;e++)
				if(obj.regEventsBefore[type][e].onevent)
					obj.regEventsBefore[type][e].onevent.apply(obj.regEventsBefore[type][e]._this, arguments);
		}

		for(var e=0;e<obj.regEvents[type].length;e++) {
			if(obj.regEvents[type][e]&&obj.regEvents[type][e].onevent)
				obj.regEvents[type][e].onevent.apply(obj.regEvents[type][e]._this, arguments);
		}

		if(obj.regEventsAfter[type].length>0) {
			for(var e=0;e<obj.regEventsAfter[type].length;e++)
				if(obj.regEventsAfter[type][e].onevent)
					obj.regEventsAfter[type][e].onevent.apply(obj.regEventsAfter[type][e]._this, arguments);
		}

	},
	EventExists: function(config) {
		var obj = config.obj;
		var type = config.type;
		if(obj&&obj.regEvents&&obj.regEvents[type]&&obj.regEvents[type].length>0)	{
			for(var e=0;e<obj.regEvents[type].length;e++)
				if(obj.regEvents[type][e].onevent&&obj.regEvents[type][e].onevent==config.onevent)
					return true;
		}
		return false;
	},
	AddWIEvent: function(config) {
		this._addEvent(config.obj, config.type, config.onevent);
	},
	RemoveWIEvent: function(config) {
		this._removeEvent(config.obj, config.type, config.onevent);
	},
	AddDOMEvent: function(config) {
		if(!$WI.Variables.VARS.DOMEvents(config.type)) return;
		var type, obj, _target, arguments;
		var obj = config.obj;
		var type = config.type;
		if(!obj) return;
		if(!obj._this) obj._this = this;
		if(!obj._construct)obj._construct = this;

		var newevent = function(event){
			try{
				var _target = $WI.DOM._getTarget(event);
				config.onevent.apply(obj._construct, [event, _target, obj]);
			} catch(e){}
		};
		if(config.type=='load'&&this._isIE()) {
					obj.onreadystatechange = function() {
																	if (this.readyState=="complete"||this.readyState=="loaded")
																		config.onevent.apply(obj._construct, [event, _target, obj]);
																};

		} else {
			this._addEvent(obj, type, newevent);
		}
		//fix IE bug for onload event of images
		//if(config.type='load'&&config.obj.tagName&&config.obj.tagName.toLowerCase()=='img')
			 //config.obj.src = config.obj.src;
	},
	OnLoadDOM: function(func) {
		$WI.Event.onLoad.push(func);
	},
	OnLoadPage: function(func) {
		this._addEvent(window, 'load', func);
	},
	PreloadJSLibraries: function(options) {
		if(!options.start&&options.start!=0) options.start = 0;
		else options.start++;
		if(options.libs.length==options.start&&options.onComplete)
			options.onComplete.call();
		else
			this.LoadJS({src: options.libs[options.start], include_once: true, onload: function(){this.PreloadJSLibraries(options)}.Apply(this)});
	},
	_onLoadDOM: function() {
		if ($WI.Event.documentLoaded) return;
    if ($WI.Event.interval) window.clearInterval($WI.Event.interval);
    $WI.Event.documentLoaded = true;
		for(var e=0;e<$WI.Event.onLoad.length;e++)
			$WI.Event.onLoad[e].call();
	},
	_initLoadDOM: function(event) {
		$WI.Event._this = this;
		$WI.Event.onLoad = [];
		if (document.addEventListener) {
	    if ($WI.DOM._isSafari()) {
	      $WI.Event.interval = window.setInterval(function() {
	        if (/loaded|complete/.test(document.readyState))
	          $WI.Event._onLoadDOM();
	      }, 0);
	      $WI.Event.AddDOMEvent({obj: window, type: 'load', onevent: $WI.Event._onLoadDOM});
	    } else {
	      document.addEventListener("DOMContentLoaded", $WI.Event._onLoadDOM, false);
	    }
	  } else {
	    document.write("<script id=__onPrismDOMLoaded defer src=//:><\/script>");
	    $E("__onPrismDOMLoaded").onreadystatechange = function() {
	      if (this.readyState == "complete") {
	        this.onreadystatechange = null;
	        $WI.Event._onLoadDOM();
	      }
	    };
	  }
	},
	_addEvent: function(obj, type, fn) {
		if (obj.attachEvent) {
			obj['e'+type+fn] = fn;
			obj[type+fn] = function(){
				var _event = window.event;
				if(!_event) {
				//event happend in an IFRAME check them
					var element = D.getElementsByTagName("iframe");
					for (var i=0; i<element.length; i++)
						if(element[i].contentWindow.event)
							_event = element[i].contentWindow.event;
				}
				obj['e'+type+fn](_event);
			};

			obj.attachEvent('on'+type, obj[type+fn]);
	  } else {
			if(type=='mousewheel'&&!this._isSafari()&&!this._isChrome()) type = 'DOMMouseScroll';
			if(obj.isArray&&obj.length>1) {
				for(var o=0;o<obj.length;o++)
					obj[o].addEventListener(type, fn, false);
			}
			else
				obj.addEventListener(type, fn, false);
		}
	},
	_removeEvent: function(obj, type, fn) {
		try {
		  if (obj.detachEvent) {
				obj.detachEvent('on'+type, obj[type+fn]);
		    obj[type+fn] = null;
		  } else {
		    obj.removeEventListener(type, fn, false);
			}
		} catch(e) {}
	},
	_getFuncStruct: function(event) {
		return function(event) {
			try{
				var _target = $WI.DOM._getTarget(event);
				fn.apply(obj._construct, [event, _target, obj]);
			} catch(e){}
		};
	},
	_cancelEvent: function(event) {
		if(event.stopPropagation)
			event.stopPropagation();
		else
			event.cancelBubble = true;
		this._preventDefault(event);
	},
	_cancelSelect: function(event, disable, obj) {
		//FOR OPERA -o-user-select:none
		if(!obj) var obj = document.body;
		if(event) this._preventDefault(event);
		if(this._isIE() || this._isChrome())
			//(disable)?document.onselectstart = function(){event.returnValue = false;}:document.onselectstart = function(){};
			(disable)?obj.onselectstart=new Function('return false'):obj.onselectstart=new Function('return true');
		//else if(this._isOpera())
			//(disable)?this._setStyle(obj, 'oUserSelect', 'none'):this._setStyle(obj, 'oUserSelect', '');
		else if(this._isSafari())
			(disable)?this._setStyle(obj, 'KhtmlUserSelect', 'none'):this._setStyle(obj, 'KhtmlUserSelect', '');
		else
			(disable)?this._setStyle(obj, 'MozUserSelect', 'none'):this._setStyle(obj, 'MozUserSelect', '');
	},
	_preventDefault: function(event) {
		if(event.preventDefault)
			event.preventDefault();
		else
			event.returnValue = false;
	},
	_keyEvent: function(event) {
		(window.event)?e=window.event:e=event;
		this.Key = (e.keyCode)?e.keyCode:(e.which)?e.which:e.charCode;
		this.KeyChar = String.fromCharCode(this.Key);
		switch(this.Key) {
			case 13 :	//enter
			$WI.REG.Buttons.Enter = (e.type=='keydown')?true:false;
			break;
			case 16 :	//shift
			$WI.REG.Buttons.Shift = (e.type=='keydown')?true:false;
			this._cancelSelect(event, (e.type=='keydown')?true:false);
			break;
			case 17 :	//ctrl
			$WI.REG.Buttons.Ctrl = (e.type=='keydown')?true:false;
			this._cancelSelect(event, (e.type=='keydown')?true:false);
			break;
			case 18 :	//alt
			$WI.REG.Buttons.Alt = (e.type=='keydown')?true:false;
			break;
			default:
			break;
		}
	},
	_getWheelDelta: function(event){
     //positive if wheel was scrolled up, negative, if wheel was scrolled down.
		 var delta = 0;
     if (!event) event = window.event;
		 if (event.wheelDelta)  /* IE/Opera */
       delta = event.wheelDelta/120;
     else if (event.detail)  /* Mozilla */
        delta = -event.detail/3;
     return delta;
	},
	_Animation: function(options) {
		if($WI.Class.Animation){
			if(!options._this) options._this = this;
			var animation = new $WI.Class.Animation;
					animation._construct = this;
			return animation.Animation(options);
		} else $WI.trace("animation.js Class is required and must be included into the page!");
	}
});
$WI.extend($WI.Class.DOM, $WI.Class.EventManager);

/*********************************************************
*		INTERFACE DISPLAY METHODS
*		Extends: DOM Class
*********************************************************/
$WI.Method.Display = {
	SetActiveStyleSheet: function(title) {
		var i, a, main;
	  title = title.replace(/%20/g, " ");
		if(title) {
	    var links = document.getElementsByTagName('link');
	    for(i = 0; (a = links[i]); i++) {
	      if (/style/.test(a.getAttribute('rel')) && a.getAttribute('title')) {
	        a.disabled = true;
	        if (a.getAttribute('title') == title)
	          a.disabled = false;
	        else if (a.getAttribute('title') == 'IE7')
						a.disabled = false;
	      }
	    }
		}
	},
	DisableScreen: function(options) {
		if(!options) var options = {};
		if(this._getChildrenByClassName(document.body, '_element-screen-disabled').length==0) {
			this.screen = $WI.DOM._insertDOM(null, {objType: 'div', objClass: '_element-screen-disabled', opacity: 0, backgroundColor: '#000000', position: 'absolute', textAlign: 'center',	top: '0px', left: '0px', zIndex: 10000}, 'insertinto');
			this.screen.options = options;
			this._hideElements('SELECT');
			this._hideElements('OBJECT');
			this.MaxZ(this.screen);
			this.AjustScreen();
			if($WI.Class.Animation&&$_VAR(options.effect, true)){
				var _effect = this._Animation({effect: 'AlphaIn', obj: this.screen, to: 80, speed: 3});
				if(this.screen.options.onDisable) {
						_effect.onAnimationFinishedEffect = function() {
									_effect._construct.screen.options.onDisable();
							}
				}
			} else {
				this._setStyle(this.screen, 'opacity', .8);
				if(options.onDisable)options.onDisable();
			}
			this.AddWIEvent({obj: window, type: 'resize', onevent: function(){this.AjustScreen()}.Apply(this)});
			//this.AddWIEvent({obj: window, type: 'resize', onevent: this.AjustScreen});
			//enable screen on click
			if($_VAR(options.enableOnClick, true))
				this.AddDOMEvent({obj: this.screen, type: 'click', onevent: function(){this.EnableScreen()}.Apply(this)});
		}
	},
	EnableScreen: function() {
		if(this.screen) {
			this.RemoveWIEvent({obj: window, type: 'resize', onevent: function(){this.AjustScreen()}.Apply(this)});
			//this.RemoveWIEvent({obj: window, type: 'resize', onevent: this.AjustScreen});
			this._removeDOM(this.screen);
		}

		if(this.screen.options)
			if(this.screen.options.onEnable)
				this.screen.options.onEnable();
		this._showElements();
	},
	AjustScreen: function() {
		if(!this.screen) return;
		var scrl = this._getPageWH();
		this._applyConfig(this.screen, {width: this._fixPx(scrl.pageW), height: this._fixPx(scrl.pageH)});
	},
	BrowserAlert: function(options) {
		var _alert = this._insertDOM(null, {objType: 'div', overflow: 'hidden', width: '100%', height: '20px', color: '#000000', backgroundColor: '#ffffe1', borderBottom: '2px ridge #cccccc', position: 'absolute', zIndex: 999999, top: '0px', left: '0px', cursor: 'pointer', display: 'none'}, 'insertinto');
		var table = this._insertDOM(_alert, {objType: 'table', width: '100%'}, 'insertinto');
		var td = this._insertDOM(table.tr, {objType: 'td', width: '25px', vAlign: 'top'}, 'insertinto');
		this._insertDOM(td, {objType: 'img', display: 'block', width: '16px', height: '16px', src: (options.icon)?options.icon:'/prism_resource/images/icons16x16/system_alert.png', objClass: 'png'}, 'insertinto');

		_alert.txt = this._insertDOM(table.tr, {objType: 'td', font: 'menu', html: options.message}, 'insertinto');
		//create close button
		var td = this._insertDOM(table.tr, {objType: 'td', textAlign: 'right', vAlign: 'top'}, 'insertinto');
		var _delete = this._insertDOM(td, {objType: 'img', align: 'right', display: 'block', width: '16px', height: '16px', src: '/prism_resource/images/icons16x16/system_close.gif'}, 'insertinto');

		this.AddDOMEvent({obj: _alert, type: 'click', onevent: function(){this._removeDOM(_alert);}});
		this.AddDOMEvent({obj: _alert, type: 'mouseover', onevent: function(){this._setStyle(_alert, 'backgroundColor', '#001c84');this._setStyle(_alert.txt, 'color', '#ffffff');}});
		this.AddDOMEvent({obj: _alert, type: 'mouseout', onevent: function(){this._setStyle(_alert, 'backgroundColor', '#ffffe1');this._setStyle(_alert.txt, 'color', '#000000');}});

		if($WI.Class.Animation)
			this._Animation({effect: 'SlideOut', obj: _alert, style: 'top', from: -30, to: 0, speed: 50});


		this.MaxZ(_alert);
		this._isDisplay(_alert, true);
	},
	Alert: function(options) {
		if($WI.Class.Window){
			this.DisableScreen({enableOnClick: false, effect: false});
			var win = new $WI.Class.Window;
			win.Create({label: (options.label)?options.label:'Alert!', width: '300px', height: '150px', icon: (options.icon)?options.icon:'/prism_resource/images/icons16x16/system_alert.png', resize: false, buttons: false, textArea: {padding: '20px', textAlign: 'center'}});
			win.AddEvent({type: 'closewindow', obj: win, onevent: function(){this.EnableScreen()}.Apply(this)});
			win.Write();
			win.MaxZ();
			win.GetContent().innerHTML = options.message + '<br><br><br>';

			//create OK Button
			var button_yes = new $WI.Class.Element;
			button_yes.Button({title: 'OK', width: '80px', config: {align: 'center'}});
			button_yes.Write(win.GetContent());
			button_yes.AddEvent({obj: button_yes.GetBody(), type: 'click', onevent: function(){this.CloseWindow()}.Apply(win)});

			//ajust window height by the body
			win.AjustHeight();
			this.CenterObject(win.GetBody());

		} else
			alert(options.message);
		return false;
	},
	Confirm: function(options) {
		if($WI.Class.Window&&$WI.Class.Element){
			this.DisableScreen({enableOnClick: false, effect: false});
			var win = new $WI.Class.Window;
			win.Create({label: (options.label)?options.label:'Confirm', width: '400px', height: '150px', icon: (options.icon)?options.icon:'/prism_resource/images/icons16x16/system_question.png', resize: false, buttons: false, textArea: {padding: '20px', textAlign: 'center'}});

			win.AddEvent({type: 'closewindow', obj: win, onevent: function(){this.EnableScreen()}.Apply(this)});

			//win.OnWindowClosed = function(){this.EnableScreen()}.Apply(this);
			win.Write();
			win.MaxZ();

			var t = this._insertDOM(win.GetContent(), {objType: 'table', cellSpacing: '10px', cellPadding: '10px', width: '100%'}, 'insertinto');
			this._insertDOM(t.tr, {objType: 'td', html: options.message, textAlign: 'center', colSpan: 2}, 'insertinto');
			var tr = this._insertDOM(t.tbody, {objType: 'tr'}, 'insertinto');
			var td = this._insertDOM(tr, {objType: 'td', height: '50px', align: 'right'}, 'insertinto');
			//create Yes Button
			var button_yes = new $WI.Class.Element;
			button_yes.Button({title: 'Yes', icon: '/prism_resource/images/icons16x16/system_yes.png', width: '50px'});
			button_yes.Write(td);
			button_yes.OnClickEvent(options.YesFunction);
			button_yes.AddEvent({obj: button_yes.GetBody(), type: 'click', onfire: {obj: win, fire: 'closewindow'}});

			//create No Button
			var td = this._insertDOM(tr, {objType: 'td'}, 'insertinto');
			var button_no = new $WI.Class.Element;
			button_no.Button({title: 'No', icon: '/prism_resource/images/icons16x16/system_delete.gif', width: '50px'});
			button_no.Write(td);
			button_no.AddEvent({obj: button_no.GetBody(), type: 'click', onfire: {obj: win, fire: 'closewindow'}});

			//ajust window height by the body
			win.AjustHeight();
			this.CenterObject(win.GetBody());

		} else {
			if(confirm(options.message))
				options.YesFunction();
		}
		return false;
	},
	CenterObject: function(obj, options) {
		var display = this._getClientWH();
		if(obj) {
			var w = this._getWidth(obj);
			var h = this._getHeight(obj);
		} else {
			var w = parseInt(options.width);
			var h = parseInt(options.height);
		}
		var xy = this._getScrollXY();
		var _left = (display.w - w) / 2;
		var _top = (display.h - h) / 2;
		if(_left<0) _left = 0;
		if(_top<0) _top = 0;

		_top += xy.y;
		_left += xy.x;

		if(obj)
			this._applyConfig(obj, {left: this._fixPx(_left), top: this._fixPx(_top)});
		else
			return {top: _top, left: _left};
	}
};
$WI._extend($WI.Class.DOM, $WI.Method.Display);

/*********************************************************
*		SYSTEM HELPFUL METHODS
*********************************************************/
$WI.System = {
	isArray: function(obj) {
		if(!obj) return false;
		return obj.isArray;
	},
	isFunc: function(func) {
		return ((typeof func).toLowerCase()=='function');
	},
	isBoolean: function(value) {
		if(value.toString()=='true'||value.toString()=='false')
			return true;
		else
			return false;
	},
	getBoolean: function(value) {
		if($WI.System.isBoolean(value))
			return value;
		else
			return false;
	},
	isDefined: function(value) {
	 if (!value&&value!=0) return false;
	 else return true;
  },
	isNumeric: function(value) {
	 if (!value&&value!==0||isNaN(value*1)) return false;
	 return true;
  },
	isCookieEnabled: function() {
	 document.cookie = "Enabled=true";
	 var cookieValid = document.cookie;
	 if (cookieValid.indexOf("Enabled=true") != -1)  return true;
	 else return false;
  },
	GetFileName: function(value) {
	 if(typeof value != 'string') return null;
	 var _v = value.split('/');
	 return (_v.length>0)?_v[_v.length-1]:'';
  },
	Cursor: function(cursor, options){
		var doc;
		if(options&&options.objDoc) doc = options.objDoc;
		else doc = D;
		doc.body.style.cursor = (cursor)?cursor:'default';
	},
	Check: function() {
    var val;
    for (var i=0,length=arguments.length;i<length;i++) {
			if(arguments[i]!=undefined) {
				if($WI.System.isFunc(arguments[i])) {
					try {val = arguments[i]();break;} catch (e) {}
				} else {
					val = arguments[i];break;
				}
			}
    }
    return val;
  },
	Random: function(val) {
   if(val!==undefined) return Math.round(val*Math.random());
	 else return Math.round(9999999*Math.random());
  },
	PreloadImages: function(imgs) {
		var dom = new $WI.Class.DOM;
		for(var i=0;i<imgs.length;i++)
			dom._insertDOM(null, {objType: 'img', src: imgs[i], top: '-3000px', left: '-3000px', zIndex: '-999', display: 'none'}, 'insertinto');
	},
	DateTimeFormat: function(datetime, mask) {
		return this.DateFormat(datetime, this.TimeFormat(datetime, mask));
	},
	DateFormat: function(datedata, mask) {
		if(!datedata) var datedata = new Date();
		if(!mask) return datedata;
		var date_string = '';
		var day_names = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
		var	day_value = datedata.getDay();
		var	date_value = datedata.getDate();
		var	day_text = day_names[day_value];
		var month_names = ["January","February","March","April","May","June","July","August","September","October","November","December"];
		var	month_value = datedata.getMonth();
		var month_text = month_names[month_value];
		var year_value = datedata.getFullYear();
		//increament month value for the digit output
		month_value++;

		//create year
		mask = mask.replace(/([$][y]{3,4})/g, year_value);
		mask = mask.replace(/([$][y]{1,2})/g, year_value.toString().substring(2,4));
		//create month
		mask = mask.replace(/([$][m]{4})/g, month_text);
		mask = mask.replace(/([$][m]{3})/g, month_text.substring(0,3));
		mask = mask.replace(/([$][m]{2})/g, (month_value.toString().length==1)?'0'+month_value.toString():month_value.toString());
		mask = mask.replace(/([$][m]{1})/g, month_value.toString());
		//create day and day of the week
		mask = mask.replace(/([$][d]{4})/g, day_text);
		mask = mask.replace(/([$][d]{3})/g, day_text.substring(0,3));
		mask = mask.replace(/([$][d]{2})/g, (date_value.toString().length==1)?'0'+date_value.toString():date_value.toString());
		mask = mask.replace(/([$][d]{1})/g, date_value.toString());

		return mask;
	},
	TimeFormat: function(timedata, mask) {
		if(!timedata) var timedata = new Date();
		var hour_value = timedata.getHours();
		var minute_value = timedata.getMinutes();
		var second_value = timedata.getSeconds();
		if(hour_value<12) {
			var hour_value12 = hour_value;
			var time_mode = "AM";
		} else {
			var hour_value12 = hour_value - 12;
			var time_mode = "PM";
		}
		//create hours
		mask = mask.replace(/([$][h]{2})/g, (hour_value12.toString().length==1)?'0'+hour_value12.toString():hour_value12.toString());
		mask = mask.replace(/([$][h]{1})/g, hour_value12.toString());
		mask = mask.replace(/([$][H]{2})/g, (hour_value.toString().length==1)?'0'+hour_value.toString():hour_value.toString());
		mask = mask.replace(/([$][H]{1})/g, hour_value.toString());
		//create minutes
		mask = mask.replace(/([$][n]{2})/g, (minute_value.toString().length==1)?'0'+minute_value.toString():minute_value.toString());
		mask = mask.replace(/([$][n]{1})/g, minute_value.toString());
		//create seconds
		mask = mask.replace(/([$][s]{2})/g, (second_value.toString().length==1)?'0'+second_value.toString():second_value.toString());
		mask = mask.replace(/([$][s]{1})/g, second_value.toString());
		//create mode
		mask = mask.replace(/([$][t]{1})/g, time_mode.toString().toLowerCase());
		mask = mask.replace(/([$][T]{1})/g, time_mode.toString());

		return mask;
	},
	Trim: function (stringToTrim) {
	 	return stringToTrim.replace(/^\s+|\s+$/g,"");
  },
  RTrim: function(stringToTrim){
	 	return stringToTrim.replace(/^\s+/,"");
  },
  LTrim: function(stringToTrim){
	  return stringToTrim.replace(/\s+$/,"");
  },
	GetCookie: function (name) {
		var start = document.cookie.indexOf( name + "=" );
		var len = start + name.length + 1;
		if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
			return null;
		}
		if ( start == -1 ) return null;
		var end = document.cookie.indexOf( ';', len );
		if ( end == -1 ) end = document.cookie.length;
		return unescape( document.cookie.substring( len, end ) );
	},
 	SetCookie: function(name, value, expires, path, domain, secure) {
		var today = new Date();
		if(!path) var path = '/';
		today.setTime( today.getTime() );
		if ( expires ) {
			expires = expires * 1000 * 60 * 60 * 24;
		}
		var expires_date = new Date( today.getTime() + (expires) );
		document.cookie = name+'='+escape( value ) +
			( ( expires ) ? ';expires='+expires_date.toGMTString() : '' ) + //expires.toGMTString()
			( ( path ) ? ';path=' + path : '' ) +
			( ( domain ) ? ';domain=' + domain : '' ) +
			( ( secure ) ? ';secure' : '' );
	},
	DeleteCookie: function (name, path, domain) {
		if(!path) var path = '/';
		if ( this.GetCookie( name ) ) document.cookie = name + '=' +
				( ( path ) ? ';path=' + path : '') +
				( ( domain ) ? ';domain=' + domain : '' ) +
				';expires=Thu, 01-Jan-1970 00:00:01 GMT';
	}
};

/*********************************************************
*		BASE64 CLASS
*		Class encodes and decodes data to base64 or utf-8 encoding
*		Designed & developed by Dima Svirid, 2009
*		Class: hash.js
*	  Extends: system.js
*********************************************************/
$WI.Base64 = {
	Encode : function (input) {
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;
		input = $WI.Base64._utf8_encode(input);
		while (i < input.length) {
			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);
			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;
			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}
			output = output +
			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
		}
		return output;
	},
	Decode : function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;
		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
		while (i < input.length) {
			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));
			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;
			output = output + String.fromCharCode(chr1);
			if (enc3 != 64) {
				output = output + String.fromCharCode(chr2);
			}
			if (enc4 != 64) {
				output = output + String.fromCharCode(chr3);
			}
		}
		output = $WI.Base64._utf8_decode(output);
		return output;

	},
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
		for (var n = 0; n < string.length; n++) {
			var c = string.charCodeAt(n);
			if (c < 128)
				utftext += String.fromCharCode(c);
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
		}
		return utftext;
	},
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
		while ( i < utftext.length ) {
			c = utftext.charCodeAt(i);
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
		}
		return string;
	},
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
};

/*********************************************************
*		UUID Generator CLASS
*********************************************************/
$WI.UUID = function(options) {
	return new $WI.Class.UUID().Create();
};
$WI.Class.UUID = new $WI.Class({
	Create: function(){
		var dg = this.timeInMs(new Date(1582, 10, 15, 0, 0, 0, 0));
		var dc = this.timeInMs(new Date());
		var t = dc - dg;
		var h = '-';
		var tl = this.getIntegerBits(t,0,31);
		var tm = this.getIntegerBits(t,32,47);
		var thv = this.getIntegerBits(t,48,59) + '1';
		var csar = this.getIntegerBits(this.randrange(0,4095),0,7);
		var csl = this.getIntegerBits(this.randrange(0,4095),0,7);
		var n = this.getIntegerBits(this.randrange(0,8191),0,7) +
				this.getIntegerBits(this.randrange(0,8191),8,15) +
				this.getIntegerBits(this.randrange(0,8191),0,7) +
				this.getIntegerBits(this.randrange(0,8191),8,15) +
				this.getIntegerBits(this.randrange(0,8191),0,15);
		return tl + h + tm + h + thv + h + csar + csl + h + n;
	},
	getIntegerBits: function(val,start,end){
		var base16 = this.returnBase(val,16);
		var quadArray = new Array();
		var quadString = '';
		for(var i=0;i<base16.length;i++)
			quadArray.push(base16.substring(i,i+1));
		for(i=Math.floor(start/4);i<=Math.floor(end/4);i++){
			if(!quadArray[i] || quadArray[i] == '') quadString += '0';
			else quadString += quadArray[i];
		}
		return quadString;
	},
	returnBase: function(number, base){
		var convert = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
	    if (number < base) var output = convert[number];
	    else {
	        var MSD = '' + Math.floor(number / base);
	        var LSD = number - MSD*base;
	        if (MSD >= base) var output = this.returnBase(MSD,base) + convert[LSD];
	        else var output = convert[MSD] + convert[LSD];
	    }
	    return output;
	},
	timeInMs: function(d){
		var ms_per_second = 100;
		var ms_per_minute = 6000;
		var ms_per_hour   = 360000;
		var ms_per_day    = 8640000;
		var ms_per_month  = 207360000;
		var ms_per_year   = 75686400000;
		return Math.abs((d.getUTCFullYear() * ms_per_year) + (d.getUTCMonth() * ms_per_month) + (d.getUTCDate() * ms_per_day) + (d.getUTCHours() * ms_per_hour) + (d.getUTCMinutes() * ms_per_minute) + (d.getUTCSeconds() * ms_per_second) + d.getUTCMilliseconds());
	},
	randrange: function(min,max){
		var num = Math.round(Math.random() * max);
		if(num < min)	num = min;
		else if (num > max)	num = max;
		return num;
	}
});

/*********************************************************
*		LOGGER CLASS
*********************************************************/
$WI.Class.Logger = new $WI.Class({
	_initLogger: function(options) {
		var loggerObj = this._insertDOM(null, {objType: 'div', bottom: '0px', left: '0px', zIndex: 100000, backgroundColor: '#eeeeee',	position: 'absolute',	overflow: 'hidden',	border: '1px dashed #000000',	width: '200px',	height: '300px'}, 'insertinto');
		var handler = this._insertDOM(loggerObj, {objType: 'div', html: 'Tracer', cursor: 'pointer', backgroundColor: '#585858', border: '1px solid #000000', height: '20px', margin: '5px',	padding: '2px', paddingLeft: '5px',	color: '#e6e6e6', fontFamily:'Arial', overflow: 'hidden', fontSize: '11px'}, 'insertinto');
		if($WI.Class.DragDrop){
			$WI.extend($WI.Class.Logger, $WI.Class.DragDrop);
			this.initDD(loggerObj, {handler: handler});
			this.Resize();
		}
		this.logBody = this._insertDOM(loggerObj, {objType: 'div', color: '#9c9c9c', cursor: 'default',	position: 'relative',	top: '0px', bottom: '0px', right: '0px', left: '0px',	backgroundColor: '#ffffff', border: '1px solid #000000',margin: '5px',	padding: '2px',	overflow: 'auto',	height: '85%', fontFamily:'Arial', fontSize: '11px'}, 'insertinto');
	},
	Write: function(message) {
		message = "<font style='color:#cbcbc8;font-size:7pt;'>------------" + $WI.System.DateTimeFormat(now(), '$HH:$nn:$ss - $mmm $d, $yy') + "-----------<\/font><br>" + message;
		this._insertDOM(this.logBody, {objType: 'div', html: message}, 'insertfirst');
	}
});

$WI.init();	//Initialize System Class, do not remove


