﻿/*jslint plusplus: true, devel: true, undef: true, sloppy: true, unparam: true, maxerr: 50, indent: 4 */
/*global document:false, setTimeout:false, setInterval:false, window:false, self:false, escape:false, unescape:false, XMLHttpRequest:false, ActiveXObject:false */

var _gaq = _gaq || [];

var jillPopup;

var isNull = function (obj) {
	"use strict";
	var tag;

	if (obj === undefined) {
		return true;
	} else if (obj instanceof Array || obj !== null) {
		tag = obj.tagName || "";

		if (tag.length === 0 || tag.toLowerCase() !== "select") {
			return obj.length === 0; 
		} else if (tag.toLowerCase() === "select") {
			return false;
		} else {
			return tru;
		}
	} else {
		return true;
	}
},
	isArray = function (obj) {
		"use strict";
		var tag;

		if (obj === undefined) {
			return false;
		} else if (obj instanceof Array) {
			return true;
		} else if (obj === null) {
			return false;
		} else {
			tag = obj.tagName || "";

			if (obj.length > 0 && (typeof obj !== "string") && (tag.length === 0 || tag.toLowerCase() !== "select")) {
				return true;
			} else {
				return false;
			}
		}
	},

	JILL = {
		NONE: 1,
		APPEND: 2,
		PREPEND: 3,
		REPLACE: 4,
		REMOVE: 5,
		UP: 1,
		DOWN: 2,
		SUCCESS: 1,
		FAIL: 2
	};

var browserAgent = navigator.userAgent.toLowerCase(),
	browser = {
		version: (browserAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [0, "0"])[1],
		safari: /webkit/.test(browserAgent) && !/chrome/.test(browserAgent),
		opera: /opera/.test(browserAgent),
		msie: /msie/.test(browserAgent) && !/opera/.test(browserAgent),
		chrome: /chrome/.test(browserAgent),
		mozilla: /mozilla/.test(browserAgent) && !/(compatible|webkit)/.test(browserAgent)
	};

var jCore = {
	google: {
		analytics: function (pKey, pDomain) {
			var ga = document.createElement("script"),
				s = document.getElementsByTagName("script")[0];

			_gaq.push(["_setAccount", pKey]);

			if (pDomain.length > 0) {
				_gaq.push(['_setDomainName', pDomain]);
			}
			_gaq.push(["_trackPageview"]);

			ga.type = "text/javascript";
			ga.async = true;
			ga.src = ("https:" === document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";

			s.parentNode.insertBefore(ga, s);
		}
	},

	image: function () {
		"use strict";

		var retObj = {};

		retObj.protect = function () {
			alert("Right-Click is Disabled\nImage is Copy Protected");
			return false;
		};

		return retObj;
	},

	mouse: function (e) {
		"use strict";

		var retObj = {},
			evt = e || window.event;

		retObj.event = evt;
		
		retObj.target = evt.target || evt.srcElement;

		retObj.leftButton = ((evt.button === 1 && window.event !== null) || evt.button === 0);

		retObj.coords = function () {
			var intX, intY, old;

			if (typeof(evt.pageX) === "number") {
				intX = evt.pageX;
				intY = evt.pageY;
			} else if (typeof(evt.clientX) === "number") {
				intX = evt.clientX;
				intY = evt.clientY;
				old = (window.navigator.userAgent.indexOf("Opera") + 1) ||
					(window.ScriptEngine && ScriptEngine().indexOf("InScript") + 1) ||
					(navigator.vendor === "KDE");
				if (!old) {
					if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
						intX += document.body.scrollLeft;
						intY += document.body.scrollTop;
					} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
						intX += document.documentElement.scrollLeft;
						intY += document.documentElement.scrollTop;
					}
				}
			}

			return {x: intX, y:intY };
		};

		return retObj;
	},

	window: function () {
		var retObj = {},
			domLoad = function () {
				document.removeEventListener("DOMContentLoaded", arguments.callee, false);
				jWin.load();
			},
			stateChange = function () {
				if (document.readyState === "complete") {
					document.detachEvent("onreadystatechange", arguments.callee);
					jWin.load();
				}
			},
			stateCheck = function () {
				try {
					document.documentElement.doScroll("left");
				} catch (e) {
					setTimeout(arguments.callee, 0);
					return;
				}
				jWin.load();
			};

		// Sets the document event listeners depending on the type of browser
		if (document.addEventListener) {
			document.addEventListener("DOMContentLoaded", domLoad, false);
		} else if (document.attachEvent) {
			document.attachEvent("onreadystatechange", stateChange);
			if (document.documentElement.doScroll && window === window.top) {
				stateCheck();
			}
		}

		// Gets the window's onLoad events
		retObj.events = [];

		// Gets a value indicatin whether the form has been loaded
		retObj.loaded = false;

		// Gets the window's url pathname
		retObj.path = window.location.pathname;

		// Gets the window's url querystring
		retObj.queryString = window.location.search;

		// Gets the current windows complete url
		retObj.url = window.location.pathname + window.location.search;

		// Conctenates the submitted url with a "&t=value" parameter to "tickle" the page to refresh
		retObj.addTickle = function (pUrl) {
			var today = new Date(),
				i = parseInt(today.getFullYear().toString() + today.getMonth().toString() + today.getDate().toString() + today.getHours().toString() + today.getMinutes().toString() + today.getSeconds().toString() + today.getMilliseconds().toString(), 10),
				tickle = "t=" + i,
				regEx = new RegExp("([?|&])t=\\d+", "g");

			if (/[?|&]t=\d+/.test(pUrl)) {
				pUrl = pUrl.replace(regEx, "$1" + tickle);
			} else {
				pUrl += (pUrl.indexOf("?") > 0 ? "&" : "?") + tickle;
			}
			return pUrl;
		};

		// Returns the the submitted url OR the current page's url if the submitted url is null or empty
		retObj.getUrl = function (pUrl) {
			if (isNull(pUrl)) {
				return this.url;
			} else {
				return pUrl;
			}
		};

		// Sets the current window's url (reloads the page with the new url)
		retObj.href = function (pUrl) {
			if (isNull(pUrl)) {
				pUrl = this.url + this.addTickle(this.url);
			}
			self.location.href = pUrl;
			return false;
		};

		// Executes the onLoad events (if any exist)
		retObj.load = function () {
			var eLen = this.events.length;

			if (this.loaded === false) {
				this.loaded = true;

				while (eLen--) {
					if (typeof this.events[eLen] === "function") {
						this.events[eLen]();
					}
				}
			}
		};

		// Add a new function to the current onLoad events collection
		retObj.onLoad = function (pFunc) {
			this.events.unshift(pFunc);
		};

		// Returns the value of the desired querystring parameter
		retObj.queryValue = function (pParm, pDef) {
			var regEx, search;

			pDef = pDef || "";
			pParm = pParm.replace(/[\[]/, "\\\\[").replace(/[\]]/, "\\\\]");
			regEx = new RegExp("[\\?&/]" + pParm + "[=/]([^&#]*)");
			search = regEx.exec(this.queryString);

			if (search !== null) {
				if (search.length === 0) {
					search = null;
				}
			}
			return (search === null ? pDef : search[1]);
		};

		// Returns the current window's scroll position
		retObj.scroll = function () {
			var iT = 0, iL = 0;

			if (document.documentElement && !document.documentElement.scrollTop && window.pageYOffset) {
				iL = window.pageXOffset;
				iT = window.pageYOffset;
			} else if (document.documentElement && document.documentElement.scrollTop) {
				iL = document.documentElement.scrollLeft;
				iT = document.documentElement.scrollTop;
			} else if (document.body && document.body.scrollTop) {
				iL = document.body.scrollLeft;
				iT = document.body.scrollTop;
			}

			return { left: iL, top: iT };
		};

		// Returns the current window's document and view dimensions
		retObj.size = function () {
			var h = Math.max(Math.max(document.body.scrollHeight, document.documentElement.scrollHeight),
				Math.max(document.body.offsetHeight, document.documentElement.offsetHeight),
				Math.max(document.body.clientHeight, document.documentElement.clientHeight)),
				w = Math.max(Math.max(document.body.scrollWidth, document.documentElement.scrollWidth), Math.max(document.body.offsetWidth, document.documentElement.offsetWidth), Math.max(document.body.clientWidth, document.documentElement.clientWidth)),
				cW = (!window.innerWidth ? ((document.documentElement.clientWidth !== 0) ? document.documentElement.clientWidth : document.body.clientWidth) : window.innerWidth),
				cH = (!window.innerHeight ? ((document.documentElement.clientHeight !== 0) ? document.documentElement.clientHeight : document.body.clientHeight) : window.innerHeight);

			return {
				doc: {
					height: h,
					width: w
				},
				view: {
					height: cH,
					width: cW
				}
			};
		};

		return retObj;
	},

	dom: function (pRoot) {
		"use strict";

		var retObj = {};

		if (!isNull(pRoot)) { if (!isArray(pRoot)) { pRoot = [pRoot]; } }

		// Set the root element tp the submitted element root
		retObj.root = pRoot;

		// Loop through each element in this collection and call the submitted function
		retObj.forEach = function (pFunc, param) {
			var iR, iP, iA, obj = [], elm;

			param = param || "";

			if (typeof param === "string") {
				param = param.split("|");
			} else if (!isArray(param)) {
				param = [param];
			}

			for (iR = 0; iR < this.root.length; iR += 1) {
				iP = param.length;

				while (iP--) {
					elm = pFunc(this.root[iR], param[iP]);

					if (!isNull(elm)) {
						if (isArray(elm)) {
							for (iA = 0; iA < elm.length; iA += 1) {
								obj.push(elm[iA]);
							}
						} else {
							obj.push(elm);
						}
					}
				}
			}

			return obj;
		};

		// Returns all elements matching the class name
		retObj.getByClass = function (pClass) {
			var func = function (pElm, param) {
					var t = (new RegExp(param).test(pElm.className));

					return (t ? pElm : null);
				},
				notFunc = function (pElm, param) {
					return ((pElm.className.indexOf(param) >= 0) ? null : pElm);
				};

			if (pClass.indexOf("!") === 0) {
				return this.forEach(notFunc, pClass.substring(1));
			} else {
				return this.forEach(func, "^" + pClass.replace(/\*/g, ".*") + "$");
			}
		};

		// Returns all elements containing a given tag name with value matching the id
		retObj.getByDataTag = function (pId, pTag) {
		};

		// Returns an element matching the desired id
		retObj.getById = function (pId) {
			var func = function (pElm, param) {
				if (pElm.getElementById) {
					return pElm.getElementById(param);
				} else {
					return null;
				}
			};

			return this.forEach(func, pId);
		};

		retObj.getByStep = function (pStep) {
			var steps = pStep.split(","), ret = [], inx;

			if (steps.length === 1) {
				inx = pStep.toInt();
				if (inx < this.root.length && inx > -1) {
					ret.push(this.root[inx]);
				}
			} else if (steps.length === 2) {
			} else if (steps.length === 3) {
			}

			if (ret.length === 0) {
				return null;
			} else {
				return ret;
			}
		};

		// Returns all elements matching the tag name
		retObj.getByTag = function (pTag) {
			var func = function (pElm, param) {
				if (pElm.getElementsByTagName) {
					return pElm.getElementsByTagName(param);
				} else {
					return null;
				}
			};

			return this.forEach(func, pTag);
		};

		return retObj;
	},

	element: function (pObj) {
		"use strict";

		var retObj = {};

		retObj.object = pObj;

		retObj.length = (isNull(pObj) ? 0 : (isArray(pObj) ? (isNull(pObj[0]) ? 0 : pObj.length) : 1));

		// Enumerates through eacj element in this array of elements, triggering the submitted delegate
		retObj.forEach = function (func, useElem) {
			var ret = [], i;

			useElem = (isNull(useElem) ? true : useElem);

			if (!isNull(this.object)) {
				if (isArray(this.object)) {
					for (i = 0; i < this.object.length; i += 1) {
						ret.push(func(this.object[i]));
					}
				} else {
					ret.push(func(this.object));
				}
			}

			if (ret.length === 1) {
				ret = ret[0];
			}
			if (useElem) {
				return jCore.element(ret);
			} else {
				return ret;
			}
		};

		// Gets or sets the elements attributes
		retObj.attr = function (pName, pVal, pAct, pRepl) {
			pAct = pAct || JILL.NONE;
			
			if (!isNull(pVal)) {
				return this.forEach(function (obj) {
					var val = obj[pName] || "";

					switch (pAct) {
					case JILL.NONE:
						val = pVal;
						break;
					case JILL.APPEND:
						val += pVal;
						break;
					case JILL.PREPEND:
						val = pVal + val;
						break;
					case JILL.REPLACE:
						val = val.replace(new RegExp(pVal, "g"), pRepl);
						break;
					case JILL.REMOVE:
						val = val.replace(new RegExp(pVal, "g"), "");
						break;
					}
					window.status = obj.tagName + ": " + pName + " = " + val;
					obj[pName] = val;
					return obj;
				});
			} else {
				return this.forEach(function (obj) {
					var val = "";
					if (obj[pName]) {
						val = obj[pName] || "";
					} else if (obj.attributes) {
						val = obj.attributes.getNamedItem(pName);

						if (!isNull(val)) {
							val = val.value || "";
						}
					} else if (obj.getAttribute) {
						val = obj.getAttribute(pName) || "";
					}

					if (val === null) {
						val = "";
					}

					return val;
				}, false);
			}
		};

		// Centers the current elements within the sumbitted elements context
		retObj.center = function (pElm) {
			var sizeElm = (pElm === window ? jCore.window().size().view : { width: pElm.offsetWidth, height: pElm.offsetHeight }),
				scroll = (pElm === window ? jCore.window().scroll() : { top: 0, left: 0 });

			return this.forEach(function (obj) {
				var size = {
						width: obj.offsetWidth,
						height: obj.offsetHeight
					},
					yPos = ((sizeElm.height - size.height) / 2),
					xPos = ((sizeElm.width - size.width) / 2);

				obj.style.left = xPos + "px";
				obj.style.top = yPos + "px";

				return obj;
			});
		};

		// Trigger the click event on the object
		retObj.click = function () {
			this.forEach(function (obj) {
				if (obj.click) { obj.click(); } else { obj.onclick(); }
			});

			return this;
		};

		// get or set the className attribute for all elements in this collection
		retObj.css = function (pVal, pAct, pNew) {
			return this.attr("className", pVal, pAct, pNew);
		};

		// set the enabled status of the elements in this collection
		retObj.enabled = function (pEnabled) {
			return this.forEach(function (obj) {
				var onClick;

				if (obj.tagName.toLowerCase() === "a") {
					onClick = obj.onclick.toString().functionText();

					if (obj.onclick) {
						if (pEnabled) {
							obj.onclick = new Function(onClick.replace("return false;", ""));
						} else {
							obj.onclick = new Function("return false;" + onClick);
						}
					} else {
					}

				} else {
					obj.disabled = !pEnabled;
					jill(obj.parentNode).css(" disabled", (pEnabled ? JILL.REMOVE : JILL.APPEND));
				}

				return obj;
			});
		};

		// get or remove the event for all elements in this collection
		retObj.event = function (pEvt, pFunc, pRemove) {
			return this.forEach(function (obj) {
				var newFunc = (typeof (pFunc) === "string" ? new Function(pFunc) : pFunc);

				if (obj.addEventListener) {
					if (pRemove || false) {
						obj.removeEventListener(pEvt.replace("on", ""), newFunc, false);
					} else {
						obj.addEventListener(pEvt.replace("on", ""), newFunc, false);
					}
				} else if (obj.attachEvent) {
					if (pRemove || false) {
						obj.detachEvent(pEvt, newFunc);
					} else {
						obj.attachEvent(pEvt, newFunc);
					}
				}
				return obj;
			});
		};

		retObj.find = function (pPath) {
			return jill(pPath, this.object);
		};

		// hide all elements in this collection
		retObj.hide = function () {
			return this.style("display", "none");
		};

		// get or set the href attribute for all elements in this collection
		retObj.href = function (pVal) {
			return this.attr("href", pVal);
		};

		// get or set the jasvcript href attribute for all elements in this collection
		retObj.hrefJs = function (pVal) {
			if (!isNull(pVal)) {
				pVal = "jav" + "ascr" + "ipt" + ":" + pVal;
			}
			return this.attr("href", pVal);
		};

		// get or set the id attribute for all elements in this collection
		retObj.id = function (pVal) {
			return this.attr("id", pVal);
		};
		retObj.inx = function (pX) {
			if (pX < this.length) {
				if (this.length === 1) {
					return this;
				} else {
					return jCore.element(this.object[pX]);
				}
			} else {
				return null;
			}
		};

		// insert a new element into the DOM collection and return the new element collection
		retObj.insert = function (pTag, pAct, pSib) {
			pAct = pAct || JILL.NONE;
			return this.forEach(function (obj) {
				var newElm = (typeof pTag === "string" ? document.createElement(pTag) : pTag), retElm;

				switch (pAct) {
				case JILL.NONE:
				case JILL.APPEND:
					if (obj.appendChild) {
						if (!isNull(pSib)) {
							retElm = obj.insertBefore(newElm, pSib);
						} else {
							retElm = obj.appendChild(newElm);
						}
					}
					break;
				case JILL.PREPEND:
					if (obj.insertBefore) {
						retElm = obj.insertBefore(newElm, obj);
					}
					break;
				case JILL.REMOVE:
					if (obj.removeChild) {
						retElm = obj.parentNode;
						retElm.removeChild(obj);
					}
					break;
				}
				return retElm;
			});
		};

		// Gets or sets the location of the current elements
		retObj.location = function (pLeft, pTop) {
			if (isNull(pLeft)) {
				return this.forEach(function (obj) {
					var l = obj.offsetLeft, t = obj.offsetTop;

					while (obj.offsetParent) {
						obj = obj.offsetParent;
						l += obj.offsetLeft;
						t += obj.offsetTop;
					}

					return { left: l, top: t };
				}, false);
			} else {
				return this.forEach(function (obj) {
					obj.style.left = pLeft + "px";
					obj.style.top = pTop + "px";
				});
			}
		};

		retObj.move = function (pDir, pEnforce) {
			var sibling, item, parent = this.parent();

			if (pDir === JILL.UP) {
				sibling = this.sibling(pDir);

				if (!isNull(sibling)) {
					item = this.object;
					this.remove();
					parent.insert(item, 0, sibling.object);
				}
			} else {
				item = this.sibling(pDir);
				if (!isNull(item)) {
					item.move(JILL.UP);
				}
			}
		};

		// Gets or sets the opacity for all elements in this collection
		retObj.opacity = function (pVal) {
			if (pVal === 0) {
				return this.hide();
			} else {
				return this.forEach(function (obj) {
					obj.style["zoom"] = "1";
					obj.style["filter"] = "alpha(opacity=" + pVal + ")";
					obj.style["opacity"] = (pVal / 100).toString();
					return obj;
				});
			}
		};

		// Sets the element's (HTMLSelect object) options
		retObj.options = function (pOpts) {
			var parseOption = function (pObj, pRes) {
					var regEx = new RegExp("<option value=\"([^\"]+)\">([^>]+)</option>", "gi"), result = regEx.exec(pRes), i = 1, value, text, option;

					while (i < result.length) {
						value = result[i];
						text = result[i + 1];

						option = new Option(text, value);
						pObj.options.add(option);

						i += 2;
					}
				},
				parseOptions = function (pObj) {
					var matches = pOpts.match(new RegExp("<option value=\"[^\"]+\">[^>]+</option>", "gi")), iMatch;

					pObj.options.length = 0;

					if (matches) {
						for (iMatch = 0; iMatch < matches.length; iMatch += 1) {
							parseOption(pObj, matches[iMatch]);
						}
					}
				};
			
			parseOptions(this.object);
			
			return this.object;
		};

		// Gets the parent element for this collection's first element 
		retObj.parent = function (pTag, pAttr) {
			var obj = [],
				breakOut = false,
				node = (isArray(this.object) ? this.object[0] : this.object),
				first = "";

			pAttr = pAttr || "";

			if (pAttr.length > 0) {
				first = pAttr.substring(0, 1);
				pAttr = pAttr.replace(first, "");
			}

			if (isNull(node)) {
				return this;
			}

			if (isNull(pTag)) {
				obj = node.parentNode;
			} else {
				while (node.parentNode && !breakOut) {
					node = node.parentNode;
					if (node.tagName) {
						if (node.tagName.compare(pTag)) {
							if (pAttr.length > 0) {
								if (first === "@" && node.className.indexOf(pAttr) >= 0) {
									obj = node;
									breakOut = true;
								} else if (first === "." && node.id.indexOf(pAttr) >= 0) {
									obj = node;
									breakOut = true;
								} else if (first === "#" && jill(node).attr("data-xmlnode").indexOf(pAttr) >= 0) {
									obj = node;
									breakOut = true;
								} else if (first === "%" && jill(node).attr("data-xmlattr").indexOf(pAttr) >= 0) {
									obj = node;
									breakOut = true;
								}
							} else {
								obj = node;
								breakOut = true;
							}
						}
					}
				}
			}

			return jCore.element(obj);
		};

		// Remove this element from the DOM and return it's parent as a new collection
		retObj.remove = function (pKeep) {
			pKeep = pKeep || false;
			return this.forEach(function (obj) {
				var parent = obj.parentNode;

				if (!isNull(parent)) {
					parent.removeChild(obj);
				}

				if (pKeep) { return obj; } else { return parent; }
			});
		};

		/// Shows the control(s) by removing the "hidden" css style and display as "block" or pAs argument
		retObj.show = function (pAs) {
			return this.css("hidden", JILL.REMOVE).style("display", (pAs || "block"));
		};

		retObj.sibling = function (pDir) {
			var funcNext = function (obj) {
					while ((obj = obj.nextSibling) && obj.nodeType !== 1) {
					}
					return obj;
				},
				funcPrev = function (obj) {
					while ((obj = obj.previousSibling) && obj.nodeType !== 1) {
					}
					return obj;
				};

			return this.forEach(pDir === JILL.UP ? funcPrev : funcNext);
		};

		retObj.size = function (pWidth, pHeight) {
			if (isNull(pWidth)) {
				return this.forEach(function (obj) {
					return {
						width: obj.offsetWidth,
						height: obj.offsetHeight
					};
				}, false);
			} else {
				return this.forEach(function (obj) {
					obj.style.width = pWidth + "px";
					obj.style.height = pHeight + "px";
				});
			}
		};

		retObj.src = function (pVal) {
			return this.attr("src", pVal);
		};

		// Gets or sets the element's style
		retObj.style = function (pName, pVal) {
			if (isNull(pVal)) {
				return this.forEach(function (obj) {
					if (/zindex/i.test(pName)) {
						return obj.style[pName];
					} else {
						if (obj.currentStyle) {
							return obj.currentStyle[pName];
						} else if (window.getComputedStyle) {
							return document.defaultView.getComputedStyle(obj, null).getPropertyValue(pName);
						}
					}
				}, false);
			} else {
				if (/height|top|left|width/i.test(pName) && !/px|auto/i.test(pVal)) {
					pVal += "px";
				}
				return this.forEach(function (obj) {
					obj.style[pName] = pVal;
					return obj;
				});
			}
		};

		// Gets or sets the text attribute for all elements in this collection
		retObj.text = function (pVal, pAct, pNew) {
			return this.attr("innerHTML", pVal, pAct, pNew);
		};

		// Sets the background transparency for the elements in this collection
		retObj.transparency = function (pVal) {
			var rgba = pVal.toString().convertToRGBA(),
				filter = "progid:DXImageTransform.Microsoft.gradient(startColorstr='" + pVal + "',endColorstr='" + pVal + "')";

			return this.forEach(function (obj) {
				try {
					obj.style["backgroundColor"] = rgba;
				} catch (e) {
					obj.style["backgroundColor"] = "transparent";
					obj.style["zoom"] = "1";
					obj.style["filter"] = filter;
				}
				return obj;
			});
		};

		if (pObj === null) {
			return null;
		} else {
			return retObj;
		}
	},

	// Returns an element object with added protoype functions given the selected control criteria (pSel) and the root element (pCont)
	elements: function (pSel, pCnt) {
		var retObj,
			getElements = function () {
				var matches = pSel.match(new RegExp("([@\\#%]?[^>@\\#%]*)", "g")), iM, match, first, dom, ret = [], num, sub,
					getNum = function (obj) {
						var num = -1;
						if (obj.isNumeric()) {
							num = obj.toInt();
							if (num < 0 || num > ret.length) {
								num = -1;
							}
						}
						return num;
					};

				for (iM = 0; iM < matches.length; iM += 1) {
					match = matches[iM];
					if (match.length > 0) {
						first = match.substring(0, 1);
						dom = jCore.dom(pCnt);
						num = getNum(match);
						sub = match.substring(1);

						switch (first) {
						case ".":
							ret = dom.getById(sub);
							break;
						case "#":
							ret = dom.getByStep(sub);
							break;
						case "@":
							ret = dom.getByClass(sub);
							break;
						default:
							ret = (num > 0 ? [ret[num]] : dom.getByTag(match));
							break;
						}

						pCnt = ret;
					}
				}
				if (ret.length === 1) {
					ret = ret[0];
				}
				return ret;
			};

		pCnt = pCnt || document;

		if (isNull(pSel)) {
			pSel = "body";
		}
		if (typeof pSel === "string") {
			retObj = getElements();
		} else {
			retObj = pSel;
		}

		return jCore.element(retObj);
	}
};

var jill = function (pSel, pCnt) {
	"use strict";
	return new jCore.elements(pSel, pCnt);
};

var jWin = jCore.window(),
	jMouse = jCore.mouse;
	jImg = jCore.image(),
	jillForm = jCore.form;

jCore.context = {
	currentContext: null,

	close: function (e) {
		var closeCtx = function () {
				jCore.context.currentContext.remove();
				document.onmousedown = null;
			},
			testClose = function () {
				var evt = e || window.event, size = jCore.context.currentContext.size(), loc = jCore.context.currentContext.location();

				if (evt.clientX < loc.left || evt.clientY < loc.top || evt.clientX > (loc.left + size.width) || evt.clientY > (loc.top + size.height)) {
					closeCtx();
				}
			};

		if (isNull(e)) {
			closeCtx();
		} else {
			testClose();
		}
	},
	addItem: function (pElm) {
		var css = "ctx-icon" + (isNull(pElm.css) ? "" : " " + pElm.css),
			close = function () {
				if (!isNull(pElm.evt)) {
					pElm.evt();
				}
				jCore.context.close();
			};

		this.currentContext.insert("a").insert("span").css(css).parent().insert("span").css("ctx-label").text(pElm.text).event("onclick", close);
	},
	// Show a new context menu
	show: function (pArgs, pPos) {
		var i;

		if (!isNull(pArgs)) {
			this.currentContext = jill().insert("div").css("ctx-menu").style("left", pPos.left).style("top", pPos.top);
			document.onmousedown = jCore.context.close;
			for (i = 0; i < pArgs.length; i += 1) {
				this.addItem(pArgs[i]);
			}
		}
	}
};

var jContext = function (pArgs, pPos) {
	return jCore.context.show(pArgs, pPos);
};

jCore.form = {
	events: [],

	// Return the formatted argument name and value for pos/callback support
	formatArg: function (pName, pVal) {
		var arg = "&" + pName + "=", key;

		if (typeof pVal !== "string") {
			for (key in pVal) {
				if (pVal.hasOwnProperty(key)) {
					arg += "&" + key + "=" + pVal[key];
				}
			}
		} else {
			arg += pVal;
		}

		return arg;
	},
	formatArgs: function (pArgs) {
		var i = 0, ret = "", name, value;

		while (i < pArgs.length) {
			if (i < (pArgs.length - 1)) {
				name = pArgs[i]; value = pArgs[i + 1];
				ret += jCore.form.formatArg(name, value);
			}

			i += 2;
		}

		return ret;
	},
	getData: function (pRoot) {
		var xml = "",
			elm = "",
			concat = function (name, val) {
				elm += (elm.length > 0 ? "&" : "") + name + "=" + val;
			},
			process = function (obj) {
				input = jCore.form.input(obj);

				if (!isNull(input)) {
					if (!isNull(input.value)) {
						if ("__EVENTTARGET__EVENTARGUMENT__VIEWSTATE__JILLEVENT".indexOf(input.name) < 0) {
							if (isNull(input.xmlAttr) && isNull(input.xmlNode)) {
								concat(input.name, input.value);
							}
						}
					}
				}
			},
			find = function (root) {
				var i, l, inp;

				process(root);

				if (root.childNodes) {
					l = root.childNodes.length;
					for (i = 0; i < l; i += 1) {
						find(root.childNodes[i]);
					}
				}
			};

		find(pRoot);

		return "&" + elm;
	},

	// Get the form's input data parameters and values
	getForm: function (pTarget, pArgument, pControl) {
		var getRoot = function () {
				var root = document.forms[0], cId;
				
				if (!isNull(jillPopup) && jillPopup.popupCount > 0) {
					root = jillPopup.getTable().object;
				} else if (typeof pControl === "string") {
					cId = pControl.replace(/\$/g, "_");
					if (!isNull(document.getElementById(cId))) {
						root = document.getElementById(cId);
					}
				}

				return root;
			},
			data = "__JILLEVENT=JillPostBack" + jCore.form.formatArgs(["__EVENTTARGET", pTarget, "__EVENTSOURCE", pControl, "__EVENTARGUMENT", pArgument, ]);

		data += jCore.form.getData(getRoot());

		return data;
	},

	input: function (obj) {
		var tag = obj.tagName || "", type = "", name, value, xmlAttr, xmlNode, i;

		if (/input|select|textarea/i.test(tag)) {
			type = obj.type;
			name = obj.name;

			switch (tag.toLowerCase()) {
			case "input":
				if (/text|password|hidden/i.test(type)) {
					value = obj.value;
				} else if (/checkbox/i.test(type)) {
					value = (obj.checked ? "true" : "false");
				} else if (/radio/i.test(type)) {
					if (obj.checked) {
						name = obj.name.replace(/^(.*\$)+/gi, "");
						value = obj.value;
					}
				}

				break;

			case "select":
				value = "";
				for (i = 0; i < obj.options.length; i += 1) {
					if (obj.options[i].selected) {
						value += (value.length > 0 ? "," : "") + obj.options[i].value;
					}
				}
				break;

			case "textarea":
				if (obj.style["display"] === "none" && !isNull(jill("." + obj.id + "___Frame").object)) {
					obj.value = FCKeditorAPI.GetInstance(obj.id).GetXHTML();
				}
				value = obj.value;
				break;
			}

			if (!isNull(value)) {
				value = value.escape();
			}

			return {
				type: type,
				name: name,
				value: value,
				xmlAttr: xmlAttr,
				xmlNode: xmlNode
			};
		} else {
			return null;
		}
	},

	// Parse the response from the posted result
	parse: function (pRes) {
		var update = function (pCon, pType, pName, pVal) {
			pVal = pVal.replace(new RegExp("&#43;", "g"), "+");

			if (pType === "Attr") {
				jill(pCon).attr(pName, pVal);
			} else if (pType === "Options") {
				jill(pCon).options(pVal);
			} else if (pType === "Style") {
				jill(pCon).style(pName, pVal);
			} else if (pType === "Event") {
				jCore.form.events.push(pVal);
			}
		},
			parseResult = function (pMatch) {
				var matches = pMatch.match(new RegExp("(\"((?!\",\")[\\s\\S])*\")", "g")), type, control, name, value, func,
					strip = function (pVal) {
						return pVal.substring(1, pVal.length - 1);
					};
				if (matches) {
					if (matches.length === 4) {
						control = strip(matches[0]);
						type = strip(matches[1]);
						name = strip(matches[2]);
						value = strip(matches[3]).unescape();
						update(control, type, name, value);
					}
				}
			},
			parseResults = function () {
				var matches = pRes.match(new RegExp("\\[\"(((?!\",\")[\\s\\S])*\",\"){3}((?!\"\\])[\\s\\S])*\"\\]", "g")), iMatch;

				if (matches) {
					for (iMatch = 0; iMatch < matches.length; iMatch += 1) {
						parseResult(matches[iMatch]);
						pRes = pRes.replace(matches[iMatch], "");
					}
				}
			};

		jCore.form.events = [];
		parseResults();
		return pRes;
	},

	// Send a "POST" command to the servier
	post: function (pUrl, pData, pType, pComp, pHeaders) {
		var xmlObj = jCore.form.xmlObject(),
			async = !isNull(pComp),
			method = "POST",
			key,
			i;

		if (xmlObj) {
			if (async) {
				xmlObj.onreadystatechange = function () {
					if (xmlObj.readyState === 4) {
						pComp(xmlObj.responseText);
					}
				};
			}

			xmlObj.open(method, pUrl, async);
			xmlObj.setRequestHeader("Content-Type", pType || "application/x-www-form-urlencoded");

			if (!isNull(pHeaders)) {
				for (key in pHeaders) {
					if (pHeaders.hasOwnProperty(key)) {
						xmlObj.setRequestHeader(key, pHeaders[key]);
					}
				}
			}
			xmlObj.send(pData);

			if (!async) {
				while (xmlObj.readyState !== 4) {
					i += 1;
				}

				if (xmlObj.status !== 500) {
					if (xmlObj.status === 404) {
						return "Page cannot be found";
					} else {
						while (xmlObj.status !== 200) {
							i += 1;
						}
					}
					try {
						return xmlObj.responseText;
					} catch (e) {
					}
				} else {
					return xmlObj.responseText;
				}
			} else {
				return "Asyncronouse data not available";
			}
		} else {
			if (async) {
				pComp("Cannot create Xml Object for Posted Request");
			} else {
				return "Cannot create Xml Object for Posted Request";
			}
		}
	},

	// Enumerate and trigger all of the currently stored javascript events
	runEvents: function () {
		var iEvt, func, s = true;
		for (iEvt = 0; iEvt < jCore.form.events.length; iEvt += 1) {
			try {
				func = new Function(jCore.form.events[iEvt]);
				func();
			} catch (fE) {
				s = false;
				//alert(fE + "\n" + jCore.form.events[iEvt]);
			}
		}
		if (!s) {
			alert("Not all events succesfullys started");
		}
	},

	// Return an XmlHTTP object
	xmlObject: function () {
		var oXml = null;
		if (window.XMLHttpRequest) {
			oXml = new XMLHttpRequest();
		} else if (window.ActiveXObject) {
			try {
				oXml = new ActiveXObject("MSXML2.XMLHTTP");
			} catch (e) {
				try {
					oXml = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (ex) {
				}
			}
		}
		return oXml;
	}

};

// Returns a value indicating whether the current string matches the comparison string
String.prototype.compare = function (pVal) {
	"use strict";
	return (this.toLowerCase() === pVal.toLowerCase());
};

String.prototype.queryString = function (pName, pVal) {
	"use strict";
	var ret = this;
	ret += (ret.indexOf("?") > 0 ? "&" : "?") + pName + "=" + pVal;
	return ret;
};

// Returns the string convert to an RGBA vlaue
String.prototype.convertToRGBA = function () {
	"use strict";

	var val = this.replace("#", ""), red, green, blue, alpha;

	if (val.length === 3) {
		red = val.substring(0, 1);
		green = val.substring(1, 2);
		blue = val.substring(2, 3);
		alpha = "FF";
		red += red;
		blue += blue;
		green += green;
	} else if (val.length === 4) {
		alpha = val.substring(0, 1);
		red = val.substring(1, 2);
		green = val.substring(2, 3);
		blue = val.substring(3, 4);
		alpha += alpha;
		red += red;
		blue += blue;
		green += green;
	} else if (val.length === 6) {
		red = val.substring(0, 2);
		green = val.substring(2, 4);
		blue = val.substring(4, 6);
		alpha = "FF";
	} else if (val.length === 8) {
		alpha = val.substring(0, 2);
		red = val.substring(2, 4);
		green = val.substring(4, 6);
		blue = val.substring(6, 8);
	}

	return "rgba(" + parseInt(red, 16) + "," + parseInt(green, 16) + "," + parseInt(blue, 16) + "," + (parseInt(alpha, 16) / 255) + ")";
};

String.prototype.escape = function () {
	var retString = escape(this);

	retString = retString.replace(/ /g, "%20");

	return retString;
};

// Performs a C# string.Format operation on the string
String.prototype.format = function () {
	var a = arguments, aL = a.length, val = this;
	while (aL--) {
		val = val.replace("{" + aL + "}", a[aL]);
	}
	return val;
};

// Returns a value indicating whether the string is a valid numeric integer
String.prototype.isNumeric = function () {
	return (parseInt(this, 10).toString() !== "NaN");
};

String.prototype.startsWith = function (pCx) {
	return (this.indexOf(pCx) === 0);
};

// Retuns an integer value of the string
String.prototype.toInt = function () {
	return parseInt(this, 10);
};

// Retuns an unescaped version of the string
String.prototype.unescape = function () {
	var retString = unescape(this);

	retString = retString.replace(/%20/g, " ");

	return retString;
};
