/* library.js - Library
**
** $Id: library.js 158 2009-06-29 18:57:27Z mcnelis $
**
** Copyright 2007-2009, CloseTies, Inc. All Rights Reserved.
*/

/******************************************************************************/

window.$ = (window.$||function() {});

/********************************************************************************/

function bind(obj, method) {
	var args = [];
	for (var arg = 2; arg < arguments.length; arg++) {
		args.push(arguments[arg]);
	}
	return function() {
		var _obj = obj || this;
		var _args = args.slice();
		for (var jj = 0; jj < arguments.length; jj++) {
			_args.push(arguments[jj]);
		}
		if (typeof(method) == "string") {
			if (_obj[method]) {
				return _obj[method].apply(_obj, _args);
			}
		} else {
			return method.apply(_obj, _args);
		}
	};
}

/********************************************************************************/

Function.prototype.bind = function(context) {
	var argv = [arguments[0], this];
	var argc = arguments.length;
	for (var arg = 1; arg < argc; arg++) {
		argv.push(arguments[arg]);
	}
	return bind.apply(null, argv);
};

/********************************************************************************/

function copyproperties(d, s) {
	for (var prop in s) {
		d[prop] = s[prop];
	}
	return d;
}

/********************************************************************************/

function isArray(obj) {
 	if (obj.constructor.toString().indexOf("Array") == -1) {
		return false;
 	}
	else {
		return true;
 	}
}

/********************************************************************************/

$.$id = function(id, doc) {
	if (typeof(id) == 'undefined') {
		$.error('Can\'t find undefined element!');
		return null;
	}
	var obj;
	if (typeof(id) == 'string') {
		if (!doc) {
			doc = document;
		}
		obj = doc.getElementById(id);
		if (! ($.ua.ie >= 7)) {
			return obj;
		}
		if (!obj) {
			return null;
		} else if (typeof(obj.id) == 'string' && obj.id == id) {
			return obj;
		} else {
			var candidates = doc.getElementsByName(id);
			if (!candidates || !candidates.length) {
				return null;
			}
			var maybe = [];
			for (var elem = 0; elem < candidates.length; elem++) {
				var c = candidates[elem];
				if (!c.id && id) {
					continue;
				}
				if (typeof(c.id) == 'string' && c.id != id) {
					continue;
				}
				maybe.push(candidates[elem]);
			}
			if (maybe.length != 1) {
				$.error('Can\'t find element!');
				return null;
			}
			return maybe[0];
		}
	} else {
		return id;
	}
	return null;
};

/********************************************************************************/

$.$class = function(className, tag, doc) {
	var tag = tag || "*";
	var elm = doc || document;
	var elements = (tag == '*' && elm.all) ? elm.all: elm.getElementsByTagName(tag);
	var arr = [];
	var delim = className.indexOf('|') != -1 ? '|': ' ';
	var arrClass = className.split(delim);
	var j = elements.length;
	for (var i = 0; i < j; i++) {
		if (elements[i].className == undefined) continue;
		var arrObjClass = elements[i].className.split(' ');
		if (delim == ' ' && arrClass.length > arrObjClass.length) continue;
		var c = 0;
		comparison: {
			var l = arrObjClass.length;
			for (var k = 0; k < l; k++) {
				var n = arrClass.length;
				for (var m = 0; m < n; m++) {
					if (arrClass[m] == arrObjClass[k]) c++;
					if ((delim == '|' && c == 1) || (delim == ' ' && c == arrClass.length)) {
						arr.push(elements[i]);
						break comparison;
					}
				}
			}
		}
	}
	return arr;
};

/********************************************************************************/

$.$tag = function(tag, doc) {
	var elm = doc || document;
	return elm.getElementsByTagName(tag);
};

/********************************************************************************/

$.framedocument = function(id) {
	var frame;
	var doc;

	if (document.frames) {
		// For IE5 Mac
		frame = document.frames[id];
	} else {
		frame = $.$id(id);
	}

	if (frame.contentDocument) {
		// For NS6
		doc = frame.contentDocument;
	} else if (frame.contentWindow) {
		// For IE5.5 and IE6
		doc = frame.contentWindow.document;
	} else if (frame.document) {
		// For IE5
		doc = frame.document;
	} else {
		doc = undefined;

	}
	return doc;
};

/********************************************************************************/

$.isDescendantOf = function(elem,ancestor) {
	if (!elem) return false;
	if (!ancestor) return false;
	if (elem == ancestor) return false;
	if (!elem.parentNode) return false;
	var e = elem.parentNode;
	while (true) {
		if (e == ancestor) return true;
		if (e == document) return false;
		if (!e.parentNode) return true;
		e = e.parentNode;
	}
	return false; 
};
/********************************************************************************/

$.show = function() {
	for (var i = 0; i < arguments.length; i++) {
		var element = $.$id(arguments[i]);
		if (element && element.style) element.style.display = '';
	}
	return false;
};

/********************************************************************************/

$.hide = function() {
	for (var i = 0; i < arguments.length; i++) {
		var element = $.$id(arguments[i]);
		if (element && element.style) element.style.display = 'none';
	}
	return false;
};

/********************************************************************************/

$.shown = function(el) {
	el = $.$id(el);
	return (el.style.display != 'none');
};

/********************************************************************************/

$.toggle = function() {
	for (var i = 0; i < arguments.length; i++) {
		var element = $.$id(arguments[i]);
		element.style.display = $.getstyle(element, "display") == 'block' ? 'none': 'block';
	}
	return false;
};

/********************************************************************************/

$.visable = function() {
	for (var i = 0; i < arguments.length; i++) {
		var element = $.$id(arguments[i]);
		if (element && element.style) element.style.visibility = 'visible';
	}
	return false;
};

/********************************************************************************/

$.invisable = function() {
	for (var i = 0; i < arguments.length; i++) {
		var element = $.$id(arguments[i]);
		if (element && element.style) element.style.visibility = 'hidden';
	}
	return false;
};

/********************************************************************************/

$.showvisable = function() {
	for (var i = 0; i < arguments.length; i++) {
		var element = $.$id(arguments[i]);
		if (element && element.style) element.style.display = '';
		if (element && element.style) element.style.visibility = 'visible';
	}
	return false;
};

/********************************************************************************/

$.hideinvisable = function() {
	for (var i = 0; i < arguments.length; i++) {
		var element = $.$id(arguments[i]);
		if (element && element.style) element.style.visibility = 'hidden';
		if (element && element.style) element.style.display = 'none';
	}
	return false;
};

/********************************************************************************/

$.getstyle = function(object, prop) {
	function hyphenate(prop) {
		return prop.replace(/[A-Z]/g,
		function(match) {
			return '-' + match.toLowerCase();
		});
	}
	if (window.getComputedStyle) {
		return window.getComputedStyle(object, null).getPropertyValue(hyphenate(prop));
	}
	if (document.defaultView && document.defaultView.getComputedStyle) {
		var computedStyle = document.defaultView.getComputedStyle(object, null);
		if (computedStyle) return computedStyle.getPropertyValue(hyphenate(prop));
		if (prop == "display") return "none";
		$.error("Can't get " + prop + " style");
	}
	if (object.currentStyle) {
		return object.currentStyle[prop];
	}
	return object.style[prop];
};

/********************************************************************************/

$.focus = function(el) {
	el = $.$id(el);
	el.focus();
	return;
};

/********************************************************************************/

$.info = function(func, message) {
	if (window.Debug) {
		Debug.log(Debug.typeInfo, '', func, message);
	}
};

/********************************************************************************/

$.warning = function(func, message) {
	if (window.Debug) {
		Debug.log(Debug.typeWarning, '', func, message);
	}
};

/********************************************************************************/

$.error = function(func, message) {
	if (window.Debug) {
		Debug.log(Debug.typeError, '', func, message);
	}
};

/********************************************************************************/

$.addslashes = function(str) {
	return (((str.replace(/\'/g,'\\\'')).replace(/\"/g,'\\"')).replace(/\\/g,'\\\\')).replace(/\0/g,'\\0');
};

/********************************************************************************/

$.stripslashes = function(str) {
	return (((str.replace(/\\'/g,'\'')).replace(/\\"/g,'"')).replace(/\\\\/g,'\\')).replace(/\\0/g,'\0');
};

/********************************************************************************/

$.setcookie = function(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = '; expires='+date.toGMTString();
	}
	else var expires = '';
	document.cookie = name+'='+value+expires+'; path=/';
};

/********************************************************************************/

$.getcookie = function(name) {
	var nameEQ = name + '=';
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
};

/********************************************************************************/

$.deletecookie = function(name) {
	$.setcookie(name,'',-1);
};

/********************************************************************************/

$.ua = function() {}

$.ua.ie = NaN;
$.ua.firefox = NaN;
$.ua.opera = NaN;
$.ua.safari = NaN;
$.ua.windows = NaN;
$.ua.osx = NaN;

/********************************************************************************/

$.ua.detect = function() {
	var agent = /(?:MSIE.(\d+\.\d+))|(?:(?:Firefox|GranParadiso).(\d+\.\d+))|(?:Opera.(\d+\.\d+))|(?:AppleWebKit.(\d+(?:\.\d+)?))/.exec(navigator.userAgent);
	var os = /(Mac OS X)|(Windows)/.exec(navigator.userAgent);
	if (agent) {
		this.ie = agent[1] ? parseFloat(agent[1]) : NaN;
		this.firefox = agent[2] ? parseFloat(agent[2]) : NaN;
		this.opera = agent[3] ? parseFloat(agent[3]) : NaN;
		this.safari = agent[4] ? parseFloat(agent[4]) : NaN;
	} else {
		this.ie = NaN;
		this.firefox = NaN;
		this.opera = NaN;
		this.safari = NaN;
	}
	if (os) {
		this.windows = !!os[2];
	} else {
		this.osx = false;
		this.windows = false;
	}
};

/********************************************************************************/

$.ua.behaviors = function() {
	if ($.ua.safari < 500) {
		$.loadqueue($.ua.safarilabels);
	}
	if ($.ua.ie < 7) {
		try {
			document.execCommand('BackgroundImageCache', false, true);
		} catch(ignored) {}
	}
};

/********************************************************************************/

$.ua.safarilabels = function() {
	if ($.ua.safari < 500) {
		var labels = (base || document.body).getElementsByTagName("label");
		for (i = 0; i < labels.length; i++) {
			labels[i].addEventListener('click', $.ua.safarilabelaction, true);
		}
	}
};

/********************************************************************************/

$.ua.safarilabelaction = function() {
	var id = this.getAttribute('for');
	var item = null;
	if (id) {
		item = document.getElementById(id);
	} else {
		item = this.getElementsByTagName('input')[0];
	}
	if (!item || event.srcElement == item) {
		return;
	}
	if (item.type == 'checkbox') {
		item.checked = !item.checked;
	} else if (item.type == 'radio') {
		var radios = document.getElementsByTagName('input');
		for (i = 0; i < radios.length; i++) {
			if (radios[i].name == item.name && radios[i].form == item.form) {
				radios.checked = false;
			}
		}
		item.checked = true;
	} else {
		item.focus();
	}
	if (item.onclick) {
		item.onclick(event);
	}
};

/********************************************************************************/

$.chain = function(u, v) {
	var calls = [];
	for (var arg = 0; arg < arguments.length; arg++) {
		calls.push(arguments[arg]);
	}
	return function() {
		for (var arg = 0; arg < calls.length; arg++) {
			if (calls[arg] && calls[arg].apply(null, arguments) === false) {
				return false;
			}
		}
		return true;
	}
};

/********************************************************************************/

$.loadqueue = function(handler) { (window.loaded ? $.runhandler(handler) : $.enqueue('loadqueue', handler));
};

/********************************************************************************/

$.postloadqueue = function(handler) { (window.loaded ? $.runhandler(handler) : $.enqueue('postloadqueue', handler));
};

/********************************************************************************/

$.preunloadqueue = function(handler) {
	$.enqueue('preunloadqueue', handler);
};

/********************************************************************************/

$.unloadqueue = function(handler) {
	$.enqueue('unloadqueue', handler);
};

/********************************************************************************/

$.runloadhandlers = function() {
	$.runhandlers('loadqueue');
	window.loaded = true;
};

/********************************************************************************/

$.runpostloadhandlers = function() {
	$.runhandlers('postloadqueue');
};

/********************************************************************************/

$.runpreunloadhandlers = function() {
	var warn;
	if (! (warn = $.runhandlers('preunloadqueue'))) {
		window.loaded = false;
	}
	return warn;
};

/********************************************************************************/

$.rununloadhandlers = function() {
	$.runhandlers('unloadqueue');
};

/********************************************************************************/

$.runhandler = function(handler) {
	try {
		handler();
	} catch(ex) {
		$.error('Uncaught exception in handler: ' + ex.toString());
	}
};

/********************************************************************************/

$.runhandlers = function(queue) {
	if (queue == 'preunloadqueue') {
		var warn = false;
		if (window[queue]) {
			for (var handler = 0; handler < window[queue].length; handler++) {
				try {
					warn = (warn || window[queue][handler]());
				} catch(ex) {
					$.error('Uncaught exception in handler: ' + ex.toString());
				}
			}
			window[queue] = [];
		}
		if (warn) {
			return warn;
		} else {
			window.exiting = true;
		}
	} else {
		if (window[queue]) {
			for (var handler = 0; handler < window[queue].length; handler++) {
				try {
					window[queue][handler]();
				} catch(ex) {
					$.error('Uncaught exception in handler: ' + ex.toString());
				}
			}
			window[queue] = [];
		}
	}
};

/********************************************************************************/

$.enqueue = function(queue, handler) { (window[queue] ? window[queue] : (window[queue] = [])).push(handler);
};

/********************************************************************************/

$.initqueues = function() {
	if (document.addEventListener) {
		if ($.ua.safari) {
			var timeout = setInterval(function() {
				if (/loaded|complete/.test(document.readyState)) { (window.Debug && (Debug.domloaded = (new Date()).getTime()));
					$.runloadhandlers();
					clearTimeout(timeout);
				}
			},
			3);
		} else {
			document.addEventListener("DOMContentLoaded",
			function() { (window.Debug && (Debug.domloaded = (new Date()).getTime()));
				$.runloadhandlers();
			},
			true);
		}
	} else {
		var src = 'javascript:void(0)';
		if (window.location.protocol == 'https:') {
			src = '//:';
		}
		document.write('<script onreadystatechange="if (this.readyState==\'complete\') {' + '(window.Debug&&(Debug.domloaded=(new Date()).getTime()));' + 'this.parentNode.removeChild(this);$.runloadhandlers();}" defer="defer" ' + 'src="' + src + '"><\/script\>');
	}
	window.onload = $.chain(window.onload,
	function() { (window.Debug && (Debug.layout = (new Date()).getTime()));
		var force = document && document.body && document.body.offsetWidth; (window.Debug && (Debug.onload = (new Date()).getTime()));
		$.runloadhandlers();
		$.runpostloadhandlers();
	});
	window.onbeforeunload = function() {
		return $.runpreunloadhandlers();
	};
	window.onunload = $.chain(window.onunload,
	function() {
		$.rununloadhandlers();
	});
};

/********************************************************************************/

$.ua.detect();
$.initqueues();
$.ua.behaviors();
if (! ($.ua.firefox < 1.5)) {
	//document.domain='closeties.com';
}