 
/* 
 * Toolbelt Javascript Library 
  
 * http://tbelt 
 * Created by Stephen Rushing, eSiteful 
 * Compiled Mon 12/14/2009, 15:40:15.94 
 */ 
  

if (!Array.indexOf) {
    Array.prototype.indexOf = function(arr){
        for (var i = 0; i < this.length; i++) {
            if (this[i] == arr) {
                return i;
            }
        }
        return -1;
    }
}

if (!Array.indexesOf) {
    Array.prototype.indexesOf = function(arr){
        var idxs = [];
		for (var i = 0; i < this.length; i++) {
            if (this[i] == arr) {
               idxs.push(i);
            }
        }
        return idxs;
    }
}

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to){
	var rest = this.slice((to || from) + 1 || this.length);
	this.length = from < 0 ? this.length + from : from;
	return this.push.apply(this, rest);
};




/* STRING EXTENSIONS */
String.prototype.trim = function(){
    return this.replace(/^\s+|\s+$/g, '');
}

String.prototype.toTitleCase = function(){
    var regex = /(^[a-z]|\b[a-z])/g;
    var returnString = this.replace(regex, makeTitle);
    function makeTitle(){
        return arguments[0].toUpperCase();
    }
    return returnString;
}

String.prototype.setCharAt = function(index,chr) {
	if(index > this.length-1) return str;
	return this.substr(0,index) + chr + this.substr(index+1);
}


if (document.__defineGetter__ && !HTMLElement.outerHTML) {
    HTMLElement.prototype.__defineGetter__("outerHTML", function(){
        var emptyTags = {
		   "img":   true,
		   "br":    true,
		   "input": true,
		   "meta":  true,
		   "link":  true,
		   "param": true,
		   "hr":    true
		};

		var attrs = this.attributes,
		tagName = this.tagName.toLowerCase(),
		str = "<" + tagName;
		for (var a = 0; a < attrs.length; a++)
		  str += " " + attrs[a].name + "=\"" + attrs[a].value + "\"";

		if (emptyTags[tagName])
		  return str + "/>";
		
		return str + ">" + this.innerHTML + "</" + tagName + ">";

    });
}






function trace(msg, priority){
	//console.log(!console);
	if (!window["console"]) {
    	//tbelt.createConsole();
	}
	if (priority == null) {
        priority = 1;
    }
    if (debugMode >= priority) {        
        console.log(msg);
    }
}


window.mouseY=0;
window.mouseX=0;
jQuery(document).mousemove(function(evt){
	window.mouseX = evt.pageX;
	window.mouseY = evt.pageY;
});	



(function($j){

	var window=this,
	undefined=undefined;
	
	window["tbelt"] = (function(){
		
		function tbelt(){
			
		
		}
		
		tbelt.prototype={
			debugMode:0,
			jQuery:$j,
			typeOf:function(obj){		
				//define the types
				var types = {
					Null: function(o){
						return o === null;
					},
					Undefined: function(o){
						return o === undefined;
					},        
					RegExp: function(o){
						//trace(constr + (typeof(o) === 'object' || typeof(o) === 'function') + (constr.match(/regexp/i)!=null));
						return (typeof(o) === 'object' || typeof(o) === 'function') ? (constr.match(/regexp/i)) !== null : false;
					},
					String: function(o){
						return (typeof(o) === 'string') ? true : (typeof(o) === 'object') ? constr.match(/string/i) !== null : false;
					},
					Array: function(o){
						return (typeof(o) === 'object') ? constr.match(/array/i) !== null : false;
					},
					Boolean: function(o){
						return (typeof(o) === 'boolean') ? true : (typeof(o) === 'object') ? constr.match(/boolean/i) !== null : false;
					},
					Date: function(o){
						return (typeof(o) === 'date') ? true : (typeof(o) === 'object') ? constr.match(/date/i) !== null : false;
					},
					HTML: function(o){
						return (typeof(o) === 'object') ? constr.match(/html/i) !== null : false;
					},
					Number: function(o){
						return (typeof(o) === 'number') ? true : (typeof(o) === 'object') ? constr.match(/number/i) !== null : false;
					},
					Window: function(o){
						 if(typeof(o) === 'object' &&o.self !=null && o.status!=null){
							return true;
						 }
						 else{
							return false;
						 }
					},
					Function: function(o){
						return (typeof(o) === 'function') ? constr.match(/function/i) !== null : false;
					},
					Object: function(o){
						return (typeof(o) === 'object') ? constr.match(/object/i) !== null : false;
					}
				}
				//figure out the type
				var constr = (obj && obj.constructor)?obj.constructor.toString():"null";
				for (var t in types) {       
					//trace(t + " : " +types[t](obj));
					if (types[t](obj)) {
						return t.toLowerCase();
					}
					
				}   
				
			}
		
		}

		
		return new tbelt();


	})();



	tbelt.console = (function(){
		function Console(){
			var I = this;
			I.jI = $j(I);
			if(!window["console"]){
				window["console"]=I;
				$j(function(){ I.init()});
			}
			else I.isNeeded=false;
			
		}
		
		Console.prototype={
			jI:null,
			className:"Console",
			isNeeded:true,
			element:"<div id='tbeltConsole'><div class='console-inner'><h6>tbelt console</h6><div class='console-messages'>{$messages}</div></div></div>",
			styles:"<style type='text/css'>#tbeltConsole {background:#fff;border:2px solid purple;font-size:11px;text-align:left;font-family:'courier new',serif;} #tbeltConsole .console-inner {padding:10px;} #tbeltConsole h6 {font-weight:bold;font-size:16px;color:purple;border-bottom:1px dotted purple;background:#F4D8EE;margin:0;padding:2px;} #tbeltConsole .message-block {border-bottom:1px solid #E8B0DD;padding:2px;}</style>",
			messages:[],
			init:function(){
				var I = this;
				if(tbelt.debugMode<=0){I.isNeeded=false; return;}
				I.element = $j(I.element);
				I.element.find(">div>div.console-messages").html("");
				I.styles = $j(I.styles);
				
				I.refresh();
				
			},
			log:function(msg){
				var I = this;
				if(tbelt.debugMode<=0)return;
				I.messages.push(msg.toString());
				I.refresh(I.messages.length-1);
				return I;
			},
			dir:function(obj){
				var I = this;
				if(tbelt.debugMode<=0)return;
				I.messages.push(obj.toString());
				I.refresh(I.messages.length-1);
				return I;
			},
			clear:function(){
				this.messages=[];
				this.refresh();
				return this;
			},
			refresh:function(fromIdx){
				var I = this;
				if(fromIdx==null) fromIdx=0;
				if(!I.element.jquery || !I.isNeeded || tbelt.debugMode<=0) return;
				else if(I.messages.length>0 && I.element.closest("body").length==0) $j("body").append([I.element[0], I.styles[0]]);
				var msgCont = I.element.find(">div>div.console-messages"),
				msgBlocks = msgCont.find("div.message-block");
				msgBlocks.filter(":gt("+fromIdx+")").remove();
				
				for(var i=fromIdx; i<I.messages.length;i++){
					msgCont.append("<div class='message-block'>"+i+": "+I.messages[i]+"</div>");
				}
				return I;
			}
		
		}
		
		return new Console();
	})();



})(jQuery);










	


tbelt.string = (function($j){

	function string(){
	
	}
	
	string.prototype={
		
		
		mesh:function(str, vars){
			var returnStr = str;
			for(var varName in vars){
				var varVal = (typeof(vars[varName])!="function") ? vars[varName] : arguments.callee.caller.apply(vars[varName]),
				regex = new RegExp("\\{\\s*?\\$"+varName+"\\s*?\\}","g");
				returnStr = returnStr.replace(regex, vars[varName]);
			}
			return returnStr;
		},
		 

		multiply:function(str, times){    
			if (times <= 0) return str;
			var returnStr = str;
			while (times > 0) {
				returnStr += str;
				times--;
			};
			return returnStr;
		},


		/**
		 * string.translate is similar to the XSLT translate function. 
		 * @param {Object} str Original string to translate.
		 * @param {Object} fromKey Original translation key (eg. 'abc').
		 * @param {Object} toKey Desired translation key (eg. 'cab').
		 * @return The str parameter with all characters replaced based on index comparisons of fromKey and toKey.
		 */
		translate:function(str, fromKey, toKey){
			var translated = str;
			//console.log(returnStr.replace(/(.)/g, "[$1]"));
			for(var f=0; f<str.length; f++){
				var tmpIdx = fromKey.indexOf(str[f]);
				if(tmpIdx>-1){
					//console.log(returnStr[f] + " : " +toKey[tmpIdx]);
					translated = translated.setCharAt(f, toKey.charAt(tmpIdx));
				}
			}
			return translated;
		},	



		charNodes:function(string, classPrefix, specialChars){
			var charNodes=string,regex;
			
			charNodes = charNodes.replace(/(\S)/ig, "<span class='" + (classPrefix||"") + "$1'>$1</span>");
			
			if(!specialChars) specialChars=[
					{c:".", r:"period"},
					{c:",", r:"comma"},
					{c:":", r:"colon"},
					{c:";", r:"semicolon"},
					{c:"'", r:"squo"},
					{c:"\"", r:"dbquo"},
					{c:"-", r:"dash"},
					{c:"+", r:"plus"},
					{c:"=", r:"equals"},
					{c:"?", r:"question"},
					{c:"!", r:"exclamation"},
					{c:"@", r:"at"},
					{c:"#", r:"hash"},
					{c:"$", r:"money"},
					{c:"%", r:"percent"},
					{c:"^", r:"caret"},
					{c:"&", r:"caret"},
					{c:"*", r:"asterisk"},
					{c:"(", r:"lparen"},
					{c:")", r:"rparen"}
				];
				
				
			for(var c=0; c<specialChars.length; c++){
				regex = new RegExp("class='" + (classPrefix||"") + "\\"+ specialChars[c].c, "g");		
				charNodes = charNodes.replace(regex, "class='"+ (classPrefix||"") +specialChars[c].r)
			}
			
			return charNodes;
			
		}
		
		
	
	}
	
	return new string();

})(tbelt.jQuery);









tbelt.num = (function($j){

	function num(){
	
	}
	
	num.prototype={
		
		
		random:function(min,max){
			return ((max-min)*Math.random())+(min);		
		},
		
		roundDecimal:function(num, dec){
			console.log("tbelt.num.roundDecimal() has been depricated. Use Number.toFixed() instead.");
			if(dec==null) dec=2;
			var result = Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
			return result;
		}
		
		
	
	}
	
	return new num();

})(tbelt.jQuery);






tbelt.array = (function($j){

	function array(){
	
	}
	
	array.prototype={
		
		clean:function(dirtyArray){
			var returnArray = [];
			for(var a=0;a<dirtyArray.length; a++){
				if(dirtyArray[a]!=null && dirtyArray[a]!=undefined && dirtyArray[a].toString().trim()!=""){
					returnArray.push(dirtyArray[a]);
				}
			}
			return returnArray;	
		},
		
		
		
		
		search:function(searchFor, arrayToSearch) {
			var returnArray = [];
			for (var f = 0; f < arrayToSearch.length; f++) {
				//trace(arrayToSearch[f] + " : " + tbelt.typeOf(arrayToSearch[f]) + " : " + searchFor);
				if (tbelt.typeOf(arrayToSearch[f])== "regexp" && arrayToSearch[f].test(searchFor)) {			
					returnArray.push(searchFor);
				}else if(arrayToSearch[f]==searchFor){
					returnArray.push(searchFor);
				}
			}
			return (returnArray.length>0)?returnArray:false;
		},
		
		
		
		searchObjects:function(objQuery, objArray, excludeObjects){
			var returnList = [];
			function isMatch(obj){		
				for (var prop in objQuery) {			
					if (obj[prop] != objQuery[prop]) return false;
					//trace(obj[prop] + " = " + objQuery[prop]);			
				}
				return true;
			}

			for (var obj = 0; obj < objArray.length; obj++) {
				if(!excludeObjects || excludeObjects.indexOf(objArray[obj])==-1){
					if(isMatch(objArray[obj]))
						returnList.push(objArray[obj]);
				}
			}
			
			return returnList;
		}
		
		
	
	}
	
	return new array();

})(tbelt.jQuery);





(function($j){

	tbelt.util = (function(){
	
		function util(){
		
		}
		
		util.prototype={
			
			XMLtoJSON:function(xml){

				var jsonObj = new Object();
				//convert a variable to float, bool, etc
				var convertValue=function(val, valName) {
					var returnVal = val;
					if ((/true|false/i).test(val)) {
						returnVal = (val == "true");
					} else if (!isNaN(parseFloat(val))&&valName!="ZipCode") {
						returnVal = parseFloat(val);
					}
					return returnVal;
				}
				//recursively build the JSON object
				var buildJSON=function(node, obj) {
					var parent = obj,
					obj = new Object(),
					attr, a, c, nodeText;
					//trace(node.nodeType + " : " + node.nodeName + " : " + node.nodeValue);
					//get node attributes
					if (node.attributes.length > 0) obj["attributes"] = new Object();
					for (a = 0; a < node.attributes.length; a++) {
						attr = node.attributes[a];
						obj.attributes[attr.name] = convertValue(attr.value);
					}
					var twins = $j(node).siblings(node.nodeName);
					//create an array if the node name is not unique
					if(twins.length>0){
						if(!parent[node.nodeName] || !parent[node.nodeName].length)parent[node.nodeName]=new Array();
						if($j(node).children("*").length>0) parent[node.nodeName].push(obj);
					}else{
						parent[node.nodeName]=obj;					
					}
					//get children
					for (c = 0; c < node.childNodes.length; c++) {
						var cNode = node.childNodes[c];
						//first make sure the node isn't the text value
						if (cNode.nodeType == 3 || cNode.nodeType == 4) {
							//trace(cNode);
							nodeText = cNode.nodeValue.trim();
							if (!(/^\s*$/).test(nodeText)) {
								if(parent[node.nodeName].length!=null) parent[node.nodeName].push(convertValue(nodeText, node.nodeName))
								else parent[node.nodeName] = convertValue(nodeText, node.nodeName); //trace("\t" + nodeText);
							}
						} 
						//otherwise keep traversing the node
						else {
							buildJSON(cNode, obj);
						}
					}

				}
				buildJSON(xml, jsonObj);
				//console.dir(jsonObj);
				return jsonObj;

			},
			
			cookie:function(name, value, options){

				if(arguments.length==2 && arguments[1]!=null && (arguments[1].expires || arguments[1].domain || arguments[1].path || arguments[1].secure)){
					options=arguments[1];
					value="{[GETCOOKIE]}";
				}
				
				options = $j.extend({
					expires:"",
					path:"",
					domain:"",
					secure:""
				}, options);	
				
				var today = new Date(),
				cookie=null;
			
				//delete cookie
				if(value==null && arguments.length>1){
					cookie = tbelt.util.cookie(name);
					if(cookie){
						options.expires = -10;
						tbelt.util.cookie(name, "", options);
					}
				}
				//set cookie value
				else if(value!=null && value!="{[GETCOOKIE]}"){
					var cookieStr = name+"="+escape(value);
					
					if(options.expires!="" && !isNaN(options.expires)) options.expires = new Date(today.getTime() + (1000 * 60 * 60 * 24 * options.expires)).toGMTString();
					
					for(var prop in options){				
						if(options[prop]!="") cookieStr+= ";"+prop+"="+options[prop];				
					}
					document.cookie = cookie = cookieStr;
				}
				//get cookie value
				else{
					var regex = new RegExp("(.*)?"+name+"=(.[^;]*);?(.*)?");
					value = document.cookie.replace(regex, "$2");
					if(value==document.cookie)value=null;
					else value = unescape(value);
				}
				//trace(value);
				return value;
			
			},
			
			
			/**
				@method timeSpan
				@param fromDate {Date} The starting date.
				@param toDate {Date} The ending date.
				@param format {String} A comma separated list of the formats to return, from greatest to least (years > months > weeks > days > hours > minutes > seconds > milliseconds).
				@sample timeSpan(new Date(2009,12,12), new Date(2008,1,17), "months,weeks,days");
				@author Stephen Rushing		
			*/
			timeSpan:function(fromDate, toDate, format){
				if(format==null) format="milliseconds";	
				var formatMS = {
					milliseconds:1,
					seconds:1000,
					minutes:1000*60,
					hours:1000*60*60,
					days:1000*60*60*24,
					weeks:1000*60*60*24*7,
					months:function(m){
						var ms = this.days,
						daysPer = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
						return ms*daysPer[m];
					},
					years:function(y){
						var ms = 1000*60*60*24*365;
						//add a day for leap years
						if( (y % 4 == 0 && y % 100 == 0) || y % 400 == 0 )
							ms += this.days;
						return ms;
					}
				},
				//get the time difference in milliseconds
				ms = toDate.getTime()-fromDate.getTime(),
				reqFormats = format.split(","),
				isYearReq = (format.indexOf("years")>-1),
				isMonthReq = (format.indexOf("months")>-1),
				result = {};
				
				if(isYearReq){ 
					result["years"]=0;
					for(var y=fromDate.getFullYear(); y <= toDate.getFullYear(); y++){	
						var yearMS = formatMS.years(y);
						if(ms >= yearMS){
							ms -= yearMS;
							result["years"]+=1;
						}
					}
					//use "to" year for calculating decimal
					formatMS.years = formatMS.years(toDate.getFullYear());
				}
				if(isMonthReq){
					result["months"]=0;
					var month = fromDate.getMonth(),
						year = (result["years"]>0) ? fromDate.getFullYear() + result["years"] : fromDate.getFullYear();					
					for(month; month<=11; month++){
						var monthMS = formatMS.months(month);
						if(month==toDate.getMonth() && year== toDate.getFullYear()) break;
						else if(ms >= monthMS){
							ms -= monthMS;
							result["months"]+=1;
						}
						if(month==12 && year < toDate.getFullYear()) {
							month=0; 
							year++;
						}
					}
					//use "to" month for decimal
					formatMS.months = formatMS.months(toDate.getMonth());
				}

				//handle the remaining milliseconds
				for(var f=0; f < reqFormats.length && reqFormats[0]!=""; f++){
					var res=(f<reqFormats.length-1) ? Math.floor(ms/formatMS[reqFormats[f]]) : ms/formatMS[reqFormats[f]];
					if(ms>0) result[reqFormats[f]] = (result[reqFormats[f]]>=0) ? result[reqFormats[f]]+=res : res;
					else result[reqFormats[f]]=0;

					ms -= res * formatMS[reqFormats[f]];
				}
				return result;
			}
		}
	
	
		return new util();
	})();
	


})(tbelt.jQuery);
(function($j){

	tbelt.util.Meshtml=function(opts){
		
		var I=this;
		I.jI = $j(I);
	
		I.options=opts;
		$j.extend(I, opts);
		
		$j(function(){I.init()});

	}

	tbelt.util.Meshtml.prototype={
		className:"Meshtml",
		jI:null,
		opts:null,
		elements:".mesh",
		template:"<div class='mesh-wrapper'>{$mesh}</div>",
		data:{},
		replaceMode:true,
		autoMesh:true,
		events:{
			EACH_START:"Meshtml.eachStart",
			EACH_FINISH:"Meshtml.eachFinish",
			INIT:"Meshtml.init",
			MESH:"Meshtml.mesh"
		},
		init:function(){
			var I = this;
			if(!I.elements.jquery) I.elements = $j(I.elements);

			I.jI.trigger(I.events.INIT);
			if(I.autoMesh) I.mesh();
		},
		mesh:function(){
			var I = this;

			//loop through the elements
			for(var i=0; i<I.elements.length;i++){
				var e = I.elements[i],
				each = $j(e);
				if(!each.data("meshed")){

					I.jI.trigger(I.events.EACH_START, i, e);
					
					var meshData = {};
					for(var varName in I.data){
						var varVal = (I.data[varName].indexOf("each.")==-1) ? I.data[varName] : eval(I.data[varName]);
						//var varVal = I.data[varName];
						meshData[varName]=varVal;
					}
					var meshedMarkup = tbelt.string.mesh(I.template, meshData);
					
					//if replace is false, insert the html inside of the current element				
					if(!I.replaceMode){
						each.html(meshedMarkup);
					}else{
						e = $j(meshedMarkup)[0];
						//replace by default
						//each.before(e);
						//each.remove();
						each.replaceWith(e);
					}
					
					each.data("meshed",true);
					I.jI.trigger(I.events.EACH_FINISH, i);
				}
			
			}
			
			I.jI.trigger(I.events.MESH);
		}
	}

})(tbelt.jQuery);

(function($j){

	tbelt.util.Timer = function(opts){
		var I = this;
		I.defaults = {		
			interval:250,
			duration:0,
			loop:false,
			onInterval:function(){return true;},
			onFinish:function(){},
			onError:function(){}
		};
		$j.extend(I, I.defaults, opts);
		
		var timerInterval;
		
		I.reset=function(){	
			I.stop();
			I.time=0;
		}
		
		I.stop=function(){
			clearInterval(timerInterval);	
			$j(I).trigger("stopped",I);
		}
		
		I.start=function(){
			timerInterval = setInterval(function(){
				if(I.onInterval()){
					I.force();
				}else if(I.duration>0 && I.time >= I.duration){
					I.fail();
				}
				I.time+=I.interval;
				$j(I).trigger("interval",I);
				
			}, I.interval);
			$j(I).trigger("started",I);
		}
		
		I.fail=function(){
			I.stop();		
			I.onError(I);
			$j(I).trigger("failed",I);
		}
		
		I.force=function(){
			I.stop();		
			I.onFinish(I);
			$j(I).trigger("finished",I);
			if(I.loop) I.start();
		}
		
		I.reset();
		I.start();
	}

})(tbelt.jQuery);





tbelt.url = (function($j){

	function url(){
	
	}
	
	url.prototype={
		
		
		relative:function(fullPath, root, guess){
			var returnPath="";	
			if(root && fullPath.indexOf(root)){
				returnPath = fullPath.replace(root,"");
			}else if(fullPath.indexOf(window.location.hostname)>-1){
				returnPath = fullPath.replace(window.location.protocol+"//"+window.location.host,"");
			}else if(guess){
				returnPath = fullPath.replace(/\/{2,5}/,"/").split("/");
				returnPath = returnPath.slice(2,returnPath.length).join("/");
			}
			return returnPath;	
		},
		
		
		
		/**
		 * url.queryString returns the value of a url query string.
		 * @param {String} qsName Name of the query string to return.
		 * @return Specified query string via qsName parameter, or the entire URL query string (if qsName is empty).
		 */
		queryString:function(qsName, qString){
			if(qString==null) qString=window.location.href;
			var returnQS = (/\?(.[^\#]*)\#?/).exec(qString);	
			if(returnQS && returnQS.length>0){
				returnQS = returnQS[1];
				if(qsName && qsName.length>0){
					var regex = new RegExp("&?"+qsName+"=(.[^&$]*)")
					returnQS = regex.exec(returnQS);
					if(returnQS && returnQS.length>0){
						returnQS = returnQS[1];
					}else{
						returnQS = "";
					}
				}
			}else{
				returnQS=null;
			}
			//trace(returnQS);
			return unescape(returnQS);
		},
		
		
		
		
		compare:function(suspectURL, compareURL, ignoreProtocol, ignoreQueryStrings, ignoreAnchors){
			var regex, hashes, queryString;
			var suspectQS="", compareQS="";
			var patterns=[], replacements=[];
			//trace(suspectURL + " : " +compareURL);
			//get and sort query strings according to compareURL
			regex = /\?.*$/;
			suspectQS = suspectURL.match(regex);
			compareQS = compareURL.match(regex);	
			if (compareQS && compareQS.length > 0 && suspectQS && suspectQS.length > 0){
				suspectURL = suspectURL.replace(regex, "");
				compareURL = compareURL.replace(regex, "");
				//remove ? from query strings
				regex = /(^\?)/;
				suspectQS = suspectQS[0].replace(regex,"");
				compareQS = compareQS[0].replace(regex,"");
				//replace slashes in query string values
				regex = /\//g;
				suspectQS = suspectQS.replace(regex, "%2F");
				compareQS = compareQS.replace(regex, "%2F");
				//split the query string values
				suspectQS = suspectQS.split("&");
				compareQS = compareQS.split("&");
				
				suspectQS = suspectQS.sort(function(a,b){
					//trace(a + " : " + compareQS.indexOf(a));
					//trace(b + " : " + compareQS.indexOf(b));
					var aPos = compareQS.indexOf(a);
					var bPos = compareQS.indexOf(b);
					if(aPos==-1) return 1;
					else
					return compareQS.indexOf(a) - compareQS.indexOf(b);
				});		
				suspectURL += "/"+suspectQS.join("/");
				compareURL += "/"+compareQS.join("/");
			}
			//ignore protocol (default)
			if(ignoreProtocol!=false){
				patterns.push(/^(http|https|file|www):/i);
				replacements.push("");	
			}
			//remove anchors if specified
			if(ignoreAnchors){		
				patterns.push(/\#.*$/);
				replacements.push("");
			}
			//remove query strings if specified
			if(ignoreQueryStrings){		
				patterns.push(/\?.*$/);
				replacements.push("");
			}		
			//replace hash with slash
			patterns.push(/#/);
			replacements.push("/");	
			//replace double slashes
			patterns.push(/(\/\/)/g);
			replacements.push("/");
			//remove leading and trailing slashes
			patterns.push(/(^\/|\/$)/g);
			replacements.push("");
			
			//apply patterns & replacements to urls
			for(var p=0;p<patterns.length;p++){
				suspectURL = suspectURL.replace(patterns[p],replacements[p]);
				compareURL = compareURL.replace(patterns[p],replacements[p]);
				//trace("\t\t"+suspectURL + " : " +compareURL);
			}	
			
			//split the urls into an array for comparison
			regex = /\//;		
			suspectURL = suspectURL.split(regex);
			compareURL = compareURL.split(regex);	
			
			//remove empty items from urls
			suspectURL = tbelt.array.clean(suspectURL);
			compareURL = tbelt.array.clean(compareURL);
			
			//compare and return rigidity	
			var returnRigidity=0;
			for(var r=0;r<compareURL.length;r++){
				//trace("\t\t"+suspectURL[r] + " : " +compareURL[r]);
				if(suspectURL[r]==compareURL[r]){
					returnRigidity=r+1;
				}
			}
			//trace(returnRigidity + " : " +suspectURL + " : " +compareURL);
			return returnRigidity;
			
		}
		
		
	
	}
	
	return new url();

})(tbelt.jQuery);


(function($j){

	tbelt.url.Highlighter = function(opts){
		var I = this;

		I.options = $j.extend({}, I.defaults, opts);	
		
		if(opts!=null && opts.links!=null){ 
			$j(document).ready(function(){
				I.init()
			});
		}
		
		return I;
		
	}
	tbelt.url.Highlighter.prototype = {
		defaults:{
			links:$j(""),
			manualMatches:[],
			url:window.location.href,
			minRigidity:0,
			alterElements: [{element:"each", className:"active"}],
			defaultPages: [/(default|index)\.[a-z]{2,5}/i],
			ignoreAnchors:false,
			ignoreQueryStrings:false,
			ignoreProtocols:true,
			autoHighlight:true,
			useLastBestMatch:false
		},
		options:null,
		bestMatch:null,
		matches:null,
		/*
			PUBLIC FUNCTIONS
		*/
		//init()
		init:function(){
			var I=this;
			if(I.options.autoHighlight){
				I.highlight();
			}else{
				I.setMatches();
			}
			$j(I).trigger("Highlighter.init", I);
		},
		//getMatches(rigidity)
		getMatches:function(rigidity){				
			var I=this;
			if(rigidity==null) return I.matches;
			return tbelt.array.searchObjects({rigidity:rigidity}, I.matches);
		},
		//setMatches()
		setMatches:function(){
			var I=this;
			var links = $j(I.options.links);
			I.matches = [];
			//convert rigidity to array if necessary
			if(typeof(I.options.rigidity)=="number"){
				I.options.rigidity=[I.options.rigidity];	
			}
			//convert alterElements to array if necessary
			if(I.options.alterElements.element!=null){
				I.options.alterElements = [I.options.alterElements];
			}
			var compareURL = I._cleanURL(I.options.url);
			var bestRigidity=0;
			links.each(function(i, link){
				var tmpURL = I._cleanURL(link.href);
				
				//check manual matches first
				function manualMatchIdx(url){
					for(var mm=0; mm < I.options.manualMatches.length; mm++){
						var manMatch=I.options.manualMatches[mm][0];
						
						if((tbelt.typeOf(manMatch)=="regexp" && (url).match(manMatch)) || url.indexOf(manMatch)>-1){
							trace(manMatch + " : " + url);
							return mm;
						}
					}
					return -1;		
				}
				var mmidx=manualMatchIdx(link.href);
				if(mmidx>-1){				
				
						var manMatchList = I.options.manualMatches[mmidx];					
					
						for(var mm=1; mm < manMatchList.length; mm++){
							var manMatch=manMatchList[mm];
							
							if((tbelt.typeOf(manMatch)=="regexp" && (I.options.url).match(manMatch)) || I.options.url.indexOf(manMatch)>-1){
								trace("\t"+manMatch + " : " + I.options.url);
								var match={
									link:link,
									rigidity:I.options.url.split(/\/|\?|&/).length
								};
								I.bestMatch=match;
								I.matches.push(match);
								//trace(match);
								return;
							}
						}

				}
				
				
				//compare urls			
				var rigidity = tbelt.url.compare(compareURL, tmpURL, I.options.ignoreProtocols, I.options.ignoreAnchors, I.options.ignoreQueryStrings);
				if(rigidity>I.options.minRigidity){				
					var match = {
						link: link,
						rigidity: rigidity
					};
					//set best match
					if(I.matches.length==0 || (I.options.useLastBestMatch && I.matches[I.matches.length-1].rigidity<=rigidity)
						|| I.bestMatch.rigidity < match.rigidity){
						I.bestMatch = match;
						//trace(I.bestMatch.link);
					} 
					//add to matches
					I.matches.push(match);	
				}
			});
					
		},
		//highlight(rigidity)
		highlight:function(rigidity){
			var I=this;
			I.setMatches(); 
			var toHighlight=[I.bestMatch];
			if(rigidity!=null && rigidity>0){
				toHighlight = I.getMatches(rigidity);
			}
			for(var th=0; th<toHighlight.length; th++){
				for(var ae=0; ae<I.options.alterElements.length; ae++){			
					try{
						//trace(I.options.alterElements[ae]);
						var alterElement = eval(I.options.alterElements[ae].element.replace(/each/,"$j(toHighlight[th].link)"));								
						alterElement.addClass(I.options.alterElements[ae].className);
						//trace(alterElement[0]);
					}catch(err){
						//trace(err);
					}
				}
			}
			$j(I).trigger("Highlighter.highlight", toHighlight);		
		},
		/*
			PRIVATE FUNCTIONS
		*/
		_cleanURL:function (dirtyURL){
			var I=this;
			var returnURL=dirtyURL;
			var regex;
			//remove default pages
			for(var dp=0;dp<I.options.defaultPages.length;dp++){			
				var dpType = tbelt.typeOf(I.options.defaultPages[dp]);
				if(dpType=="string"){
					returnURL = returnURL.replace(I.options.defaultPages[dp], "");
				}else if(dpType=="regexp"){
					returnURL = returnURL.replace(I.options.defaultPages[dp], "");
				}
			}	
			//trace(returnURL);
			return returnURL;
		}
	};
	
})(tbelt.jQuery);
tbelt.ui = (function($j){

	function ui(){
	
	}
	
	ui.prototype={
		
		
		animateScroll:function(scrollTo, duration, easing, callback){
			if(duration==null) speed=500;
			if(easing==null) easing="swing";

			function getTop(pos){
				if(typeof(pos)=="number") return pos;
				if(pos.offset()) return pos.offset().top;
				if(pos.nodeName) return $j(pos).offset().top;
				if(pos.top) return getTop(pos.top);
				return $j("html").scrollTop();		
			}
			function getLeft(pos){
				if (pos.left) {
					if(typeof(pos)=="number") return pos;
					if(pos.offset()) return pos.offset().top;
					if(pos.nodeName) return $j(pos).offset().left;
				}
				return $j("html").scrollLeft();
			}
			
			$j('html').animate({scrollTop: getTop(scrollTo)}, duration, easing, callback);
		},
		
		
		
		
		
		/*
		 * http://www.learningjquery.com/2007/10/improved-animated-scrolling-script-for-same-page-links
		 * why it's better: 
		 * One particular improvement is that I'm only cleaning the current page's path once, whereas Karl Swedberg's is running it through the function with each comparison. Another more debateable improvement is that the target scroll position is calculated when the link is clicked, rather than all at once. This is a definite improvement where you have alot of Javascript content initialization on a page.
		 */
		animateAnchors:function(duration, easing, ignoreSelector){
			$j(function(){
				function cleanPath(dirty){
					return dirty.replace(/(index|default)\..[a-zA-Z]*$/,"").replace(/\/{2,5}/g,"/").replace(/(^\/)|(\/$)/g,"");	
				}
				var pagePath = cleanPath(window.location.pathname);
				//assign actions to all anchor links on the page
				if(ignoreSelector==null)ignoreSelector="nothing"
				$j("a[href*='#']").not(ignoreSelector).each(function(i,a){
					if(cleanPath(a.pathname)==pagePath){
						$j(a).click(function(evt){
							evt.preventDefault();
							tbelt.ui.animateScroll($j("a[name='"+a.hash.replace(/^#/,"")+"']"), duration, easing, function(){window.location.hash=a.hash;});					
						});
					}
				});
				//check for current anchor link and go to it
				if(window.location.hash.length>0){
					tbelt.ui.animateScroll($j("a[name='"+window.location.hash.replace(/^#/,"")+"']"), duration, easing);
				}
			});	
		},
		
		


		allowsFixed:function(){
			//if browser is ie6 or ie and there is no doctype
			if(!$j.boxModel || $j.browser.msie && $j.browser.version.indexOf("6.")>-1){
				return false;
			}
			return true;
		},



		cacheImages:function(pathsArray){
			if(pathsArray && pathsArray.length>0){
				for(var i=0; i<pathsArray.length; i++){
					var img = new Image();
					img.src = pathsArray[i];
				}
			}
		},


		ratioResize:function(oldDims, newDims, round){
			if(newDims.height!=null && !isNaN(newDims.height)){
				newDims.width = (newDims.height/oldDims.height) * oldDims.width;
			}else if(newDims.width!=null && !isNaN(newDims.width)){
				newDims.height = (newDims.width/oldDims.width) * oldDims.height;
			}trace(newDims);
			if(round!=false){
				newDims.width = Math.round(newDims.width);
				newDims.height = Math.round(newDims.height);
			}	
			return newDims;
		},



		relativePosition:function(anchor, posEl, relativity, fixed, outside){
			relativity = $j.extend({x:"center", y:"center"}, relativity);
			if(anchor=="mouse") anchor = {top:mouseY, left:mouseX};
			if(anchor.top==null || tbelt.typeOf(anchor)=="window") anchor=$j(anchor);	
			
			var returnPos = {top:null,left:null};
			
			var posItemDims={height:null, width:null};
			if(posEl.height != null && posEl.width !=null && typeof(posEl.height)!="function"){
				posItemDims=posEl;
			}else{
				posEl = $j(posEl);
				posItemDims.height=posEl.outerHeight();
				posItemDims.width=posEl.outerWidth();		
			}
			
			//trace(anchor.top);
			var anchorDims = {height:0,width:0,top:0,left:0};
			
			if(tbelt.typeOf(anchor[0])!="window" && anchor.top==null){
				anchorDims.top = anchor.offset().top;
				anchorDims.left = anchor.offset().left;
				anchorDims.height = anchor.outerHeight();
				anchorDims.width = anchor.outerWidth();
			}else if(anchor.top==null){
				anchorDims.top = anchor.scrollTop();
				anchorDims.left = anchor.scrollLeft();
				anchorDims.height = anchor.height();
				anchorDims.width = anchor.width();
			}else{
				anchorDims.top = anchor.top;
				anchorDims.left = anchor.left;
			}
			
			//vertical position
			if(relativity.y=="center"){
				returnPos.top = anchorDims.top+(anchorDims.height/2)-(posItemDims.height/2);
			}else if((relativity.y=="bottom" && anchorDims.height>0) || (anchorDims.height==0 && relativity.y=="top")){
				returnPos.top = (anchorDims.top+anchorDims.height)-posItemDims.height;
				if(outside&&anchorDims.height>0) returnPos.top+=posItemDims.height;
			}else if((relativity.y=="top" && anchorDims.height>0) || (anchorDims.height==0 && relativity.y=="bottom")){
				returnPos.top = (anchorDims.top);
				if(outside&&anchorDims.height>0) returnPos.top-=posItemDims.height;
			}
			//console.dir(anchorDims);
			//horizontal position
			if(relativity.x=="center"){
				returnPos.left = anchorDims.left+(anchorDims.width/2)-(posItemDims.width/2);
			}else if(relativity.x=="right" && anchorDims.width>0 || anchorDims.width==0 && relativity.x=="left"){
				returnPos.left = anchorDims.left+(anchorDims.width-posItemDims.width);
				if(outside&&anchorDims.width>0) returnPos.left+=posItemDims.width;
			}else if(relativity.x=="left" && anchorDims.width>0 || anchorDims.width==0 && relativity.x=="right"){
				returnPos.left=anchorDims.left;
				if(outside&&anchorDims.width>0) returnPos.left-=posItemDims.width;
			}
			
			
			//get fixed position if true
			if(fixed){
				returnPos.top-=$j(window).scrollTop();
				returnPos.left-=$j(window).scrollLeft();
			}
			
			//console.dir(returnPos);
			return returnPos;
		}
		
		
		
		
	}
	
	
	return new ui();


})(tbelt.jQuery);



tbelt.ui.Accordion = (function($j){

	function Accordion(opts){
		var I = this;
		I.opts = opts;
		$j.extend(true, I, I.opts);
		I.jI=$j(I);
		if(I.autoInit) I.init();
	}
	
	Accordion.prototype={
		jI:null,
		opts:null,
		className:"Accordion",
		autoInit:true,
		triggers:null,
		triggerClasses:{expanded:"trigger-expanded", collapsed:"trigger-collapsed"},
		sections:null,
		sectionClasses:{expanded:"section-expanded", collapsed:"section-collapsed"},
		lastExpanded:null,
		lastCollapsed:null,
		orientation:"vertical",
		allowFullCollapse:false,
		allowMultipleExpand:false,
		speed:500,
		init:function(){
			var I = this;
			
			if(I.sections!=null && I.triggers!=null){
				I.triggers = $j(I.triggers);			
				I.sections = $j(I.sections);
				//associate triggers with sections
				I.sections.each(function(i, s){
					I.addSection(s, I.triggers[i]);				
				});

				if (!I.lastExpanded) {
					I.expand(0);
				} else {
					I.expand(I.lastExpanded);
				}
			}else{
				I.sections=$j([]);
				I.triggers=$j([]);	
			}
			
			I.jI.trigger(I.className+".init");
		},
		addSection:function(section, trigger, idx, autoExpand){
			var I = this;
			section = $j(section);
			trigger = $j(trigger);
			section.css("display","none");
			section.dataDirect(I.className+".trigger", trigger);
			
			//get the original height and overflow styles
			var origStyles = {
				dim:section.css("height"),
				overflow:section.css("overflow")
			}
			
			if(origStyles.dim=="0px") origStyles.dim=section.css("height","").css("height");
			if(origStyles.dim=="0px") origStyles.dim=section.css("height","auto").height();
			section.dataDirect(I.className+".origStyles", origStyles);
			
			
			trigger.dataDirect(I.className+".section", section);
			trigger.click(function(evt){				
				I.toggle(section[0]);
			});
			
			if(idx==null)idx = I.sections.length-1;
			
			//add to I.sections
			if(I.sections.indexOf(section[0])==-1){
				if(idx==0) I.sections.unshift(section[0]);
				else if(idx>0 && idx<I.sections.length) I.sections.splice(idx, 0, section[0]);
				else I.sections.add(section[0]);
			}
			//add to I.triggers
			if(I.triggers.indexOf(trigger[0])==-1){
				if(idx==0) I.triggers.unshift(trigger[0]);
				else if(idx>0 && idx<I.triggers.length) I.triggers.splice(idx, 0, trigger[0]);
				else I.triggers.add(trigger[0]);
			}
			
			if(autoExpand) I.expand(section);
			else I.collapse(section);
			I.jI.trigger(I.className+".addSection", section);
			return I;
		},
		removeSection:function(section){
			var I = this, idx=I.sections.length-1;
			if(section==null) section = I.sections[idx]
			else if(typeof(section).toLowerCase()=="number"){
				idx = section;
			}else{
				section = $j(section);
				idx = I.sections.indexOf(section[0])
			}
			section = $j(I.sections[idx]);
			var trigger = section.dataDirect(I.className+".trigger");
			if(trigger) $j(trigger).remove();
			
			I.sections = I.sections.filter(function(i){return I.sections[i]!=section[0]});
			if(trigger) I.triggers = I.triggers.filter(function(i){return I.triggers[i]!=trigger[0]});
			
			section.remove();			
			I.jI.trigger(I.className+".removeSection", section);
			return I;
		},
		expandedSections:function(){
			return this.sections.filter("."+this.sectionClasses.expanded);			
		},
		collapsedSections:function(){
			return this.sections.filter("."+this.sectionClasses.collapsed);
		},
		toggle:function(section){
			var I = this;
			section = $j(section);
			if(section.hasClass(I.sectionClasses.expanded)){
				I.collapse(section);		
			}else{				
				I.expand(section);
			}
			return I;
		},
		
		expand:function(sectionOrIdx){
			var I = this, section;	
			if(!isNaN(sectionOrIdx)) section = $j(I.sections[sectionOrIdx]);
			else section = $j(sectionOrIdx);
			
			I.toExpand(section);	
			if(!I.allowMultipleExpand){
				var expSecs = I.expandedSections(); 
				expSecs.each(function(e, es){
					if(es!=section[0]) I.collapse(es);
				});
			}
			I.lastExpanded=section;
			I.jI.trigger(I.className+".expand", section);
			return I;
		},
		
		toExpand:function(section){
			if(!section)return;
			var I = this;
			section = $j(section);				
			var trigger = $j(section.dataDirect(I.className+".trigger")),
			origStyles = section.dataDirect(I.className+".origStyles");
			
			trigger.removeClass(I.triggerClasses.collapsed).addClass(I.triggerClasses.expanded);
			section.removeClass(I.sectionClasses.collapsed).addClass(I.sectionClasses.expanded);
			
			section.stop();
			//section.slideDown(I.speed);
			if(section.css("overflow")!="scroll" && section.css("overflow")!="hidden")
				section.css({overflow:"hidden"});			
			section.css({height:0});
			
			section.animate({height:origStyles.dim}, I.speed, function(){
				section.css({overflow:origStyles.overflow});
			});
			
			return section;
		},
		
		collapse:function(sectionOrIdx){
			var I = this, section, expSecs = I.expandedSections();	
			if(!isNaN(sectionOrIdx)) section = $j(I.sections[sectionOrIdx]);
			else section = $j(sectionOrIdx);
			
			if(I.allowFullCollapse || expSecs.length>1) I.toCollapse(section);
			I.lastCollapsed=section;
			I.jI.trigger(I.className+".collapse", section);			
			return I;
		},
		
		toCollapse:function(section){
			if(!section)return;
			var I = this;
			section = $j(section);				
			var trigger = section.dataDirect(I.className+".trigger"),
			origStyles = section.dataDirect(I.className+".origStyles");			
			
			trigger.removeClass(I.triggerClasses.expanded).addClass(I.triggerClasses.collapsed);
			section.removeClass(I.sectionClasses.expanded).addClass(I.sectionClasses.collapsed);
			
			section.stop();
			//section.slideUp(I.speed);
			
			section.css({overflow:"hidden"});
			section.animate({height:0}, I.speed);
			
			return section;
		}
	}
	
	return Accordion;
	
})(jQuery);


(function($j){

	
	tbelt.ui.Overlay = (function(){

		function Overlay(opts){
		
			var I = this;
			I.jI=$j(I);
			I.opts = opts;
			
			I.positionAt = $j.extend({}, I.positionAt, opts.position);
			I.positionOffset = $j.extend({}, I.positionOffset, opts.positionOffset);

			$j.extend(I, I.opts);

			if(I.autoInit) I.init();
			
			
			I._onWindowScrollResize=function(evt){
				if(I.isShowing) I.position();
			}			
			I._onKeyPress=function(evt){
				//if esc
				if(I.cancelKeys.indexOf(evt.keyCode)>-1) I.hide(false);
				//if enter
				else if(I.confirmKeys.indexOf(evt.keyCode)>-1) I.hide(true);				
			}
			I._onMouseMove=function(evt){
				I.position();
			}
			I._onMatteClick=function(evt){
				I.hide(I.matteClick);
			}
			
		}

		Overlay.prototype={
			jI:null,
			opts:null,
			autoInit:true,
			className:"Overlay",
			zIndex:1000,
			element:null,
			positionAt:{x:"center", y:"center"},
			positionOffset:{top:0, left:0},
			positionAnchor:window,
			positionOutsideAnchor:false,
			positionSpeed:200,
			matte:null,
			matteFullScreen:true,
			matteOpacity:.7,
			matteSpeed:500,
			matteClick:false,
			cancelKeys:[27],
			confirmKeys:[13],
			followScroll:true,
			followResize:true,
			followMouse:false,
			isShowing:false,
			
			init:function(){
				var I = this;	
				I.element = $j(I.element);
				if(I.element.closest("body").length==0) $j("body").append(I.element);
				I.element.css({display:"none"});
				
				if(I.matte!=null){
					I.matte = $j(I.matte);
					if(I.matte.closest("body").length==0) $j("body").append(I.matte);
					I.matte.css({display:"none"});
				}
				
				if(I.positionAnchor!="mouse") I.positionAnchor=$j(I.positionAnchor);
				I.position(false);
				
				I.jI.trigger(I.className+".init");
			},
			
			show:function(){
				var I = this;
				if(I.isShowing)return I;
				I.toShow();
				
				//bind enter/esc keys
				$j(document).bind("keyup", I._onKeyPress);
				//bind to mouse move
				if(I.followMouse) $j(document).bind("mousemove", I._onMouseMove);
				//bind to window scroll
				if(I.followScroll) $j(window).bind("scroll",I._onWindowScrollResize);
				//bind to window resize
				if(I.followResize) $j(window).bind("resize",I._onWindowScrollResize);
				
				if(I.matte!=null && I.matteClick!=null) I.matte.bind("click", I._onMatteClick);
				
				I.isShowing=true;
				I.jI.trigger(I.className+".show");
				return I;
			},
			
			toShow:function(){
				var I = this;
				I.position(false);
				var doPos = function(){
					I.element.css({display:"block"});
				}
				//I.element.animate({opacity:1});
				if(I.matte!=null){
					I.matte.stop();
					I.matte.css({display:"block", opacity:0});					
					I.matte.animate({opacity:I.matteOpacity}, I.matteSpeed, doPos);
				}else{
					doPos();
				}
								
			},
			
			hide:function(success){
				var I = this;
				if(!I.isShowing)return I;
				I.toHide();
				
				$j(document).unbind("keyup", I._onKeyPress);
				$j(document).unbind("mousemove", I._onMouseMove);
				$j(window).unbind("scroll", I._onWindowScrollResize);
				
				if(I.matte!=null) I.matte.unbind("click", I._onMatteClick);
				
				I.isShowing=false;
				I.jI.trigger(I.className+".hide", success);
				return I;
			},
			
			toHide:function(){
				var I = this;
				I.element.stop();
				I.element.css({display:"none"});
				
				if(I.matte!=null){
					I.matte.stop();
					I.matte.animate({opacity:0}, I.matteSpeed, function(){
						I.matte.css({display:"none"});
					});
				}
				
			},
			
			position:function(aParms, duration, easing, complete, step, queue){
				var I = this,
				elStyles={zIndex:I.zIndex, position:"absolute"},
				animateParams=$j.extend({height:I.element.height(), width:I.element.width(), top:0, left:0}, aParms),
				newPos=tbelt.ui.relativePosition(I.positionAnchor, {height:animateParams.height,width:animateParams.width}, I.positionAt, false, I.positionOutsideAnchor);
				//position absolutely to I.anchor, bind to window.scroll
				
				newPos.top+=I.positionOffset.top;
				newPos.left+=I.positionOffset.left;
				
				$j.extend(animateParams, newPos);
				
				I.element.css(elStyles);
				
				if(I.matte!=null){
					
					var matteStyles = {
						position:"absolute",
						zIndex:I.zIndex-1						
					},
					matteAnim={
						top:animateParams.top-parseInt(I.matte.css("padding-top").replace(/px/,"")),
						left:animateParams.left-parseInt(I.matte.css("padding-left").replace(/px/,"")),
						height:animateParams.height,
						width:animateParams.width
					};
					
					if(I.matteFullScreen){
						var matteAnim={
							height:$j(document).height(),
							width:$j(document).width(),
							top:0,
							left:0
						}
					}
					
					I.matte.css(matteStyles);
					if(aParms==false){
						I.matte.css(matteAnim);
					}else{
						I.matte.stop();
						I.matte.animate(matteAnim, duration||I.positionSpeed);
					}
				}
				
				
				//move the element into position
				if(aParms==false){
					I.element.css(animateParams);
				}else{
					I.element.stop();
					I.element.animate(animateParams, duration||I.positionSpeed, easing, complete, step, queue);
				}
				
				I.jI.trigger(I.className+".position", newPos);
				return I;
			}
			

		}

		return Overlay;

	})();	

})(tbelt.jQuery);

(function($j){

	tbelt.ui.Tabset = function(opts){
		var I = this;
		I.options = $j.extend({}, I.defaults, opts);
		
		$j(document).ready(function(){I.init();});
	}

	tbelt.ui.Tabset.prototype = {
		/*
			PUBLIC PROPERTIES
		*/
		defaults:{
			tabs:"",
			contents:"",
			activeClass:"active",
			autoDisplay:0,
			hide:function(paneToHide){
				paneToHide.css({display:"none"});	
			},
			show:function(paneToShow){paneToShow.fadeIn(300);}
		},
		options:null,
		tabs:null,
		contents:null,
		activeTabset:null,
		/*
			PUBLIC METHOD
		*/
		init:function(){
			var I = this;
			I.tabs = $j(I.options.tabs);
			I.contents = $j(I.options.contents);
			
			var invalids = [];
			I.tabs.each(function(i,n){			
				var tmpTab = $j(n);
				var tmpTabLink = tmpTab.find("a[href^=#]");	
				if (tmpTabLink.length>0 && tmpTabLink.attr("href")) {
					tmpTabLink.click(function(evt){
						evt.preventDefault();
						I.showTabset(tmpTabLink.attr("href"));
					});
				}else{
					invalids.push(i);
				}
				
			});	
			I.tabs = I.tabs.filter(function(i){
				return (invalids.indexOf(i)==-1);						   
			});	
			I.hideContents(true);
			//set the first tab as active
			if(I.options.autoDisplay>=0){
				if(I.options.autoDisplay < I.tabs.length){
					$j(I.tabs[I.options.autoDisplay]).find("a[href!='']").trigger("click");
				}else{
					$j(I.tabs[I.tabs.length-1]).find("a[href!='']").trigger("click");
				}
			}
			

		},
		hideContents:function(instant){
			var I = this;
			I.tabs.each(function(i, n){
				var tabset = I.getTabset($j(n).find("a[href*='#']").attr("href"));
				if(tabset!=null){			
					if (tabset.content.css("display") != "none" && (!I.activeTabset || tabset.content[0]!=I.activeTabset.content[0])) {				
						if(instant!=true)
							I.options.hide(tabset.content);
						else
							tabset.content.css({display:"none"});			
					}
				}
			});
		},
		deactivateButtons:function(){
			var I = this;
			I.tabs.removeClass("active");
		},
		showTabset:function(tabAnchor){
			var I = this;
			tabAnchor = tabAnchor.replace(/^\#/, "");
			var tabset = I.getTabset(tabAnchor);
			if(tabset!=null){
				if(!I.activeTabset || I.activeTabset.content[0]!=tabset.content[0]){				
					I.options.show(tabset.content);
					I.deactivateButtons();
					tabset.tab.addClass(I.options.activeClass);
					I.activeTabset=tabset;
					I.hideContents();
				}
			}
		},
		getTabset:function(tabAnchor){
			var I = this;
			tabAnchor = tabAnchor.replace(/^\#/, "");
			var tabsetContent, tabsetTab;
			for(var c=0; c<I.contents.length; c++){
				if($j(I.contents[c]).find("a[name='"+tabAnchor+"']").length>0){					
					tabsetContent=I.contents[c];
					break;
				}				
			}		
			for(var t=0; t<I.tabs.length; t++){
				if($j(I.tabs[t]).find("a[href='#"+tabAnchor+"']").length>0){					
					tabsetTab=I.tabs[t];
					break;
				}				
			}	
			//trace("tab: "+tabsetTab + ", content: "+tabsetContent);
			if(tabsetTab && tabsetContent)
				return {tab:$j(tabsetTab), content:$j(tabsetContent)};
			else
				return null;
		}
	}

	
})(tbelt.jQuery);


tbelt.ui.Repeater = (function($j){

	function Repeater(opts){
		var I = this;
		
		I.opts = opts;
		if(opts.dataTemplate) $j.extend(I.dataTemplate, opts.dataTemplate);
		$j.extend(I, I.opts);
		I.jI=$j(I);
		I.init();
	}
	
	Repeater.prototype = {
		jI:null,
		opts:null,
		className:"Repeater",
		data:[],
		dataTemplate:{},
		autoBind:true,
		itemsContainer:null,
		itemsSelector:null,
		_items:null,
		items:function(isFresh){
			if(!isFresh) return this._items;
			else return this._items = this.itemsContainer.find(">"+this.itemsSelector);
		},
		itemHtml:null,
		maxItems:false,
		minItems:false,
		init:function(){
		
			var I = this;
			I.itemsContainer = $j(I.itemsContainer);
			I.items(true);
			I.itemHtml = I.items()[0].outerHTML;			
			
			if(I.autoBind) I.bind();
			I.jI.trigger(I.className+".init");
		},
		bind:function(startAt){
			var I = this,
			newItems="";
			if(startAt==null || startAt<0) startAt=0;
			for(var i=startAt; i<I.data.length; i++){
				I.data[i] = $j.extend({}, I.dataTemplate, I.data[i]);
				I.data[i].index=i;
				var item = I._meshItemData(I.data[i]);				
				newItems+=item;
			}
			//trace(newItems);
			//newItems = $j(newItems);
			var items = I.items().filter(":eq("+startAt+"),:gt("+startAt+")");
			//trace(items.selector + " : " +items.length);
		
			items.remove();
			if(newItems.length>0) I.itemsContainer.append($j(newItems));
			I.items(true);
			
			I.jI.trigger(I.className+".bind", startAt);			
			
			return I;
		},
		_meshItemData:function(data){
			var I = this;			
			var item = I.itemHtml.replace(/(\{\$.[^\}]*\})/g, function(){
				var evalSrc = (arguments[0].replace(/(^\{\$)|(\}$)/g,"")),
				evalResult=null;
				try {evalResult = eval(evalSrc);}
				catch(err) {trace(I.className+"._meshItemData(): "+err.message)};				
				if(typeof(evalResult)=="function") evalResult = evalResult(data, I);				
				//trace(evalSrc + " : " +arguments[0] + " : "+evalResult);
				return  (evalResult!=null) ? evalResult : arguments[0];
			});
			return item;
		},
		addItem:function(data, idx, fullBind){
			var I = this;
			data = $j.extend({}, I.dataTemplate, data);
			if(idx==null){
				idx = I.data.length;
				I.data.push(data);
			} else if(idx<=0){
				I.data = [].concat(data, I.data);
			}else {
				I.data = I.data.splice(idx, 0, data);
			}
			data.index = idx;
			if(I.maxItems!=false && idx>=I.maxItems) return;
			
			if(!fullBind) I.bind(idx);
			else I.bind(0);	
			
			I.jI.trigger(I.className+".addItem", {index:idx, data:data});					
			
			return I;
		},
		removeItem:function(itemOrIdx, fullBind){
			var I = this,
			idx=I.data.length-1,
			itemData=null;
			if(I.minItems!=false && I.data.length<=I.minItems) return;
			
			if(itemOrIdx!=null && isNaN(itemOrIdx)){
				idx = I.data.indexOf(itemOrIdx);
			}else if(!isNaN(itemOrIdx)){
				idx = itemOrIdx;
			}
			itemData=I.data[idx];
			
			I.data.remove(idx);

			if(!fullBind) I.bind(idx);
			else I.bind(0);	
			
			//console.dir(I.data);
			I.jI.trigger(I.className+".removeItem", {index: idx, data:itemData});
			return I;
		}
		
	}
	
	return Repeater;
	
})(tbelt.jQuery);


//debugMode=2;

tbelt.ui.SlotWheel = (function(j){

	function SlotWheel(opts){
		var I = this;
		j.extend(I, I.defaults, opts);
		
		j(document).ready(function(){I.init()});
	}
	
	SlotWheel.prototype={
		
		slots:null, //jQuery selector/HTML element array
		slotsWrapper:"<div class='slots-wrapper'></div>", //HTML string/jQuery selector/HTML element
		slotsWindow:null, //jQuery selector/HTML element		
		currentIndex:0,
		isHorizontal:true,
		scrollSpeed:500,
		scrollEasing:"swing",
		scrollCallback:function(idx,position){},
		
		init:function(){
			var I = this;
			I.slots = j(I.slots);
			I.slotsWindow=j(I.slotsWindow);
			
			I.slotsWrapper = j(I.slotsWrapper);
			I.slotsWrapper.css((I.isHorizontal)?"width":"height", I._getSlotsDim());
			
			I.slots.wrapAll(I.slotsWrapper);			
			I.slotsWrapper = I.slotsWindow.find(">*:eq(0)");
		
			I.showSlot(0);
		},
		
		showSlot:function(idx, position){
			//trace("showSlot("+idx+")");
			var I = this;
			I.currentIndex=idx;
			function getPosition(){
				position = I._getSlotsDim(idx)*-1;
				return position;
			}
			var animateParms = {};
			if(I.isHorizontal){
				animateParms.marginLeft=getPosition();
			}else{
				animateParms.marginTop=getPosition();
			}
			I.slotsWrapper.stop(true);
			I.slotsWrapper.animate(animateParms, I.scrollSpeed, I.scrollEasing, function(){I.scrollCallback(idx,position)});
		},
		
		next:function(){
			var I = this;
			var nextIdx = I.currentIndex+1;
			I.showSlot((nextIdx<I.slots.length) ? nextIdx : 0);
		},
		
		previous:function(){
			var I = this;
			var prevIdx = I.currentIndex-1;
			I.showSlot((prevIdx>-1) ? prevIdx : I.slots.length-1);
		},
		
		_getSlotsDim:function(maxIndex){
			var I = this;
			var dim=0;
			
			for(var s=0; (s<I.slots.length); s++){
				if(s==maxIndex)break;
				var slot = j(I.slots[s]);
				if(I.isHorizontal){
					dim+=slot.outerWidth("px"); //seems like it auto calculates margin with "px" as parameter
				}else{
					dim+=slot.outerHeight("px");
				}
				
			}
			
			return dim;
		}
	};
	
	return SlotWheel;

})(jQuery);


tbelt.form = (function($j){

	function form(){
	
	}
	
	form.prototype={
		
		
		toQueryString:function(formToConvert, escapeResult){
			if(formToConvert.nodeName)	formToConvert = $j(formToConvert);
			if(escapeResult==null) escapeResult = true;
			var queryString="";
			
			$j(formToConvert).find("*").each(function(i,field){
				var nodeName = field.nodeName.toLowerCase();
				if(nodeName=="input" && field.type=="text" ||
					nodeName=="input" && field.type=="hidden" ||
					nodeName=="input" && field.type=="radio" && field.checked ||
					nodeName=="input" && field.type=="checkbox" && field.checked ||
					nodeName=="select" ||
					nodeName=="textarea"){
					queryString += ((queryString.length==0)?"?":"&")+$j(field).attr("name") +"="+ ((escapeResult)?escape($j(field).val()):$j(field).val());			
				}		
			});
			
			return queryString;	
		},


		validateField:function(field, expression, required){
			var isValid = true;	
			var checkValue = "";
			field = $j(field);
			//console.log(field.attr("name") + " : " +field.attr("type"));
			if(field.attr("type")=="radio" || field.attr("type")=="checkbox"){
				var activeInputs = $j("input[name='"+field.attr("name")+"']:checked");
				activeInputs.each(function(i, n){
					checkValue += (i==0)?$j(n).val():","+$j(n).val();
				});
			}else{
				checkValue = field.val();
			}
			
			//if not required and no value
			if(!required && (!checkValue || checkValue.length==0)) return true;
			else if(required && (!checkValue || checkValue.length==0)) return false;
			
			//check the input value against the expression 
			if(tbelt.typeOf(expression)=="string" && expression.length>0){
				if(expression=="creditcard"){
					isValid = tbelt.form.isValCreditCard(checkValue);
				}else if(expression=="date"){
					isValid = tbelt.form.isValDate(checkValue);
				}else if(expression=="email"){
					isValid = tbelt.form.isValEmail(checkValue);
				}else if(expression=="phone"){
					isValid = tbelt.form.isValPhone(checkValue);
				}else if(expression=="url"){
					isValid = tbelt.form.isValUrl(checkValue);
				}else{
					isValid = (checkValue==expression);
				}
			}else if(tbelt.typeOf(expression)=="regexp"){
				isValid = expression.test(checkValue);
				//trace(expression.toString() + " : " + checkValue + " : " +isValid);
			}else if(typeof(expression)=="function"){
				isValid = expression(field, required);
			}
			
			//trace(field[0]);
			//trace("\t"+isValid + " : " +checkValue);
			return isValid;
		},
		
		

		isValEmail:function(emailStr){
			var regex = /^(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+([;.](([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+)*$/i;
			return regex.test(emailStr);
		},


		isValCreditCard:function(ccStr){
			var validFormats = [/(^(4|5)\d{3}-?\d{4}-?\d{4}-?\d{4}|(4|5)\d{15})|(^(6011)-?\d{4}-?\d{4}-?\d{4}|(6011)-?\d{12})|(^((3\d{3}))-\d{6}-\d{5}|^((3\d{14})))/,
			/^((4\d{3})|(5[1-5]\d{2})|(6011))-?\d{4}-?\d{4}-?\d{4}|3[4,7]\d{13}$/];
			return tbelt.array.search(ccStr, validFormats);	
		},

		isValDate:function(dateStr){
			//Basic check for format validity
			var validFormats = [(/^\d{2}\/\d{2}\/\d{4}$/), (/^\d{1}\/\d{2}\/\d{4}$/), (/^\d{1}\/\d{1}\/\d{4}$/), (/^\d{2}\/\d{1}\/\d{4}$/)];
			//var isValid = this.isInList(dateStr, validFormats);
			var isValid = tbelt.array.search(dateStr, validFormats);
			if(!isValid)return false;	

			//Detailed check for valid date ranges
			var monthfield=dateStr.split("/")[0]
			var dayfield=dateStr.split("/")[1]
			var yearfield=dateStr.split("/")[2]
			var dayobj = new Date(yearfield, monthfield-1, dayfield)
			if ((dayobj.getMonth()+1!=monthfield)||(dayobj.getDate()!=dayfield)||(dayobj.getFullYear()!=yearfield)){
				return false;			
			}else{
				return true;
			}
			
		},


		isValPhone:function(phoneStr){
			var validFormats = [/^([\(]{1}[0-9]{3}[\)]{1}[\.| |\-]{0,1}|^[0-9]{3}[\.|\-| ]?)?[0-9]{3}(\.|\-| )?[0-9]{4}$/];	
			return tbelt.array.search(phoneStr, validFormats);	
		},

		isValUrl:function(ccStr){
			var validFormats = [/(http|https:\/\/)?([a-z0-9][^\.]*)\.([a-z0-9][^\.]*)/i];
			return tbelt.array.search(ccStr, validFormats);	
		}
		
		
	
	}
	
	return new form();

})(tbelt.jQuery);






tbelt.form.Checkbox = (function(j){

	function Checkbox(opts){
		var I = this;
		I.elementClasses = j.extend({}, I.elementClasses, opts.elementClasses);
		I.labelClasses = j.extend({}, I.labelClasses, opts.labelClasses);
		I.options = j.extend(I, opts);
		I.jI=j(I);
		if(I.autoInit) I.init();
	}
	
	Checkbox.prototype={
		jI:null,
		autoInit:true,
		className:"Checkbox",
		options:null,
		elementClasses:{base:"checkbox", hover:"checkbox-hover", checked:"checkbox-checked", disabled:"checkbox-disabled"},
		element:null, //jQuery selector/HTML elment
		//skin:"<span class='checkbox'></span>", //html string
		skin:false,
		label:false, //jQuery selector
		labelClasses:{base:"label", hover:"label-hover", checked:"label-checked", disabled:"label-disabled", error:"label-error"},

		init:function(){
			var I = this;
			
			I.element=j(I.element);
			if(I.element.length>1) I.element=j(I.element[0]);
			
			if(I.element.data("tbelt.form.Checkbox")!=null){
				I = I.element.data("tbelt.form.Checkbox");
			}else{
				I.element.data("tbelt.form.Checkbox", I);
			}
			I.element.click(I._onInputClick);
			
			//try to find label if none is specified
			I.label=j(I.label);
			if(I.label[0]==document) I.label=false;
			
			if((!I.label ||I.label.length==0) && I.element[0].id){
				var lbl = j("label[for='"+I.element[0].id+"']");
				if(lbl.length>0) I.label = lbl;					
				else I.label = false;
			}
			if(I.label!=false){ 
				I.label.data("tbelt.form.Checkbox", I);
				I.label.addClass(I.labelClasses.base);
				I.label.click(I._onLabelClick);
				I.label.hover(I._onLabelHover, I._onLabelHover);
			}
			
						
			
			if(I.skin!=false){
				I.skin = j(I.skin);				
				I.skin.addClass(I.elementClasses.base);
				
				I.element.wrap(I.skin);
				I.skin = I.element.closest("."+I.elementClasses.base);
				I.skin.data("tbelt.form.Checkbox", I);				
				
				I.skin.click(function(evt){I.element.click()});
				I.skin.hover(I._onInputHover, I._onInputHover);				
				
			}else{
				I.element.addClass(I.elementClasses.base);
				I.element.hover(I._onInputHover, I._onInputHover);
			}
			//set initial checked state
			if(I.element[0].checked) I.checked(true);
		},
		
		checked:function(isChecked){
			var I = this;
			//trace("checked("+isChecked);

			if(isChecked==true){
				I.element[0].checked=true;	
				(I.skin || I.element).addClass(I.elementClasses.checked);								
				if(I.label!=false) I.label.addClass(I.labelClasses.checked);
			}else if(isChecked==false){
				I.element[0].checked=false;
				(I.skin || I.element).removeClass(I.elementClasses.checked);				
				if(I.label!=false) I.label.removeClass(I.labelClasses.checked);
			}else{
				isChecked = I.element[0].checked;
			}
			
			return isChecked;
		},
		
		click:function(isChecked){
			var I = this;
			//trace("click("+isChecked);
			if(isChecked==null){
				I.element.click();
				return;
			}
			I.checked(isChecked);
			I.jI.trigger(I.className+".click", isChecked);
			return isChecked;
		},
		
		hover:function(isHover){
			var I = this;
			
			if(isHover==true){
				(I.skin || I.element).addClass(I.elementClasses.hover);
				if(I.label!=false) I.label.addClass(I.labelClasses.hover);
			}else{
				(I.skin || I.element).removeClass(I.elementClasses.hover);
				if(I.label!=false) I.label.removeClass(I.labelClasses.hover);
				isHover=false;
			}
			I.jI.trigger(I.className+".hover", isHover);
			return isHover;
		},
		
		disabled:function(toDisable){
			var I = this;
			if(toDisable!=null){
				if(toDisable){
					I.element.attr("disabled","disabled");
					(I.skin || I.element).addClass(I.elementClasses.disabled);
					if(I.label!=false) I.label.addClass(I.labelClasses.disabled);
				}else{
					I.element.removeAttr("disabled");
					(I.skin || I.element).removeClass(I.elementClasses.disabled);
					if(I.label!=false) I.label.removeClass(I.labelClasses.disabled);
				}
			}else{
				toDisable = (I.element.attr("disabled"))? true : false;
			}
			I.jI.trigger(I.className+".disabled", toDisable);
			return toDisable;
		},
		
		validate:function(){
			var I = this;
			var isValid = tbelt.form.validateField(I.element, I.criteria, I.required);
			if(isValid){
				(I.skin || I.element).removeClass(I.elementClasses.error);
				I.label.removeClass(I.labelClasses.error);
			}else{
				(I.skin || I.element).addClass(I.elementClasses.error);
				I.label.addClass(I.labelClasses.error);
			}
			I.jI.trigger(I.className+".validate", isValid);
			return isValid;
		},
		
		_onInputClick:function(evt){
			var I = j(evt.target).data("tbelt.form.Checkbox");
			if(!I) return;
			
			if(evt.target==I.element[0]) evt.stopPropagation();
			
			/*if(!I.element[0].checked){
				I.click(false);
			}else{
				I.click(true);
			}*/
			setTimeout(function(){
				I.click(I.checked());
			}, 50);
		},
		
		_onInputHover:function(evt){
			var I = j(evt.target).data("tbelt.form.Checkbox");
			if(!I) return;				
			if(evt.type=="mouseenter"){
				I.hover(true);
			}else{
				I.hover(false);
			}
		},
		
		_onLabelHover:function(evt){		
			var target = j(evt.target);
			var I = j(evt.target).data("tbelt.form.Checkbox");
			if(!I) I=target.closest("label").data("tbelt.form.Checkbox"); 
			if(!I) return;	
			if(evt.type=="mouseenter"){
				if(!I.disabled())I.hover(true);
			}else{
				if(!I.disabled())I.hover(false);
			}
			
		},
		
		_onLabelClick:function(evt){		
			evt.preventDefault();
			var target = j(evt.target);		
			var I = j(evt.target).data("tbelt.form.Checkbox");		
			if(!I) I=target.closest("label").data("tbelt.form.Checkbox"); 
			if(!I) return;	
			if(!I.disabled())I.element.click();
		}
		
		
		
	};
	
	
	
	
	return Checkbox;

})(jQuery);






tbelt.form.RadioButton = (function(j){

	function RadioButton(opts){
	
		tbelt.form.Checkbox.apply(this, arguments);
		//j(document).ready(function(){I.init()});
	}
	
	j.extend(RadioButton.prototype, tbelt.form.Checkbox.prototype,
	{
		elementClasses:{base:"radio", hover:"radio-hover", checked:"radio-checked", disabled:"radio-disabled"}		
	});
	
	
	return RadioButton;

})(jQuery);
/*
tbelt.form.Checkbox = (function(){
	var Checkbox=function(){
	
	}
	return Checkbox;
})();
*/


tbelt.form.OptionsGroup = (function(j){

	function OptionsGroup(opts){
		var I = this;
		I.options = j.extend(true, I, opts);
		
		j(document).ready(function(){I.init()});
	}
	
	OptionsGroup.prototype={
		elements:null, //jQuery selector/HTML elment
		optionParams:{}, //parameters to be passed to each tbelt.form.Checkbox/RadioButton instance
		group:[],
		mode:"checkbox", //or radio
		required:false,
		criteria:/.*/,
		errorMessage:"",
		label:null, //jQuery selector
		labelClasses:{base:"label", hover:"label-hover", focus:"label-focus", disabled:"label-disabled", error:"label-error"},		
		
		init:function(){
			var I = this;
			
			I.elements = j(I.elements);	
			if(I.elements[0]==document)return;			
			I.mode = I.elements[0].type.toLowerCase();
			//trace(I.mode);
			//try to get label automatically if none is specified
			I.label=j(I.label);
			if(I.label[0]==document && I.elements[0].name){
				var lbl = j("label[for='"+I.elements[0].name+"']");
				if(lbl.length>0) I.label = lbl;
			}
			I.label.addClass(I.labelClasses.base);
			
			for(var e=0; e<I.elements.length; e++){
				var el = j(I.elements[e]);
				var option;
				I.optionParams.element=el;
				if(I.mode=="checkbox"){
					option = el.data("tbelt.form.Checkbox");
					if(option==null){
						option = new tbelt.form.Checkbox(I.optionParams);
					}					
				}else if(I.mode=="radio"){
					option = el.data("tbelt.form.RadioButton");
					if(option==null){
						option = new tbelt.form.RadioButton(I.optionParams);
					}
				}
				el.data("tbelt.form.OptionsGroup",I);
				I.group.push(option);
			}
			
		},
		
		validate:function(){
			var I = this;
			var isValid = tbelt.form.validateField(I.elements[0], I.criteria, I.required);
			if(isValid){				
				if(I.label) I.label.removeClass(I.labelClasses.error);
			}else{
				if(I.label) I.label.addClass(I.labelClasses.error);
			}
			j(I).trigger("Select.validate", isValid);
			return isValid;
		}
		
		
		
	};
	
	
	return OptionsGroup;

})(jQuery);


tbelt.form.TextField = (function(j){

	function TextField(opts){
		var I = this;
		var criteria = opts.criteria || I.criteria;
		I.opts=opts;
		j.extend(true, I, I.opts);
		I.criteria=criteria;
		
		I.onInputFocus=function(evt){
			I.focus(evt);
		}
		
		I.onInputBlur=function(evt){
			I.blur(evt);
		}
		
		I.onInputHover=function(evt){
			if(evt.type=="mouseenter"){
				I.hover(true);
			}else{
				I.hover(false);
			}
		}
		
		I.onLabelHover=function(evt){		
			if(evt.type=="mouseenter"){
				if(!I.disabled())I.hover(true);
			}else{
				if(!I.disabled())I.hover(false);
			}
			
		}
		
		I.onLabelClick=function(evt){		
			evt.preventDefault();
			if(!I.disabled())I.element.focus();
		}
		
		j(document).ready(function(){I.init()});
	}
	
	TextField.prototype={
		opts:null,
		elementClasses:{base:"textfield", hover:"textfield-hover", focus:"textfield-focus", disabled:"textfield-disabled", error:"textfield-error"},
		element:null, //jQuery selector/HTML elment
		//skin:"<span></span>", //html string
		skin:false,
		label:false, //jQuery selector
		labelClasses:{base:"label", hover:"label-hover", focus:"label-focus", disabled:"label-disabled", error:"label-error"},
		required:false,
		errorMessage:"",
		criteria:/.*/, //regexp, string, function
		init:function(){
			var I = this;
			
			I.element=j(I.element);		
			var original = I.element.data("tbelt.form.TextField");	
			if(original!=null){				
				//j.extend(original, I.opts);
				//I=original;
				//original.init();				
				//return;
			}else{
				I.element.data("tbelt.form.TextField", I);				
			}
			
			//try to find label if none is specified
			I.label=j(I.label);
			if(I.label[0]==document) I.label=false;
			
			if((!I.label ||I.label.length==0) && I.element[0].id){
				var lbl = j("label[for='"+I.element[0].id+"']");
				if(lbl.length>0) I.label = lbl;					
				else I.label = false;
			}
			if(I.label!=false){ 
				I.label.data("tbelt.form.TextField", I);
				I.label.addClass(I.labelClasses.base);
			}
			
			
			if(original==null){
				I.element.hover(I.onInputHover, I.onInputHover);			
				I.element.focus(I.onInputFocus);
				I.element.blur(I.onInputBlur);
				if(I.label!=false){
					I.label.click(I.onLabelClick);
					I.label.hover(I.onLabelHover,I.onLabelHover);
				}
			}
			if(I.skin!=false && !I.element.data("skinned")){
				I.skin = j(I.skin);
				I.skin.addClass(I.elementClasses.base);
				I.element.wrap(I.skin);	
				I.skin = I.element.closest("."+I.elementClasses.base);
				I.element.data("skinned",true);
			}else{
				I.element.addClass(I.elementClasses.base);
				
				
			}
			
			if(I.element.attr("disabled")) I.disabled(true);
		},
		focus:function(evt){
			var I = this;
			(I.skin||I.element).addClass(I.elementClasses.focus);	
				
			if(I.label!=false) I.label.addClass(I.labelClasses.focus);				
			j(I).trigger("TextField.focus");
		},
		blur:function(evt){
			var I = this;
			if(evt==null){
				I.element.blur();
				return;
			}
		
			(I.skin || I.element).removeClass(I.elementClasses.hover);
			(I.skin || I.element).removeClass(I.elementClasses.focus);
	
			if(I.label!=false){
				I.label.removeClass(I.labelClasses.hover);	
				I.label.removeClass(I.labelClasses.focus);
			}
			j(I).trigger("TextField.blur");
		},
		
		disabled:function(toDisable){
			var I = this;
			if(toDisable!=null){
				if(toDisable){
					I.element.attr("disabled","disabled");				
					(I.skin || I.element).addClass(I.elementClasses.disabled);					
					if(I.label!=false) I.label.addClass(I.labelClasses.disabled);
				}else{
					I.element.removeAttr("disabled");			
					(I.skin || I.element).removeClass(I.elementClasses.disabled);					
					if(I.label!=false) I.label.removeClass(I.labelClasses.disabled);
				}
			}else{
				toDisable = (I.element.attr("disabled"))? true : false;
			}
			j(I).trigger("TextField.disabled", toDisable);
			return toDisable;
		},
		
		hover:function(isHover){
			var I = this;
			
			if(isHover==true){
				(I.skin || I.element).addClass(I.elementClasses.hover);				
				if(I.label!=false) I.label.addClass(I.labelClasses.hover);
			}else{
				(I.skin || I.element).removeClass(I.elementClasses.hover);				
				if(I.label!=false) I.label.removeClass(I.labelClasses.hover);
				isHover=false;
			}
			j(I).trigger("TextField.hover", isHover);
			return isHover;
		},
		
		validate:function(){
			var I = this;
			var isValid = tbelt.form.validateField(I.element, I.criteria, I.required);
			if(isValid){
				(I.skin || I.element).removeClass(I.elementClasses.error);			
				if(I.label!=false) I.label.removeClass(I.labelClasses.error);
			}else{
				(I.skin || I.element).addClass(I.elementClasses.error);
				if(I.label!=false) I.label.addClass(I.labelClasses.error);
			}
			j(I).trigger("TextField.validate", isValid);
			return isValid;
		}
		
		
	};
	
	
	
	
	
	
	return TextField;

})(jQuery);




tbelt.form.Select = (function(j){

	function Select(opts){
		var I = this;
		var criteria = opts.criteria || I.criteria;
		j.extend(true, I, opts);
		I.criteria=criteria;
		
		I.onInputFocus=function(evt){
			I.focus(evt);
		}
		
		I.onInputBlur=function(evt){
			I.blur(evt);
		}
		
		I.onInputHover=function(evt){
			if(evt.type=="mouseenter"){
				I.hover(true);
			}else{
				I.hover(false);
			}
		}
		
		I.onLabelHover=function(evt){
			if(evt.type=="mouseenter"){
				if(!I.disabled())I.hover(true);
			}else{
				if(!I.disabled())I.hover(false);
			}
			
		}
		
		I.onLabelClick=function(evt){		
			evt.preventDefault();		
			if(!I.disabled())I.element.focus();
		}
		
		j(document).ready(function(){I.init()});
	}
	
	Select.prototype={
		elementClasses:{base:"select", hover:"select-hover", focus:"select-focus", disabled:"select-disabled", error:"select-error"},
		element:null, //jQuery selector/HTML elment
		//skin:"<span class='textfield'></span>", //html string
		skin:false,
		label:false, //jQuery selector
		labelClasses:{base:"label", hover:"label-hover", focus:"label-focus", disabled:"label-disabled", error:"label-error"},
		required:false,
		criteria:/.*/, //regexp, string, function
		initValidate:false,
		errorMessage:"",
		init:function(){
			var I = this;
			
			I.element=j(I.element);			
			if(I.element.data("tbelt.form.Select")!=null){
				I = I.element.data("tbelt.form.Select");
				return;
			}else{
				I.element.data("tbelt.form.Select", I);				
			}
			if(I.element.attr("disabled")) I.disabled();
			
			//try to find label if none is specified
			I.label=j(I.label);
			if(I.label[0]==document) I.label=false;
			
			if((!I.label ||I.label.length==0) && I.element[0].id){
				var lbl = j("label[for='"+I.element[0].id+"']");
				if(lbl.length>0) I.label = lbl;					
				else I.label = false;
			}
			if(I.label!=false){ 
				I.label.data("tbelt.form.Select", I);
				I.label.addClass(I.labelClasses.base);
				I.label.click(I.onLabelClick);
				I.label.hover(I.onLabelHover, I.onLabelHover);
			}
			
			
			I.element.hover(I.onInputHover, I.onInputHover);
			I.element.focus(I.onInputFocus);
			I.element.blur(I.onInputBlur);
			
			if(I.skin!=false){
				I.skin = j(I.skin);
				I.skin.addClass(I.elementClasses.base);
				I.element.wrap(I.skin);	
				I.skin = I.element.closest("."+I.elementClasses.base);
				
				I.skin.click(function(evt){
					//I.element.click();
				});							
				
				//I.skin.hover(function(evt){I.hover(true);}, function(evt){I.hover(false)});
				
			}else{
				I.element.addClass(I.elementClasses.base);
				
				
			}
			
			if(I.initValidate){
				I.validate();
			}
		},
		focus:function(evt){
			var I = this;
			if(evt==null){
				I.element.focus();
				return;
			}
			(I.skin||I.element).addClass(I.elementClasses.focus);	
			
			if(I.label!=false) I.label.addClass(I.labelClasses.focus);			
			j(I).trigger("TextField.focus");
		},
		blur:function(evt){
			var I = this;
			if(evt==null){
				I.element.blur();
				return;
			}
			(I.skin||I.element).removeClass(I.elementClasses.hover);
			(I.skin||I.element).removeClass(I.elementClasses.focus);
			
			if(I.label!=false) I.label.removeClass(I.labelClasses.focus);	
			j(I).trigger("TextField.blur");
		},
		
		disabled:function(toDisable){
			var I = this;
			if(toDisable!=null){
				if(toDisable){
					I.element.attr("disabled","disabled");
					if(I.skin!=false){
						I.skin.addClass(I.elementClasses.disabled);
					}else{
						I.element.addClass(I.elementClasses.disabled);
					}
					if(I.label!=false) I.label.addClass(I.labelClasses.disabled);	
				}else{
					I.element.removeAttr("disabled");
					if(I.skin!=false){
						I.skin.removeClass(I.elementClasses.disabled);
					}else{
						I.element.removeClass(I.elementClasses.disabled);
					}
					if(I.label!=false) I.label.removeClass(I.labelClasses.disabled);	
				}
			}else{
				toDisable = (I.element.attr("disabled"))? true : false;
			}
			j(I).trigger("TextField.disabled");
			return toDisable;
		},
		
		hover:function(isHover){
			var I = this;
			
			if(isHover==true){
				(I.skin||I.element).addClass(I.elementClasses.hover);
				if(I.label!=false) I.label.addClass(I.labelClasses.hover);	
			}else{
				(I.skin||I.element).removeClass(I.elementClasses.hover);
				if(I.label!=false) I.label.removeClass(I.labelClasses.hover);	
				isHover=false;
			}
			return isHover;
		},
		
		validate:function(){
			var I = this;
			var isValid = tbelt.form.validateField(I.element, I.criteria, I.required);
			if(isValid){
				(I.skin||I.element).removeClass(I.elementClasses.error);
				if(I.label!=false) I.label.removeClass(I.labelClasses.error);
			}else{
				(I.skin||I.element).addClass(I.elementClasses.error);
				if(I.label!=false) I.label.addClass(I.labelClasses.error);
			}
			j(I).trigger("Select.validate", isValid);
			return isValid;
		}
		
		
	};
	
	
	
	
	
	return Select;

})(jQuery);tbelt.form.Handler = (function(j){

	function Handler(opts){
		var I = this;
		I.opts = opts;
		j.extend(true, I, I.opts);

		j(document).ready(function(){I.init()});
	}
	
	Handler.prototype={
		opts:null,
		form:null, //jQuery Selector or HTML Element
		fields:[],
		elementClasses:{base:null, error:null}, //{base:"input", error:""}
		labelClasses:{base:null, error:null},
		errorMessageContainer:null, //jQuery Selector or HTML Element
		onError:function(handler, errorMsg){},
		onSuccess:function(handler){},
		
		init:function(){
			var I = this;
			I.form=j(I.form);
			I.fields=[];
			
			I.errorMessageContainer=j(I.errorMessageContainer);
			if(I.errorMessageContainer[0]!=document) I.errorMessageContainer.css({display:"none"});
			
			I.form.data("tbelt.form.Handler", I);
			
			for(var f=0; f<I.opts.fields.length; f++){
				I.addField(I.opts.fields[f]);
			}
			
			if(I.form[0].nodeName.toLowerCase()=="form"){
				I.form.submit(function(evt){
					if(!I.validate()) evt.preventDefault();					
				});				
			}
			
			j(I).trigger("Handler.init");
		},
		
		addField:function(newField){
			var I = this;
			//if a tbelt.form.Checkbox/TextField/Select etc object is NOT being directly passed
			if(newField.validate==null){
				var el = j(newField.element||newField.elements);
				if(el.length==0) return;
				
				var nodeName = el[0].nodeName.toLowerCase();
				if(nodeName=="input"){
					var nodeType = el[0].type.toLowerCase();
					if(nodeType=="text"){
						var existingObj = el.data("tbelt.form.TextField");
						if(!existingObj) newField = new tbelt.form.TextField(newField);
						else newField = existingObj;
					}else if(nodeType=="checkbox" || nodeType=="radio"){
						var existingObj = el.data("tbelt.form.OptionsGroup");
						if(!existingObj) newField = new tbelt.form.OptionsGroup(newField);
						else newField = existingObj;
					}
					
				}else if(nodeName=="select"){
					var existingObj = el.data("tbelt.form.Select");
					if(!existingObj) newField = new tbelt.form.Select(newField);
					else newField = existingObj;
				
				}else if(nodeName=="textarea"){
					var existingObj = el.data("tbelt.form.TextField");
					if(!existingObj) newField = new tbelt.form.TextField(newField);
					else newField = existingObj;
				}
			
			}
			//override base/error classes
			for(prop in I.elementClasses)
				if(I.elementClasses[prop]==null) delete I.elementClasses[prop];
			j.extend(newField.elementClasses, I.elementClasses);
			for(prop in I.labelClasses)
				if(I.labelClasses[prop]==null) delete I.labelClasses[prop];
			j.extend(newField.labelClasses, I.labelClasses);
			I.fields.push(newField);
			
			j(I).trigger("Handler.addField", newField);
			return newField;
		},
		
		validate:function(){
			var I = this;
			var isValid=true;
			var errorMsg="";
			for(var f=0; f<I.fields.length; f++){
				var field = I.fields[f];
				var tmpValid = field.validate();
				if(!tmpValid) {
					isValid=false;
					errorMsg += "<li>"+field.errorMessage+"</li>";
				}
			}
			
			if(isValid) I.onSuccess(I);
			else{
				if(I.errorMessageContainer[0]!=document){
					I.errorMessageContainer.css({display:""});
					I.errorMessageContainer.html("<ul>"+errorMsg+"</ul>");
				}
				I.onError(I, errorMsg);
			}
			j(I).trigger("Handler.validate", isValid, errorMsg);
			return isValid;
		}
	}
	
	return Handler;
	
})(jQuery);
(function($j){

	$j.fn.toArray=function(){
		var array=[];
		this.each(function(i, e){
			array.push(e);
		});
		return array;
	}

	$j.fn.indexOf=function(element){	
		for(var e=0; e<this.length; e++){
			if(this[e]==element) return e;
		}
		return -1;
	}

	$j.fn.splice=function(index, howMany, element){
		var arr = this.toArray();
		arr.splice.apply(arr, arguments);
		this.setArray(arr);
		return this;
	}

	$j.fn.concat=function(arrN){
		var arr = this.toArray();
		arr = arr.concat.apply(arr, arguments);
		this.setArray(arr);
		return this;
	}

	$j.fn.dataDirect=function(name, value){
		for(var e=0; e<this.length; e++){
			if(value==null && this[e][name]!=null && this[e][name]!=undefined)
				return this[e][name];
			else
				this[e][name]=value;
		}
		return this;
	}

	$j.fn.shift=function(){
		var arr = this.toArray();
		arr = arr.shift.apply(arr, arguments);
		return this;
	}

	$j.fn.unshift=function(item){
		var arr = this.toArray();	
		arr = [].concat.apply(item, arr);
		this.setArray(arr);
		return this;
	}

	$j.fn.last=function(){
		return $j(this[this.length-1]);
	}


	$j.fn.outerHTML=function(){
		var html="";
		for(var i=0; i<this.length; i++){
			html += this[i].outerHTML;
		}
		return html;
	}
	
	
	
	window.mouseY=0;
	window.mouseX=0;
	$j(document).mousemove(function(evt){
		window.mouseX = evt.pageX;
		window.mouseY = evt.pageY;
	});	


})(tbelt.jQuery);