/**@preserve jPaq - A fully customizable JavaScript/JScript library
 * http://jpaq.org/
 * Copyright (c) 2011 Christopher West
 * Licensed under the MIT license.
 *
 * Version: custom
 * Revised: July 21, 2011
 *
 */
(function(
	/*IF[Color Class,DOM Selector,Event Handling]*/
	privatize,
	/*ENDIF*/
	undefined
) {
// A reference to the global object.
var global = this;

// Reference to the document and the documentElement.
// NOTE:  If not referenced, Google Closure Compiler will remove these
//        definitions.
var doc = document, docElem = doc.documentElement;

/*IF[jPaq Class,Type Checking]*/
// Basically identical to Sizzle's isXML() function.
function isXML(elem) {
  return !!(elem = (elem ? elem.ownerDocument || elem : 0).documentElement) && elem.nodeName !== "HTML";
}
/*ENDIF*/

/*IF[!jPaq Class]*/
var jPaq = {};
/*ENDIF*/

/*IF[jPaq Class]*/
// Returns the text for the given element.  Idea stems from Sizzle's
// implementation of the contains selector.
function getText(elem) {
	function getChildrenText(childNodes) {
		for(var text = "", childNode, i = 0; childNode = childNodes[i]; i++) {
			// If this is a text node (3) or CDATA section node (4), add the node
			// value to the text.  Otherwise, as long as this is not a comment node
			// (8), recursively get the text for all of this node's children.
			childNode.nodeType === 3 || childNode.nodeType === 4
				? text += childNode.nodeValue
				: childNode.nodeType !== 8 && (text += getChildrenText(childNode.childNodes));
		}
		// Return the text that was found.
		return text;
	}

	return elem.textContent || elem.innerText || getChildrenText([elem]) || "";
}

// Either use a native function or create one.
// Loosely based on http://ejohn.org/blog/comparing-document-position/
var contains = docElem.contains
  ? function(elem1, elem2) {
    return elem1 !== elem2 && (elem1.contains ? elem1.contains(elem2) : true);
  }
  : docElem.compareDocumentPosition
    ? function(elem1, elem2) {
      return !!(elem1.compareDocumentPosition(elem2) & 16);
    }
    : function(elem1, elem2) {
    	// Loop through all of elem2's ancestor to see if elem1 is one of them.
    	while(elem2 = elem2.parentNode) {
    		if(elem1 === elem2) {
    			return true;
    		}
    	}
      return false;
    };

/*IF[Sizzle Selector]*/
/**@preserve Includes Sizzle CSS Selector Engine
 *  Copyright 2011, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
var Sizzle=function(){function y(a,b,c,d,f,e){for(var f=0,h=d.length;f<h;f++){var g=d[f];if(g){for(var i=!1,g=g[a];g;){if(g.sizcache===c){i=d[g.sizset];break}if(g.nodeType===1&&!e)g.sizcache=c,g.sizset=f;if(g.nodeName.toLowerCase()===b){i=g;break}g=g[a]}d[f]=i}}}function z(a,b,c,d,f,e){for(var f=0,h=d.length;f<h;f++){var g=d[f];if(g){for(var j=!1,g=g[a];g;){if(g.sizcache===c){j=d[g.sizset];break}if(g.nodeType===1){if(!e)g.sizcache=c,g.sizset=f;if(typeof b!=="string"){if(g===b){j=!0;break}}else if(i.filter(b,
[g]).length>0){j=g;break}}g=g[a]}d[f]=j}}}var w=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,x=0,A=Object.prototype.toString,t=!1,B=!0,p=/\\/g,u=/\W/;[0,0].sort(function(){B=!1;return 0});var i=function(a,b,c,d){var c=c||[],f=b=b||doc;if(b.nodeType!==1&&b.nodeType!==9)return[];if(!a||typeof a!=="string")return c;var e,h,g,l,s,m=!0,n=isXML(b),k=[],p=a;do if(w.exec(""),e=w.exec(p))if(p=e[3],k.push(e[1]),
e[2]){l=e[3];break}while(e);if(k.length>1&&D.exec(a))if(k.length===2&&j.relative[k[0]])h=C(k[0]+k[1],b);else for(h=j.relative[k[0]]?[b]:i(k.shift(),b);k.length;)a=k.shift(),j.relative[a]&&(a+=k.shift()),h=C(a,h);else if(!d&&k.length>1&&b.nodeType===9&&!n&&j.match.ID.test(k[0])&&!j.match.ID.test(k[k.length-1])&&(e=i.find(k.shift(),b,n),b=e.expr?i.filter(e.expr,e.set)[0]:e.set[0]),b){e=d?{expr:k.pop(),set:o(d)}:i.find(k.pop(),k.length===1&&(k[0]==="~"||k[0]==="+")&&b.parentNode?b.parentNode:b,n);h=
e.expr?i.filter(e.expr,e.set):e.set;for(k.length>0?g=o(h):m=!1;k.length;)e=s=k.pop(),j.relative[s]?e=k.pop():s="",e==null&&(e=b),j.relative[s](g,e,n)}else g=[];g||(g=h);g||i.error(s||a);if(A.call(g)==="[object Array]")if(m)if(b&&b.nodeType===1)for(a=0;g[a]!=null;a++)g[a]&&(g[a]===!0||g[a].nodeType===1&&contains(b,g[a]))&&c.push(h[a]);else for(a=0;g[a]!=null;a++)g[a]&&g[a].nodeType===1&&c.push(h[a]);else c.push.apply(c,g);else o(g,c);l&&(i(l,f,c,d),i.uniqueSort(c));return c};i.uniqueSort=function(a){if(v&&
(t=B,a.sort(v),t))for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1);return a};i.matches=function(a,b){return i(a,null,null,b)};i.matchesSelector=function(a,b){return i(b,null,null,[a]).length>0};i.find=function(a,b,c){var d;if(!a)return[];for(var f=0,e=j.order.length;f<e;f++){var h,g=j.order[f];if(h=j.leftMatch[g].exec(a)){var i=h[1];h.splice(1,1);if(i.substr(i.length-1)!=="\\"&&(h[1]=(h[1]||"").replace(p,""),d=j.find[g](h,b,c),d!=null)){a=a.replace(j.match[g],"");break}}}d||(d=typeof b.getElementsByTagName!==
"undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}};i.filter=function(a,b,c,d){for(var f,e,h=a,g=[],l=b,o=b&&b[0]&&isXML(b[0]);a&&b.length;){for(var m in j.filter)if((f=j.leftMatch[m].exec(a))!=null&&f[2]){var n,k,p=j.filter[m];k=f[1];e=!1;f.splice(1,1);if(k.substr(k.length-1)!=="\\"){l===g&&(g=[]);if(j.preFilter[m])if(f=j.preFilter[m](f,l,c,g,d,o)){if(f===!0)continue}else e=n=!0;if(f)for(var q=0;(k=l[q])!=null;q++)if(k){n=p(k,f,q,l);var r=d^!!n;c&&n!=null?r?e=!0:l[q]=!1:r&&(g.push(k),
e=!0)}if(n!==void 0){c||(l=g);a=a.replace(j.match[m],"");if(!e)return[];break}}}if(a===h)if(e==null)i.error(a);else break;h=a}return l};i.error=function(a){throw"Syntax error, unrecognized expression: "+a;};var j=i.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=
typeof b==="string",d=c&&!u.test(b),c=c&&!d;d&&(b=b.toLowerCase());for(var d=0,f=a.length,e;d<f;d++)if(e=a[d]){for(;(e=e.previousSibling)&&e.nodeType!==1;);a[d]=c||e&&e.nodeName.toLowerCase()===b?e||!1:e===b}c&&i.filter(b,a,!0)},">":function(a,b){var c,d=typeof b==="string",f=0,e=a.length;if(d&&!u.test(b))for(b=b.toLowerCase();f<e;f++){if(c=a[f])c=c.parentNode,a[f]=c.nodeName.toLowerCase()===b?c:!1}else{for(;f<e;f++)(c=a[f])&&(a[f]=d?c.parentNode:c.parentNode===b);d&&i.filter(b,a,!0)}},"":function(a,
b,c){var d,f=x++,e=z;typeof b==="string"&&!u.test(b)&&(d=b=b.toLowerCase(),e=y);e("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=x++,e=z;typeof b==="string"&&!u.test(b)&&(d=b=b.toLowerCase(),e=y);e("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!=="undefined"&&!c)return(a=b.getElementById(a[1]))&&a.parentNode?[a]:[]},NAME:function(a,b){if(typeof b.getElementsByName!=="undefined"){for(var c=[],d=b.getElementsByName(a[1]),f=0,e=d.length;f<e;f++)d[f].getAttribute("name")===
a[1]&&c.push(d[f]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!=="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,f,e){a=" "+a[1].replace(p,"")+" ";if(e)return a;for(var e=0,h;(h=b[e])!=null;e++)h&&(f^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[e]=!1));return!1},ID:function(a){return a[1].replace(p,"")},TAG:function(a){return a[1].replace(p,"").toLowerCase()},CHILD:function(a){if(a[1]===
"nth"){a[2]||i.error(a[0]);a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0;a[3]=b[3]-0}else a[2]&&i.error(a[0]);a[0]=x++;return a},ATTR:function(a,b,c,d,f,e){b=a[1]=a[1].replace(p,"");!e&&j.attrMap[b]&&(a[1]=j.attrMap[b]);a[4]=(a[4]||a[5]||"").replace(p,"");a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(a,b,c,d,f){if(a[1]==="not")if((w.exec(a[3])||"").length>1||
/^\w/.test(a[3]))a[3]=i(a[3],null,null,b);else return a=i.filter(a[3],b,c,1^f),c||d.push.apply(d,a),!1;else if(j.match.POS.test(a[0])||j.match.CHILD.test(a[0]))return!0;return a},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},
has:function(a,b,c){return!!i(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),a=a.type;return"text"===a&&(b===a||b===null)},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===
a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,
b,c,d){var f=b[1],e=j.filters[f];if(e)return e(a,c,b,d);else if(f==="contains")return getText(a).indexOf(b[3])>=0;else if(f==="not"){b=b[3];c=0;for(d=b.length;c<d;c++)if(b[c]===a)return!1;return!0}else i.error(f)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case "only":case "first":for(;d=d.previousSibling;)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case "last":for(;d=d.nextSibling;)if(d.nodeType===1)return!1;return!0;case "nth":var c=b[2],f=b[3];
if(c===1&&f===0)return!0;var e=b[0],h=a.parentNode;if(h&&(h.sizcache!==e||!a.nodeIndex)){for(var g=0,d=h.firstChild;d;d=d.nextSibling)if(d.nodeType===1)d.nodeIndex=++g;h.sizcache=e}d=a.nodeIndex-f;return c===0?d===0:d%c===0&&d/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],c=
j.attrHandle[c]?j.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),d=c+"",f=b[2],e=b[4];return c==null?f==="!=":f==="="?d===e:f==="*="?d.indexOf(e)>=0:f==="~="?(" "+d+" ").indexOf(e)>=0:!e?d&&c!==!1:f==="!="?d!==e:f==="^="?d.indexOf(e)===0:f==="$="?d.substr(d.length-e.length)===e:f==="|="?d===e||d.substr(0,e.length+1)===e+"-":!1},POS:function(a,b,c,d){var f=j.setFilters[b[2]];if(f)return f(a,c,b,d)}}},D=j.match.POS,E=function(a,b){return"\\"+(b-0+1)},q;for(q in j.match)j.match[q]=RegExp(j.match[q].source+
/(?![^\[]*\])(?![^\(]*\))/.source),j.leftMatch[q]=RegExp(/(^(?:.|\r|\n)*?)/.source+j.match[q].source.replace(/\\(\d+)/g,E));var o=function(a,b){a=Array.prototype.slice.call(a,0);if(b)return b.push.apply(b,a),b;return a};try{Array.prototype.slice.call(docElem.childNodes,0)}catch(F){o=function(a,b){var c=0,d=b||[];if(A.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);
return d}}var v,r;docElem.compareDocumentPosition?v=function(a,b){if(a===b)return t=!0,0;if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(v=function(a,b){var c,d,f=[],e=[];c=a.parentNode;d=b.parentNode;var h=c;if(a===b)return t=!0,0;else if(c===d)return r(a,b);else if(c){if(!d)return 1}else return-1;for(;h;)f.unshift(h),h=h.parentNode;for(h=d;h;)e.unshift(h),h=h.parentNode;c=f.length;d=e.length;
for(h=0;h<c&&h<d;h++)if(f[h]!==e[h])return r(f[h],e[h]);return h===c?r(a,e[h],-1):r(f[h],b,1)},r=function(a,b,c){if(a===b)return c;for(a=a.nextSibling;a;){if(a===b)return-1;a=a.nextSibling}return 1});(function(){var a=doc.createElement("div"),b="script"+(new Date).getTime(),c=docElem;a.innerHTML="<a name='"+b+"'/>";c.insertBefore(a,
c.firstChild);if(doc.getElementById(b))j.find.ID=function(a,b,c){if(typeof b.getElementById!=="undefined"&&!c)return(b=b.getElementById(a[1]))?b.id===a[1]||typeof b.getAttributeNode!=="undefined"&&b.getAttributeNode("id").nodeValue===a[1]?[b]:void 0:[]},j.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b};c.removeChild(a);c=a=null})();(function(){var a=doc.createElement("div");a.appendChild(doc.createComment(""));
if(a.getElementsByTagName("*").length>0)j.find.TAG=function(a,c){var d=c.getElementsByTagName(a[1]);if(a[1]==="*"){for(var f=[],e=0;d[e];e++)d[e].nodeType===1&&f.push(d[e]);d=f}return d};a.innerHTML="<a href='#'></a>";if(a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#")j.attrHandle.href=function(a){return a.getAttribute("href",2)};a=null})();doc.querySelectorAll&&function(){var a=i,b=doc.createElement("div");b.innerHTML="<p class='TEST'></p>";
if(!(b.querySelectorAll&&b.querySelectorAll(".TEST").length===0)){i=function(b,c,e,h){c=c||doc;if(!h&&!isXML(c)){var g=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(g&&(c.nodeType===1||c.nodeType===9))if(g[1])return o(c.getElementsByTagName(b),e);else if(g[2]&&j.find.CLASS&&c.getElementsByClassName)return o(c.getElementsByClassName(g[2]),e);if(c.nodeType===9){if(b==="body"&&c.body)return o([c.body],e);else if(g&&g[3]){var l=c.getElementById(g[3]);if(l&&l.parentNode){if(l.id===g[3])return o([l],
e)}else return o([],e)}try{return o(c.querySelectorAll(b),e)}catch(p){}}else if(c.nodeType===1&&c.nodeName.toLowerCase()!=="object"){var g=c,m=(l=c.getAttribute("id"))||"__sizzle__",n=c.parentNode,k=/^\s*[+~]/.test(b);l?m=m.replace(/'/g,"\\$&"):c.setAttribute("id",m);if(k&&n)c=c.parentNode;try{if(!k||n)return o(c.querySelectorAll("[id='"+m+"'] "+b),e)}catch(q){}finally{l||g.removeAttribute("id")}}}return a(b,c,e,h)};for(var c in a)i[c]=a[c];b=null}}();(function(){var a=docElem,b=
a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var c=!b.call(doc.createElement("div"),"div"),d=!1;try{b.call(docElem,"[test!='']:sizzle")}catch(f){d=!0}i.matchesSelector=function(a,f){f=f.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!isXML(a))try{if(d||!j.match.PSEUDO.test(f)&&!/!=/.test(f)){var g=b.call(a,f);if(g||!c||a.document&&a.document.nodeType!==11)return g}}catch(l){}return i(f,null,null,[a]).length>0}}})();(function(){var a=
doc.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0&&(a.lastChild.className="e",a.getElementsByClassName("e").length!==1))j.order.splice(1,0,"CLASS"),j.find.CLASS=function(a,c,d){if(typeof c.getElementsByClassName!=="undefined"&&!d)return c.getElementsByClassName(a[1])},a=null})();
var C=function(a,b){for(var c,d=[],f="",e=b.nodeType?[b]:b;c=j.match.PSEUDO.exec(a);)f+=c[0],a=a.replace(j.match.PSEUDO,"");a=j.relative[a]?a+"*":a;c=0;for(var h=e.length;c<h;c++)i(a,e[c],d);return i.filter(f,d)};return i}();
/*END OF SIZZLE DEFINITION*/
/*ENDIF*/

// Define the jPaq function.
var doExternalIndexing = true, jPaq = function(selector, context) {
  // If this is a recursive call, return this blank jPaq object.  This forces
  // the jPaq function to always act as a constructor.
  if(selector === privatize) {
    return this;
  }
  
  /*IF[jPaq.ready]*/
  if(isFunction(selector)) {
  	return jPaq.ready(selector);
  }
  /*ENDIF*/

  // If this is not a jPaq object, turn it into one.
  var me = !(this instanceof jPaq) ? new jPaq(privatize) : this, elems;
  
  privatize(me, {
    $elements : elems = (
    	jPaq.isArray(selector)
				? selector
        /*IF[Sizzle Selector]*/
				: jPaq.isString(selector)
						? jPaq.isArray(context)
							? Sizzle.matches(selector, context)
							: Sizzle(selector, context)
        /*ENDIF*/
						: [selector]
		),
    $args : arguments
  });
  
  me.length = elems.length;
  if(me.indexed = doExternalIndexing) {
		for(var i = elems.length - 1; i >= 0; i--) {
			me[i] = elems[i];
		}
	}
	
  // Return the instance of the jPaq object.
  return me;
};

function dashToCamelCase(str) {
	return str.replace(/-(\w)/g, function(a, b) {
		return b.toUpperCase();
	});
}

function camelCaseToDash(str) {
	return str.replace(/[A-Z]/g, function(a) {
		return "-" + a.toLowerCase();
	});
}

function queryDOM(selector, context) {
  return new jPaq(selector, context);
}

function strToClassNames(className) {
	return (" " + (className.match(/[^\s\u00A0]+/g) || []).join(" , ") + " ").split(",");
}

// Internal jPaq each function.
function jPaqEach(jPaqObj, fnCallback, actLikeMap) {
	for(var arrReturns = [], elems = jPaqObj._(privatize).$elements, i = 0, len = elems.length; i < len; i++) {
		arrReturns.push(fnCallback.call(jPaqObj, elems[i], i));
	}
  return actLikeMap ? arrReturns : jPaqObj;
}
/*ENDIF*/

// Can be used to either get all of the keys for an object or just the keys that
// correspond to property that were defined specifically for that object.
var keysOf = (function() {
	// This is an IE fix.
	var unenumerableKeys = "constructor,hasOwnProperty,isPrototypeOf,prototypeIsEnumerable,toLocaleString,toString,valueOf".split(",");
	for(var key, o = {}, i = 0; key = unenumerableKeys[i]; i++) {
		o[key] = i;
		for(key in o) {
			unenumerableKeys.splice(i--, 1);
			delete o[key];
		}
	}
	
	// Definition for hasOwnerProperty() because it may be overwritten in the object.
	var hasOwnProperty = Object.prototype.hasOwnProperty;

	// The definition for keysOf().
	return function(obj, showAll) {
		var keys = unenumerableKeys.slice(0);
		for(var key in obj) {
			keys.push(key);
		}
		for(var ret = [], i = 0; key = keys[i]; i++) {
			if(showAll || hasOwnProperty.call(obj, key)) {
				ret.push(key);
			}
		}
		return ret;
	};
})();

/*IF[Object.keys]*/
Object.keys = Object.keys || function(obj) {
	return keysOf(obj, 0);
};
/*ENDIF*/

// Takes the properties of objExtras and attaches them to objToExtend.  If
// fnFilter is specified, it should return a value which will be coerced to a
// boolean to determine whether or not the property will be transferred.
function extend(objToExtend, objExtras, fnFilter, copyAll) {
	// If fnFilter wasn't specified...
  if(typeof fnFilter != "function") {
    // If copyAll's value was put into fnFilter, use it as copyAll.
    if(fnFilter !== undefined) {
    	copyAll = fnFilter;
    }
    
    // Define a default for fnFilter since it wasn't defined.
    fnFilter = function(){return true;};
  }
  
  // Get the keys for the properties that will be copied to objToExtend.
	var keys = keysOf(objExtras, copyAll);
	
	// Copy over the properties from objExtras to objToExtend.
	for(var i = 0; key = keys[i]; i++) {
    if(fnFilter(objExtras[key], key, objToExtend[key], objToExtend)) {
      objToExtend[key] = objExtras[key];
		}
	}
  return objToExtend;
}

/*IF[Event Handling]*/
var expando = (privatize.expando = "__jPaqExpando" + Math.random() + "__"),
	expandoValue = 0;

// Anonymous function to deal with internal Event handling definitions.
// Anonymous function used to avoid over-crowding of namespace for code
// minification.
(function() {
	var events = {};
	
	function wrapExtras(elem, type, fnHandler) {
		var realType = type == "mouseenter"
			? "mouseover"
			: type == "mouseleave"
				? "mouseout"
				: 0;

		// Returns the augmented handler and the real event type.
		return [
      // The type of the event that will be fired off.
			realType || type,
      // The new definition for fnHandler which includes an augmented version of
      // the event object that will be passed in as the first parameter.
      function(e) {
        e = e || global.event;
        if(!e.jPaqType != (e.jPaqType == type)) {
          // Make e a jPaqEvent.
          // Defined to allow mouseenter and mouseleave to be shown.
          e = jPaq.Event(e, type);
          
          // Define the currentTarget if it wasn't already defined.
          e.currentTarget = e.currentTarget || elem;
        
          // Don't execute the handler if the type was originally mouseenter or
          // mouseleave and the related target is this element or is inside of
          // this element.
          if(!(realType && (elem == e.relatedTarget || (e.relatedTarget && contains(elem, e.relatedTarget))))) {
            // Returns the call to the handler.
            var ret = fnHandler.call(this, e);
            if(e.cancelable && (e.isPreventDefault() || ret === false)) {
              return false;
            }
          }
        }
      }
		];
	}

	if(global.addEventListener) {
		var addEventTo = function(elem, type, handler) {
      var newHandler = wrapExtras(elem, type, function(e) {
        return handler.call(elem, e);
      });
			elem.addEventListener(newHandler[0], newHandler[1], false);
			return newHandler[1];
		};
		var removeEventFrom = function(elem, type, modifiedHandler) {
			elem.removeEventListener(type, modifiedHandler, false);
		};
	}
	else if(global.attachEvent) {
		addEventTo = function(elem, type, handler) {
      var newHandler = wrapExtras(elem, type, function(e) {
        return handler.call(elem, e);
      });
			elem.attachEvent("on" + newHandler[0], newHandler[1]);
			return newHandler[1];
		};
		removeEventFrom = function(elem, type, modifiedHandler) {
			elem.detachEvent("on" + type, modifiedHandler);
		};
	}
	
	function removeEventHelper(arrEvents, elem, type, handler) {
    type = type == "mouseenter"
      ? "mouseover"
      : type == "mouseleave"
        ? "mouseout"
        : type;
		for(var i = 0, len = arrEvents.length; i < len; i++) {
			if(!handler || arrEvents[i].a === handler) {
				removeEventFrom(elem, type, arrEvents[i].b);
				arrEvents.splice(i, 1);
				if(handler)
					return 1;
			}
		}
	};

	var reBubbles = /^(abort|error|select|change|submit|reset|resize|scroll|mouse(down|up|over|move|out)|click|dblclick)$/;
	var reCancelable = /^(click|mouse(down|up|over|enter|leave|out)|submit)$/;
	var toFromElemHash = {mouseenter:0,mouseover:0,mouseleave:1,mouseout:1};

	extend(jPaq, {
		// Derived from http://www.quirksmode.org/js/events_properties.html.
		Event : function(e, type) {
			// If this is a recursive call, return this blank jPaqEvent object.  This
			// forces the jPaq function to always act as a constructor.
			if(e === privatize) {
				return this;
			}
			
			var original = e;
			
			// Copy over the values from the real event object to this jPaqEvent.
			e = extend((this instanceof jPaq.Event) ? this : new jPaq.Event(privatize), e, function(newItem) {
				return !isFunction(newItem);
			}, 1/*Firefox fix for grabbing target and other properties that are prototypal values*/);
			
			// Add reference to original event.
			e.originalEvent = original;
			
			// Get the real target.
			var target = e.target || e.srcElement || document;
			if(target.nodeType == 3) {
				target = target.parentNode;
			}
			e.target = target;
				
			// If the pageX is not given as a number, but the clientX is, try to fix
			// the pageX and pageY.
			// Coordinates telling where the event fired off.
			if(isNaN(e.pageX)) {
			  if(isNaN(e.clientX)) {
			    e.pageX = 0;
			    e.pageY = 0;
			  }
			  else {
          var eDoc = target.ownerDocument || doc,
            body = eDoc.body,
            docElem = eDoc.documentElement;
          e.pageX = e.clientX
            + (docElem.scrollLeft || (body && body.scrollLeft) || 0)
            - (docElem.clientLeft || (body && body.clientLeft) || 0);
          e.pageY = e.clientY
            + (docElem.scrollTop || (body && body.scrollTop) || 0)
            - (docElem.clientTop || (body && body.clientTop) || 0);
        }
      }
			
			// Make sure that non-Macs relate ctrlKey to metaKey if it is doesn't e.
			e.metaKey = e.metaKey == null ? e.ctrlKey : e.metaKey;

			// If the type is different, change it.
			e.type = type = type || e.type;
			// Determine whether or not the event can bubble up.
			e.bubbles = e.bubbles || reBubbles.test(type);
			// Determine whether or not the event is cancelable.
			e.cancelable = e.cancelable || reCancelable.test(type);
			// Set the timestamp if it isn't already attached.
			e.timeStamp = e.timeStamp || +(new Date);
			// Get the relatedTarget.
			e.relatedTarget = e.relatedTarget || [e.fromElement, e.toElement][((toFromElemHash[type] + 1) || 3) - 1];
			// Make sure which has either the keyCode or the button code.
			e.which = e.which || e.charCode || e.keyCode || (
			  e.button & 1
			    ? 1
			    : e.button & 2
			      ? 3
			      : ((e.button & 4) >> 1)
			);
			
			// Set up the private variables.
			privatize(e, {
				e : original,	// The actual event object.
				s : false,		// Indicates that stopPropagation() was called.
				p : false			// Indicates that preventDefault() was called.
			});
			
			return e;
		},
		addEvent : function(elem, type, handler) {
			var index = elem[expando] == null
				? (elem[expando] = ++expandoValue)
				: elem[expando];
			var eventObj = events[index]
				? events[index]
				: (events[index] = {});
			(eventObj[type]
				? eventObj[type]
				: (eventObj[type] = [])
      ).push({
				a : handler,
				b : addEventTo(elem, type, handler)
			});
		},
		removeEvent : function(elem, type, handler) {
			var index = elem[expando];
			if(index == null)
				return;
			var eventObj = events[index];
			if(!eventObj) {
				return;
			}
		
			if(type && eventObj[type]) {
				removeEventHelper(eventObj[type], elem, type, handler);
			}
			else {
				for(type in eventObj) {
					removeEventHelper(eventObj[type], elem, type, handler);
				}
			}
		},
		getEventsFor : function(elem, type) {
			var index = elem[expando];
			if(index + 1) {
				var eventObj = events[index];
				if(eventObj) {
          var hashReturn = {};
					if(!type) {
						for(type in eventObj) {
							hashReturn[type] = eventObj[type].slice(0);
            }
					}
					else if(eventObj[type]) {
						hashReturn[type] = eventObj[type].slice(0);
          }
          for(var type in hashReturn) {
            for(var arr = hashReturn[type], i = arr.length - 1; i >= 0; i--) {
              arr[i] = arr[i].a;
            }
          }
          return hashReturn;
				}
			}
			return {};
		},
		triggerEvent : function(elem, type) {
      // If this is a mouseenter or a mouseleave event, make sure the event
      // doesn't bubble up.
      var diffType = type == "mouseenter"
        ? "mouseover"
        : type == "mouseleave"
          ? "mouseout"
          : 0;
					
			var bubbles = reBubbles.test(type);
			var cancelable = reCancelable.test(type);
      
			if(doc.createEvent) {
        // Create the event.
				var e = doc.createEvent('HTMLEvents');
				e.initEvent(diffType || type, bubbles, cancelable);
        e.jPaqType = type;
        e.cancelable = cancelable;
        // Fire the event.
				elem.dispatchEvent(e);
			}
			else if(doc.createEventObject) {
        // Create the event.
        var e = doc.createEventObject();
        e.jPaqType = type;
        e.cancelBubble = bubbles;
        e.cancelable = cancelable;
        e.currentTarget = elem;
        // Fire the event.
				elem.fireEvent('on' + (diffType || type), e);
			}
		},
		triggerHandler : function(elem, type) {
			var hashHandlers = jPaq.getEventsFor(elem, type);
      for(type in hashHandlers) {
        var handlers = hashHandlers[type];
        for(var ret, rets = [], i = 0, len = handlers.length; i < len; i++) {
          rets.push(ret = handlers[i].call(elem, jPaq.Event({
            target : elem
          }, type)));
          if(ret === false) {
            break;
          }
        }
      }
			return rets;
		}
	});
	
	// Establish the prototypal function for a jPaqEvent.
	extend(jPaq.Event.prototype, {
		stopPropagation : function() {
			var pData = this._(privatize);
			if(pData.e.stopPropagation) {
				pData.e.stopPropagation();
			}
			else {
				pData.e.cancelBubble = true;
			}
			pData.s = true;
		},
		preventDefault : function() {
			var pData = this._(privatize);
			if(pData.e.preventDefault) {
				pData.e.preventDefault();
			}
			pData.p = true;
		},
		isStopPropagation : function() {
			return this._(privatize).s;
		},
		isPreventDefault : function() {
			return this._(privatize).p;
		}
	});
})();
// End if Event Handling section.
/*ENDIF*/

/*IF[Type Checking]*/
// Define all of the type checking functions.
var typeOf = (function() {
  var types = "null undefined Array Boolean Date Error Function Number Object RegExp String".split(" ");
  var toString = ({}).toString;

  // Creates a hash table to properly determine the type of the
  // parameter passed into the jPaq.typeOf() function.
  // Defines isNull(), isUndefined(), isArray(), isBoolean(), isDate(),
  // isError(), isFunction(), isNumber(), isObject(), isRegExp(), and
  // isString() and attaches them to the jPaq object.
  for(var i = types.length; --i; ) {
    (function(type) {
      if(i > 1) {
        types["[object " + type + "]"] = type;
      }
      jPaq["is" + type.charAt(0).toUpperCase() + type.slice(1)] = function(arg) {
        return typeOf(arg) == type;
      };
    })(types[i]);
  }
  i = jPaq.isObject;

  // A persistent reference to the isNumber() function.
  var isNumber = jPaq.isNumber;
  
  // Augment the jPaq object with the isObject(), isFloat(), isInt() and
  // typeOf() functions and then return a reference to the typeOf() function so
  // that it is easily accessible to the rest of the code.
  return extend(jPaq, {
		// Augment the definition for isObject().
		isObject : function(arg, allowAnyType) {
			return allowAnyType ? arg != null : i(arg);
		},
		
		isElement : function(obj) {
			return !!obj && obj.nodeType === 1;
		},
		
		isFloat : function(num) {
			/// <summary>
			///   Indicates whether or not the argument is an integer.
			/// </summary>
			// isFinite() is used to account for NaN and Infinity.
			return isFinite(num) && isNumber(num) && num != parseInt(num.toString(16), 16);
		},
		
		isInt : function(num) {
			/// <summary>
			///   Indicates whether or not the argument is an integer.
			/// </summary>
			return isNumber(num) && num == parseInt(num.toString(16), 16);
		},
		
		isXML : isXML,
		
		// Defines the typeOf() function on the local and jPaq level.
		// Local variable also declared to prevent errors that would occur
		// from externally redefining typeOf().
		typeOf : function(arg) {
			/// <summary>
			///   Determines the type of the element that is passed.
			/// </summary>
			/// <param name="obj" type="Object">
			///   The object whose type will be returned as a string.
			/// </param>
			/// <returns type="String">
			///   Returns the type of parameter that is passed as a lowercased string.
			/// </returns>
			return arg == null
				? arg + ""
				: types[toString.call(arg)]
					|| (
						/*IF[DOM Selector]*/
						arg instanceof jPaq
							? "jPaq"
							:
						/*ENDIF*/
						/*IF[Color Class]*/
						arg instanceof Color
							? "Color"
							:
						/*ENDIF*/
						/*IF[Event Handling]*/
						arg instanceof jPaq.Event
							? "jPaqEvent"
							:
						/*ENDIF*/
								"Object"
						);
		}		
  }).typeOf;
})();

var isFunction = jPaq.isFunction;

/*IF[Array.isArray]*/
Array.isArray = Array.isArray || jPaq.isArray;
/*ENDIF*/

// End of the type checking functions.
/*ENDIF*/


/*IF[AJAX]*/
// Definition came from http://www.quirksmode.org/js/xmlhttp.html
var xhrMakers = [
  function(){ return new XMLHttpRequest(); },
  function(){ return new ActiveXObject("Msxml2.XMLHTTP"); },
  function(){ return new ActiveXObject("Msxml3.XMLHTTP"); },
  function(){ return new ActiveXObject("Microsoft.XMLHTTP"); }
];
/*ENDIF*/

/*IF[jPaq Class,jPaq.ready()]*/
var old$ = global.$;
$ = jPaq;
/*ENDIF*/

/*IF[$id]*/
var old$id = global.$id;
$id = function(id, encapsulate) {
	var elem = doc.getElementById(id);
	return ((arguments.length < 2) || encapsulate)
		? new jPaq(elem)
		: elem;
};
/*ENDIF*/

// Extend the jPaq function.
extend(jPaq, {
  /*IF[jPaq.parseArray(),DOM Selector,Function.prototype.curry()]*/
	parseArray : parseArray,
	/*ENDIF*/

  /*IF[AJAX]*/
  xhr : function() {
    for(var triesLeft = xhrMakers.length; triesLeft > 0; triesLeft--) {
      try {
        return xhrMakers[0]();
      }
      catch(e) {
        xhrMakers.push(xhrMakers.shift());
      }
    }
  },
  
  // Idea came from http://www.quirksmode.org/js/xmlhttp.html
  request : function(url, fnCallback, options) {
    options = options || {};
    var xhr = options.xhr || jPaq.xhr(),
        postData = options.postData,
        onReadyStateChange = options.onReadyStateChange,
        onFailure = options.onFailure,
        originalState = xhr.readyState;
    
    // If the XMLHTTPRequest object can't be created, false is returned.
    if(!xhr) {
      return false;
    }
    
    if(postData) {
      xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
    }
    xhr.onreadystatechange = function () {
      if(onReadyStateChange) {
        onReadyStateChange(xhr);
      }
      if(xhr.readyState == 4) {
        if(xhr.status == 200 || xhr.status == 304) {
          fnCallback(xhr);
        }
        else if(onFailure) {
          onFailure(xhr);
        }
      }
    }
    xhr.open((postData) ? "POST" : "GET", url, options.async != null ? options.async : true);
    xhr.setRequestHeader('User-Agent','XMLHTTP/1.0');
    if(originalState == 4 || xhr.readyState != 4) {
      xhr.send(postData);
    }
    return xhr;
  },
  /*ENDIF*/
  
  /*IF[jPaq Class]*/
  queryDOM : queryDOM,
  
  autoIndex : function(autoIndexObjects) {
  	doExternalIndexing = !!autoIndexObjects;
  },
  
  prototype : {
    offset : function() {
      var elem = this._(privatize).$elements[0];
      for(var ret = {left:0,top:0}; elem.offsetParent; elem = elem.offsetParent) {
				ret.left += elem.offsetLeft;
				ret.top += elem.offsetTop;
			}
			return ret;
    },
    
    /*IF[Event Handling]*/
    bind : function(evtName, handler) {
			return jPaqEach(this, function(elem) {
				jPaq.addEvent(elem, evtName, handler);
			});
		},
		unbind : function(evtName, handler) {
			return jPaqEach(this, function(elem) {
				jPaq.removeEvent(elem, evtName, handler);
			});
		},
		trigger : function(evtName) {
			return jPaqEach(this, function(elem) {
				return jPaq.triggerEvent(elem, evtName);
			}, true);
		},
		triggerHandler : function(evtName) {
			return jPaqEach(this, function(elem) {
				jPaq.triggerHandler(elem, evtName);
			});
		},
		hover : function(fnIn, fnOut) {
			return this.mouseenter(fnIn).mouseleave(fnOut || fnIn);
		},
    /*ENDIF*/
    
    get : function(index) {
      var elems = this._(privatize).$elements;
      return index == null
        ? elems.slice(0)
        : elems.slice(index, 1)[0];
    },
    slice : function(start, end) {
      return this._(privatize).$elements.slice(start, end);
    },
    size : function() {
      return this._(privatize).$elements.length;
    },
    refresh : function() {
      var pData = this._(privatize), newMe = jPaq.apply(null, pData.$args);
      pData.$elements = newMe._(privatize).$elements;
      return this;
    },
		filter : function(aFilter) {
      var pData = this._(privatize), arr = pData.$elements;
      if(isFunction(aFilter)) {
        for(var i = 0, len = arr.length; i < len; i++) {
          if(!aFilter.call(this, arr[i], i)) {
            arr.splice(i--, 1);
            len--;
          }
        }
      }
      else {
        pData.$elements = Sizzle.matches(aFilter, arr);
      }
      return this;
		},
		each : function(fnCallback) {
			for(var arr = this._(privatize).$elements, i = 0, len = arr.length; i < len; i++) {
				fnCallback.call(arr[i], i, this);
			}
			return this;
		},
		addClass : function(className, maxCount) {
			maxCount = maxCount || 1;
			var classNames = strToClassNames(className);
			return jPaqEach(this, function(elem) {
				var elemClassName = elem.className;
				for(var i = classNames.length - 1; i >= 0; i--) {
					if(maxCount >= elemClassName.split(classNames[i]).length) {
						elemClassName += " " + classNames[i];
					}
				}
				elem.className = (elemClassName.match(/[^\s\u00A0]+/g) || []).join(" ");
			});
		},
		removeClass : function(className, deleteLimit) {
			deleteLimit = deleteLimit || Infinity;
			var classNames = strToClassNames(className);
			return jPaqEach(this, function(elem) {
				var elemClassName = " " + elem.className + " ";
				for(var i = classNames.length - 1; i >= 0; i--) {
					var aClassName = classNames[i];
					for(var oldClassName, iter = 0; iter < deleteLimit && elemClassName != oldClassName; iter++) {
						oldClassName = elemClassName;
						elemClassName = elemClassName.replace(aClassName, " ");
					}
				}
				elem.className = (elemClassName.match(/[^\s\u00A0]+/g) || []).join(" ");
			});
		},
		hasClass : function(className) {
			var arr = strToClassNames(className), elem = this._(privatize).$elements[0];
			var elemClassName = " " + elem.className.split(/[\s\u00A0]/g).join(" ") + " ";
			for(var i = arr.length - 1; i >= 0; i--) {
				if(elemClassName.indexOf(arr[i]) < 0) {
					return false;
				}
			}
			return true;
		},
		contains : function(elem) {
			return contains(this._(privatize).$elements[0], elem);
		}
  },
	/*ENDIF*/

	/*IF[URI Functions,jPaq.GET]*/
	escape : function(str, forApp) {
		str = jPaq.encodeURIComponent(str);
		if(forApp) {
			str = str.replace(/%20/g, "+");
		}
		return str;
	},
	unescape : function(str, forApp){
		return decodeURIComponent(str.replace(forApp ? /\+/g : "", forApp ? "%20" : ""));
	},  
  encodeURI : function(str) {
    return str.replace(/[^\[\]]+/g, function(a){return encodeURI(a);});
  },
  encodeURIComponent : function(str) {
    return encodeURIComponent(str)
      .replace(/!/g, '%21')
      .replace(/'/g, '%27')
      .replace(/\(/g, '%28')
      .replace(/\)/g, '%29')
      .replace(/\*/g, '%2A');
  },
  /*ENDIF*/
  
  /*IF[jPaq.preloadImages()]*/
  preloadImages : function(arrImagePaths, fnCallback) {
    var loadsLeft = (arrImagePaths = arrImagePaths.slice(0)).length,
      successes = [],
      failures = [];

    function imageOn(arr) {
      arr.push(this);
      if(!(--loadsLeft)) {
        fnCallback(successes, failures, arrImagePaths);
      }
    }
    
    function imageOnBad() {
    	imageOn.call(this, failures);
    }
    
    for(var path, i = 0; (path = arrImagePaths[i]) != undefined; i++) {
      extend(new Image(), {
      	src : path,
      	onload : function() {
					imageOn.call(this, successes);
				},
				onabort : imageOnBad,
				onerror : imageOnBad
			});
    }
  },
  /*ENDIF*/
  
  /*IF[jPaq.round()]*/
  round : (function() {
    var reRoundPosUp = /^[5-9]/,
      reRoundNegDown = /^(5.*[1-9]|[6-9])/;
    return function(num, decimals) {
      // If decimals is zero or not a number, return num as a string after using
      // the default Math.round() function.
      if(!(decimals = decimals << 0))
        return Math.round(+num || 0) + "";
      
      // Make sure num is actually a number and then turn it into a string.
      num = (+num || 0) + "";
      
      // If there is no decimal point in num, append ".0".
      if(num.indexOf(".") < 0)
        num += ".0";
      
      // Split num into two or more parts based on the decimal point.
      // If more than one decimal point is found, the digits after the second
      // one will not be considered.
      num = num.split(".");
      
      // If decimals is positive and yet there are not enough digits after the
      // decimal point, add the necessary amount of zeroes.
      if(decimals > 0 && num[1].length < decimals)
        num[1] += (new Array(1 + decimals - num[1].length)).join("0");
      // If decimals is negative and yet there are not enough digits before the
      // decimal point, prepend the necessary amount of zeroes.
      else if(decimals < 0 && num[0].length < -decimals)
        num[0] = (new Array(1 - decimals - num[0].length)).join("0") + num[0];
      
      // Represents the sign of the digit that needs to be added if rounding
      // must occur.
      num[3] = /^-/.test(num[0]) ? -1 : 1;
      
      // If the digits to the left of the decimal point need to be rounded, do it.
      if(decimals < 0) {
        return ((
          (num[0].slice(0, decimals) << 0)
          + num[3] * ((num[3] < 0 ?  reRoundNegDown : reRoundPosUp).test(num[0].substring(num[0].length + decimals)) << 0))
                + (new Array(1 - decimals)).join("0")).replace(/^0+(?=0$|[1-9])/, "");
        
      }
      // If the digits to the right of the decimal point need to be rounded...
      else {
        // If the number must be rounded, change the necessary digit(s).
        if((num[3] < 0 ? reRoundNegDown : reRoundPosUp).test(num[1].substring(decimals))) {
          num[2] = ((num[4] = num[1].substring(0, decimals)) << 0) + 1 + "";
          if(num[2].length > num[4].length) {
            num[0] = (num[0] << 0) + num[3];
            num[2] = num[2].substring(1);
          }
          num[1] = num[1].substring(0, decimals - num[2].length) + num[2];
        }
        // The string version of this, with all of the extra digits truncated.
        // Also make sure -0 is not returned.
        return (num[0] + "." + num[1].substring(0, decimals)).replace(/^-(?=0(\.0+)?$)/, "");
      }
    }
  })(),
  /*ENDIF*/
  
  /*IF[jPaq.getAbsPath()]*/
  getAbsPath : (function() {
    var img = new Image();
    return function(relPath) {
      img.src = relPath;
      return img.src;
    };
  })(),
  /*ENDIF*/
  
  /*IF[Cookies]*/
  setCookie : function(name, value, expires, domain, path, secure) {
    // Set the name/value pair.
    var parts = [encodeURIComponent(name) + "=" + encodeURIComponent(value)];
    // Set expiration time.
    if(expires)
      parts.push("expires=" + (new Date(expires)).toGMTString());
    // Set domain.
    if(domain)
      parts.push("domain=" + encodeURIComponent(domain));
    // Set path.
    if(path)
      parts.push("path=" + encodeURIComponent(path));
    // Set secure flag.
    if(secure)
      parts.push("secure");
    // Setup the actual cookie.
    doc.cookie = parts.join("; ");
  },
  getCookie : function(name) {
    if(name instanceof RegExp) {
      var ret = jPaq.getCookie();
      for(var key in ret)
        if(!name.test(key))
          delete ret[key];
    }
    else if(name == null) {
      var ret = {};
      doc.cookie.replace(/(?:^|;\s*)(.+?)(?=;\s*|$)/g, function($0, $1) {
        $1 = $1.match(/(.*?)=(.*)/);
        ret[decodeURIComponent($1[1])] = decodeURIComponent($1[2]);
      });
    }
    else {
      name = doc.cookie.match(new RegExp("(?:^|;\\s*)" + encodeURIComponent(name) + "=(.*?)(?:;\\s*|$)"));
      if(name)
        var ret = decodeURIComponent(name[1]);
    }
    return ret;
  },
  removeCookie : function(name, domain, path, secure) {
    var cookies = jPaq.getCookie(name);
    if(cookies && ("string" == typeof cookies)) {
      (cookies = {})[name] = 1;
    }
    for(var key in cookies) {
      jPaq.setCookie(key, "", new Date(0), domain, path, secure);
    }
  },
  /*ENDIF*/
  
  /*IF[jPaq.getOrdinalFor()]*/
  getOrdinalFor : function(intNum, includeNumber) {
    /// <summary>
    ///   Retrieves the ordinal for the integer that is specified.  If
    ///   includeNumber evaluates to true, the number will be prefixed to the
    ///   ordinal.
    /// </summary>
    /// <param name="intNum" type="Number">
    ///   This is the number for which the ordinal shall be retrieved.
    /// </param>
    /// <param name="includeNumber" type="Boolean" optional="true">
    ///   Optional.  The boolean value which indicates whether or not the integer
    ///   value of intNum should be prefixed to the returned ordinal.
    /// </param>
    /// <returns type="String">
    ///   The ordinal that ordinal the corresponds with the integer value of
    ///   intNum.  In addition, if includeNumber evaluates to true, the integer
    ///   value of intNum will be prefixed to this.
    /// </returns>
    intNum = intNum << 0;
    return (includeNumber ? intNum : "") + (((intNum = Math.abs(intNum) % 100)
      % 10 == 1 && intNum != 11) ? "st" : (intNum % 10 == 2 && intNum != 12)
      ? "nd" : (intNum % 10 == 3 && intNum != 13) ? "rd" : "th");
  },
  /*ENDIF*/

  /*IF[jPaq.ready()]*/
  // Code loosely based on Ryan Morr's solution:
  // http://ryanmorr.com/archives/ondomready-no-browser-sniffing
  ready : (function(handlers) {
    var ready;
    
    function fireDOMReady(){
      if(!ready){
        ready = true;
        for(var i = 0, len = handlers.length; i < len; i++) {
          try {
            handlers[i][0].call(handlers[i][1]);
          }
          catch(e) {
            setTimeout(function(){ throw e; }, 0);
          }
        }
      }
    }
    
    function onChange(e, doTimeout) {
      e = e || global.event;
      // If this was invoked by the DOMContentLoaded event or load event, call fireDOMReady.
      if(e && /^(DOMContentLoaded|load)$/.test(e.type)) {
        fireDOMReady();
      }
      // If the ready state of the document is set...
      else if(doc.readyState) {
        if(/^(loaded|complete)$/.test(doc.readyState)) {
          fireDOMReady();
        }
        // Try the doScroll trick, but only if this is the top-level frame.
        else if(docElem.doScroll && !global.frameElement) {
          try {
            // If the document is ready, don't try to scroll left, just call fireDOMReady.
            ready || docElem.doScroll('left');
            fireDOMReady();
          } catch(e){}
        }
      }
      
      // If doTimeout evaluates to true and fireDOMReady wasn't yet called, call this function
      // again in 9 milliseconds.
      if(doTimeout && !ready)
        setTimeout(function(){onChange(0,1);}, 9);
    }
    
    onChange(0,1);
    
    if(doc.addEventListener) {
      doc.addEventListener("DOMContentLoaded", onChange, false);
      global.addEventListener("load", onChange, false);
    }
    else if(doc.attachEvent) {
      doc.attachEvent("onreadystatechange", onChange);
      global.attachEvent("onload", onChange);
    }
    onChange(0,1);

    return function(fn, ctx) {
      if(ready)
        fn.call(ctx);
      else
        handlers.push([fn, ctx]);
    };
  })([]),
  /*ENDIF*/
  
  /*IF[Client Data]*/
  browser : "Unknown",
  browserVersion : "Unknown",
  OS : "Unknown",
  /*ENDIF*/
  
  /*IF[$id]*/
  $id : $id,
  /*ENDIF*/
  
  /*IF[jPaq.time]*/
  time : function(fnCallback) {
    var d1 = new Date;
    fnCallback(d1);
    return (new Date) - d1;
  },
  /*ENDIF*/
  
  noConflict : function() {
  	/*IF[Color Class]*/
  	if(global.Color === Color) {
      global.Color = oldColor;
  	}
  	/*ENDIF*/

  	/*IF[DOM Selector,jPaq.ready()]*/
  	if(global.$ === jPaq) {
      global.$ = old$;
  	}
  	/*ENDIF*/
  	
  	/*IF[$id]*/
  	if(global.$id === $id) {
      global.$id = old$id;
  	}
  	/*ENDIF*/
  	
  	if(global.jPaq === jPaq) {
      global.jPaq = oldJPaq;
    }
  	
  	return jPaq;
  },
	
	contains : contains,
	
	keysOf : keysOf,

	extend : extend,
  
  global : global
});

/*IF[Client Data]*/
(function() {
	// Detection method from http://www.quirksmode.org/js/detect.html.
	// Determine the browser name.
	var arrBrowser = [
    {b:"Chrome", u:"Chrome"},
		{b:"OmniWeb", u:"OmniWeb", v:"OmniWeb/"},
		{b:"Safari", s:navigator.vendor, t:"Apple", v:"Version"},
		{b:"Opera", p:global.opera},
		{b:"iCab", s:navigator.vendor, t:"iCab"},
		{b:"Konqueror", s:navigator.vendor, t:"KDE"},
		{b:"Firefox", u:"Firefox"},
		{b:"Camino", s:navigator.vendor, t:"Camino"},
		{b:"Netscape", u:"Netscape"},
		{b:"Internet Explorer", u:"MSIE", v:"MSIE"},
		{b:"Mozilla", u:"Gecko", v:"rv"},
		{b:"Netscape", u:"Mozilla", v:"Mozilla"}
  ];
	for(var i = 0; i < arrBrowser.length; i++) {
		// Defined for identifying the browser version.
		arrBrowser.v = arrBrowser[i].v || arrBrowser[i].b;
		// If this is the browser.
		if((arrBrowser[i].s && arrBrowser[i].s.indexOf(arrBrowser[i].t) > -1
    || arrBrowser[i].u && navigator.userAgent.indexOf(arrBrowser[i].u) > -1
    || arrBrowser[i].p) && (jPaq.browser = arrBrowser[i].b)) {
			break;
    }
	}

	// Determine the browser version.
	arrBrowser.f = function(subject) {
		var i = subject.indexOf(arrBrowser.v);
		return i < 0 ? false : parseFloat(subject.substring(i + arrBrowser.v.length + 1));
	}
	jPaq.browserVersion = arrBrowser.f(navigator.userAgent)
		|| arrBrowser.f(navigator.appVersion)
		|| jPaq.browserVersion;

	// Determine the system's OS.
	var arrOS = [
		{n:"Linux", s:"platform", t:"Linux"},
		{n:"iPhone/iPod", s:"userAgent", t:"iPhone"},
		{n:"Mac", s:"platform", t:"Mac"},
    {n:"Windows", s:"platform", t:"Win"}
  ];
	for(var i = arrOS.length - 1; i >= 0; i--) {
		if(navigator[arrOS[i].s].indexOf(arrOS[i].t) > -1 && (jPaq.OS = arrOS[i].n)) {
			break;
    }
  }
})();
/*ENDIF*/

/*IF[DOM Selector]*/
(function() {
	var getsAndSets = {
		// Loosely based on http://ejohn.org/blog/jquery-16-and-attr/
		attr : {
			g : function(elem, name) {
				return ("getAttribute" in elem && "boolean" != typeof elem[name])
					? (name === "value" && elem.nodeName && elem.nodeName.toUpperCase() === "BUTTON")
						? (function(attrNode) {
							return (attrNode && attrNode.specified)
								? attrNode.nodeValue
								: undefined;
						})(elem.getAttributeNode(name))
						: elem.getAttribute(name, /^(href|src|width|height)$/.test(name) ? 2 : undefined) || undefined
					: elem[name];
			},
			s : function(elem, name, value) {
				if("setAttribute" in elem) {
					if(value === false) {
						elem.removeAttribute(name);
					}
					else {
						elem.setAttribute(name, value === true ? name : value);
					}
				}
				else {
					elem[name] = value;
				}
			}
		},
		prop : {
			g : function(elem, name) {
				if(jPaq.isString(name)) {
					return elem[propHash[name] || name];
				}
				else {
					for(var key in name) {
						this.prop(key, name[key]);
					}
					return this;
				}
			},
			s : function(elem, name, value) {
				elem[propHash[name] || name] = value;
			}
		},
		text : {
			g : getText,
			s : function(elem, newText, currentMeta) {
				for(var child; child = elem.firstChild; ) {
					elem.removeChild(child);
				}
				elem.appendChild((elem.ownerDocument || doc).createTextNode(
					currentMeta
						? (newText + "").split(currentMeta).join(getText(elem))
						: (
								isFunction(newText)
									? newText.call(elem, index, elem[textAttr], this)
									: newText
							) + "")
				);
			}
		},
		html : {
			g : function(elem) {
				return elem.innerHTML;
			},
			s : function(elem, newHTML, currentMeta) {
				elem.innerHTML = currentMeta
					? (newHTML + "").split(currentMeta).join(elem.innerHTML)
					: (
							isFunction(newHTML)
								? newHTML.call(elem, index, elem.innerHTML, this)
								: newHTML
						) + "";
			}
		},
		css : {
			g : function(elem, prop) {
				if(jPaq.isString(prop)) {
					prop = getCSSProp(elem, prop);
					if(cssHooks[prop] && cssHooks[prop].g) {
						return cssHooks[prop].g(elem);
					}
					return getStyleFor(elem, prop);
				}
				else {
					return this.css(prop, 1);
				}
			},
			s : function(elem, key, value) {
				if(jPaq.isString(key)) {
					if(key in cssHash) {
						key = cssHash[key = dashToCamelCase(key)] || calculateCSSHash(elem, key);
					}
					if(cssHooks[key] && cssHooks[key].s) {
						cssHooks[key].s(elem, value);
					}
					else {
						elem.style[key] = value + "";
					}
				}
				else if(value = key) {
					for(var key in value) {
						var realKey = key in cssHash
							? cssHash[key = dashToCamelCase(key)] || calculateCSSHash(elem, key)
							: key;
						if(cssHooks[realKey] && cssHooks[realKey].s) {
							cssHooks[realKey].s(elem, value[key]);
						}
						else {
							elem.style[realKey] = value[key] + "";
						}
					}
				}
			}
		}
	};
	
	function getCSSProp(elem, prop) {
		return  (prop = camelCaseToDash(prop)) in cssHash
			? cssHash[prop = dashToCamelCase(prop)] || calculateCSSHash(elem, prop)
			: prop;
	}
	
	function getStyleFor(elem, prop) {
		return global.getComputedStyle
			? doc.defaultView.getComputedStyle(elem, null).getPropertyValue(prop = getCSSProp(elem, prop))
			: elem.currentStyle
				? elem.currentStyle[dashToCamelCase(prop)]
				: undefined;
	}
	
	// From http://dailyjs.com/2011/05/05/framework-61/
	var propHash = {
		cellpadding: "cellPadding",
		cellspacing: "cellSpacing",
		"class" : "className",
		colspan: "colSpan",
		contenteditable: "contentEditable",
		"for" : "htmlFor",
		frameborder: "frameBorder",
		maxlength: "maxLength",
		readonly: "readOnly",
		rowspan: "rowSpan",
		tabindex : "tabIndex",
		usemap: "useMap"
	};

	var cssHash = {
		"float" : 0,
		"styleFloat" : 0,
		"cssFloat" : 0
	};
	
	var cssHooks = {
		opacity : {
			g : function(elem) {
				var ret, currentStyle = elem.currentStyle;
				if(currentStyle && "hasLayout" in currentStyle && "filter" in currentStyle) {
					if(!currentStyle.hasLayout || "string" != typeof currentStyle.filter) {
						ret = 1;
					}
					else {
						ret = (+(currentStyle.filter.match(/alpha\s*\([^)]*opacity\s*=\s*(\d+)/i) || [0,100])[1]) / 100;
					}
				}
				else {
					ret = getStyleFor(elem, "opacity");
				}
				return ret + "";
			},
			s : function(elem, value) {
				var currentStyle = elem.currentStyle, style = elem.style;
				if(currentStyle && "hasLayout" in currentStyle && "filter" in currentStyle) {
					if(!currentStyle.hasLayout) {
						style.zoom = 1;
						
					}
					style.filter = currentStyle.filter.replace(/(progid:DXImageTransform\.Microsoft\.)?Alpha\s*\(.+?\)/gi, "") + (value < 1 ? " alpha(opacity=" + (value * 100) + ")" : "");
				}
				else {
					style.opacity = value;
				}
			}
		}
	};

	function calculateCSSHash(elem, cssKey) {
		var style = elem.style, ret;
		switch(cssKey) {
			case "float":
			case "styleFloat":
			case "cssFloat":
				if("cssFloat" in style)
					ret = "cssFloat";
				else if("styleFloat" in style)
					ret = "styleFloat";
		}
		return (cssHash[cssKey] = ret) || cssKey;
	}

	for(var key in getsAndSets) {
    (function(item) {
    	var getterMaxArgs = item.g.length - 1;
      jPaq.prototype[key] = function() {
        var arrArgs = parseArray(arguments);
        // Setter being called...
        if(arrArgs.length > getterMaxArgs) {
          return jPaqEach(this, function(elem) {
            item.s.apply(this, [elem].concat(arrArgs));
          });
        }
        // Getter being called...
        else {
          var arr = this._(privatize).$elements;
          if(arr.length) {
            return item.g.apply(this, [arr[0]].concat(arrArgs));
          }
        }
      };
    })(getsAndSets[key]);
	}
	
	/*IF[Event Handling]*/
	var jPaqPrototype = jPaq.prototype;
	var shortcuts = "abort,blur,change,click,error,focus,keydown,keypress,keyup,load,mousedown,mouseenter,mouseleave,mousemove,mouseout,mouseover,mouseup,reset,resize,scroll,select,submit,unload".split(",");
	for(var i = shortcuts.length - 1; i >= 0; i--) {
		(function(shortcut) {
			jPaqPrototype[shortcut] = function(fnHandler) {
				if(isFunction(fnHandler)) {
					this.bind(shortcut, fnHandler);
				}
				else {
					this.trigger(shortcut);
				}
				return this;
			};
		})(shortcuts[i]);
	}
	/*ENDIF*/
})();
/*ENDIF*/

/*IF[jPaq.GET]*/
// Define the jPaq.GET object.
(function() {
	var objGET = {}, arr = location.search.substring(1).split("&");
	for(var parts, i = 0, len = arr.length; i < len; i++) {
		if(!(parts = arr[i].match(/^(.*?)=(.*)$/)) || parts.length < 3)
			continue;
		parts[2] = jPaq.unescape(parts[2], true);
		if((parts[1] = jPaq.unescape(parts[1], true)) in objGET)
			if(objGET[parts[1]] instanceof Array)
				objGET[parts[1]].push(parts[2]);
			else
				objGET[parts[1]] = [objGET[parts[1]], parts[2]];
		else
			objGET[parts[1]] = parts[2];
	}
	jPaq.GET = objGET;
})();
/*ENDIF*/

/*IF[Array.range()]*/
// This was inspired by the Python range function.
Array.range = function(start, stop, step) {
	if(arguments.length == 1) {
		stop = start;
		start = 0;
	}
	for(var ret = [], negativeStep = (step = step || 1) < 0;
	negativeStep ? start > stop : (start < stop); start += step)
		ret.push(start);
	return ret;
};
/*ENDIF*/

/*IF[Array.prototype.fillWith()]*/
// Fills an array with either the specified value or the return values from
// a function iterated through each index, starting at the first one.
Array.prototype.fillWith = function(filler, storeFuncs) {
  /// <summary>
  ///   Fills an array with either the specified value or the return values
  ///   from a function.
  /// </summary>
  var me = this, execFiller = (typeof filler == "function") && !storeFuncs;
  for(var i = 0, len = me.length; i < len; i++)
    me[i] = execFiller ? filler.call(me, i, me[i]) : filler;
  return me;
};
/*ENDIF*/

/*IF[Array.prototype.uniquify()]*/
Array.prototype.uniquify = function() {
	for(var arr = this.slice(0), i = 0, jLen = arr.length, iLen = jLen - 1; i < iLen; i++)
		for(var j = i + 1; j < jLen; j++)
			if(arr[i] === arr[j]) {
				arr.splice(j--, 1);
				jLen = iLen--;
			}
	return arr;
};
/*ENDIF*/

/*IF[Array.prototype.clone()]*/
Array.prototype.clone = function(doDeepCopy) {
	if(doDeepCopy) {
		var encountered = [{
			a : this,
			b : []
		}];

		var item,
			levels = [{a:this, b:encountered[0].b, i:0}],
			level = 0,
			i = 0,
			len = this.length;

		while(i < len) {
			item = levels[level].a[i];
			if(Object.prototype.toString.call(item) === "[object Array]") {
				for(var j = encountered.length - 1; j >= 0; j--) {
					if(encountered[j].a === item) {
						levels[level].b.push(encountered[j].b);
						break;
					}
				}
				if(j < 0) {
					encountered.push(j = {
						a : item,
						b : []
					});
					levels[level].b.push(j.b);
					levels[level].i = i + 1;
					levels[++level] = {a:item, b:j.b, i:0};
					i = -1;
					len = item.length;
				}
			}
			else {
				levels[level].b.push(item);
			}

			if(++i == len && level > 0) {
				levels.pop();
				i = levels[--level].i;
				len = levels[level].a.length;
			}
		}

		return encountered[0].b;
	}
	else {
		return this.slice(0);
	}
};
/*ENDIF*/

/*IF[Arrays as Sets]*/
extend(Array.prototype, {
	// Returns all elements that are in this array but not in arrOther.
	subtract : function(arrOther) {
		if(!(arrOther instanceof Array))
			return [];
		var j, i = 0, difference = [], arrOtherFound = [];
		for(; i < this.length; i++) {
			for(j = 0; j < arrOther.length; j++) {
				if(arrOtherFound[j] != true && arrOther[j] === this[i]) {
					arrOtherFound[j] = true;
					break;
				}
			}
			if(j == arrOther.length)
				difference.push(this[i]);
		}
		return difference;
	},
	// Returns all elements that are common to this array and arrOther.
	intersect : function(arrOther) {
		// A - B = C
		// A - C = A & B
		if(!(arrOther instanceof Array))
			return [];
		return this.subtract(this.subtract(arrOther));
	},
	// Returns all elements that are in the first array and the second (not
	// including duplicates).
	union : function(arrOther) {
		// B - A = C
		// A + C = A | B
		if(!(arrOther instanceof Array))
			return [];
		return this.concat(arrOther.subtract(this));
	}
});
/*ENDIF*/

/*IF[Function.prototype.curry()]*/
Function.prototype.curry = function() {
	var me = this, args = parseArray(arguments);
	return function() {
		return me.apply(this, args.concat(parseArray(arguments)));
	};
};
/*ENDIF*/

/*IF[Function.prototype.curryAny()]*/
Function.prototype.curryAny = function(args, preserveIndices) {
  /// <jPaq name="Function.prototype.curryAny()"
  ///   origin="Function.prototype.curryAny()" makeDoc="true" for="PC,Web" />
  /// <summary>
  ///   Produces a new function, with the specified parameters set as the default
  ///   values for this function.
  /// </summary>
  /// <param name="paramIndex" type="Object">
  ///   An object literal whose keys must be integers which specify where the values
  ///   will be passed as arguments to this function.  'undefined' is the only thing
  ///   that will not take precedence over another predefined parameter.
  /// </param>
  /// <param name="preserveIndices" type="Boolean">
  ///   A value indicating whether or not the parameters defined at the specified
  ///   indices may be redefined later.  The default value is false.
  /// </param>
  /// <returns type="Function">
  ///   Returns a new function with the specified arguments already filled in.
  /// </returns>
  var me = this, arr = [];
  for(var i in args)
    arr[parseInt(i, 10)] = args[i];
  return preserveIndices
    ? function() {
      for(var args = arguments, len = args.length, i = 0; i < len; i++)
        if(args[i] !== undefined)
          arr[i] = args[i];
      return me.apply(this, arr);
    }
    : function() {
      for(var args = arguments, len = args.length, i = 0, j = 0; j < len; i++)
        if(arr[i] === undefined)
          arr[i] = args[j++];
      return me.apply(this, arr);
    };
};
/*ENDIF*/

/*IF[Function.prototype.invoke()]*/
Function.prototype.invoke = function(objThis, objArgs) {
	var args = [];
	if(objArgs !== null && objArgs !== undefined) {
		(((this + "")
		.replace(/^.*?function.+?|\/\*[\s\S]*?\*\/|\/\/.*?[\r\n]/g, "")
		.match(/\([\s\S]*?\)/)||args)[0]||"")
		.replace(/[\$A-Za-z_][\w\$]*/g, function(argName) {
			args.push(objArgs[argName]);
		});
	}
	args.push(objArgs);
	return this.apply(objThis, args);
};
/*ENDIF*/

/*IF[Function.prototype.compose()]*/
// Inspired by
// http://javascriptweblog.wordpress.com/2010/04/14/compose-functions-as-building-blocks/
(function() {
  var slice = [].slice;
  Function.prototype.compose = function(fn, arraysToParams, useReturnAsThis) {
    var me = this;
    return function() {
      var ret = fn.apply(this, slice.call(arguments, 0)),
        objThis = useReturnAsThis ? ret : this;
      if(arraysToParams && (ret instanceof Array))
        return me.apply(objThis, ret);
      return me.call(objThis, ret);
    };
  };
})();
/*ENDIF*/

/*IF[Function.prototype.getCacheable()]*/
Function.prototype.getCacheable = function() {
  var me = this, cache = {}, cacheableFn = function() {
    for(var prefix, arg, currentCache = cache, i = 0, len = arguments.length; i < len; i++) {
      arg = arguments[i];
      prefix = ((prefix = (typeof arg)) == "string" || prefix == "number")
        ? prefix.charAt(0)
        : "o";
      if(prefix == "o" && !cacheableFn.cacheObjects)
        return me.apply(this, [].slice.call(arguments, 0));
      currentCache = (currentCache[prefix] = currentCache[prefix] || (prefix == "o" ? [] : {}));
      if(prefix == "o") {
        for(var j = currentCache.length - 1; j >= 0; j--) {
          if(currentCache[j].a === arg) {
            currentCache = currentCache[j].c;
            break;
          }
        }
        if(j < 0)
          currentCache = (currentCache[currentCache.length] = {a : arg, c : {}}).c;
      }
      else
        currentCache = (currentCache[arg] = currentCache[arg] || {});
    }
    return (cacheableFn.useCache && ("v" in currentCache))
      ? currentCache.v
      : currentCache.v = me.apply(this, [].slice.call(arguments, 0));
  };
  cacheableFn.cacheObjects = !(cacheableFn.useCache = true);
  return cacheableFn;
};
/*ENDIF*/

/*IF[Function.prototype.overload()]*/
Function.prototype.overload = function(fnToAdd, objFilters) {
  var fnOriginal = this;
  return function() {
    var fnToUse = fnToAdd, args = arguments, len = args.length;
    if(objFilters) {
      for(var key in objFilters) {
        if((key == "all" && !objFilters[key].call(this, args))
           || (key == "length" && len != objFilters[key])
           || (/^\d+$/.test(key) && !objFilters[key](args[key]))) {
          fnToUse = fnOriginal;
          break;
        }
      }
    }
    else if(fnToAdd.length !== len) {
      fnToUse = fnOriginal;
    }
    return fnToUse.apply(this, args);
  };
};
/*ENDIF*/

/*IF[Array.prototype.every()]*/
// Source:  https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/forEach
Array.prototype.every = Array.prototype.every || function(fnCallback, objThis) {
	if(typeof fnCallback != "function")
		throw new TypeError();
	for(var i = 0, len = this.length >>> 0; i < len; i++)
		if(i in this && !fnCallback.call(objThis, this[i], i, this))
			return false;
	return true;
};
/*ENDIF*/

/*IF[Array.prototype.forEach()]*/
// Source:  https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/forEach
Array.prototype.forEach = Array.prototype.forEach || function(fn, objThis) {
	if(typeof fn != "function")
		throw new TypeError();
	for(var i = 0, len = this.length >>> 0; i < len; i++)
		if(i in this)
			fn.call(objThis, this[i], i, this);
};
/*ENDIF*/

/*IF[Array.prototype.filter()]*/
// Source:  https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter
Array.prototype.filter = Array.prototype.filter || function(fn, objThis) {
	if(typeof fn != "function")
		throw new TypeError();
	for(var val, res = [], i = 0, len = this.length >>> 0; i < len; i++)
		if(i in this && fn.call(objThis, val = this[i], i, this))
			res.push(val);
	return res;
};
/*ENDIF*/

/*IF[Array.prototype.indexOf()]*/
// Source:  https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf
Array.prototype.indexOf = Array.prototype.indexOf || function(target, start) {
	var len = this.length >>> 0;
	start = Number(start) || 0;
	if((start = (start < 0) ? Math.ceil(start) : Math.floor(start)) < 0)
		start += len;
	for(; start < len; start++)
		if(start in this && this[start] === target)
			return start;
	return -1;
};
/*ENDIF*/

/*IF[Array.prototype.lastIndexOf()]*/
// Source:  https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/lastIndexOf
Array.prototype.lastIndexOf = Array.prototype.lastIndexOf || function(target, start) {
	var len = this.length;
	start = (isNaN(start = Number(start)) ? len - 1 : ((start = (start < 0) ? Math.ceil(start) : Math.floor(start)) < 0 ? start + len : (start >= len ? len - 1 : start)));
	for(; start > -1; start--)
		if(start in this && this[start] === target)
			return start;
	return -1;
};
/*ENDIF*/

/*IF[Array.prototype.map()]*/
// Source:  https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/map
Array.prototype.map = Array.prototype.map || function(fnCallback, objThis) {
	if(typeof fnCallback != "function")
		throw new TypeError();
	var len = this.length >>> 0;
	for(var res = new Array(len), i = 0; i < len; i++)
		if (i in this)
			res[i] = fnCallback.call(objThis, this[i], i, this);
	return res;
};
/*ENDIF*/

/*IF[Array.prototype.reduce()]*/
// Source:  https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Array/Reduce
Array.prototype.reduce = Array.prototype.reduce || function(fnCallback, initial) {
	if(typeof fnCallback != "function")
		throw new TypeError();
	// no value to return if no initial value and an empty array
	var len = this.length >>> 0, aLen = arguments.length;
	if(len == 0 && aLen == 1)
		throw new TypeError();
	var i = 0;
	if(aLen < 2)
		do {
			if (i in this) {
				initial = this[i++];
				break;
			}
			// if array contains no values, no initial value to return
			if(++i >= len)
				throw new TypeError();
		} while(1);
	for(; i < len; i++)
		if(i in this)
			initial = fnCallback.call(undefined, initial, this[i], i, this);
	return initial;
};
/*ENDIF*/

/*IF[Array.prototype.reduceRight()]*/
// Source:  https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Array/ReduceRight
Array.prototype.reduceRight = Array.prototype.reduceRight || function(fnCallback, initial) {
	if(typeof fnCallback != "function")
		throw new TypeError();
	// no value to return if no initial value, empty array
	var len = this.length >>> 0, aLen = arguments.length;
	if(len == 0 && aLen == 1)
		throw new TypeError();
	var i = len - 1;
	if(aLen < 2)
		do {
			if (i in this) {
				initial = this[i--];
				break;
			}
			// if array contains no values, no initial value to return
			if(--i < 0)
				throw new TypeError();
		} while(true);
	for(; i >= 0; i--)
		if(i in this)
			initial = fnCallback.call(undefined, initial, this[i], i, this);
	return initial;
};
/*ENDIF*/

/*IF[Array.prototype.some()]*/
// Source:  https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/some
Array.prototype.some = Array.prototype.some || function(fnCallback, objThis) {
	if (typeof fnCallback != "function")
		throw new TypeError();
	for (var i = 0, len = this.length >>> 0; i < len; i++) {
		if (i in this && fnCallback.call(objThis, this[i], i, this)) {
			return true;
		}
	}
	return false;
};
/*ENDIF*/

/*IF[Color Class,Color.random()]*/
// A class to represent a color.
var oldColor = global.Color;

// A class to represent a color.
function Color(rValue, gValue, bValue) {
	// Make sure that this function always acts a constructor.
	if(rValue === privatize) {
		return this;
	}
	var me = this instanceof Color ? this : new Color(privatize);

	// Initialize the color.
	privatize(me, {r : 0, g : 0, b : 0, h : 0, s : 0, l : 0, a : 100});
	return me.setTo.apply(me, arguments);
}

// Code derived from http://dbj.org/dbj/?p=423
var parseColorName = (function() {
	var button = doc.createElement("BUTTON");
	doc.getElementsByTagName("head")[0].appendChild(button);
	if(global.getComputedStyle) {
		return function(color) {
			// For browsers who support it, we use getComputedStyle()
			button.style.color = color;
			return global.getComputedStyle(button, null).getPropertyValue("color");
		};
	}
	else {
		var textRange = button.createTextRange();
		return function(color) {
			// for IE we use queryCommandValue()
			// http://www.geoffchappell.com/viewer.htm?doc=studies/windows/ie/mshtml/methods/basemso/querycommandvalue.htm
			button.style.color = color;
			var value = textRange.queryCommandValue("ForeColor");
			value = ((value & 0x0000ff) << 16) | (value & 0x00ff00) | ((value & 0xff0000) >>> 16);
			value = value.toString(16);
			return "000000".slice(0, 6 - value.length) + value;
		};
	}
})();

// Set up the prototypal functions.
extend((global.Color = jPaq.Color = Color).prototype, {
	setTo : function(rValue, gValue, bValue, aValue) {
		var me = this;
		if(arguments.length == 1) {
			if(rValue instanceof Color) {
				me.r(rValue.r())
					.g(rValue.g())
					.b(rValue.b())
					.a(rValue.a());
			}
			else if(typeof rValue == "string") {
				rValue.replace(/^.*(rgb|hsl)(a)?.*?\((.*?)\).*$/i, function(all, scale, alpha, params) {
					params = params.replace(/^[^%\d]+|[^%\d]+$/g, "").split(/[^%\d\.]+/);
					rValue = params[0];
					gValue = params[1];
					bValue = params[2];
					aValue = params[3];
					
					var rPercent = rValue && rValue.indexOf("%") >= 0 && (rValue = rValue.replace("%", "")),
						gPercent = gValue && gValue.indexOf("%") >= 0 && (gValue = gValue.replace("%", "")),
						bPercent = bValue && bValue.indexOf("%") >= 0 && (bValue = bValue.replace("%", "")),
						aPercent = aValue && aValue.indexOf("%") >= 0 && (aValue = aValue.replace("%", ""));
						
					aValue = aValue && aValue.replace("%", "");
					
					if(scale == "rgb") {
						me.r(rPercent ? parseFloat(rValue) / 100 * 255 : rValue)
							.g(gPercent ? parseFloat(gValue) / 100 * 255 : gValue)
							.b(bPercent ? parseFloat(bValue) / 100 * 255 : bValue);
					}
					else {
						me.h(rPercent ? parseFloat(rValue) / 100 * 360 : rValue)
							.s(gValue)
							.l(bValue);
					}
					if(alpha) {
						me.a(aPercent ? parseFloat(aValue) / 100 : +aValue);
					}
					return "";
				})
				.replace(/^#?((?:[\dA-F]{3,4}){1,2})$/i, function(all, hexCode) {
					if(hexCode.length < 6) {
						hexCode = hexCode.replace(/(.)/g, "$1$1");
					}
					me.r(parseInt(hexCode.substring(0, 2), 16))
						.g(parseInt(hexCode.substring(2, 4), 16))
						.b(parseInt(hexCode.substring(4, 6), 16));
					if(hexCode.length > 6) {
						me.a(parseInt(hexCode.substring(6), 16) / 255 * 100);
					}
					return "";
				})
				.replace(/^\d+$/, function(num) {
					me.r(num);
					return "";
				})
				.replace(/.+/, function(colorName) {
					me.setTo(parseColorName(colorName));
					return "";
				});
			}
			else {
				me.r(rValue);
			}
		}
		else {
			// Checks done using undefined instead of null because "undefined" will be
			// minified.
			if(rValue != undefined) {
				me.r(rValue);
			}
			if(gValue != undefined) {
				me.g(gValue);
			}
			if(bValue != undefined) {
				me.b(bValue);
			}
			if(aValue != undefined) {
				me.a(aValue);
			}
		}
		return me;
	},

	getHexCode : function(includeAlpha) {
		var arr = [
			Math.round(this.r()).toString(16),
			Math.round(this.g()).toString(16),
			Math.round(this.b()).toString(16)
		];
		if(includeAlpha) {
			arr.unshift(Math.round(this.a() * 255).toString(16));
		}
		return "#" + arr.join(",").replace(/\b(\w)\b/gi, "0$1").toUpperCase().replace(/,/g, "");
	},
	
	toRGB : function(includeAlpha) {
		includeAlpha = includeAlpha || this.a() < 1;
		return "rgb" + (includeAlpha ? "a(" : "(") + Math.round(this.r()) + ", "
			+ Math.round(this.g()) + ", " + Math.round(this.b())
			+ (includeAlpha ? ", " + this.a() : "") + ")";
	},
	
	toHSL : function(includeAlpha) {
		includeAlpha = includeAlpha || this.a() < 1;
		return "hsl" + (includeAlpha ? "a(" : "(") + (Math.round(this.h()) % 360)
			+ ", " + Math.round(this.s()) + "%, " + Math.round(this.l())
			+ (includeAlpha ? "%, " + this.a() : "%") + ")";
	},
	
	a : function(newValue, addValue) {
		var pData = this._(privatize);
		if(arguments.length) {
			pData.a = Math.max(0, Math.min(1, parseFloat(newValue) + (addValue ? addValue == -1 ? -pData.a : pData.a : 0)));
			return this;
		}
		else {
			return pData.a;
		}
	},
	
	toString : function() {
		return this.a() < 1
			? this.toRGB(1)
			: this.toHex();
	},

	combine : function(secondColor, strength) {
		if(isNaN(strength = +strength))
			strength = 50;
		var percent2 = Math.max(Math.min(strength, 100), 0) / 100;
		var percent1 = 1 - percent2;
		return new Color(
			this.r() * percent1 + secondColor.r() * percent2,
			this.g() * percent1 + secondColor.g() * percent2,
			this.b() * percent1 + secondColor.b() * percent2
		);
	},
	
	clone : function() {
		return new Color(this);
	},

	// Returns a color that can be displayed well on the specified color.
	getSafeColor : function() {
		return (this.getLuminance() < 128 ? white : black).clone();
	},

	getLuminance : function() {
		return .299 * this.r() + .587 * this.g() + .114 * this.b();
	},

	// Gets an approximation of the grayscale version of the color.
	toGrayscale : function() {
		var i = Math.round(this.getLuminance());
		return new Color(i, i, i);
	},

	// Gets the opposite color.
	getOpposite : function() {
		return this.clone().r(255,-1).g(255,-1).b(255,-1);
	},

	// Gives the user the ability to get a lighter version of a color.
	getLighter : function(strength) {
		return this.combine(white, strength != null ? strength >>> 0 : 30);
	},

	// Gives the user the ability to get a darker version of a color.
	getDarker : function(strength) {
		return this.combine(black, strength != null ? strength >>> 0 : 30);
	}
}).toHex = Color.prototype.getHexCode;

// Create the jQuery-like getter/setter functions for the RGB values.
for(var arr = "rgbhsl".split(""), i = 0; i < 6; i++) {
	(function(name, adjustor) {
		Color.prototype[name] = function(value, addValue) {
			var privateData = this._(privatize);
			if(!arguments.length)
				return privateData[name];
      adjustor(name, value, addValue, privateData);
			return this;
		};
	})(arr[i], i < 3 ? adjustHSL : adjustRGB);
}

// Adjusts the HSL values by converting from the RGB values.
// Code derived from http://easyrgb.com/index.php?X=MATH&H=18#text18
function adjustHSL(name, value, addValue, privateData) {
    // Validate and assign the specified R, G, or B value.
    privateData[name] = Math.min(Math.max(0, (value >>> 0) + (addValue ? (addValue == -1 ? -1 : 1) * privateData[name] : 0)), 255);

    // RGB values as a percentage.
    var r = privateData.r / 255;
    var g = privateData.g / 255;
    var b = privateData.b / 255;

    // Min, max and delta RGB values.
    var min = Math.min(r, g, b);
    var max = Math.max(r, g, b);
    var delta = max - min;

    // Default hue, saturation, and light values.
    var h = 0, s = 0, l = (min + max) / 2;

    // If the color isn't a shade of gray...
    if(delta != 0) {
       s = delta / (l < .5 ? max + min : (2 - max - min));

       var deltaR = (((max - r) / 6) + (delta / 2)) / delta;
       var deltaG = (((max - g) / 6) + (delta / 2)) / delta;
       var deltaB = (((max - b) / 6) + (delta / 2)) / delta;

       h = r != max
           ? g == max
               ? (1 / 3) + deltaR - deltaB
               : ((2 / 3) + deltaG - deltaR)
           : deltaB - deltaG;
       h += (h < 0 ? 1 : h > 1 ? -1 : 0);
    }

    // Store these new values.
    privateData.h = (h * 360) % 360;
    privateData.s = s * 100;
    privateData.l = l * 100;
}

// Adjusts the RGB values by converting from the HSL values.
function adjustRGB(name, value, addValue, privateData) {
  // Validate and assign the specified H, S, or L value.
  value = parseFloat(value) + (addValue ? (addValue == -1 ? -1 : 1) * privateData[name] : 0);
	privateData[name] = name == "h"
		? ((value % 360) + 360) % 360
		: Math.max(0, Math.min(100, value));
  var h = privateData.h / 360,
    s = privateData.s / 100,
    l = privateData.l / 100;
    
/*******************************************************************************
 * From http://www.w3.org/TR/2003/CR-css3-color-20030514/:
 * HOW TO RETURN hsl.to.rgb(h, s, l): 
 * 	SELECT: 
 * 		l<=0.5: PUT l*(s+1) IN m2
 * 		ELSE: PUT l+s-l*s IN m2
 * 	PUT l*2-m2 IN m1
 * 	PUT hue.to.rgb(m1, m2, h+1/3) IN r
 * 	PUT hue.to.rgb(m1, m2, h    ) IN g
 * 	PUT hue.to.rgb(m1, m2, h-1/3) IN b
 * 	RETURN (r, g, b)
 ******************************************************************************/
  if(l <= 0.5) {
  	m2 = l * s + l;
  }
  else {
  	m2 = l + s - l * s;
  }
  m1 = l * 2 - m2;
  privateData.r = hue2rgb(m1, m2, h + 1 / 3) * 255;
  privateData.g = hue2rgb(m1, m2, h) * 255;
  privateData.b = hue2rgb(m1, m2, h - 1 / 3) * 255;
}


function hue2rgb(m1, m2, h) {
/*******************************************************************************
 * From http://www.w3.org/TR/2003/CR-css3-color-20030514/:
 * HOW TO RETURN hue.to.rgb(m1, m2, h): 
 * 	 IF h<0: PUT h+1 IN h
 * 	 IF h>1: PUT h-1 IN h
 * 	 IF h*6<1: RETURN m1+(m2-m1)*h*6
 * 	 IF h*2<1: RETURN m2
 * 	 IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6
 * 	 RETURN m1
 ******************************************************************************/
  return 6 * (h += (h < 0 ? 1 : h > 1 ? -1 : 0)) < 1
    ? m1 + (m2 - m1) * 6 * h
    : 2 * h < 1
      ? m2
      : 3 * h < 2
        ? m1 + (m2 - m1) * ((2 / 3) - h) * 6
        : m1;
}

// Shortcuts for black and white.
var black = new Color(), white = new Color(255, 255, 255);
/*ENDIF*/

/*IF[Color.random()]*/
Color.random = function(r, g, b) {
	for(var c = [[r || 0, 0], [g || 0, 1], [b || 0, 2]].sort(function(a, b) {
		return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0;
	}), ret = [], lastIndex, lastVal, i = 0; i < 3; i++) {
		if(c[i][0] instanceof Array)
			ret[c[i][1]] = c[i][0].length == 1
				? c[i][0][0]
				: Math.randomIn.apply(null, c[i][0]);
		else {
			if(c[i][0] != lastIndex || lastIndex == 0)
				lastVal = Math.round(Math.randomIn(lastIndex > 0 ? lastVal : 0, 255));
			lastIndex = c[i][0];
			ret[c[i][1]] = lastVal;
		}
	}
	return new Color(ret[0], ret[1], ret[2]);
};
/*ENDIF*/

/*IF[Math.randomIn(),Color.random()]*/
Math.randomIn = function(min, max) {
	if(!isFinite(min = +min))
		min = 0;
	if(!isFinite(max = +max))
		max = 1;
	return Math.random() * (max - min) + min;
};
/*ENDIF*/

/*IF[Math.isPrime()]*/
Math.isPrime = function(num) {
	if(!isFinite(num) || num == null || num === "" || (((num = +num) + "").indexOf(".") + 1))
		throw new TypeError("expected a finite integer");
	if(num < 2)
		return false;
	if(num < 4)
		return true;
	if(num % 2 == 0 || num % 3 == 0)
		return false;
	for(var max = parseInt(Math.sqrt(num)) + 2, check = 6; check <= max; check += 6)
		if(num % (check - 1) == 0 || num % (check + 1) == 0)
			return false;
	return true;
};
/*ENDIF*/

/*IF[Math.nthRoot()]*/
Math.nthRoot = function(n, x) {
  try {
    var negate = n % 2 == 1 && x < 0;
    if(negate)
      x = -x;
    var possible = Math.pow(x, 1 / n);
    n = Math.pow(possible, n);
    if(Math.abs(x - n) < 1 && (x > 0 == n > 0))
      return negate ? -possible : possible;
  } catch(e){}
};
/*ENDIF*/

/*IF[RegExp.escape()]*/
RegExp.escape = function(aString, regExpFlags) {
  aString = aString.replace(/([\[\]\(\)\{\}\.\+\*\^\$\|\\\/])/g, "\\$1");
  return new RegExp(aString, regExpFlags);
};
/*ENDIF*/

/*IF[RegExp.fromWildExp(),Wildcard String Functions]*/
RegExp.fromWildExp = function(pat, opts) {
	var oOpt = opts && opts.indexOf("o") > -1;
	var i, m, p = "", sAdd = (opts && opts.indexOf("l") > -1 ? "" : "?");
	var re = new RegExp("~.|\\[!|" + (oOpt ? "{\\d+,?\\d*\\}|[" : "[")
		+ (opts && opts.indexOf("p") > -1 ? "" : "\\(\\)")
		+ "\\{\\}\\\\\\.\\*\\+\\?\\:\\|\\^\\$%_#<>]");
	while((i = pat.search(re)) > -1 && i < pat.length) {
		p += pat.substring(0, i);
		if((m = pat.match(re)[0]) == "[!")
			p += "[^";
		else if(m.charAt(0) == "~")
			p += "\\" + m.charAt(1);
		else if(m == "*" || m == "%")
			p += ".*" + sAdd;
		else if(m == "?" || m == "_")
			p += ".";
		else if(m == "#")
			p += "\\d";
		else if(oOpt && m.charAt(0) == "{")
			p += m + sAdd;
		else if(m == "<")
			p += "\\b(?=\\w)";
		else if(m == ">")
			p += "(?:\\b$|(?=\\W)\\b)";
		else
			p += "\\" + m;
		pat = pat.substring(i + m.length);
	}
	p += pat;
	if(opts) {
		if(/[ab]/.test(opts))
			p = "^" + p;
		if(/[ae]/.test(opts))
			p += "$";
	}
	return new RegExp(p, opts ? opts.replace(/[^gim]/g, "") : "");
};
/*ENDIF*/

/*IF[Wildcard String Functions]*/
extend(String.prototype, {
	// Find one or more substrings which match the specified wildcard expression.
	findPattern : function(pat, opts) {
		var arr = this.match(RegExp.fromWildExp(pat, opts));
		return arr != null && (opts || "").indexOf("g") < 0 ? arr[0] : arr;
	},
	// Find one or more indices which match the specified wildcard expression.
	indexOfPattern : function(pat, opts) {
		var ret = [];
		this.replace(RegExp.fromWildExp(pat, opts), function() {
			ret.push(arguments[arguments.length - 2]);
		});
		return ((opts || "").indexOf("g") < 0 || !ret.length)
			? ret[0] || null
			: ret;
	},
	// Find and replace one or more substrings which match the specified wildcard
	// expression.
	replacePattern : function(pat, opts, rep) {
		return this.replace.apply(this, [RegExp.fromWildExp(pat, opts), rep]);
	}
});
/*ENDIF*/

/*IF[String Trimming]*/
(function(p) {
	p.trim = p.trim || function() {
		return this.trimLeft().trimRight();
	};
	p.trimLeft = p.trimLeft || function() {
		return this.replace(/^[\s\u00A0]+/, "");
	};
	p.trimRight = p.trimRight || function() {
		return this.replace(/[\s\u00A0]+$/, "");
	};
})(String.prototype);
/*ENDIF*/

/*IF[String Padding]*/
extend(String.prototype, {
	padLeft : function(numOfChars, padding) {
		if(!padding || padding.constructor !== String)
				padding = " ";
		var m = Math.max(Math.ceil((numOfChars - this.length) / padding.length), 0);
		return new Array(m + 1).join(padding).slice(this.length - numOfChars) + this;
	},
	padRight : function(numOfChars, padding) {
		if(!padding || padding.constructor !== String)
				padding = " ";
		var m = Math.max(Math.ceil((numOfChars - this.length) / padding.length), 0);
		return this + (new Array(m + 1).join(padding).slice(0, numOfChars - this.length));
	},
	padCenter : function(numOfChars, padding, rightDominant) {
		if(!padding || padding.constructor !== String)
				padding = " ";
		return this.padLeft(Math[rightDominant ? "ceil" : "floor"]((this.length + numOfChars) / 2), padding).padRight(numOfChars, padding);
	}
});
/*ENDIF*/

/*IF[HTML String Conversion]*/
var div = doc.createElement("DIV"),
	textAttr = ("innerText" in div) ? "innerText" : "textContent";
extend(String.prototype, {
	toHTML : function() {
		div[textAttr] = this;
		return div.innerHTML.replace(/  /g, " &nbsp;");
	},
	fromHTML : function() {
		div.innerHTML = this;
		return div[textAttr];
	},
	tag : function(tagName, attributes, escapeHTML) {
		var arr = [tagName], val;
		for(var name in attributes || {}) {
			if((val = attributes[name]) === false) {
				continue;
			}
			val = val !== true ? val + "" : name;
			arr.push(name + '="' + val.replace(/"/g, "&quot;") + '"');
		}
		return "<" + arr.join(" ") + ">"
			+ ((escapeHTML || (arguments.length < 3)) ? this.toHTML() : this)
			+ "</" + tagName + ">";
	}
});
/*ENDIF*/

/*IF[String.prototype.toProperCase()]*/
String.prototype.toProperCase = function() {
	return this.replace(/(^|[\u00A0\s])\S/g, function(a) {
		return a.toUpperCase();
	});
};
/*ENDIF*/

/*IF[String.prototype.compareTo()]*/
String.prototype.compareTo = function(subject, caseSensitive) {
	var me = !caseSensitive ? this.toUpperCase() : this;
	subject = !caseSensitive ? (subject + "").toUpperCase() : subject + "";
	return me < subject ? -1 : me > subject ? 1 : 0;
};
/*ENDIF*/

/*IF[String.prototype.splice()]*/
String.prototype.splice = function(index, howMany, newSubstring) {
  var argc = arguments.length;
  if((index = index << 0) < 0) {
    index = Math.max(this.length + index, 0);
  }
  if(argc == 1) {
    howMany = this.length;
  }
  else if((howMany = howMany << 0) < 0) {
    howMany = Math.max(this.length + howMany, index);
  }
  else {
    howMany += index;
  }
  return this.slice(0, index) + (argc > 2 ? newSubstring : "")
    + this.slice(howMany);
};
/*ENDIF*/

/*IF[String.prototype.count]*/
String.prototype.count = function(target) {
  return this.split(target).length - 1;
};
/*ENDIF*/

// Idea from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now
Date.now = Date.now || function() {
	return +new Date;
};

/*IF[Date.prototype.format()]*/
var shortDays = "Sun,Mon,Tue,Wed,Thu,Fri,Sat".split(",");
var fullDays = "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(",");
var shortMonths = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(",");
var fullMonths = "January,February,March,April,May,June,July,August,September,October,November,December".split(",");
function getOrdinalFor(intNum) {
	return (((intNum = Math.abs(intNum) % 100) % 10 == 1 && intNum != 11) ? "st"
		: (intNum % 10 == 2 && intNum != 12) ? "nd" : (intNum % 10 == 3
		&& intNum != 13) ? "rd" : "th");
}
function getISO8601Year(aDate) {
	var d = new Date(aDate.getFullYear() + 1, 0, 4);
	if((d - aDate) / 86400000 < 7 && (aDate.getDay() + 6) % 7 < (d.getDay() + 6) % 7)
		return d.getFullYear();
	if(aDate.getMonth() > 0 || aDate.getDate() >= 4)
		return aDate.getFullYear();
	return aDate.getFullYear() - (((aDate.getDay() + 6) % 7 - aDate.getDate() > 2) ? 1 : 0);
}
function getISO8601Week(aDate) {
	// Get a day during the first week of the year.
	var d = new Date(getISO8601Year(aDate), 0, 4);
	// Get the first monday of the year.
	d.setDate(d.getDate() - (d.getDay() + 6) % 7);
	return parseInt((aDate - d) / 604800000) + 1;
}
Date.prototype.format = function(format) {
	// If the format was not passed, use the default toString method.
	if(typeof format !== "string" || /^\s*$/.test(format))
		return this + "";
	var jan1st = new Date(this.getFullYear(), 0, 1);
	var me = this;
	return format.replace(/[dDjlNSwzWFmMntLoYyaABgGhHisu]/g, function(option) {
		switch(option) {
			// Day of the month, 2 digits with leading zeros
			case "d": return ("0" + me.getDate()).replace(/^.+(..)$/, "$1");
			// A textual representation of a day, three letters
			case "D": return shortDays[me.getDay()];
			// Day of the month without leading zeros
			case "j": return me.getDate();
			// A full textual representation of the day of the week
			case "l": return fullDays[me.getDay()];
			// ISO-8601 numeric representation of the day of the week
			case "N": return (me.getDay() + 6) % 7 + 1;
			// English ordinal suffix for the day of the month, 2 characters
			case "S": return getOrdinalFor(me.getDate());
			// Numeric representation of the day of the week
			case "w": return me.getDay();
			// The day of the year (starting from 0)
			case "z": return Math.ceil((jan1st - me) / 86400000);
			// ISO-8601 week number of year, weeks starting on Monday
			case "W": return ("0" + getISO8601Week(me)).replace(/^.(..)$/, "$1");
			// A full textual representation of a month, such as January or March
			case "F": return fullMonths[me.getMonth()];
			// Numeric representation of a month, with leading zeros
			case "m": return ("0" + (me.getMonth() + 1)).replace(/^.+(..)$/, "$1");
			// A short textual representation of a month, three letters
			case "M": return shortMonths[me.getMonth()];
			// Numeric representation of a month, without leading zeros
			case "n": return me.getMonth() + 1;
			// Number of days in the given month
			case "t": return new Date(me.getFullYear(), me.getMonth() + 1, -1).getDate();
			// Whether it's a leap year
			case "L": return new Date(me.getFullYear(), 1, 29).getDate() == 29 ? 1 : 0;
			// ISO-8601 year number. This has the same value as Y, except that if the
			// ISO week number (W) belongs to the previous or next year, that year is
			// used instead.
			case "o": return getISO8601Year(me);
			// A full numeric representation of a year, 4 digits
			case "Y": return me.getFullYear();
			// A two digit representation of a year
			case "y": return (me.getFullYear() + "").replace(/^.+(..)$/, "$1");
			// Lowercase Ante meridiem and Post meridiem
			case "a": return me.getHours() < 12 ? "am" : "pm";
			// Uppercase Ante meridiem and Post meridiem
			case "A": return me.getHours() < 12 ? "AM" : "PM";
			// Swatch Internet time
			case "B": return Math.floor((((me.getUTCHours() + 1) % 24) + me.getUTCMinutes() / 60 + me.getUTCSeconds() / 3600) * 1000 / 24);
			// 12-hour format of an hour without leading zeros
			case "g": return me.getHours() % 12 != 0 ? me.getHours() % 12 : 12;
			// 24-hour format of an hour without leading zeros
			case "G": return me.getHours();
			// 12-hour format of an hour with leading zeros
			case "h": return ("0" + (me.getHours() % 12 != 0 ? me.getHours() % 12 : 12)).replace(/^.+(..)$/, "$1");
			// 24-hour format of an hour with leading zeros
			case "H": return ("0" + me.getHours()).replace(/^.+(..)$/, "$1");
			// Minutes with leading zeros
			case "i": return ("0" + me.getMinutes()).replace(/^.+(..)$/, "$1");
			// Seconds, with leading zeros
			case "s": return ("0" + me.getSeconds()).replace(/^.+(..)$/, "$1");
			// Milliseconds
			case "u": return me.getMilliseconds();
		}
	});
};
/*ENDIF*/

/*IF[jPaq.parseArray(),DOM Selector,Function.prototype.curry()]*/
function parseArray(objArray) {
	/*IF[DOM Selector]*/
	if(objArray instanceof jPaq) {
		return objArray.get();
	}
	/*ENDIF*/
	
	if(!objArray || !isFinite(objArray.length || "a") || objArray.length < 0) {
		return [];
	}
	try {
		return Array.prototype.slice.call(objArray);
	}
	catch(e) {
		for(var arr = [], i = objArray.length - 1; i >= 0; i--)
			arr[i] = objArray[i];
		return arr;
	}
}
/*ENDIF*/

// Make jPaq globally accessible.
var oldJPaq = global.jPaq;
global.jPaq = jPaq;

})(
	/*IF[Color Class,DOM Selector,Event Handling]*/
	// The function responsible for making private data accessible to internal
	// functions.  Define privatize here just in-case the user needs multiple
	// instances of jPaq to communicate.  In such a case, the user will need to
	// assign this object to variable and then pass that variable into the closure
	// of the other version.
	(function() {
		function privatize(obj, privateData) {
			obj._ = function(aKey) {
				if(privatize === aKey)
					return privateData;
			};
		};
		return privatize;
	})()
	/*ENDIF*/
);
