/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;




/*
 * The Mojo Framework
 *
 * Copyright (c) 2008, Blast Radius, Inc.
 * All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

var mojo = {
	Version: "0.1b"
};
dojo.provide("mojo.log");
mojo.log = function(E, A, D, C) {
	var B = mojo.widget.Logger;
	if (B && B.log) {
		return B.log(E, A, D, C)
	} else {
		return false
	}
};
dojo.provide("mojo.command.Behavior");
dojo.declare("mojo.command.Behavior", null, {
	_requestObj: null,
	getRequest: function() {
		if (!this._requestObj) {
			throw new Error("ERROR mojo.command.Behavior.getRequest - requestObj is not set")
		}
		return this._requestObj
	},
	_execute: function(B) {
		this._requestObj = B;
		if (typeof(B.update) == "function") {
			B.update()
		}
		if (this._requestObj == null || (!this._requestObj)) {
			throw new Error("ERROR mojo.command.Behavior._execute - requestObj is not set")
		} else {
			if (! (this._requestObj instanceof mojo.controller.Request)) {
				throw new Error("ERROR mojo.command.Behavior._execute - requestObj is not type of mojo.controller.Request")
			} else {
				if (!this._requestObj.callerObj) {
					throw new Error("ERROR mojo.command.Behavior._execute - callerObj is not set")
				}
			}
		}
		if(!this._requestObj.getParams() && typeof(this._requestObj.getParams()) == "boolean") return;
		return this.execute(B)
	},
	execute: function(A) {
		throw new Error("ERROR mojo.command.Behavior.execute - execute() method is not implemented")
	}
});
dojo.provide("mojo.command.Command");
dojo.declare("mojo.command.Command", null, {
	_requestObj: null,
	getRequest: function() {
		if (!this._requestObj) {
			throw new Error("ERROR mojo.command.Command.getRequest - requestObj is not set")
		}
		return this._requestObj
	},
	_execute: function(A) {
		this._requestObj = A;
		if (typeof(A.update) == "function") {
			A.update()
		}
		if (this._requestObj == null || (!this._requestObj)) {
			throw new Error("ERROR mojo.command.Command._execute - requestObj is not set")
		} else {
			if (! (this._requestObj instanceof mojo.controller.Request)) {
				throw new Error("ERROR mojo.command.Command._execute - requestObj is not type of mojo.controller.Request")
			}
		}
		
		if(!this._requestObj.getParams() && typeof(this._requestObj.getParams()) == "boolean") return;
		return this.execute(A)
	},
	execute: function(A) {
		throw new Error("ERROR mojo.command.Command.execute - execute() method is not implemented")
	},
	onResponse: function(A) {
		throw new Error("ERROR mojo.command.Command.onResponse - onResponse() method is not implemented")
	},
	onError: function(A) {
		throw new Error("ERROR mojo.command.Command.onError - onError() method is not implemented")
	}
});
dojo.provide("mojo.command.Rule");
dojo.declare("mojo.command.Rule", null, {
	_requestObj: null,
	getRequest: function() {
		if (!this._requestObj) {
			throw new Error("ERROR mojo.command.Rule.getRequest -requestObj is not set")
		}
		return this._requestObj
	},
	_execute: function(B) {
		this._requestObj = B;
		if (typeof(B.update) == "function") {
			B.update()
		}
		if (this._requestObj == null || (!this._requestObj)) {
			throw new Error("ERROR mojo.command.Rule._execute - requestObj is not set")
		} else {
			if (! (this._requestObj instanceof mojo.controller.Request)) {
				throw new Error("ERROR mojo.command.Rule._execute - requestObj is not type of mojo.controller.Request")
			} else {
				if (!this._requestObj.callerObj) {
					throw new Error("ERROR mojo.command.Rule._execute - callerObj is not set")
				} else {
					if (!this._requestObj.invocation) {
						throw new Error("ERROR mojo.command.Rule._execute - invocation is not set")
					}
				}
			}
		}
		try {
			if (this.execute(B)) {
				return true
			}
			return false
		} catch(A) {}
	},
	execute: function(A) {
		if (this.condition(A)) {
			return A.invocation.proceed()
		}
	},
	condition: function(A) {
		throw new Error("ERROR mojo.command.Rule.condition - condition() method is not implemented")
	}
});
if (!dojo._hasResource["mojo.component.Template"]) {
	dojo._hasResource["mojo.component.Template"] = true;
	dojo.provide("mojo.component.Template");
	dojo.require("dijit.dijit");
	dojo.require("dijit._Widget");
	dojo.require("dijit._Templated");
	dojo.require("dijit._Container");
	dojo.declare("mojo.component.Template", [dijit._Widget, dijit._Templated, dijit._Container], {
		initWithData: false,
		iterate: true,
		escapeHtml: false,
		escapeQuotes: false,
		modelSource: "",
		modelDependency: "",
		templateObj: [],
		templateConditions: [],
		_controllers: null,
		getModelSource: function() {
			if (!this.modelSource) {
				return ""
			}
			return this.modelSource
		},
		getModelDependency: function() {
			if (!this.modelDependency) {
				return ""
			}
			return this.modelDependency
		},
		_modelSourceHandle: null,
		_modelDependencyHandle: null,
		setModelSource: function(A) {
			if (!A) {
				throw new Error("ERROR mojo.component.Template.setModelSource - modelSource parameter is required")
			}
			if (typeof(A) != "string") {
				throw new Error("ERROR mojo.component.Template.setModelSource - modelSource parameter is not type String")
			}
			if (this.getModelSource().length > 0) {
				if (this._modelSourceHandle) {
					mojo.Model.removeObserver(this._modelSourceHandle)
				}
				this.modelSource = A;
				this._modelSourceHandle = mojo.Model.addObserver(this.modelSource, this, "onModelUpdate");
				this.onModelUpdate()
			}
		},
		setModelDependency: function(A) {
			if (!A && A != "") {
				throw new Error("ERROR mojo.component.Template.setModelDependency - modelDependency parameter is required")
			}
			if (typeof(A) != "string") {
				throw new Error("ERROR mojo.component.Template.setModelDependency - modelDependency parameter is not type String")
			}
			this.modelDependency = A;
			if (this._modelDependencyHandle) {
				mojo.Model.removeObserver(this._modelDependencyHandle)
			}
			if (this.modelDependency) {
				this._modelDependencyHandle = mojo.Model.addObserver(this.modelDependency, this, "onModelDependencyUpdate")
			}
			this.onModelDependencyUpdate()
		},
		_getTemplateControllers: function() {
			var B = this.srcNodeRef.parentNode;
			var D = mojo.controller.Map.getInstance();
			var A = [];
			while (B != null) {
				if (B.mojoControllers) {
					for (var C in B.mojoControllers) {
						A.push(B.mojoControllers[C])
					}
				}
				B = B.parentNode
			}
			return A
		},
		buildRendering: function() {
			var C = mojo.query("*[dojoType=mojo.component.Template]", this.srcNodeRef);
			var D = C.length;
			for (var F = 0; F < D; F++) {
				var A = document.createTextNode("{cdata}");
				var E = document.createTextNode("{/cdata}");
				dojo.place(A, C[F], "before");
				dojo.place(E, C[F], "after")
			}
			var K = [];
			this.templateConditions = [];
			var J = mojo.query("> [prototype]", this.srcNodeRef);
			for (var F = 0,
			B, H; F < J.length; F++) {
				this.templateConditions[F] = J[F].getAttribute("prototype");
				K[F] = J[F].innerHTML;
				J[F].style.display = "none"
			}
			if (K.length == 0) {
				K[0] = this.srcNodeRef.innerHTML
			}
			for (var F = 0,
			G = K.length; F < G; F++) {
				K[F] = K[F].replace(/&lt;/g, "<").replace(/&gt;/g, ">");
				K[F] = K[F].replace(/\%21/g, "!").replace(/\%7B/g, "{").replace(/\%7D/g, "}");
				K[F] = this._normalize(K[F]);
				K[F] = TrimPath.parseTemplate(K[F], this.srcNodeRef.id + ":" + F)
			}
			this.templateObj = K;
			var I = this.srcNodeRef.childNodes;
			this.initWithData = ((I.length > J.length) && J.length > 0);
			this.hide();
			this.setModelDependency(this.getModelDependency());
			this.setModelSource(this.getModelSource())
		},
		_bindToModel: function() {
			var modifiers = {
				escapeQuotes: function(str) {
					str = str.toString();
					str = str.replace(/\"/g, "&#34;");
					str = str.replace(/\'/g, "&#39;");
					return str
				}
			};
			var sModel = this.getModelSource();
			if (sModel.length > 0 && mojo.Model.contains(sModel) && this.srcNodeRef) {
				var modelData = mojo.Model.get(sModel);
				var result = new Array();
				if (!dojo.isArray(modelData)) {
					modelData = [modelData]
				}
				var modelDataLength = modelData.length;
				if (!this.iterate && modelDataLength > 0) {
					modelDataLength = 1
				}
				var iActiveTemplate = 0;
				if (modelDataLength > 0 && modelData[0] != null) {
					with(modelData[0]) {
						for (var i = 0,
						len = this.templateConditions.length; i < len; i++) {
							try {
								if (this.templateConditions[i].toLowerCase() == "true" || eval(this.templateConditions[i])) {
									iActiveTemplate = i;
									break
								}
							} catch(e) {}
						}
					}
				}
				for (var i = 0,
				len = modelDataLength; i < len; i++) {
					if (modelData[i]) {
						if (typeof(modelData[i]) != "object") {
							var tmpModelData = modelData[i].toString();
							modelData[i] = new Object();
							modelData[i].data = tmpModelData
						}
						modelData[i].currentIndex = i;
						modelData[i].totalLength = len;
						if (this.escapeQuotes) {
							modelData[i]._MODIFIERS = modifiers;
							modelData[i].content = modifiers.escapeQuotes(modelData[i].content)
						}
						result.push(this.templateObj[iActiveTemplate].process(modelData[i]))
					}
				}
				if (!this._controllers) {
					this._controllers = this._getTemplateControllers()
				}
				var templateNode = this.srcNodeRef;
				var content = result.join("");
				templateNode.innerHTML = "";
				templateNode.innerHTML = content;
				var inlineDijits = mojo.query("*[dojoType='mojo.component.Template']", this.srcNodeRef);
				var inlineDijitsLength = inlineDijits.length;
				var allowedAttributes = ["escapeHtml", "escapeQuotes", "modelSource", "modelDependency"];
				var attributeCount = allowedAttributes.length;
				for (var i = 0; i < inlineDijitsLength; i++) {
					var dijitParams = {};
					var attributeAsTemplate;
					for (var j = 0; j < attributeCount; j++) {
						if (inlineDijits[i].getAttribute(allowedAttributes[j])) {
							attributeValue = inlineDijits[i].getAttribute(allowedAttributes[j]);
							if (/[\!|\$]\{[^\}]*\}/.test(attributeValue)) {
								attributeAsTemplate = this._normalize(attributeValue);
								attributeAsTemplate = TrimPath.parseTemplate(attributeAsTemplate);
								attributeValue = attributeAsTemplate.process(modelData[i])
							}
							dijitParams[allowedAttributes[j]] = attributeValue
						}
					}
					var newDijit = new mojo.component.Template(dijitParams, inlineDijits[i])
				}
				var parent = this.srcNodeRef.parentNode;
				while (parent != null) {
					if (parent.id && dijit.byId(parent.id)) {
						var widget = dijit.byId(parent.id);
						if (widget["sync"] && typeof(widget["sync"]) == "function") {
							widget.sync()
						}
					}
					parent = parent.parentNode
				}
				if (!this._controllers) {
					this._controllers = this._getTemplateControllers()
				}
				if (this._controllers && mojo.Model.contains("__mojoTemplateControllers")) {
					var controllersLength = this._controllers.length;
					for (var i = 0; i < controllersLength; i++) {
						this._controllers[i].updateController = true;
						mojo.Model.get("__mojoTemplateControllers").push(this._controllers[i])
					}
				}
				this.show()
			} else {
				if (!this.initWithData) {
					this.initWithData = false;
					this.hide()
				}
			}
		},
		hide: function() {
			if (this.srcNodeRef) {
				dojo.style(this.srcNodeRef, "display", "none")
			}
		},
		show: function() {
			if (this.srcNodeRef) {
				dojo.style(this.srcNodeRef, "display", "block")
			}
		},
		_replacedNode: null,
		_normalize: function(E) {
			var D = /[\!|\$]\{[^\}]*\}/g;
			var B = E.match(D);
			var F = E.split(D);
			var I = new Array();
			var A = 0;
			if (B) {
				A = B.length
			}
			for (var C = 0; C < A; C++) {
				I.push(F[C]);
				var H = "$" + B[C].substring(1);
				var G = "";
				if (this.escapeHtml) {
					G += "|escape"
				}
				if (this.escapeQuotes) {
					G += "|escapeQuotes"
				}
				H = H.substring(0, H.length - 1) + G + "}";
				I.push(H)
			}
			I.push(F[A]);
			return I.join("")
		},
		onModelUpdate: function() {
			if (this.getModelDependency().length == 0 || this._dependencyMet) {
				this._bindToModel()
			}
		},
		_dependencyMet: false,
		onModelDependencyUpdate: function() {
			if (this.getModelDependency().length > 0 && mojo.Model.contains(this.getModelDependency())) {
				this._dependencyMet = true;
				this.onModelUpdate()
			} else {
				this._dependencyMet = false
			}
		}
	})
}
dojo.provide("mojo.controller.Controller");
dojo.declare("mojo.controller.Controller", null, {
	constructor: function(A, B) {
		this._init(A, B)
	},
	_contextElementObj: null,
	_commands: new Array(),
	_connectHandles: new Array(),
	_queryCache: new Object(),
	_observers: new Object(),
	_tags: new Array(),
	_init: function(A, E) {
		if (this.params) {
			var D = {};
			D.onChange = function() {};
			var F = this._getBaseProperty("params");
			for (var B in F) {
				if (typeof F[B] == "object") {
					var C = F[B];
					D[B] = new mojo.controller.Param(B, dojo.clone(C.defaultValue), C.required, C.type, D);
					if (E) {
						D[B].setValue(E[B])
					}
				}
			}
			for (var B in this.params) {
				if (typeof this.params[B] == "object") {
					var C = this.params[B];
					D[B] = new mojo.controller.Param(B, dojo.clone(C.defaultValue), C.required, C.type, D);
					if (E) {
						D[B].setValue(E[B])
					}
				}
			}
			this.params = D;
			D = null;
			E = null
		}
		this._contextElementObj = null;
		if (A) {
			this._contextElementObj = A
		}
		this._commands = new Array();
		this._tags = new Array();
		this._connectHandles = new Array();
		this._callBaseMethod("addCommands");
		this.addCommands();
		this._addObservers();
		this._callBaseMethod("addIntercepts");
		this.addIntercepts();
		this.onInit();
		if (this.params) {
			for (var B in this.params) {
				if (typeof this.params[B] == "object") {
					var C = this.params[B];
					if (C.getValue() != null) {
						C.onChange()
					}
				}
			}
		}
		mojo.Messaging.subscribe("/mojo/controller/" + this.declaredClass + "/addObservers", this, "_addObservers");
		mojo.Messaging.subscribe("/mojo/controller/addObservers", this, "_addObservers")
	},
	getConfig: function(A) {
		A = A.toLowerCase();
		switch (A) {
		case "params":
			return this[A];
			break
		}
		return null
	},
	getValue: function(A) {
		return this.params[A].getValue()
	},
	setValue: function(B, A) {
		this.params[B].setValue(A)
	},
	getContextController: function(A) {
		if (this.getContextElement() && this.getContextElement().mojoControllers[A]) {
			return this.getContextElement().mojoControllers[A]
		}
		return null
	},
	_getBaseProperty: function(propertyName) {
		var superclass = eval(this.declaredClass + ".superclass");
		if (superclass.declaredClass != "mojo.controller.Controller" && superclass[propertyName]) {
			return superclass[propertyName]
		}
		return null
	},
	_callBaseMethod: function(A) {
		var B = this._getBaseProperty(A);
		if (B) {
			B.call(this)
		}
	},
	getContextElement: function() {
		if (!this._contextElementObj) {
			return null
		}
		return this._contextElementObj
	},
	onInit: function() {},
	_addObservers: function() {
		this._queryCache = new Object();
		this._observers = new Object();
		this._callBaseMethod("addObservers");
		this.addObservers();
		for (var B in this._queryCache) {
			if (this._queryCache[B]["length"]) {
				for (var D in this._observers[B]) {
					if (this._observers[B][D]["length"]) {
						var C = this._queryCache[B].length;
						for (var A = 0; A < C; A++) {
							this._addObserver(this._queryCache[B][A], D, this._observers[B][D])
						}
					}
				}
			}
		}
		this._queryCache = new Object();
		this._observers = new Object()
	},
	addObservers: function() {
		throw new Error("ERROR mojo.controller.Controller.addObservers - addObservers() method is not implemented")
	},
	removeObservers: function() {
		var A = this._connectHandles.length;
		for (var B = 0; B < A; B++) {
			dojo.disconnect(this._connectHandles[B])
		}
	},
	addObserver: function(I, E, H, F) {
		var A = function(K) {
			if (!dojo.isArray(K)) {
				return false
			}
			for (var L = 0,
			J = K.length; L < J; L++) {
				if (typeof(K[L]) != "string") {
					return false
				}
			}
			return true
		};
		if (!I) {
			return
		}
		if (!E) {
			throw new Error("ERROR mojo.controller.Controller.addObserver - srcFunc is not set")
		}
		if (typeof(E) != "string") {
			throw new Error("ERROR mojo.controller.Controller.addObserver - srcFunc is not type String")
		}
		if (!H) {
			throw new Error("ERROR mojo.controller.Controller.addObserver - cmdName is not set")
		}
		if (typeof(H) != "string" && H != null) {
			throw new Error("ERROR mojo.controller.Controller.addObserver - cmdName is not type String")
		}
		if (typeof(I) == "string" || A(I)) {
			if (!dojo.isArray(I)) {
				I = [I]
			}
			for (var D = 0,
			G = I.length; D < G; D++) {
				var C = I[D];
				if (this.getContextElement() && E.match(/^onclick|onmouse|onkey|onmove/) != null) {
					this._addObserver(this.getContextElement(), E, [{
						cmdName: H,
						paramsObj: F,
						eventDelegate: C
					}])
				} else {
					if (!this._queryCache[C]) {
						this._queryCache[C] = mojo.query(C, this.getContextElement())
					}
					if (!this._observers[C]) {
						this._observers[C] = new Object()
					}
					if (!this._observers[C][E]) {
						this._observers[C][E] = new Array()
					}
					var B = this._observers[C][E].length;
					this._observers[C][E][B] = {
						cmdName: H,
						paramsObj: F
					}
				}
			}
		} else {
			if (!dojo.isArray(I)) {
				I = [I]
			}
			for (var D = 0,
			G = I.length; D < G; D++) {
				this._addObserver(I[D], E, [{
					cmdName: H,
					paramsObj: F
				}])
			}
		}
		if (! (this._commands[H]) || this._commands[H] == null) {
			throw new Error("ERROR mojo.controller.Controller.addObserver - cmdName does not reference a Command in the Controller")
		}
	},
	_addObserver: function(J, D, A) {
		var B = new Array();
		var E = A.length;
		for (var C = 0; C < E; C++) {
			if (typeof(A[C].eventDelegate) == "undefined") {
				A[C].eventDelegate = ""
			}
			if (!this._observerIsTagged(J, D + A[C].eventDelegate, A[C])) {
				B.push(A[C]);
				this._tagObserver(J, D + A[C].eventDelegate, A[C])
			}
		}
		if (!J.mojoObservers) {
			J.mojoObservers = new Object()
		}
		if (!J.mojoObservers[D]) {
			J.mojoObservers[D.toLowerCase()] = new Array()
		}
		if (B.length > 0) {
			var H = this;
			var G = function(O) {
				var N = function(S) {
					var S = S || window.event;
					var R = S.target || S.srcElement;
					if (R.nodeType == 3) {
						R = R.parentNode
					}
					return R
				};
				if (H.getContextElement() && H.getContextElement().parentNode == null) {
					H.removeObservers()
				} else {
					var P = B.length;
					for (var L = 0; L < P; L++) {
						if (typeof(mojo) != "undefined") {
							var K = J;
							if (B[L].eventDelegate.length > 0) {
								var M = N(O);
								K = mojo.queryMatch(M, B[L].eventDelegate, H.getContextElement(), true)
							}
							if (K != null) {
								var Q = H._setRequest(B[L].paramsObj, K, O, B[L].cmdName);
								H.fireCommandChain(B[L].cmdName, Q)
							}
						}
					}
				}
			};
			var I = D.toLowerCase();
			if ((I == "onmouseleave" || I == "onmouseenter") && MooTools && Element.Events.mouseleave && Element.Events.mouseenter) {
				$(J).addEvent(D.replace("on", ""), G)
			} else {
				var F = dojo.connect(J, D, G);
				this._connectHandles.push(F)
			}
			J.mojoObservers[D.toLowerCase()].push(G)
		}
	},
	_tagObserver: function(A, E, D) {
		if (!A.mojoObserve) {
			A.mojoObserve = new Object()
		}
		if (typeof A.mojoObserve[this.declaredClass] == "undefined") {
			var F = this._tags.length;
			A.mojoObserve[this.declaredClass] = F;
			this._tags[F] = new Object()
		}
		var C = A.mojoObserve[this.declaredClass];
		var B = this._generateTagKey(E, D);
		if (this._tags[C] && !this._tags[C][B]) {
			this._tags[C][B] = true
		}
	},
	_generateTagKey: function(D, C) {
		var B = D + "_" + C.cmdName;
		if (C.paramsObj) {
			var E;
			if (typeof(C.paramsObj) == "function") {
				E = C.paramsObj.toString()
			} else {
				if (typeof(C.paramsObj) == "object") {
					for (var A in C.paramsObj) {
						if (C.paramsObj[A]) {
							E += A + ":" + C.paramsObj[A].toString() + ","
						}
					}
				}
			}
			B += "_" + E
		}
		return B
	},
	_observerIsTagged: function(A, D, C) {
		if (!A.mojoObserve) {
			A.mojoObserve = new Object()
		}
		var E = false;
		var B = this._generateTagKey(D, C);
		if (typeof A.mojoObserve[this.declaredClass] != "undefined" && this._tags[A.mojoObserve[this.declaredClass]] && this._tags[A.mojoObserve[this.declaredClass]][B]) {
			E = true
		}
		return E
	},
	addCommands: function() {
		throw new Error("ERROR mojo.controller.Controller.addCommands - addCommands() method is not implemented")
	},
	addCommand: function(cmdName, cmdObjPath) {
		if (!cmdName) {
			throw new Error("ERROR mojo.controller.Controller.addCommand - cmdName is not set")
		}
		if (typeof(cmdName) != "string") {
			throw new Error("ERROR mojo.controller.Controller.addCommand - cmdName is not type String")
		}
		if (!cmdObjPath) {
			throw new Error("ERROR mojo.controller.Controller.addCommand - cmdObjPath is not set")
		}
		if (typeof(cmdObjPath) != "string") {
			throw new Error("ERROR mojo.controller.Controller.addCommand - cmdObjPath is not type String")
		}
		if (!this._commands[cmdName]) {
			this._commands[cmdName] = new Array()
		}
		var addFunc = function(cmdName, cmdObjPath, thisObj) {
			dojo.require(cmdObjPath);
			var cmdObj = eval("new " + cmdObjPath + "()");
			if ((cmdObj instanceof mojo.command.Command) || (cmdObj instanceof mojo.command.Rule || (cmdObj instanceof mojo.command.Behavior))) {
				thisObj._commands[cmdName].push(cmdObj)
			} else {
				throw new Error("ERROR mojo.controller.Controller.addCommand - Command object is not type mojo.command.Command or mojo.command.Behavior or mojo.command.Rule")
			}
		};
		addFunc(cmdName, cmdObjPath, this)
	},
	getCommand: function(A) {
		if (!A) {
			throw new Error("ERROR mojo.controller.Controller.getCommand - cmdName is not set")
		}
		if (typeof(A) != "string") {
			throw new Error("ERROR mojo.controller.Controller.getCommand - cmdName is not type String")
		}
		if (this._commands[A]) {
			return this._commands[A][0]
		}
		throw new Error("ERROR mojo.controller.Controller.getCommand - cmdName does not reference a Command in the Controller")
	},
	getCommandChain: function(A) {
		if (!A) {
			throw new Error("ERROR mojo.controller.Controller.getCommandChain - cmdName is not set")
		}
		if (typeof(A) != "string") {
			throw new Error("ERROR mojo.controller.Controller.getCommandChain - cmdName is not type String")
		}
		if (!this._commands[A]) {
			throw new Error("ERROR mojo.controller.Controller.getCommandChain - cmdName does not reference a Command in the Controller")
		}
		if (this._commands[A]) {
			return this._commands[A]
		}
		return null
	},
	fireCommandChain: function(A, D) {
		var C = this._commands[A].length;
		for (var B = 0; B < C; B++) {
			this._commands[A][B]._execute(D)
		}
	},
	addIntercepts: function() {
		throw new Error("ERROR mojo.controller.Controller.addIntercepts - addIntercepts() method is not implemented")
	},
	addIntercept: function(G, F, B, E) {
		if (!G) {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - interceptType is not set")
		}
		if (typeof(G) != "string") {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - interceptType is not type String")
		}
		if (G == "before" || G == "after" || G == "around") {} else {
			throw new Error('ERROR mojo.controller.Controller.addIntercept - interceptType is not "before", "after", or "around"')
		}
		if (!F) {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - interceptCmdName is not set")
		}
		if (typeof(F) != "string") {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - interceptCmdName is not type String")
		}
		if (!B) {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - cmdName is not set")
		}
		if (typeof(B) != "string") {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - cmdName is not type String")
		}
		if (F.toString() == B.toString()) {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - a command cannot add advice to itself")
		}
		if (!this._commands[F]) {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - interceptCmdName does not reference a Command in the Controller")
		}
		if (!this._commands[B]) {
			throw new Error("ERROR mojo.controller.Controller.addIntercept - cmdName does not reference a Command in the Controller")
		}
		var C = this;
		var D = this.getCommand(F)["_execute"];
		var A = function(H) {
			if (typeof(mojo) != "undefined") {
				requestObj = C._setRequest(E, H.args[0].callerObj, H.args[0].eventObj, B, H);
				C.fireCommandChain(B, requestObj)
			}
		};
		switch (G) {
		case "before":
			this._commands[F][0]["_execute"] = function() {
				var H = {
					args: arguments,
					calleeObj: this
				};
				A.apply(this, [H]);
				return D.apply(this, arguments)
			};
			break;
		case "after":
			this._commands[F][0]["_execute"] = function() {
				var H = {
					args: arguments,
					calleeObj: this
				};
				D.apply(this, arguments);
				return A.apply(this, [H])
			};
			break;
		case "around":
			this._commands[F][0]["_execute"] = function() {
				var H = {
					args: arguments,
					calleeObj: this
				};
				H.proceed = function() {
					return D.apply(this.calleeObj, this.args)
				};
				return A.apply(this, [H])
			};
			break
		}
	},
	_setRequest: function(E, A, C, B, D) {
		var F = new mojo.controller.Request(E, A, C, B, this, D);
		return F
	}
});
mojo.controller.Controller.updateObservers = function(A) {
	if (A) {
		mojo.Messaging.publish("/mojo/controller/" + A + "/addObservers")
	} else {
		mojo.Messaging.publish("/mojo/controller/addObservers")
	}
};
dojo.provide("mojo.controller.Map");
__mojoControllerMap = null;
dojo.declare("mojo.controller.Map", null, {
	onComplete: function() {},
	constructor: function() {
		mojo.Messaging.subscribe("/mojo/controller/mapControllers", this, "mapControllers")
	},
	_controllers: new Array(),
	_siteMap: null,
	getSiteMap: function() {
		if (!this._siteMap) {
			throw new Error("ERROR mojo.controller.Map - siteMap not set")
		}
		return this._siteMap
	},
	setSiteMap: function(F) {
		if (F == null || typeof F == "undefined") {
			throw new Error("ERROR mojo.controller.Map.setSiteMap - siteMapObj parameter is required")
		}
		var B = function() {
			throw new Error('ERROR mojo.controller.Map.setSiteMap - siteMapObj parameter must consist of patterns in the format {pattern: "pattern", controllers: [{controller: "controller.path"}]}')
		};
		if (!dojo.isArray(F)) {
			B()
		}
		for (var D = 0,
		A = F.length; D < A; D++) {
			var E = F[D];
			if (typeof E.pattern == "undefined" || E.pattern == null) {
				B()
			}
			if (!dojo.isArray(E.controllers)) {
				B()
			}
			for (var C = 0,
			A = E.controllers.length; C < A; C++) {
				if (typeof E.controllers[C].controller == "undefined" || !dojo.isString(E.controllers[C].controller) || E.controllers[C].controller == "") {
					B()
				}
			}
		}
		for (pattern in F) {}
		this._siteMap = F
	},
	mapControllers: function(C) {
		var B = this.getSiteMap();
		var I = B.length;
		for (var E = 0; E < I; E++) {
			var G = B[E].pattern;
			if (typeof(G) == "string") {
				var A = [];
				if (C && typeof(C) == "object") {
					A = mojo.query(G, C)
				} else {
					A = mojo.query(G)
				}
				var F = A.length;
				for (var D = 0; D < F; D++) {
					this._mapControllers(B[E].controllers, A[D])
				}
			} else {
				if (typeof(G) == "function" || typeof(G) == "object") {
					if (C && typeof(C) == "string") {
						var H = new RegExp(G);
						if (H.test(C)) {
							this._mapControllers(B[E].controllers)
						}
					}
				} else {
					alert(G);
					throw new Error("ERROR mojo.controller.Map - siteMap contains invalid pattern")
				}
			}
		}
		this.onComplete()
	},
	_mapControllers: function(F, A) {
		var B = F.length;
		for (var D = 0; D < B; D++) {
			var E = F[D].controller;
			var G = F[D].params;
			if (djConfig && djConfig.isDebug) {
				try {
					this.mapController(E, A, G)
				} catch(C) {
					console.debug("EXCEPTION: " + C.message + " in mojo.controller.Map.mapController() for controller: " + E)
				}
			} else {
				this.mapController(E, A, G)
			}
		}
	},
	mapController: function(controllerName, contextElementObj, controllerParams) {
		if (controllerName == null || typeof controllerName == "undefined") {
			throw new Error("ERROR mojo.controller.Map.mapController - controllerName parameter is required")
		}
		if (!dojo.isString(controllerName) || controllerName == "") {
			throw new Error("ERROR mojo.controller.Map.mapController - controllerName parameter must be a non-empty string")
		}
		dojo.require(controllerName);
		if (contextElementObj) {
			if (!contextElementObj.mojoControllers) {
				contextElementObj.mojoControllers = {}
			}
			if (!contextElementObj.mojoControllers[controllerName]) {
				contextElementObj.mojoControllers[controllerName] = eval("new " + controllerName + "(contextElementObj, controllerParams)");
				if (! (contextElementObj.mojoControllers[controllerName] instanceof mojo.controller.Controller)) {
					throw new Error('ERROR mojo.controller.Map.mapController - "' + controllerName + '" must be an instance of mojo.controller.Controller')
				}
			}
		} else {
			if (!this._controllers[controllerName]) {
				this._controllers[controllerName] = eval("new " + controllerName + "(null, controllerParams)");
				if (! (this._controllers[controllerName] instanceof mojo.controller.Controller)) {
					throw new Error('ERROR mojo.controller.Map.mapController - "' + controllerName + '" must be an instance of mojo.controller.Controller')
				}
			}
		}
	}
});
mojo.controller.Map.mapControllers = function(A) {
	mojo.Messaging.publish("/mojo/controller/mapControllers", [A])
};
mojo.controller.Map.getInstance = function() {
	if (__mojoControllerMap == null) {
		__mojoControllerMap = new mojo.controller.Map()
	}
	return __mojoControllerMap
};
dojo.provide("mojo.controller.Param");
dojo.declare("mojo.controller.Param", null, {
	constructor: function(C, A, E, D, B) {
		this._value = null;
		this._defaultValue = null;
		this._params = null;
		this._type = null;
		this._name = C;
		this._defaultValue = A;
		if (D) {
			this._type = D
		}
		if (B) {
			this._params = B
		}
		this.setValue(this._defaultValue);
		if (typeof E == "boolean") {
			this._required = E
		}
	},
	_name: null,
	_value: null,
	_defaultValue: null,
	_required: false,
	_type: null,
	_params: null,
	getName: function() {
		return this._name
	},
	getValue: function() {
		return this._value
	},
	setValue: function(B) {
		var D = mojo.helper.Validation.getInstance();
		var C = this.getRequired();
		var A = this.getType();
		if (C && !D.isRequired(B)) {
			throw new Error("ERROR mojo.controller.Param.setValue - value parameter is required")
		}
		if (typeof B == "undefined") {
			return
		}
		if (A && !D.isType(B, {
			type: A
		})) {
			throw new Error("ERROR mojo.controller.Param.setValue - value parameter is invalid type")
		}
		if (this.getValue() != B) {
			this._value = B;
			this.onChange();
			if (this._params != null && this._params["onChange"]) {
				this._params.onChange()
			}
		}
	},
	getDefaultValue: function() {
		return this._defaultValue
	},
	getRequired: function() {
		return this._required
	},
	getType: function() {
		return this._type
	},
	onChange: function() {}
});
dojo.provide("mojo.controller.Request");
dojo.declare("mojo.controller.Request", null, {
	constructor: function(F, A, D, B, C, E) {
		this._paramsFunc = null;
		this.paramsObj = null;
		this.callerObj = null;
		this.eventObj = null;
		this.commandName = null;
		this.controllerObj = null;
		this.invocation = null;
		if (typeof(F) == "function") {
			this.paramsObj = {};
			this._paramsFunc = F
		} else {
			if (typeof(F) == "object") {
				this.paramsObj = F
			}
		}
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.controller.Request.constructor - callerObj is not set")
		} else {
			this.callerObj = A
		}
		this.eventObj = D;
		if (B == null || typeof B == "undefined") {
			throw new Error("ERROR mojo.controller.Request.constructor - commandName is not set")
		} else {
			if (typeof B != "string") {
				throw new Error("ERROR mojo.controller.Request.constructor - commandName is not type String")
			} else {
				this.commandName = B
			}
		}
		if (C == null || typeof C == "undefined") {
			throw new Error("ERROR mojo.controller.Request.constructor - controllerObj is not set")
		} else {
			if (! (C instanceof mojo.controller.Controller)) {
				throw new Error("ERROR mojo.controller.Request.constructor - controllerObj is not type mojo.controller.Controller")
			} else {
				this.controllerObj = C
			}
		}
		this.invocation = E
	},
	_paramsFunc: null,
	paramsObj: null,
	callerObj: null,
	eventObj: null,
	commandName: null,
	controllerObj: null,
	invocation: null,
	update: function() {
		if (this._paramsFunc && typeof(this._paramsFunc) == "function") {
			var A = this._paramsFunc(this.getContextElement(), this.getCaller(), this.getController());
			for (var B in A) {
				this.paramsObj[B] = A[B]
			}
		}
	},
	getParams: function() {
		if (!this.paramsObj) {
			this.update()
		}
		return this.paramsObj
	},
	getCaller: function() {
		return this.callerObj
	},
	getContextElement: function() {
		return this.getController().getContextElement()
	},
	getEvent: function() {
		return this.eventObj
	},
	getCommandName: function() {
		return this.commandName
	},
	getController: function() {
		return this.controllerObj
	},
	getControllerName: function() {
		return this.getController().declaredClass
	},
	getInvocation: function() {
		return this.invocation
	}
});
dojo.provide("mojo.helper.Events");
mojo.fireEvent = function(B, A) {
	var C = B.mojoObservers[A.toLowerCase()];
	if (C) {
		C.forEach(function(D) {
			D()
		})
	}
};
dojo.provide("mojo.helper.ObjectQuery");
mojo.helper.ObjectQuery.select = function(A, C) {
	var E = mojo.helper.ObjectQuery._createSchema(A);
	var B = TrimPath.makeQueryLang(E);
	var D = B.parseSQL(C);
	return D.filter(A)
};
mojo.helper.ObjectQuery._createSchema = function(B) {
	var D = {};
	if (B) {
		if (dojo.isArray(B)) {
			B = B[0]
		}
		for (var E in B) {
			D[E] = {};
			var A = B[E];
			if (dojo.isArray(A)) {
				A = A[0]
			}
			for (var C in A) {
				if (typeof(A[C]).toString().toLowerCase().indexOf("number") > -1) {
					D[E][C] = {
						type: "Number"
					}
				} else {
					D[E][C] = {
						type: "String"
					}
				}
			}
		}
	}
	return D
};
dojo.provide("mojo.helper.String");
mojo.toSentenceCase = function(A) {
	return A.charAt(0).toUpperCase() + A.replace(/ \w/g,
	function(B) {
		return B.toUpperCase()
	}).substring(1)
};
dojo.provide("mojo.helper.Validation");
dojo.require("dojox.validate");
dojo.require("dojox.validate.web");
var __mojoHelperValidation = null;
dojo.declare("mojo.helper.Validation", null, {
	isRequired: function(A) {
		if (typeof A == "undefined" || A == null) {
			return false
		}
		if (dojo.isString(A)) {
			return dojo.string.trim(A).length > 0
		}
		return true
	},
	isType: function(A, B) {
		switch (B.type) {
		case String:
			return (typeof A == "string" || A instanceof String);
			break;
		case Number:
			return (typeof A == "number" || A instanceof Number);
			break;
		case Boolean:
			return (typeof A == "boolean" || A instanceof Boolean);
			break;
		default:
			return (A instanceof B.type)
		}
	},
	isEmailAddress: function(A) {
		if (A == null) {
			throw new Error("ERROR mojo.helper.Validation.isEmailAddress - value parameter is required")
		}
		if (!dojo.isString(A)) {
			throw new Error("ERROR mojo.helper.Validation.isEmailAddress - value parameter must be a non-empty string")
		}
		if (!dojox.validate.isEmailAddress(A, {}) || A.match(/[^\w-_@\.]/gi)) {
			return false
		}
		return true
	},
	isEmailAddressList: function(A) {
		if (A == null) {
			throw new Error("ERROR mojo.helper.Validation.isEmailAddressList - value parameter is required")
		}
		if (!dojo.isString(A)) {
			throw new Error("ERROR mojo.helper.Validation.isEmailAddressList - value parameter must be a non-empty string")
		}
		if (!dojox.validate.isEmailAddressList(A, {})) {
			return false
		}
		return true
	},
	isUrl: function(A) {
		if (A == null) {
			throw new Error("ERROR mojo.helper.Validation.isUrl - value parameter is required")
		}
		if (!dojo.isString(A)) {
			throw new Error("ERROR mojo.helper.Validation.isUrl - value parameter must be a non-empty string")
		}
		return dojox.validate.isUrl(A, {
			allowLocal: true
		})
	},
	isLength: function(A, B) {
		if ((A == null) || (A == "")) {
			return true
		}
		if (!dojo.isString(A)) {
			throw new Error("ERROR mojo.helper.Validation.isLength - value parameter must be a string")
		}
		if (B) {
			if (B.min && B.min > A.length) {
				return false
			}
			if (B.max && B.max < A.length) {
				return false
			}
		}
		return true
	},
	isRange: function(A, B) {
		if ((A == null) || (A == "")) {
			return true
		}
		A = parseInt(A);
		if (isNaN(A)) {
			return false
		}
		if (B) {
			if (typeof(B.min) == "undefined") {
				B.min = 0
			}
			if (B.min > A) {
				return false
			}
			if (typeof(B.max) != "undefined" && B.max < A) {
				return false
			}
		}
		return true
	},
	isMatch: function(A, B) {
		if ((A == null) || (A == "")) {
			return true
		}
		if (B) {
			if (B.refValue) {
				B.regex = "^" + B.refValue + "$"
			}
			if (! (new RegExp(B.regex)).test(A)) {
				return false
			}
		}
		return true
	},
	isZipCode: function(D) {
		var B = "0123456789-";
		var C = 0;
		if ((D == null) || (D == "")) {
			return true
		}
		if (D.length != 5 && D.length != 10) {
			return false
		}
		for (var A = 0; A < D.length; A++) {
			temp = "" + D.substring(A, A + 1);
			if (temp == "-") {
				C++
			}
			if (B.indexOf(temp) == "-1") {
				return false
			}
			if ((C > 1) || ((D.length == 10) && "" + D.charAt(5) != "-")) {
				return false
			}
		}
		return true
	},
	isPostalCode: function(A) {
		if (A == null) {
			throw new Error("ERROR mojo.helper.Validation.isPostalCode - value parameter is required")
		}
		if (!dojo.isString(A)) {
			throw new Error("ERROR mojo.helper.Validation.isPostalCode - value parameter must be a non-empty string")
		}
		if (typeof A == "undefined" || A == null) {
			return false
		}
		if (A.length == 6 && A.search(/^[a-zA-Z]\d[a-zA-Z]\d[a-zA-Z]\d$/) != -1) {
			return true
		} else {
			if (A.length == 7 && A.search(/^[a-zA-Z]\d[a-zA-Z](-|\s)\d[a-zA-Z]\d$/) != -1) {
				return true
			} else {
				return false
			}
		}
		return true
	},
	execute: function(I, T) {
		if (typeof I == "undefined" || I == null) {
			throw new Error("ERROR mojo.helper.Validation.execute - rulesObj parameter is required")
		}
		if (typeof T == "undefined" || T == null) {
			throw new Error("ERROR mojo.helper.Validation.execute - domElmListObj parameter is required")
		}
		var S = function() {
			throw new Error('ERROR mojo.helper.Validation.execute - rulesObj parameter must consist of rules in the format {"inputName": [{rule: testFunction[, errorMsg: "msg"]}[, ...]]}')
		};
		if (!dojo.isArray(T)) {
			T = [T]
		}
		for (rule in I) {
			if (!dojo.isArray(I[rule])) {
				S()
			}
			for (var P = 0,
			Q = I[rule].length; P < Q; P++) {
				if (typeof I[rule][P].rule != "function") {
					S()
				}
				if (typeof I[rule][P].error != "undefined" && !dojo.isString(I[rule][P].error)) {
					S()
				}
			}
		}
		var F = function(b, a) {
			if (!b) {
				return null
			}
			do {
				b = b.nextSibling
			} while ( b && b . nodeType != 1 );
			if (b && a && a.toLowerCase() != b.tagName.toLowerCase()) {
				return F(b, a)
			}
			return b
		};
		var B = new Array();
		var D = T.length;
		for (var P = 0; P < D; P++) {
			var C = mojo.query("*[name]", T[P]);
			if (T[P].name) {
				C.push(T[P])
			}
			var X = C.length;
			for (var O = 0; O < X; O++) {
				B.push(C[O])
			}
			B = mojo.distinct(B);
			var R = mojo.query(".mojoValidationError", T[P]);
			var U = F(T[P], "SPAN");
			if (U != null && dojo.hasClass(U, "mojoValidationError")) {
				R.push(U)
			}
			var W = R.length;
			for (var O = 0; O < W; O++) {
				dojo._destroyElement(R[O])
			}
		}
		var N = true;
		var E = new Array();
		var J = function(b) {
			var a = true;
			while (b != null) {
				if (dojo.style(b, "visibility") == "hidden" || dojo.style(b, "display") == "none") {
					a = false;
					break
				}
				b = (b.tagName == "BODY") ? null: b.parentNode
			}
			return a
		};
		var L = B.length;
		var V = {};
		for (var P = (L - 1); P >= 0; P--) {
			var H = B[P];
			if (H.type == "radio" || H.type == "checkbox") {
				H.mojoValidationGroup = true;
				if (!V[H.name]) {
					V[H.name] = new Array()
				} else {
					B[P] = null
				}
				if (H.checked) {
					V[H.name].push((H.value) ? H.value: "checked")
				}
			}
		}
		for (var P = 0; P < L; P++) {
			var H = B[P];
			if (H) {
				if (I[H.name]) {
					var Z = I[H.name];
					var G = Z.length;
					for (var O = 0; O < G; O++) {
						var A = Z[O];
						if (A["force"] || (J(H) && !H.disabled) || (H.type && H.type == "hidden")) {
							if (A.params && A.params.ref) {
								var Y = mojo.queryFirst('*[name="' + A.params.ref + '"]').value;
								if (Y && Y.length > 0) {
									A.params.refValue = Y
								}
							}
							var K = H.value;
							if (H.mojoValidationGroup) {
								K = V[H.name].toString()
							}
							if (! (A.rule(K, A.params))) {
								var M = {
									element: H,
									message: A["errorMsg"]
								};
								E.push(M);
								N = false;
								break
							}
						}
					}
				}
			}
		}
		return E
	}
});
mojo.helper.Validation.getInstance = function() {
	if (__mojoHelperValidation == null) {
		__mojoHelperValidation = new mojo.helper.Validation()
	}
	return __mojoHelperValidation
};
dojo.provide("mojo.helper.view.Error");
mojo.helper.view.Error.showElementErrors = function(F, C) {
	var A = F.length;
	for (var D = 0; D < A; D++) {
		var B = F[D];
		var E = document.createElement("span");
		E.className = "mojoValidationError";
		E.innerHTML = B.message;
		if (C != null) {
			C.appendChild(E)
		} else {
			if (B.element.type == "checkbox") {
				if (B.element.parentNode.tagName == "LABEL") {
					dojo.place(E, B.element.parentNode, "after")
				} else {
					dojo.place(E, B.element, "after")
				}
			} else {
				dojo.place(E, B.element, "after")
			}
		}
	}
};
dojo.provide("mojo.History");
var __mojoHistory = null;
dojo.declare("mojo.History", null, {
	constructor: function() {
		var A = this;
		if (typeof rsh != "undefined" && rsh["dhtmlHistory"] && rsh["dhtmlHistory"]["_isIE"]) {
			rsh.dhtmlHistory.init();
			dojo.connect(rsh.dhtmlHistory, "_fireHistoryEvent",
			function(B) {
				A.setHash(B);
				A._execute()
			})
		} else {
			this._interval = window.setInterval(function() {
				A._execute()
			},
			100)
		}
		A._execute()
	},
	_interval: null,
	_defaultHash: "",
	_savedHash: "",
	_paramsObj: null,
	_topic: null,
	onChange: function() {},
	getHash: function() {
		var A = window.location.hash;
		if (A.length > 0) {
			A = A.substring(1)
		}
		if (A.toLowerCase() == "null" || A.toLowerCase() == "undefined") {
			A = ""
		}
		if (A.length == 0 && this._defaultHash.length > 0) {
			A = this._defaultHash
		}
		return A
	},
	setHash: function(A) {
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.History.setHash - newHash parameter is required")
		}
		if (!dojo.isString(A) || A == "") {
			throw new Error("ERROR mojo.History.setHash - newHash parameter must be a non-empty string")
		}
		window.location.hash = A
	},
	setDefault: function(A) {
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.History.setDefault - defaultHashObj parameter is required")
		}
		if (typeof(A) == "string") {
			this._defaultHash = A
		} else {
			if (typeof(A) == "object") {
				this._defaultHash = this._parseObj(A)
			}
		}
		this._execute()
	},
	_execute: function() {
		var A = this.getHash();
		if (A.length == 0 && this._defaultHash.length > 0) {
			A = this._defaultHash
		}
		if (this._savedHash != A) {
			document.title = document.title.replace(window.location.hash, "");
			this._savedHash = A;
			this._paramsObj = this._parseHash(this._savedHash);
			this._topic = this._paramsObj["topic"] || null;
			this.onChange();
			if (this._topic) {
				mojo.Messaging.publish(this._topic, this._paramsObj)
			}
		}
	},
	_parseHash: function(D) {
		var C = new Object();
		var B = D.split("&");
		for (var A = 0; A < B.length; A++) {
			var E = B[A].split("=");
			if (E.length == 2) {
				C[E[0]] = unescape(E[1])
			}
		}
		return C
	},
	_parseObj: function(C) {
		var D = new Array();
		for (var A in C) {
			D.push(A + "=" + escape(C[A].toString()))
		}
		var B = D.join("&");
		return B
	},
	getParams: function() {
		return this._paramsObj
	},
	getTopic: function() {
		return this._topic
	}
});
mojo.History.getInstance = function() {
	if (__mojoHistory == null) {
		__mojoHistory = new mojo.History()
	}
	return __mojoHistory
};
dojo.provide("mojo.log");
mojo.log = function(D, A, C, B) {
	if (!mojo.widget.Logger._enabled) {
		return false
	} else {
		return mojo.widget.Logger.log(D, A, C, B)
	}
};
dojo.provide("mojo.*");
dojo.provide("mojo.Messaging");
__mojoMessagingTopics = new Array();
mojo.Messaging.publish = function(B, C) {
	if (B == null || typeof B == "undefined") {
		throw new Error("ERROR mojo.Messaging.publish - topic parameter is required")
	}
	if (!dojo.isString(B) || B == "") {
		throw new Error("ERROR mojo.Messaging.publish - topic parameter must be a non-empty string")
	}
	var A = mojo.Messaging.getTopic(B);
	A.setMessage(C);
	A.onPublish(C);
	if (!dojo.isArray(C)) {
		C = [C]
	}
	dojo.publish(B, C);
	A.setMessage(null)
};
mojo.Messaging.subscribe = function(A, B, C) {
	if (A == null || typeof A == "undefined") {
		throw new Error("ERROR mojo.Messaging.subscribe - topic parameter is required")
	}
	if (!dojo.isString(A) || A == "") {
		throw new Error("ERROR mojo.Messaging.subscribe - topic parameter must be a non-empty string")
	}
	if (!dojo.isObject(B) && !dojo.isString(B)) {
		throw new Error("ERROR mojo.Messaging.subscribe - targetObj parameter must be an object or a string")
	}
	mojo.Messaging.getTopic(A);
	return dojo.subscribe(A, B, C)
};
mojo.Messaging.unsubscribe = function(A) {
	dojo.unsubscribe(A)
};
mojo.Messaging.getTopic = function(A) {
	if (A == null || typeof A == "undefined") {
		throw new Error("ERROR mojo.Messaging.getTopic - topic parameter is required")
	}
	if (!dojo.isString(A) || A == "") {
		throw new Error("ERROR mojo.Messaging.getTopic - topic parameter must be a non-empty string")
	}
	if (!__mojoMessagingTopics[A]) {
		__mojoMessagingTopics[A] = new mojo.MessagingTopic(A)
	}
	return __mojoMessagingTopics[A]
};
dojo.provide("mojo.MessagingTopic");
dojo.declare("mojo.MessagingTopic", null, {
	onPublish: function() {},
	constructor: function(A) {
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.MessagingTopic - topic parameter is required")
		}
		if (typeof A == "string") {
			if (A == "") {
				throw new Error("ERROR mojo.MessagingTopic - topic parameter must be a non-empty string")
			}
		} else {
			throw new Error("ERROR mojo.MessagingTopic - topic parameter is not type String")
		}
		this._topic = A;
		__mojoMessagingTopics[A] = this
	},
	_topic: null,
	_messageObj: null,
	getTopic: function() {
		return this._topic
	},
	getMessage: function() {
		return this._messageObj
	},
	setMessage: function(A) {
		this._messageObj = A
	}
});
dojo.provide("mojo.Model");
__mojoModel = new Array();
__mojoModelReferences = new Array();
mojo.Model.set = function(A, B) {
	if (A == null || typeof A == "undefined") {
		throw new Error("ERROR mojo.Model.set - key parameter is required")
	}
	if (!dojo.isString(A) || A == "") {
		throw new Error("ERROR mojo.Model.set - key parameter must be a non-empty string")
	}
	__mojoModel[A] = B;
	mojo.Model.notify(A)
};
mojo.Model.add = function(B, D) {
	if (B == null || typeof B == "undefined") {
		throw new Error("ERROR mojo.Model.add - key parameter is required")
	}
	if (!dojo.isString(B) || B == "") {
		throw new Error("ERROR mojo.Model.add - key parameter must be a non-empty string")
	}
	if (D == null || typeof D == "undefined") {
		throw new Error("ERROR mojo.Model.add - valueObj parameter is required")
	}
	if (D == "") {
		throw new Error("ERROR mojo.Model.add - valueObj parameter must be a non-empty string")
	}
	if (mojo.Model.contains(B)) {
		if (!dojo.isArray(__mojoModel[B])) {
			var C = __mojoModel[B];
			__mojoModel[B] = new Array();
			__mojoModel[B].push(C)
		}
		if (dojo.isArray(D)) {
			for (var A = 0; A < D.length; A++) {
				__mojoModel[B].push(D[A])
			}
		} else {
			__mojoModel[B].push(D)
		}
		mojo.Model.notify(B)
	} else {
		mojo.Model.set(B, D)
	}
};
mojo.Model.get = function(B) {
	if (B == null || typeof B == "undefined") {
		throw new Error("ERROR mojo.Model.get - key parameter is required")
	}
	if (!dojo.isString(B) || B == "") {
		throw new Error("ERROR mojo.Model.get - key parameter must be a non-empty string")
	}
	var A = __mojoModel[B];
	if (typeof A == "undefined") {
		A = null
	}
	if (djConfig && djConfig.isDebug) {
		console.debug('WARNING mojo.Model - No entry found for "' + B + '" key')
	}
	return A
};
mojo.Model.getReference = function(A) {
	if (A == null || typeof A == "undefined") {
		throw new Error("ERROR mojo.Model.getReference - key parameter is required")
	}
	if (!dojo.isString(A) || A == "") {
		throw new Error("ERROR mojo.Model.getReference - key parameter must be a non-empty string")
	}
	if (!__mojoModelReferences[A]) {
		__mojoModelReferences[A] = new mojo.ModelReference(A)
	}
	return __mojoModelReferences[A]
};
mojo.Model.remove = function(A) {
	if (A == null || typeof A == "undefined") {
		throw new Error("ERROR mojo.Model.remove - key parameter is required")
	}
	if (!dojo.isString(A) || A == "") {
		throw new Error("ERROR mojo.Model.remove - key parameter must be a non-empty string")
	}
	__mojoModel[A] = null;
	mojo.Model.notify(A)
};
mojo.Model.contains = function(B) {
	if (B == null || typeof B == "undefined") {
		throw new Error("ERROR mojo.Model.contains - key parameter is required")
	}
	if (!dojo.isString(B) || B == "") {
		throw new Error("ERROR mojo.Model.contains - key parameter must be a non-empty string")
	}
	var A = __mojoModel[B];
	if (A) {
		return true
	}
	return false
};
mojo.Model.notify = function(C) {
	if (C == null || typeof C == "undefined") {
		throw new Error("ERROR mojo.Model.notify - key parameter is required")
	}
	if (!dojo.isString(C) || C == "") {
		throw new Error("ERROR mojo.Model.notify - key parameter must be a non-empty string")
	}
	__mojoModel["__mojoTemplateControllers"] = [];
	var D = mojo.Model.getReference(C);
	D.onNotify();
	mojo.Messaging.publish("/mojo/model/" + C);
	var E = __mojoModel["__mojoTemplateControllers"].length;
	for (var B = 0; B < E; B++) {
		var A = __mojoModel["__mojoTemplateControllers"][B];
		if (A && A.updateController) {
			A._addObservers();
			A.updateController = null
		}
	}
	__mojoModel["__mojoTemplateControllers"] = null
};
mojo.Model.addObserver = function(B, A, C) {
	if (B == null || typeof B == "undefined") {
		throw new Error("ERROR mojo.Model.addObserver - key parameter is required")
	}
	if (!dojo.isString(B) || B == "") {
		throw new Error("ERROR mojo.Model.addObserver - key parameter must be a non-empty string")
	}
	if (A == null || typeof A == "undefined") {
		throw new Error("ERROR mojo.Model.addObserver - targetObj parameter is required")
	}
	if (!dojo.isObject(A)) {
		throw new Error("ERROR mojo.Model.addObserver - targetObj parameter must be an object")
	}
	if (C == null || typeof C == "undefined") {
		throw new Error("ERROR mojo.Model.addObserver - targetFunc parameter is required")
	}
	if (!dojo.isString(C) || C == "") {
		throw new Error("ERROR mojo.Model.addObserver - targetFunc parameter must be a function and is not of type string")
	}
	return mojo.Messaging.subscribe("/mojo/model/" + B, A, C)
};
mojo.Model.removeObserver = function(A) {
	if (A == null || typeof A != "object") {
		throw new Error("ERROR mojo.Model.removeObserver - handle parameter is required")
	}
	mojo.Messaging.unsubscribe(A)
};
dojo.provide("mojo.ModelReference");
dojo.declare("mojo.ModelReference", null, {
	onNotify: function() {},
	constructor: function(A) {
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.ModelReference - key parameter is required")
		}
		if (!dojo.isString(A) || A == "") {
			throw new Error("ERROR mojo.ModelReference - key parameter must be a non-empty string")
		}
		this._key = A;
		__mojoModelReferences[A] = this
	},
	_key: null,
	getKey: function() {
		return this._key
	},
	getValue: function() {
		return mojo.Model.get(this._key)
	},
	setValue: function(A) {
		mojo.Model.set(this._key, A)
	}
});
dojo.provide("mojo.query");
mojo.query = function(D, C) {
	if (C && (typeof C == "string" || typeof C == "object")) {
		var B = dojo.query(D, C)
	} else {
		if ((new RegExp(/^\#[a-zA-Z0-9\-\_]*$/)).test(D)) {
			var A = document.getElementById(D.substring(1));
			if (A) {
				var B = [A]
			} else {
				var B = []
			}
		} else {
			var B = dojo.query(D)
		}
	}
	return B
};
mojo.queryFirst = function(C, B) {
	var A = mojo.query(C, B);
	if (A.length > 0) {
		return A[0]
	}
	return null
};
mojo.distinct = function(E) {
	if (E.length == 0) {
		return E
	}
	var C = [],
	F;
	for (var B = 0,
	A = E.length; B < A; B++) {
		if (! (F = E[B])._counted) {
			F._counted = true;
			C.push(F)
		}
	}
	for (var B = 0,
	D; D = C[B]; B++) {
		D._counted = undefined
	}
	return C
};
mojo.queryMatch = function(B, H, F, C) {
	if (!B || B == F) {
		return null
	}
	var G = false;
	var E = [];
	if ((new RegExp(/^[\#|\.]?[a-zA-Z0-9\-\_]+$/)).test(H)) {
		G = true
	} else {
		E = mojo.query(H, F)
	}
	while (B && B != F) {
		if (G) {
			if ((H.indexOf("#") == 0 && B.id == H.substring(1)) || (H.indexOf(".") == 0 && dojo.hasClass(B, H.substring(1))) || (B.tagName.toLowerCase() == H.toLowerCase())) {
				return B
			}
		} else {
			for (var D = 0,
			A = E.length; D < A; D++) {
				if (E[D] == B) {
					return B
				}
			}
		}
		if (C) {
			B = B.parentNode
		} else {
			break
		}
	}
	return null
};
dojo.provide("mojo.service.Delegate");
dojo.declare("mojo.service.Delegate", null, {
	constructor: function(A) {
		this._callerObj = A
	},
	_callerObj: null,
	getCaller: function() {
		return this._callerObj
	},
	setCaller: function(A) {
		this._callerObj = A
	}
});
dojo.provide("mojo.service.Locator");
__mojoServiceRegistry = new Array();
dojo.declare("mojo.service.Locator", null, {
	constructor: function() {
		if (__mojoServiceRegistry.length == 0) {
			this.addServices()
		}
	},
	addServices: function() {
		if (djConfig && djConfig.isDebug) {
			console.debug("ERROR mojo.service.Locator - addServices() not implemented")
		}
	},
	addService: function(A) {
		if (A == null || typeof A == "undefined") {
			throw (new Error("ERROR mojo.service.Locator.addService - serviceObj parameter is required"))
		}
		if (! (A instanceof mojo.service.Service)) {
			throw (new Error("ERROR mojo.service.Locator.addService - serviceObj parameter must be an instance of the mojo.service.Service class"))
		}
		var B = A.getName();
		if (!__mojoServiceRegistry[B]) {
			__mojoServiceRegistry[B] = A
		} else {
			throw (new Error('ERROR mojo.service.Locator.addService - service with the name "' + B + '" already exists in the registry; service not added'))
		}
	},
	getService: function(A) {
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.service.Locator.getService - name parameter is required")
		}
		if (!dojo.isString(A) || A == "") {
			throw new Error("ERROR mojo.service.Locator.getService - name parameter must be a non-empty string")
		}
		return __mojoServiceRegistry[A] || null
	}
});
dojo.provide("mojo.service.Service");
dojo.declare("mojo.service.Service", null, {
	VALID_METHODS: ["GET", "POST", "PUT", "DELETE"],
	DEFAULT_PARAMS: {
		json: true,
		method: "GET",
		cacheExpiry: 0,
		cache: true,
		retry: 1,
		hijax: false
	},
	constructor: function(A, B, C) {
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.service.Service.constructor - name parameter is required")
		}
		if (!dojo.isString(A) || A == "") {
			throw new Error("ERROR mojo.service.Service.constructor - name parameter must be a non-empty string")
		}
		if (B == null || typeof B == "undefined") {
			throw new Error("ERROR mojo.service.Service.constructor - uri parameter is required")
		}
		if (!dojo.isString(B) || B == "") {
			throw new Error("ERROR mojo.service.Service.constructor - uri parameter must be a non-empty string")
		}
		var D = {};
		for (property in this.DEFAULT_PARAMS) {
			D[property] = this.DEFAULT_PARAMS[property]
		}
		if (A.toLowerCase().indexOf("add") == 0) {
			D.method = "POST"
		} else {
			if (A.toLowerCase().indexOf("update") == 0) {
				D.method = "PUT"
			} else {
				if (A.toLowerCase().indexOf("delete") == 0) {
					D.method = "DELETE"
				}
			}
		}
		if (C) {
			if (C.method) {
				if (C.method != "GET") {
					D.cache = false
				}
			} else {
				if (D.method != "GET") {
					D.cache = false
				}
			}
			if (C.method) {
				if (C.method != "GET") {
					D.retry = 0
				}
			} else {
				if (D.method != "GET") {
					D.retry = 0
				}
			}
		}
		if (C) {
			for (property in C) {
				D[property] = C[property]
			}
		}
		this.setName(A);
		this.setUri(B);
		this.setParams(D)
	},
	_name: "",
	_uri: "",
	_params: new Object(),
	getName: function() {
		return this._name
	},
	setName: function(A) {
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.service.Service.setName - name parameter is required")
		}
		if (!dojo.isString(A) || A == "") {
			throw new Error("ERROR mojo.service.Service.setName - name parameter must be a non-empty string")
		}
		this._name = A
	},
	getUri: function() {
		return this._uri
	},
	setUri: function(A) {
		if (A == null || typeof A == "undefined") {
			throw new Error("ERROR mojo.service.Service.setUri - uri parameter is required")
		}
		if (!dojo.isString(A) || A == "") {
			throw new Error("ERROR mojo.service.Service.setUri - uri parameter must be a non-empty string")
		}
		this._uri = A
	},
	getParams: function() {
		return this._paramsObj
	},
	setParams: function(D) {
		if (!D) {
			throw new Error("ERROR mojo.service.Service.setParams - paramsObj parameter is required")
		}
		if (D) {
			for (property in D) {
				switch (property) {
				case "json":
				case "hijax":
				case "cache":
					if (typeof D[property] != "boolean") {
						throw new Error("ERROR mojo.service.Service.setParams - " + property + " property of paramsObj must be a boolean")
					}
					break;
				case "cacheExpiry":
				case "retry":
					if (typeof D[property] != "number") {
						throw new Error("ERROR mojo.service.Service.setParams - " + property + " property of paramsObj must be a number")
					}
					break;
				case "method":
					var B = false;
					for (var C = 0,
					A = this.VALID_METHODS.length; C < A; C++) {
						if (this.VALID_METHODS[C] == D[property].toUpperCase()) {
							B = true
						}
					}
					if (!B) {
						throw new Error('ERROR mojo.service.Service.setParams - method property of paramsObj must be one of "GET", "POST", "PUT", or "DELETE"')
					}
					break
				}
			}
		}
		if (!this._paramsObj) {
			this._paramsObj = {}
		}
		for (property in D) {
			this._paramsObj[property] = D[property]
		}
	},
	invoke: function(paramsObj, callerObj) {
		if (!callerObj) {
			throw new Error("ERROR mojo.service.Service.invoke - callerObj parameter is required")
		}
		if (!dojo.isObject(callerObj)) {
			throw new Error("ERROR mojo.service.Service.invoke - callerObj parameter must be an object")
		}
		if (typeof callerObj.onResponse != "function") {
			throw new Error("ERROR mojo.service.Service.invoke - callerObj parameter must contain an object with an onResponse method")
		}
		if (typeof callerObj.onError != "function") {
			throw new Error("ERROR mojo.service.Service.invoke - callerObj parameter must contain an object with an onError method")
		}
		var serviceParams = this.getParams();
		if (typeof TrimPath != "undefined" && TrimPath.parseTemplate) {
			var uriFinal = TrimPath.parseTemplate(this.getUri()).process(paramsObj);
			if (paramsObj && paramsObj["_MODIFIERS"] && paramsObj["defined"]) {
				delete paramsObj["_MODIFIERS"];
				delete paramsObj["defined"]
			}
		} else {
			var uriFinal = this.getUri()
		}
		if (serviceParams.hijax && callerObj.getRequest() && callerObj.getRequest().callerObj && callerObj.getRequest().callerObj.tagName == "A") {
			uriFinal = callerObj.getRequest().callerObj.href
		}
		var tried = 0;
		var serializeName = this.getName();
		var pairs = new Array();
		for (var key in paramsObj) {
			if (typeof(paramsObj[key]) != "function") {
				pairs.push(key + "_" + paramsObj[key])
			} else {
				pairs.push(key + "__function")
			}
		}
		if (pairs.length > 0) {
			serializeName += "_" + pairs.join("_")
		}
		var errorCallback = function(errorObj, httpObj) {
			var errors = new Array();
			if (httpObj) {
				errorObj.code = httpObj.status;
				errors.push(errorObj)
			}
			if (typeof(errorObj) == "string") {
				var msg = errorObj;
				errorObj = new Object();
				errorObj.message = msg
			}
			if (errorObj.name) {
				errorObj.code = errorObj.name;
				errors.push(errorObj)
			}
			if (errorObj.errors) {
				errors = errorObj.errors
			}
			if (errorObj.error) {
				errors.push(errorObj.error)
			}
			if (errors[0]["redirectUrl"]) {
				window.location.replace(errors[0]["redirectUrl"])
			}
			if (httpObj && serviceParams.retry >= tried) {
				serviceInvoke()
			} else {
				callerObj.onError(errors)
			}
		};
		var thisObj = this;
		var serviceInvoke = function() {
			return dojo["xhr" + mojo.toSentenceCase(serviceParams.method.toLowerCase())]({
				url: uriFinal,
				preventCache: (!serviceParams.cache && serviceParams.method == "GET"),
				handleAs: serviceParams.json ? "json": "text",
				content: paramsObj,
				load: function(response, ioArgs) {
					tried++;
					if (ioArgs.handleAs == "json") {
						if (!dojo.isObject(response)) {
							try {
								response = eval(response)
							} catch(ex) {
								errorCallback(ex);
								return
							}
						}
						if (response.error || response.errors) {
							errorCallback(response)
						} else {
							if (serviceParams.cache) {
								thisObj._setCache(serializeName, response, serviceParams.cacheExpiry)
							}
							callerObj.onResponse(response, ioArgs.args.content)
						}
					} else {
						if (serviceParams.cache) {
							thisObj._setCache(serializeName, response, serviceParams.cacheExpiry)
						}
						callerObj.onResponse(response, ioArgs.args.content)
					}
				},
				error: function(response, ioArgs) {
					tried++;
					errorCallback(response, ioArgs.xhr)
				}
			})
		};
		var cacheObj;
		if (serviceParams.cache) {
			cacheObj = this._getCache(serializeName)
		}
		if (cacheObj) {
			callerObj.onResponse(cacheObj.data, paramsObj)
		} else {
			var currentXhr = serviceInvoke()
		}
		return currentXhr
	},
	_setCache: function(A, D, C) {
		var B = 0;
		if (C > 0) {
			B = (new Date()).getTime() + (C * 1000)
		}
		mojo.Model.set(A, {
			data: D,
			expiryTime: B
		})
	},
	_getCache: function(C) {
		var A = null;
		if (mojo.Model.contains(C)) {
			A = mojo.Model.get(C);
			var B = (new Date()).getTime();
			if (A.expiryTime > 0 && B > A.expiryTime) {
				mojo.Model.remove(C);
				A = null
			}
		}
		return A
	}
});
dojo.provide("mojo.widget.Logger");
mojo.widget.Logger = {
	_stack: [],
	_reader: null,
	_loader: false,
	_enabled: false,
	_categories: ["info", "warn", "error"],
	_sources: ["Controller", "Command", "Behavior", "Rule", "Service", "Model", "History", "Template"]
};
mojo.widget.Logger._expandBox = function(A) {
	var B = A.nextSibling.nextSibling;
	if (B.style.display == "block") {
		B.style.display = "none"
	} else {
		B.style.display = "block"
	}
};
mojo.widget.Logger._loadLogger = function() {
	var B = mojo.widget.Logger.getSources();
	var A = mojo.widget.Logger.getCategories();
	YAHOO.widget.Logger.sources = B;
	YAHOO.widget.Logger.categories = A;
	var C = document.createElement("div");
	C.id = "mojo_logger_div_id";
	mojo.widget.Logger._reader = new YAHOO.widget.LogReader(document.body.appendChild(C), {
		verboseOutpt: false,
		newestOnTop: false,
		draggable: true
	})
};
mojo.widget.Logger.log = function(B, G, H, M) {
	if (this._enabled) {
		if (!G) {
			G = "info"
		} else {
			if (YAHOO.widget.Logger._isNewCategory(G)) {
				YAHOO.widget.Logger._createNewCategory(G)
			}
		}
		var D = "global";
		var A = null;
		if (H) {
			var E = H.indexOf(" ");
			if (E > 0) {
				D = H.substring(0, E);
				A = H.substring(E, H.length)
			} else {
				D = H;
				if (YAHOO.widget.Logger._isNewSource(D)) {
					YAHOO.widget.Logger._createNewSource(D)
				}
			}
		}
		var K = null;
		var L = function(S) {
			if (typeof S.toSource !== "undefined" && typeof S.callee === "undefined") {
				return S.toSource()
			}
			switch (typeof S) {
			case "number":
			case "boolean":
			case "function":
				return S;
				break;
			case "string":
				return "'" + S + "'";
				break;
			case "object":
				var R;
				if (S.constructor === Array || typeof S.callee !== "undefined") {
					R = "[";
					var Q, O = S.length;
					for (Q = 0; Q < O - 1; Q++) {
						R += L(S[Q]) + ","
					}
					R += L(S[Q]) + "]"
				} else {
					R = "{";
					var P;
					for (P in S) {
						R += P + ":" + L(S[P]) + ",\n"
					}
					R = R.replace(/\,$/, "") + "}"
				}
				return R;
				break;
			default:
				return "UNKNOWN";
				break
			}
		};
		try {
			if (M) {
				K = L(M);
				K = YAHOO.lang.JSON.stringify(K);
				K = K.replace(/\{\}/gi, "Object");
				K = K.replace(/\\\"/gi, '"');
				B = B + " [ (startanchor) href='#' onclick='mojo.widget.Logger._expandBox(this);return false;' (/startanchor) Toggle (endanchor) ] \n(((" + K + ")))"
			}
		} catch(C) {}
		var I = new Date();
		var N = new YAHOO.widget.LogMsg({
			msg: B,
			time: I,
			category: G,
			source: D,
			sourceDetail: A
		});
		var J = YAHOO.widget.Logger._stack;
		var F = YAHOO.widget.Logger.maxStackEntries;
		if (F && !isNaN(F) && (J.length >= F)) {
			J.shift()
		}
		J.push(N);
		YAHOO.widget.Logger.newLogEvent.fire(N);
		if (YAHOO.widget.Logger._browserConsoleEnabled) {
			YAHOO.widget.Logger._printToBrowserConsole(N)
		}
		return true
	} else {
		return false
	}
};
mojo.widget.Logger.reset = function() {
	YAHOO.widget.Logger.reset()
};
mojo.widget.Logger.getReader = function() {
	return mojo.widget.Logger._reader
};
mojo.widget.Logger.isEnabled = function() {
	return mojo.widget.Logger._enabled
};
mojo.widget.Logger.enable = function() {
	if (!mojo.widget.Logger._loaded) {
		mojo.widget.Logger._loaded = true;
		mojo.widget.Logger._enabled = true;
		mojo.widget.Logger._loadLogger()
	}
};
mojo.widget.Logger.disable = function() {};
mojo.widget.Logger.getCategories = function() {
	return mojo.widget.Logger._categories
};
mojo.widget.Logger.setCategories = function(A) {
	mojo.widget.Logger._categories = A
};
mojo.widget.Logger.getSources = function() {
	return mojo.widget.Logger._sources
};
mojo.widget.Logger.setSources = function(A) {
	mojo.widget.Logger._sources = A
};
dojo.provide("extLib.trimpath.query");
if (typeof(TrimPath) == "undefined") {
	TrimPath = {}
} (function() {
	var theEval = eval;
	var theString = String;
	var theArray = Array;
	if (TrimPath == null) {
		TrimPath = new Object()
	}
	if (TrimPath.TEST == null) {
		TrimPath.TEST = new Object()
	}
	var arrayUniq = function(arr) {
		var result = [];
		for (var i = 0; i < arr.length; i++) {
			if (arrayInclude(result, arr[i]) == false) {
				result.push(arr[i])
			}
		}
		return result
	};
	var arrayInclude = function(arr, val) {
		for (var j = 0; j < arr.length; j++) {
			if (arr[j] == val) {
				return true
			}
		}
		return false
	};
	var arrayCompact = function(arr) {
		var result = [];
		for (var i = 0; i < arr.length; i++) {
			if (arr[i] != null) {
				result.push(arr[i])
			}
		}
		return result
	};
	var simpleJson = function(fields, values) {
		var json = ["{"];
		for (var i = 0; i < fields.length; i++) {
			if (i > 0) {
				json.push(",")
			}
			json.push(fields[i]);
			json.push(":");
			if (values[i]) {
				json.push('"');
				json.push(values[i].replace(/(["\\])/g, "\\$1").replace(/\r/g, "").replace(/\n/g, "\\n"));
				json.push('"')
			} else {
				json.push(null)
			}
		}
		json.push("}");
		return json.join("")
	};
	var hashKeys = function(object) {
		var keys = [];
		for (var property in object) {
			keys.push(property)
		}
		return keys
	};
	var hashValues = function(object) {
		var values = [];
		for (var property in object) {
			values.push(object[property])
		}
		return values
	};
	var strip = function(str) {
		return str.replace(/^\s+/, "").replace(/\s+$/, "")
	};
	TrimPath.makeQueryLang_etc = {};
	TrimPath.makeQueryLang_etc.Error = function(message, stmt) {
		this.message = message;
		this.stmt = stmt
	};
	TrimPath.makeQueryLang_etc.Error.prototype.toString = function() {
		return ("TrimPath query Error in " + (this.stmt != null ? this.stmt: "[unknown]") + ": " + this.message)
	};
	var TODO = function() {
		throw "currently unsupported"
	};
	var USAGE = function() {
		throw "incorrect keyword usage"
	};
	var QueryLang = function() {};
	TrimPath.makeQueryLang = function(tableInfos, etc) {
		if (etc == null) {
			etc = TrimPath.makeQueryLang_etc
		}
		var aliasArr = [];
		var aliasReg = function(aliasKey, scope, obj) {
			if (scope[aliasKey] != null) {
				throw new etc.Error("alias redefinition: " + aliasKey)
			}
			aliasArr.push({
				aliasKey: aliasKey,
				scope: scope,
				orig: scope[aliasKey]
			});
			scope[aliasKey] = obj;
			return obj
		};
		var queryLang = new QueryLang();
		var checkArgs = function(args, minLength, maxLength, name, typeCheck) {
			args = cleanArray(args);
			if (minLength == null) {
				minLength = 1
			}
			if (args == null || args.length < minLength) {
				throw new etc.Error("not enough arguments for " + name)
			}
			if (maxLength != null && args.length > maxLength) {
				throw new etc.Error("too many arguments for " + name)
			}
			if (typeCheck != null) {
				for (var k in args) {
					if (typeof(args[k]) != "function" && args[k] instanceof typeCheck == false) {
						throw new etc.Error("wrong type for " + args[k] + " to " + name)
					}
				}
			}
			return args
		};
		var sql_date_to_js_date = function(data) {
			if (typeof data == "string" && data.match(/\d{4}-\d{1,2}-\d{1,2}/)) {
				var dateArr = data.match(/\d{4}-\d{1,2}-\d{1,2}/)[0].split("-");
				var date = new Date(parseInt(dateArr[0], 10), (parseInt(dateArr[1], 10) - 1), parseInt(dateArr[2], 10));
				return date
			}
			return data
		};
		var data_insertion = function(table_info, field_name, data, column_ref) {
			if (table_info[field_name]) {
				var data = eval(data);
				if (table_info[field_name].type && table_info[field_name].type == "Number") {
					data = Number(data, 10)
				} else {
					if (table_info[field_name].type && table_info[field_name].type == "Date") {
						data = sql_date_to_js_date(data)
					}
				}
				column_ref[field_name] = data
			}
		};
		var NodeType = {
			select: function(args) {
				var columns = [];
				var nodes = {
					from: null,
					where: null,
					groupBy: null,
					having: null,
					orderBy: null,
					limit: null
				};
				for (var i = 0; i < args.length; i++) {
					var arg = args[i];
					var argIsNode = false;
					for (var nodeTypeName in nodes) {
						if (arg instanceof NodeType[nodeTypeName]) {
							if (nodes[nodeTypeName] != null) {
								throw new etc.Error("too many " + nodeTypeName.toUpperCase() + " clauses")
							}
							nodes[nodeTypeName] = arg;
							argIsNode = true;
							break
						}
					}
					if (argIsNode == false) {
						columns.push(arg)
					}
				}
				columns = checkArgs(columns, 1, null, "COLUMNS");
				if (nodes.from == null) {
					throw new etc.Error("missing FROM clause")
				}
				var joinDriver = null;
				var joinFilter = null;
				var whereFilter = null;
				var columnConvertor = null;
				var orderByComparator = null;
				var groupByCalcValues = null;
				var havingFilter = null;
				var typeConverter = function(results) {
					for (var i = 0; i < results.length; i++) {
						var result = results[i];
						for (var attr in result) {
							var value = result[attr];
							if (value instanceof Date) {
								results[i][attr] = dateToString(value)
							}
						}
					}
				};
				this.prepareFilter = function() {
					if (joinDriver == null) {
						joinDriver = compileJoinDriver(nodes.from.tables)
					}
					if (joinFilter == null) {
						joinFilter = compileFilter(compileFilterForJoin, nodes.from.tables)
					}
					if (whereFilter == null) {
						whereFilter = compileFilter(compileFilterForWhere, nodes.from.tables, nodes.where != null ? nodes.where.exprs: null)
					}
					if (groupByCalcValues == null && nodes.groupBy != null) {
						groupByCalcValues = compileGroupByCalcValues(nodes.from.tables, nodes.groupBy.exprs)
					}
					if (havingFilter == null && nodes.having != null) {
						havingFilter = compileFilter(compileFilterForWhere, [], nodes.having.exprs, {
							aliasOnly: true
						})
					}
					if (columnConvertor == null) {
						columnConvertor = compileColumnConvertor(nodes.from.tables, columns)
					}
					if (orderByComparator == null && nodes.orderBy != null) {
						orderByComparator = compileOrderByComparator(nodes.orderBy.exprs)
					}
				};
				this.filter = function(dataTables, bindings, params) {
					this.prepareFilter();
					if (bindings == null) {
						bindings = {}
					}
					if (params == null) {
						params = {}
					}
					var resultOfFromWhere = joinDriver(dataTables, joinFilter, whereFilter, bindings);
					if (groupByCalcValues != null) {
						for (var i = 0; i < resultOfFromWhere.length; i++) {
							resultOfFromWhere[i].groupByValues = groupByCalcValues.apply(null, resultOfFromWhere[i])
						}
						resultOfFromWhere.sort(groupByComparator)
					}
					if (params.return_reference) {
						return resultOfFromWhere
					}
					var groupByAccum = {};
					var groupByFuncs = {
						SUM: function(key, val) {
							groupByAccum[key] = zeroDefault(groupByAccum[key]) + zeroDefault(val);
							return groupByAccum[key]
						},
						COUNT: function(key) {
							groupByAccum[key] = zeroDefault(groupByAccum[key]) + 1;
							return groupByAccum[key]
						},
						AVG: function(key, val) {
							return groupByFuncs.SUM(key, val) / groupByFuncs.COUNT("_COUNT" + key)
						}
					};
					var result = [],
					prevItem = null,
					currItem;
					for (var i = 0; i < resultOfFromWhere.length; i++) {
						currItem = resultOfFromWhere[i];
						currItem[0] = groupByFuncs;
						if (prevItem != null && groupByComparator(prevItem, currItem) != 0) {
							if (havingFilter == null || havingFilter(prevItem.record) == true) {
								result.push(prevItem.record)
							}
							groupByAccum = {}
						}
						currItem.record = columnConvertor.apply(null, currItem.concat([params.with_table]));
						prevItem = currItem
					}
					if (prevItem != null && (havingFilter == null || havingFilter(prevItem.record) == true)) {
						result.push(prevItem.record)
					}
					if (orderByComparator != null) {
						result.sort(orderByComparator)
					}
					if (nodes.limit != null) {
						if (nodes.limit.total == 0) {
							return []
						}
						var start = (nodes.limit.offset != null ? nodes.limit.offset: 0);
						result = result.slice(start, start + (nodes.limit.total > 0 ? nodes.limit.total: result.length))
					}
					typeConverter(result);
					return result
				};
				setSSFunc(this,
				function() {
					var sqlArr = ["SELECT", map(columns, toSqlWithAlias).join(", "), nodes.from.toSql()];
					if (nodes.where != null) {
						sqlArr.push(nodes.where.toSql())
					}
					if (nodes.groupBy != null) {
						sqlArr.push(nodes.groupBy.toSql())
					}
					if (nodes.having != null) {
						sqlArr.push(nodes.having.toSql())
					}
					if (nodes.orderBy != null) {
						sqlArr.push(nodes.orderBy.toSql())
					}
					if (nodes.limit != null) {
						sqlArr.push(nodes.limit.toSql())
					}
					return sqlArr.join(" ")
				});
				for (var i = 0; i < aliasArr.length; i++) {
					var aliasItem = aliasArr[i];
					aliasItem.scope[aliasItem.aliasKey] = aliasItem.orig
				}
				aliasArr = []
			},
			insert: function(args) {
				var table_info = args[0];
				var object = args[1];
				this.filter = function(dataTables, bindings) {
					var table_name = table_info[".name"];
					if (!dataTables[table_name]) {
						dataTables[table_name] = []
					}
					dataTables[table_name].push({});
					for (var field_name in object) {
						data_insertion(table_info, field_name, object[field_name], dataTables[table_name][dataTables[table_name].length - 1])
					}
					return true
				};
				setSSFunc(this,
				function() {
					var sqlArr = ["INSERT INTO", table_info.toSql(), "(" + hashKeys(object).join(", ") + ")", "VALUES", "(" + hashValues(object).join(", ") + ")"];
					return sqlArr.join(" ")
				})
			},
			update: function(args) {
				var from_node = args[0];
				var assignments = args[1];
				var where_node = args[2];
				this.filter = function(dataTables, bindings) {
					var table_info = from_node.tables[0];
					var resultOfFromWhere = queryLang.SELECT(from_node, where_node, 1).filter(dataTables, null, {
						return_reference: true
					});
					for (var i = 0; i < resultOfFromWhere.length; i++) {
						var object = resultOfFromWhere[i][1];
						for (var field in assignments) {
							var fieldSplit = field.split(".");
							var field_name = field;
							if (fieldSplit.length == 2) {
								field_name = fieldSplit[1]
							}
							data_insertion(table_info, field_name, assignments[field], object)
						}
					}
					return true
				};
				setSSFunc(this,
				function() {
					var sqlArr = ["UPDATE", from_node.toSql()];
					var assignmentsArr = [];
					for (var attr in assignments) {
						assignmentsArr.push(attr + "=" + assignments[attr])
					}
					sqlArr.push(assignmentsArr.join(", "));
					if (where_node != null) {
						sqlArr.push(where_node.toSql())
					}
					return sqlArr.join(" ")
				})
			},
			destroy: function(args) {
				var select_node = args[0];
				this.filter = function(dataTables, bindings) {
					var resultOfFromWhere = select_node.filter(dataTables, null, {
						return_reference: true
					});
					for (var i = 0; i < resultOfFromWhere.length; i++) {
						var record = resultOfFromWhere[i];
						for (var j = 1; j < record.length; j++) {
							var object = record[j];
							for (var attr in object) {
								delete object[attr]
							}
						}
					}
					for (var table_name in dataTables) {
						var table = dataTables[table_name];
						for (var i = 0; i < table.length; i++) {
							if (hashKeys(table[i]).length == 0) {
								delete table[i]
							}
						}
					}
					for (var table_name in dataTables) {
						dataTables[table_name] = arrayCompact(dataTables[table_name])
					}
					return true
				};
				setSSFunc(this,
				function() {
					var sqlArr = ["DELETE", select_node.toSql()];
					return sqlArr.join(" ").replace(/SELECT\s/, "")
				})
			},
			from: function(tables) {
				this.tables = checkArgs(tables, 1, null, "FROM", NodeType.tableDef)
			},
			where: function(exprs) {
				this.exprs = checkArgs(exprs, 1, null, "WHERE", NodeType.expression)
			},
			groupBy: function(exprs) {
				this.exprs = checkArgs(exprs, 1, null, "GROUP_BY")
			},
			having: function(exprs) {
				this.exprs = checkArgs(exprs, 1, null, "HAVING", NodeType.expression)
			},
			orderBy: function(exprs) {
				this.exprs = checkArgs(exprs, 1, null, "ORDER_BY")
			},
			expression: function(args, name, opFix, sqlText, minArgs, maxArgs, jsText, alias) {
				var theExpr = this;
				this.args = checkArgs(args, minArgs, maxArgs, name);
				this[".name"] = name;
				this[".alias"] = alias != null ? alias: name;
				this.opFix = opFix;
				this.sqlText = sqlText != null ? sqlText: this[".name"];
				this.jsText = jsText != null ? jsText: this.sqlText;
				this.AS = function(aliasArg) {
					this[".alias"] = this.ASC[".alias"] = this.DESC[".alias"] = aliasArg;
					return aliasReg(aliasArg, queryLang, this)
				};
				this.ASC = setSSFunc({
					".name": name,
					".alias": theExpr[".alias"],
					order: "ASC"
				},
				function() {
					return theExpr[".alias"] + " ASC"
				});
				this.DESC = setSSFunc({
					".name": name,
					".alias": theExpr[".alias"],
					order: "DESC"
				},
				function() {
					return theExpr[".alias"] + " DESC"
				});
				this.COLLATE = TODO
			},
			aggregate: function() {
				NodeType.expression.apply(this, arguments)
			},
			limit: function(offset, total) {
				if (total == null) {
					this.total = cleanString(offset)
				} else {
					this.total = cleanString(total);
					this.offset = cleanString(offset)
				}
			},
			tableDef: function(name, columnInfos, alias) {
				this[".name"] = name;
				this[".alias"] = alias != null ? alias: name;
				this[".allColumns"] = [];
				for (var columnName in columnInfos) {
					this[columnName] = new NodeType.columnDef(columnName, columnInfos[columnName], this);
					this[".allColumns"].push(this[columnName])
				}
				setSSFunc(this,
				function() {
					return name
				});
				this.AS = function(alias) {
					return aliasReg(alias, queryLang, new NodeType.tableDef(name, columnInfos, alias))
				};
				this.ALL = new NodeType.columnDef("*", null, this);
				this.ALL.AS = null
			},
			columnDef: function(name, columnInfo, tableDef, alias) {
				var theColumnDef = this;
				this[".name"] = name;
				this[".alias"] = alias != null ? alias: name;
				this.tableDef = tableDef;
				setSSFunc(this,
				function(flags) {
					if (flags != null && flags.aliasOnly == true) {
						return this[".alias"]
					}
					return tableDef != null ? ((tableDef[".alias"]) + "." + name) : name
				});
				this.AS = function(aliasArg) {
					return aliasReg(aliasArg, queryLang, new NodeType.columnDef(name, columnInfo, tableDef, aliasArg))
				};
				if (columnInfo && columnInfo.type) {
					this.type = columnInfo.type
				} else {
					this.type = "String"
				}
				this.ASC = setSSFunc({
					".name": name,
					".alias": theColumnDef[".alias"],
					tableDef: tableDef,
					order: "ASC"
				},
				function() {
					return theColumnDef.toSql() + " ASC"
				});
				this.DESC = setSSFunc({
					".name": name,
					".alias": theColumnDef[".alias"],
					tableDef: tableDef,
					order: "DESC"
				},
				function() {
					return theColumnDef.toSql() + " DESC"
				});
				this.COLLATE = TODO
			},
			join: function(joinType, tableDef) {
				var theJoin = this;
				this.joinType = joinType;
				this.fromSeparator = " " + joinType + " JOIN ";
				for (var k in tableDef) {
					this[k] = tableDef[k]
				}
				this.ON = function() {
					theJoin.ON_exprs = checkArgs(arguments, 1, null, "ON");
					return theJoin
				};
				this.USING = function() {
					theJoin.USING_exprs = cleanArray(arguments, false);
					return theJoin
				};
				this.fromSuffix = function() {
					if (theJoin.ON_exprs != null) {
						return (" ON " + map(theJoin.ON_exprs, toSql).join(" AND "))
					}
					if (theJoin.USING_exprs != null) {
						return (" USING (" + theJoin.USING_exprs.join(", ") + ")")
					}
					return ""
				}
			}
		};
		var setSSFunc = function(obj, func) {
			obj.toSql = obj.toJs = obj.toString = func;
			return obj
		};
		setSSFunc(NodeType.from.prototype,
		function() {
			var sqlArr = ["FROM "];
			for (var i = 0; i < this.tables.length; i++) {
				if (i > 0) {
					var sep = this.tables[i].fromSeparator;
					if (sep == null) {
						sep = ", "
					}
					sqlArr.push(sep)
				}
				sqlArr.push(toSqlWithAlias(this.tables[i]));
				if (this.tables[i].fromSuffix != null) {
					sqlArr.push(this.tables[i].fromSuffix())
				}
			}
			return sqlArr.join("")
		});
		setSSFunc(NodeType.where.prototype,
		function() {
			return "WHERE " + map(this.exprs, toSql).join(" AND ")
		});
		setSSFunc(NodeType.orderBy.prototype,
		function() {
			return "ORDER BY " + map(this.exprs, toSql).join(", ")
		});
		setSSFunc(NodeType.groupBy.prototype,
		function() {
			return "GROUP BY " + map(this.exprs, toSql).join(", ")
		});
		setSSFunc(NodeType.having.prototype,
		function() {
			return "HAVING " + map(this.exprs, toSql, {
				aliasOnly: true
			}).join(" AND ")
		});
		setSSFunc(NodeType.limit.prototype,
		function() {
			return "LIMIT " + (this.total < 0 ? "ALL": this.total) + (this.offset != null ? (" OFFSET " + this.offset) : "")
		});
		var makeToFunc = function(toFunc, opText) {
			return function(flags) {
				if (flags != null && flags.aliasOnly == true && this[".alias"] != this[".name"]) {
					return this[".alias"]
				}
				if (this.opFix < 0) {
					return this[opText] + " (" + map(this.args, toFunc, flags).join(") " + this[opText] + " (") + ")"
				}
				if (this.opFix > 0) {
					return "(" + map(this.args, toFunc, flags).join(") " + this[opText] + " (") + ") " + this[opText]
				}
				return "(" + map(this.args, toFunc, flags).join(") " + this[opText] + " (") + ")"
			}
		};
		NodeType.expression.prototype.toSql = makeToFunc(toSql, "sqlText");
		NodeType.expression.prototype.toJs = makeToFunc(toJs, "jsText");
		NodeType.aggregate.prototype = new NodeType.expression([], null, null, null, 0);
		NodeType.aggregate.prototype.toJs = function(flags) {
			if (flags != null && flags.aliasOnly == true && this[".alias"] != this[".name"]) {
				return this[".alias"]
			}
			return this.jsText + " ('" + this[".alias"] + "', (" + map(this.args, toJs).join("), (") + "))"
		};
		NodeType.join.prototype = new NodeType.tableDef();
		NodeType.whereSql = function(sql) {
			this.exprs = [new NodeType.rawSql(sql)]
		};
		NodeType.whereSql.prototype = new NodeType.where([new NodeType.expression([0], null, 0, null, 0, null, null, null)]);
		NodeType.havingSql = function(sql) {
			this.exprs = [new NodeType.rawSql(sql)]
		};
		NodeType.havingSql.prototype = new NodeType.having([new NodeType.expression([0], null, 0, null, 0, null, null, null)]);
		NodeType.rawSql = function(sql) {
			this.sql = sql
		};
		NodeType.rawSql.prototype.toSql = function(flags) {
			return this.sql
		};
		NodeType.rawSql.prototype.toJs = function(flags) {
			var js = this.sql;
			js = js.replace(/ AND /g, " && ");
			js = js.replace(/ OR /g, " || ");
			js = js.replace(/ = /g, " == ");
			js = js.replace(/ IS NULL/g, " == null");
			js = js.replace(/ IS NOT NULL/g, " != null");
			js = js.replace(/ NOT /g, " ! ");
			var LIKE_regex = /(\S+)\sLIKE\s'(\S+)'/g;
			var matchArr;
			while (matchArr = LIKE_regex.exec(js)) {
				matchArr[2] = matchArr[2].replace(/%/, ".*");
				js = js.replace(LIKE_regex, "$1.match(/" + matchArr[2] + "/)")
			}
			var DATE_regex = /'(\d{4})-(\d{1,2})-(\d{1,2})'/g;
			while (matchArr = DATE_regex.exec(js)) {
				var dateArr = [parseInt(matchArr[1], 10).toString(), (parseInt(matchArr[2], 10) - 1).toString(), parseInt(matchArr[3], 10).toString()];
				var replacement = "(new Date(" + dateArr.join(", ") + ").valueOf())";
				js = js.replace(matchArr[0], replacement)
			}
			return js
		};
		var keywords = {
			INSERT: function() {
				return new NodeType.insert(arguments)
			},
			UPDATE: function() {
				return new NodeType.update(arguments)
			},
			DESTROY: function() {
				return new NodeType.destroy(arguments)
			},
			SELECT_ALL: function() {
				return new NodeType.select(arguments)
			},
			SELECT_DISTINCT: TODO,
			ALL: USAGE,
			FROM: function() {
				return new NodeType.from(arguments)
			},
			WHERE: function() {
				return new NodeType.where(arguments)
			},
			AND: function() {
				return new NodeType.expression(arguments, "AND", 0, null, 1, null, "&&")
			},
			OR: function() {
				return new NodeType.expression(arguments, "OR", 0, null, 1, null, "||")
			},
			NOT: function() {
				return new NodeType.expression(arguments, "NOT", -1, null, 1, 1, "!")
			},
			EQ: function() {
				return new NodeType.expression(arguments, "EQ", 0, "=", 2, 2, "==")
			},
			NEQ: function() {
				return new NodeType.expression(arguments, "NEQ", 0, "!=", 2, 2)
			},
			LT: function() {
				return new NodeType.expression(arguments, "LT", 0, "<", 2, 2)
			},
			GT: function() {
				return new NodeType.expression(arguments, "GT", 0, ">", 2, 2)
			},
			LTE: function() {
				return new NodeType.expression(arguments, "LTE", 0, "<=", 2, 2)
			},
			GTE: function() {
				return new NodeType.expression(arguments, "GTE", 0, ">=", 2, 2)
			},
			IS_NULL: function() {
				return new NodeType.expression(arguments, "IS_NULL", 1, "IS NULL", 1, 1, "== null")
			},
			IS_NOT_NULL: function() {
				return new NodeType.expression(arguments, "IS_NOT_NULL", 1, "IS NOT NULL", 1, 1, "!= null")
			},
			ADD: function() {
				return new NodeType.expression(arguments, "ADD", 0, "+", 2, null)
			},
			SUBTRACT: function() {
				return new NodeType.expression(arguments, "SUBTRACT", 0, "-", 2, null)
			},
			NEGATE: function() {
				return new NodeType.expression(arguments, "NEGATE", -1, "-", 1, 1)
			},
			MULTIPLY: function() {
				return new NodeType.expression(arguments, "MULTIPLY", 0, "*", 2, null)
			},
			DIVIDE: function() {
				return new NodeType.expression(arguments, "DIVIDE", 0, "/", 2, null)
			},
			PAREN: function() {
				return new NodeType.expression(arguments, "PAREN", 0, "", 1, 1)
			},
			LIKE: function() {
				return new NodeType.expression(arguments, "LIKE", 0, "LIKE", 2, 2, "match")
			},
			BETWEEN: TODO,
			AVG: function() {
				return new NodeType.aggregate(arguments, "AVG", -1, null, 1, 1)
			},
			AVG_ALL: TODO,
			AVG_DISTINCT: TODO,
			SUM: function() {
				return new NodeType.aggregate(arguments, "SUM", -1, null, 1, 1)
			},
			SUM_ALL: TODO,
			SUM_DISTINCT: TODO,
			COUNT: function() {
				return new NodeType.aggregate(arguments, "COUNT", -1, null, 1, 1)
			},
			COUNT_ALL: TODO,
			COUNT_DISTINCT: TODO,
			AS: USAGE,
			IN: TODO,
			UNION: TODO,
			UNION_ALL: TODO,
			EXCEPT: TODO,
			EXCEPT_ALL: TODO,
			INTERSECT: TODO,
			INTERSECT_ALL: TODO,
			CROSS_JOIN: function(tableDef) {
				return tableDef
			},
			INNER_JOIN: function(tableDef) {
				return new NodeType.join("INNER", tableDef)
			},
			LEFT_OUTER_JOIN: function(tableDef) {
				return new NodeType.join("LEFT OUTER", tableDef)
			},
			RIGHT_OUTER_JOIN: TODO,
			FULL_OUTER_JOIN: TODO,
			ON: USAGE,
			USING: USAGE,
			GROUP_BY: function() {
				return new NodeType.groupBy(arguments)
			},
			HAVING: function() {
				return new NodeType.having(arguments)
			},
			ORDER_BY: function() {
				return new NodeType.orderBy(arguments)
			},
			LIMIT: function(offset, total) {
				return new NodeType.limit(offset, total)
			},
			LIMIT_ALL: function(offset) {
				return queryLang.LIMIT( - 1, offset)
			},
			OFFSET: USAGE,
			ANY_SELECT: TODO,
			ALL_SELECT: TODO,
			EXISTS: TODO,
			WHERE_SQL: function(sql) {
				return new NodeType.whereSql(sql)
			},
			HAVING_SQL: function(sql) {
				return new NodeType.havingSql(sql)
			}
		};
		keywords.SELECT = keywords.SELECT_ALL;
		for (var k in keywords) {
			queryLang[k] = keywords[k]
		}
		for (var tableName in tableInfos) {
			queryLang[tableName] = new NodeType.tableDef(tableName, tableInfos[tableName])
		}
		return queryLang
	};
	var compileJoinDriver = function(tables) {
		var funcText = ["var TrimPath_query_tmpJD = function(dataTables, joinFilter, whereFilter, bindings) {", "var result = [], filterArgs = [ bindings ];"];
		for (var i = 0; i < tables.length; i++) {
			funcText.push("var T" + i + " = dataTables['" + tables[i][".name"] + "'] || [];")
		}
		for (var i = 0; i < tables.length; i++) {
			funcText.push("for (var t" + i + " = 0; t" + i + " < T" + i + ".length; t" + i + "++) {");
			funcText.push("var resultLength" + i + " = result.length;");
			funcText.push("filterArgs[" + (i + 1) + "] = T" + i + "[t" + i + "];")
		}
		funcText.push("if ((joinFilter == null || joinFilter.apply(null, filterArgs) == true) && ");
		funcText.push("    (whereFilter == null || whereFilter.apply(null, filterArgs) == true))");
		funcText.push("result.push(filterArgs.slice(0));");
		for (var i = tables.length - 1; i >= 0; i--) {
			funcText.push("}");
			if (i >= 1 && tables[i].joinType == "LEFT OUTER") {
				funcText.push("if (resultLength" + (i - 1) + " == result.length) {");
				for (var j = i; j < tables.length; j++) {
					funcText.push("filterArgs[" + (j + 1) + "] = ")
				}
				funcText.push("{}; if (whereFilter == null || whereFilter.apply(null, filterArgs) == true) result.push(filterArgs.slice(0)); }")
			}
		}
		funcText.push("return result; }; TrimPath_query_tmpJD");
		return theEval(funcText.join(""))
	};
	var compileFilter = function(bodyFunc, tables, whereExpressions, flags) {
		var funcText = ["var TrimPath_query_tmpWF = function(_BINDINGS"];
		for (var i = 0; i < tables.length; i++) {
			funcText.push(", " + tables[i][".alias"])
		}
		funcText.push("){ with(_BINDINGS) {");
		bodyFunc(funcText, tables, whereExpressions, flags);
		funcText.push("return true; }}; TrimPath_query_tmpWF");
		return theEval(funcText.join(""))
	};
	var compileFilterForJoin = function(funcText, tables, whereExpressions, flags) {
		for (var i = 0; i < tables.length; i++) {
			if (tables[i].joinType != null) {
				if (tables[i].ON_exprs != null || tables[i].USING_exprs != null) {
					funcText.push("if (!(");
					if (tables[i].ON_exprs != null && tables[i].ON_exprs[0].exprs != null) {
						funcText.push(tables[i].ON_exprs[0].exprs[0].toJs())
					} else {
						if (tables[i].ON_exprs != null) {
							funcText.push(map(tables[i].ON_exprs, toJs).join(" && "))
						}
					}
					if (tables[i].USING_exprs != null) {
						funcText.push(map(tables[i].USING_exprs,
						function(col) {
							return "(" + tables[i - 1][".alias"] + "." + col + " == " + tables[i][".alias"] + "." + col + ")"
						}).join(" && "))
					}
					funcText.push(")) return false;")
				}
			}
		}
	};
	var compileFilterForWhere = function(funcText, tables, whereExpressions, flags) {
		if (whereExpressions != null) {
			funcText.push("if (!((");
			for (var i = 0; i < whereExpressions.length; i++) {
				if (i > 0) {
					funcText.push(") && (")
				}
				funcText.push(toJs(whereExpressions[i], flags))
			}
			funcText.push("))) return false;")
		}
	};
	var compileColumnConvertor = function(tables, columnExpressions) {
		var funcText = ["var TrimPath_query_tmpCC = function(_BINDINGS, "];
		var table_aliases = [];
		for (var i = 0; i < tables.length; i++) {
			table_aliases.push(tables[i][".alias"])
		}
		funcText.push(arrayUniq(table_aliases).join(", "));
		funcText.push(", with_table){ with(_BINDINGS) {");
		funcText.push("var _RESULT = {};");
		funcText.push("if(with_table) {");
		compileColumnConvertorHelper(funcText, columnExpressions, true);
		funcText.push("} else {");
		compileColumnConvertorHelper(funcText, columnExpressions, false);
		funcText.push("}");
		funcText.push("return _RESULT; }}; TrimPath_query_tmpCC");
		return theEval(funcText.join(""))
	};
	var test = function(stuff) {
		var i
	};
	var compileColumnConvertorHelper = function(funcText, columnExpressions, with_table) {
		for (var i = 0; i < columnExpressions.length; i++) {
			var columnExpression = columnExpressions[i];
			if (columnExpression[".name"] == "*") {
				compileColumnConvertorHelper(funcText, columnExpression.tableDef[".allColumns"], with_table)
			} else {
				funcText.push("_RESULT['");
				if (with_table == true) {
					funcText.push(columnExpression.toString())
				} else {
					funcText.push(columnExpression[".alias"])
				}
				funcText.push("'] = (");
				funcText.push(toJs(columnExpression));
				funcText.push(");")
			}
		}
	};
	var dateToString = function(date) {
		if (typeof date == "object") {
			return [date.getFullYear(), "-", (date.getMonth() + 1), "-", date.getDate()].join("")
		}
		if (date == null) {
			return null
		}
	};
	var compileOrderByComparator = function(orderByExpressions) {
		var funcText = ["var TrimPath_query_tmpOC = function(A, B) { var a, b; "];
		for (var i = 0; i < orderByExpressions.length; i++) {
			var orderByExpression = orderByExpressions[i];
			if (orderByExpression.tableDef) {
				funcText.push("a = A['" + orderByExpression[".alias"] + "'] || A['" + orderByExpression.tableDef[".alias"] + "." + orderByExpression[".alias"] + "'] || '';");
				funcText.push("b = B['" + orderByExpression[".alias"] + "'] || B['" + orderByExpression.tableDef[".alias"] + "." + orderByExpression[".alias"] + "'] || '';")
			} else {
				funcText.push("a = A['" + orderByExpression[".alias"] + "'] || '';");
				funcText.push("b = B['" + orderByExpression[".alias"] + "'] || '';")
			}
			var sign = (orderByExpression.order == "DESC" ? -1 : 1);
			funcText.push("if (a.valueOf() < b.valueOf()) return " + (sign * -1) + ";");
			funcText.push("if (a.valueOf() > b.valueOf()) return " + (sign * 1) + ";")
		}
		funcText.push("return 0; }; TrimPath_query_tmpOC");
		return theEval(funcText.join(""))
	};
	var compileGroupByCalcValues = function(tables, groupByExpressions) {
		var funcText = ["var TrimPath_query_tmpGC = function(_BINDINGS"];
		for (var i = 0; i < tables.length; i++) {
			funcText.push(", " + tables[i][".alias"])
		}
		funcText.push("){ var _RESULT = [];");
		for (var i = 0; i < groupByExpressions.length; i++) {
			funcText.push("_RESULT.push(");
			funcText.push(toJs(groupByExpressions[i]));
			funcText.push(");")
		}
		funcText.push("return _RESULT; }; TrimPath_query_tmpGC");
		return theEval(funcText.join(""))
	};
	var groupByComparator = function(a, b) {
		return arrayCompare(a.groupByValues, b.groupByValues)
	};
	var arrayCompare = function(x, y) {
		if (x == null || y == null) {
			return - 1
		}
		for (var i = 0; i < x.length && i < y.length; i++) {
			if (x[i] < y[i]) {
				return - 1
			}
			if (x[i] > y[i]) {
				return 1
			}
		}
		return 0
	};
	var toSqlWithAlias = function(obj, flags) {
		var res = toSql(obj, flags);
		if (obj[".alias"] != null && obj[".alias"] != obj[".name"]) {
			return res + " AS " + obj[".alias"]
		}
		return res
	};
	var toSql = function(obj, flags) {
		return toX(obj, "toSql", flags)
	};
	var toJs = function(obj, flags) {
		return toX(obj, "toJs", flags)
	};
	var toX = function(obj, funcName, flags) {
		if (typeof(obj) == "object" && obj[funcName] != null) {
			return obj[funcName].call(obj, flags)
		}
		return theString(obj)
	};
	var zeroDefault = function(x) {
		return (x != null ? x: 0)
	};
	var map = function(arr, func, arg2) {
		for (var result = [], i = 0; i < arr.length; i++) {
			result.push(func(arr[i], arg2))
		}
		return result
	};
	var cleanArray = function(src, quotes) {
		for (var result = [], i = 0; i < src.length; i++) {
			result.push(cleanString(src[i], quotes))
		}
		return result
	};
	var cleanString = TrimPath.TEST.cleanString = function(src, quotes) {
		if (src instanceof theString || typeof(src) == "string") {
			src = theString(src).replace(/\\/g, "\\\\").replace(/'/g, "\\'");
			if (quotes != false) {
				src = "'" + src + "'"
			}
		}
		return src
	};
	var findClause = function(str, regexp) {
		var clauseEnd = str.search(regexp);
		if (clauseEnd < 0) {
			clauseEnd = str.length
		}
		return str.substring(0, clauseEnd)
	};
	QueryLang.prototype.parseSQL = function(sqlQueryIn, paramsArr) {
		var sqlQuery = sqlQueryIn.replace(/\n/g, " ").replace(/\r/g, "");
		if (paramsArr != null) {
			if (paramsArr instanceof theArray == false) {
				paramsArr = [paramsArr]
			}
			var sqlParts = sqlQuery.split(" ?");
			for (var i = 0; i < sqlParts.length - 1; i++) {
				sqlParts[i] = sqlParts[i] + " " + cleanString(paramsArr[i], true)
			}
			sqlQuery = sqlParts.join("")
		}
		sqlQuery = sqlQuery.replace(/ AS ([_a-zA-z0-9]+)/g, ".AS('$1')");
		var err = function(errMsg) {
			throw ("[ERROR: " + errMsg + " in query: " + sqlQueryIn + "]")
		};
		var query_type = sqlQuery.split(/\s+/)[0];
		if (query_type == "DELETE") {
			query_type = "DESTROY"
		}
		if (!arrayInclude(["SELECT", "DESTROY", "UPDATE", "INSERT"], query_type)) {
			err("not a valid query type")
		}
		var strip_whitespace = function(str) {
			return str.replace(/\s+/g, "")
		};
		if (query_type == "SELECT" || query_type == "DESTROY") {
			var fromSplit = sqlQuery.substring(7).split(" FROM ");
			if (fromSplit.length != 2) {
				err("missing a FROM clause")
			}
			var columnsClause = fromSplit[0].replace(/\.\*/g, ".ALL");
			var remaining = fromSplit[1];
			var fromClause = findClause(remaining, /\sWHERE\s|\sGROUP BY\s|\sHAVING\s|\sORDER BY\s|\sLIMIT/);
			var fromTableClause = findClause(fromClause, /\sLEFT OUTER JOIN\s/);
			var fromTables = strip_whitespace(fromTableClause).split(",");
			remaining = remaining.substring(fromClause.length);
			var fromClauseSplit = fromClause.split(" LEFT OUTER JOIN ");
			var fromClauseParts = [fromClauseSplit[0]];
			var leftJoinComponents;
			for (var i = 1; i < fromClauseSplit.length; i++) {
				leftJoinComponents = /(\w+)\sON\s(.+)/.exec(fromClauseSplit[i]);
				fromTables.push(leftJoinComponents[1]);
				fromClauseParts.push("(" + leftJoinComponents[1] + ').ON(WHERE_SQL("' + leftJoinComponents[2] + '"))')
			}
			fromClause = fromClauseParts.join(", LEFT_OUTER_JOIN");
			if (strip_whitespace(columnsClause) == "*") {
				var new_columns = [];
				for (var i = 0; i < fromTables.length; i++) {
					new_columns.push(fromTables[i] + ".ALL")
				}
				columnsClause = columnsClause.replace(/\*/, new_columns.join(", "))
			}
			var whereClause = findClause(remaining, /\sGROUP BY\s|\sHAVING\s|\sORDER BY\s|\sLIMIT/);
			remaining = remaining.substring(whereClause.length);
			var groupByClause = findClause(remaining, /\sHAVING\s|\sORDER BY\s|\sLIMIT /);
			remaining = remaining.substring(groupByClause.length);
			var havingClause = findClause(remaining, /\sORDER BY\s|\sLIMIT /);
			remaining = remaining.substring(havingClause.length);
			var orderByClause = findClause(remaining, /\sLIMIT /).replace(/\sASC/g, ".ASC").replace(/\sDESC/g, ".DESC");
			remaining = remaining.substring(orderByClause.length);
			var limitClause = remaining;
			var tql = ["SELECT(FROM(", fromClause, "), ", columnsClause];
			if (whereClause.length > 0) {
				tql.push(', WHERE_SQL("' + whereClause.substring(7) + '")')
			}
			if (groupByClause.length > 0) {
				tql.push(", GROUP_BY(" + groupByClause.substring(10) + ")")
			}
			if (havingClause.length > 0) {
				tql.push(', HAVING_SQL("' + havingClause.substring(8) + '")')
			}
			if (orderByClause.length > 0) {
				tql.push(", ORDER_BY(" + orderByClause.substring(10) + ")")
			}
			if (limitClause.length > 0) {
				tql.push(", LIMIT(" + limitClause.substring(7) + ")")
			}
			tql.push(")")
		} else {
			if (query_type == "INSERT") {
				var intoSplit = sqlQuery.substring(6).split(" INTO ");
				if (intoSplit.length != 2) {
					err("missing an INTO clause")
				}
				var insertion_regex = /^\s*(\w+)\s*\((.+)\)\s+VALUES\s+\((.+)\)/;
				var parsed_sql = intoSplit[1].match(insertion_regex);
				var table_name = parsed_sql[1];
				var fields = strip_whitespace(parsed_sql[2]).split(",");
				var values = parsed_sql[3].split(",");
				if (fields.length != values.length) {
					err("values and fields must have same number of elements")
				}
				tql = ["INSERT(", table_name, ",", simpleJson(fields, values), ")"]
			} else {
				if (query_type == "UPDATE") {
					var setSplit = sqlQuery.substring(7).split(" SET ");
					if (setSplit.length != 2) {
						err("missing a SET clause")
					}
					var fromClause = setSplit[0];
					var remaining = setSplit[1];
					var assignmentClause = findClause(remaining, /\sWHERE\s/);
					remaining = remaining.substring(assignmentClause.length);
					var whereClause = remaining;
					var assignmentArray = assignmentClause.split(",");
					var fields = [];
					var values = [];
					for (var i = 0; i < assignmentArray.length; i++) {
						var components = assignmentArray[i].split("=");
						fields.push(strip(components[0]));
						values.push(strip(components[1]))
					}
					var update_regex = /^UPDATE\s+(\w+)\s+SET\s+(\w+\s*=\s*\w+)/;
					var parsed_sql = sqlQuery.match(update_regex);
					var tql = ["UPDATE(FROM(", fromClause, "), ", simpleJson(fields, values)];
					tql.push(', WHERE_SQL("' + whereClause.substring(7) + '")');
					tql.push(")")
				}
			}
		}
		if (query_type == "DESTROY") {
			tql.unshift("DESTROY(");
			tql.push(")")
		}
		with(this) {
			return eval(tql.join(""))
		}
	}
})();
dojo.provide("extLib.trimpath.template");
if (typeof(TrimPath) == "undefined") {
	TrimPath = {}
} (function() {
	if (TrimPath == null) {
		TrimPath = new Object()
	}
	if (TrimPath.evalEx == null) {
		TrimPath.evalEx = function(src) {
			return eval(src)
		}
	}
	var UNDEFINED;
	if (Array.prototype.pop == null) {
		Array.prototype.pop = function() {
			if (this.length === 0) {
				return UNDEFINED
			}
			return this[--this.length]
		}
	}
	if (Array.prototype.push == null) {
		Array.prototype.push = function() {
			for (var i = 0; i < arguments.length; ++i) {
				this[this.length] = arguments[i]
			}
			return this.length
		}
	}
	TrimPath.parseTemplate = function(tmplContent, optTmplName, optEtc) {
		if (optEtc == null) {
			optEtc = TrimPath.parseTemplate_etc
		}
		var funcSrc = parse(tmplContent, optTmplName, optEtc);
		var func = TrimPath.evalEx(funcSrc, optTmplName, 1);
		if (func != null) {
			return new optEtc.Template(optTmplName, tmplContent, funcSrc, func, optEtc)
		}
		return null
	};
	try {
		String.prototype.process = function(context, optFlags) {
			var template = TrimPath.parseTemplate(this, null);
			if (template != null) {
				return template.process(context, optFlags)
			}
			return this
		}
	} catch(e) {}
	TrimPath.parseTemplate_etc = {};
	TrimPath.parseTemplate_etc.statementTag = "forelse|for|if|elseif|else|var|macro";
	TrimPath.parseTemplate_etc.statementDef = {
		"if": {
			delta: 1,
			prefix: "if (",
			suffix: ") {",
			paramMin: 1
		},
		"else": {
			delta: 0,
			prefix: "} else {"
		},
		"elseif": {
			delta: 0,
			prefix: "} else if (",
			suffix: ") {",
			paramDefault: "true"
		},
		"/if": {
			delta: -1,
			prefix: "}"
		},
		"for": {
			delta: 1,
			paramMin: 3,
			prefixFunc: function(stmtParts, state, tmplName, etc) {
				if (stmtParts[2] != "in") {
					throw new etc.ParseError(tmplName, state.line, "bad for loop statement: " + stmtParts.join(" "))
				}
				var iterVar = stmtParts[1];
				var listVar = "__LIST__" + iterVar;
				return ["var ", listVar, " = ", stmtParts[3], ";", "var __LENGTH_STACK__;", "if (typeof(__LENGTH_STACK__) == 'undefined' || !__LENGTH_STACK__.length) __LENGTH_STACK__ = new Array();", "__LENGTH_STACK__[__LENGTH_STACK__.length] = 0;", "if ((", listVar, ") != null) { ", "var ", iterVar, "_ct = 0;", "for (var ", iterVar, "_index in ", listVar, ") { ", iterVar, "_ct++;", "if (typeof(", listVar, "[", iterVar, "_index]) == 'function') {continue;}", "__LENGTH_STACK__[__LENGTH_STACK__.length - 1]++;", "var ", iterVar, " = ", listVar, "[", iterVar, "_index];"].join("")
			}
		},
		"forelse": {
			delta: 0,
			prefix: "} } if (__LENGTH_STACK__[__LENGTH_STACK__.length - 1] == 0) { if (",
			suffix: ") {",
			paramDefault: "true"
		},
		"/for": {
			delta: -1,
			prefix: "} }; delete __LENGTH_STACK__[__LENGTH_STACK__.length - 1];"
		},
		"var": {
			delta: 0,
			prefix: "var ",
			suffix: ";"
		},
		"macro": {
			delta: 1,
			prefixFunc: function(stmtParts, state, tmplName, etc) {
				var macroName = stmtParts[1].split("(")[0];
				return ["var ", macroName, " = function", stmtParts.slice(1).join(" ").substring(macroName.length), "{ var _OUT_arr = []; var _OUT = { write: function(m) { if (m) _OUT_arr.push(m); } }; "].join("")
			}
		},
		"/macro": {
			delta: -1,
			prefix: " return _OUT_arr.join(''); };"
		}
	};
	TrimPath.parseTemplate_etc.modifierDef = {
		"eat": function(v) {
			return ""
		},
		"escape": function(s) {
			return String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
		},
		"capitalize": function(s) {
			return String(s).toUpperCase()
		},
		"default": function(s, d) {
			return s != null ? s: d
		}
	};
	TrimPath.parseTemplate_etc.modifierDef.h = TrimPath.parseTemplate_etc.modifierDef.escape;
	TrimPath.parseTemplate_etc.Template = function(tmplName, tmplContent, funcSrc, func, etc) {
		this.process = function(context, flags) {
			if (context == null) {
				context = {}
			}
			if (context._MODIFIERS == null) {
				context._MODIFIERS = {}
			}
			if (context.defined == null) {
				context.defined = function(str) {
					return (context[str] != undefined)
				}
			}
			for (var k in etc.modifierDef) {
				if (context._MODIFIERS[k] == null) {
					context._MODIFIERS[k] = etc.modifierDef[k]
				}
			}
			if (flags == null) {
				flags = {}
			}
			var resultArr = [];
			var resultOut = {
				write: function(m) {
					resultArr.push(m)
				}
			};
			try {
				func(resultOut, context, flags)
			} catch(e) {
				if (flags.throwExceptions == true) {
					throw e
				}
				var result = new String(resultArr.join("") + "[ERROR: " + e.toString() + (e.message ? "; " + e.message: "") + "]");
				result["exception"] = e;
				return result
			}
			return resultArr.join("")
		};
		this.name = tmplName;
		this.source = tmplContent;
		this.sourceFunc = funcSrc;
		this.toString = function() {
			return "TrimPath.Template [" + tmplName + "]"
		}
	};
	TrimPath.parseTemplate_etc.ParseError = function(name, line, message) {
		this.name = name;
		this.line = line;
		this.message = message
	};
	TrimPath.parseTemplate_etc.ParseError.prototype.toString = function() {
		return ("TrimPath template ParseError in " + this.name + ": line " + this.line + ", " + this.message)
	};
	var parse = function(body, tmplName, etc) {
		body = cleanWhiteSpace(body);
		var funcText = ["var TrimPath_Template_TEMP = function(_OUT, _CONTEXT, _FLAGS) { with (_CONTEXT) {"];
		var state = {
			stack: [],
			line: 1
		};
		var endStmtPrev = -1;
		while (endStmtPrev + 1 < body.length) {
			var begStmt = endStmtPrev;
			begStmt = body.indexOf("{", begStmt + 1);
			while (begStmt >= 0) {
				var endStmt = body.indexOf("}", begStmt + 1);
				var stmt = body.substring(begStmt, endStmt);
				var blockrx = stmt.match(/^\{(cdata|minify|eval)/);
				if (blockrx) {
					var blockType = blockrx[1];
					var blockMarkerBeg = begStmt + blockType.length + 1;
					var blockMarkerEnd = body.indexOf("}", blockMarkerBeg);
					if (blockMarkerEnd >= 0) {
						var blockMarker;
						if (blockMarkerEnd - blockMarkerBeg <= 0) {
							blockMarker = "{/" + blockType + "}"
						} else {
							blockMarker = body.substring(blockMarkerBeg + 1, blockMarkerEnd)
						}
						var blockEnd = body.indexOf(blockMarker, blockMarkerEnd + 1);
						if (blockEnd >= 0) {
							emitSectionText(body.substring(endStmtPrev + 1, begStmt), funcText);
							var blockText = body.substring(blockMarkerEnd + 1, blockEnd);
							if (blockType == "cdata") {
								emitText(blockText, funcText)
							} else {
								if (blockType == "minify") {
									emitText(scrubWhiteSpace(blockText), funcText)
								} else {
									if (blockType == "eval") {
										if (blockText != null && blockText.length > 0) {
											funcText.push("_OUT.write( (function() { " + blockText + " })() );")
										}
									}
								}
							}
							begStmt = endStmtPrev = blockEnd + blockMarker.length - 1
						}
					}
				} else {
					if (body.charAt(begStmt - 1) != "$" && body.charAt(begStmt - 1) != "\\") {
						var offset = (body.charAt(begStmt + 1) == "/" ? 2 : 1);
						if (body.substring(begStmt + offset, begStmt + 10 + offset).search(TrimPath.parseTemplate_etc.statementTag) == 0) {
							break
						}
					}
				}
				begStmt = body.indexOf("{", begStmt + 1)
			}
			if (begStmt < 0) {
				break
			}
			var endStmt = body.indexOf("}", begStmt + 1);
			if (endStmt < 0) {
				break
			}
			emitSectionText(body.substring(endStmtPrev + 1, begStmt), funcText);
			emitStatement(body.substring(begStmt, endStmt + 1), state, funcText, tmplName, etc);
			endStmtPrev = endStmt
		}
		emitSectionText(body.substring(endStmtPrev + 1), funcText);
		if (state.stack.length != 0) {
			throw new etc.ParseError(tmplName, state.line, "unclosed, unmatched statement(s): " + state.stack.join(","))
		}
		funcText.push("}}; TrimPath_Template_TEMP");
		return funcText.join("")
	};
	var emitStatement = function(stmtStr, state, funcText, tmplName, etc) {
		var parts = stmtStr.slice(1, -1).split(" ");
		var stmt = etc.statementDef[parts[0]];
		if (stmt == null) {
			emitSectionText(stmtStr, funcText);
			return
		}
		if (stmt.delta < 0) {
			if (state.stack.length <= 0) {
				throw new etc.ParseError(tmplName, state.line, "close tag does not match any previous statement: " + stmtStr)
			}
			state.stack.pop()
		}
		if (stmt.delta > 0) {
			state.stack.push(stmtStr)
		}
		if (stmt.paramMin != null && stmt.paramMin >= parts.length) {
			throw new etc.ParseError(tmplName, state.line, "statement needs more parameters: " + stmtStr)
		}
		if (stmt.prefixFunc != null) {
			funcText.push(stmt.prefixFunc(parts, state, tmplName, etc))
		} else {
			funcText.push(stmt.prefix)
		}
		if (stmt.suffix != null) {
			if (parts.length <= 1) {
				if (stmt.paramDefault != null) {
					funcText.push(stmt.paramDefault)
				}
			} else {
				for (var i = 1; i < parts.length; i++) {
					if (i > 1) {
						funcText.push(" ")
					}
					funcText.push(parts[i])
				}
			}
			funcText.push(stmt.suffix)
		}
	};
	var emitSectionText = function(text, funcText) {
		if (text.length <= 0) {
			return
		}
		var nlPrefix = 0;
		var nlSuffix = text.length - 1;
		while (nlPrefix < text.length && (text.charAt(nlPrefix) == "\n")) {
			nlPrefix++
		}
		while (nlSuffix >= 0 && (text.charAt(nlSuffix) == " " || text.charAt(nlSuffix) == "\t")) {
			nlSuffix--
		}
		if (nlSuffix < nlPrefix) {
			nlSuffix = nlPrefix
		}
		if (nlPrefix > 0) {
			funcText.push('if (_FLAGS.keepWhitespace == true) _OUT.write("');
			var s = text.substring(0, nlPrefix).replace("\n", "\\n");
			if (s.charAt(s.length - 1) == "\n") {
				s = s.substring(0, s.length - 1)
			}
			funcText.push(s);
			funcText.push('");')
		}
		var lines = text.substring(nlPrefix, nlSuffix + 1).split("\n");
		for (var i = 0; i < lines.length; i++) {
			emitSectionTextLine(lines[i], funcText);
			if (i < lines.length - 1) {
				funcText.push('_OUT.write("\\n");\n')
			}
		}
		if (nlSuffix + 1 < text.length) {
			funcText.push('if (_FLAGS.keepWhitespace == true) _OUT.write("');
			var s = text.substring(nlSuffix + 1).replace("\n", "\\n");
			if (s.charAt(s.length - 1) == "\n") {
				s = s.substring(0, s.length - 1)
			}
			funcText.push(s);
			funcText.push('");')
		}
	};
	var emitSectionTextLine = function(line, funcText) {
		var endMarkPrev = "}";
		var endExprPrev = -1;
		while (endExprPrev + endMarkPrev.length < line.length) {
			var begMark = "${",
			endMark = "}";
			var begExpr = line.indexOf(begMark, endExprPrev + endMarkPrev.length);
			if (begExpr < 0) {
				break
			}
			if (line.charAt(begExpr + 2) == "%") {
				begMark = "${%";
				endMark = "%}"
			}
			var endExpr = line.indexOf(endMark, begExpr + begMark.length);
			if (endExpr < 0) {
				break
			}
			emitText(line.substring(endExprPrev + endMarkPrev.length, begExpr), funcText);
			var exprArr = line.substring(begExpr + begMark.length, endExpr).replace(/\|\|/g, "#@@#").split("|");
			for (var k in exprArr) {
				if (exprArr[k].replace) {
					exprArr[k] = exprArr[k].replace(/#@@#/g, "||")
				}
			}
			funcText.push("_OUT.write(");
			emitExpression(exprArr, exprArr.length - 1, funcText);
			funcText.push(");");
			endExprPrev = endExpr;
			endMarkPrev = endMark
		}
		emitText(line.substring(endExprPrev + endMarkPrev.length), funcText)
	};
	var emitText = function(text, funcText) {
		if (text == null || text.length <= 0) {
			return
		}
		text = text.replace(/\\/g, "\\\\");
		text = text.replace(/\n/g, "\\n");
		text = text.replace(/"/g, '\\"');
		funcText.push('_OUT.write("');
		funcText.push(text);
		funcText.push('");')
	};
	var emitExpression = function(exprArr, index, funcText) {
		var expr = exprArr[index];
		if (index <= 0) {
			funcText.push(expr);
			return
		}
		var parts = expr.split(":");
		funcText.push('_MODIFIERS["');
		funcText.push(parts[0]);
		funcText.push('"](');
		emitExpression(exprArr, index - 1, funcText);
		if (parts.length > 1) {
			funcText.push(",");
			funcText.push(parts[1])
		}
		funcText.push(")")
	};
	var cleanWhiteSpace = function(result) {
		result = result.replace(/\t/g, "    ");
		result = result.replace(/\r\n/g, "\n");
		result = result.replace(/\r/g, "\n");
		result = result.replace(/^(\s*\S*(\s+\S+)*)\s*$/, "$1");
		return result
	};
	var scrubWhiteSpace = function(result) {
		result = result.replace(/^\s+/g, "");
		result = result.replace(/\s+$/g, "");
		result = result.replace(/\s+/g, " ");
		result = result.replace(/^(\s*\S*(\s+\S+)*)\s*$/, "$1");
		return result
	};
	TrimPath.parseDOMTemplate = function(elementId, optDocument, optEtc) {
		if (optDocument == null) {
			optDocument = document
		}
		var element = optDocument.getElementById(elementId);
		var content = element.value;
		if (content == null) {
			content = element.innerHTML
		}
		content = content.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
		return TrimPath.parseTemplate(content, elementId, optEtc)
	};
	TrimPath.processDOMTemplate = function(elementId, context, optFlags, optDocument, optEtc) {
		return TrimPath.parseDOMTemplate(elementId, optDocument, optEtc).process(context, optFlags)
	}
})();
//MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006 Valerio Proietti, <http://mad4milk.net>, MIT Style License.

var MooTools={'version':1.1};function $defined(obj){return(obj!=undefined);};function $type(obj){if(!$defined(obj))return false;if(obj.htmlElement)return'element';var type=typeof obj;if(type=='object'&&obj.nodeName){switch(obj.nodeType){case 1:return'element';case 3:return/\S/.test(obj.nodeValue)?'textnode':'whitespace';}}
if(type=='object'||type=='function'){switch(obj.constructor){case Array:return'array';case RegExp:return'regexp';case Class:return'class';}
if(typeof obj.length=='number'){if(obj.item)return'collection';if(obj.callee)return'arguments';}}
return type;};function $merge(){var mix={};for(var i=0;i<arguments.length;i++){for(var property in arguments[i]){var ap=arguments[i][property];var mp=mix[property];if(mp&&$type(ap)=='object'&&$type(mp)=='object')mix[property]=$merge(mp,ap);else mix[property]=ap;}}
return mix;};var $extend=Object.extend=function(){var args=arguments;if(!args[1])args=[this,args[0]];for(var property in args[1])args[0][property]=args[1][property];return args[0];};var $native=Object.Native=function(){for(var i=0,l=arguments.length;i<l;i++){arguments[i].extend=function(props){for(var prop in props){if(!this.prototype[prop])this.prototype[prop]=props[prop];if(!this[prop])this[prop]=$native.generic(prop);}};}};$native.generic=function(prop){return function(bind){return this.prototype[prop].apply(bind,Array.prototype.slice.call(arguments,1));};};$native(Function,Array,String,Number);var Abstract=function(obj){obj=obj||{};obj.extend=$extend;return obj;};var Window=new Abstract(window);var Document=new Abstract(document);document.head=document.getElementsByTagName('head')[0];function $chk(obj){return!!(obj||obj===0);};function $pick(obj,picked){return $defined(obj)?obj:picked;};function $random(min,max){return Math.floor(Math.random()*(max-min+1)+min);};function $time(){return new Date().getTime();};function $clear(timer){clearTimeout(timer);clearInterval(timer);return null;};window.xpath=!!(document.evaluate);if(window.ActiveXObject)window.ie=window[window.XMLHttpRequest?'ie7':'ie6']=true;else if(document.childNodes&&!document.all&&!navigator.taintEnabled)window.khtml=window.webkit=window[window.xpath?'webkit420':'webkit419']=true;else if(document.getBoxObjectFor!=null)window.gecko=true;if(typeof HTMLElement=='undefined'){var HTMLElement=function(){};if(window.webkit)document.createElement("iframe");HTMLElement.prototype=(window.webkit)?window["[[DOMElement.prototype]]"]:{};}
HTMLElement.prototype.htmlElement=true;if(window.ie6)try{document.execCommand("BackgroundImageCache",false,true);}catch(e){};var Class=function(properties){var klass=function(){return(arguments[0]!==null&&this.initialize&&$type(this.initialize)=='function')?this.initialize.apply(this,arguments):this;};$extend(klass,this);klass.prototype=properties;klass.constructor=Class;return klass;};Class.empty=function(){};Class.prototype={extend:function(properties){var proto=new this(null);for(var property in properties){var pp=proto[property];proto[property]=Class.Merge(pp,properties[property]);}
return new Class(proto);},implement:function(){for(var i=0,l=arguments.length;i<l;i++)$extend(this.prototype,arguments[i]);}};Class.Merge=function(previous,current){if(previous&&previous!=current){var type=$type(current);if(type!=$type(previous))return current;switch(type){case'function':var merged=function(){this.parent=arguments.callee.parent;return current.apply(this,arguments);};merged.parent=previous;return merged;case'object':return $merge(previous,current);}}
return current;};var Chain=new Class({chain:function(fn){this.chains=this.chains||[];this.chains.push(fn);return this;},callChain:function(){if(this.chains&&this.chains.length)this.chains.shift().delay(10,this);},clearChain:function(){this.chains=[];}});var Events=new Class({addEvent:function(type,fn){if(fn!=Class.empty){this.$events=this.$events||{};this.$events[type]=this.$events[type]||[];this.$events[type].include(fn);}
return this;},fireEvent:function(type,args,delay){if(this.$events&&this.$events[type]){this.$events[type].each(function(fn){fn.create({'bind':this,'delay':delay,'arguments':args})();},this);}
return this;},removeEvent:function(type,fn){if(this.$events&&this.$events[type])this.$events[type].remove(fn);return this;}});var Options=new Class({setOptions:function(){this.options=$merge.apply(null,[this.options].extend(arguments));if(!this.addEvent)return this;for(var option in this.options){if($type(this.options[option]=='function')&&option.test(/^on[A-Z]/))this.addEvent(option,this.options[option]);}
return this;}});Array.extend({forEach:function(fn,bind){for(var i=0,j=this.length;i<j;i++)fn.call(bind,this[i],i,this);},filter:function(fn,bind){var results=[];for(var i=0,j=this.length;i<j;i++){if(fn.call(bind,this[i],i,this))results.push(this[i]);}
return results;},map:function(fn,bind){var results=[];for(var i=0,j=this.length;i<j;i++)results[i]=fn.call(bind,this[i],i,this);return results;},every:function(fn,bind){for(var i=0,j=this.length;i<j;i++){if(!fn.call(bind,this[i],i,this))return false;}
return true;},some:function(fn,bind){for(var i=0,j=this.length;i<j;i++){if(fn.call(bind,this[i],i,this))return true;}
return false;},indexOf:function(item,from){var len=this.length;for(var i=(from<0)?Math.max(0,len+from):from||0;i<len;i++){if(this[i]===item)return i;}
return-1;},copy:function(start,length){start=start||0;if(start<0)start=this.length+start;length=length||(this.length-start);var newArray=[];for(var i=0;i<length;i++)newArray[i]=this[start++];return newArray;},remove:function(item){var i=0;var len=this.length;while(i<len){if(this[i]===item){this.splice(i,1);len--;}else{i++;}}
return this;},contains:function(item,from){return this.indexOf(item,from)!=-1;},associate:function(keys){var obj={},length=Math.min(this.length,keys.length);for(var i=0;i<length;i++)obj[keys[i]]=this[i];return obj;},extend:function(array){for(var i=0,j=array.length;i<j;i++)this.push(array[i]);return this;},merge:function(array){for(var i=0,l=array.length;i<l;i++)this.include(array[i]);return this;},include:function(item){if(!this.contains(item))this.push(item);return this;},getRandom:function(){return this[$random(0,this.length-1)]||false;},getLast:function(){return this[this.length-1]||false;}});Array.prototype.each=Array.prototype.forEach;Array.prototype.test=Array.prototype.contains;function $A(array){return Array.copy(array);};function $each(iterable,fn,bind){if(iterable&&typeof iterable.length=='number'&&$type(iterable)!='object')Array.forEach(iterable,fn,bind);else for(var name in iterable)fn.call(bind||iterable,iterable[name],name);};String.extend({test:function(regex,params){return(($type(regex)=='string')?new RegExp(regex,params):regex).test(this);},toInt:function(){return parseInt(this,10);},toFloat:function(){return parseFloat(this);},camelCase:function(){return this.replace(/-\D/g,function(match){return match.charAt(1).toUpperCase();});},hyphenate:function(){return this.replace(/\w[A-Z]/g,function(match){return(match.charAt(0)+'-'+match.charAt(1).toLowerCase());});},capitalize:function(){return this.replace(/\b[a-z]/g,function(match){return match.toUpperCase();});},trim:function(){return this.replace(/^\s+|\s+$/g,'');},clean:function(){return this.replace(/\s{2,}/g,' ').trim();},rgbToHex:function(array){var rgb=this.match(/\d{1,3}/g);return(rgb)?rgb.rgbToHex(array):false;},hexToRgb:function(array){var hex=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(hex)?hex.slice(1).hexToRgb(array):false;},contains:function(string,s){return(s)?(s+this+s).indexOf(s+string+s)>-1:this.indexOf(string)>-1;},escapeRegExp:function(){return this.replace(/([.*+?^${}()|[\]\/\\])/g,'\\$1');}});Array.extend({rgbToHex:function(array){if(this.length<3)return false;if(this.length==4&&this[3]==0&&!array)return'transparent';var hex=[];for(var i=0;i<3;i++){var bit=(this[i]-0).toString(16);hex.push((bit.length==1)?'0'+bit:bit);}
return array?hex:'#'+hex.join('');},hexToRgb:function(array){if(this.length!=3)return false;var rgb=[];for(var i=0;i<3;i++){rgb.push(parseInt((this[i].length==1)?this[i]+this[i]:this[i],16));}
return array?rgb:'rgb('+rgb.join(',')+')';}});Function.extend({create:function(options){var fn=this;options=$merge({'bind':fn,'event':false,'arguments':null,'delay':false,'periodical':false,'attempt':false},options);if($chk(options.arguments)&&$type(options.arguments)!='array')options.arguments=[options.arguments];return function(event){var args;if(options.event){event=event||window.event;args=[(options.event===true)?event:new options.event(event)];if(options.arguments)args.extend(options.arguments);}
else args=options.arguments||arguments;var returns=function(){return fn.apply($pick(options.bind,fn),args);};if(options.delay)return setTimeout(returns,options.delay);if(options.periodical)return setInterval(returns,options.periodical);if(options.attempt)try{return returns();}catch(err){return false;};return returns();};},pass:function(args,bind){return this.create({'arguments':args,'bind':bind});},attempt:function(args,bind){return this.create({'arguments':args,'bind':bind,'attempt':true})();},bind:function(bind,args){return this.create({'bind':bind,'arguments':args});},bindAsEventListener:function(bind,args){return this.create({'bind':bind,'event':true,'arguments':args});},delay:function(delay,bind,args){return this.create({'delay':delay,'bind':bind,'arguments':args})();},periodical:function(interval,bind,args){return this.create({'periodical':interval,'bind':bind,'arguments':args})();}});Number.extend({toInt:function(){return parseInt(this);},toFloat:function(){return parseFloat(this);},limit:function(min,max){return Math.min(max,Math.max(min,this));},round:function(precision){precision=Math.pow(10,precision||0);return Math.round(this*precision)/precision;},times:function(fn){for(var i=0;i<this;i++)fn(i);}});var Element=new Class({initialize:function(el,props){if($type(el)=='string'){if(window.ie&&props&&(props.name||props.type)){var name=(props.name)?' name="'+props.name+'"':'';var type=(props.type)?' type="'+props.type+'"':'';delete props.name;delete props.type;el='<'+el+name+type+'>';}
el=document.createElement(el);}
el=$(el);return(!props||!el)?el:el.set(props);}});var Elements=new Class({initialize:function(elements){return(elements)?$extend(elements,this):this;}});Elements.extend=function(props){for(var prop in props){this.prototype[prop]=props[prop];this[prop]=$native.generic(prop);}};function $(el){if(!el)return false;if(el.htmlElement)return Garbage.collect(el);if([window,document].contains(el))return el;var type=$type(el);if(type=='string'){el=document.getElementById(el);type=(el)?'element':false;}
if(type!='element')return false;if(el.htmlElement)return Garbage.collect(el);if(['object','embed'].contains(el.tagName.toLowerCase()))return el;$extend(el,Element.prototype);el.htmlElement=true;return Garbage.collect(el);};document.getElementsBySelector=document.getElementsByTagName;function $$(){var elements=[];for(var i=0,j=arguments.length;i<j;i++){var selector=arguments[i];switch($type(selector)){case'element':elements.push(selector);case'boolean':break;case false:break;case'string':selector=document.getElementsBySelector(selector,true);default:elements.extend(selector);}}
return $$.unique(elements);};$$.unique=function(array){var elements=[];for(var i=0,l=array.length;i<l;i++){if(array[i].$included)continue;var element=$(array[i]);if(element&&!element.$included){element.$included=true;elements.push(element);}}
for(var i=0,l=elements.length;i<l;i++)elements[i].$included=null;return new Elements(elements);};Elements.Multi=function(property){return function(){var args=arguments;var items=[];var elements=true;for(var i=0,j=this.length,returns;i<j;i++){returns=this[i][property].apply(this[i],args);if($type(returns)!='element')elements=false;items.push(returns);};return(elements)?$$.unique(items):items;};};Element.extend=function(properties){for(var property in properties){HTMLElement.prototype[property]=properties[property];Element.prototype[property]=properties[property];Element[property]=$native.generic(property);var elementsProperty=(Array.prototype[property])?property+'Elements':property;Elements.prototype[elementsProperty]=Elements.Multi(property);}};Element.extend({set:function(props){for(var prop in props){var val=props[prop];switch(prop){case'styles':this.setStyles(val);break;case'events':if(this.addEvents)this.addEvents(val);break;case'properties':this.setProperties(val);break;default:this.setProperty(prop,val);}}
return this;},inject:function(el,where){el=$(el);switch(where){case'before':el.parentNode.insertBefore(this,el);break;case'after':var next=el.getNext();if(!next)el.parentNode.appendChild(this);else el.parentNode.insertBefore(this,next);break;case'top':var first=el.firstChild;if(first){el.insertBefore(this,first);break;}
default:el.appendChild(this);}
return this;},injectBefore:function(el){return this.inject(el,'before');},injectAfter:function(el){return this.inject(el,'after');},injectInside:function(el){return this.inject(el,'bottom');},injectTop:function(el){return this.inject(el,'top');},adopt:function(){var elements=[];$each(arguments,function(argument){elements=elements.concat(argument);});$$(elements).inject(this);return this;},remove:function(){return this.parentNode.removeChild(this);},clone:function(contents){var el=$(this.cloneNode(contents!==false));if(!el.$events)return el;el.$events={};for(var type in this.$events)el.$events[type]={'keys':$A(this.$events[type].keys),'values':$A(this.$events[type].values)};return el.removeEvents();},replaceWith:function(el){el=$(el);this.parentNode.replaceChild(el,this);return el;},appendText:function(text){if(window.ie){switch(this.getTag()){case'style':this.styleSheet.cssText=text;return this;case'script':return this.setProperty('text',text);}}
this.appendChild(document.createTextNode(text));return this;},hasClass:function(className){return this.className.contains(className,' ');},addClass:function(className){if(!this.hasClass(className))this.className=(this.className+' '+className).clean();return this;},removeClass:function(className){this.className=this.className.replace(new RegExp('(^|\\s)'+className+'(?:\\s|$)'),'$1').clean();return this;},toggleClass:function(className){return this.hasClass(className)?this.removeClass(className):this.addClass(className);},setStyle:function(property,value){switch(property){case'opacity':return this.setOpacity(parseFloat(value));case'float':property=(window.ie)?'styleFloat':'cssFloat';}
property=property.camelCase();switch($type(value)){case'number':if(!['zIndex','zoom'].contains(property))value+='px';break;case'array':value='rgb('+value.join(',')+')';}
this.style[property]=value;return this;},setStyles:function(source){switch($type(source)){case'object':Element.setMany(this,'setStyle',source);break;case'string':this.style.cssText=source;}
return this;},setOpacity:function(opacity){if(opacity==0){if(this.style.visibility!="hidden")this.style.visibility="hidden";}else{if(this.style.visibility!="visible")this.style.visibility="visible";}
if(!this.currentStyle||!this.currentStyle.hasLayout)this.style.zoom=1;if(window.ie)this.style.filter=(opacity==1)?'':"alpha(opacity="+opacity*100+")";this.style.opacity=this.$tmp.opacity=opacity;return this;},getStyle:function(property){property=property.camelCase();var result=this.style[property];if(!$chk(result)){if(property=='opacity')return this.$tmp.opacity;var result=[];for(var style in Element.Styles){if(property==style){Element.Styles[style].each(function(s){var style=this.getStyle(s);result.push(parseInt(style)?style:'0px');},this);if(property=='border'){var every=result.every(function(bit){return(bit==result[0]);});return(every)?result[0]:false;}
return result.join(' ');}}
if(property.contains('border')){if(Element.Styles.border.contains(property)){return['Width','Style','Color'].map(function(p){return this.getStyle(property+p);},this).join(' ');}else if(Element.borderShort.contains(property)){return['Top','Right','Bottom','Left'].map(function(p){return this.getStyle('border'+p+property.replace('border',''));},this).join(' ');}}
if(document.defaultView)result=document.defaultView.getComputedStyle(this,null).getPropertyValue(property.hyphenate());else if(this.currentStyle)result=this.currentStyle[property];}
if(window.ie)result=Element.fixStyle(property,result,this);if(result&&property.test(/color/i)&&result.contains('rgb')){return result.split('rgb').splice(1,4).map(function(color){return color.rgbToHex();}).join(' ');}
return result;},getStyles:function(){return Element.getMany(this,'getStyle',arguments);},walk:function(brother,start){brother+='Sibling';var el=(start)?this[start]:this[brother];while(el&&$type(el)!='element')el=el[brother];return $(el);},getPrevious:function(){return this.walk('previous');},getNext:function(){return this.walk('next');},getFirst:function(){return this.walk('next','firstChild');},getLast:function(){return this.walk('previous','lastChild');},getParent:function(){return $(this.parentNode);},getChildren:function(){return $$(this.childNodes);},hasChild:function(el){return!!$A(this.getElementsByTagName('*')).contains(el);},getProperty:function(property){var index=Element.Properties[property];if(index)return this[index];if(!window.ie)return this.getAttribute(property);var node=this.attributes[property];return(node)?node.nodeValue:null;},removeProperty:function(property){var index=Element.Properties[property];if(index)this[index]='';else this.removeAttribute(property);return this;},getProperties:function(){return Element.getMany(this,'getProperty',arguments);},setProperty:function(property,value){var index=Element.Properties[property];if(index)this[index]=value;else this.setAttribute(property,value);return this;},setProperties:function(source){return Element.setMany(this,'setProperty',source);},setHTML:function(){this.innerHTML=$A(arguments).join('');return this;},getTag:function(){return this.tagName.toLowerCase();},empty:function(){Garbage.trash(this.getElementsByTagName('*'));return this.setHTML('');}});Element.fixStyle=function(property,result,element){if($chk(parseInt(result)))return result;if(['height','width'].contains(property)){var values=(property=='width')?['left','right']:['top','bottom'];var size=0;values.each(function(value){size+=element.getStyle('border-'+value+'-width').toInt()+element.getStyle('padding-'+value).toInt();});return element['offset'+property.capitalize()]-size+'px';}else if(property.test(/border(.+)Width|margin|padding/)){return'0px';}
return result;};Element.Styles={'border':[],'padding':[],'margin':[]};['Top','Right','Bottom','Left'].each(function(direction){for(var style in Element.Styles)Element.Styles[style].push(style+direction);});Element.borderShort=['borderWidth','borderStyle','borderColor'];Element.getMany=function(el,method,keys){var result={};$each(keys,function(key){result[key]=el[method](key);});return result;};Element.setMany=function(el,method,pairs){for(var key in pairs)el[method](key,pairs[key]);return el;};Element.Properties=new Abstract({'class':'className','for':'htmlFor','colspan':'colSpan','rowspan':'rowSpan','accesskey':'accessKey','tabindex':'tabIndex','maxlength':'maxLength','readonly':'readOnly','value':'value','disabled':'disabled','checked':'checked','multiple':'multiple'});Element.Methods={Listeners:{addListener:function(type,fn){if(this.addEventListener)this.addEventListener(type,fn,false);else this.attachEvent('on'+type,fn);return this;},removeListener:function(type,fn){if(this.removeEventListener)this.removeEventListener(type,fn,false);else this.detachEvent('on'+type,fn);return this;}}};window.extend(Element.Methods.Listeners);document.extend(Element.Methods.Listeners);Element.extend(Element.Methods.Listeners);var Garbage={elements:[],collect:function(el){if(!el.$tmp){Garbage.elements.push(el);el.$tmp={'opacity':1};}
return el;},trash:function(elements){for(var i=0,j=elements.length,el;i<j;i++){if(!(el=elements[i])||!el.$tmp)continue;if(el.$events)el.fireEvent('trash').removeEvents();for(var p in el.$tmp)el.$tmp[p]=null;for(var p in Element.prototype)el[p]=null;el.htmlElement=el.$tmp=el=null;Garbage.elements.remove(el);}},empty:function(){Garbage.collect(window);Garbage.collect(document);Garbage.trash(Garbage.elements);}};window.addListener('beforeunload',function(){window.addListener('unload',Garbage.empty);if(window.ie)window.addListener('unload',CollectGarbage);});var Event=new Class({initialize:function(event){if(event&&event.$extended)return event;this.$extended=true;event=event||window.event;this.event=event;this.type=event.type;this.target=event.target||event.srcElement;if(this.target.nodeType==3)this.target=this.target.parentNode;this.shift=event.shiftKey;this.control=event.ctrlKey;this.alt=event.altKey;this.meta=event.metaKey;if(['DOMMouseScroll','mousewheel'].contains(this.type)){this.wheel=(event.wheelDelta)?event.wheelDelta/120:-(event.detail||0)/3;}else if(this.type.contains('key')){this.code=event.which||event.keyCode;for(var name in Event.keys){if(Event.keys[name]==this.code){this.key=name;break;}}
if(this.type=='keydown'){var fKey=this.code-111;if(fKey>0&&fKey<13)this.key='f'+fKey;}
this.key=this.key||String.fromCharCode(this.code).toLowerCase();}else if(this.type.test(/(click|mouse|menu)/)){this.page={'x':event.pageX||event.clientX+document.documentElement.scrollLeft,'y':event.pageY||event.clientY+document.documentElement.scrollTop};this.client={'x':event.pageX?event.pageX-window.pageXOffset:event.clientX,'y':event.pageY?event.pageY-window.pageYOffset:event.clientY};this.rightClick=(event.which==3)||(event.button==2);switch(this.type){case'mouseover':this.relatedTarget=event.relatedTarget||event.fromElement;break;case'mouseout':this.relatedTarget=event.relatedTarget||event.toElement;}
this.fixRelatedTarget();}
return this;},stop:function(){return this.stopPropagation().preventDefault();},stopPropagation:function(){if(this.event.stopPropagation)this.event.stopPropagation();else this.event.cancelBubble=true;return this;},preventDefault:function(){if(this.event.preventDefault)this.event.preventDefault();else this.event.returnValue=false;return this;}});Event.fix={relatedTarget:function(){if(this.relatedTarget&&this.relatedTarget.nodeType==3)this.relatedTarget=this.relatedTarget.parentNode;},relatedTargetGecko:function(){try{Event.fix.relatedTarget.call(this)}catch(e){this.relatedTarget=this.target};}};Event.prototype.fixRelatedTarget=(window.gecko)?Event.fix.relatedTargetGecko:Event.fix.relatedTarget;Event.keys=new Abstract({'enter':13,'up':38,'down':40,'left':37,'right':39,'esc':27,'space':32,'backspace':8,'tab':9,'delete':46});Element.Methods.Events={addEvent:function(type,fn){this.$events=this.$events||{};this.$events[type]=this.$events[type]||{'keys':[],'values':[]};if(this.$events[type].keys.contains(fn))return this;this.$events[type].keys.push(fn);var realType=type;var custom=Element.Events[type];if(custom){if(custom.add)custom.add.call(this,fn);if(custom.map)fn=custom.map;if(custom.type)realType=custom.type;}
if(!this.addEventListener)fn=fn.create({'bind':this,'event':true});this.$events[type].values.push(fn);return this.addListener(realType,fn);},removeEvent:function(type,fn){if(!this.$events||!this.$events[type])return this;var pos=this.$events[type].keys.indexOf(fn);if(pos==-1)return this;var key=this.$events[type].keys.splice(pos,1)[0];var value=this.$events[type].values.splice(pos,1)[0];var custom=Element.Events[type];if(custom){if(custom.remove)custom.remove.call(this,fn);if(custom.type)type=custom.type;}
return this.removeListener(type,value);},addEvents:function(source){return Element.setMany(this,'addEvent',source);},removeEvents:function(type){if(!this.$events)return this;if(!type){for(var evType in this.$events)this.removeEvents(evType);this.$events=null;}else if(this.$events[type]){this.$events[type].keys.each(function(fn){this.removeEvent(type,fn);},this);this.$events[type]=null;}
return this;},fireEvent:function(type,args,delay){if(!this.$events||!this.$events[type])return this;this.$events[type].keys.each(function(fn){fn.create({'bind':this,'delay':delay,'arguments':args})();},this);return this;},cloneEvents:function(from,type){if(!from.$events)return this;if(!type){for(var evType in from.$events)this.cloneEvents(from,evType);}else if(from.$events[type]){from.$events[type].keys.each(function(fn){this.addEvent(type,fn);},this);}
return this;}};window.extend(Element.Methods.Events);document.extend(Element.Methods.Events);Element.extend(Element.Methods.Events);Element.Events=new Abstract({'mouseenter':{type:'mouseover',map:function(event){event=new Event(event);if(event.relatedTarget==this||this.hasChild(event.relatedTarget))return;this.fireEvent('mouseenter',event);}},'mouseleave':{type:'mouseout',map:function(event){event=new Event(event);if(event.relatedTarget==this||this.hasChild(event.relatedTarget))return;this.fireEvent('mouseleave',event);}},'mousewheel':{type:(window.gecko)?'DOMMouseScroll':'mousewheel'}});Function.extend({bindWithEvent:function(bind,args){return this.create({'bind':bind,'arguments':args,'event':Event});}});Elements.extend({filterByTag:function(tag){return new Elements(this.filter(function(el){return(Element.getTag(el)==tag);}));},filterByClass:function(className,nocash){var elements=this.filter(function(el){return(el.className&&el.className.contains(className,' '));});return(nocash)?elements:new Elements(elements);},filterById:function(id,nocash){var elements=this.filter(function(el){return(el.id==id);});return(nocash)?elements:new Elements(elements);},filterByAttribute:function(name,operator,value,nocash){var elements=this.filter(function(el){var current=Element.getProperty(el,name);if(!current)return false;if(!operator)return true;switch(operator){case'=':return(current==value);case'*=':return(current.contains(value));case'^=':return(current.substr(0,value.length)==value);case'$=':return(current.substr(current.length-value.length)==value);case'!=':return(current!=value);case'~=':return current.contains(value,' ');}
return false;});return(nocash)?elements:new Elements(elements);}});function $E(selector,filter){return($(filter)||document).getElement(selector);};function $ES(selector,filter){return($(filter)||document).getElementsBySelector(selector);};$$.shared={'regexp':/^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/,'xpath':{getParam:function(items,context,param,i){var temp=[context.namespaceURI?'xhtml:':'',param[1]];if(param[2])temp.push('[@id="',param[2],'"]');if(param[3])temp.push('[contains(concat(" ", @class, " "), " ',param[3],' ")]');if(param[4]){if(param[5]&&param[6]){switch(param[5]){case'*=':temp.push('[contains(@',param[4],', "',param[6],'")]');break;case'^=':temp.push('[starts-with(@',param[4],', "',param[6],'")]');break;case'$=':temp.push('[substring(@',param[4],', string-length(@',param[4],') - ',param[6].length,' + 1) = "',param[6],'"]');break;case'=':temp.push('[@',param[4],'="',param[6],'"]');break;case'!=':temp.push('[@',param[4],'!="',param[6],'"]');}}else{temp.push('[@',param[4],']');}}
items.push(temp.join(''));return items;},getItems:function(items,context,nocash){var elements=[];var xpath=document.evaluate('.//'+items.join('//'),context,$$.shared.resolver,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);for(var i=0,j=xpath.snapshotLength;i<j;i++)elements.push(xpath.snapshotItem(i));return(nocash)?elements:new Elements(elements.map($));}},'normal':{getParam:function(items,context,param,i){if(i==0){if(param[2]){var el=context.getElementById(param[2]);if(!el||((param[1]!='*')&&(Element.getTag(el)!=param[1])))return false;items=[el];}else{items=$A(context.getElementsByTagName(param[1]));}}else{items=$$.shared.getElementsByTagName(items,param[1]);if(param[2])items=Elements.filterById(items,param[2],true);}
if(param[3])items=Elements.filterByClass(items,param[3],true);if(param[4])items=Elements.filterByAttribute(items,param[4],param[5],param[6],true);return items;},getItems:function(items,context,nocash){return(nocash)?items:$$.unique(items);}},resolver:function(prefix){return(prefix=='xhtml')?'http://www.w3.org/1999/xhtml':false;},getElementsByTagName:function(context,tagName){var found=[];for(var i=0,j=context.length;i<j;i++)found.extend(context[i].getElementsByTagName(tagName));return found;}};$$.shared.method=(window.xpath)?'xpath':'normal';Element.Methods.Dom={getElements:function(selector,nocash){var items=[];selector=selector.trim().split(' ');for(var i=0,j=selector.length;i<j;i++){var sel=selector[i];var param=sel.match($$.shared.regexp);if(!param)break;param[1]=param[1]||'*';var temp=$$.shared[$$.shared.method].getParam(items,this,param,i);if(!temp)break;items=temp;}
return $$.shared[$$.shared.method].getItems(items,this,nocash);},getElement:function(selector){return $(this.getElements(selector,true)[0]||false);},getElementsBySelector:function(selector,nocash){var elements=[];selector=selector.split(',');for(var i=0,j=selector.length;i<j;i++)elements=elements.concat(this.getElements(selector[i],true));return(nocash)?elements:$$.unique(elements);},getElementsByClassName:function(className){return this.getElements('.'+className);}};Element.extend({getElementById:function(id){var el=document.getElementById(id);if(!el)return false;for(var parent=el.parentNode;parent!=this;parent=parent.parentNode){if(!parent)return false;}
return el;}});document.extend(Element.Methods.Dom);Element.extend(Element.Methods.Dom);Element.extend({scrollTo:function(x,y){this.scrollLeft=x;this.scrollTop=y;},getSize:function(){return{'scroll':{'x':this.scrollLeft,'y':this.scrollTop},'size':{'x':this.offsetWidth,'y':this.offsetHeight},'scrollSize':{'x':this.scrollWidth,'y':this.scrollHeight}};},getPosition:function(overflown){overflown=overflown||[];var el=this,left=0,top=0;do{left+=el.offsetLeft||0;top+=el.offsetTop||0;el=el.offsetParent;}while(el);overflown.each(function(element){left-=element.scrollLeft||0;top-=element.scrollTop||0;});return{'x':left,'y':top};},getTop:function(overflown){return this.getPosition(overflown).y;},getLeft:function(overflown){return this.getPosition(overflown).x;},getCoordinates:function(overflown){var position=this.getPosition(overflown);var obj={'width':this.offsetWidth,'height':this.offsetHeight,'left':position.x,'top':position.y};obj.right=obj.left+obj.width;obj.bottom=obj.top+obj.height;return obj;}});Element.Events.domready={add:function(fn){if(window.loaded){fn.call(this);return;}
var domReady=function(){if(window.loaded)return;window.loaded=true;window.timer=$clear(window.timer);this.fireEvent('domready');}.bind(this);if(document.readyState&&window.webkit){window.timer=function(){if(['loaded','complete'].contains(document.readyState))domReady();}.periodical(50);}else if(document.readyState&&window.ie){if(!$('ie_ready')){var src=(window.location.protocol=='https:')?'://0':'javascript:void(0)';document.write('<script id="ie_ready" defer src="'+src+'"><\/script>');$('ie_ready').onreadystatechange=function(){if(this.readyState=='complete')domReady();};}}else{window.addListener("load",domReady);document.addListener("DOMContentLoaded",domReady);}}};window.onDomReady=function(fn){return this.addEvent('domready',fn);};window.extend({getWidth:function(){if(this.webkit419)return this.innerWidth;if(this.opera)return document.body.clientWidth;return document.documentElement.clientWidth;},getHeight:function(){if(this.webkit419)return this.innerHeight;if(this.opera)return document.body.clientHeight;return document.documentElement.clientHeight;},getScrollWidth:function(){if(this.ie)return Math.max(document.documentElement.offsetWidth,document.documentElement.scrollWidth);if(this.webkit)return document.body.scrollWidth;return document.documentElement.scrollWidth;},getScrollHeight:function(){if(this.ie)return Math.max(document.documentElement.offsetHeight,document.documentElement.scrollHeight);if(this.webkit)return document.body.scrollHeight;return document.documentElement.scrollHeight;},getScrollLeft:function(){return this.pageXOffset||document.documentElement.scrollLeft;},getScrollTop:function(){return this.pageYOffset||document.documentElement.scrollTop;},getSize:function(){return{'size':{'x':this.getWidth(),'y':this.getHeight()},'scrollSize':{'x':this.getScrollWidth(),'y':this.getScrollHeight()},'scroll':{'x':this.getScrollLeft(),'y':this.getScrollTop()}};},getPosition:function(){return{'x':0,'y':0}}});var Fx={Shared:{}};Fx.Base=new Class({options:{onStart:Class.empty,onComplete:Class.empty,onCancel:Class.empty,transition:function(p){return-(Math.cos(Math.PI*p)-1)/2;},duration:500,unit:'px',wait:true,fps:50},initialize:function(options){this.element=this.element||null;this.setOptions(options);if(this.options.initialize)this.options.initialize.call(this);},step:function(){var time=$time();if(time<this.time+this.options.duration){this.delta=this.options.transition((time-this.time)/this.options.duration);this.setNow();this.increase();}else{this.stop(true);this.set(this.to);this.fireEvent('onComplete',this.element,10);this.callChain();}},set:function(to){this.now=to;this.increase();return this;},setNow:function(){this.now=this.compute(this.from,this.to);},compute:function(from,to){return(to-from)*this.delta+from;},start:function(from,to){if(!this.options.wait)this.stop();else if(this.timer)return this;this.from=from;this.to=to;this.change=this.to-this.from;this.time=$time();this.timer=this.step.periodical(Math.round(1000/this.options.fps),this);this.fireEvent('onStart',this.element);return this;},stop:function(end){if(!this.timer)return this;this.timer=$clear(this.timer);if(!end)this.fireEvent('onCancel',this.element);return this;},custom:function(from,to){return this.start(from,to)},clearTimer:function(end){return this.stop(end)}});Fx.Base.implement(new Chain,new Events,new Options);Fx.CSS={select:function(property,to){if(property.test(/color/i))return this.Color;if(to.contains&&to.contains(' '))return this.Multi;return this.Single;},parse:function(el,property,fromTo){if(!fromTo.push)fromTo=[fromTo];var from=fromTo[0],to=fromTo[1];if(!to&&to!=0){to=from;from=el.getStyle(property);}
var css=this.select(property,to);return{from:css.parse(from),to:css.parse(to),css:css};}};Fx.CSS.Single={parse:function(value){return parseFloat(value);},getNow:function(from,to,fx){return fx.compute(from,to);},getValue:function(value,unit,property){if(unit=='px'&&property!='opacity')value=Math.round(value);return value+unit;}};Fx.CSS.Multi={parse:function(value){return value.push?value:value.split(' ').map(function(v){return parseFloat(v);});},getNow:function(from,to,fx){var now=[];for(var i=0;i<from.length;i++)now[i]=fx.compute(from[i],to[i]);return now;},getValue:function(value,unit,property){if(unit=='px'&&property!='opacity')value=value.map(Math.round);return value.join(unit+' ')+unit;}};Fx.CSS.Color={parse:function(value){return value.push?value:value.hexToRgb(true);},getNow:function(from,to,fx){var now=[];for(var i=0;i<from.length;i++)now[i]=Math.round(fx.compute(from[i],to[i]));return now;},getValue:function(value){return'rgb('+value.join(',')+')';}};Fx.Style=Fx.Base.extend({initialize:function(el,property,options){this.element=$(el);this.property=property;this.parent(options);},hide:function(){return this.set(0);},setNow:function(){this.now=this.css.getNow(this.from,this.to,this);},set:function(to){this.css=Fx.CSS.select(this.property,to);return this.parent(this.css.parse(to));},start:function(from,to){if(this.timer&&this.options.wait)return this;var parsed=Fx.CSS.parse(this.element,this.property,[from,to]);this.css=parsed.css;return this.parent(parsed.from,parsed.to);},increase:function(){this.element.setStyle(this.property,this.css.getValue(this.now,this.options.unit,this.property));}});Element.extend({effect:function(property,options){return new Fx.Style(this,property,options);}});Fx.Styles=Fx.Base.extend({initialize:function(el,options){this.element=$(el);this.parent(options);},setNow:function(){for(var p in this.from)this.now[p]=this.css[p].getNow(this.from[p],this.to[p],this);},set:function(to){var parsed={};this.css={};for(var p in to){this.css[p]=Fx.CSS.select(p,to[p]);parsed[p]=this.css[p].parse(to[p]);}
return this.parent(parsed);},start:function(obj){if(this.timer&&this.options.wait)return this;this.now={};this.css={};var from={},to={};for(var p in obj){var parsed=Fx.CSS.parse(this.element,p,obj[p]);from[p]=parsed.from;to[p]=parsed.to;this.css[p]=parsed.css;}
return this.parent(from,to);},increase:function(){for(var p in this.now)this.element.setStyle(p,this.css[p].getValue(this.now[p],this.options.unit,p));}});Element.extend({effects:function(options){return new Fx.Styles(this,options);}});Fx.Scroll=Fx.Base.extend({options:{overflown:[],offset:{'x':0,'y':0}},initialize:function(element,options){this.now=[];this.element=$(element);this.bound={'stop':this.stop.bind(this,false)};this.addEvent('onStart',function(){document.addEvent('mousewheel',this.bound.stop);}.bind(this));this.removeEvent('onComplete',function(){document.removeEvent('mousewheel',this.bound.stop);}.bind(this));this.parent(options);},setNow:function(){for(var i=0;i<2;i++)this.now[i]=this.compute(this.from[i],this.to[i]);},scrollTo:function(x,y){if(this.timer&&this.options.wait)return this;var el=this.element.getSize();var values={'x':x,'y':y};for(var z in el.size){var max=el.scrollSize[z]-el.size[z];if($chk(values[z]))values[z]=($type(values[z])=='number')?values[z].limit(0,max):max;else values[z]=el.scroll[z];values[z]+=this.options.offset[z];}
return this.start([el.scroll.x,el.scroll.y],[values.x,values.y]);},toTop:function(){return this.scrollTo(false,0);},toBottom:function(){return this.scrollTo(false,'full');},toLeft:function(){return this.scrollTo(0,false);},toRight:function(){return this.scrollTo('full',false);},toElement:function(el){var parent=this.element.getPosition(this.options.overflown);var target=$(el).getPosition(this.options.overflown);return this.scrollTo(target.x-parent.x,target.y-parent.y);},increase:function(){this.element.scrollTo(this.now[0],this.now[1]);}});Fx.Slide=Fx.Base.extend({options:{mode:'vertical'},initialize:function(el,options){this.element=$(el);this.wrapper=new Element('div',{'styles':$extend(this.element.getStyles('margin'),{'overflow':'hidden'})}).injectAfter(this.element).adopt(this.element);this.element.setStyle('margin',0);this.setOptions(options);this.now=[];this.parent(this.options);if(window.webkit419)this.addEvent('onComplete',function(){this.element.remove().inject(this.wrapper);});},setNow:function(){for(var i=0;i<2;i++)this.now[i]=this.compute(this.from[i],this.to[i]);},vertical:function(){this.margin='margin-top';this.layout='height';this.offset=this.element.offsetHeight;},horizontal:function(){this.margin='margin-left';this.layout='width';this.offset=this.element.offsetWidth;},slideIn:function(mode){this[mode||this.options.mode]();return this.start([this.element.getStyle(this.margin).toInt(),this.wrapper.getStyle(this.layout).toInt()],[0,this.offset]);},slideOut:function(mode){this[mode||this.options.mode]();return this.start([this.element.getStyle(this.margin).toInt(),this.wrapper.getStyle(this.layout).toInt()],[-this.offset,0]);},hide:function(mode){this[mode||this.options.mode]();return this.set([-this.offset,0]);},show:function(mode){this[mode||this.options.mode]();return this.set([0,this.offset]);},toggle:function(mode){if(this.wrapper.offsetHeight==0||this.wrapper.offsetWidth==0)return this.slideIn(mode);return this.slideOut(mode);},increase:function(){this.element.setStyle(this.margin,this.now[0]+this.options.unit);this.wrapper.setStyle(this.layout,this.now[1]+this.options.unit);}});Fx.Transition=function(transition,params){params=params||[];if($type(params)!='array')params=[params];return $extend(transition,{easeIn:function(pos){return transition(pos,params);},easeOut:function(pos){return 1-transition(1-pos,params);},easeInOut:function(pos){return(pos<=0.5)?transition(2*pos,params)/2:(2-transition(2*(1-pos),params))/2;}});};Fx.Transitions=new Abstract({linear:function(p){return p;}});Fx.Transitions.extend=function(transitions){for(var transition in transitions){Fx.Transitions[transition]=new Fx.Transition(transitions[transition]);Fx.Transitions.compat(transition);};};Fx.Transitions.compat=function(transition){['In','Out','InOut'].each(function(easeType){Fx.Transitions[transition.toLowerCase()+easeType]=Fx.Transitions[transition]['ease'+easeType];});};Fx.Transitions.extend({Pow:function(p,x){return Math.pow(p,x[0]||6);},Expo:function(p){return Math.pow(2,8*(p-1));},Circ:function(p){return 1-Math.sin(Math.acos(p));},Sine:function(p){return 1-Math.sin((1-p)*Math.PI/2);},Back:function(p,x){x=x[0]||1.618;return Math.pow(p,2)*((x+1)*p-x);},Bounce:function(p){var value;for(var a=0,b=1;1;a+=b,b/=2){if(p>=(7-4*a)/11){value=-Math.pow((11-6*a-11*p)/4,2)+b*b;break;}}
return value;},Elastic:function(p,x){return Math.pow(2,10*--p)*Math.cos(20*p*Math.PI*(x[0]||1)/3);}});['Quad','Cubic','Quart','Quint'].each(function(transition,i){Fx.Transitions[transition]=new Fx.Transition(function(p){return Math.pow(p,[i+2]);});Fx.Transitions.compat(transition);});var SmoothScroll=Fx.Scroll.extend({initialize:function(options){this.parent(window,options);this.links=(this.options.links)?$$(this.options.links):$$(document.links);var location=window.location.href.match(/^[^#]*/)[0]+'#';this.links.each(function(link){if(link.href.indexOf(location)!=0)return;var anchor=link.href.substr(location.length);if(anchor&&$(anchor))this.useLink(link,anchor);},this);if(!window.webkit419)this.addEvent('onComplete',function(){window.location.hash=this.anchor;});},useLink:function(link,anchor){link.addEvent('click',function(event){this.anchor=anchor;this.toElement(anchor);event.stop();}.bindWithEvent(this));}});/*


Sample application header
*/

dojo.provide("stdlib.behavior.AutoSuggest.SuggestNavigationBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.AutoSuggest.SuggestNavigationBehavior", mojo.command.Behavior,
{
	suggestionIndex: -1,
	suggestion: null,
	execute: function(requestObj) {
		var e = requestObj.getEvent();
		var up = 38; // up arrow
		var down = 40; // down arrow
		var tabKey = 9; // tab key
		var suggestions = requestObj.getParams().suggestions;
		var suggestionsLength = suggestions.length;
		this.suggestionIndex = -1;
		for (var i = 0; i < suggestionsLength; i++) {
			if (dojo.hasClass(suggestions[i], "selected")) {
				this.suggestionIndex = i;
				break;
			}
		}

		if (e && e.which) {
			e = e;
			characterCode = e.which;
		} else {
			e = event;
			characterCode = e.keyCode;
		}

		if (suggestionsLength > 0) {
			switch (characterCode) {
				case up:
					this.suggestionIndex--;
					if (this.suggestionIndex < 0) {
						this.suggestionIndex = suggestionsLength - 1;
					}
					this.suggestion = suggestions[this.suggestionIndex];
					this.onNav();
					break;
				case down:
					this.suggestionIndex++;
					if (this.suggestionIndex >= suggestionsLength) {
						this.suggestionIndex = 0;
					}
					this.suggestion = suggestions[this.suggestionIndex];
					this.onNav();
					break;
			}
		}
	},
	onNav: function() {}
});
dojo.provide("stdlib.behavior.ClearFormBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.ClearFormBehavior", mojo.command.Behavior, {
	execute: function(requestObj) {
		var params = requestObj.getParams();
		var formSet = requestObj.contextObj;
		var noload = false;
		var clearHidden = false;
		var clearImages = false;
		if (!params) params = {};
		if (params.noload != null) noload = params.noload;
		if (params.formSet != null) formSet = params.formSet;
		if (params.clearHidden != null) clearHidden = params.clearHidden;
		if (params.clearImages != null) clearImages = params.clearImages;

		if (!noload) {
			var inputs = mojo.query("input", formSet);
			for (var i = 0; i < inputs.length; i++) {

				switch (inputs[i].type) {
					case "hidden":
						if (clearHidden) inputs[i].value = "";
						break;

					case "image":
						if (clearImages) inputs[i].value = "";
						break;

					case "checkbox":
						if (inputs[i].checked) inputs[i].checked = false;
						break;

					case "radio":
						if (inputs[i].checked) inputs[i].checked = false;
						break;

					case "button":
						break;

					case "submit":
						break;

					default:
						// file and text
						inputs[i].value = "";
				}

			}
			var textareas = mojo.query("textarea", formSet);
			for (var i = 0; i < textareas.length; i++) {
				textareas[i].value = "";
			}
			var selects = mojo.query("select", formSet);
			for (var i = 0; i < selects.length; i++) {
				selects[i].selectedIndex = 0;
			}
		}
	}
});
dojo.provide("stdlib.behavior.dialog.DialogBehavior");
dojo.require("mojo.command.Behavior");
dojo.declare("stdlib.behavior.dialog.DialogBehavior", mojo.command.Behavior,
{
	onComplete: function() {},
	onDataReady: function() {},
	_onDataReady: function(params) {
		this.onDataReady();
		var content = mojo.queryFirst(params.elContent, params.elContainer);
		var container = mojo.queryFirst(params.elContainer);

		var title = mojo.queryFirst(params.elTitle, params.elContainer);
		var flashElements = mojo.query("embed, object");


		title.innerHTML = params.title;

		if(dojo.isFF && (navigator.appVersion.indexOf("Mac")!=-1)) {
			this.hideFlash(flashElements);
		}

		container.style.visibility = "";
		if(dojo.isIE) {
			mojo.queryFirst("html").style.overflowX = "hidden";
		} else {
			document.body.style.overflowX = "hidden";
		}
		this.onComplete();
	},
	execute: function(requestObj) {
		//You may choose to pass in an ID or an HREF, if you pass in an
		//HREF, the dialog will fetch the content via xhr, else it grabs
		//the element's inner HTML of the specific ID, and shoves it into
		//the div.dialog's innerHTML.

		//Parameters
		// enabled: Boolean
		// width: Number
		// height: Number
		// href: (optional) String
		// id: (optional) String

		///TODO
		// add an icon param that loads the associated img src into ".dialog-component .dialog-component-title-icon" ?
		var params = requestObj.getParams();

		if(!params.elContainer) {
			params.elContainer = ".dialog-component";
		}

		if(!params.elContent) {
			params.elContent = ".dialog-component-content";
		}

		if(!params.elTitle) {
			params.elTitle = ".dialog-component-title";
		}
		if(!params.title) {
			params.title = "Default Dialog Text";
		}

		var flashElements = mojo.query("embed, object");

		//Find the Underlay
		var underlay = mojo.queryFirst("#underlay");

		if(!underlay) {
			underlay = document.createElement("div");
			underlay.id = "underlay";
			document.body.appendChild(underlay);
		}
		underlay.style.display = "block";

		var container = mojo.queryFirst(params.elContainer);
		if(!container) {

			//@Jaime Bueza: Forget the recovery, if the
			//developer forgets to add the basic template markup
			//for the dialog, then he should be warned. So, let's warn
			//him.


			throw new Error("stdlib.behavior.dialog.DialogBehavior - Unable to find the Dialog template");
			return;
		}

		var content = mojo.queryFirst(params.elContent, params.elContainer);
		var title = mojo.queryFirst(params.elTitle, params.elContainer);
				content.innerHTML = "";
		var thisObj = this;

		if (params.enabled && params.width && params.height) {
			container.style.width = params.width + "px";
			container.style.height = params.height + "px";
			container.style.display = "block";
			container.style.visibility = "hidden";
			if(!params.id) {
				dojo.xhrGet({
					url: params.href,
					load: function(data) {
						mojo.Model.set('mojo.dialog.content', data);
						thisObj._onDataReady(params);
					}
				});
			} else {
				var contentOnPage = mojo.queryFirst(params.id);
				mojo.Model.set('mojo.dialog.content', contentOnPage.innerHTML);
				thisObj._onDataReady(params);
			}

		}else{

			if(dojo.isFF && (navigator.appVersion.indexOf("Mac")!=-1)) {
				this.showFlash(flashElements);
			}

			underlay.style.display = 'none';
			container.style.display = 'none';

			if(dojo.isIE) {
				mojo.queryFirst("html").style.overflowX = "auto";
			} else {
				document.body.style.overflowX = "auto";
				content.innerHTML = "";
			}


		}
	},
	hideFlash: function(list) {
		for(var i = 0, len = list.length; i < len; i++) {
			list[i].style.display = "none";
		}
	},
	showFlash: function(list) {
		for(var i = 0, len = list.length; i < len; i++) {
			list[i].style.display = "block";
		}
	}
});
/*
	Class: EscapeKeyBehavior

	Provides functionality for intercepting the Escape (ESC) keystroke.

	Note:
		Perhaps this can be deprecated and we can have a generalized "KeyBehavior"
		in stdlib, where you pass in an array of keystrokes to intercept.
*/
dojo.provide("stdlib.behavior.dialog.EscapeKeyBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.dialog.EscapeKeyBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {
		var e = requestObj.eventObj;
		var characterCode;
		if(e && e.which){
			e = e
			characterCode = e.which;
		} else{
			e = event
			characterCode = e.keyCode;
		}
		if(characterCode == 27){
			this.onResponse();
			return false
		} else{
			return true
		}
	},
	onResponse: function() {
	}
});
/*
	Class: PositionBehavior

*/
dojo.provide("stdlib.behavior.dialog.PositionBehavior");
dojo.require("mojo.command.Behavior");
dojo.declare("stdlib.behavior.dialog.PositionBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {

		var params = requestObj.getParams();
		var underlay = mojo.queryFirst("#underlay");
		var container = mojo.queryFirst(".dialog-component");
		var content = mojo.queryFirst(".dialog-component .dialog-component-content");

		if(!container || !underlay || !content) {
			return;
		}

		var windowDimensions = {};
		var scrollPosition;
		// the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
		if (typeof window.innerWidth != 'undefined') {

		    windowDimensions.w = window.innerWidth;
		    windowDimensions.h = window.innerHeight;
			if(navigator.userAgent.indexOf("opera") == -1) {
				scrollPosition = window.pageYOffset + window.innerHeight;
			} else {
				scrollPosition = window.scrollY + window.innerHeight;
			}
		}
		// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
		else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0) {
			
		    windowDimensions.w = document.documentElement.clientWidth,
		    windowDimensions.h = document.documentElement.clientHeight;
			scrollPosition = /* (dojo.coords(mojo.queryFirst("body"), true)).h */ document.documentElement.scrollTop + document.documentElement.clientHeight;
		}else {


			windowDimensions.w = document.body.clientWidth;
			windowDimensions.h = document.body.clientHeight;
			scrollPosition = document.body.scrollTop + document.body.clientHeight;
		}

		
		//Remodulate the underlay dimensions.
		underlay.style.width = windowDimensions.w + "px";
		underlay.style.height = /* (dojo.coords(mojo.queryFirst("html"), true)).h */  scrollPosition + "px";


		//Remodulate the Dialog container dimensions.
		var containerCoords = dojo.coords(container, true);
		var contentCoords = dojo.coords(content, true);
		
		var centerY = Math.round(scrollPosition - (windowDimensions.h / 2)  - (containerCoords.h / 2));
		var centerX = Math.round((windowDimensions.w / 2) - (containerCoords.w / 2));
		
		container.style.top = centerY + "px";
		container.style.left = centerX + "px";

	}
});

/* 
	Class: stdlib.behavior.DisableBoxBehavior
	Author: Jaime Bueza
	
	Provides functionality to disable parts of the UI or the whole UI
	with a loading screen. Developers may specifiy the throbber className
	if they wish, but by default the generated throbber className will be
	"throbber". To define its presentation, do the following:
	
	Example:
		(start code)

		#disablebox {
			background: transparent  url("../../img/global/bg-loading-throbber.png") center center no-repeat;
			_background: transparent  url("../../img/global/bg-loading-throbber.gif") center center no-repeat; 
			_background: none;
			text-align: center;
		}
		#disablebox .throbber {
			position: absolute;
			background: url("../../img/global/icon-loading-throbber.gif");
			width: 16px;
			height: 16px;
		}
		
		(end)
	
	Parameters:
		target - {HTMLElement} The target element you wish to disable
		show - {Boolean} Shows the disablebox on/off
		throbberClass - {String} The specific className of the throbber.
		
*/
dojo.provide("stdlib.behavior.DisableBoxBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.DisableBoxBehavior", mojo.command.Behavior,
{
	_box: null,
	execute: function(requestObj) {
		var params = requestObj.getParams();
		if (!this._box) {
			this._box = mojo.queryFirst("#disablebox");
			if (!this._box) { //recovery + creation
				this._box = document.createElement("div");
				this._box.id = "disablebox";
				document.body.appendChild(this._box);
				this._box.style.position = "absolute";
			}
		}
		
		//Clean up
		this._box.innerHTML = "";

		if (requestObj.getParams().show) {
			var throbber = document.createElement("div");
			throbber.className = params.throbberClass || "throbber";

			if (requestObj.getParams().target) {
				var offset = dojo.coords(requestObj.getParams().target, true);
				this._box.style.top = offset.y + "px";
				this._box.style.left = offset.x + "px";
				this._box.style.width = offset.w + "px";
				this._box.style.height = offset.h + "px";
				
				//Shift up and left 8 px since the loader gif is 16x16.
				throbber.style.left = ((offset.w / 2) - 8) + "px";
				throbber.style.top = ((offset.h / 2)  - 8) + "px";
	
				this._box.appendChild(throbber);
				
				
			} else {
				this._box.style.top = "0px";
				this._box.style.left = "0px";
				this._box.style.width = "100%";
				this._box.style.height = (document.all) ? document.body.offsetHeight + "px" : "100%";
				
				throbber.style.left = ((offset.w / 2) - 8) + "px";
				throbber.style.top = ((offset.h / 2)  - 8) + "px";
				
				this._box.appendChild(throbber);
			}
			this._box.style.zIndex = "9999";
			this._box.style.display = "block";
		} else {
			this._box.style.display = "none";
		}
	}
});
/*
	Class: DragBehavior
*/
dojo.provide("stdlib.behavior.DragBehavior");
dojo.require("mojo.command.Behavior");
dojo.declare("stdlib.behavior.DragBehavior", mojo.command.Behavior,
{
	selectedIndex: 0,
	execute: function(requestObj) {
		var params = requestObj.getParams();
		var evt = requestObj.eventObj,
			el = params.element,
			elCoords = dojo.coords(el),
			draggable = params.draggable,
			container = params.container,
			containerCoords = dojo.coords(container),
			orientation = params.orientation,
			tickSize = params.tickSize,
			direction,
			dimension,
			prop,
			position;

		if (orientation == "vertical") {
			direction = "y";
			dimension = "h";
			prop = "top";
			if(typeof params.position != "undefined" && !isNaN(parseInt(params.position))) { //Are we specifically setting the position via onInit
				position = params.position + containerCoords[direction];;
			} else {
				position = evt.clientY;
			}


		} else {
			direction = "x";
			dimension = "w";
			prop = "left";
			//Horizontal
			if(typeof params.position != "undefined" && !isNaN(parseInt(params.position))) { //Are we specifically setting the position via onInit
				position = params.position + containerCoords[direction];;
			} else {
	 			position = evt.clientX;
			}
		}

		var maxDimension = containerCoords[direction] + containerCoords[dimension] - elCoords[dimension];

		if(position >= maxDimension) {
			el.style[prop] = (containerCoords[dimension] - elCoords[dimension] - 3) + "px"; //Offset of 3 pixels

		} else if (position <= containerCoords[direction] + 1){
			el.style[prop] = 0 + "px";

		} else {
			if(tickSize) {
				var relativePosition = (position - containerCoords[direction]);
				this.selectedIndex = Math.round(relativePosition / tickSize);
				el.style[prop] = this.selectedIndex * tickSize + "px";
			} else {
				el.style[prop] = (position - containerCoords[direction]) + "px";
			}

		}
	}

});
dojo.provide("stdlib.behavior.InsertHtmlBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.InsertHtmlBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {

		// element - DOM element to apply CSS action to
		// action - action to perform [before|after|append|prepend|replace|empty]
		// insertHtml - HTML string insert

		var elms = requestObj.getParams().element;
		var action = requestObj.getParams().action;
		var insertHtml = requestObj.getParams().insertHtml;

		if (elms && action) {
			if (!dojo.isArray(elms)) elms = [elms];

			elmsLength = elms.length;
			for (var i = 0; i < elmsLength; i++) {
				elm = elms[i];
				isIE = elm["insertAdjacentHTML"];
				var insertElement = insertHtml;
				if (!isIE && typeof insertHtml == "string") {
					if (insertHtml.length == 0) {
						action = "empty";
					} else {
						var range = elm.ownerDocument.createRange();
						range.setStartBefore(elm);
						insertElement = range.createContextualFragment(insertHtml);
					}
				}
				if (action.length > 0) {
					switch (action) {
						case "empty":
							elm.innerHTML = "";
							break;
						case "before":
							if (isIE) {
								elm.insertAdjacentHTML("beforeBegin", insertHtml);
							} else {
								elm.parentNode.insertBefore(insertElement, elm);
							}
							break;
						case "after":
							if (isIE) {
								elm.insertAdjacentHTML("afterEnd", insertHtml);
							} else {
								if (elm.nextSibling) {
									elm.parentNode.insertBefore(insertElement, elm.nextSibling);
								} else {
									elm.parentNode.appendChild(insertElement);
								}
							}
							break;
						case "prepend":
							if (isIE) {
								elm.insertAdjacentHTML("afterBegin", insertHtml);
							} else {
								elm.insertBefore(insertElement, elm.firstChild);
							}
							break;
						case "append":
							if (isIE) {
								elm.insertAdjacentHTML("beforeEnd", insertHtml);
							} else {
								elm.appendChild(insertElement);
							}
							break;
						case "replace":
							if (isIE) {
								elm.innerHTML = insertHtml;
							} else {
								elm.innerHTML = "";
								elm.appendChild(insertElement);
							}
							break;
					}
				}
			}
		}
	}
});
dojo.provide("stdlib.behavior.MessagingBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.MessagingBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {
		mojo.Messaging.publish(requestObj.paramsObj.topic, requestObj.paramsObj.message);
	}
});
dojo.provide("stdlib.behavior.PopulateDateBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.PopulateDateBehavior", mojo.command.Behavior,
{
	months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],

	execute: function(requestObj) {
		var params = requestObj.getParams(), //Request Object's parameters.
			chosenMonth = params.month, //Specified Month from Controller.
			chosenYear = params.year,	//Specified Year from Controller.
			minYear = parseInt(params.minYear,10), //Minimum value of the Year range.
			maxYear = parseInt(params.year,10) + 50; //Maximum value of the Year range.

		var selectYear 	= mojo.queryFirst("select.date-year", params.target);
		var selectMonth = mojo.queryFirst("select.date-month", params.target);

		//Blow away all markup.
		selectYear.innerHTML = "";
		selectMonth.innerHTML = "";

		//Generate Years
		for(var i = minYear; i < maxYear; i++) {
			var option = new Option(i.toString(), i);
			if(i == chosenYear) option.selected = true;
			selectYear.options.add(option);
		}

		//Generate months
		for(var i = 0, len = this.months.length; i < len; i++) {
			var monthName = this.months[i]
			var monthValue = (i <= 8) ? "0" + (i + 1) : i + 1;
			var option = new Option(monthName, monthValue);
			if(i == chosenMonth) option.selected = true;
			selectMonth.options.add(option);
		}
	}
});
dojo.provide("stdlib.behavior.PopulateDaysBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.PopulateDaysBehavior", mojo.command.Behavior,
{
	daysInMonth: function(iMonth, iYear) {
		return (new Date(iYear, iMonth, 0)).getDate();
	},
	execute: function(requestObj) {
		//target
		//default day || if null, then today will be selected
		//month
		//year

		var params = requestObj.getParams();
		if(!params.day) {
			params.day = (new Date()).getDate();
		}
		var selectDays 	= params.target;
		selectDays.innerHTML = "";
		var daysInMonth = this.daysInMonth(params.month, params.year);
		for(var i = 1; i <= daysInMonth; i++) {
			var dayValue = (i <= 9) ? "0" + (i) : i;

			var option = new Option(i, dayValue);
			if(i == params.day) option.selected = true;
			selectDays.options.add(option);
		}
	}
});
dojo.provide("stdlib.behavior.RedirectBehavior");
dojo.require("mojo.command.Behavior");
dojo.declare("stdlib.behavior.RedirectBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {
		//If you pass don't pass a URL, it can be assumed
		//that you intend to refresh the current page.
		var params 	= requestObj.getParams();
		var delay = 25;
		if (params) {
			var url    	= params.url; //Location of the redirect
			var removeHash 	= params.removeHash || false; //If removeHash doesn't exist, then it's false.
			var delay 	= params.delay || 25;	//25ms redirect delay by default
		}
		if (!url) {
			//We want to refresh the page.
			if (removeHash) {
				window.location = window.location.href.replace(/#.*/, "");
				setTimeout ("window.location.reload()", 750); //Safari hack to reload
			} else {
				window.location.reload();
			}
		} else {
			//We want to redirect the user to a specific URL.
			setTimeout(function() {
				window.location.href = url;
			}, delay);

		}
	}
});
dojo.provide("stdlib.behavior.SetHistoryBehavior");
dojo.require("mojo.command.Behavior");
dojo.require("mojo.History");

dojo.declare("stdlib.behavior.SetHistoryBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {
		if (requestObj.getParams()) {
			var clearHash; // if clearHash is true, everything after the hash is cleared
			var historyObj = mojo.History.getInstance();
			var params = requestObj.getParams();
			if (params) {
				if (typeof params.clearHash != "undefined") {
					if (params.clearHash) window.location.hash = "#";
				} else {
					var hash = historyObj._parseObj(params);
					mojo.History.getInstance().setHash(hash);
				}
			}
		}
	}
});
dojo.provide("stdlib.behavior.TweenBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.TweenBehavior", mojo.command.Behavior,
{
	onComplete:function() {},
	onStart:function() {},
	_effect: null,
	execute: function(requestObj) {
		// element
		// width, height, x, y

		// set properties of animation
		var props = {};
		var duration;
		if (requestObj.getParams().width != null) props.width = requestObj.getParams().width;
		if (requestObj.getParams().height != null) props.height = requestObj.getParams().height;
		if (dojo.isIE && props.height == 0) props.height = 1;
		if (requestObj.getParams().x != null) props.left = requestObj.getParams().x;
		if (requestObj.getParams().y != null) props.top = requestObj.getParams().y;
		
		if (requestObj.getParams().duration != null) {
			duration =  requestObj.getParams().duration;
		} else {
			duration = 600;
		}
		
		// normalize elements into array
		var elements = requestObj.getParams().element;
		if (!dojo.isArray(elements)) {
			elements = [elements];
		}
		var elementLength = elements.length;

		var thisObj = this;
		for (var i = 0; i < elementLength; i++) {
			if (elements[i]) {
				if (elements[i].style.height == "auto" && props.height != null) {
					elements[i].style.height = dojo.coords(elements[i]).h + "px";
				}
				var fx = new Fx.Styles(elements[i], {
					duration: duration,
					transition: Fx.Transitions.Expo.easeInOut,
					onStart: function() {
						thisObj.onStart();
						if (dojo.isIE && this.from.height == "1") this.element.style.display = "block";

					},
					onComplete: function() {
						if (this.to.height == "1")   this.element.style.display = "none";
						if ((this.from.height == "0")||(this.from.height == "1")) this.element.style.height = "auto";
						if (this.element.style.height == "auto" && this.to.height > 0 && dojo.coords(this.element).h == 0) this.element.style.height = this.to.height + "px";

						thisObj.onComplete();
					}
				});
				this._effect = fx;
				fx.start(props);
			}
		}
	}
});
dojo.provide("stdlib.behavior.UpdateCssClassBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.UpdateCssClassBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {

// element - DOM element to apply CSS action to
// action - action to perform [add|remove|set|toggle]
// cssClass - CSS Class to apply action to

		var elmLength;											// empty var which will be used to store the length of the array
		var elms = requestObj.paramsObj.element;				// gets the parameter "element" from the controller
		var action = requestObj.paramsObj.action;
		var cssClass = requestObj.paramsObj.cssClass;


		// ERROR CHECKING
		if (elms == null || typeof elms == 'undefined') {
			return;
		} else {
			if (typeof elms == 'object') {
				//check array to see that all items are objects
				if (elms.length > 0) {
					for (var i=0; i< elms.length; i++) {
						if (typeof elms[i] != 'object') {
							throw new Error('ERROR stdlib.behavior.UpdateCssClassBehavior - element parameter is not an array of type Object');
							break;
						}
					}
				}
			} else {
				throw new Error('ERROR stdlib.behavior.UpdateCssClassBehavior - element parameter is not a type Object');
			}
		}

		if (action == null || typeof action == 'undefined') {
			throw new Error('ERROR stdlib.behavior.UpdateCssClassBehavior - action parameter is required');
		} else {
			if (typeof action != 'string') {
				throw new Error('ERROR stdlib.behavior.UpdateCssClassBehavior - action parameter is not a type String');
			} else {
				if ((action != 'add') && (action != 'remove') && (action != 'set') && (action != 'toggle')) throw new Error('ERROR stdlib.behavior.UpdateCssClassBehavior - action parameter is invalid');
			}
		}

		if (cssClass == null || typeof cssClass == 'undefined') {
			throw new Error('ERROR stdlib.behavior.UpdateCssClassBehavior - CssClass parameter is required');
		} else {
			if (typeof cssClass == 'object') {
				//check array to see that all items are objects
				if (cssClass.length > 0) {
					for (var i=0; i< cssClass.length; i++) {
						if (typeof cssClass[i] != 'string') {
							throw new Error('ERROR stdlib.behavior.UpdateCssClassBehavior - CssClass parameter is not an array of type String');
							break;
						}
					}
				}
			} else {
				if (typeof cssClass != 'string') throw new Error('ERROR stdlib.behavior.UpdateCssClassBehavior - CssClass parameter is not a type String');
			}
		}



// checks to see that an element has been passed
		if (elms) {

// helper function. checks to see if the elms variable is an array.
			var isArray = function(srcObj) {
				if (!srcObj.constructor || srcObj.constructor.toString().toLowerCase().indexOf("array") == -1) return false;
				return true;
			};


// if elms is not an array, make it an array
			if (!isArray(elms)) elms = [elms];

// if cssClass is not an array, make it an array
			if (!isArray(cssClass)) cssClass = [cssClass];

// gets the length of the cssClass array for performance issues
			cssLength = cssClass.length;

// gets the length of the elms array for performance issues
			elmLength = elms.length;

// loops through the elements
			for (var i = 0; i < elmLength; i++) {
				elm = elms[i];
				// loops through the css classes
				for (var j = 0; j < cssLength; j++) {
					css = cssClass[j];
					// perform the CSS action
					if (action.length > 0){
						// just a nicer way of doing an If/Else
						switch(action) {
							case "add" :
								dojo.addClass(elm, css);
								break;
							case "remove" :
								dojo.removeClass(elm, css);
								break;
							case "set" :
								elm.className = "";
								dojo.addClass(elm, css);
								break;
							case "toggle" :
								dojo.toggleClass(elm, css);
								break;
						}
					}
				}
			}
		}
	},
	onResponse: function() {
	}
});
/* 
	Class: stdlib.behavior.UpdateFormFieldBehavior
	Author: Mojo Core Team
	
	Provides the ability to change input values based on the
	name= attribute and specifying a value.
	
	Example:
		(start code)
		//Controller addObservers() code.
		//When the controller maps, clear the username and email field values (they are text
		//boxes).
		this.addObserver(this, "onInit", "UpdateFormField", function(context, caller) {
			return {
				formId: "registration-form",
				fields: [ 
					{
						name: "username",
						value: ""
					},
					{
						name: "txt-email-address-over",
						value: ""	
					}
				]	
			};
		});
		(end)

*/
dojo.provide("stdlib.behavior.UpdateFormFieldBehavior");
dojo.require("mojo.command.Behavior");
dojo.declare("stdlib.behavior.UpdateFormFieldBehavior", mojo.command.Behavior, {
	execute: function(requestObj) {
		// this behavior will iterate thru a targeted form and assign "values" to
		// the appropriate form elements based on the element's "name"
		
		var formObj;
		var formChildren = new Array();
		var formArray = new Array();
		var formHTMLElements = ["INPUT", "SELECT", "TEXTAREA"]; // these are the valid form elements
		var params = requestObj.getParams();
		if (!params) params = {};
		var fields = params.fields; // 'fields' is an array of json objects that represent form input fields
		if (params.formId != null) formObj = mojo.queryFirst("#" + params.formId);
		if (params.formObj != null) formObj = params.formObj;

		if (formObj) {
			// getting the appropriate objects in the form
			for (var i = 0, iLen = formHTMLElements.length; i < iLen; i++) {
				var HTMLobj = mojo.query(formHTMLElements[i], formObj);
				for (var j = 0, jLen = HTMLobj.length; j < jLen; j++) {
					formChildren.push(HTMLobj[j]);
				}
			}

			// check fields and assign values
			for (var i = 0, iLen = fields.length; i < iLen; i++) {
				var objName = fields[i].name;
				var objValue = fields[i].value;
				for (var j = 0, jLen = formChildren.length; j < jLen; j++) {
					var fireOnChange = false;

					// fire onchange if values are different
//					if ((formChildren[j].tagName == "INPUT")&&(formChildren[j].value != objValue)) {
//						fireOnChange = true;
//					}

					if (formChildren[j].tagName == "SELECT") {
						if (formChildren[j].name == objName) {
							for (var k = 0, kLen = formChildren[j].options.length; k < kLen; k++) {
								var o = formChildren[j].options[k];
								if (o.value == objValue) formChildren[j].selectedIndex = k;
							}
						}
					} else if (formChildren[j].tagName == "TEXTAREA") {
						if (formChildren[j].name == objName) {
							if (formChildren[j].value == objValue) fireOnChange = true; //PC FF needs this
							if (formChildren[j].innerHTML == objValue) fireOnChange = true;
							formChildren[j].value = objValue; // PC FF needs this
							formChildren[j].innerHTML = objValue;
						}
					} else if (formChildren[j].tagName == "INPUT") {
						if (formChildren[j].name == objName) {
							if ((formChildren[j].type == "radio")||(formChildren[j].type == "checkbox")) {
								if (formChildren[j].value == objValue) {
									formChildren[j].checked = "checked";
								} else {
									formChildren[j].checked = "";
								}
							} else if ((formChildren[j].type == "text")||(formChildren[j].type == "password")||(formChildren[j].type == "hidden")) {
								if (formChildren[j].value != objValue) fireOnChange = true;
								formChildren[j].value = objValue;
							}
						}
					}

					if (fireOnChange) {
						//On IE
						if (formChildren[j].fireEvent) formChildren[j].fireEvent("onchange");

						//On Gecko based browsers
						if (document.createEvent) {
							var evt = document.createEvent("HTMLEvents");
							if(evt.initEvent) evt.initEvent("change", true, true);
							if(formChildren[j].dispatchEvent) formChildren[j].dispatchEvent(evt);
						}
					}

				}
			}


		}
	}
});
dojo.provide("stdlib.behavior.SubmitFormBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.SubmitFormBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {
		var params = requestObj.getParams();
		if (params && params.form) {
			if (params.form.tagName.toLowerCase() != "form") {
				params.form = mojo.queryFirst("form", params.form);
			}
			this.onResponse();
			params.form.submit();
		}
	},
	onResponse: function() {
		
	},
	onError: function() {
		
	}
});
dojo.provide("stdlib.behavior.EnterKeyBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.EnterKeyBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {
		var e = requestObj.eventObj;
		var characterCode;
		if(e && e.which){
			e = e
			characterCode = e.which;
		} else{
			e = event
			characterCode = e.keyCode;
		}
		if(characterCode == 13){
			this.onResponse();
			return false 
		} else{
			return true 
		}
	},
	onResponse: function() {
	}
});
dojo.provide("stdlib.behavior.RemoveElementsBehavior");

dojo.declare("stdlib.behavior.RemoveElementsBehavior", mojo.command.Behavior, {
	execute: function(requestObj) {

		var __className; // must be a string. cannot be an array of strings.
		var __targetId;  // must be a string. cannot be an array of strings.
		var __target;
		var __elements;
		var params = requestObj.paramsObj;
		if (params) {
			if (params.className != null ) __className = params.className;
			if (params.targetId != null ) __targetId = params.targetId;
			if (params.target != null) __target = params.target;
		}

		// Execution
		if ((__className != null) && (__targetId != null || __target != null)) {
			if (__targetId && !__target) {
				if (__targetId.indexOf("#") != 0) __targetId = "#" + __targetId;
				__target = mojo.queryFirst(__targetId);
			}
			__elements = mojo.query(__className, __target);
			if (__elements) {
				if (__elements.length > 0) {
					for (var i=0; i < __elements.length; i++) {
						if ((__elements[i])&&(__elements[i].parentNode)) __elements[i].parentNode.removeChild(__elements[i]);
					}
				} else {
					if ((__elements)&&(__elements.parentNode)) __elements.parentNode.removeChild(__elements);
				}
			}
		}
	}
});

dojo.provide("stdlib.command.AutoSuggest.GetSuggestionsCommand");
dojo.require("mojo.command.Command");
dojo.require("mojo.Model");

dojo.declare("stdlib.command.AutoSuggest.GetSuggestionsCommand", mojo.command.Command, {
	inputValue: null,
	_clearTimeout: null,
	_lastValue: null,
	execute: function(requestObj) {
		if (requestObj.getParams().inputValue != this.inputValue) {
			this.inputValue = requestObj.getParams().inputValue.replace(/\s*$/g, ""); // get rid of trailing spaces
			clearTimeout(this._clearTimeout);
			if (this.inputValue.length > 0) { // handle empty
				var thisObj = this;
				dojo.require(requestObj.getParams().serviceLocator);
				this._clearTimeout = setTimeout(function() {
					if (thisObj._lastValue != thisObj.inputValue) {
						thisObj._lastValue = thisObj.inputValue;
						var locator = eval(requestObj.getParams().serviceLocator);
						locator.getInstance().getService(requestObj.getParams().serviceName).invoke({inputValue: thisObj.inputValue}, thisObj);
					}
				}, 400);
			} else {
				mojo.Model.remove(requestObj.getParams().model);
			}
		}
	},
	onResponse: function(data) {
		mojo.Model.set(this.getRequest().getParams().model, data[this.getRequest().getParams().modelPath]);
	},
	onError: function(error) {
	}
});
dojo.provide("stdlib.command.ClearModelCommand");
dojo.require("mojo.Model");

dojo.declare("stdlib.command.ClearModelCommand", mojo.command.Command, {
	execute: function(requestObj) {
		var model = requestObj.paramsObj.model;

		// ERROR CHECKING
		if (model == null || typeof model == 'undefined') {
			throw new Error('ERROR stdlib.command.ClearModelCommand - model parameter is required');
		} else {
			if (typeof model == 'array' || typeof model == 'object') {
				//check array to see that all items are string
				if (model.length > 0) {
					for (var i=0; i<model.length; i++) {
						if (typeof model[i] != 'string') {
							throw new Error('ERROR stdlib.command.ClearModelCommand - model parameter is not an array of type String');
							break;
						}
					}
				}
			} else {
				if (typeof model == 'string') {
					if (model == "") throw new Error('ERROR stdlib.command.ClearModelCommand - model parameter must be a non-empty string');
				} else {
					throw new Error('ERROR stdlib.command.ClearModelCommand - model parameter is not a type String');
				}
			}
		}

		// EXECUTION
		if (model) {
			if (typeof(model) == "string") model = [model];

			if (dojo.isArray(model)) {
				for (i=0; i<model.length; i++) {
					mojo.Model.remove(model[i]);
				}
			}
		}
	}
});
dojo.provide("stdlib.command.InsertIntoModelCommand");
dojo.require("mojo.command.Command");
dojo.require("mojo.Model");

dojo.declare("stdlib.command.InsertIntoModelCommand", mojo.command.Command, {
	execute: function(requestObj) {
		//parameters {model:String, index:Number, value:Object}
		var __model;
		var __index;
		var __value;
		var __modelContents;
		var __error = false;
		var params = requestObj.getParams();
		if (!params) params = {};
		if (params.model != null) __model = params.model;
		if (params.index != null) __index = params.index;
		if (params.value != null) __value = params.value;


		// ERROR CHECKING
		if (__model == null || typeof __model == 'undefined') {
			throw new Error('ERROR stdlib.command.InsertIntoModelCommand - model parameter is required');
		} else {
			if (__model == '') throw new Error('ERROR stdlib.command.InsertIntoModelCommand - model parameter must be a non-empty string');
			if (typeof __model != 'string') {
				throw new Error('ERROR stdlib.command.InsertIntoModelCommand - model parameter must be type String');
			} else {
				if (!mojo.Model.contains(__model)) {
					throw new Error('ERROR stdlib.command.InsertIntoModelCommand - specified model does not exist');
				} else {
					__modelContents = mojo.Model.get(__model).length;
					if (typeof __modelContents != 'number') throw new Error('ERROR stdlib.command.InsertIntoModelCommand - specified model must be type Array');
				}
			}
		}

		if (__value == null || typeof __value == 'undefined') throw new Error('ERROR stdlib.command.InsertIntoModelCommand - value is not set');

		if (__index != null) {
			if (typeof __index != 'number') {
				throw new Error('ERROR stdlib.command.InsertIntoModelCommand - index parameter must be type Number');
			} else {
//				if (__index < 0) throw new Error('ERROR stdlib.command.InsertIntoModelCommand - index parameter cannot be less than zero');
			}
		}


		// ASSIGN ORDER
		var targetModel = mojo.Model.get(__model);
		if (targetModel.length != 0) {
			if (typeof __index == "undefined" || __index < 0 || __index >= targetModel.length) {
				var targetIndex = targetModel.length;
			} else {
				var targetIndex = __index;
			}
		} else {
			var targetIndex = 0;
		}


		// RE-ORDER ARRAY
		if (targetModel.length == 0) {
			mojo.Model.add(__model, __value);
		} else {
			if (targetIndex == targetModel.length - 1) {
				mojo.Model.add(__model, __value);
			} else {
				targetModel.splice(targetIndex,0, __value);
				mojo.Model.set(__model, targetModel);
			}
		}


	},
	onResponse: function(data) {
	},

	onError: function(error) {
	}
});
dojo.provide("stdlib.command.MapControllersCommand");
dojo.require("mojo.command.Command");

dojo.declare("stdlib.command.MapControllersCommand", mojo.command.Command, {
	execute: function(requestObj) {

		var contextObj = null;
		if(requestObj.getParams()) {

			// parameters: contextObj: String or HTMLElement
			contextObj = requestObj.getParams().contextObj;
		}

		mojo.controller.Map.mapControllers(contextObj);



	}
});
dojo.provide("stdlib.command.PaginationCommand");
dojo.require("mojo.command.Command");


// passing in pageSize, total, and pageIndex

dojo.declare("stdlib.command.PaginationCommand", mojo.command.Command,
{

    model: "paginationState",
	execute: function(requestObj) {
	    if (requestObj.getParams().model != null){
			this.model = requestObj.getParams().model;
		}
	    mojo.Model.remove(this.model);
		if (typeof requestObj.getParams().pageSize != "undefined" && typeof requestObj.getParams().total != "undefined") {
			if (requestObj.getParams().pageSize <= 0 || requestObj.getParams().total <= 0) {
				// reset all properties
				mojo.Model.set(this.model, {
					pageIndex: 0,
					pageSize: 0,
					total: 0,
					from: 0,
					to: 0,
					pageNext: -1,
					pagePrev: -1,
					pageTotal: 0,
					pages: []
				});
			} else {
				var pageState = {};
				pageState.pageSize = requestObj.getParams().pageSize;
				pageState.total = requestObj.getParams().total;
				pageState.pageIndex = 0;
				if (requestObj.getParams().pageIndex && requestObj.getParams().pageIndex > 0) {
					pageState.pageIndex = requestObj.getParams().pageIndex;
				}
				pageState.pageTotal = Math.ceil(pageState.total / pageState.pageSize);
				if (pageState.pageIndex > pageState.pageTotal) {
					return;
				}
				pageState.from = (pageState.pageSize * pageState.pageIndex) + 1;
				pageState.to = pageState.pageSize * (pageState.pageIndex + 1);
				if (pageState.to > pageState.total) {
					pageState.to = pageState.total;
				}
				pageState.pageNext = ((pageState.pageIndex + 1) >= pageState.pageTotal) ? -1 : (pageState.pageIndex + 1);
				pageState.pagePrev = (pageState.pageIndex == 0) ? -1 : (pageState.pageIndex - 1);
				pageState.showPages = 8;
				if (requestObj.getParams().showPages && requestObj.getParams().showPages > 0) {
					pageState.showPages = requestObj.getParams().showPages;
				}
				var shift = Math.ceil(pageState.showPages/2);
				var start = 0;
				if ((pageState.pageIndex - shift) > 0) {
					start = pageState.pageIndex - shift;
					if (start > 0 && (pageState.pageTotal - pageState.pageIndex) < shift) {
						start = start - (shift - (pageState.pageTotal - pageState.pageIndex));
						if (start <= 0) {
							start = 0;
						}
					}
				}
				pageState.pages = [];
				for (var i = start; i < (start+pageState.showPages); i++) {
					if (i < pageState.pageTotal) {
						pageState.pages.push(i+1);
					}
				}
				mojo.Model.set(this.model, pageState);
			}
		}
	}
});
dojo.provide("stdlib.command.RemoveFromModelCommand");
dojo.require("mojo.command.Command");
dojo.require("mojo.Model");

dojo.declare("stdlib.command.RemoveFromModelCommand", mojo.command.Command,
{
	execute: function(requestObj) {
		//parameters {model:String, index:Number, key:String, value:Object, firstOnly:Boolean}
		var __model;
		var __index;
		var __key;
		var __value;
		var __first = true;
		var __modelContents;
		var __error = false;
		var spliced = false;
		var params = requestObj.getParams();
		if (!params) params = {};
		if (params.model != null) __model = params.model;
		if (params.index != null) __index = params.index;
		if (params.value != null) __value = params.value;
		if (params.key != null)   __key   = params.key;
		if (params.firstOnly != null) __first = params.firstOnly;


		// ERROR CHECKING
		if (__model == null || typeof __model == 'undefined') {
			throw new Error('ERROR stdlib.command.RemoveFromModelCommand - model parameter is required');
		} else {
			if (__model == '') {
				throw new Error('ERROR stdlib.command.RemoveFromModelCommand - model parameter must be a non-empty string');
			} else {
				if (typeof __model != 'string') {
					throw new Error('ERROR stdlib.command.RemoveFromModelCommand - model parameter must be type String');
				} else {
					if (!mojo.Model.contains(__model)) {
						throw new Error('ERROR stdlib.command.RemoveFromModelCommand - specified model does not exist');
					} else {
						__modelContents = mojo.Model.get(__model).length;
						if (typeof __modelContents != 'number') throw new Error('ERROR stdlib.command.RemoveFromModelCommand - specified model must be type Array');
					}
				}
			}
		}

		if (__index == null || typeof __index == 'undefined') {
			if ((__key == null || typeof __key != 'string' || __key == '')||(__value == null || typeof __value == 'undefined' || __value == '')) {
				if (__key == null || typeof __key == 'undefined') {
					throw new Error('ERROR stdlib.command.RemoveFromModelCommand - either [index] parameter or [key and value] parameters are required');
				} else {
					if (__key == '') {
						throw new Error('ERROR stdlib.command.RemoveFromModelCommand - key parameter must be a non-empty string');
					} else {
						if (typeof __key != 'string') {
							throw new Error('ERROR stdlib.command.RemoveFromModelCommand - key parameter must be type String');
						} else {
							if (__value == null || typeof __value == 'undefined') throw new Error('ERROR stdlib.command.RemoveFromModelCommand - either [index] parameter or [key and value] parameters are required');
						}
					}
				}
			}
		} else {
			if ((__key != null) && (typeof __key != 'undefined') && (__key == '')) throw new Error('ERROR stdlib.command.RemoveFromModelCommand - key parameter must be a non-empty string');
			if (typeof __index != 'number') {
				throw new Error('ERROR stdlib.command.RemoveFromModelCommand - index parameter must be type Number');
			} else {
				if (__index < 0) {
					throw new Error('ERROR stdlib.command.RemoveFromModelCommand - index parameter cannot be less than zero');
				} else {
					if (mojo.Model.contains(__model)) {
						if (__index >= mojo.Model.get(__model).length) throw new Error('ERROR stdlib.command.RemoveFromModelCommand - index parameter is out of bounds');
					}
				}
			}
		}


		// RE-ORDER ARRAY
		//assume model, key, value and index is correct
		var targetModel = mojo.Model.get(__model);
		if ((__key != null) && (typeof __key != 'undefined') && (__key != '') && (__value != null) && (typeof __value != 'undefined') && (__value != '')) {
			if (__first) {
				//search for the first key/value combo and then delete
				for (i=0; i<targetModel.length; i++) {
					if (typeof targetModel[i][__key] != 'undefined') {
						if (targetModel[i][__key] == __value) {
							targetModel.splice(i,1);
							mojo.Model.set(__model, targetModel);
							break;
						}
					}
				}
			} else {
				//search and delete all key/value combinations
				for (i=targetModel.length-1; i>=0; i--) {
					if (typeof targetModel[i][__key] != 'undefined') {
						if (targetModel[i][__key] == __value) {
							targetModel.splice(i,1);
							spliced = true;
						}
					}
				}
				if (spliced) mojo.Model.set(__model, targetModel);
			}
		} else {
			if ((__index != null) && (typeof __index != 'undefined') && (typeof __index == 'number')) {
				//remove targeted index
				targetModel.splice(__index,1);
				mojo.Model.set(__model, targetModel);
			}
		}


	},
	onResponse: function(data) {
	},

	onError: function(error) {
	}
});
dojo.provide("stdlib.command.SetModelCommand");
dojo.require("mojo.command.Command");
dojo.require("mojo.Model");

dojo.declare("stdlib.command.SetModelCommand", mojo.command.Command, {
	execute: function(requestObj) {
		var __model = requestObj.paramsObj.model;
		var __set = requestObj.paramsObj.set;

		// ERROR CHECKING
		if (__model == null || typeof __model == 'undefined') {
			throw new Error('ERROR stdlib.command.SetModelCommand - model parameter is required');
		} else {
			if (typeof __model == 'string') {
				if (__model == '') throw new Error('ERROR stdlib.command.SetModelCommand - model parameter must be a non-empty string');
			} else {
				throw new Error('ERROR stdlib.command.SetModelCommand - model parameter must be type String');
			}
		}

		if (!__set) __set = mojo.Model.get(__model); //reset by default

		mojo.Model.set(__model, __set);
		requestObj.paramsObj.set = null;
	}
});
dojo.provide("stdlib.command.UpdateControllerParamCommand");
dojo.require("mojo.command.Command");

dojo.declare("stdlib.command.UpdateControllerParamCommand", mojo.command.Command, {
	execute: function(requestObj) {
		var __elm;
		var __control;
		var __parameter;
		var __value;

		var params = requestObj.getParams();
		if (params) {
			if (params.element != null) __elm = params.element;
			if (params.control != null) __control = params.control;
			if (params.params != null) __parameter = params.params;
			if (params.value != null) __value = params.value;
		}

		try {
			if ((__control!=null)&&(__parameter!=null)&&(__value!=null)) {
				if (__elm) {
					__elm.mojoControllers[__control].setValue(__parameter, __value);
				} else {
					requestObj.getController().getContextController(__control).setValue(__parameter, __value);
				}
			}
		} catch(err) {}


	},

	onResponse: function() {
	},

	onError: function() {
	}
});
dojo.provide("stdlib.command.UpdateObserversCommand");
dojo.require("mojo.controller.Controller");
dojo.require("mojo.command.Command");

dojo.declare("stdlib.command.UpdateObserversCommand", mojo.command.Command, {
	execute: function(requestObj) {
		var timeout = setTimeout(function() {
			mojo.controller.Controller.updateObservers(requestObj.getParams().controllerName);
			clearTimeout(timeout);
		}, 20);


	}
});
dojo.provide("stdlib.command.ValidateRulesCommand");
dojo.require("mojo.command.Command");
dojo.require("mojo.helper.Validation");
dojo.require("mojo.helper.view.Error");
dojo.require("mojo.query");

dojo.declare("stdlib.command.ValidateRulesCommand", mojo.command.Command, {
	_targetElement: null, // error messages will appear INSIDE the target (container) element
	_checkAll: true,
	_output: function(errorList, targetElement) {
		
	},
	execute: function(requestObj) {

		var rules;
		var formSet;
		var params = requestObj.getParams();
		if (params) {
			if (params.targetElement != null) this._targetElement = params.targetElement;
			if (params.checkAll != null) this._checkAll = params.checkAll;
			if (params.rules != null) rules = params.rules;
			if (params.formSet != null) formSet = params.formSet;
		}

		if (rules) {
			if (this._targetElement != null) {
				this._targetElement.innerHTML = "";
				if (formSet) {
					var clearTags = ["label","inputs","textarea","select"];
					for (var i = 0; i < clearTags.length; i++) {
						var Tag = mojo.query(clearTags[i], formSet);
						for (var j = 0; j < Tag.length; j++) {
							dojo.removeClass(Tag[j], "error");
						}
					}
				}
			}
			if (typeof(rules) == "string") {
				dojo.require(rules);
				eval("requestObj.getParams().rules = " + rules);
			}
			var val = mojo.helper.Validation.getInstance();
			if ((formSet)&&(this._checkAll)) {
				var errorList = val.execute(requestObj.getParams().rules, formSet);
			} else {
				var errorList = val.execute(requestObj.getParams().rules, [requestObj.callerObj]);

			}
			if (errorList.length > 0) {
				if (this._targetElement != null) {
					mojo.helper.view.Error.showElementErrors(errorList, this._targetElement);
					for (var i=0; i<errorList.length; i++) {
						dojo.addClass(errorList[i].element, "error");
						if (errorList[i].element.parentNode.tagName == "LABEL") dojo.addClass(errorList[i].element.parentNode, "error");
					}
				} else {
				//	mojo.helper.view.Error.showElementErrors(errorList)
					for (var i = 0, len = errorList.length; i < len; i++) {
						var error = errorList[i];
						var err = document.createElement("span");
						err.className = "mojoValidationError";
						err.innerHTML = error.message;

						if(error.element.type == "checkbox") {
							if(error.element.parentNode.tagName == "LABEL") {
								dojo.place(err, error.element.parentNode, 'after');
							} else {
								dojo.place(err, error.element, 'after');
							}
						} else {
							dojo.place(err, error.element, 'after');
						}

						
					}
				}
				this.onError();
			} else if (requestObj.invocation) {
				this.onResponse();
				requestObj.invocation.proceed();
			}
		} else {
			console.debug("ERROR stdlib.command.ValidateRulesCommand - No rules passed");
		}
	},
	onResponse: function() {
	},
	onError: function() {
	}
});
dojo.provide("stdlib.controller.AccordionController");
dojo.require("mojo.controller.Controller");

dojo.declare("stdlib.controller.AccordionController", mojo.controller.Controller,
{
	params: {
		selectedIndex: {
			required: false,
			defaultValue: 0,
			type: Number
		},
		activeOn: {
			required: false,
			defaultValue: "onclick"
		},
		toggleClose: {
			required: false,
			defaultValue: false
		},
		direction: {
			required: false,
			defaultValue: "vertical"
		}
	},
	addObservers: function() {
		var accordionPanels = mojo.query("> .accordion-panel", this.getContextElement());
		var accordions = mojo.query("> .accordion-panel > .accordion", this.getContextElement());
		var accordionContents = mojo.query("> .accordion-panel > .accordion-content", this.getContextElement());

		this.addObserver("> .accordion-panel > .accordion", this.getValue("activeOn"), "UpdateClass", function(context, caller) {
			var tabs = accordions;
			var index = 0;
			for (var i = 0; i < tabs.length; i++) {
				if (tabs[i] == caller) {
					index = i;
					break;
				}
			}
			if (this.getController().getValue("toggleClose") && index == this.getController().getValue("selectedIndex")) {
				this.getController().setValue("selectedIndex", -1);
			} else {
				this.getController().setValue("selectedIndex", index);
			}
		});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "Tween", function(context, caller, controller) {
			return {
			height: (controller.getValue("direction") == "vertical") ? 0 : null,
			width: (controller.getValue("direction") == "horizontal") ? 0 : null,
			element: mojo.query("> .open > .accordion-content", context)
		}});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller) { return {
			element: accordionPanels,
			action: "remove",
			cssClass: "open"
		}});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller) { return {
			element: accordionPanels[caller.getValue()],
			action: "add",
			cssClass: "open"
		}});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "Tween", function(context, caller, controller) {
			var elm = accordionContents[caller.getValue()];
			if (!elm) return;
			return {
			element: elm,
			height: (controller.getValue("direction") == "vertical") ? elm.scrollHeight : null,
			width: (controller.getValue("direction") == "horizontal") ? elm.scrollWidth : null
		}});
	},
	addCommands: function() {
		this.addCommand("UpdateClass", "stdlib.behavior.UpdateCssClassBehavior");
		this.addCommand("Tween", "stdlib.behavior.TweenBehavior");
	},
	addIntercepts: function() {

	}
});
dojo.provide("stdlib.controller.AutoSuggestController");
dojo.require("mojo.controller.Controller");

dojo.declare("stdlib.controller.AutoSuggestController", mojo.controller.Controller,
{
	params: {
		model: {
			required: false,
			defaultValue: "suggestions"
		},
		modelPath: {
			required: false,
			defaultValue: "suggestions"
		},
		serviceLocator: {
			required: true,
			defaultValue: "sample.service.Locator"
		},
		serviceName: {
			required: false,
			defaultValue: "getSuggestions"
		},
		inputName: {
			required: false,
			defaultValue: "suggest-input"
		}
	},
	addObservers: function() {
		this.addObserver("input.suggest-input", "onkeyup", "GetSuggestions", function(context, caller) { return {
			inputValue: caller.value,
			model: this.getController().getValue("model"),
			modelPath: this.getController().getValue("modelPath"),
			serviceLocator: this.getController().getValue("serviceLocator"),
			serviceName: this.getController().getValue("serviceName")
		};});
		this.addObserver("input.suggest-input", "onkeydown", "SuggestNavigation", function(context, caller) { return {
			suggestions: mojo.query(".suggestion", context)
		};});
		this.addObserver(this.getCommand("SuggestNavigation"), "onNav", "UpdateClass", function(context, caller) { return {
			element: mojo.query(".suggestion", context),
			action: "remove",
			cssClass: "selected"
		};});
		this.addObserver(this.getCommand("SuggestNavigation"), "onNav", "UpdateClass", function(context, caller) { return {
			element: caller.suggestion,
			action: "add",
			cssClass: "selected"
		};});
		this.addObserver(this.getCommand("SuggestNavigation"), "onNav", "UpdateForm", function(context, caller) {
			return {
				formObj: context,
				fields: [{
					name: this.getController().getValue("inputName"),
					value: (caller.suggestion.innerHTML.split("\n")[0] || caller.suggestion.innerHTML.split("\n")[1]).replace(/\s*\<[^\>]+\>\s*/g, "")
				}]
			};
		});
		this.addObserver(".suggestion", "onmouseover", "UpdateForm", function(context, caller) { return {
			formObj: context,
			fields: [{
				name: this.getController().getValue("inputName"),
				value: (caller.innerHTML.split("\n")[0] || caller.innerHTML.split("\n")[1]).replace(/\s*\<[^\>]+\>\s*/g, "")
			}]
		};});
		this.addObserver(".suggestion", "onmouseover", "UpdateClass", function(context, caller) { return {
			element: caller,
			action: "add",
			cssClass: "selected"
		};});
		this.addObserver(".suggestion", "onmouseout", "UpdateClass", function(context, caller) { return {
			element: caller,
			action: "remove",
			cssClass: "selected"
		};});
		this.addObserver("input.suggest-input", "onblur", "ClearModel", function(context, caller) { return {
			model: this.getController().getValue("model")
		};});
	},
	addCommands: function() {
		this.addCommand("SuggestNavigation", "stdlib.behavior.AutoSuggest.SuggestNavigationBehavior");
		this.addCommand("UpdateClass", 	"stdlib.behavior.UpdateCssClassBehavior");
		this.addCommand("GetSuggestions", "stdlib.command.AutoSuggest.GetSuggestionsCommand");
		this.addCommand("ClearModel", "stdlib.command.ClearModelCommand");
		this.addCommand("UpdateForm", "stdlib.behavior.UpdateFormFieldBehavior");
	},
	addIntercepts: function() {

	}
});
dojo.provide("stdlib.controller.DateController");
dojo.require("mojo.controller.Controller");

dojo.declare("stdlib.controller.DateController", mojo.controller.Controller,
{
	params: {
		date:		{ defaultValue: new Date() },
		minYear:	{ defaultValue: "1920" }
	},
	addObservers: function() {
		//Upon starting up this controller, set the date to what was specified in the sitemap.
		this.addObserver(this, "onInit", "PopulateDate", function(context, caller) {
			//Retrieve the controller instances' date obj
			//This date obj can be current date if you did not specify a value from the SiteMap
			if (this.getController().getValue("minYear") == "today") {
				var minYear = new Date();
				this.getController().setValue("minYear", minYear.getFullYear());
			}
			return {
				target: this.getContextElement(),
				month: this.getController().getValue("date").getMonth(),
				year: this.getController().getValue("date").getFullYear(),
				minYear: this.getController().getValue("minYear")
			}
		});
		this.addObserver(this.getCommand("PopulateDate"), "execute", "PopulateDays", function(context, caller) {
			if (this.getController().getValue("minYear") == "today") {
				var minYear = new Date();
				this.getController().setValue("minYear", minYear.getFullYear());
			}
			return {
				target: mojo.queryFirst("> .date-day", context),
				day: (new Date()).getDate(),
				month: mojo.queryFirst("> .date-month", context).value,
				year: mojo.queryFirst("> .date-year", context).value,
				minYear: this.getController().getValue("minYear")
			}
		});

		this.addObserver("> .date-month", "onchange", "PopulateDays", function(context, caller) {
			return {
				target: mojo.queryFirst("> .date-day", context),
				month: mojo.queryFirst("> .date-month", context).value,
				year: mojo.queryFirst("> .date-year", context).value
			}
		});
		this.addObserver("> .date-year", "onchange", "PopulateDays", function(context, caller) {
			return {
				target: mojo.queryFirst("> .date-day", context),
				month: mojo.queryFirst("> .date-month", context).value,
				year: mojo.queryFirst("> .date-year", context).value
			}
		});
		this.addObserver(this.getConfig("params").date, "onChange", "PopulateDate", function(context, caller) {
			if (this.getController().getValue("minYear") == "today") {
				var minYear = new Date();
				this.getController().setValue("minYear", minYear.getFullYear());
			}
			return {
				target: this.getContextElement(),
				month: this.getController().getValue("date").getMonth(),
				year: this.getController().getValue("date").getFullYear(),
				minYear: this.getController().getValue("minYear")
			}
		});

	},
	addCommands: function() {
		this.addCommand("PopulateDate", "stdlib.behavior.PopulateDateBehavior");
		this.addCommand("PopulateDays", "stdlib.behavior.PopulateDaysBehavior");
	},
	addIntercepts: function() {

	}
});
/*
	Class: stdlib.controller.DialogController
	Author: Jaime Bueza

	The Mojo Dialog Controller can be accessed by publishing messages with a topic called "dialog".

	In order to use this, you can simply use:

	(start code)
	mojo.Messaging.publish("dialog", { enabled: true, href: "/my-url-to-a-file.jsp", width: 500, height: 250 });
	(end)

	If you pass "url" (String), the Dialog Controller will fetch the html content and inject it into
	<div class="dialog">, which is automatically generated if it is not in the DOM.

	If you pass "id" (String), the Dialog Controller will fetch the innerHTML of the specific DOM Element
	by ID and inject the innerHTML into <div class="dialog">.

	In its entirety, you can render Dialogs internally (already in the DOM), or externally (on the fly in
	a remote location).

	There are two main behaviours which dictate the functionality of the Dialog.
		- DialogBehavior
			This behavior is responsible for rendering the dialog and fetching the markup, whether
			the content is external (remotely fetched via XHR) or internal (fetched via already on the DOM).

		- PositionBehavior
			This behavior is responsible for recalculating the dimensions of the Dialog based on content,
			and repositioning the Dialog to the center of the screen based on the dimensions of its content.

	Assumptions:
		- There can only be 1 dialog open at a time.

	Notes:
		- Perhaps we can pass a parameter to the Position behaviour to allow transitions (fading in, sliding, etc)?

*/
dojo.provide("stdlib.controller.DialogController");
dojo.require("mojo.controller.Controller");
dojo.declare("stdlib.controller.DialogController", mojo.controller.Controller,
{
	params: {
		/*
			Parameter: container {String}
				Override this parameter when you're extending the Dialog Controller.
		*/
		container: {
			required: false,
			defaultValue: ".dialog-component",
			type: String
		},
		/*
			Parameter: title {String}
				Override this parameter when you're extending the Dialog Controller.
		*/
		title: {
			required: false,
			defaultValue: ".dialog-component .dialog-component-title",
			type: String
		},
		titleText: {
			required: false,
			defaultValue: "Hello World",
			type: String
		},
		content: {
			required: false,
			defaultValue: ".dialog-component .dialog-component-content",
			type: String
		},
		width: {
			defaultValue: 0,
			type: Number
		},
		height: {
			defaultValue: 0,
			type: Number
		}
	},
	addObservers: function() {
		var content = this.getValue("content"),
			title = this.getValue("title"),
			container = this.getValue("container"),
			titleText = this.getValue("titleText");

		//Trigger for initializing a Mojo Dialog.
		this.addObserver(mojo.Messaging.getTopic("dialog"), "onPublish", "Dialog", function(context, caller) {

			var msgObj = caller.getMessage();
			msgObj.elContainer = container;
			msgObj.elContent = content;
			msgObj.elTitle = title;
			if(!msgObj.title) {
				msgObj.title = titleText;
			}

			this.getController().setValue("width", msgObj.width);
			this.getController().setValue("height", msgObj.height);

			//set msgObj into a model
			mojo.Model.set("stlib.dialog.params", msgObj);
			return msgObj;
		});

		//Re-update observers once the Dialog has instantiated itself.
		this.addObserver(this.getCommand("Dialog"), "onComplete", "MapControllers", function() {
			return {
				contextObj:  mojo.queryFirst(this.getController().getValue("container"))
			}
		});

		this.addObserver(this.getCommand("Dialog"), "onComplete", "UpdateObservers", function(context, caller) {
			return {
				controllerName: this.getController().declaredClass
			};
		});

		//Accessibility feature of allowing the user to keypress "ESC" on their keyboard to close the dialog.
		this.addObserver(window, "onkeyup", "EscapeKey"); //TODO: keyCode vs charCode in IE--IE won't register ESC properly.
		this.addObserver(this.getCommand("EscapeKey"), "onResponse", "Dialog", function(context, caller) {
			return {
				enabled: false
			};
		});

		//Repositioning based on User Behaviour (if they resize, scroll, etc)
		this.addObserver(this.getCommand("Dialog"), "onDataReady", "Position");
		this.addObserver(window, "onresize", "Position");
		this.addObserver(window, "onscroll", "Position");

		//Basic functionality
		//mojo.queryFirst(
		this.addObserver(".btn-close", "onclick", "Messaging", function(context, caller) {
			//Allows a user to close the dialog.
			return {
				topic: "dialog",
				message: {
					enabled: false
				}
			};
		});

	},
	addCommands: function() {
		this.addCommand("ClearModel",				"stdlib.command.ClearModelCommand");
		this.addCommand("Messaging",				"stdlib.behavior.MessagingBehavior");
		this.addCommand("Dialog", 					"stdlib.behavior.dialog.DialogBehavior");
		this.addCommand("Position", 				"stdlib.behavior.dialog.PositionBehavior");
		this.addCommand("EscapeKey", 				"stdlib.behavior.dialog.EscapeKeyBehavior");
		this.addCommand("MapControllers", 			"stdlib.command.MapControllersCommand");
		this.addCommand("UpdateObservers", 			"stdlib.command.UpdateObserversCommand");
	},
	addIntercepts: function() {

	}
});
dojo.provide("stdlib.controller.FilmStripController");
dojo.require("mojo.controller.Controller");

dojo.declare("stdlib.controller.FilmStripController", mojo.controller.Controller, 
{
	params: {
		selectedIndex: {
			required: false,
			defaultValue: 0,
			type: Number
		},
		loop: {
			required: false,
			defaultValue: false,
			type: Boolean
		}
	},
	addObservers: function() {
		var pages = function(context) {
			return mojo.query("> .filmstrip-viewer > .filmstrip-content > .filmstrip-page", context);
		};
		this.addObserver("> .filmstrip-next", "onclick", "UpdateClass", function(context, caller) { 
			var tabs = pages(context);
			var index = this.getController().getValue("selectedIndex");
			index++;
			if (index >= pages(context).length) {
				if (this.getController().getValue("loop")) {
					this.getController().setValue("selectedIndex", 0);
				}
			} else {
				this.getController().setValue("selectedIndex", index);
			}
		});
		this.addObserver("> .filmstrip-prev", "onclick", "UpdateClass", function(context, caller) { 
			var tabs = pages(context);
			var index = this.getController().getValue("selectedIndex");
			index--;
			if (index < 0) {
				if (this.getController().getValue("loop")) {
					this.getController().setValue("selectedIndex", pages(context).length-1);
				}
			} else {
				this.getController().setValue("selectedIndex", index);
			}
		});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller, controller) {
			return {
				element: mojo.query("> .filmstrip-next", context),
				action: (caller.getValue() >= pages(context).length-1) ? "add" : "remove",
				cssClass: "disabled"
			}
		});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller, controller) {
			return {
				element: mojo.query("> .filmstrip-prev", context),
				action: (caller.getValue() <= 0) ? "add" : "remove",
				cssClass: "disabled"
			}
		});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller) {
			return {
				element: pages(context),
				action: "remove",
				cssClass: "selected"
			}
		});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller) {
			return {
				element: pages(context)[caller.getValue()],
				action: "add",
				cssClass: "selected"
			}
		});
		this.addObserver('> .filmstrip-pagi > li > a', 'onclick', 'UpdateClass', function(context, caller, controller){
			var elIndex = this.getController().getValue('selectedIndex');
			var anchors = dojo.query('> .filmstrip-pagi > li > a', context);

			anchors.forEach(function(el, i){
				if(el != caller){
					dojo.removeClass(el, 'in');
				}else{
					dojo.addClass(el, 'in');
					elIndex = i;
				}
			});

			this.getController().setValue('selectedIndex', elIndex);
		});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "Tween", function(context, caller, controller) {			
			var elIndex = caller.getValue('selectedIndex');
			var anchors = dojo.query('> .filmstrip-pagi > li > a', context);

			anchors.forEach(function(el, i){
				if(elIndex != i){
					dojo.removeClass(el, 'in');
				}else{
					dojo.addClass(el, 'in');
				}
			});

			return {
				x: (-1*pages(context)[caller.getValue()].offsetLeft),
				y: (-1*pages(context)[caller.getValue()].offsetTop),
				element: mojo.query("> .filmstrip-viewer > .filmstrip-content", context),
				duration: 600
			}
		});
	},
	addCommands: function() {
		this.addCommand("UpdateClass", "stdlib.behavior.UpdateCssClassBehavior");
		this.addCommand("Tween", "stdlib.behavior.TweenBehavior");
	},
	addIntercepts: function() {

	}
});
dojo.provide("stdlib.controller.FormController");
dojo.require("mojo.controller.Controller");
dojo.declare("stdlib.controller.FormController", mojo.controller.Controller,
{
	params: {
		isSubmitted: {
			required: false,
			defaultValue: false,
			type: Boolean
		},
		formSubmitCommand: {
			required: true,
			defaultValue: "FormSubmitCommand",
			type: String
		},
		formRules: {
			required: true,
			defaultValue: "stdlib.rules.Rules",
			type: String
		},
		modelErrors: {
			required: true,
			defaultValue: "stdlib.myModel",
			type: String
		},
		formId: {
			required: true,
			defaultValue: "#form",
			type: String
		},
		submitButtonId: {
			required: true,
			defaultValue: "#submit-form",
			type: String
		},
		cancelButtonId: {
			required: true,
			defaultValue: "#cancel-form",
			type: String
		}
	},
	addObservers: function() {
		//Parameters
		var rules = this.getValue("formRules"),
			errorsModel = this.getValue("modelErrors"),
			formId = this.getValue("formId");


		//Tooltips
		this.addObserver("span.info", "onmouseover", "ToolTip", function() { return { show: true }});
		this.addObserver("span.info", "onmouseout", "ToolTip", function() { return { show: false }});

		//Handles all "Enter" key submits.
		this.addObserver("input", "onkeydown", "EnterKey");

		//Handles onblur validation only if the user has clicked "submit", but has errors in it.
		this.addObserver("input", "onblur", "ValidateRules", function(context, caller) {
			if(!this.getController().getValue("isSubmitted")) return { rules: {}, formSet: mojo.query(formId)};
			return {
				rules: rules,
				formSet: mojo.query(formId)
			}
		});
		this.addObserver("textarea", "onblur", "ValidateRules", function(context, caller) {
			if(!this.getController().getValue("isSubmitted")) return { rules: {}, formSet: mojo.query(formId)};
			return {
				rules: rules,
				formSet: mojo.query(formId)
			}
		});
		this.addObserver("select", "onchange", "ValidateRules", function(context, caller) {
			if(!this.getController().getValue("isSubmitted")) return { rules: {}, formSet: mojo.query(formId)};
			return {
				rules: rules,
				formSet: mojo.query(formId)
			}
		});

		//Handles form submission.
		this.addObserver(this.getCommand(this.getValue("formSubmitCommand")), "onError", "DisableBox", function(context, caller) {
			return {
				target: context, show: false
			}
		});
		this.addObserver(this.getCommand(this.getValue("formSubmitCommand")), "onResponse", "ClearModel", function() {
			return {
				model: errorsModel
			}
		});
		this.addObserver(this.getCommand(this.getValue("formSubmitCommand")), "onResponse", "DisableBox", function(context, caller) {
			return {
				target: context, show: false
			}
		});

		//Add an observer to the onclick of Submit to update the Controller's parameters for isSubmitted = true.
		this.addObserver(this.getValue("submitButtonId"), "onclick", "UpdateControllerParam", function(context, caller, controller) {

			return {
				control: this.getController().declaredClass,
				params: "isSubmitted",
				value: true,
				element: context
			}
		});

		//Re-run ValidateRules when isSubmitted changes values.
		this.addObserver(this.getConfig("params").isSubmitted, "onChange", "ValidateRules", function(context, caller) {
			if(!this.getController().getValue("isSubmitted")) return { rules: {}, formSet: mojo.query(formId)};
			return {
				rules: rules,
				formSet: mojo.query(formId)
			}
		});

		//Cancel Button
		this.addObserver(this.getValue("cancelButtonId"), "onclick", "ClearErrors", function(context, caller) {
			return {
				className: ".mojoValidationError",
				targetId: this.getController().getValue("formId")
			}
		});
		this.addObserver(this.getValue("cancelButtonId"), "onclick", "ClearForm", function(context, caller) {
			return {
				formSet: mojo.queryFirst(this.getController().getValue("formId"),context)
			}
		});

		//Show DisableBox if we pass Validation.
		this.addObserver(this.getCommand("ValidateRules"), "onResponse", "DisableBox", function(context, caller) {
			return {
				target: context,
				show: true
			}
		});
	},
	addCommands: function() {
		//Add pre-made commands to automatically handle the following:
			//Messaging
			//EnterKey
			//UpdateControllerParam
			//DisableBox
			//ClearForm
			//ClearErrors
			//ClearModel
			//Refresh
			//ToolTip
			//Validate
			//DATA COMMANd
		this.addCommand("Messaging",				"stdlib.behavior.MessagingBehavior");
		this.addCommand("EnterKey",					"stdlib.behavior.EnterKeyBehavior");
		this.addCommand("UpdateControllerParam",	"stdlib.command.UpdateControllerParamCommand");
		this.addCommand("DisableBox",				"stdlib.behavior.DisableBoxBehavior");
		this.addCommand("ClearForm",				"stdlib.behavior.ClearFormBehavior");
		this.addCommand("ClearErrors",				"stdlib.command.RemoveObjectsCommand");
		this.addCommand("ClearModel",				"stdlib.command.ClearModelCommand");
		this.addCommand("Redirect", 					"stdlib.behavior.RedirectBehavior");
		this.addCommand("ToolTip", 					"stdlib.behavior.ToolTipBehavior");
		this.addCommand("ValidateRules",			"stdlib.command.ValidateRulesCommand");
	},
	addIntercepts: function() {
		this.addIntercept("around", this.getValue("formSubmitCommand"),	"ValidateRules", { rules: this.getValue("formRules"), formSet: mojo.query(this.getValue("formId")) });
	}
});
/*
	Class: SliderController

	An abstract Slider component that a
*/
dojo.provide("stdlib.controller.SliderController");
dojo.require("mojo.controller.Controller");
dojo.declare("stdlib.controller.SliderController", mojo.controller.Controller,
{
	params: {
		//The number of pixels between ticks.
		formId: {
			required: true,
			defaultValue: ""
		},
		tickSize: {
			required: false,
			defaultValue: 10,
			type: Number
		},
		tickValue: {
			required: false,
			defaultValue: 1,
			type: Number
		},
		tickMaxValue: {
			required: false,
			defaultValue: 10,
			type: Number
		},
		value: {
			required: false,
			defaultValue: 0,
			type: Number
		},
		valueInput: {
			required: false,
			defaultValue: "slider-value-input",
			type: String
		},
		thumb: {
			required: false,
			defaultValue: ".slider-thumb",
			type: String
		},
		draggable: {
			required: false,
			defaultValue: false,
			type: Boolean
		},
		selectedIndex: {
			required: false,
			defaultValue: 0,
			type: Number
		},
		//"horizontal" or "vertical"
		orientation: {
			required: false,
			defaultValue: "horizontal",
			type: String
		}
	},
	addObservers: function() {
		this.addObserver(this.getContextElement(), "onmousedown", "UpdateControllerParam", function(context, caller) {
			return {
				control: "stdlib.controller.SliderController",
				params: "draggable",
				value: true
			}
		});

		this.addObserver(this.getContextElement(), "onmousedown", "Drag", function(context, caller) {
			return {
				element: mojo.queryFirst(".slider-thumb", context),
				container: mojo.queryFirst(".slider-bg", context),
				orientation: this.getController().getValue("orientation"),
				tickSize: this.getController().getValue("tickSize")
			};
		});

		this.addObserver(document.body, "onmouseup", "UpdateControllerParam", function(context, caller) {
			return {
				control: "stdlib.controller.SliderController",
				params: "draggable",
				value: false
			}
		});

		this.addObserver(this.getContextElement(), "onmousemove", "Drag", function(context, caller) {
			if(!this.getController().getValue("draggable")) return;
			return {
				element: mojo.queryFirst(".slider-thumb", context),
				container: mojo.queryFirst(".slider-bg", context),
				orientation: this.getController().getValue("orientation"),
				tickSize: this.getController().getValue("tickSize")
			};
		});

		this.addObserver(this.getCommand("Drag"), "execute", "UpdateControllerParam", function(context, caller) {
			if(!this.getController().getValue("draggable")) return;
			return {
				control: "stdlib.controller.SliderController",
				params: "selectedIndex",
				value: this.getController().getCommand("Drag").selectedIndex
			};
		});

		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateControllerParam", function(context, caller) {
			if(!this.getController().getValue("draggable")) return;
			return {
				control: "stdlib.controller.SliderController",
				params: "value",
				value: caller.getValue() * this.getController().getValue("tickValue")
			};
		});

		this.addObserver(this.getConfig("params").draggable, "onChange", "UpdateFormField", function(context, caller) {
			if(this.getController().getValue("draggable")) return;
			return {
				formId: this.getController().getValue("formId"),
				fields: [{
					name: this.getController().getValue("valueInput"),
					value: this.getController().getValue("value")
				}]
			};
		});
		this.addObserver(mojo.queryFirst("#"+this.getValue("valueInput")), "onchange", "UpdateControllerParam", function(context, caller) {
			if(this.getController().getValue("draggable")) return;
			return {
				control: "stdlib.controller.SliderController",
				params: "value",
				value: parseInt(caller.value)
			};
		});

		this.addObserver(this.getConfig("params").value, "onChange", "UpdateControllerParam", function(context, caller) {
			if(this.getController().getValue("draggable")) return;
			return {
				control: "stdlib.controller.SliderController",
				params: "selectedIndex",
				value: Math.round(caller.getValue() / this.getController().getValue("tickValue"))
			};
		});

		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "Drag", function(context, caller) {
			if(this.getController().getValue("draggable")) return;
			return {
				element: mojo.queryFirst(".slider-thumb", context),
				container: mojo.queryFirst(".slider-bg", context),
				orientation: this.getController().getValue("orientation"),
				tickSize: this.getController().getValue("tickSize"),
				position: caller.getValue() * this.getController().getValue("tickSize")
			};
		});

	},
	addCommands: function() {
		this.addCommand("Drag",				"stdlib.behavior.DragBehavior");
		this.addCommand("Tween",			"stdlib.behavior.TweenBehavior");
		this.addCommand("UpdateControllerParam",	"stdlib.command.UpdateControllerParamCommand");
		this.addCommand("UpdateFormField", 		"stdlib.behavior.UpdateFormFieldBehavior");
	},
	addIntercepts: function() {}
});
dojo.provide("stdlib.controller.TabController");
dojo.require("mojo.controller.Controller");

dojo.declare("stdlib.controller.TabController", mojo.controller.Controller,
{
	params: {
		selectedIndex: {
			required: false,
			defaultValue: 0,
			type: Number
		},
		activeOn: {
			required: false,
			defaultValue: "onclick"
		}
	},
	addObservers: function() {
		this.addObserver("> .tabs-nav > .tab", this.getValue("activeOn"), "UpdateClass", function(context, caller) {
			var tabs = mojo.query("> .tabs-nav > .tab", context);
			var index = 0;
			for (var i = 0; i < tabs.length; i++) {
				if (tabs[i] == caller) {
					index = i;
					break;
				}
			}
			this.getController().setValue("selectedIndex", index);
		});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller) { return {
			element: mojo.query("> .tabs-nav > .selected", context),
			action: "remove",
			cssClass: "selected"
		}});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller) { return {
			element: mojo.query("> .tabs-content > .selected", context),
			action: "remove",
			cssClass: "selected"
		}});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller) { return {
			element: mojo.query("> .tabs-nav > .tab", context)[caller.getValue()],
			action: "add",
			cssClass: "selected"
		}});
		this.addObserver(this.getConfig("params").selectedIndex, "onChange", "UpdateClass", function(context, caller) { return {
			element: mojo.query("> .tabs-content > .tab-content", context)[caller.getValue()],
			action: "add",
			cssClass: "selected"
		}});
		this.addObserver("> .add", "onclick", "UpdateClass", function(context, caller) {
			mojo.Model.add("testData", {name: "new", description: (new Date()).getTime()});
			this.getController().setValue("selectedIndex", 0);
			this.getController().getConfig("params").selectedIndex.onChange();
		});
	},
	addCommands: function() {
		this.addCommand("UpdateClass", "stdlib.behavior.UpdateCssClassBehavior");
	},
	addIntercepts: function() {

	}
});
dojo.provide("stdlib.controller.FormValidationController");
dojo.require("mojo.controller.Controller");
dojo.declare("stdlib.controller.FormValidationController", mojo.controller.Controller, 
{
	params: {
		isSubmitted: {
			required: false,
			defaultValue: false,
			type: Boolean
		},
		formRules: {
			required: true,
			defaultValue: "stdlib.rules.Rules",
			type: String
		},
		submitButtonId: {
			required: true,
			defaultValue: "#submit-form",
			type: String
		},
		cancelButtonId: {
			required: false,
			defaultValue: "#cancel-form",
			type: String
		},
		errorsContainerId: {
			required: false,
			defaultValue: "",
			type: String
		},
		showDisableBox: {
			required: false,
			defaultValue: true
		}
	},
	addObservers: function() {
		var formRules = this.getValue("formRules");
		var targetElement = (this.getValue("errorsContainerId") != "") ? mojo.queryFirst(this.getValue("errorsContainerId")) : null;
		
	
		//Handles all "Enter" key submits.
		this.addObserver("input", "onkeydown", "EnterKey");
		this.addObserver(this.getCommand("EnterKey"), "onResponse", "UpdateControllerParam", function(context, caller) {
			return {
				control: this.getController().declaredClass,
				params: "isSubmitted", 
				value: true, 
				element: context
			}
		});
		this.addObserver(this.getCommand("EnterKey"), "onResponse", "SubmitForm", function(context, caller) {
			return {
				form: this.getContextElement()
			}
		});
		
		//Handles onblur validation only if the user has clicked "submit", but has errors in it.
		this.addObserver(["input", "textarea"], "onblur", "ValidateRules", function(context, caller) {
			if(!this.getController().getValue("isSubmitted")) return { rules: {}, formSet: this.getContextElement()};
			return {
				rules: formRules,
				formSet: this.getContextElement(),
				targetElement: targetElement
			}
		});
		this.addObserver("select", "onchange", "ValidateRules", function(context, caller) {
			if(!this.getController().getValue("isSubmitted")) return { rules: {}, formSet: this.getContextElement()};
			return {
				rules: formRules,
				formSet: this.getContextElement(),
				targetElement: targetElement
			}
		});

		//Add an observer to the onclick of Submit to update the Controller's parameters for isSubmitted = true.
		this.addObserver(this.getValue("submitButtonId"), "onclick", "UpdateControllerParam", function(context, caller) {
			return {
				control: this.getController().declaredClass,
				params: "isSubmitted", 
				value: true, 
				element: context
			}
		});
		this.addObserver(this.getValue("submitButtonId"), "onclick", "SubmitForm", function(context, caller) {
			return {
				form: this.getContextElement()
			}
		});
		
		this.addObserver(this.getCommand("SubmitForm"), "execute", "DisableBox", function(context, caller) {
			if(!this.getController().getValue("showDisableBox")) return; //No disable box if the dev specifies it in the controller paarams.
			return {
				show: true,
				target: context
			}
		});
		
		//Re-run ValidateRules when isSubmitted changes values. 
		this.addObserver(this.getConfig("params").isSubmitted, "onChange", "ValidateRules", function(context, caller) {
			if(!this.getController().getValue("isSubmitted")) return { rules: {}, formSet: this.getContextElement()};
			return {
				rules: formRules,
				formSet: this.getContextElement(),
				targetElement: targetElement
			}
		});
		
		this.addObserver(this.getValue("cancelButtonId"), "onclick", "ClearErrors", function(context, caller) { 
			return { 
				className: ".mojoValidationError", 
				target: this.getContextElement()
			}
		});
	},
	addCommands: function() {
		this.addCommand("EnterKey",			"stdlib.behavior.EnterKeyBehavior");
		this.addCommand("UpdateControllerParam",	"stdlib.command.UpdateControllerParamCommand");
		this.addCommand("ClearErrors",			"stdlib.behavior.RemoveElementsBehavior");
		this.addCommand("ValidateRules",		"stdlib.command.ValidateRulesCommand");
		this.addCommand("SubmitForm",			"stdlib.behavior.SubmitFormBehavior");
		this.addCommand("DisableBox", 			"stdlib.behavior.DisableBoxBehavior");
	},
	addIntercepts: function() {
		this.addIntercept("around", "SubmitForm", "ValidateRules", { 
			rules: this.getValue("formRules"),
			formSet: this.getContextElement(),
			targetElement: (this.getValue("errorsContainerId") != "") ? mojo.queryFirst(this.getValue("errorsContainerId")) : null
		});
	}
});

/* 
	Class: stdlib.command.GenericServiceCommand
	Author: Jaime Bueza
	
	Provides a generic command that can be used against a service.
	
	Parameters:
		serviceName - {String}
		serviceLocator - {String}
		serviceParams - {Object}
		model - {String}
		
	Example:
		(start code)
			this.addObserver("a.login", "onclick", "GenericServiceCommand", function(context, caller) {
				return {
					serviceName: "LoginService",
					serviceLocator: "app.service.Locator",
					serviceParams: {
						username: mojo.queryFirst("input[name='username']", context).value,
						password: mojo.queryFirst("input[name='password']", context).value
					},
					model: "member.login"
				};
			});
		(end)
*/
dojo.provide("stdlib.command.GenericServiceCommand");
dojo.require("mojo.command.Command");
dojo.declare("stdlib.command.GenericServiceCommand", mojo.command.Command, {
	_model: null,
	execute: function(requestObj) {
		var params = requestObj.getParams();
		//Warn the developer if we're not passing any parameters to the Generic Service Command.
		if(!params) {
			//console.log("stdlib.command.GenericServiceCommand - Warning - No params passed.");
		}
		
		//Set the command's model so that we can access the reference in the onResponse/onError events.
		this._model = params.model;
		//Fetch the application specific service locator.
		dojo.require(params.serviceLocator);
		//Invoke the service
		(eval(params.serviceLocator)).getInstance().getService(params.serviceName).invoke(params.serviceParams, this);
	},
	onResponse: function(data) {
		if(this._model) mojo.Model.set(this._model, data); //If we have a model to set, then we can set it here.
	},
	onError: function(errors) {
		if(this._model) mojo.Model.set(this._model + ".errors", errors);
	}
});

/*
	Class: stdlib.behavior.CheckBoxSelectionBehavior
	Author: Jaime Bueza
	
	Provides the ability to check/uncheck multiple or specific checkboxes
	at the same time.
	
	Paramters:
		element - {DOM Array}
		checked - {Boolean}
	
	Example:
		(start code)
		
		//Add an observer to an element to provide the UI the ability to check the checkboxes
		this.addObserver(mojo.queryFirst("#btn-select-all"), "onclick", "CheckBoxSelection", function(context, caller) {
			return {
				element: mojo.query("input[name='dataRecord']"),
				checked: true
			};
		});
		(end)
*/
dojo.provide("stdlib.behavior.CheckBoxSelectionBehavior");
dojo.require("mojo.command.Behavior");

dojo.declare("stdlib.behavior.CheckBoxSelectionBehavior", mojo.command.Behavior, 
{
	execute: function(requestObj) {
		var params = requestObj.getParams(), els = params.element;
		if(!dojo.isArray(params.element)) {
			els = [params.element];
		}
		
		for(var i = 0, len = els.length; i < len; i++) {
			if(params.checked) {
				els[i].checked = true;
			} else {
				els[i].checked = false;
			}
		}
	}
});


/* 

	Class: stdlib.command.metrics.omniture.TransactionCommand
	Author: Jaime Bueza
*/
dojo.provide("stdlib.command.metrics.omniture.TransactionCommand");
dojo.require("mojo.command.Command");
dojo.declare("stdlib.command.metrics.omniture.TransactionCommand", mojo.command.Command, 
{
	onComplete: function() { 
		//Generic event that signifies a Track/Set operation has been completed.
	},
	onError: function() {
		//console.log("There was an error in the Metrics command.");
	},
	execute: function(requestObj) {
		var params = requestObj.getParams();		
		//if the dev doesn't specify which transactionType they want, it will default to "page".
		if(!params.transactionType) {
			s.t();
		} else if(params.transactionType == "customLink"){
			
			//We need to consolidate params.properties into an array.
			
			if(!dojo.isArray(params.properties)) {
				params.properties = [params.properties];
			}

			for(var i = 0, len = params.properties.length; i < len; i++) {
				var tmp = {};
				var callerName = params.callerName || 'anonymousTrigger';
				var linkVars = [];
				var linkEvents = [];
				
				for(key in params.properties[i]) {

					if(key.indexOf("prop") == 0 || key.indexOf("eVar") == 0) linkVars.push(key);
					if(key.indexOf("event") == 0) linkEvents.push(key);

					tmp[key] = s[key];
					s[key] = params.properties[i][key];
				}

				if (linkEvents.length) linkVars.push('events');

				s.linkTrackVars = linkVars.length ? linkVars.join(",") : "None";
				s.linkTrackEvents = linkEvents.length ? linkEvents.join(",") : "None";
				//Execute the transaction.
				if(requestObj.callerObj.href) {
					s.tl(requestObj.callerObj,'o');
				} else {
					s.tl(requestObj.callerObj,'o', callerName);
				}
				//Resets the original keys before the transaction occurs
				//TODO: Check to see if we're actually restoring the old
				//values of the s object prior to the transaction.
				for(key in tmp) {
					s[key] = tmp[key];
				}
			}
		}
	

	}
});

/* 
	Class: stdlib.command.metrics.omniture.InitializeMetricsMap
	Author: Jaime Bueza
	
	Responsible for mapping page-specific properties for Omniture Metrics.
*/
dojo.provide("stdlib.command.metrics.InitializeMetricsMapCommand");
dojo.require("mojo.command.Command");
dojo.declare("stdlib.command.metrics.InitializeMetricsMapCommand", mojo.command.Command, 
{
	execute: function(requestObj) {
		var params = requestObj.getParams();
		var metricsMap = params.map;
		var map = eval(metricsMap);
		var pages = map.pages;
		
		
		for(var i = 0, len = pages.length; i < len; i++) {
			var metricsProperties = {};
			var pattern = pages[i].pattern;
			var properties = pages[i].properties;
			if (typeof(pattern) == "string") {
				//We're a css selector, so we try to find the selecotr on the current page, match it, map it.
				var currentPage = mojo.query(pattern);
				if(currentPage) {
					metricsProperties = properties;
				}
			} else if (typeof(pattern) == "function" || typeof(pattern) == "object") {
				var regex = new RegExp(pattern);
				if(regex.test(window.location.href)) {
					if(typeof(properties) == "function") {
						properties = properties();
					}
					metricsProperties = properties;
				}
			} else {
				throw new Error("ERROR stdlib.command.metrics.omniture.GetMetricsMapCommand - metricsMap for Pages contains invalid pattern");
			}
			for (key in metricsProperties) {
				s[key] = metricsProperties[key];
			}
		}		
		
	}
});


dojo.provide("stdlib.controller.metrics.MetricsController");
dojo.require("mojo.controller.Controller");
/*
	Class: stdlib.controller.metrics.MetricsController
	Author: Steven Luscher, Jaime Bueza, Loyal Chow
			
	Manages generic Omniture access via Transaction Command and InitializeMetricsMap Command.
	
	Notes:
		- You cannot add trackableLinks (customLink events) to onInit of any controller due
		to the way this Metrics engine is designed. The Metrics Engine initializes when
		all other controllers have been mapped, thusly, you can't observe onInit. If
		you wanted to observe a custom event when the app starts up, you can either
			a) put the events into the MetricsMap.pages property
				or
			b) attach the track to a command that is fired at the beginning of your application
			
			
	Exmample Metrics Map (MetricsMap.js):
		(start code)
		dojo.provide("clubn.MetricsMap");
		clubn.MetricsMap = {
			pages: [
				{
					pattern: /clubnintendo/,
					properties: function() {
						return {
							pageName: "nintendo:club nintendo"
						}
					}
				},
				{
					pattern: /registration/,
					properties: {
						//Optionally, you can specify an object, instead of a function returning an object.
						pageName: "Homepage"
					}
				}	
			],
			links: [
				{

					pattern: ".promo-hot-spot .promo",
					event: "onclick",
					properties: function(caller) {
						return {
							prop1: caller.className,
							eVar2: "evar 2 set"
						}
					}
				}
			]
		};
		(end)		
*/
dojo.declare("stdlib.controller.metrics.MetricsController", mojo.controller.Controller, 
{
	params: {
		metricsMap: {
			defaultValue: "app.MetricsMap",
			required: true
		},
		pageIsLoaded: {
			defaultValue: false 
		},
		analyticsSuite: {
			defaultValue: "omniture",
			required: false
		}
	},
	getMetricsMap: function() {
		dojo.require(this.getValue("metricsMap"));
		var obj = (eval(this.getValue("metricsMap")));
		return obj;
	},
	addObservers: function() {
		this.addObserver(this, "onInit", "Init", { map: this.getValue("metricsMap") });		
		this.addObserver(mojo.controller.Map.getInstance(), "onComplete", "TrackPage", function(context, caller) {
			if(this.getController().getValue("pageIsLoaded")) return false;
			this.getController().setValue("pageIsLoaded", true);
		});
		
		var links = this.getMetricsMap().links;
		
		
		for (var i = 0, len = links.length; i < len; i++) {
			var trackableLink = links[i];	
		

			//Generic variables for the addObservers, we're going to fill this in based on the logic below.
			var whatToTrack = null, whenToTrack = null; 
			
			//BIG TODO: Refactor both the "this.addObserver" calls within this block into
			//a controlller-based call to nullify code duplication.
			
			if(!trackableLink.command && !trackableLink.controller) {
				//We're a DOM element
				whatToTrack = trackableLink.pattern;
				whenToTrack = trackableLink.event;
				this.addObserver(whatToTrack, whenToTrack, "TrackLink", function(tl) {
					return function(context, caller) {
						if(typeof(tl.properties) == "function") {
							tl.properties =  tl.properties(caller);			
						}
						return {
							transactionType: "customLink",
							properties: tl.properties
						}
					}
				}(trackableLink));
			} else {
				//We're a Mojo Object
				var mojoObj = mojo.query(trackableLink.pattern); //Grabs a X number of context elements
				if(!mojoObj) {
					//if we can't find the context of the controller on the page, we must continue the loop
					//and not add an observer
					continue;
				} else {
					if(!dojo.isArray(mojoObj)) {
						mojoObj = [mojoObj];
					}
					for(var x = 0, newLen = mojoObj.length; x < newLen; x++) {
						var obj = mojoObj[x].mojoControllers[trackableLink.controller];

						whenToTrack = trackableLink.event;
						if(!trackableLink.command || trackableLink.command == 'undefined') {
							//If you don't pass a command param, the observer == controller.
							whatToTrack = obj;
			
						} else {
							//We observe the command within the controller.
							whatToTrack = obj.getCommand(trackableLink.command);
						}
				
					
						//console.log("Controller: ", whatToTrack.declaredClass, " --> ", whenToTrack);	

						//Fixes TrackableLink reference problem because function(context, caller){}
						//is invoked upon the user interaction, so the returning object will always
						//be the last link object within the MetricsMap. The following patches this 
						//by passing in a
						//function that takes the trackableLink, and returns the context, caller
						//into the TrackLink callback function.
						this.addObserver(whatToTrack, whenToTrack, "TrackLink", function(tl) {
							return function(context, caller) {
								if(typeof(tl.properties) == "function") {
									tl.properties =  tl.properties(caller);			
								}
								return {
									transactionType: "customLink",
									properties: tl.properties
								}
							}
						}(trackableLink));
						
					}
				}
			}
		}
	},
	addCommands: function() {
	  	this.addCommand("TrackPage", 		"stdlib.command.metrics." + this.getValue("analyticsSuite") + ".TransactionCommand");
	 	this.addCommand("TrackLink", 		"stdlib.command.metrics." + this.getValue("analyticsSuite") + ".TransactionCommand");
		this.addCommand("Init", 			"stdlib.command.metrics.InitializeMetricsMapCommand");
	},
	addIntercepts: function() {}
});
/* 
	Class: stdlib.behavior.PreventDefaultEventBehavior
	Author: Steven Luscher, Chad Oakenfold
	
	Attempts to stop the default event
*/
dojo.provide("stdlib.behavior.PreventDefaultEventBehavior");
dojo.require("mojo.command.Command");
dojo.declare("stdlib.behavior.PreventDefaultEventBehavior", mojo.command.Command, 
{
	execute: function(requestObj) {
	  /* Cancel the default event if possible */
    try {	
	 		var e = requestObj.eventObj;
			if (e["preventDefault"]) e.preventDefault();
			if (e["stopPropagation"]) e.stopPropagation();
			e.returnValue = false;
			return false;	  
		} catch(e) {}
  }
});
/* 	
	Class: stdlib.behavior.SwfObjectBehavior
	Author: Jaime Bueza
	
	Provides an application with the ability to integrate flash objects with swfobject 1.5.
		
	Notes:
		- Requires swfobject 1.5
		
	Implementation:
		HTML Markup:
		
		(start code)
			<div class="flash-component">
				<div id="flash-content">
					<h1>You need flash to view this site.</h1>
				</div> <!-- flash-content -->
			</div> <!-- flash-component -->
		(end)
		
		Controller addObservers() method:
		
		(start code)
		this.addObserver(this, "onInit", "InitSwfObject", function(context, caller) { 
			return {
				elementId: "flash-content", 
				contentName: "main_flash",
				containerId: "#flash-content", 
				src: "/flash/residential/internet/018.swf", 
				width: "779", 
				height: "312", 
				version: "9", 
				defaultBackground: "#FFFFFF", 
				expressInstallSrc: "/flash/expressinstall.swf",
				params: {} 
			} 
		});*
		(end)
*/
dojo.provide("stdlib.behavior.SwfObjectBehavior");
dojo.require("mojo.command.Behavior");
dojo.declare("stdlib.behavior.SwfObjectBehavior", mojo.command.Behavior, 
{
	/* 
		Function: execute
		
		Renders the flash object on to the UI.
		
		Parameters:
			{Object} requestObj 
			
		Request Object Parameters:
			{String} elementId 		- SWFObject writes an element to the page with this ID
			{String} src 			- Location of the flash object
			{String} containerId 	- 
			{Number} width			- width of the flash object, usually set by CSS, but swfobject also adds the width attribute.
			{Number} height			- Height of the flash object, usually set by CSS, but swfobect also adds the height attribute.
			
	*/
	execute: function(requestObj) {
		var params = requestObj.getParams();
		
		//We check to see if the SWFObject library has been loaded.
		if(!deconcept.SWFObject) {
			throw new Error("ERROR stdlib.behavior.SwfObjectBehavior.execute - SWFObject library cannot be found");
		}
		
		if(!params.elementId) {
			throw new Error("ERROR stdlib.behavior.SwfObjectBehavior.execute - elementId is not set");
		}
		if(!params.src) {
			throw new Error("ERROR stdlib.behavior.SwfObjectBehavior.execute - src is not set");
		}
		if(!params.containerId) {
			throw new Error("ERROR stdlib.behavior.SwfObjectBehavior.execute - containerId is not set");
		}
		
		if(!params.width || !params.height) {
			throw new Error("ERROR stdlib.behavior.SwfObjectBehavior.execute - width and/or height is not set");
		}

		if(!params.contentName) {
			params.contentName = "flash_module";
		}
		if(!params.version) {
			params.version = 9;
		}
		if(!params.defaultBackground) {
			params.defaultBackground = "#fff";
		}
		if(!params.wmode) {
			params.wmode = "window";
		}
		
		var so = new SWFObject(params.src, params.contentName, params.width, params.height, params.version, params.defaultBackground);	
		
		// The width must be > 214px and the height must be > 137px in order for Express Install to work.
		if (params.expressInstallSrc) { 
			so.useExpressInstall(params.expressInstallSrc);
		}
		so.addParam("base", params.basePath);
		so.addParam("wmode", params.wmode);
		so.addParam("allowFullScreen", params.allowFullScreen);
		so.addParam("allowScriptAccess", params.allowScriptAccess);
		so.addParam('flashvars',params.flashvars);
		so.write(params.elementId);
	}
});
/* 
	Class: stdlib.behavior.IEPngFixBehavior
	Author: Jaime Bueza
	
	Uses a vml-based ie png fix solution by Drew Diller (http://www.dillerdesign.com/experiment/DD_belatedPNG/).
	This approach uses javascript but uses VML (10x faster) instead of a filter. In order to use this,
	pass a selector or a set of selectors into the behavior. 
	
	Below is a list of gotchas for using this solution:
	- cannot use 'body' as a selector
	- does not play well with <tr>, <td>
	
*/
dojo.provide("stdlib.behavior.IEPngFixBehavior");
dojo.require("mojo.command.Behavior");
dojo.declare("stdlib.behavior.IEPngFixBehavior", mojo.command.Behavior,
{
	execute: function(requestObj) {
		//Parameters:
		//	- selector (String) - CSS Selector of elements you wish to have the fix applied to.
		
		var selectors = requestObj.getParams().selector;
		if(!selectors) {
			throw new Error("stdlib.behavior.IEPngFixBehavior - parameter 'selector' cannot be empty.");
			return false;
		}
		//Check IE6.
		if(dojo.isIE == 6) { 
			DD_belatedPNG.fix(selectors);
		}
	}
});




// mootools scrollbar plugin
Fx.ScrollWindow = Fx.Base.extend({

	initialize: function(options){
		this.setOptions(options);
		this.now = [];
		var b = document.body;
		var stop = this.clearTimer.bind(this);
		if (!this.options.continuer){
			if (b.addEventListener) b.addEventListener('DOMMouseScroll', stop, false);
			else b.onmousewheel = stop;
		}
	},

	setNow: function(){
		[0,1].each(function(i){
			this.now[i] = this.compute(this.from[i], this.to[i]);
		}, this);
	},

	scrollTo: function(x, y){
		if (this.timer && this.options.wait) return;
		var left = Window.getScrollLeft();
		var top =  Window.getScrollTop();
		var width = Window.getWidth();
		var height = Window.getHeight();
		var fullWidth = Window.getScrollWidth();
		var fullHeight = Window.getScrollHeight();
		var maxScrollWidth = fullWidth - width;
		var maxScrollHeight = fullHeight - height;
		if (x > maxScrollWidth) x = maxScrollWidth;
//		if (y > maxScrollHeight) y = maxScrollHeight;
		return this.custom([left, top], [x, y]);
	},

	toElement: function(el){
		return this.scrollTo($(el).getLeft(), $(el).getTop());
	},

	increase: function(){
		window.scrollTo(this.now[0], Math.round(this.now[1]));
	}

});




