var o_O = new function() {
    var self = this;
    self.browser = {name: false, v: false};
    var browserDetect = new function() {
	if ('\v' == 'v') {
	    self.browser.name = 'IE';
	    if (!window.XMLHttpRequest) {
		self.browser.v = 6;
	    } else if (!window.JSON) {
		self.browser.v = 7;
	    } else {
		self.browser.v = 8;
	    }
	} else if (/a/[-1] == 'a') {
	    self.browser.name = 'FF';
	    if ((function x(){})[-6] == 'x') {
		self.browser.v = 2;
	    } else if (!window.JSON) {
		self.browser.v = 3;
	    } else {
		self.browser.v = 3.5;
	    }
	} else if (/a/.__proto__ == '//') {
	    self.browser.name = 'S';
	} else if (/source/.test((/a/.toString+''))) {
	    self.browser.name = 'C';
	} else {
	    self.browser.name = 'O';
	    if (!document.designMode) {
		self.browser.v = 8;
	    } else {
		self.browser.v = 9;
	    }
	}
    };
    self.AJAX = {
	process: function() {
	    var xhr = (self.browser.name == 'IE' && self.browser.v <= 6) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
	    var a = arguments[0];
	    a.async = a.async || true;
	    a.params = a.params || null;
	    a.onProcess = a.onProcess || null;
	    a.onComplete = a.onComplete || null;
	    a.onError = a.onError || null;
	    if (xhr) {
		if (a.method == 'GET') {
		    a.url += ((a.url.match(/\?/)) ? '&' : '?')+'_='+Math.random();
		}
		xhr.open(a.method, a.url, a.async);
		xhr.setRequestHeader('Cookie', (document.cookie.length == 0) ? 'null' : document.cookie);
		xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
		xhr.onreadystatechange = function() {
		    if (xhr.readyState == 1) {
			if (a.onProcess) a.onProcess();
		    } else if (xhr.readyState == 4) {
			if (xhr.status == 200) {
			    if (a.onComplete) a.onComplete(xhr.responseText, xhr.getAllResponseHeaders());
			} else {
			    if (a.onError) a.onError(xhr.status);
			}
		    }
		}
		if (a.method == 'POST') {
		    xhr.send(((a.params == null) ? '' : a.params+'&')+'_='+Math.random());
		} else {
		    xhr.send(null);
		}
		return true;
	    } else {
		if (a.onError) a.onError('500');
		return false;
	    }
	}
    };
    self.Array = {
	inArray: function(needle, haystack) {
	    var found = false, key, strict = (arguments[2]) ? true : false;
	    for (key in haystack) {
		if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
		    found = true;
		    break;
		}
	    }
	    return found;
	},
	keyExists: function(key, search) {
	    return key in search;
	},
	search: function(needle, haystack) {
	    var strict = !!arguments[2];
	    for (var key in haystack) {
		if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
		    return key;
		}
	    }
	    return false;
	}
    };
    self.Document = {
	walkDOM: function(node, func) {
	    func(node);
	    node = node.firstChild;
	    while (node) {
		self.Document.walkDOM(node, func);
		node = node.nextSibling;
	    }
	},
	getElementsByClassName: function(className) {
	    var results = [];
	    self.Document.walkDOM(document.body, function(node) {
		var a, c = node.className, i;
		if (c) {
		    a = c.split(' ');
		    for (i = 0; i < a.length; i++) {
			if (a[i] === className) {
			    results.push(node);
			    break;
			}
		    }
		}
	    });
	    return results;
	},
	getElementCoords: function(obj) {
	    var t = 0, l = 0;
	    while (obj.offsetParent) {
		t += obj.offsetTop;
		l += obj.offsetLeft;
		obj = obj.offsetParent;
	    }
	    return {left: l, top: t};
	},
	getDocumentSize: function() {
	    with (document) {
		var w = Math.max(
		    Math.max(body.scrollWidth, documentElement.scrollWidth),
		    Math.max(body.offsetWidth, documentElement.offsetWidth),
		    Math.max(body.clientWidth, documentElement.clientWidth)
		);
		var h = Math.max(
		    Math.max(body.scrollHeight, documentElement.scrollHeight),
		    Math.max(body.offsetHeight, documentElement.offsetHeight),
		    Math.max(body.clientHeight, documentElement.clientHeight)
		);
	    }
	    return {width: w, height: h};
	},
	getElementStyle: function(obj, css_rule) {
	    var s = '';
	    if (document.defaultView && document.defaultView.getComputedStyle) {
		s = document.defaultView.getComputedStyle(obj, '').getPropertyValue(css_rule);
	    } else if (obj.currentStyle) {
		css_rule = css_rule.replace(/\-(\w)/g, function(m, p) {
			return p.toUpperCase();
		});
		s = obj.currentStyle[css_rule];
	    }
	    return s;
	},
	getCookie: function(name) {
	    var c = document.cookie.split(';'), ca = [];
	    for (var i in c) {
		ca.push({name: c[i].split('=')[0].replace(/\s/, ''), value: c[i].split('=')[1]});
	    }
	    if (name) {
		var r = false;
		for (var i in ca) {
		    if (ca[i].name == name) {
			r = ca[i].value;
			break;
		    }
		}
		return r;
	    } else {
		return ca;
	    }
	},
	setCookie: function(name, value, expires, path, domain, secure) {
	    if (expires instanceof Date) {
		expires = expires.toGMTString();
	    } else if (typeof expires == 'number') {
		expires = (new Date(+(new Date) + expires * 1e3)).toGMTString();
	    }
	    var r = [name + '=' + value], s, i;
	    for (i in s = {expires: expires, path: path, domain: domain}) {
		s[i] && r.push(i + '=' + s[i]);
	    }
	    return secure && r.push('secure'), document.cookie = r.join(';'), true;
	}
    };
    self.Effects = {
	setOpacity: function(obj, value) {
	    if (self.browser.name == 'IE' && obj.style.width == '') {
		obj.style.width = obj.offsetWidth+'px';
	    }
	    if (self.browser.name == 'IE' && obj.style.height == '') {
		obj.style.height = obj.offsetHeight+'px';
	    }
	    obj.style.opacity = value/10;
	    obj.style.filter = 'alpha(opacity='+(value*10)+')';
	    return true;
	},
	FadeTransparent: {
	    Faders: [],
	    setup: function(obj, params, direction) {
		var speed = params && params.speed || 30;
		var stop = params && params.stop || 10;
		if (obj === document.body) {
		    for (var i = 0; i < document.body.childNodes.length; i++) {
			var n = document.body.childNodes[i].nodeName;
			if (n == 'SELECT' || n == 'OBJECT' || n == 'EMBED') {
			    document.body.childNodes[i].style.visibility = 'hidden';
			}
		    }
		    var colour = params && params.colour || '000';
		    var start = params && params.start || 0;
		    var z = params && params.z || 90;
		    var mask = document.createElement('div');
		    mask.id = 'FadeMask'+Math.ceil(Math.random()*10000);
		    mask.style.position = 'absolute';
		    mask.style.zIndex = z;
		    mask.style.top = '0px';
		    mask.style.left = '0px';
		    mask.style.height = self.Document.getDocumentSize()['height']+'px';
		    mask.style.width = (self.Document.getDocumentSize()['width']-((self.browser.name == 'IE' && self.browser.v <= 6) ? 20 : 0))+'px';
		    self.Event.add(window, 'resize', function(){
			mask.style.width = (self.Document.getDocumentSize()['width']-((self.browser.name == 'IE' && self.browser.v <= 6) ? 20 : 0))+'px';
			mask.style.height = self.Document.getDocumentSize()['height']+'px';
		    });
		    document.body.appendChild(mask);
		    self.Effects.FadeTransparent.Faders.push({colour: colour, fader_id: null, mask: mask, speed: speed, start: start, stop: stop});
		} else {
		    var start = (direction == 'in') ? params && params.start || 0 : params && params.start || 10;
		    self.Effects.FadeTransparent.Faders.push({fader_id: null, speed: speed, start: start, stop: stop});
		}
		obj.fader_id = self.Effects.FadeTransparent.Faders.length-1;
		return obj.fader_id;
	    },
	    fadeOut: function(obj, params) {
		var F = self.Effects.FadeTransparent;
		var id = F.setup(obj, params);
		if (obj === document.body) {
		    F.Faders[id].fader_id = setTimeout(function(){runOut(F.Faders[id].mask, id);}, F.Faders[id].speed);
		} else {
		    F.Faders[id].fader_id = setTimeout(function(){runOut(obj, id);}, F.Faders[id].speed);
		}
		var runOut = function(obj, id) {
		    var F = self.Effects.FadeTransparent.Faders[id];
		    if (obj === F.mask) {
			obj.style.backgroundColor = '#'+F.colour;
			if (F.start < F.stop) {
			    F.start++;
			    self.Effects.setOpacity(obj, F.start);
			    F.fader_id = setTimeout(function(){runOut(obj, id);}, F.speed);
			} else {
			    clearTimeout(F.fader_id);
			    F.fader_id = null;
			}
		    } else {
			if (F.start > 0) {
			    F.start--;
			    self.Effects.setOpacity(obj, F.start);
			    F.fader_id = setTimeout(function(){runOut(obj, id);}, F.speed);
			} else {
			    clearTimeout(F.fader_id);
			    F.fader_id = null;
			}
		    }
		    return true;
		};
		return true;
	    },
	    fadeIn: function(obj, params) {
		var F = self.Effects.FadeTransparent;
		if (typeof obj.fader_id != 'undefined') {
		    if (F.Faders[obj.fader_id].fader_id == null) {
			if (obj === document.body) {
			    for (var i = 0; i < document.body.childNodes.length; i++) {
				var n = document.body.childNodes[i].nodeName;
				if (n == 'SELECT' || n == 'OBJECT' || n == 'EMBED') {
				    document.body.childNodes[i].style.visibility = 'visible';
				}
			    }
			    F.Faders[obj.fader_id].fader_id = setTimeout(function(){runIn(F.Faders[obj.fader_id].mask, obj.fader_id);}, F.Faders[obj.fader_id].speed);
			} else {
			    F.Faders[obj.fader_id].fader_id = setTimeout(function(){runIn(obj, obj.fader_id);}, F.Faders[obj.fader_id].speed);
			}
		    } else {
			setTimeout(function(){F.fadeIn(obj, params);}, 100);
		    }
		} else {
		    var id = F.setup(obj, params, 'in');
		    if (obj === document.body) {
			F.Faders[obj.fader_id].fader_id = setTimeout(function(){runIn(F.Faders[obj.fader_id].mask, obj.fader_id);}, F.Faders[obj.fader_id].speed);
		    } else {
			F.Faders[id].fader_id = setTimeout(function(){runIn(obj, id);}, F.Faders[id].speed);
		    }
		}
		var runIn = function(obj, id) {
		    var F = self.Effects.FadeTransparent.Faders[id];
		    if (obj === F.mask) {
			obj.style.backgroundColor = '#'+F.colour;
			if (F.start > 0) {
			    F.start--;
			    self.Effects.setOpacity(obj, F.start);
			    F.fader_id = setTimeout(function(){runIn(obj, id);}, F.speed);
			} else {
			    document.body.removeChild(F.mask);
			    clearTimeout(F.fader_id);
			}
		    } else {
			if (F.start < F.stop) {
			    F.start++;
			    self.Effects.setOpacity(obj, F.start);
			    F.fader_id = setTimeout(function(){runIn(obj, id);}, F.speed);
			} else {
			    clearTimeout(F.fader_id);
			}
		    }
		    return true;
		};
		return true;
	    }
	},
	showTip: function(obj, tip, func) {
	    var container = document.createElement('div');
	    container.className = 'tip';
	    container.id = 'o_O_tip';
	    container.innerHTML = tip;
	    document.body.appendChild(container);
	    container.style.top = (self.Document.getElementCoords(obj).top+20)+'px';
	    container.style.left = self.Document.getElementCoords(obj).left+'px';
	    if (func && typeof(func) == 'function') {
		func();
	    }
	    return true;
	},
	closeTip: function() {
	    document.body.removeChild(document.getElementById('o_O_tip'));
	    return true;
	}
    };
    self.Event = {
	get: function(e) {
	    return window.event || e;
	},
	getObj: function(e) {
	    return e.srcElement || e.target;
	},
	add: function(element, type, handler) {
	    if (!handler.guid) handler.guid = self.Event.add.guid++;
	    if (!element.events) element.events = {};
	    var handlers = element.events[type];
	    if (!handlers) {
		handlers = element.events[type] = {};
		if (element['on' + type]) {
		    handlers[0] = element['on' + type];
		}
	    }
	    handlers[handler.guid] = handler;
	    element['on' + type] = self.Event.handle;
	},
	remove: function(element, type, handler) {
	    if (element.events && element.events[type]) {
		delete element.events[type][handler.guid];
	    }
	},
	handle: function(event) {
	    var returnValue = true;
	    event = event || self.Event.fix(window.event);
	    var handlers = this.events[event.type];
	    for (var i in handlers) {
		this.handleEvent = handlers[i];
		if (this.handleEvent(event) === false) {
		    returnValue = false;
		}
	    }
	    return returnValue;
	},
	fix: function(event) {
	    event.preventDefault = self.Event.preventDefault;
	    event.stopPropagation = self.Event.stopPropagation;
	    return event;
	},
	preventDefault: function() {
	    this.returnValue = false;
	},
	stopPropagation: function() {
	    this.cancelBubble = true;
	}
    };
    self.Window = {
	top: function() {
	    return typeof window.pageYOffset != 'undefined' ? window.pageYOffset : document.documentElement && document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ? document.body.scrollTop : 0;
	},
	left: function() {
	    return typeof window.pageXOffset != 'undefined' ? window.pageXOffset : document.documentElement && document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ? document.body.scrollLeft : 0;
	}
    };
}