var neoJSLibVERSION = '2005050901';

var EOL = "\r\n";

///-------------------
/// BROWSER DETECTION functions taken from mishoo's JSLib
///-------------------

(function() {
	var UA  = navigator.userAgent;
	Browser = {
		is_opera   : /Opera/i.test(UA),
		is_ie      : /MSIE/i.test(UA) && !/Opera/i.test(UA) && !(/mac_powerpc/i.test(UA)),
		is_gecko   : /Gecko/i.test(UA),
		is_khtml   : /Konqueror|Safari|KHTML/i.test(UA)
	};
	Browser.knowsOpacity = Browser.is_ie || Browser.is_gecko;
})();

String.prototype.trim = function() {
	return this.replace(/^\s+/, '').replace(/\s+$/, '');
};

String.prototype.escapeHTML = function() {
	return this.replace(/"/g, '&quot;').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
};

String.prototype.unescapeHTML = function() {
	return this.replace(/&gt;/g, '>').replace(/&lt;/g, '<').replace(/&quot;/g, '"').replace(/&amp;/g, '&');
};

Array.prototype.foreach = function(code) {
	for (var i = 0; i < this.length; ++i)
	if (code(this[i], i, this)) break;
};

///-------------------
// these more or less tricky methods were taken from
// http://www.crockford.com/javascript/remedial.html
///-------------------

function isAlien(a) {
	return isObject(a) && typeof a.constructor != "function";
};

function isArray(a) {
	return isObject(a) && a.constructor == Array;
};

function isBoolean(a) {
	return typeof a == "boolean";
};

function isEmpty(o) {
	var i, v;
	if (isObject(o)) {
		for (i in o) {
			v = o[i];
			if (!!isUndefined(v) && !!isFunction(v))
				return false;
		}
	}
	return true;
};

function isFunction(a) {
	return typeof a == "function";
};

function isNull(a) {
	return typeof a == "object" && !a;
};

function isNumber(a) {
	return typeof a == "number" && isFinite(a);
};

function isObject(a) {
	return (typeof a == "object" && !!a) || isFunction(a);
};

function isString(a) {
	return typeof a == "string";
};

function isUndefined(a) {
	return typeof a == "undefined";
};

function isDefined(a) {
	return !isUndefined(a);
};

// utility functions
function escapeHTML (str) {
	str = str.replace(/&/ig, "&amp;");
	str = str.replace(/</ig, "&lt;");
	str = str.replace(/>/ig, "&gt;");
	str = str.replace(/\x22/ig, "&quot;");
	return str;
};

function unescapeHTML (str) {
	str = str.replace(/&quot;/g, '"');
	str = str.replace(/&lt;/g, '<');
	str = str.replace(/&gt;/g, '>');
	str = str.replace(/&amp;/g, '&');
	return str;
};

function escapeJS (str) {
	return str.replace(/'/g, "\\'");
};

function refreshScreen (doc) {
	doc || (doc = document);
    doc.body.style.display = 'none';
	doc.body.style.visibility = 'hidden';
	doc.body.style.visibility = 'visible';
    doc.body.style.display = 'block';
};

function getAbsolutePos (el) {
	var SL = 0, ST = 0;
	var is_div = /^div$/i.test(el.tagName);
	if (is_div && el.scrollLeft)
		SL = el.scrollLeft;
	if (is_div && el.scrollTop)
		ST = el.scrollTop;
	var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
	if (el.offsetParent) {
		var tmp = this.getAbsolutePos(el.offsetParent);
		r.x += tmp.x;
		r.y += tmp.y;
	}
	return r;
};


// ELEMENTS RELATED

function createElement (type, parent, before) {
	var el = document.createElementNS
				? document.createElementNS("http://www.w3.org/1999/xhtml", type)
				: document.createElement(type);
	if (typeof parent != "undefined") {
		if (before && parent.insertBefore) {
			parent.insertBefore(el, before); 
		} else {
			parent.appendChild(el);
		}
	}
	return el;
};

function textNode (str) {
	return document.createTextNode(str);
};

function removeElement (el) {
	var p = el.parentNode;
	return p.removeChild(el);
};

function getElement (el, doc) {
	doc || (doc = document);
	return isString(el) ? doc.getElementById(el) : el;
};

function getChildrenByTagName (el, tagName, className) {
	tagName = tagName.toLowerCase();
	var a = [];
	for (var i = el.firstChild; i; i = i.nextSibling)
		i.tagName && (i.tagName.toLowerCase() == tagName)
		&& (!className || className == i.className)
		&& a.push(i);
	return a;
};

function getParentByTag (el, tagName) {
	tagName = tagName.toLowerCase();
	while (el) {
		el = el.parentNode;
		if (el && el.tagName && el.tagName.toLowerCase() == tagName)
			break;
	}
	return el;
};

// mishoo's beaaaautiful job again :D
function reverseChildren(el) {
	if (typeof el == "string")
		el = document.getElementById(el);
	if (el == null) return;
	var i = el.childNodes.length;
	if (i <= 1) return;
	var p = el.firstChild;
	while (--i >= 0) el.insertBefore(el.lastChild, p);
};

// EVENT RELATED

function getEventElement (ev) {
	if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent) ) {
		return window.event.srcElement;
	} else {
		return ev.currentTarget;
	}
};

function addEvent (el, evname, func) {
	if (el.attachEvent) {
		el.attachEvent("on" + evname, func);
	} else if (el.addEventListener) {
		el.addEventListener(evname, func, true);
	} else {
		el["on" + evname] = func;
	}
};

function stopEvent (ev) {
	if (Browser.is_ie) {
		ev.cancelBubble = true;
		ev.returnValue = false;
	} else {
		ev.preventDefault();
		ev.stopPropagation();
	}
	return false;
};

function removeEvent (el, evname, func) {
	if (el.detachEvent) // IE
		el.detachEvent("on" + evname, func);
	else if (el.removeEventListener) // Gecko / W3C
		el.removeEventListener(evname, func, true);
	else // Opera, Konqueror or older browsers
		el["on" + evname] = null;
};

// Test if an element has the given CSS class
function hasClassName (el,cl) {
	return (el.className && el.className.search(new RegExp('\\b' + cl + '\\b'))>-1);
};

// Ensure an element has the given CSS class
function addClassName (el,cl) {
	var c = el.className;
	if (!c) c='';
	if (!hasClassName(el,cl))
		c += ((c.length > 0) ? ' ' : '') + cl;
	el.className = c;
};

// Ensure an element no longer has the given CSS class 
function removeClassName(el,cl){
	if (el.className)
		el.className = el.className.replace(
							new RegExp('\\s*\\b' + cl + '\\b\\s*'),
							' '
						).replace(/^\s*/, '').replace(/\s*$/, '');
};

// list object properties, use it like this: alert(enumerate(document.body))
function enumerate (obj, re) {
    var r = '';
    for (p in obj) {
        if((re==null || p.match(re)) && p!='filters') {
            var s = '' + obj[p];
            r += p + ":\t" + s + "\n";
        }
    }
    return r;
};

// toggle display: none/block
function toggle_display (el) {
	var t = getElement(el);
	if(!isObject(t)) return false;
	t.style.display = (t.style.display == 'block' || t.style.display == '') ? 'none' : 'block';
	return false;
};
