<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>site/app.rb</filename>
    </added>
    <added>
      <filename>site/config.ru</filename>
    </added>
    <added>
      <filename>site/favicon.ico</filename>
    </added>
    <added>
      <filename>site/public/css/global.css</filename>
    </added>
    <added>
      <filename>site/public/css/global.css.bak</filename>
    </added>
    <added>
      <filename>site/public/images/button_bgs.gif</filename>
    </added>
    <added>
      <filename>site/public/images/content_bg.gif</filename>
    </added>
    <added>
      <filename>site/public/images/content_bottom_corner.gif</filename>
    </added>
    <added>
      <filename>site/public/images/content_top_corner.gif</filename>
    </added>
    <added>
      <filename>site/public/images/fleegix_bg.gif</filename>
    </added>
    <added>
      <filename>site/public/images/fleegix_js_logo.gif</filename>
    </added>
    <added>
      <filename>site/public/images/merb.jpg</filename>
    </added>
    <added>
      <filename>site/public/images/simple_useful.gif</filename>
    </added>
    <added>
      <filename>site/public/images/text_elem_gradient.gif</filename>
    </added>
    <added>
      <filename>site/public/images/web2_badge.gif</filename>
    </added>
    <added>
      <filename>site/public/js/fleegix.jgz</filename>
    </added>
    <added>
      <filename>site/public/js/fleegix.js</filename>
    </added>
    <added>
      <filename>site/public/js/fleegix.js.gz</filename>
    </added>
    <added>
      <filename>site/public/js/fleegix.js.uncompressed.js</filename>
    </added>
    <added>
      <filename>site/public/js/site.js</filename>
    </added>
    <added>
      <filename>site/views/build.erb</filename>
    </added>
    <added>
      <filename>site/views/contribute.erb</filename>
    </added>
    <added>
      <filename>site/views/docs.erb</filename>
    </added>
    <added>
      <filename>site/views/download.erb</filename>
    </added>
    <added>
      <filename>site/views/faq.erb</filename>
    </added>
    <added>
      <filename>site/views/index.erb</filename>
    </added>
    <added>
      <filename>site/views/layout.erb</filename>
    </added>
    <added>
      <filename>site/views/layout.erb.bak</filename>
    </added>
    <added>
      <filename>site/views/plugins.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/color/convert.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/date/date.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/date/util.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/ejs.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/form/diff.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/form/restore.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/hash/hash.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/popup.erb</filename>
    </added>
    <added>
      <filename>site/views/plugins/xml.erb</filename>
    </added>
    <added>
      <filename>site/views/ref.erb</filename>
    </added>
    <added>
      <filename>site/views/thanks.erb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1 +1 @@
-if(typeof fleegix==&quot;undefined&quot;){var fleegix={}}if(typeof $==&quot;undefined&quot;){var $=function(A){return document.getElementById(A)}}var $elem=function(A,E){var C=E||{};var B=document.createElement(A);for(var D in C){B[D]=C[D]}return B};var $text=function(A){return document.createTextNode(A)};fleegix.bind=function(B,A){return function(){B.apply(A,arguments)}};fleegix.extend=function(A,B){return function(){A.apply(this,arguments);A.prototype.constructor.apply(this,arguments);B.apply(this,arguments);this.superClass=A;this.subClass=B}};fleegix.mixin=function(E,C){var B;if(typeof C==&quot;function&quot;){B=new C()}else{B=C}var A={};for(var D in B){if(typeof A[D]==&quot;undefined&quot;||baseObjj[D]!=B[D]){E[D]=B[D]}}return E};fleegix.clone=function(C){if(typeof C==&quot;object&quot;){var A;if(typeof C.constructor==&quot;function&quot;){A=new C.constructor()}else{A={}}for(var B in C){if(typeof C[B]==&quot;object&quot;&amp;&amp;C[B]!==null){A[B]=fleegix.clone(C[B])}else{A[B]=C[B]}}}else{A=C}return A};fleegix.ua=new function(){var C=navigator.userAgent;var A=function(F,G){var E=G.exec(F);if(E&amp;&amp;E.length&gt;1){E=E[1].substr(0,1);if(!isNaN(E)){return parseInt(E)}else{return null}}return null};this.isWebKit=C.indexOf(&quot;AppleWebKit&quot;)&gt;-1;this.isKHTML=C.indexOf(&quot;KHTML&quot;)&gt;-1;this.isGecko=C.indexOf(&quot;Gecko&quot;)&gt;-1&amp;&amp;!this.isWebKit&amp;&amp;!this.isKHTML;this.isOpera=C.indexOf(&quot;Opera&quot;)&gt;-1;this.isChrome=C.indexOf(&quot;Chrome&quot;)&gt;-1;this.isSafari=C.indexOf(&quot;Safari&quot;)&gt;-1&amp;&amp;!this.isChrome;this.isFF=C.indexOf(&quot;Firefox&quot;)&gt;-1||C.indexOf(&quot;Iceweasel&quot;)&gt;-1||C.indexOf(&quot;IceCat&quot;)&gt;-1;this.isFirefox=this.isFF;this.isIE=C.indexOf(&quot;MSIE &quot;)&gt;-1&amp;&amp;!this.isOpera;this.isIPhone=C.indexOf(&quot;iPhone&quot;)&gt;-1;this.isMobile=this.isIPhone||C.indexOf(&quot;Opera Mini&quot;)&gt;-1;this.isMac=C.indexOf(&quot;Mac&quot;)&gt;-1;this.isUnix=C.indexOf(&quot;Linux&quot;)&gt;-1||C.indexOf(&quot;BSD&quot;)&gt;-1||C.indexOf(&quot;SunOS&quot;)&gt;-1;this.isLinux=C.indexOf(&quot;Linux&quot;)&gt;-1;this.isWindows=C.indexOf(&quot;Windows&quot;)&gt;-1||C.indexOf(&quot;Win&quot;);this.majorVersion=null;var B={FF:/Firefox\/([0-9\.]*)/,Safari:/Version\/([0-9\.]*) /,IE:/MSIE ([0-9\.]*);/,Opera:/Opera\/([0-9\.]*) /,Chrome:/Chrome\/([0-9\.]*)/};for(var D in B){if(this[&quot;is&quot;+D]){this.majorVersion=A(C,B[D])}}for(var D in this){fleegix[D]=this[D]}};fleegix.fx=new function(){function B(G,D,H){var F={};var M=0;var I=0;if(D.blindType==&quot;clip&quot;){M=H==&quot;down&quot;?0:G.offsetHeight;I=H==&quot;down&quot;?G.offsetHeight:0;M=[0,G.offsetWidth,M,0];I=[0,G.offsetWidth,I,0];F.props={clip:[M,I]}}else{if(H==&quot;down&quot;){if(D.endHeight){I=D.endHeight}else{G.style.height=&quot;&quot;;var J=document.createElement(&quot;div&quot;);J.position=&quot;absolute&quot;;J.style.top=&quot;-9999999999px&quot;;J.style.left=&quot;-9999999999px&quot;;var K=G.parentNode;var C=K.removeChild(G);J.appendChild(C);document.body.appendChild(J);I=C.offsetHeight;G=J.removeChild(C);var L=document.body.removeChild(J);G.style.height=&quot;0px&quot;;K.appendChild(G)}M=0}else{M=G.offsetHeight;I=0}F.props={height:[M,I]}}for(var E in D){F[E]=D[E]}F.trans=&quot;lightEaseIn&quot;;return new fleegix.fx.Effecter(G,F)}function A(F,E,C){var D=C==&quot;in&quot;?0:100;var H=C==&quot;in&quot;?100:0;var I={props:{opacity:[D,H]},trans:&quot;lightEaseIn&quot;};for(var G in E){I[G]=E[G]}return new fleegix.fx.Effecter(F,I)}this.fadeOut=function(E,D){return A(E,D,&quot;out&quot;);E.style.visibility=&quot;hidden&quot;;var C=this.setCssProp(E,&quot;opacity&quot;,100)};this.fadeIn=function(E,D){var C=this.setCssProp(E,&quot;opacity&quot;,0);E.style.visibility=&quot;visible&quot;;return A(E,D,&quot;in&quot;)};this.blindUp=function(D,C){var E=C||{};E.blindType=E.blindType||&quot;height&quot;;return B(D,E,&quot;up&quot;)};this.blindDown=function(D,C){var E=C||{};E.blindType=E.blindType||&quot;height&quot;;return B(D,E,&quot;down&quot;)};this.setCSSProp=function(D,E,C){if(E==&quot;opacity&quot;){if(document.all){D.style.filter=&quot;alpha(opacity=&quot;+C+&quot;)&quot;}else{var F=C/100;D.style.opacity=F}}else{if(E==&quot;clip&quot;||E.toLowerCase().indexOf(&quot;color&quot;)&gt;-1){D.style[E]=C}else{D.style[E]=document.all?parseInt(C,10)+&quot;px&quot;:C+&quot;px&quot;}}return true};this.setCssProp=this.setCSSProp;this.hexPat=/^[#]{0,1}([\w]{1,2})([\w]{1,2})([\w]{1,2})$/;this.hex2rgb=function(G){var C=[];var F=G.match(this.hexPat);if(F){for(var D=1;D&lt;F.length;D++){var E=F[D];E=E.length==1?E+E:E;C.push(parseInt(E,16))}return C}else{throw (&quot;\&quot;&quot;+G+&quot;\&quot; not a valid hex value.&quot;)}}};fleegix.fx.Effecter=function(B,A){var C=this;this.props=A.props;this.trans=A.trans||&quot;lightEaseIn&quot;;this.duration=A.duration||500;this.fps=30;this.startTime=new Date().getTime();this.timeSpent=0;this.doBeforeStart=A.doBeforeStart||null;this.doAfterFinish=A.doAfterFinish||null;this.autoStart=A.autoStart===false?false:true;if(typeof this.transitions[this.trans]!=&quot;function&quot;){throw (&quot;\&quot;&quot;+this.trans+&quot;\&quot; is not a valid transition.&quot;)}this.start=function(){C.id=setInterval(function(){C.doStep.apply(C,[B])},Math.round(1000/C.fps));if(typeof A.doBeforeStart==&quot;function&quot;){C.doBeforeStart()}};if(this.autoStart){this.start()}return this};fleegix.fx.Effecter.prototype.doStep=function(C){var B=new Date().getTime();var D=this.props;if(B&lt;(this.startTime+this.duration)){this.timeSpent=B-this.startTime;for(var A in D){fleegix.fx.setCSSProp(C,A,this.calcCurrVal(A))}}else{for(var A in D){if(A==&quot;clip&quot;){fleegix.fx.setCSSProp(C,A,&quot;rect(&quot;+D[A][1].join(&quot;px,&quot;)+&quot;px)&quot;)}else{fleegix.fx.setCSSProp(C,A,D[A][1])}}clearInterval(this.id);if(typeof this.doAfterFinish==&quot;function&quot;){this.doAfterFinish()}}};fleegix.fx.Effecter.prototype.calcCurrVal=function(G){var A=this.props[G][0];var F=this.props[G][1];var I=this.transitions[this.trans];var B;var D;var J;var H;var E;if(G.toLowerCase().indexOf(&quot;color&quot;)&gt;-1){B=fleegix.fx.hex2rgb(A);D=fleegix.fx.hex2rgb(F);J=[];for(var C=0;C&lt;B.length;C++){H=B[C];E=D[C];J.push(parseInt(I(this.timeSpent,H,(E-H),this.duration),10))}return&quot;rgb(&quot;+J.join()+&quot;)&quot;}else{if(G==&quot;clip&quot;){B=A;D=F;J=[];for(var C=0;C&lt;B.length;C++){H=B[C];E=D[C];J.push(parseInt(I(this.timeSpent,H,(E-H),this.duration),10))}return&quot;rect(&quot;+J.join(&quot;px,&quot;)+&quot;px)&quot;}else{return I(this.timeSpent,A,(F-A),this.duration)}}};fleegix.fx.Effecter.prototype.transitions={linear:function(B,A,D,C){return D*(B/C)+A},lightEaseIn:function(B,A,D,C){return D*(B/=C)*B+A},lightEaseOut:function(B,A,D,C){return -D*(B/=C)*(B-2)+A},lightEaseInOut:function(B,A,D,C){if((B/=C/2)&lt;1){return D/2*B*B+A}return -D/2*((--B)*(B-2)-1)+A},heavyEaseIn:function(B,A,D,C){return D*(B/=C)*B*B+A},heavyEaseOut:function(B,A,D,C){return D*((B=B/C-1)*B*B+1)+A},heavyEaseInOut:function(B,A,D,C){if((B/=C/2)&lt;1){return D/2*B*B*B+A}return D/2*((B-=2)*B*B+2)+A}};fleegix.dom=new function(){var A=function(B){if(document.all){if(document.documentElement&amp;&amp;document.documentElement[&quot;client&quot;+B]){return document.documentElement[&quot;client&quot;+B]}else{return document.body[&quot;client&quot;+B]}}else{return window[&quot;inner&quot;+B]}};this.getViewportWidth=function(){return A(&quot;Width&quot;)};this.getViewportHeight=function(){return A(&quot;Height&quot;)};this.center=function(G){var B=G.offsetWidth;var E=G.offsetHeight;var F=fleegix.dom.getViewportWidth();var H=fleegix.dom.getViewportHeight();var D=parseInt((F/2)-(B/2),10);var C=parseInt((H/2)-(E/2),10);C+=document.documentElement.scrollTop;G.style.left=D+&quot;px&quot;;G.style.top=C+&quot;px&quot;;return true};this.getOffset=function(D){var C=function(F){var G=0;var E=0;if(F.offsetParent){do{G+=F.offsetLeft;E+=F.offsetTop}while(F=F.offsetParent)}return{left:G,top:E}};var B=null;if(fleegix.isIE||fleegix.isMoz){B=D.getBoundingClientRect()}else{B=C(D)}return B}};fleegix.url=new function(){var E=this;var D=&quot;\\?|;&quot;;var C=new RegExp(D);var B=new RegExp(&quot;(&quot;+D+&quot;)&quot;);var A=function(L,M,F,I){var K=B.exec(M);var H;var G;var N;var J;var O=&quot;&quot;;if(K&amp;&amp;K.length&gt;0){H=K[0]}if(H){G=E.getBase(M);N=E.getQS(M)}else{N=M}J=E.qsToObject(N,{arrayizeMulti:true});if(L==&quot;set&quot;){J[F]=I}else{delete J[F]}if(G){O=G+H}O+=E.objectToQS(J);return O};this.qsToObject=function(N,H){var F=H||{};var M={};var O=F.arrayizeMulti||false;if(N){var L=N.split(&quot;&amp;&quot;);for(var K=0;K&lt;L.length;K++){var J=L[K].split(&quot;=&quot;);var G=J[0];var I=decodeURIComponent(J[1]);if(typeof M[G]!=&quot;undefined&quot;&amp;&amp;O){if(typeof M[G]==&quot;string&quot;){M[G]=[M[G]]}M[G].push(I)}else{M[G]=I}}}return M};this.objectToQS=function(K,G){var F=G||{};var N=&quot;&quot;;var M=F.stripTags?/&lt;[^&gt;]*&gt;/g:null;for(var H in K){var R=&quot;&quot;;var P=K[H];if(P!=undefined){if(P.length&amp;&amp;typeof P!=&quot;string&quot;){var Q=&quot;&quot;;if(F.collapseMulti){Q=&quot;,&quot;;N+=H+&quot;=&quot;}else{Q=&quot;&amp;&quot;}for(var I=0;I&lt;P.length;I++){R=F.stripTags?P[I].replace(M,&quot;&quot;):P[I];R=(!F.collapseMulti)?H+&quot;=&quot;+encodeURIComponent(R):encodeURIComponent(R);N+=R+Q}N=N.substr(0,N.length-1)}else{R=F.stripTags?P.replace(M,&quot;&quot;):P;N+=H+&quot;=&quot;+encodeURIComponent(R)}N+=&quot;&amp;&quot;}else{if(F.includeEmpty){N+=H+&quot;=&amp;&quot;}}}if(F.deCamelizeParams){if(!fleegix.string){throw new Error(&quot;deCamelize option depends on fleegix.string module.&quot;)}var L=N.split(&quot;&amp;&quot;);var O;N=&quot;&quot;;for(var J=0;J&lt;L.length;J++){O=L[J].split(&quot;=&quot;);if(O[0]){N+=fleegix.string.deCamelize(O[0])+&quot;=&quot;+O[1]+&quot;&amp;&quot;}}}N=N.substr(0,N.length-1);return N};this.objectToQs=this.objectToQS;this.getQSParam=function(L,F,K){var J=null;var I=C.test(L)?E.getQS(L):L;var H=K||{};if(I){var G=E.qsToObject(I,H);J=G[F]}return J};this.getQsParam=this.getQSParam;this.setQSParam=function(H,F,G){return A(&quot;set&quot;,H,F,G)};this.setQsParam=this.setQSParam;this.removeQSParam=function(G,F){return A(&quot;remove&quot;,G,F,null)};this.removeQsParam=this.removeQSParam;this.getQS=function(F){return F.split(C)[1]};this.getQs=this.getQS;this.getBase=function(F){return F.split(C)[0]}};fleegix.uri=new function(){this.getParamHash=fleegix.url.qsToObject;this.getParam=function(A,C){var B=C||fleegix.url.getQS(document.location.href);return fleegix.url.getQSParam(B,A)};this.setParam=function(A,D,C){var B=C||fleegix.url.getQS(document.location.href);return fleegix.url.setQSParam(B,A,D)};this.getQuery=fleegix.url.getQS;this.getBase=fleegix.url.getBase};fleegix.css=new function(){this.addClass=function(B,A){fleegix.css.removeClass(B,A);var C=B.className;C+=&quot; &quot;+A;C=fleegix.string.trim(C);B.className=C};this.removeClass=function(C,B){var D=C.className;var A=&quot;\\b&quot;+B+&quot;\\b&quot;;A=new RegExp(A,&quot;g&quot;);D=D.replace(A,&quot;&quot;);D=D.replace(&quot;  &quot;,&quot; &quot;);D=fleegix.string.trim(D);C.className=D};this.replaceClass=function(B,A,C){this.removeClass(B,A);this.addClass(B,C)}};fleegix.event=new function(){var B=[];var A={};this.compatibilityMode=false;this.listen=function(){var G=arguments[0];var D=arguments[1];var F=this.compatibilityMode;var E={};var H={};if(typeof arguments[2]==&quot;function&quot;){E.method=arguments[2];H=arguments[3]||{}}else{E.context=arguments[2];E.method=arguments[3];H=arguments[4]||{}}if(!G){throw new Error(&quot;fleegix.listen called on an object (&quot;+G+&quot;) that does not exist.&quot;)}if(D==&quot;onmousewheel&quot;){if(window.addEventListener&amp;&amp;typeof G.onmousewheel==&quot;undefined&quot;){G.onmousewheel=null}}var C;if(this.compatibilityMode){if(G[D]&amp;&amp;G._fleegixEventListenReg){C=G._fleegixEventListenReg[D]}else{C=null}}else{C=G[D]?G[D].listenReg:null}if(!C){C={};C.orig={};C.orig.obj=G;C.orig.methName=D;if(G[D]){C.orig.methCode=G[D]}C.after=[];G[D]=function(){var L=F?G._fleegixEventListenReg[D]:G[D].listenReg;if(!L){if(G[&quot;_&quot;+D+&quot;_suppressErrors&quot;]){return false}else{throw new Error(&quot;Cannot execute handlers for &quot;+G+&quot;  \&quot;&quot;+D+&quot;\&quot;. Something (likely another JavaScript library) has removed the fleegix.event.listen handler registry.&quot;)}}var I=[];for(var K=0;K&lt;arguments.length;K++){I.push(arguments[K])}if(L.orig.methCode){L.orig.methCode.apply(L.orig.obj,I)}var M=null;if(G.attachEvent||G.nodeType||G.addEventListener){if(!I.length){try{switch(true){case !!G.ownerDocument:M=G.ownerDocument.parentWindow.event;break;case !!G.documentElement:M=G.documentElement.ownerDocument.parentWindow.event;break;case !!G.event:M=G.event;break;default:M=window.event;break}}catch(O){M=window.event}}else{M=I[0]}if(M){if(typeof M.target==&quot;undefined&quot;){M.target=M.srcElement}if(typeof M.srcElement==&quot;undefined&quot;){M.srcElement=M.target}if(M.type==&quot;DOMMouseScroll&quot;||M.type==&quot;mousewheel&quot;){if(M.wheelDelta){M.delta=M.wheelDelta/120}else{if(M.detail){M.delta=-M.detail/3}}}I[0]=M}}for(var K=0;K&lt;L.after.length;K++){var J=L.after[K];var N=null;var P=null;if(!J.context){N=J.method;P=window}else{N=J.context[J.method];P=J.context}if(typeof N!=&quot;function&quot;){throw (N+&quot; is not an executable function.&quot;)}else{N.apply(P,I)}M=I[0];if(J.stopPropagation){this.stopPropagation(M)}if(J.preventDefault){this.preventDefault(M)}}};if(this.compatibilityMode){if(!G._fleegixEventListenReg){G._fleegixEventListenReg={}}G._fleegixEventListenReg[D]=C}else{G[D].listenReg=C}B.push(C);if(D==&quot;onmousewheel&quot;){if(window.addEventListener){G.addEventListener(&quot;DOMMouseScroll&quot;,G.onmousewheel,false)}}}C.after.push(E);if(this.compatibilityMode){if(!G._fleegixEventListenReg){G._fleegixEventListenReg={}}G._fleegixEventListenReg[D]=C}else{G[D].listenReg=C}};this.unlisten=function(){var H=arguments[0];var E=arguments[1];var D;if(this.compatibilityMode){if(H[E]&amp;&amp;H._fleegixEventListenReg){D=H._fleegixEventListenReg[E]}else{D=null}}else{D=H[E]?H[E].listenReg:null}var C=null;if(!D){return false}for(var F=0;F&lt;D.after.length;F++){var G=D.after[F];if(typeof arguments[2]==&quot;function&quot;){if(G.method==arguments[2]){D.after.splice(F,1);break}}else{if(G.context==arguments[2]&amp;&amp;G.method==arguments[3]){D.after.splice(F,1);break}}}if(this.compatibilityMode){H._fleegixEventListenReg[E]=D}else{H[E].listenReg=D}};this.flush=function(){for(var C=0;C&lt;B.length;C++){var D=B[C];removeObj=D.orig.obj;removeMethod=D.orig.methName;removeObj[removeMethod]=null}};this.subscribe=function(C,D,E){if(!D){return }if(!A[C]){A[C]={};A[C].audience=[]}else{this.unsubscribe(C,D)}A[C].audience.push([D,E])};this.unsubscribe=function(E,D){if(!D){A[E]=null}else{if(A[E]){var F=A[E].audience;for(var C=0;C&lt;F.length;C++){if(F[C][0]==D){F.splice(C,1)}}}}};this.publish=function(F,G){if(A[F]){var H=A[F].audience;for(var D=0;D&lt;H.length;D++){var C=H[D][0];var E=H[D][1];C[E](G)}}};this.getSrcElementByAttribute=function(D,E){var C;if(D.srcElement){C=D.srcElement}else{if(D.target){C=D.target}}if(!C||typeof C[E]==&quot;undefined&quot;){return null}else{while(!C[E]||C.nodeType==3){if(C.parentNode){C=C.parentNode}else{return null}}}return C};this.getSrcElementId=function(D){var C=this.getSrcElementByAttribute(D,&quot;id&quot;)||null;return C.id||null};this.annihilate=function(C){this.stopPropagation(C);this.preventDefault(C)};this.stopPropagation=function(C){if(C.stopPropagation){C.stopPropagation()}else{C.cancelBubble=true}return C};this.preventDefault=function(C){if(C.preventDefault){C.preventDefault()}else{C.returnValue=false}return C};this.suppressHandlerErrors=function(D,C){D[&quot;_&quot;+C+&quot;_suppressErrors&quot;]=true}};fleegix.xhr=new function(){this.maxXhrs=5;this.lastReqId=0;this.debug=false;this.defaultTimeoutSeconds=300;this.useDefaultErrHandlerForSync=true;this.responseFormats={TXT:&quot;text&quot;,XML:&quot;xml&quot;,OBJ:&quot;object&quot;};this.get=function(){var X={};var S=null;var U=Array.prototype.slice.apply(arguments);if(typeof U[0]==&quot;function&quot;){X.async=true;S=U.shift()}else{X.async=false}var T=U.shift();if(typeof U[0]==&quot;object&quot;){var V=U.shift();for(var W in V){X[W]=V[W]}}else{X.responseFormat=U.shift()||&quot;text&quot;}X.handleSuccess=S;X.url=T;return this.doReq(X)};this.doGet=function(){return this.get.apply(this,arguments)};this.post=function(){var Y={};var S=null;var U=Array.prototype.slice.apply(arguments);if(typeof U[0]==&quot;function&quot;){Y.async=true;S=U.shift()}else{Y.async=false}var T=U.shift();var W=U.shift();if(typeof U[0]==&quot;object&quot;){var V=U.shift();for(var X in V){Y[X]=V[X]}}else{Y.responseFormat=U.shift()||&quot;text&quot;}Y.handleSuccess=S;Y.url=T;Y.data=W;Y.method=&quot;POST&quot;;return this.doReq(Y)};this.doPost=function(){return this.post.apply(this,arguments)};this.doReq=function(S){return this.send(S)};this.send=function(W){var T=W||{};var S=new fleegix.xhr.Request();var V=null;for(var U in T){if(T.hasOwnProperty(U)){S[U]=T[U]}}S.method=S.method.toUpperCase();S.id=this.lastReqId;this.lastReqId++;if(S.async){if(K.length){V=K.shift()}else{if(H.length&lt;this.maxXhrs){V=D()}}if(V!==null){G(S,V)}else{if(S.uber){J.unshift(S)}else{J.push(S)}}return S.id}else{return G(S)}};this.abort=function(U){var T=F[U];var S=H[T.xhrId];if(S){S.onreadystatechange=function(){};S.abort();T.aborted=true;O(T);return true}else{return false}};this.isReqSuccessful=function(T){var S=T.status;if(!S){return false}if(document.all&amp;&amp;S==1223){S=204}if((S&gt;199&amp;&amp;S&lt;300)||S==304){return true}else{return false}};var L=this;var Q=null;var M;var H=[];var J=[];var K=[];var F={};var N=[];var C=null;var I=null;var A=null;var D=function(V){var U=0;var T=[&quot;Msxml2.XMLHTTP.6.0&quot;,&quot;MSXML2.XMLHTTP.3.0&quot;,&quot;Microsoft.XMLHTTP&quot;];var S=null;if(window.XMLHttpRequest){S=new XMLHttpRequest()}else{if(window.ActiveXObject){if(Q){S=new ActiveXObject(Q)}else{for(var U=0;U&lt;T.length;U++){try{S=new ActiveXObject(T[U]);Q=T[U];break}catch(X){}}}}}if(S){if(V){return S}else{H.push(S);var W=H.length-1;return W}}else{throw new Error(&quot;Could not create XMLHttpRequest object.&quot;)}};var G=function(b,c){var Y=null;var Z=null;var T=&quot;&quot;;var W=null;if(b.async){Y=c;Z=H[Y];F[b.id]=b;N.unshift(b);b.xhrId=Y}else{if(!C){C=D(true)}Z=C;I=b}if(b.preventCache){var U=new Date().getTime();T=b.url.indexOf(&quot;?&quot;)&gt;-1?b.url+&quot;&amp;preventCache=&quot;+U:b.url+&quot;?preventCache=&quot;+U}else{T=b.url}if(document.all){Z.abort()}if(b.username&amp;&amp;b.password){Z.open(b.method,T,b.async,b.username,b.password)}else{Z.open(b.method,T,b.async)}if(b.mimeType&amp;&amp;navigator.userAgent.indexOf(&quot;MSIE&quot;)==-1){Z.overrideMimeType(b.mimeType)}var V=b.headers;for(var X in V){if(V.hasOwnProperty(X)){Z.setRequestHeader(X,V[X])}}if(b.method==&quot;POST&quot;||b.method==&quot;PUT&quot;){b.data=b.data||b.dataPayload;if(!b.data){b.data=&quot;&quot;}if(!fleegix.isSafari){var S=typeof b.data==&quot;string&quot;?b.data.length:0;Z.setRequestHeader(&quot;Content-Length&quot;,S)}if(typeof b.headers[&quot;Content-Type&quot;]==&quot;undefined&quot;){Z.setRequestHeader(&quot;Content-Type&quot;,&quot;application/x-www-form-urlencoded&quot;)}}Z.send(b.data);if(A===null){A=setTimeout(B,10)}if(!b.async){var a=R(Z,b);I=null;if(N.length){A=setTimeout(B,10)}else{A=null}return a}};var B=function(){var S=N;var X=new Date().getTime();if(I!==null){return }else{for(var U=0;U&lt;S.length;U++){var V=S[U];var T=H[V.xhrId];var W=((X-V.startTime)&gt;(V.timeoutSeconds*1000));switch(true){case (V.aborted||!T.readyState):N.splice(U,1);break;case W:N.splice(U,1);P(V);break;case (T.readyState==4):N.splice(U,1);R.call(L,T,V);break}}}clearTimeout(A);if(N.length){A=setTimeout(B,10)}else{A=null}};var R=function(S,T){var V;switch(T.responseFormat){case&quot;xml&quot;:if(T.xmlDocFromResponseText&amp;&amp;typeof fleegix.xml!=&quot;undefined&quot;){V=fleegix.xml.createDoc(S.responseText)}else{V=S.responseXML}break;case&quot;object&quot;:V=S;break;case&quot;text&quot;:default:V=S.responseText;break}if(T.handleAll){T.handleAll(V,T.id)}else{try{switch(true){case L.isReqSuccessful(S):if(T.async){if(!T.handleSuccess){throw new Error(&quot;No response handler defined for this request&quot;)}else{T.handleSuccess(V,T.id)}}else{return V}break;case (S.status==0):if(L.debug){throw new Error(&quot;XMLHttpRequest HTTP status is zero.&quot;)}break;case (S.status==M):if(L.debug){throw new Error(&quot;XMLHttpRequest HTTP status not set.&quot;)}break;default:if(!T.async&amp;&amp;!L.useDefaultErrHandlerForSync){return V}else{if(T.handleErr){T.handleErr(V,T.id)}else{E(S)}}break}}catch(U){throw U}}if(T.async){O(T)}return true};var P=function(S){if(L.abort.apply(L,[S.id])){if(typeof S.handleTimeout==&quot;function&quot;){S.handleTimeout()}else{alert(&quot;XMLHttpRequest to &quot;+S.url+&quot; timed out.&quot;)}}};var O=function(T){delete F[T.id];if(J.length){var S=J.shift();S.startTime=new Date().getTime();G(S,T.xhrId)}else{K.push(T.xhrId)}};var E=function(T){var S;try{S=window.open(&quot;&quot;,&quot;errorWin&quot;);S.document.body.innerHTML=T.responseText}catch(U){alert(&quot;An error occurred, but the error message cannot be displayed because of your browser's pop-up blocker.\nPlease allow pop-ups from this Web site.&quot;)}}};fleegix.xhr.Request=function(){this.id=0;this.xhrId=null;this.url=null;this.status=null;this.statusText=&quot;&quot;;this.method=&quot;GET&quot;;this.async=true;this.data=null;this.readyState=null;this.responseText=null;this.responseXML=null;this.handleSuccess=null;this.handleErr=null;this.handleAll=null;this.handleTimeout=null;this.responseFormat=fleegix.xhr.responseFormats.TXT;this.xmlDocFromResponseText=false;this.mimeType=null;this.username=&quot;&quot;;this.password=&quot;&quot;;this.headers=[];this.preventCache=false;this.startTime=new Date().getTime();this.timeoutSeconds=fleegix.xhr.defaultTimeoutSeconds;this.uber=false;this.aborted=false};fleegix.xhr.Request.prototype.setRequestHeader=function(B,A){this.headers.push(B+&quot;: &quot;+A)};fleegix.json=new function(){var _cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;this.serialize=function(obj){var str=&quot;&quot;;switch(typeof obj){case&quot;object&quot;:switch(true){case obj===null:return&quot;null&quot;;break;case obj instanceof Array:for(var i=0;i&lt;obj.length;i++){if(str){str+=&quot;,&quot;}str+=fleegix.json.serialize(obj[i])}return&quot;[&quot;+str+&quot;]&quot;;break;case (fleegix.isFF&amp;&amp;obj instanceof DOMException):str+=&quot;\&quot;&quot;+obj.toString()+&quot;\&quot;&quot;;break;case typeof obj.toString!=&quot;undefined&quot;:for(var i in obj){if(str){str+=&quot;,&quot;}str+=&quot;\&quot;&quot;+i+&quot;\&quot;:&quot;;if(typeof obj[i]==&quot;undefined&quot;){str+=&quot;\&quot;undefined\&quot;&quot;}else{str+=fleegix.json.serialize(obj[i])}}return&quot;{&quot;+str+&quot;}&quot;;break}return str;case&quot;unknown&quot;:case&quot;undefined&quot;:case&quot;function&quot;:return&quot;\&quot;undefined\&quot;&quot;;case&quot;string&quot;:str+=&quot;\&quot;&quot;+obj.replace(/([&quot;\\])/g,&quot;\\$1&quot;).replace(/\r/g,&quot;&quot;).replace(/\n/g,&quot;\\n&quot;)+&quot;\&quot;&quot;;return str;default:return String(obj)}};this.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&amp;&amp;typeof value===&quot;object&quot;){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}_cx.lastIndex=0;if(_cx.test(text)){text=text.replace(_cx,function(a){return&quot;\\u&quot;+(&quot;0000&quot;+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:[&quot;\\\/bfnrt]|u[0-9a-fA-F]{4})/g,&quot;@&quot;).replace(/&quot;[^&quot;\\\n\r]*&quot;|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,&quot;]&quot;).replace(/(?:^|:|,)(?:\s*\[)+/g,&quot;&quot;))){j=eval(&quot;(&quot;+text+&quot;)&quot;);return typeof reviver===&quot;function&quot;?walk({&quot;&quot;:j},&quot;&quot;):j}throw new SyntaxError(&quot;JSON not parseable.&quot;)}};fleegix.string=new function(){var D=/^\s+/;var A=/\s+$/;var C=/^\s+|\s+$/g;var B={&quot;&amp;&quot;:&quot;&amp;amp;&quot;,&quot;&lt;&quot;:&quot;&amp;lt;&quot;,&quot;&gt;&quot;:&quot;&amp;gt;&quot;,&quot;\&quot;&quot;:&quot;&amp;quot;&quot;,&quot;'&quot;:&quot;&amp;#39;&quot;};var F=function(G){return function(J){s=J;var H,K;for(var I in B){H=G==&quot;to&quot;?I:B[I];K=G==&quot;to&quot;?B[I]:I;s=s.replace(new RegExp(H,&quot;gm&quot;),K)}return s}};var E=function(){return function(H){var G=&quot;&quot;;for(var I in B){G+=I+&quot;|&quot;}G=G.substr(0,G.length-1);G=new RegExp(G,&quot;gm&quot;);return G.test(H)}};this.escapeXML=F(&quot;to&quot;);this.unescapeXML=F(&quot;from&quot;);this.needsEscape=E();this.toArray=function(I){var G=[];for(var H=0;H&lt;I.length;H++){G[H]=I.substr(H,1)}return G};this.reverse=function(G){return this.toArray(G).reverse().join(&quot;&quot;)};this.ltrim=function(I,H){var G=H?new RegExp(&quot;^&quot;+H+&quot;+&quot;):D;return I.replace(G,&quot;&quot;)};this.rtrim=function(I,H){var G=H?new RegExp(H+&quot;+$&quot;):A;return I.replace(G,&quot;&quot;)};this.trim=function(I,H){var G=H?new RegExp(&quot;^&quot;+H+&quot;+|&quot;+H+&quot;+$&quot;,&quot;g&quot;):C;return I.replace(G,&quot;&quot;)};this.lpad=function(J,I,H){var G=J;while(G.length&lt;H){G=I+G}return G};this.rpad=function(J,I,H){var G=J;while(G.length&lt;H){G=G+I}return G};this.toLowerCaseWithUnderscores=function(G){return G.replace(/([A-Z]+)/g,&quot;_$1&quot;).toLowerCase().replace(/^_/,&quot;&quot;)};this.deCamelize=function(G){return this.toLowerCaseWithUnderscores(G)};this.toCamelCase=function(G){return G.replace(/_[a-z]{1}/g,function(H){return H.replace(&quot;_&quot;,&quot;&quot;).toUpperCase()})};this.camelize=function(G){return this.toCamelCase(G)};this.capitalize=function(G){return G.substr(0,1).toUpperCase()+G.substr(1)}};fleegix.cookie=new function(){this.set=function(B,H,E){var A=E||{};var K=&quot;/&quot;;var I=0;var G=0;var F=0;var D=&quot;&quot;;var J=0;if(typeof E==&quot;object&quot;){K=A.path||&quot;/&quot;;I=A.days||0;G=A.hours||0;F=A.minutes||0}else{K=E||&quot;/&quot;}J+=I?I*24*60*60*1000:0;J+=G?G*60*60*1000:0;J+=F?F*60*1000:0;if(J){var C=new Date();C.setTime(C.getTime()+J);D=&quot;; expires=&quot;+C.toGMTString()}else{D=&quot;&quot;}document.cookie=B+&quot;=&quot;+H+D+&quot;; path=&quot;+K};this.get=function(B){var D=B+&quot;=&quot;;var A=document.cookie.split(&quot;;&quot;);for(var C=0;C&lt;A.length;C++){var E=A[C];while(E.charAt(0)==&quot; &quot;){E=E.substring(1,E.length)}if(E.indexOf(D)===0){return E.substring(D.length,E.length)}}return null};this.create=this.set;this.destroy=function(A,C){var B={};B.minutes=-1;if(C){B.path=C}this.set(A,&quot;&quot;,B)}};fleegix.form={};fleegix.form.serialize=function(C,B){var A=fleegix.form.toObject(C,B);if(typeof fleegix.url==&quot;undefined&quot;){throw new Error(&quot;fleegix.form.serialize depends on the fleegix.url module.&quot;)}var D=fleegix.url.objectToQS(A,B);return D};fleegix.form.toObject=function(K,D){var A=D||{};var J={};function H(R,Q){if(R){var P=null;if(typeof R==&quot;string&quot;){P=[];P.push(R)}else{P=R}P.push(Q);return P}else{return Q}}for(var I=0;I&lt;K.elements.length;I++){var F=K.elements[I];if(F.name){var O=F.name.indexOf(&quot;[&quot;);var C=F.name.indexOf(&quot;]&quot;);var N=&quot;&quot;;var B=&quot;&quot;;var M;var E;if(A.hierarchical&amp;&amp;(O&gt;0)&amp;&amp;(C&gt;2)){N=F.name.substring(0,O);B=F.name.substring(O+1,C);if(typeof J[N]==&quot;undefined&quot;){J[N]={}}M=J[N];E=B}else{M=J;E=F.name}switch(F.type){case&quot;text&quot;:case&quot;hidden&quot;:case&quot;password&quot;:case&quot;textarea&quot;:case&quot;select-one&quot;:M[E]=F.value;break;case&quot;select-multiple&quot;:for(var G=0;G&lt;F.options.length;G++){var L=F.options[G];if(L.selected){M[E]=H(M[E],L.value)}}break;case&quot;radio&quot;:if(F.checked){M[E]=F.value}break;case&quot;checkbox&quot;:if(F.checked){M[E]=H(M[E],F.value)}break;case&quot;submit&quot;:case&quot;reset&quot;:case&quot;file&quot;:case&quot;image&quot;:case&quot;button&quot;:if(A.pedantic){M[E]=F.value}break}}}return J};fleegix.form.toHash=fleegix.form.toObject;if(typeof fleegix.date==&quot;undefined&quot;){fleegix.date={}}fleegix.date.util={};fleegix.date.util.weekdayLong=[&quot;Sunday&quot;,&quot;Monday&quot;,&quot;Tuesday&quot;,&quot;Wednesday&quot;,&quot;Thursday&quot;,&quot;Friday&quot;,&quot;Saturday&quot;];fleegix.date.util.weekdayShort=[&quot;Sun&quot;,&quot;Mon&quot;,&quot;Tue&quot;,&quot;Wed&quot;,&quot;Thu&quot;,&quot;Fri&quot;,&quot;Sat&quot;];fleegix.date.util.monthLong=[&quot;January&quot;,&quot;February&quot;,&quot;March&quot;,&quot;April&quot;,&quot;May&quot;,&quot;June&quot;,&quot;July&quot;,&quot;August&quot;,&quot;September&quot;,&quot;October&quot;,&quot;November&quot;,&quot;December&quot;];fleegix.date.util.monthShort=[&quot;Jan&quot;,&quot;Feb&quot;,&quot;Mar&quot;,&quot;Apr&quot;,&quot;May&quot;,&quot;Jun&quot;,&quot;Jul&quot;,&quot;Aug&quot;,&quot;Sep&quot;,&quot;Oct&quot;,&quot;Nov&quot;,&quot;Dec&quot;];fleegix.date.util.meridian={&quot;AM&quot;:&quot;AM&quot;,&quot;PM&quot;:&quot;PM&quot;};fleegix.date.util.supportedFormats={&quot;a&quot;:function(A){return fleegix.date.util.weekdayShort[A.getDay()]},&quot;A&quot;:function(A){return fleegix.date.util.weekdayLong[A.getDay()]},&quot;b&quot;:function(A){return fleegix.date.util.monthShort[A.getMonth()]},&quot;h&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%b&quot;)},&quot;B&quot;:function(A){return fleegix.date.util.monthLong[A.getMonth()]},&quot;c&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%a %b %d %T %Y&quot;)},&quot;C&quot;:function(A){return fleegix.date.util.calcCentury(A.getFullYear())},&quot;d&quot;:function(A){return fleegix.date.util.leftPad(A.getDate(),2,&quot;0&quot;)},&quot;D&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%m/%d/%y&quot;)},&quot;e&quot;:function(A){return fleegix.date.util.leftPad(A.getDate(),2,&quot; &quot;)},&quot;f&quot;:function(){return fleegix.date.util.strftimeNotImplemented(&quot;f&quot;)},&quot;F&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%Y-%m-%d&quot;)},&quot;g&quot;:function(){return fleegix.date.util.strftimeNotImplemented(&quot;g&quot;)},&quot;G&quot;:function(){return fleegix.date.util.strftimeNotImplemented(&quot;G&quot;)},&quot;H&quot;:function(A){return fleegix.date.util.leftPad(A.getHours(),2,&quot;0&quot;)},&quot;I&quot;:function(A){return fleegix.date.util.leftPad(fleegix.date.util.hrMil2Std(A.getHours()),2,&quot;0&quot;)},&quot;j&quot;:function(A){return fleegix.date.util.leftPad(fleegix.date.util.calcDays(A),3,&quot;0&quot;)},&quot;k&quot;:function(A){return fleegix.date.util.leftPad(A.getHours(),2,&quot; &quot;)},&quot;l&quot;:function(A){return fleegix.date.util.leftPad(fleegix.date.util.hrMil2Std(A.getHours()),2,&quot; &quot;)},&quot;m&quot;:function(A){return fleegix.date.util.leftPad((A.getMonth()+1),2,&quot;0&quot;)},&quot;M&quot;:function(A){return fleegix.date.util.leftPad(A.getMinutes(),2,&quot;0&quot;)},&quot;n&quot;:function(){return&quot;\n&quot;},&quot;p&quot;:function(A){return fleegix.date.util.getMeridian(A.getHours())},&quot;r&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%I:%M:%S %p&quot;)},&quot;R&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%H:%M&quot;)},&quot;S&quot;:function(A){return fleegix.date.util.leftPad(A.getSeconds(),2,&quot;0&quot;)},&quot;t&quot;:function(){return&quot;\t&quot;},&quot;T&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%H:%M:%S&quot;)},&quot;u&quot;:function(A){return fleegix.date.util.convertOneBase(A.getDay())},&quot;U&quot;:function(){return fleegix.date.util.strftimeNotImplemented(&quot;U&quot;)},&quot;V&quot;:function(){return fleegix.date.util.strftimeNotImplemented(&quot;V&quot;)},&quot;W&quot;:function(){return fleegix.date.util.strftimeNotImplemented(&quot;W&quot;)},&quot;w&quot;:function(A){return A.getDay()},&quot;x&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%D&quot;)},&quot;X&quot;:function(A){return fleegix.date.util.strftime(A,&quot;%T&quot;)},&quot;y&quot;:function(A){return fleegix.date.util.getTwoDigitYear(A.getFullYear())},&quot;Y&quot;:function(A){return fleegix.date.util.leftPad(A.getFullYear(),4,&quot;0&quot;)},&quot;z&quot;:function(){return fleegix.date.util.strftimeNotImplemented(&quot;z&quot;)},&quot;Z&quot;:function(){return fleegix.date.util.strftimeNotImplemented(&quot;Z&quot;)},&quot;%&quot;:function(A){return&quot;%&quot;}};fleegix.date.util.getSupportedFormats=function(){var B=&quot;&quot;;for(var A in fleegix.date.util.supportedFormats){B+=A}return B};fleegix.date.util.supportedFormatsPat=new RegExp(&quot;%[&quot;+fleegix.date.util.getSupportedFormats()+&quot;]{1}&quot;,&quot;g&quot;);fleegix.date.util.strftime=function(C,E){var G=null;var D=[];var A=[];var F=E;G=C?C:new Date();G=typeof C==&quot;number&quot;?new Date(C):C;while(D=fleegix.date.util.supportedFormatsPat.exec(E)){A.push(D[0])}for(var B=0;B&lt;A.length;B++){key=A[B].replace(/%/,&quot;&quot;);F=F.replace(&quot;%&quot;+key,fleegix.date.util.supportedFormats[key](G))}return F};fleegix.date.util.strftimeNotImplemented=function(A){throw (&quot;fleegix.date.util.strftime format \&quot;&quot;+A+&quot;\&quot; not implemented.&quot;)};fleegix.date.util.leftPad=function(B,A,C){var E=B.toString();var D=C?C:&quot; &quot;;while(E.length&lt;A){E=D+E}return E};fleegix.date.util.calcCentury=function(B){var A=parseInt(B/100);A=A.toString();return fleegix.date.util.leftPad(A)};fleegix.date.util.calcDays=function(B){var D=new Date(B.getFullYear(),0,1);var C=0;var A=0;D=D.getTime();C=(B.getTime()-D);A=parseInt(((((C/1000)/60)/60)/24))+1;return A};fleegix.date.util.convertOneBase=function(A){return A==0?7:A};fleegix.date.util.getTwoDigitYear=function(A){var C=A+1000;var B=C.toString();B=B.substr(2);return B};fleegix.date.util.getMeridian=function(A){return A&gt;11?fleegix.date.util.meridian.PM:fleegix.date.util.meridian.AM};fleegix.date.util.hrMil2Std=function(A){var B=typeof A==&quot;number&quot;?A:parseInt(A);var C=B&gt;12?B-12:B;C=C==0?12:C;return C};fleegix.date.util.hrStd2Mil=function(A,B){var C=typeof A==&quot;number&quot;?A:parseInt(A);var D=&quot;&quot;;if(B){D=C&lt;12?(C+12):C}else{D=C==12?0:C}return D};fleegix.date.util.dateParts={YEAR:0,MONTH:1,DAY:2,HOUR:3,MINUTE:4,SECOND:5,MILLISECOND:6,QUARTER:7,WEEK:8,WEEKDAY:9};fleegix.date.util.add=function(dt,interv,incr){if(typeof dt==&quot;number&quot;){dt=new Date(dt)}function fixOvershoot(){if(sum.getDate()&lt;dt.getDate()){sum.setDate(0)}}var sum=new Date(dt);with(fleegix.date.util.dateParts){switch(interv){case YEAR:sum.setFullYear(dt.getFullYear()+incr);fixOvershoot();break;case QUARTER:incr*=3;case MONTH:sum.setMonth(dt.getMonth()+incr);fixOvershoot();break;case WEEK:incr*=7;case DAY:sum.setDate(dt.getDate()+incr);break;case WEEKDAY:var dat=dt.getDate();var weeks=0;var days=0;var strt=0;var trgt=0;var adj=0;var mod=incr%5;if(mod==0){days=(incr&gt;0)?5:-5;weeks=(incr&gt;0)?((incr-5)/5):((incr+5)/5)}else{days=mod;weeks=parseInt(incr/5)}strt=dt.getDay();if(strt==6&amp;&amp;incr&gt;0){adj=1}else{if(strt==0&amp;&amp;incr&lt;0){adj=-1}}trgt=strt+days;if(trgt==0||trgt==6){adj=(incr&gt;0)?2:-2}sum.setDate(dat+(7*weeks)+days+adj);break;case HOUR:sum.setHours(sum.getHours()+incr);break;case MINUTE:sum.setMinutes(sum.getMinutes()+incr);break;case SECOND:sum.setSeconds(sum.getSeconds()+incr);break;case MILLISECOND:sum.setMilliseconds(sum.getMilliseconds()+incr);break;default:break}}return sum};fleegix.date.util.diff=function(date1,date2,interv){if(typeof date1==&quot;number&quot;){date1=new Date(date1)}if(typeof date2==&quot;number&quot;){date2=new Date(date2)}var yeaDiff=date2.getFullYear()-date1.getFullYear();var monDiff=(date2.getMonth()-date1.getMonth())+(yeaDiff*12);var msDiff=date2.getTime()-date1.getTime();var secDiff=msDiff/1000;var minDiff=secDiff/60;var houDiff=minDiff/60;var dayDiff=houDiff/24;var weeDiff=dayDiff/7;var delta=0;with(fleegix.date.util.dateParts){switch(interv){case YEAR:delta=yeaDiff;break;case QUARTER:var m1=date1.getMonth();var m2=date2.getMonth();var q1=Math.floor(m1/3)+1;var q2=Math.floor(m2/3)+1;q2+=(yeaDiff*4);delta=q2-q1;break;case MONTH:delta=monDiff;break;case WEEK:delta=parseInt(weeDiff);break;case DAY:delta=dayDiff;break;case WEEKDAY:var days=Math.round(dayDiff);var weeks=parseInt(days/7);var mod=days%7;if(mod==0){days=weeks*5}else{var adj=0;var aDay=date1.getDay();var bDay=date2.getDay();weeks=parseInt(days/7);mod=days%7;var dtMark=new Date(date1);dtMark.setDate(dtMark.getDate()+(weeks*7));var dayMark=dtMark.getDay();if(dayDiff&gt;0){switch(true){case aDay==6:adj=-1;break;case aDay==0:adj=0;break;case bDay==6:adj=-1;break;case bDay==0:adj=-2;break;case (dayMark+mod)&gt;5:adj=-2;break;default:break}}else{if(dayDiff&lt;0){switch(true){case aDay==6:adj=0;break;case aDay==0:adj=1;break;case bDay==6:adj=2;break;case bDay==0:adj=1;break;case (dayMark+mod)&lt;0:adj=2;break;default:break}}}days+=adj;days-=(weeks*2)}delta=days;break;case HOUR:delta=houDiff;break;case MINUTE:delta=minDiff;break;case SECOND:delta=secDiff;break;case MILLISECOND:delta=msDiff;break;default:break}}return Math.round(delta)};if(typeof fleegix.hash==&quot;undefined&quot;){fleegix.hash={}}fleegix.hash.UNDEFINED_VALUE;fleegix.hash.Hash=function(A){this.count=0;this.items={};this.order=[];if(A){this.defaultValue=A}};fleegix.hash.Hash.prototype=new function(){var A=function(){var F=&quot;0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz&quot;;var B=16;var G=&quot;&quot;;var E=new Date().getTime();for(var D=0;D&lt;B;D++){if(navigator.userAgent.indexOf(&quot;Safari/41&quot;)&gt;-1){C=(((E/(D+1))+E)%F.length)}else{var C=(Math.random()*F.length)}C=Math.floor(C);G+=F.substring(C,C+1)}return G};this.addItem=function(B,C){if(typeof B!=&quot;string&quot;){throw (&quot;Hash only allows string keys.&quot;)}return this.setByKey(B,C)};this.addItemCreateKey=function(C){var B=A();this.setByKey(B,C);return B};this.getItem=function(B){if(typeof B==&quot;string&quot;){return this.getByKey(B)}else{if(typeof B==&quot;number&quot;){return this.getByIndex(B)}}};this.setItem=function(B,C){if(typeof B==&quot;string&quot;){this.setByKey(B,C)}else{if(typeof B==&quot;number&quot;){this.setByIndex(B,C)}}};this.removeItem=function(B){if(typeof B==&quot;string&quot;){this.removeByKey(B)}else{if(typeof B==&quot;number&quot;){this.removeByIndex(B)}}};this.getByKey=function(B){return this.items[B]};this.setByKey=function(C,D){var B=null;if(typeof D==&quot;undefined&quot;){B=this.defaultValue}else{B=D}if(typeof this.items[C]==&quot;undefined&quot;){this.order[this.count]=C;this.count++}this.items[C]=B;return this.items[C]};this.removeByKey=function(C){if(typeof this.items[C]!=&quot;undefined&quot;){var D=null;delete this.items[C];for(var B=0;B&lt;this.order.length;B++){if(this.order[B]==C){D=B}}this.order.splice(D,1);this.count--}};this.getByIndex=function(B){return this.items[this.order[B]]};this.setByIndex=function(B,C){if(B&lt;0||B&gt;=this.count){throw (&quot;Index out of bounds. Hash length is &quot;+this.count)}this.items[this.order[B]]=C};this.removeByIndex=function(C){var B=this.items[this.order[C]];if(typeof B!=&quot;undefined&quot;){delete this.items[this.order[C]];this.order.splice(C,1);this.count--;return true}else{return false}};this.hasKey=function(B){return typeof this.items[B]!=&quot;undefined&quot;};this.hasValue=function(C){for(var B=0;B&lt;this.order.length;B++){if(this.items[this.order[B]]==C){return true}}return false};this.allKeys=function(B){return this.order.join(B)};this.replaceKey=function(C,D){if(this.hasKey(D)){this.removeItem(D)}this.items[D]=this.items[C];delete this.items[C];for(var B=0;B&lt;this.order.length;B++){if(this.order[B]==C){this.order[B]=D}}};this.insertAtIndex=function(D,B,C){this.order.splice(D,0,B);this.items[B]=C;this.count++;return true};this.insertAfterKey=function(B,C,D){var E=this.getPos(B);this.insertAtPos(E,C,D)};this.getPosition=function(D){var B=this.order;if(typeof B.indexOf==&quot;function&quot;){return B.indexOf(D)}else{for(var C=0;C&lt;B.length;C++){if(B[C]==D){return C}}}};this.each=function(F,D){var B=D||{};var I=this.order.length;var C=B.start?B.start:0;var H=B.items?(C+B.items):I;H=(H&gt;I)?I:H;for(var G=C;G&lt;H;G++){var J=this.order[G];var E=this.items[J];if(B.keyOnly){F(J)}else{if(B.valueOnly){F(E)}else{F(E,J)}}}return true};this.eachKey=function(B){this.each(B,{keyOnly:true})};this.eachValue=function(B){this.each(B,{valueOnly:true})};this.clone=function(){var D=new fleegix.hash.Hash();for(var C=0;C&lt;this.order.length;C++){var B=this.order[C];var E=this.items[B];D.setItem(B,E)}return D};this.concat=function(D){for(var C=0;C&lt;D.order.length;C++){var B=D.order[C];var E=D.items[B];this.setItem(B,E)}};this.push=function(B,C){this.insertAtIndex(this.count,B,C);return this.count};this.pop=function(){var C=this.count-1;var B=this.items[this.order[C]];if(typeof B!=&quot;undefined&quot;){this.removeAtPos(C);return B}else{return fleegix.hash.UNDEFINED_VALUE}};this.unshift=function(B,C){this.insertAtIndex(0,B,C);return this.count};this.shift=function(C,D){var E=0;var B=this.items[this.order[E]];if(typeof B!=&quot;undefined&quot;){this.removeAtPos(E);return B}else{return fleegix.hash.UNDEFINED_VALUE}};this.splice=function(D,F,G){var H=this;if(F&gt;0){var B=D+F;for(var E=D;E&lt;B;E++){delete this.items[this.order[E]]}this.order.splice(D,F)}if(G){for(var E in G.items){this.items[E]=G.items[E]}var C=G.order;C.unshift(0);C.unshift(D);this.order.splice.apply(this.order,C)}this.count=this.order.length};this.sort=function(F){var G=F||fleegix.hash.sorts.ASCENDING_NOCASE;var B=[];if(typeof G!=&quot;function&quot;){throw (&quot;Hash sort requires a valid comparator function.&quot;)}var C=function(I,H){return G(I.val,H.val)};for(var E=0;E&lt;this.order.length;E++){var D=this.order[E];B[E]={key:D,val:this.items[D]}}B.sort(C);this.order=[];for(var E=0;E&lt;B.length;E++){this.order.push(B[E].key)}};this.sortByKey=function(C){var B=C||fleegix.hash.sorts.ASCENDING_NOCASE;if(typeof compar!=&quot;function&quot;){throw (&quot;Hash sort requires a valid comparator function.&quot;)}this.order.sort(B)};this.reverse=function(){this.order.reverse()}};fleegix.hash.sorts={ASCENDING_WITH_CASE:function(B,A){return(B&gt;=A)?1:-1},DESCENDING_WITH_CASE:function(B,A){return(B&lt;A)?1:-1},ASCENDING_NOCASE:function(B,A){return(B.toLowerCase()&gt;=A.toLowerCase())?1:-1},DESCENDING_NOCASE:function(B,A){return(B.toLowerCase()&lt;A.toLowerCase())?1:-1}};if(typeof fleegix.ui==&quot;undefined&quot;){fleegix.ui={}}fleegix.ui.GlyphRegistry={};fleegix.ui.defaultUnits=&quot;px&quot;;fleegix.ui.Glyph=function(A,B){this.domNode=A||null;this.id=B||A.id;if(!this.id){throw new Error(&quot;Glyph must have an id.&quot;)}this.top=0;this.left=0;this.width=0;this.height=0;this.data=null;this.parent=null;this.children=[];this.hasBeenRendered=false;this.visible=true;fleegix.ui.GlyphRegistry[B]=this;this.data=null};fleegix.ui.Glyph.prototype=new function(){this.cleanup=function(){this.domNode=null};this.clearNode=function(B,A){if(A){B.innerHTML=&quot;&quot;}else{while(B.hasChildNodes()){B.removeChild(B.firstChild)}}};this.clearAll=function(){if(this.domNode){this.clearNode(this.domNode)}var B=this.children;if(B&amp;&amp;B.length){for(var A=0;A&lt;B.length;A++){B[A].clearAll()}}};this.setPosition=function(B,A){this.setTop(A);this.setLeft(B)};this.setSize=function(B,A){this.setWidth(B);this.setHeight(A)};this.setTop=function(A){if(typeof A!=&quot;undefined&quot;){this.top=A}n=this.top;if(fleegix.ui.defaultUnits==&quot;px&quot;){n=parseInt(n,10)}this.domNode.style.position=&quot;absolute&quot;;this.domNode.style.top=n+fleegix.ui.defaultUnits};this.setLeft=function(A){if(typeof A!=&quot;undefined&quot;){this.left=A}n=this.left;if(fleegix.ui.defaultUnits==&quot;px&quot;){n=parseInt(n,10)}this.domNode.style.position=&quot;absolute&quot;;this.domNode.style.left=n+fleegix.ui.defaultUnits};this.setWidth=function(A){if(typeof A!=&quot;undefined&quot;){this.width=A}n=this.width;if(typeof n==&quot;number&quot;){if(fleegix.ui.defaultUnits==&quot;px&quot;){n=parseInt(n,10)}n=n.toString()+fleegix.ui.defaultUnits}this.domNode.style.width=n};this.setHeight=function(A){if(typeof A!=&quot;undefined&quot;){this.height=A}n=this.height;if(typeof n==&quot;number&quot;){if(fleegix.ui.defaultUnits==&quot;px&quot;){n=parseInt(n,10)}n=n.toString()+fleegix.ui.defaultUnits}this.domNode.style.height=n};this.appendToDomNode=function(A){if(!this.domNode){throw new Error(&quot;Glyph \&quot;&quot;+this.id+&quot;\&quot; has no domNode.&quot;)}else{A.appendChild(this.domNode)}};this.hide=function(A){if(A){this.domNode.style.visibility=&quot;hidden&quot;}else{this.domNode.style.display=&quot;none&quot;}this.visible=false};this.show=function(A){if(A){this.domNode.style.visibility=&quot;visible&quot;}else{this.domNode.style.display=&quot;block&quot;}this.visible=true};this.renderSelf=function(){};this.update=function(A){var B=A||{};for(var C in B){this[C]=B[C]}};this.render=function(){if(!this.hasBeenRendered&amp;&amp;typeof this.init==&quot;function&quot;){this.init()}if(typeof this.renderSelf==&quot;function&quot;){this.renderSelf()}var B=this.children;var C;for(var A=0;A&lt;B.length;A++){C=B[A];C.render()}this.hasBeenRendered=true};this.addChild=function(A){this.children.push(A);A.parent=this;this[A.id]=A;this.domNode.appendChild(A.domNode)};this.center=function(){if(!fleegix.dom){throw new Error(&quot;This method depends on the fleegix.dom module in fleegix.js base.&quot;)}else{this.domNode.style.position=&quot;absolute&quot;;fleegix.dom.center(this.domNode)}}};fleegix.i18n=new function(){var A=this;this.localizedStrings={};this.getText=function(){var B=Array.prototype.slice.apply(arguments);var D=B.shift();var E=A.localizedStrings[D]||&quot;[[&quot;+D+&quot;]]&quot;;for(var C=0;C&lt;B.length;C++){E=E.replace(new RegExp(&quot;\\{&quot;+C+&quot;\\}&quot;,&quot;g&quot;),B[C])}return E};this.setLocalizedStrings=function(B){this.localizedStrings=B||{}}};fleegix.html=new function(){var A=function(C){return document.createElement(C)};var B=function(C){return document.createTextNode(C)};this.createSelect=function(G){var E=document.createElement(&quot;select&quot;);var C=[];var D=null;D=arguments[1];C=G.options;for(var F in G){if(F!=&quot;options&quot;){E[F]=G[F]}}if(C){this.setSelectOptions(E,C)}return E};this.setSelectOptions=function(D,C){while(D.firstChild){D.removeChild(D.firstChild)}for(var F=0;F&lt;C.length;F++){var E=A(&quot;option&quot;);E.value=C[F].value||&quot;&quot;;E.appendChild(B(C[F].text));D.appendChild(E);if(C[F].selected){D.selectedIndex=F}}};this.setSelect=function(F,G){var C=0;var E=F.options;for(var D=0;D&lt;E.length;D++){if(E[D].value==G){C=D;break}}F.selectedIndex=C};this.createInput=function(G){var C=null;var F=&quot;&quot;;if((document.all||navigator.userAgent.indexOf(&quot;Safari/41&quot;)&gt;-1)&amp;&amp;(G.type==&quot;radio&quot;||G.type==&quot;checkbox&quot;)){F=&quot;&lt;input type=\&quot;&quot;+G.type+&quot;\&quot; name=\&quot;&quot;+G.name+&quot;\&quot; id =\&quot;&quot;+G.id+&quot;\&quot;&quot;;if(G.value){F+=&quot; value=\&quot;&quot;+G.value+&quot;\&quot;&quot;}if(G.size){F+=&quot; size=\&quot;&quot;+G.size+&quot;\&quot;&quot;}if(G.maxlength){F+=&quot; maxlength=\&quot;&quot;+G.maxlength+&quot;\&quot;&quot;}if(G.checked){F+=&quot; checked=\&quot;checked\&quot;&quot;}if(G.className){F+=&quot; class=\&quot;&quot;+G.className+&quot;\&quot;&quot;}F+=&quot;/&gt;&quot;;var D=A(&quot;span&quot;);D.innerHTML=F;C=D.firstChild;D.removeChild(C)}else{C=document.createElement(&quot;input&quot;);for(var E in G){C[E]=G[E]}}return C}};if(typeof fleegix.drag==&quot;undefined&quot;){fleegix.drag={}}fleegix.drag.xPos=null;fleegix.drag.yPos=null;fleegix.drag.DragManager=new function(){var A=this;this.registry=[];this.raiseMap={};this.dragMap={};this.currentDraggable=null;this.currentZIndex=99999;this.addDragWindow=function(C,E,F){if(!C.id){throw (&quot;Draggable DOM nodes must have an id&quot;)}if(!E){E=C}var B=function(H){A.setUpDrag.apply(A,[H])};fleegix.event.listen(E,&quot;onmousedown&quot;,B);var D=function(H){A.raiseDraggable.apply(A,[H])};fleegix.event.listen(C,&quot;onmousedown&quot;,D);var G=new fleegix.drag.DragWindow({containerNode:C,shadowNode:F});this.registry.push(G);this.raiseMap[C.id]=G;this.dragMap[E.id]=G;this.raiseDraggable(C.id)};this.setUpDrag=function(C){var B=C.target;var D=this.dragMap[B.id];while(!D&amp;&amp;B!=document.body){if(B.parentNode){B=B.parentNode;D=this.dragMap[B.id]}}if(D){this.currentDraggable=D;this.currentDraggable.startDrag()}};this.raiseDraggable=function(D){var B=&quot;&quot;;if(typeof D==&quot;string&quot;){var E=this.raiseMap[D]}else{var C=D.target;var E=this.raiseMap[C.id];while(!E&amp;&amp;C!=document.body){if(C.parentNode){C=C.parentNode;E=this.raiseMap[C.id]}}}this.currentZIndex++;E.containerNode.style.zIndex=this.currentZIndex;if(E.shadowNode){E.shadowNode.style.zIndex=this.currentZIndex-1}};this.mouseMoveHandler=function(B){var C=fleegix.drag;C.xPos=B.clientX;C.yPos=B.clientY;if(A.currentDraggable){A.currentDraggable.drag()}};this.mouseUpHandler=function(B){if(A.currentDraggable){A.currentDraggable.drop();A.currentDraggable=null}}};fleegix.drag.DragWindow=function(A){var B=A||{};this.containerNode=null;this.shadowNode=null;this.handleNode=null;this.clickOffsetX=0;this.clickOffsetY=0;for(var C in B){this[C]=B[C]}};fleegix.drag.DragWindow.prototype.startDrag=function(){var A=fleegix.drag;this.clickOffsetX=A.xPos-parseInt(this.containerNode.style.left);this.clickOffsetY=A.yPos-parseInt(this.containerNode.style.top);document.onselectstart=function(){return false}};fleegix.drag.DragWindow.prototype.drag=function(){var B=fleegix.drag;var A=(B.xPos-this.clickOffsetX)+&quot;px&quot;;var C=(B.yPos-this.clickOffsetY)+&quot;px&quot;;this.containerNode.style.left=A;this.containerNode.style.top=C;if(this.shadowNode){this.shadowNode.style.left=A;this.shadowNode.style.top=C}document.body.focus()};fleegix.drag.DragWindow.prototype.drop=function(){document.onselectstart=null};fleegix.event.listen(document,&quot;onmousemove&quot;,fleegix.drag.DragManager,&quot;mouseMoveHandler&quot;);fleegix.event.listen(document,&quot;onmouseup&quot;,fleegix.drag.DragManager,&quot;mouseUpHandler&quot;);if(typeof fleegix==&quot;undefined&quot;){throw (&quot;Requires fleegix base namespace.&quot;)}if(typeof fleegix.xhr==&quot;undefined&quot;){throw (&quot;Requires fleegix.xhr namespace.&quot;)}if(typeof fleegix.template==&quot;undefined&quot;){fleegix.template={}}fleegix.template.Templater=function(D){var E=D||{};var C=E.options||{};this.markup=E.markup||&quot;&quot;;this.markupFile=&quot;&quot;;this.data=E.data||{};this.requireAllKeys=typeof E.requireAllKeys==&quot;boolean&quot;?E.requireAllKeys:true;if(!this.markup){var F=this;var A=typeof this.preventCache==&quot;undefined&quot;?false:this.preventCache;this.markupFile=E.markupFile;var B=fleegix.template.templateTextCache[this.markupFile];if(!B||A){var D={url:this.markupFile,method:&quot;GET&quot;,preventCache:A,async:false};B=fleegix.xhr.doReq(D);fleegix.template.templateTextCache[this.markupFile]=B}this.markup=B}};fleegix.template.Templater.prototype.templatize=function(A){var B=this.getTemplatedMarkup();A.innerHTML=B;return A};fleegix.template.Templater.prototype.getTemplatedMarkup=function(){var B=/\$\{ *(.*?) *\}/g;var E=/[${} ]/g;var F=this.markup;var A=F.match(B);if(A){for(var C=0;C&lt;A.length;C++){m=A[C];key=m.replace(E,&quot;&quot;);var D=this.data[key]?this.data[key]:&quot;&quot;;if(D||!this.requireAllKeys){F=F.replace(m,D)}}}return F};fleegix.template.templateTextCache={};if(typeof fleegix==&quot;undefined&quot;){fleegix={}}fleegix.ejs={};fleegix.ejs.templateTextCache={};fleegix.ejs.Template=function(B){var A;var C=B||{};this.mode=null;this.templateText=C.text||this.getTemplateTextFromNode(C.node);this.afterLoaded=C.afterLoaded;this.source=&quot;&quot;;this.markup=A;if(typeof this.templateText==&quot;undefined&quot;){this.getTemplateTextFromUrl(C)}};fleegix.ejs.Template.prototype=new function(){var _REGEX=/(&lt;%%)|(%%&gt;)|(&lt;%=)|(&lt;%#)|(&lt;%)|(%&gt;\n)|(%&gt;)|(\n)/;this.modes={EVAL:&quot;eval&quot;,OUTPUT:&quot;output&quot;,APPEND:&quot;append&quot;,COMMENT:&quot;comment&quot;,LITERAL:&quot;literal&quot;};this.getTemplateTextFromNode=function(node){if(typeof fleegix.string==&quot;undefined&quot;){throw (&quot;Requires fleegix.string module.&quot;)}var ret;if(node){ret=node.value;ret=fleegix.string.unescapeXML(ret);ret=fleegix.string.trim(ret)}return ret};this.getTemplateTextFromUrl=function(params){if(typeof fleegix.xhr==&quot;undefined&quot;){throw (&quot;Requires fleegix.xhr module.&quot;)}var _this=this;var url=params.url;var noCache=params.preventCache||false;var text=fleegix.ejs.templateTextCache[url];if(text&amp;&amp;!noCache){this.templateText=text}else{var callback=function(s){_this.templateText=s;fleegix.ejs.templateTextCache[url]=s;if(typeof _this.afterLoaded==&quot;function&quot;){_this.afterLoaded()}};var opts;if(params.async){opts={url:url,method:&quot;GET&quot;,preventCache:noCache,async:true,handleSuccess:callback};fleegix.xhr.send(opts)}else{opts={url:url,method:&quot;GET&quot;,preventCache:noCache,async:false};text=fleegix.xhr.send(opts);callback(text)}}};this.process=function(p){var params=p||{};this.data=params.data||{};var domNode=params.node;this.source=this.source||&quot;&quot;;if(!this.source){this.generateSource()}var _output=&quot;&quot;;with(this.data){eval(this.source)}this.markup=_output;if(domNode){domNode.innerHTML=this.markup}return this.markup};this.generateSource=function(){var line=&quot;&quot;;var matches=this.parseTemplateText();if(matches){for(var i=0;i&lt;matches.length;i++){line=matches[i];if(line){this.scanLine(line)}}}};this.parseTemplateText=function(){var str=this.templateText;var pat=_REGEX;var result=pat.exec(str);var arr=[];while(result){var firstPos=result.index;var lastPos=pat.lastIndex;if(firstPos!==0){arr.push(str.substring(0,firstPos));str=str.slice(firstPos)}arr.push(result[0]);str=str.slice(result[0].length);result=pat.exec(str)}if(str!==&quot;&quot;){arr.push(str)}return arr};this.scanLine=function(line){var _this=this;var _addOutput=function(){line=line.replace(/\n/,&quot;\\n&quot;);line=line.replace(/&quot;/g,&quot;\\\&quot;&quot;);_this.source+=&quot;_output += \&quot;&quot;+line+&quot;\&quot;;&quot;};switch(line){case&quot;&lt;%&quot;:this.mode=this.modes.EVAL;break;case&quot;&lt;%=&quot;:this.mode=this.modes.OUTPUT;break;case&quot;&lt;%#&quot;:this.mode=this.modes.COMMENT;break;case&quot;&lt;%%&quot;:this.mode=this.modes.LITERAL;this.source+=&quot;_output += \&quot;&quot;+line+&quot;\&quot;;&quot;;break;case&quot;%&gt;&quot;:case&quot;%&gt;\n&quot;:if(this.mode==this.modes.LITERAL){_addOutput()}this.mode=null;break;default:if(this.mode){switch(this.mode){case this.modes.EVAL:this.source+=line;break;case this.modes.OUTPUT:this.source+=&quot;_output += &quot;+line+&quot;;&quot;;break;case this.modes.COMMENT:break;case this.modes.LITERAL:_addOutput();break}}else{_addOutput()}}}};if(typeof fleegix.form==&quot;undefined&quot;){fleegix.form={}}if(typeof fleegix.form.toObject==&quot;undefined&quot;){throw (&quot;fleegix.form.diff depends on the base fleegix.form module in fleegix.js.&quot;)}fleegix.form.diff=function(J,G,A){var C=A||{};var F=J.elements?fleegix.form.toObject(J):J;var B=G.elements?fleegix.form.toObject(G):G;var E=[];var D=0;function I(N,M,L,K){if(!E[N]){D++;E[N]=K?{origVal:L[N],newVal:M[N]}:{origVal:M[N],newVal:L[N]}}}function H(M,L,K){for(n in M){if(typeof L[n]==&quot;undefined&quot;){if(C.intersectionOnly){continue}I(n,M,L,K)}else{v=M[n];if(v instanceof Array){if(!L[n]||(L[n].toString()!=v.toString())){I(n,M,L,K)}}else{if(L[n]!=v){I(n,M,L,K)}}}}}H(F,B,false);H(B,F,true);return{count:D,diffs:E}};fleegix.xml=new function(){var A=/^[\s\n\r\t]+|[\s\n\r\t]+$/g;var B=function(E,D){if(E){var C=null;if(E instanceof Array==false){C=[];C.push(E)}else{C=E}C.push(D);return C}else{return D}};this.parse=function(F,E){var I={};var C=[];var G;var J;var K;var D;if(E){C=F.getElementsByTagName(E)}else{C=F.childNodes}for(var H=0;H&lt;C.length;H++){G=C[H];if(G.nodeType==1){J=G.tagName;if(G.firstChild){if(G.childNodes.length==1){K=G.firstChild.nodeType;if(K==3||K==4||K==8){D=G.firstChild.nodeValue.replace(A,&quot;&quot;);I[J]=B(I[J],D)}else{if(K==1){I[J]=B(I[J],this.parse(G.firstChild))}}}else{I[J]=B(I[J],this.parse(G))}}else{I[J]=B(I[J],null)}}}return I};this.createDoc=function(F){if(typeof DOMParser!=&quot;undefined&quot;){return(new DOMParser()).parseFromString(F,&quot;application/xml&quot;)}else{if(typeof ActiveXObject!=&quot;undefined&quot;){var E=XML.newDocument();E.loadXML(F);return E}else{var C=&quot;data:text/xml;charset=utf-8,&quot;+encodeURIComponent(F);var D=new XMLHttpRequest();D.open(&quot;GET&quot;,C,false);D.send(null);return D.responseXML}}};this.getXMLDoc=function(G,D){var C=[];var E=null;if(document.all){var F=document.getElementById(G).innerHTML;E=new ActiveXObject(&quot;Microsoft.XMLDOM&quot;);E.loadXML(F);E=E.documentElement}else{C=window.document.body.getElementsByTagName(D);E=C[0]}return E}};if(typeof fleegix.event==&quot;undefined&quot;){throw (&quot;fleegix.event.delegator depends on the base fleegix.event module in fleegix.js.&quot;)}fleegix.event.Delegator=function(A,D,B){var E=this;this.containerNode=A;this.actions=D||{};var C=B||{};this.context=C.context||null;this.stopPropagation=typeof C.stopPropagation!=&quot;undefined&quot;?C.stopPropagation:true;this.preventDefault=typeof C.preventDefault!=&quot;undefined&quot;?C.preventDefault:true;this.addClickAction=function(G,F){this.actions[G]=F};this.getClickAction=function(K){var L=this.actions;var F=this.containerNode;var I=K.target;var G=F||document.body;while(I.parentNode&amp;&amp;I!=G){if(I.className){for(var M in L){var J=I.className.split(&quot; &quot;);for(var H=0;H&lt;J.length;H++){if(J[H]==M){return M}}}}I=I.parentNode}return null};this.handleClick=function(I){var H=this.context;var G=E.getClickAction(I);if(G){var F=this.actions[G];if(H){F.call(H,I)}else{F(I)}if(this.stopPropagation){fleegix.event.stopPropagation(I)}if(this.preventDefault){fleegix.event.preventDefault(I)}}};fleegix.event.listen(A,&quot;onclick&quot;,this,&quot;handleClick&quot;)};if(typeof fleegix.event==&quot;undefined&quot;){throw (&quot;fleegix.event.delegator depends on the base fleegix.event module in fleegix.js.&quot;)}fleegix.event.Periodic=function(){var H=this;var G=false;var D=Array.prototype.slice.apply(arguments);var E;var B;if(typeof D[0]!=&quot;function&quot;){E=D.shift();B=D.shift()}else{var F=D.shift()}var A=D.shift();var C=D.shift();this.context=E||null;this.methodName=B||null;this.func=F||null;this.interval=A||null;this.waitFirst=C||false;this.start=function(I){this.waitFirst=I||this.waitFirst;if(this.waitFirst){setTimeout(this.run,this.interval)}else{this.run()}};this.run=function(){if(!G){if(H.context){H.context[H.methodName].call(H.context)}else{H.func()}setTimeout(H.run,H.interval)}};this.pause=function(){G=true};this.resume=function(){G=false;this.run()}};fleegix.event.listen(window,&quot;onunload&quot;,function(){try{fleegix.event.flush()}catch(A){}});if(typeof fleegix==&quot;undefined&quot;){throw new Error(&quot;fleegix.history depends on fleegix base module.&quot;)}fleegix.history=new function(){var F=this;var C;var D=0;this.index=0;this.currentStep=0;this.entries=[];this.entriesMap={};this.ieKeyArray=[];this.bookmarkable=true;this.domain=null;var B=function(){var G;if(fleegix.ua.isIE){G=document.getElementById(&quot;historyFrame&quot;).contentWindow.document}else{if(F.bookmarkable){G=document}else{G=document.getElementById(&quot;historyFrame&quot;).contentDocument}}return G};var E=function(){var G;if(fleegix.ua.isIE){G=D}else{G=B().location.hash.replace(&quot;#&quot;,&quot;&quot;);G=F.entriesMap[G]}if(!isNaN(G)){G=parseInt(G,10)}else{G=0}return G};var A=function(){var H=E();var G;if(H!=fleegix.history.currentStep){fleegix.history.currentStep=E();G=F.getEntry(fleegix.history.currentStep);fleegix.history.onchange(G)}C=null;C=window.setTimeout(A,200)};this.init=function(I){var H=$(&quot;historyForm&quot;);var G=H.historyEntries.value;if(G.length){var K=fleegix.json.parse(G);for(var J in K){this[J]=K[J]}}else{this.addEntry(I)}if(!document.getElementById(&quot;historyFrame&quot;)){throw new Error(&quot;This history code requires an iframe with the id of \&quot;historyFrame\&quot; to exist in the initial page load.&quot;)}C=window.setTimeout(A,200);fleegix.event.listen(window,&quot;onbeforeunload&quot;,fleegix.history,&quot;finish&quot;)};this.addEntry=function(){var G;var H;if(arguments.length==1){H=arguments[0]}else{G=arguments[0];H=arguments[1]}var J=this.currentStep;var K=J+1;var I=this.entries.length-J;this.entries.splice(K,I);this.entries.push(H);this.index=this.entries.length-1;G=G||this.index;return this.incrementHistory(G)};this.getEntry=function(G){return this.entries[G]};this.incrementHistory=function(G){var H=B();this.currentStep=this.index;this.entriesMap[G]=this.index;if(fleegix.ua.isIE){var I=this.domain?&quot;document.domain=\&quot;&quot;+this.domain+&quot;\&quot;;&quot;:&quot;&quot;;F.ieKeyArray[this.index]=G;H.open(&quot;javascript:'&lt;html&gt;&lt;/html&gt;'&quot;);H.write(&quot;&lt;html&gt;&lt;head&gt;&lt;script type=\&quot;text/javascript\&quot;&gt;&quot;+I+&quot;parent.fleegix.history.onIncremented(&quot;+this.index+&quot;);&lt;/script&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;&quot;);H.close()}else{if(fleegix.ua.isSafari&amp;&amp;!this.bookmarkable){H.body.innerHTML=&quot;&lt;form name=\&quot;x\&quot; action=\&quot;#&quot;+this.index+&quot;\&quot; method=\&quot;GET\&quot;&gt;&lt;/form&gt;&quot;;H.forms[0].submit()}else{if(G!=0){H.location.hash=&quot;#&quot;+G}}}this.index++;F.serializeHistory();return true};this.onIncremented=function(G){D=G;if(F.bookmarkable){if(G==0){location.hash=&quot;&quot;}else{location.hash=&quot;#&quot;+F.ieKeyArray[G]}}};this.serializeHistory=function(){if(F.entries.length&gt;0){var H=$(&quot;historyForm&quot;);var G={entries:F.entries,entriesMap:F.entriesMap,ieKeyArray:F.ieKeyArray};G=fleegix.json.serialize(G);H.historyEntries.value=G}};this.finish=function(){F.serializeHistory();if(C){window.clearTimeout(C)}};this.onchange=function(){}};if(typeof fleegix.string==&quot;undefined&quot;){fleegix.string={}}fleegix.string.hotlink=new function(){var C=this;var A=/(https?:\/\/|www.)([-\w]+(?:\.[-\w]+)*(:\d+)?(\/(([~\w\+%-]|([,.;@:][^\s$]))+)?)*((\?|;)[\w\+%&amp;=.;:-]+)?(\#[\w\-\.]*)?)/g;var B=/[\w\.\+-=]+@[\w\.-]+\.[\w]{2,3}/g;this.url=function(E){var D=E||&quot;&quot;;ret=D.replace(A,function(G){var F=G.indexOf(&quot;www&quot;)===0?&quot;http://&quot;+G:G;return&quot;&lt;a href=\&quot;&quot;+F+&quot;\&quot;&gt;&quot;+G+&quot;&lt;/a&gt;&quot;});return ret};this.email=function(E){var D=E||&quot;&quot;;ret=D.replace(B,function(F){return&quot;&lt;a href=\&quot;mailto:&quot;+F+&quot;\&quot;&gt;&quot;+F+&quot;&lt;/a&gt;&quot;});return ret};this.all=function(E){var D=E||&quot;&quot;;D=C.url(D);D=C.email(D);return D}};if(typeof fleegix.string==&quot;undefined&quot;){fleegix.string={}}fleegix.string.truncate=function(D,A,B){var C=B||&quot;&quot;;if(D.length&gt;A){return D.substr(0,(A-C.length))+C}else{return D}};fleegix.string.truncateHTML=function(L,J,K){var Q=&quot;&quot;;var O=K||&quot;&quot;;var H=/(&lt;[^&gt;]*&gt;)/;var C=null;var I=&quot;&quot;;var F=[];var G=0;var E=0;var A;var N;var P=H.exec(L);while(P){var B=P.index;var M=H.lastIndex;if(B!==0){F.push(L.substring(0,B));L=L.slice(B)}F.push(P[0]);L=L.slice(P[0].length);P=H.exec(L)}if(L!==&quot;&quot;){F.push(L)}for(var D=0;D&lt;F.length;D++){N=F[D];switch(true){case N.indexOf(&quot;&lt;/&quot;)==0:Q+=N;C=null;break;case N.indexOf(&quot;&lt;&quot;)==0:Q+=N;C=N;break;default:E+=N.length;if(E&gt;=J){A=N.substr(0,(J-G)-O.length);Q+=A;if(C){if(A.length){I=C.split(/\s|&gt;/)[0].replace(&quot;&lt;&quot;,&quot;&lt;/&quot;)+&quot;&gt;&quot;;Q+=I}else{Q=Q.replace(C,&quot;&quot;)}}Q+=O;return Q}else{Q+=N}G=E}}return Q}
\ No newline at end of file
+if(typeof fleegix==&quot;undefined&quot;){var fleegix={}}if(typeof $==&quot;undefined&quot;){var $=function(A){return document.getElementById(A)}}var $elem=function(A,E){var C=E||{};var B=document.createElement(A);for(var D in C){B[D]=C[D]}return B};var $text=function(A){return document.createTextNode(A)};fleegix.bind=function(B,A){return function(){B.apply(A,arguments)}};fleegix.extend=function(A,B){return function(){A.apply(this,arguments);A.prototype.constructor.apply(this,arguments);B.apply(this,arguments);this.superClass=A;this.subClass=B}};fleegix.mixin=function(E,C){var B;if(typeof C==&quot;function&quot;){B=new C()}else{B=C}var A={};for(var D in B){if(typeof A[D]==&quot;undefined&quot;||baseObjj[D]!=B[D]){E[D]=B[D]}}return E};fleegix.clone=function(C){if(typeof C==&quot;object&quot;){var A;if(typeof C.constructor==&quot;function&quot;){A=new C.constructor()}else{A={}}for(var B in C){if(typeof C[B]==&quot;object&quot;&amp;&amp;C[B]!==null){A[B]=fleegix.clone(C[B])}else{A[B]=C[B]}}}else{A=C}return A};fleegix.ua=new function(){var C=navigator.userAgent;var A=function(F,G){var E=G.exec(F);if(E&amp;&amp;E.length&gt;1){E=E[1].substr(0,1);if(!isNaN(E)){return parseInt(E)}else{return null}}return null};this.isWebKit=C.indexOf(&quot;AppleWebKit&quot;)&gt;-1;this.isKHTML=C.indexOf(&quot;KHTML&quot;)&gt;-1;this.isGecko=C.indexOf(&quot;Gecko&quot;)&gt;-1&amp;&amp;!this.isWebKit&amp;&amp;!this.isKHTML;this.isOpera=C.indexOf(&quot;Opera&quot;)&gt;-1;this.isChrome=C.indexOf(&quot;Chrome&quot;)&gt;-1;this.isSafari=C.indexOf(&quot;Safari&quot;)&gt;-1&amp;&amp;!this.isChrome;this.isFF=C.indexOf(&quot;Firefox&quot;)&gt;-1||C.indexOf(&quot;Iceweasel&quot;)&gt;-1||C.indexOf(&quot;IceCat&quot;)&gt;-1;this.isFirefox=this.isFF;this.isIE=C.indexOf(&quot;MSIE &quot;)&gt;-1&amp;&amp;!this.isOpera;this.isIPhone=C.indexOf(&quot;iPhone&quot;)&gt;-1;this.isMobile=this.isIPhone||C.indexOf(&quot;Opera Mini&quot;)&gt;-1;this.isMac=C.indexOf(&quot;Mac&quot;)&gt;-1;this.isUnix=C.indexOf(&quot;Linux&quot;)&gt;-1||C.indexOf(&quot;BSD&quot;)&gt;-1||C.indexOf(&quot;SunOS&quot;)&gt;-1;this.isLinux=C.indexOf(&quot;Linux&quot;)&gt;-1;this.isWindows=C.indexOf(&quot;Windows&quot;)&gt;-1||C.indexOf(&quot;Win&quot;);this.majorVersion=null;var B={FF:/Firefox\/([0-9\.]*)/,Safari:/Version\/([0-9\.]*) /,IE:/MSIE ([0-9\.]*);/,Opera:/Opera\/([0-9\.]*) /,Chrome:/Chrome\/([0-9\.]*)/};for(var D in B){if(this[&quot;is&quot;+D]){this.majorVersion=A(C,B[D])}}for(var D in this){fleegix[D]=this[D]}};fleegix.fx=new function(){function B(G,D,H){var F={};var M=0;var I=0;if(D.blindType==&quot;clip&quot;){M=H==&quot;down&quot;?0:G.offsetHeight;I=H==&quot;down&quot;?G.offsetHeight:0;M=[0,G.offsetWidth,M,0];I=[0,G.offsetWidth,I,0];F.props={clip:[M,I]}}else{if(H==&quot;down&quot;){if(D.endHeight){I=D.endHeight}else{G.style.height=&quot;&quot;;var J=document.createElement(&quot;div&quot;);J.position=&quot;absolute&quot;;J.style.top=&quot;-9999999999px&quot;;J.style.left=&quot;-9999999999px&quot;;var K=G.parentNode;var C=K.removeChild(G);J.appendChild(C);document.body.appendChild(J);I=C.offsetHeight;G=J.removeChild(C);var L=document.body.removeChild(J);G.style.height=&quot;0px&quot;;K.appendChild(G)}M=0}else{M=G.offsetHeight;I=0}F.props={height:[M,I]}}for(var E in D){F[E]=D[E]}F.trans=&quot;lightEaseIn&quot;;return new fleegix.fx.Effecter(G,F)}function A(F,E,C){var D=C==&quot;in&quot;?0:100;var H=C==&quot;in&quot;?100:0;var I={props:{opacity:[D,H]},trans:&quot;lightEaseIn&quot;};for(var G in E){I[G]=E[G]}return new fleegix.fx.Effecter(F,I)}this.fadeOut=function(E,D){return A(E,D,&quot;out&quot;);E.style.visibility=&quot;hidden&quot;;var C=this.setCssProp(E,&quot;opacity&quot;,100)};this.fadeIn=function(E,D){var C=this.setCssProp(E,&quot;opacity&quot;,0);E.style.visibility=&quot;visible&quot;;return A(E,D,&quot;in&quot;)};this.blindUp=function(D,C){var E=C||{};E.blindType=E.blindType||&quot;height&quot;;return B(D,E,&quot;up&quot;)};this.blindDown=function(D,C){var E=C||{};E.blindType=E.blindType||&quot;height&quot;;return B(D,E,&quot;down&quot;)};this.setCSSProp=function(D,E,C){if(E==&quot;opacity&quot;){if(document.all){D.style.filter=&quot;alpha(opacity=&quot;+C+&quot;)&quot;}else{var F=C/100;D.style.opacity=F}}else{if(E==&quot;clip&quot;||E.toLowerCase().indexOf(&quot;color&quot;)&gt;-1){D.style[E]=C}else{D.style[E]=document.all?parseInt(C,10)+&quot;px&quot;:C+&quot;px&quot;}}return true};this.setCssProp=this.setCSSProp;this.hexPat=/^[#]{0,1}([\w]{1,2})([\w]{1,2})([\w]{1,2})$/;this.hex2rgb=function(G){var C=[];var F=G.match(this.hexPat);if(F){for(var D=1;D&lt;F.length;D++){var E=F[D];E=E.length==1?E+E:E;C.push(parseInt(E,16))}return C}else{throw (&quot;\&quot;&quot;+G+&quot;\&quot; not a valid hex value.&quot;)}}};fleegix.fx.Effecter=function(B,A){var C=this;this.props=A.props;this.trans=A.trans||&quot;lightEaseIn&quot;;this.duration=A.duration||500;this.fps=30;this.startTime=new Date().getTime();this.timeSpent=0;this.doBeforeStart=A.doBeforeStart||null;this.doAfterFinish=A.doAfterFinish||null;this.autoStart=A.autoStart===false?false:true;if(typeof this.transitions[this.trans]!=&quot;function&quot;){throw (&quot;\&quot;&quot;+this.trans+&quot;\&quot; is not a valid transition.&quot;)}this.start=function(){C.id=setInterval(function(){C.doStep.apply(C,[B])},Math.round(1000/C.fps));if(typeof A.doBeforeStart==&quot;function&quot;){C.doBeforeStart()}};if(this.autoStart){this.start()}return this};fleegix.fx.Effecter.prototype.doStep=function(C){var B=new Date().getTime();var D=this.props;if(B&lt;(this.startTime+this.duration)){this.timeSpent=B-this.startTime;for(var A in D){fleegix.fx.setCSSProp(C,A,this.calcCurrVal(A))}}else{for(var A in D){if(A==&quot;clip&quot;){fleegix.fx.setCSSProp(C,A,&quot;rect(&quot;+D[A][1].join(&quot;px,&quot;)+&quot;px)&quot;)}else{fleegix.fx.setCSSProp(C,A,D[A][1])}}clearInterval(this.id);if(typeof this.doAfterFinish==&quot;function&quot;){this.doAfterFinish()}}};fleegix.fx.Effecter.prototype.calcCurrVal=function(G){var A=this.props[G][0];var F=this.props[G][1];var I=this.transitions[this.trans];var B;var D;var J;var H;var E;if(G.toLowerCase().indexOf(&quot;color&quot;)&gt;-1){B=fleegix.fx.hex2rgb(A);D=fleegix.fx.hex2rgb(F);J=[];for(var C=0;C&lt;B.length;C++){H=B[C];E=D[C];J.push(parseInt(I(this.timeSpent,H,(E-H),this.duration),10))}return&quot;rgb(&quot;+J.join()+&quot;)&quot;}else{if(G==&quot;clip&quot;){B=A;D=F;J=[];for(var C=0;C&lt;B.length;C++){H=B[C];E=D[C];J.push(parseInt(I(this.timeSpent,H,(E-H),this.duration),10))}return&quot;rect(&quot;+J.join(&quot;px,&quot;)+&quot;px)&quot;}else{return I(this.timeSpent,A,(F-A),this.duration)}}};fleegix.fx.Effecter.prototype.transitions={linear:function(B,A,D,C){return D*(B/C)+A},lightEaseIn:function(B,A,D,C){return D*(B/=C)*B+A},lightEaseOut:function(B,A,D,C){return -D*(B/=C)*(B-2)+A},lightEaseInOut:function(B,A,D,C){if((B/=C/2)&lt;1){return D/2*B*B+A}return -D/2*((--B)*(B-2)-1)+A},heavyEaseIn:function(B,A,D,C){return D*(B/=C)*B*B+A},heavyEaseOut:function(B,A,D,C){return D*((B=B/C-1)*B*B+1)+A},heavyEaseInOut:function(B,A,D,C){if((B/=C/2)&lt;1){return D/2*B*B*B+A}return D/2*((B-=2)*B*B+2)+A}};fleegix.dom=new function(){var A=function(B){if(document.all){if(document.documentElement&amp;&amp;document.documentElement[&quot;client&quot;+B]){return document.documentElement[&quot;client&quot;+B]}else{return document.body[&quot;client&quot;+B]}}else{return window[&quot;inner&quot;+B]}};this.getViewportWidth=function(){return A(&quot;Width&quot;)};this.getViewportHeight=function(){return A(&quot;Height&quot;)};this.getViewportScrollTop=function(){return window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop||0};this.getViewportScrollLeft=function(){window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft||0};this.center=function(G){var B=G.offsetWidth;var E=G.offsetHeight;var F=fleegix.dom.getViewportWidth();var H=fleegix.dom.getViewportHeight();var D=parseInt((F/2)-(B/2),10);var C=parseInt((H/2)-(E/2),10);C+=document.documentElement.scrollTop;G.style.left=D+&quot;px&quot;;G.style.top=C+&quot;px&quot;;return true};this.getOffset=function(D){var C=function(F){var G=0;var E=0;if(F.offsetParent){do{G+=F.offsetLeft;E+=F.offsetTop}while(F=F.offsetParent)}return{left:G,top:E}};var B=null;if(fleegix.isIE||fleegix.isMoz){B=D.getBoundingClientRect()}else{B=C(D)}return B}};fleegix.url=new function(){var E=this;var D=&quot;\\?|;&quot;;var C=new RegExp(D);var B=new RegExp(&quot;(&quot;+D+&quot;)&quot;);var A=function(L,M,F,I){var K=B.exec(M);var H;var G;var N;var J;var O=&quot;&quot;;if(K&amp;&amp;K.length&gt;0){H=K[0]}if(H){G=E.getBase(M);N=E.getQS(M)}else{N=M}J=E.qsToObject(N,{arrayizeMulti:true});if(L==&quot;set&quot;){J[F]=I}else{delete J[F]}if(G){O=G+H}O+=E.objectToQS(J);return O};this.qsToObject=function(N,H){var F=H||{};var M={};var O=F.arrayizeMulti||false;if(N){var L=N.split(&quot;&amp;&quot;);for(var K=0;K&lt;L.length;K++){var J=L[K].split(&quot;=&quot;);var G=J[0];var I=decodeURIComponent(J[1]);if(typeof M[G]!=&quot;undefined&quot;&amp;&amp;O){if(typeof M[G]==&quot;string&quot;){M[G]=[M[G]]}M[G].push(I)}else{M[G]=I}}}return M};this.objectToQS=function(K,G){var F=G||{};var N=&quot;&quot;;var M=F.stripTags?/&lt;[^&gt;]*&gt;/g:null;for(var H in K){var R=&quot;&quot;;var P=K[H];if(P!=undefined){if(P.length&amp;&amp;typeof P!=&quot;string&quot;){var Q=&quot;&quot;;if(F.collapseMulti){Q=&quot;,&quot;;N+=H+&quot;=&quot;}else{Q=&quot;&amp;&quot;}for(var I=0;I&lt;P.length;I++){R=F.stripTags?P[I].replace(M,&quot;&quot;):P[I];R=(!F.collapseMulti)?H+&quot;=&quot;+encodeURIComponent(R):encodeURIComponent(R);N+=R+Q}N=N.substr(0,N.length-1)}else{R=F.stripTags?P.replace(M,&quot;&quot;):P;N+=H+&quot;=&quot;+encodeURIComponent(R)}N+=&quot;&amp;&quot;}else{if(F.includeEmpty){N+=H+&quot;=&amp;&quot;}}}if(F.deCamelizeParams){if(!fleegix.string){throw new Error(&quot;deCamelize option depends on fleegix.string module.&quot;)}var L=N.split(&quot;&amp;&quot;);var O;N=&quot;&quot;;for(var J=0;J&lt;L.length;J++){O=L[J].split(&quot;=&quot;);if(O[0]){N+=fleegix.string.deCamelize(O[0])+&quot;=&quot;+O[1]+&quot;&amp;&quot;}}}N=N.substr(0,N.length-1);return N};this.objectToQs=this.objectToQS;this.getQSParam=function(L,F,K){var J=null;var I=C.test(L)?E.getQS(L):L;var H=K||{};if(I){var G=E.qsToObject(I,H);J=G[F]}return J};this.getQsParam=this.getQSParam;this.setQSParam=function(H,F,G){return A(&quot;set&quot;,H,F,G)};this.setQsParam=this.setQSParam;this.removeQSParam=function(G,F){return A(&quot;remove&quot;,G,F,null)};this.removeQsParam=this.removeQSParam;this.getQS=function(F){return F.split(C)[1]};this.getQs=this.getQS;this.getBase=function(F){return F.split(C)[0]}};fleegix.uri=new function(){this.getParamHash=fleegix.url.qsToObject;this.getParam=function(A,C){var B=C||fleegix.url.getQS(document.location.href);return fleegix.url.getQSParam(B,A)};this.setParam=function(A,D,C){var B=C||fleegix.url.getQS(document.location.href);return fleegix.url.setQSParam(B,A,D)};this.getQuery=fleegix.url.getQS;this.getBase=fleegix.url.getBase};fleegix.css=new function(){this.addClass=function(B,A){fleegix.css.removeClass(B,A);var C=B.className;C+=&quot; &quot;+A;C=fleegix.string.trim(C);B.className=C};this.removeClass=function(C,B){var D=C.className;var A=&quot;\\b&quot;+B+&quot;\\b&quot;;A=new RegExp(A,&quot;g&quot;);D=D.replace(A,&quot;&quot;);D=D.replace(&quot;  &quot;,&quot; &quot;);D=fleegix.string.trim(D);C.className=D};this.replaceClass=function(B,A,C){this.removeClass(B,A);this.addClass(B,C)}};fleegix.event=new function(){var B=[];var A={};this.compatibilityMode=false;this.listen=function(){var G=arguments[0];var D=arguments[1];var F=this.compatibilityMode;var E={};var H={};if(typeof arguments[2]==&quot;function&quot;){E.method=arguments[2];H=arguments[3]||{}}else{E.context=arguments[2];E.method=arguments[3];H=arguments[4]||{}}if(!G){throw new Error(&quot;fleegix.listen called on an object (&quot;+G+&quot;) that does not exist.&quot;)}if(D==&quot;onmousewheel&quot;){if(window.addEventListener&amp;&amp;typeof G.onmousewheel==&quot;undefined&quot;){G.onmousewheel=null}}var C;if(this.compatibilityMode){if(G[D]&amp;&amp;G._fleegixEventListenReg){C=G._fleegixEventListenReg[D]}else{C=null}}else{C=G[D]?G[D].listenReg:null}if(!C){C={};C.orig={};C.orig.obj=G;C.orig.methName=D;if(G[D]){C.orig.methCode=G[D]}C.after=[];G[D]=function(){var L=F?G._fleegixEventListenReg[D]:G[D].listenReg;if(!L){if(G[&quot;_&quot;+D+&quot;_suppressErrors&quot;]){return false}else{throw new Error(&quot;Cannot execute handlers for &quot;+G+&quot;  \&quot;&quot;+D+&quot;\&quot;. Something (likely another JavaScript library) has removed the fleegix.event.listen handler registry.&quot;)}}var I=[];for(var K=0;K&lt;arguments.length;K++){I.push(arguments[K])}if(L.orig.methCode){L.orig.methCode.apply(L.orig.obj,I)}var M=null;if(G.attachEvent||G.nodeType||G.addEventListener){if(!I.length){try{switch(true){case !!G.ownerDocument:M=G.ownerDocument.parentWindow.event;break;case !!G.documentElement:M=G.documentElement.ownerDocument.parentWindow.event;break;case !!G.event:M=G.event;break;default:M=window.event;break}}catch(O){M=window.event}}else{M=I[0]}if(M){if(typeof M.target==&quot;undefined&quot;){M.target=M.srcElement}if(typeof M.srcElement==&quot;undefined&quot;){M.srcElement=M.target}if(M.type==&quot;DOMMouseScroll&quot;||M.type==&quot;mousewheel&quot;){if(M.wheelDelta){M.delta=M.wheelDelta/120}else{if(M.detail){M.delta=-M.detail/3}}}I[0]=M}}for(var K=0;K&lt;L.after.length;K++){var J=L.after[K];var N=null;var P=null;if(!J.context){N=J.method;P=window}else{N=J.context[J.method];P=J.context}if(typeof N!=&quot;function&quot;){throw (N+&quot; is not an executable function.&quot;)}else{N.apply(P,I)}M=I[0];if(J.stopPropagation){this.stopPropagation(M)}if(J.preventDefault){this.preventDefault(M)}}};if(this.compatibilityMode){if(!G._fleegixEventListenReg){G._fleegixEventListenReg={}}G._fleegixEventListenReg[D]=C}else{G[D].listenReg=C}B.push(C);if(D==&quot;onmousewheel&quot;){if(window.addEventListener){G.addEventListener(&quot;DOMMouseScroll&quot;,G.onmousewheel,false)}}}C.after.push(E);if(this.compatibilityMode){if(!G._fleegixEventListenReg){G._fleegixEventListenReg={}}G._fleegixEventListenReg[D]=C}else{G[D].listenReg=C}};this.unlisten=function(){var H=arguments[0];var E=arguments[1];var D;if(this.compatibilityMode){if(H[E]&amp;&amp;H._fleegixEventListenReg){D=H._fleegixEventListenReg[E]}else{D=null}}else{D=H[E]?H[E].listenReg:null}var C=null;if(!D){return false}for(var F=0;F&lt;D.after.length;F++){var G=D.after[F];if(typeof arguments[2]==&quot;function&quot;){if(G.method==arguments[2]){D.after.splice(F,1);break}}else{if(G.context==arguments[2]&amp;&amp;G.method==arguments[3]){D.after.splice(F,1);break}}}if(this.compatibilityMode){H._fleegixEventListenReg[E]=D}else{H[E].listenReg=D}};this.flush=function(){for(var C=0;C&lt;B.length;C++){var D=B[C];removeObj=D.orig.obj;removeMethod=D.orig.methName;removeObj[removeMethod]=null}};this.subscribe=function(C,D,E){if(!D){return }if(!A[C]){A[C]={};A[C].audience=[]}else{this.unsubscribe(C,D)}A[C].audience.push([D,E])};this.unsubscribe=function(E,D){if(!D){A[E]=null}else{if(A[E]){var F=A[E].audience;for(var C=0;C&lt;F.length;C++){if(F[C][0]==D){F.splice(C,1)}}}}};this.publish=function(F,G){if(A[F]){var H=A[F].audience;for(var D=0;D&lt;H.length;D++){var C=H[D][0];var E=H[D][1];C[E](G)}}};this.getSrcElementByAttribute=function(D,E){var C;if(D.srcElement){C=D.srcElement}else{if(D.target){C=D.target}}if(!C||typeof C[E]==&quot;undefined&quot;){return null}else{while(!C[E]||C.nodeType==3){if(C.parentNode){C=C.parentNode}else{return null}}}return C};this.getSrcElementId=function(D){var C=this.getSrcElementByAttribute(D,&quot;id&quot;)||null;return C.id||null};this.annihilate=function(C){this.stopPropagation(C);this.preventDefault(C)};this.stopPropagation=function(C){if(C.stopPropagation){C.stopPropagation()}else{C.cancelBubble=true}return C};this.preventDefault=function(C){if(C.preventDefault){C.preventDefault()}else{C.returnValue=false}return C};this.suppressHandlerErrors=function(D,C){D[&quot;_&quot;+C+&quot;_suppressErrors&quot;]=true}};fleegix.xhr=new function(){this.maxXhrs=5;this.lastReqId=0;this.debug=false;this.defaultTimeoutSeconds=300;this.useDefaultErrHandlerForSync=true;this.responseFormats={TXT:&quot;text&quot;,XML:&quot;xml&quot;,OBJ:&quot;object&quot;};this.get=function(){var X={};var S=null;var U=Array.prototype.slice.apply(arguments);if(typeof U[0]==&quot;function&quot;){X.async=true;S=U.shift()}else{X.async=false}var T=U.shift();if(typeof U[0]==&quot;object&quot;){var V=U.shift();for(var W in V){X[W]=V[W]}}else{X.responseFormat=U.shift()||&quot;text&quot;}X.handleSuccess=S;X.url=T;return this.doReq(X)};this.doGet=function(){return this.get.apply(this,arguments)};this.post=function(){var Y={};var S=null;var U=Array.prototype.slice.apply(arguments);if(typeof U[0]==&quot;function&quot;){Y.async=true;S=U.shift()}else{Y.async=false}var T=U.shift();var W=U.shift();if(typeof U[0]==&quot;object&quot;){var V=U.shift();for(var X in V){Y[X]=V[X]}}else{Y.responseFormat=U.shift()||&quot;text&quot;}Y.handleSuccess=S;Y.url=T;Y.data=W;Y.method=&quot;POST&quot;;return this.doReq(Y)};this.doPost=function(){return this.post.apply(this,arguments)};this.doReq=function(S){return this.send(S)};this.send=function(W){var T=W||{};var S=new fleegix.xhr.Request();var V=null;for(var U in T){if(T.hasOwnProperty(U)){S[U]=T[U]}}S.method=S.method.toUpperCase();S.id=this.lastReqId;this.lastReqId++;if(S.async){if(K.length){V=K.shift()}else{if(H.length&lt;this.maxXhrs){V=D()}}if(V!==null){G(S,V)}else{if(S.uber){J.unshift(S)}else{J.push(S)}}return S.id}else{return G(S)}};this.abort=function(U){var T=F[U];var S=H[T.xhrId];if(S){S.onreadystatechange=function(){};S.abort();T.aborted=true;O(T);return true}else{return false}};this.isReqSuccessful=function(T){var S=T.status;if(!S){return false}if(document.all&amp;&amp;S==1223){S=204}if((S&gt;199&amp;&amp;S&lt;300)||S==304){return true}else{return false}};var L=this;var Q=null;var M;var H=[];var J=[];var K=[];var F={};var N=[];var C=null;var I=null;var A=null;var D=function(V){var U=0;var T=[&quot;Msxml2.XMLHTTP.6.0&quot;,&quot;MSXML2.XMLHTTP.3.0&quot;,&quot;Microsoft.XMLHTTP&quot;];var S=null;if(window.XMLHttpRequest){S=new XMLHttpRequest()}else{if(window.ActiveXObject){if(Q){S=new ActiveXObject(Q)}else{for(var U=0;U&lt;T.length;U++){try{S=new ActiveXObject(T[U]);Q=T[U];break}catch(X){}}}}}if(S){if(V){return S}else{H.push(S);var W=H.length-1;return W}}else{throw new Error(&quot;Could not create XMLHttpRequest object.&quot;)}};var G=function(b,c){var Y=null;var Z=null;var T=&quot;&quot;;var W=null;if(b.async){Y=c;Z=H[Y];F[b.id]=b;N.unshift(b);b.xhrId=Y}else{if(!C){C=D(true)}Z=C;I=b}if(b.preventCache){var U=new Date().getTime();T=b.url.indexOf(&quot;?&quot;)&gt;-1?b.url+&quot;&amp;preventCache=&quot;+U:b.url+&quot;?preventCache=&quot;+U}else{T=b.url}if(document.all){Z.abort()}if(b.username&amp;&amp;b.password){Z.open(b.method,T,b.async,b.username,b.password)}else{Z.open(b.method,T,b.async)}if(b.mimeType&amp;&amp;navigator.userAgent.indexOf(&quot;MSIE&quot;)==-1){Z.overrideMimeType(b.mimeType)}var V=b.headers;for(var X in V){if(V.hasOwnProperty(X)){Z.setRequestHeader(X,V[X])}}if(b.method==&quot;POST&quot;||b.method==&quot;PUT&quot;){b.data=b.data||b.dataPayload;if(!b.data){b.data=&quot;&quot;}if(!fleegix.isSafari){var S=typeof b.data==&quot;string&quot;?b.data.length:0;Z.setRequestHeader(&quot;Content-Length&quot;,S)}if(typeof b.headers[&quot;Content-Type&quot;]==&quot;undefined&quot;){Z.setRequestHeader(&quot;Content-Type&quot;,&quot;application/x-www-form-urlencoded&quot;)}}Z.send(b.data);if(A===null){A=setTimeout(B,10)}if(!b.async){var a=R(Z,b);I=null;if(N.length){A=setTimeout(B,10)}else{A=null}return a}};var B=function(){var S=N;var X=new Date().getTime();if(I!==null){return }else{for(var U=0;U&lt;S.length;U++){var V=S[U];var T=H[V.xhrId];var W=((X-V.startTime)&gt;(V.timeoutSeconds*1000));switch(true){case (V.aborted||!T.readyState):N.splice(U,1);break;case W:N.splice(U,1);P(V);break;case (T.readyState==4):N.splice(U,1);R.call(L,T,V);break}}}clearTimeout(A);if(N.length){A=setTimeout(B,10)}else{A=null}};var R=function(S,T){var V;switch(T.responseFormat){case&quot;xml&quot;:if(T.xmlDocFromResponseText&amp;&amp;typeof fleegix.xml!=&quot;undefined&quot;){V=fleegix.xml.createDoc(S.responseText)}else{V=S.responseXML}break;case&quot;object&quot;:V=S;break;case&quot;text&quot;:default:V=S.responseText;break}if(T.handleAll){T.handleAll(V,T.id)}else{try{switch(true){case L.isReqSuccessful(S):if(T.async){if(!T.handleSuccess){throw new Error(&quot;No response handler defined for this request&quot;)}else{T.handleSuccess(V,T.id)}}else{return V}break;case (S.status==0):if(L.debug){throw new Error(&quot;XMLHttpRequest HTTP status is zero.&quot;)}break;case (S.status==M):if(L.debug){throw new Error(&quot;XMLHttpRequest HTTP status not set.&quot;)}break;default:if(!T.async&amp;&amp;!L.useDefaultErrHandlerForSync){return V}else{if(T.handleErr){T.handleErr(V,T.id)}else{E(S)}}break}}catch(U){throw U}}if(T.async){O(T)}return true};var P=function(S){if(L.abort.apply(L,[S.id])){if(typeof S.handleTimeout==&quot;function&quot;){S.handleTimeout()}else{alert(&quot;XMLHttpRequest to &quot;+S.url+&quot; timed out.&quot;)}}};var O=function(T){delete F[T.id];if(J.length){var S=J.shift();S.startTime=new Date().getTime();G(S,T.xhrId)}else{K.push(T.xhrId)}};var E=function(T){var S;try{S=window.open(&quot;&quot;,&quot;errorWin&quot;);S.document.body.innerHTML=T.responseText}catch(U){alert(&quot;An error occurred, but the error message cannot be displayed because of your browser's pop-up blocker.\nPlease allow pop-ups from this Web site.&quot;)}}};fleegix.xhr.Request=function(){this.id=0;this.xhrId=null;this.url=null;this.status=null;this.statusText=&quot;&quot;;this.method=&quot;GET&quot;;this.async=true;this.data=null;this.readyState=null;this.responseText=null;this.responseXML=null;this.handleSuccess=null;this.handleErr=null;this.handleAll=null;this.handleTimeout=null;this.responseFormat=fleegix.xhr.responseFormats.TXT;this.xmlDocFromResponseText=false;this.mimeType=null;this.username=&quot;&quot;;this.password=&quot;&quot;;this.headers=[];this.preventCache=false;this.startTime=new Date().getTime();this.timeoutSeconds=fleegix.xhr.defaultTimeoutSeconds;this.uber=false;this.aborted=false};fleegix.xhr.Request.prototype.setRequestHeader=function(B,A){this.headers.push(B+&quot;: &quot;+A)};fleegix.json=new function(){var _cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;this.serialize=function(obj){var str=&quot;&quot;;switch(typeof obj){case&quot;object&quot;:switch(true){case obj===null:return&quot;null&quot;;break;case obj instanceof Array:for(var i=0;i&lt;obj.length;i++){if(str){str+=&quot;,&quot;}str+=fleegix.json.serialize(obj[i])}return&quot;[&quot;+str+&quot;]&quot;;break;case (fleegix.isFF&amp;&amp;obj instanceof DOMException):str+=&quot;\&quot;&quot;+obj.toString()+&quot;\&quot;&quot;;break;case typeof obj.toString!=&quot;undefined&quot;:for(var i in obj){if(str){str+=&quot;,&quot;}str+=&quot;\&quot;&quot;+i+&quot;\&quot;:&quot;;if(typeof obj[i]==&quot;undefined&quot;){str+=&quot;\&quot;undefined\&quot;&quot;}else{str+=fleegix.json.serialize(obj[i])}}return&quot;{&quot;+str+&quot;}&quot;;break}return str;case&quot;unknown&quot;:case&quot;undefined&quot;:case&quot;function&quot;:return&quot;\&quot;undefined\&quot;&quot;;case&quot;string&quot;:str+=&quot;\&quot;&quot;+obj.replace(/([&quot;\\])/g,&quot;\\$1&quot;).replace(/\r/g,&quot;&quot;).replace(/\n/g,&quot;\\n&quot;)+&quot;\&quot;&quot;;return str;default:return String(obj)}};this.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&amp;&amp;typeof value===&quot;object&quot;){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}_cx.lastIndex=0;if(_cx.test(text)){text=text.replace(_cx,function(a){return&quot;\\u&quot;+(&quot;0000&quot;+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:[&quot;\\\/bfnrt]|u[0-9a-fA-F]{4})/g,&quot;@&quot;).replace(/&quot;[^&quot;\\\n\r]*&quot;|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,&quot;]&quot;).replace(/(?:^|:|,)(?:\s*\[)+/g,&quot;&quot;))){j=eval(&quot;(&quot;+text+&quot;)&quot;);return typeof reviver===&quot;function&quot;?walk({&quot;&quot;:j},&quot;&quot;):j}throw new SyntaxError(&quot;JSON not parseable.&quot;)}};fleegix.string=new function(){var D=/^\s+/;var A=/\s+$/;var C=/^\s+|\s+$/g;var B={&quot;&amp;&quot;:&quot;&amp;amp;&quot;,&quot;&lt;&quot;:&quot;&amp;lt;&quot;,&quot;&gt;&quot;:&quot;&amp;gt;&quot;,&quot;\&quot;&quot;:&quot;&amp;quot;&quot;,&quot;'&quot;:&quot;&amp;#39;&quot;};var F=function(G){return function(J){s=J;var H,K;for(var I in B){H=G==&quot;to&quot;?I:B[I];K=G==&quot;to&quot;?B[I]:I;s=s.replace(new RegExp(H,&quot;gm&quot;),K)}return s}};var E=function(G){return function(I){var H=&quot;&quot;;for(var J in B){H+=G==&quot;to&quot;?J:B[J];H+=&quot;|&quot;}H=H.substr(0,H.length-1);H=new RegExp(H,&quot;gm&quot;);return H.test(I)}};this.escapeXML=F(&quot;to&quot;);this.unescapeXML=F(&quot;from&quot;);this.needsEscape=E(&quot;to&quot;);this.needsUnescape=E(&quot;from&quot;);this.toArray=function(I){var G=[];for(var H=0;H&lt;I.length;H++){G[H]=I.substr(H,1)}return G};this.reverse=function(G){return this.toArray(G).reverse().join(&quot;&quot;)};this.ltrim=function(I,H){var G=H?new RegExp(&quot;^&quot;+H+&quot;+&quot;):D;return I.replace(G,&quot;&quot;)};this.rtrim=function(I,H){var G=H?new RegExp(H+&quot;+$&quot;):A;return I.replace(G,&quot;&quot;)};this.trim=function(I,H){var G=H?new RegExp(&quot;^&quot;+H+&quot;+|&quot;+H+&quot;+$&quot;,&quot;g&quot;):C;return I.replace(G,&quot;&quot;)};this.lpad=function(J,I,H){var G=J;while(G.length&lt;H){G=I+G}return G};this.rpad=function(J,I,H){var G=J;while(G.length&lt;H){G=G+I}return G};this.toLowerCaseWithUnderscores=function(G){return G.replace(/([A-Z]+)/g,&quot;_$1&quot;).toLowerCase().replace(/^_/,&quot;&quot;)};this.deCamelize=function(G){return this.toLowerCaseWithUnderscores(G)};this.toCamelCase=function(G){return G.replace(/_[a-z]{1}/g,function(H){return H.replace(&quot;_&quot;,&quot;&quot;).toUpperCase()})};this.camelize=function(G){return this.toCamelCase(G)};this.capitalize=function(G){return G.substr(0,1).toUpperCase()+G.substr(1)}};fleegix.cookie=new function(){this.set=function(B,H,E){var A=E||{};var K=&quot;/&quot;;var I=0;var G=0;var F=0;var D=&quot;&quot;;var J=0;if(typeof E==&quot;object&quot;){K=A.path||&quot;/&quot;;I=A.days||0;G=A.hours||0;F=A.minutes||0}else{K=E||&quot;/&quot;}J+=I?I*24*60*60*1000:0;J+=G?G*60*60*1000:0;J+=F?F*60*1000:0;if(J){var C=new Date();C.setTime(C.getTime()+J);D=&quot;; expires=&quot;+C.toGMTString()}else{D=&quot;&quot;}document.cookie=B+&quot;=&quot;+H+D+&quot;; path=&quot;+K};this.get=function(B){var D=B+&quot;=&quot;;var A=document.cookie.split(&quot;;&quot;);for(var C=0;C&lt;A.length;C++){var E=A[C];while(E.charAt(0)==&quot; &quot;){E=E.substring(1,E.length)}if(E.indexOf(D)===0){return E.substring(D.length,E.length)}}return null};this.create=this.set;this.destroy=function(A,C){var B={};B.minutes=-1;if(C){B.path=C}this.set(A,&quot;&quot;,B)}};fleegix.form={};fleegix.form.serialize=function(C,B){var A=fleegix.form.toObject(C,B);if(typeof fleegix.url==&quot;undefined&quot;){throw new Error(&quot;fleegix.form.serialize depends on the fleegix.url module.&quot;)}var D=fleegix.url.objectToQS(A,B);return D};fleegix.form.toObject=function(K,D){var A=D||{};var J={};function H(R,Q){if(R){var P=null;if(typeof R==&quot;string&quot;){P=[];P.push(R)}else{P=R}P.push(Q);return P}else{return Q}}for(var I=0;I&lt;K.elements.length;I++){var F=K.elements[I];if(F.name){var O=F.name.indexOf(&quot;[&quot;);var C=F.name.indexOf(&quot;]&quot;);var N=&quot;&quot;;var B=&quot;&quot;;var M;var E;if(A.hierarchical&amp;&amp;(O&gt;0)&amp;&amp;(C&gt;2)){N=F.name.substring(0,O);B=F.name.substring(O+1,C);if(typeof J[N]==&quot;undefined&quot;){J[N]={}}M=J[N];E=B}else{M=J;E=F.name}switch(F.type){case&quot;text&quot;:case&quot;hidden&quot;:case&quot;password&quot;:case&quot;textarea&quot;:case&quot;select-one&quot;:M[E]=F.value;break;case&quot;select-multiple&quot;:for(var G=0;G&lt;F.options.length;G++){var L=F.options[G];if(L.selected){M[E]=H(M[E],L.value)}}break;case&quot;radio&quot;:if(F.checked){M[E]=F.value}break;case&quot;checkbox&quot;:if(F.checked){M[E]=H(M[E],F.value)}break;case&quot;submit&quot;:case&quot;reset&quot;:case&quot;file&quot;:case&quot;image&quot;:case&quot;button&quot;:if(A.pedantic){M[E]=F.value}break}}}return J};fleegix.form.toHash=fleegix.form.toObject
\ No newline at end of file</diff>
      <filename>fleegix.js</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>fleegix.js.gz</filename>
    </modified>
    <modified>
      <diff>@@ -447,6 +447,16 @@ fleegix.dom = new function() {
   this.getViewportHeight = function () {
     return getViewportMeasure('Height');
   };
+  this.getViewportScrollTop = function () {
+    return window.pageYOffset ||
+        document.body.scrollTop ||
+        document.documentElement.scrollTop || 0;
+  };
+  this.getViewportScrollLeft = function () {
+    window.pageXOffset ||
+        document.body.scrollLeft ||
+        document.documentElement.scrollLeft || 0;
+  };
   this.center = function (node) {
     var nW = node.offsetWidth;
     var nH = node.offsetHeight;
@@ -1831,11 +1841,12 @@ fleegix.string = new function () {
   // Builds a method that tests for any of the escapable
   // characters -- useful for avoiding double-escaping if
   // you're not sure whether a string is already escaped
-  var _buildEscapeTest = function () {
+  var _buildEscapeTest = function (direction) {
     return function (s) {
       var pat = '';
       for (var p in _CHARS) {
-        pat += p + '|';
+        pat += direction == 'to' ? p : _CHARS[p];
+        pat += '|';
       }
       pat = pat.substr(0, pat.length - 1);
       pat = new RegExp(pat, &quot;gm&quot;);
@@ -1848,7 +1859,8 @@ fleegix.string = new function () {
   this.unescapeXML = _buildEscapes('from');
   // Test if a string includes special chars that
   // require escaping
-  this.needsEscape = _buildEscapeTest();
+  this.needsEscape = _buildEscapeTest('to');
+  this.needsUnescape = _buildEscapeTest('from');
   this.toArray = function (str) {
     var arr = [];
     for (var i = 0; i &lt; str.length; i++) {
@@ -2088,2258 +2100,3 @@ fleegix.form.toObject= function (f, o) {
 };
 // Alias for backward compat
 fleegix.form.toHash = fleegix.form.toObject;
-
-if (typeof fleegix.date == 'undefined') { fleegix.date = {}; }
-fleegix.date.util = {};
-
-fleegix.date.util.weekdayLong = ['Sunday', 'Monday', 'Tuesday',
-  'Wednesday', 'Thursday', 'Friday', 'Saturday'];
-fleegix.date.util.weekdayShort = ['Sun', 'Mon', 'Tue', 'Wed',
-  'Thu', 'Fri', 'Sat'];
-fleegix.date.util.monthLong = ['January', 'February', 'March',
-  'April', 'May', 'June', 'July', 'August', 'September',
-  'October', 'November', 'December'];
-fleegix.date.util.monthShort = ['Jan', 'Feb', 'Mar', 'Apr',
-  'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
-fleegix.date.util.meridian = {
-  'AM': 'AM',
-  'PM': 'PM'
-}
-
-fleegix.date.util.supportedFormats = {
-  // abbreviated weekday name according to the current locale
-  'a': function (dt) { return fleegix.date.util.weekdayShort[dt.getDay()]; },
-  // full weekday name according to the current locale
-  'A': function (dt) { return fleegix.date.util.weekdayLong[dt.getDay()]; },
-  // abbreviated month name according to the current locale
-  'b': function (dt) { return fleegix.date.util.monthShort[dt.getMonth()]; },
-  'h': function (dt) { return fleegix.date.util.strftime(dt, '%b'); },
-  // full month name according to the current locale
-  'B': function (dt) { return fleegix.date.util.monthLong[dt.getMonth()]; },
-  // preferred date and time representation for the current locale
-  'c': function (dt) { return fleegix.date.util.strftime(dt, '%a %b %d %T %Y'); },
-  // century number (the year divided by 100 and truncated
-  // to an integer, range 00 to 99)
-  'C': function (dt) { return fleegix.date.util.calcCentury(dt.getFullYear());; },
-  // day of the month as a decimal number (range 01 to 31)
-  'd': function (dt) { return fleegix.date.util.leftPad(dt.getDate(), 2, '0'); },
-  // same as %m/%d/%y
-  'D': function (dt) { return fleegix.date.util.strftime(dt, '%m/%d/%y') },
-  // day of the month as a decimal number, a single digit is
-  // preceded by a space (range ' 1' to '31')
-  'e': function (dt) { return fleegix.date.util.leftPad(dt.getDate(), 2, ' '); },
-  // month as a decimal number, a single digit is
-  // preceded by a space (range ' 1' to '12')
-  'f': function () { return fleegix.date.util.strftimeNotImplemented('f'); },
-  // same as %Y-%m-%d
-  'F': function (dt) { return fleegix.date.util.strftime(dt, '%Y-%m-%d');  },
-  // like %G, but without the century.
-  'g': function () { return fleegix.date.util.strftimeNotImplemented('g'); },
-  // The 4-digit year corresponding to the ISO week number
-  // (see %V).  This has the same format and value as %Y,
-  // except that if the ISO week number belongs to the
-  // previous or next year, that year is used instead.
-  'G': function () { return fleegix.date.util.strftimeNotImplemented('G'); },
-  // hour as a decimal number using a 24-hour clock (range
-  // 00 to 23)
-  'H': function (dt) { return fleegix.date.util.leftPad(dt.getHours(), 2, '0'); },
-  // hour as a decimal number using a 12-hour clock (range
-  // 01 to 12)
-  'I': function (dt) { return fleegix.date.util.leftPad(
-    fleegix.date.util.hrMil2Std(dt.getHours()), 2, '0'); },
-  // day of the year as a decimal number (range 001 to 366)
-  'j': function (dt) { return fleegix.date.util.leftPad(
-    fleegix.date.util.calcDays(dt), 3, '0'); },
-  // Hour as a decimal number using a 24-hour clock (range
-  // 0 to 23 (space-padded))
-  'k': function (dt) { return fleegix.date.util.leftPad(dt.getHours(), 2, ' '); },
-  // Hour as a decimal number using a 12-hour clock (range
-  // 1 to 12 (space-padded))
-  'l': function (dt) { return fleegix.date.util.leftPad(
-    fleegix.date.util.hrMil2Std(dt.getHours()), 2, ' '); },
-  // month as a decimal number (range 01 to 12)
-  'm': function (dt) { return fleegix.date.util.leftPad((dt.getMonth()+1), 2, '0'); },
-  // minute as a decimal number
-  'M': function (dt) { return fleegix.date.util.leftPad(dt.getMinutes(), 2, '0'); },
-  // Linebreak
-  'n': function () { return '\n'; },
-  // either `am' or `pm' according to the given time value,
-  // or the corresponding strings for the current locale
-  'p': function (dt) { return fleegix.date.util.getMeridian(dt.getHours()); },
-  // time in a.m. and p.m. notation
-  'r': function (dt) { return fleegix.date.util.strftime(dt, '%I:%M:%S %p'); },
-  // time in 24 hour notation
-  'R': function (dt) { return fleegix.date.util.strftime(dt, '%H:%M'); },
-  // second as a decimal number
-  'S': function (dt) { return fleegix.date.util.leftPad(dt.getSeconds(), 2, '0'); },
-  // Tab char
-  't': function () { return '\t'; },
-  // current time, equal to %H:%M:%S
-  'T': function (dt) { return fleegix.date.util.strftime(dt, '%H:%M:%S'); },
-  // weekday as a decimal number [1,7], with 1 representing
-  // Monday
-  'u': function (dt) { return fleegix.date.util.convertOneBase(dt.getDay()); },
-  // week number of the current year as a decimal number,
-  // starting with the first Sunday as the first day of the
-  // first week
-  'U': function () { return fleegix.date.util.strftimeNotImplemented('U'); },
-  // week number of the year (Monday as the first day of the
-  // week) as a decimal number [01,53]. If the week containing
-  // 1 January has four or more days in the new year, then it
-  // is considered week 1. Otherwise, it is the last week of
-  // the previous year, and the next week is week 1.
-  'V': function () { return fleegix.date.util.strftimeNotImplemented('V'); },
-  // week number of the current year as a decimal number,
-  // starting with the first Monday as the first day of the
-  // first week
-  'W': function () { return fleegix.date.util.strftimeNotImplemented('W'); },
-  // day of the week as a decimal, Sunday being 0
-  'w': function (dt) { return dt.getDay(); },
-  // preferred date representation for the current locale
-  // without the time
-  'x': function (dt) { return fleegix.date.util.strftime(dt, '%D'); },
-  // preferred time representation for the current locale
-  // without the date
-  'X': function (dt) { return fleegix.date.util.strftime(dt, '%T'); },
-  // year as a decimal number without a century (range 00 to
-  // 99)
-  'y': function (dt) { return fleegix.date.util.getTwoDigitYear(dt.getFullYear()); },
-  // year as a decimal number including the century
-  'Y': function (dt) { return fleegix.date.util.leftPad(dt.getFullYear(), 4, '0'); },
-  // time zone or name or abbreviation
-  'z': function () { return fleegix.date.util.strftimeNotImplemented('z'); },
-  'Z': function () { return fleegix.date.util.strftimeNotImplemented('Z'); },
-  // Literal percent char
-  '%': function (dt) { return '%'; }
-};
-
-fleegix.date.util.getSupportedFormats = function () {
-  var str = '';
-  for (var i in fleegix.date.util.supportedFormats) { str += i; }
-  return str;
-}
-
-fleegix.date.util.supportedFormatsPat = new RegExp('%[' +
-  fleegix.date.util.getSupportedFormats() + ']{1}', 'g');
-
-fleegix.date.util.strftime = function (dt, format) {
-  var d = null;
-  var pats = [];
-  var dts = [];
-  var str = format;
-
-  // If no dt, use current date
-  d = dt ? dt : new Date();
-  // Allow either Date obj or UTC stamp
-  d = typeof dt == 'number' ? new Date(dt) : dt;
-
-  // Grab all instances of expected formats into array
-  while (pats = fleegix.date.util.supportedFormatsPat.exec(format)) {
-    dts.push(pats[0]);
-  }
-
-  // Process any hits
-  for (var i = 0; i &lt; dts.length; i++) {
-    key = dts[i].replace(/%/, '');
-    str = str.replace('%' + key,
-      fleegix.date.util.supportedFormats[key](d));
-  }
-  return str;
-
-};
-
-fleegix.date.util.strftimeNotImplemented = function (s) {
-  throw('fleegix.date.util.strftime format &quot;' + s + '&quot; not implemented.');
-};
-
-fleegix.date.util.leftPad = function (instr, len, spacer) {
-  var str = instr.toString();
-  // spacer char optional, default to space
-  var sp = spacer ? spacer : ' ';
-  while (str.length &lt; len) {
-    str = sp + str;
-  }
-  return str;
-};
-
-/**
- * Calculate the century to which a particular year belongs
- * @param y Integer year number
- * @return Integer century number
- */
-fleegix.date.util.calcCentury = function (y) {
-  var ret = parseInt(y/100);
-  ret = ret.toString();
-  return fleegix.date.util.leftPad(ret);
-};
-
-/**
- * Calculate the day number in the year a particular date is on
- * @param dt JavaScript date object
- * @return Integer day number in the year for the given date
- */
-fleegix.date.util.calcDays = function(dt) {
-  var first = new Date(dt.getFullYear(), 0, 1);
-  var diff = 0;
-  var ret = 0;
-  first = first.getTime();
-  diff = (dt.getTime() - first);
-  ret = parseInt(((((diff/1000)/60)/60)/24))+1;
-  return ret;
-};
-
-/**
- * Adjust from 0-6 base week to 1-7 base week
- * @param d integer for day of week
- * @return Integer day number for 1-7 base week
- */
-fleegix.date.util.convertOneBase = function (d) {
-  return d == 0 ? 7 : d;
-};
-
-fleegix.date.util.getTwoDigitYear = function (yr) {
-  // Add a millenium to take care of years before the year 1000,
-  // (e.g, the year 7) since we're only taking the last two digits
-  // If we overshoot, it doesn't matter
-  var millenYear = yr + 1000;
-  var str = millenYear.toString();
-  str = str.substr(2); // Get the last two digits
-  return str
-};
-
-/**
- * Return 'AM' or 'PM' based on hour in 24-hour format
- * @param h Integer for hour in 24-hour format
- * @return String of either 'AM' or 'PM' based on hour number
- */
-fleegix.date.util.getMeridian = function (h) {
-  return h &gt; 11 ? fleegix.date.util.meridian.PM :
-    fleegix.date.util.meridian.AM;
-};
-
-/**
- * Convert a 24-hour formatted hour to 12-hour format
- * @param hour Integer hour number
- * @return String for hour in 12-hour format -- may be string length of one
- */
-fleegix.date.util.hrMil2Std = function (hour) {
-  var h = typeof hour == 'number' ? hour : parseInt(hour);
-  var str = h &gt; 12 ? h - 12 : h;
-  str = str == 0 ? 12 : str;
-  return str;
-};
-
-/**
- * Convert a 12-hour formatted hour with meridian flag to 24-hour format
- * @param hour Integer hour number
- * @param pm Boolean flag, if PM hour then set to true
- * @return String for hour in 24-hour format
- */
-fleegix.date.util.hrStd2Mil = function  (hour, pm) {
-  var h = typeof hour == 'number' ? hour : parseInt(hour);
-  var str = '';
-  // PM
-  if (pm) {
-    str = h &lt; 12 ? (h+12) : h;
-  }
-  // AM
-  else {
-    str = h == 12 ? 0 : h;
-  }
-  return str;
-};
-
-// Constants for use in fleegix.date.util.add
-fleegix.date.util.dateParts = {
-  YEAR: 0, MONTH: 1, DAY: 2, HOUR: 3, MINUTE: 4, SECOND: 5,
-    MILLISECOND: 6, QUARTER: 7, WEEK: 8, WEEKDAY: 9
-};
-
-/**
- * Add to a Date in intervals of different size, from
- * milliseconds to years
- * @param dt -- Date (or timestamp Number), date to increment
- * @param interv -- Number, a constant representing the interval,
- *    e.g. YEAR, MONTH, DAY.  See fleegix.date.util.dateParts
- * @param incr -- Number, how much to add to the date
- * @return Integer day number for 1-7 base week
- */
-fleegix.date.util.add = function (dt, interv, incr) {
-  if (typeof dt == 'number') { dt = new Date(dt); }
-  function fixOvershoot(){
-    if (sum.getDate() &lt; dt.getDate()){
-      sum.setDate(0);
-    }
-  }
-  var sum = new Date(dt);
-  with (fleegix.date.util.dateParts) {
-    switch(interv){
-      case YEAR:
-        sum.setFullYear(dt.getFullYear()+incr);
-        // Keep increment/decrement from 2/29 out of March
-        fixOvershoot();
-        break;
-      case QUARTER:
-        // Naive quarter is just three months
-        incr*=3;
-        // fallthrough...
-      case MONTH:
-        sum.setMonth(dt.getMonth()+incr);
-        // Reset to last day of month if you overshoot
-        fixOvershoot();
-        break;
-      case WEEK:
-        incr*=7;
-        // fallthrough...
-      case DAY:
-        sum.setDate(dt.getDate() + incr);
-        break;
-      case WEEKDAY:
-        //FIXME: assumes Saturday/Sunday weekend, but even this is not fixed.
-        // There are CLDR entries to localize this.
-        var dat = dt.getDate();
-        var weeks = 0;
-        var days = 0;
-        var strt = 0;
-        var trgt = 0;
-        var adj = 0;
-        // Divide the increment time span into weekspans plus leftover days
-        // e.g., 8 days is one 5-day weekspan / and two leftover days
-        // Can't have zero leftover days, so numbers divisible by 5 get
-        // a days value of 5, and the remaining days make up the number of weeks
-        var mod = incr % 5;
-        if (mod == 0) {
-          days = (incr &gt; 0) ? 5 : -5;
-          weeks = (incr &gt; 0) ? ((incr-5)/5) : ((incr+5)/5);
-        }
-        else {
-          days = mod;
-          weeks = parseInt(incr/5);
-        }
-        // Get weekday value for orig date param
-        strt = dt.getDay();
-        // Orig date is Sat / positive incrementer
-        // Jump over Sun
-        if (strt == 6 &amp;&amp; incr &gt; 0) {
-          adj = 1;
-        }
-        // Orig date is Sun / negative incrementer
-        // Jump back over Sat
-        else if (strt == 0 &amp;&amp; incr &lt; 0) {
-          adj = -1;
-        }
-        // Get weekday val for the new date
-        trgt = strt + days;
-        // New date is on Sat or Sun
-        if (trgt == 0 || trgt == 6) {
-          adj = (incr &gt; 0) ? 2 : -2;
-        }
-        // Increment by number of weeks plus leftover days plus
-        // weekend adjustments
-        sum.setDate(dat + (7*weeks) + days + adj);
-        break;
-      case HOUR:
-        sum.setHours(sum.getHours()+incr);
-        break;
-      case MINUTE:
-        sum.setMinutes(sum.getMinutes()+incr);
-        break;
-      case SECOND:
-        sum.setSeconds(sum.getSeconds()+incr);
-        break;
-      case MILLISECOND:
-        sum.setMilliseconds(sum.getMilliseconds()+incr);
-        break;
-      default:
-        // Do nothing
-        break;
-    }
-  }
-  return sum; // Date
-};
-
-/**
- * Get the difference in a specific unit of time (e.g., number
- * of months, weeks, days, etc.) between two dates.
- * @param date1 -- Date (or timestamp Number)
- * @param date2 -- Date (or timestamp Number)
- * @param interv -- Number, a constant representing the interval,
- *    e.g. YEAR, MONTH, DAY.  See fleegix.date.util.dateParts
- * @return Integer, number of (interv) units apart that
- *    the two dates are
- */
-fleegix.date.util.diff = function (date1, date2, interv) {
-//  date1
-//    Date object or Number equivalent
-//
-//  date2
-//    Date object or Number equivalent
-//
-//  interval
-//    A constant representing the interval, e.g. YEAR, MONTH, DAY.  See fleegix.date.util.dateParts.
-
-  // Accept timestamp input
-  if (typeof date1 == 'number') { date1 = new Date(date1); }
-  if (typeof date2 == 'number') { date2 = new Date(date2); }
-  var yeaDiff = date2.getFullYear() - date1.getFullYear();
-  var monDiff = (date2.getMonth() - date1.getMonth()) + (yeaDiff * 12);
-  var msDiff = date2.getTime() - date1.getTime(); // Millisecs
-  var secDiff = msDiff/1000;
-  var minDiff = secDiff/60;
-  var houDiff = minDiff/60;
-  var dayDiff = houDiff/24;
-  var weeDiff = dayDiff/7;
-  var delta = 0; // Integer return value
-
-  with (fleegix.date.util.dateParts) {
-    switch (interv) {
-      case YEAR:
-        delta = yeaDiff;
-        break;
-      case QUARTER:
-        var m1 = date1.getMonth();
-        var m2 = date2.getMonth();
-        // Figure out which quarter the months are in
-        var q1 = Math.floor(m1/3) + 1;
-        var q2 = Math.floor(m2/3) + 1;
-        // Add quarters for any year difference between the dates
-        q2 += (yeaDiff * 4);
-        delta = q2 - q1;
-        break;
-      case MONTH:
-        delta = monDiff;
-        break;
-      case WEEK:
-        // Truncate instead of rounding
-        // Don't use Math.floor -- value may be negative
-        delta = parseInt(weeDiff);
-        break;
-      case DAY:
-        delta = dayDiff;
-        break;
-      case WEEKDAY:
-        var days = Math.round(dayDiff);
-        var weeks = parseInt(days/7);
-        var mod = days % 7;
-
-        // Even number of weeks
-        if(mod == 0){
-          days = weeks*5;
-        }else{
-          // Weeks plus spare change (&lt; 7 days)
-          var adj = 0;
-          var aDay = date1.getDay();
-          var bDay = date2.getDay();
-
-          weeks = parseInt(days/7);
-          mod = days % 7;
-          // Mark the date advanced by the number of
-          // round weeks (may be zero)
-          var dtMark = new Date(date1);
-          dtMark.setDate(dtMark.getDate()+(weeks*7));
-          var dayMark = dtMark.getDay();
-
-          // Spare change days -- 6 or less
-          if(dayDiff &gt; 0){
-            switch(true){
-              // Range starts on Sat
-              case aDay == 6:
-                adj = -1;
-                break;
-              // Range starts on Sun
-              case aDay == 0:
-                adj = 0;
-                break;
-              // Range ends on Sat
-              case bDay == 6:
-                adj = -1;
-                break;
-              // Range ends on Sun
-              case bDay == 0:
-                adj = -2;
-                break;
-              // Range contains weekend
-              case (dayMark + mod) &gt; 5:
-                adj = -2;
-                break;
-              default:
-                // Do nothing
-                break;
-            }
-          }else if(dayDiff &lt; 0){
-            switch (true) {
-              // Range starts on Sat
-              case aDay == 6:
-                adj = 0;
-                break;
-              // Range starts on Sun
-              case aDay == 0:
-                adj = 1;
-                break;
-              // Range ends on Sat
-              case bDay == 6:
-                adj = 2;
-                break;
-              // Range ends on Sun
-              case bDay == 0:
-                adj = 1;
-                break;
-              // Range contains weekend
-              case (dayMark + mod) &lt; 0:
-                adj = 2;
-                break;
-              default:
-                // Do nothing
-                break;
-            }
-          }
-          days += adj;
-          days -= (weeks*2);
-        }
-        delta = days;
-
-        break;
-      case HOUR:
-        delta = houDiff;
-        break;
-      case MINUTE:
-        delta = minDiff;
-        break;
-      case SECOND:
-        delta = secDiff;
-        break;
-      case MILLISECOND:
-        delta = msDiff;
-        break;
-      default:
-        // Do nothing
-        break;
-    }
-  }
-  // Round for fractional values and DST leaps
-  return Math.round(delta); // Number (integer)
-};
-
-
-
-if (typeof fleegix.hash == 'undefined') { fleegix.hash = {}; }
-fleegix.hash.UNDEFINED_VALUE;
-fleegix.hash.Hash = function (d) {
-  this.count = 0;
-  this.items = {}; // Hash keys and their values
-  this.order = []; // Array for sort order
-  if (d) { this.defaultValue = d; };
-};
-fleegix.hash.Hash.prototype = new function () {
-  // Private methods
-  var getRandomKey = function () {
-    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';
-    var len = 16;
-    var str = '';
-    var mls = new Date().getTime();
-    for (var i = 0; i &lt; len; i++) {
-      // In Safari 2 Math.random returns the same random
-      // sequence after firing up the browser -- return
-      // something randomish
-      if (navigator.userAgent.indexOf('Safari/41') &gt; -1) {
-        rnum = (((mls / (i + 1)) + mls) % chars.length);
-      }
-      else {
-        var rnum = (Math.random() * chars.length);
-      }
-      rnum = Math.floor(rnum);
-      str += chars.substring(rnum, rnum + 1);
-    }
-    return str;
-  };
-  // Interface methods
-  this.addItem = function (key, val) {
-    if (typeof key != 'string') {
-      throw('Hash only allows string keys.');
-    }
-    return this.setByKey(key, val);
-  };
-  this.addItemCreateKey = function (val) {
-    var key = getRandomKey();
-    this.setByKey(key, val);
-    return key;
-  };
-  this.getItem = function (p) {
-    if (typeof p == 'string') {
-      return this.getByKey(p);
-    }
-    else if (typeof p == 'number') {
-      return this.getByIndex(p);
-    }
-  };
-  this.setItem = function (p, val) {
-    if (typeof p == 'string') {
-      this.setByKey(p, val);
-    }
-    else if (typeof p == 'number') {
-      this.setByIndex(p, val);
-    }
-  };
-  this.removeItem = function (p) {
-    if (typeof p == 'string') {
-      this.removeByKey(p);
-    }
-    else if (typeof p == 'number') {
-      this.removeByIndex(p);
-    }
-  };
-  this.getByKey = function (key) {
-    return this.items[key];
-  };
-  this.setByKey = function (key, val) {
-    var v = null;
-    if (typeof val == 'undefined') {
-      v = this.defaultValue;
-    }
-    else { v = val; }
-    if (typeof this.items[key] == 'undefined') {
-      this.order[this.count] = key;
-      this.count++;
-    }
-    this.items[key] = v;
-    return this.items[key];
-  };
-  this.removeByKey = function (key) {
-    if (typeof this.items[key] != 'undefined') {
-      var pos = null;
-      delete this.items[key]; // Remove the value
-      // Find the key in the order list
-      for (var i = 0; i &lt; this.order.length; i++) {
-        if (this.order[i] == key) {
-          pos = i;
-        }
-      }
-      this.order.splice(pos, 1); // Remove the key
-      this.count--; // Decrement the length
-    }
-  };
-  this.getByIndex = function (ind) {
-    return this.items[this.order[ind]];
-  };
-  this.setByIndex = function (ind, val) {
-    if (ind &lt; 0 || ind &gt;= this.count) {
-      throw('Index out of bounds. Hash length is ' + this.count);
-    }
-    this.items[this.order[ind]] = val;
-  };
-  this.removeByIndex = function (pos) {
-    var ret = this.items[this.order[pos]];
-    if (typeof ret != 'undefined') {
-      delete this.items[this.order[pos]]
-      this.order.splice(pos, 1);
-      this.count--;
-      return true;
-    }
-    else {
-      return false;
-    }
-  };
-  this.hasKey = function (key) {
-    return typeof this.items[key] != 'undefined';
-  };
-  this.hasValue = function (val) {
-    for (var i = 0; i &lt; this.order.length; i++) {
-      if (this.items[this.order[i]] == val) {
-        return true;
-      }
-    }
-    return false;
-  };
-  this.allKeys = function (str) {
-    return this.order.join(str);
-  };
-  this.replaceKey = function (oldKey, newKey) {
-    // If item for newKey exists, nuke it
-    if (this.hasKey(newKey)) {
-      this.removeItem(newKey);
-    }
-    this.items[newKey] = this.items[oldKey];
-    delete this.items[oldKey];
-    for (var i = 0; i &lt; this.order.length; i++) {
-      if (this.order[i] == oldKey) {
-        this.order[i] = newKey;
-      }
-    }
-  };
-  this.insertAtIndex = function (pos, key, val) {
-    this.order.splice(pos, 0, key);
-    this.items[key] = val;
-    this.count++;
-    return true;
-  };
-  this.insertAfterKey = function (refKey, key, val) {
-    var pos = this.getPos(refKey);
-    this.insertAtPos(pos, key, val);
-  };
-  this.getPosition = function (key) {
-    var order = this.order;
-    if (typeof order.indexOf == 'function') {
-      return order.indexOf(key);
-    }
-    else {
-      for (var i = 0; i &lt; order.length; i++) {
-        if (order[i] == key) { return i;}
-      }
-    }
-  }
-  this.each = function (func, o) {
-    var opts = o || {};
-    var len = this.order.length;
-    var start = opts.start ? opts.start : 0;
-    var ceiling = opts.items ? (start + opts.items) : len;
-    ceiling = (ceiling &gt; len) ? len : ceiling;
-    for (var i = start; i &lt; ceiling; i++) {
-      var key = this.order[i];
-      var val = this.items[key];
-      if (opts.keyOnly) {
-        func(key);
-      }
-      else if (opts.valueOnly) {
-        func(val);
-      }
-      else {
-        func(val, key);
-      }
-    }
-    return true;
-  };
-  this.eachKey = function (func) {
-    this.each(func, { keyOnly: true });
-  };
-  this.eachValue = function (func) {
-    this.each(func, { valueOnly: true });
-  };
-  this.clone = function () {
-    var h = new fleegix.hash.Hash();
-    for (var i = 0; i &lt; this.order.length; i++) {
-      var key = this.order[i];
-      var val = this.items[key];
-      h.setItem(key, val);
-    }
-    return h;
-  };
-  this.concat = function (hNew) {
-    for (var i = 0; i &lt; hNew.order.length; i++) {
-      var key = hNew.order[i];
-      var val = hNew.items[key];
-      this.setItem(key, val);
-    }
-  };
-  this.push = function (key, val) {
-    this.insertAtIndex(this.count, key, val);
-    return this.count;
-  };
-  this.pop = function () {
-    var pos = this.count-1;
-    var ret = this.items[this.order[pos]];
-    if (typeof ret != 'undefined') {
-      this.removeAtPos(pos);
-      return ret;
-    }
-    else {
-      return fleegix.hash.UNDEFINED_VALUE;
-    }
-  };
-  this.unshift = function (key, val) {
-    this.insertAtIndex(0, key, val);
-    return this.count;
-  };
-  this.shift = function (key, val) {
-    var pos = 0;
-    var ret = this.items[this.order[pos]];
-    if (typeof ret != 'undefined') {
-      this.removeAtPos(pos);
-      return ret;
-    }
-    else {
-      return fleegix.hash.UNDEFINED_VALUE;
-    }
-  };
-  this.splice = function (index, numToRemove, hash) {
-    var _this = this;
-    // Removal
-    if (numToRemove &gt; 0) {
-      // Items
-      var limit = index + numToRemove;
-      for (var i = index; i &lt; limit; i++) {
-        delete this.items[this.order[i]];
-      }
-      // Order
-      this.order.splice(index, numToRemove);
-    }
-    // Adding 
-    if (hash) {
-      // Items
-      for (var i in hash.items) {
-        this.items[i] = hash.items[i];
-      }
-      // Order
-      var args = hash.order;
-      args.unshift(0);
-      args.unshift(index);
-      this.order.splice.apply(this.order, args);
-    }
-    this.count = this.order.length;
-  };
-  this.sort = function (s) {
-    var c = s || fleegix.hash.sorts.ASCENDING_NOCASE;
-    var arr = [];
-    if (typeof c != 'function') {
-      throw('Hash sort requires a valid comparator function.');
-    }
-    var comp = function (a, b) {
-      return c(a.val, b.val);
-    }
-    for (var i = 0; i &lt; this.order.length; i++) {
-      var key = this.order[i];
-      arr[i] = { key: key, val: this.items[key] };
-    }
-    arr.sort(comp);
-    this.order = [];
-    for (var i = 0; i &lt; arr.length; i++) {
-      this.order.push(arr[i].key);
-    }
-  };
-  this.sortByKey = function (s) {
-    var comp = s || fleegix.hash.sorts.ASCENDING_NOCASE;
-    if (typeof compar != 'function') {
-      throw('Hash sort requires a valid comparator function.');
-    }
-    this.order.sort(comp);
-  };
-  this.reverse = function () {
-    this.order.reverse();
-  };
-};
-
-// Stock comparators for sorts
-fleegix.hash.sorts = {
-  ASCENDING_WITH_CASE: function (a, b) {
-    return (a &gt;= b) ?  1 : -1;
-  },
-  DESCENDING_WITH_CASE: function (a, b) {
-    return (a &lt; b) ?  1 : -1;
-  },
-  ASCENDING_NOCASE: function (a, b) {
-    return (a.toLowerCase() &gt;=
-      b.toLowerCase()) ? 1 : -1;
-  },
-  DESCENDING_NOCASE: function (a, b) {
-    return (a.toLowerCase() &lt;
-      b.toLowerCase()) ? 1 : -1;
-  }
-};
-
-
-
-if (typeof fleegix.ui == 'undefined') { fleegix.ui = {}; }
-fleegix.ui.GlyphRegistry = {};
-fleegix.ui.defaultUnits = 'px';
-fleegix.ui.Glyph = function (domNode, id) {
-  this.domNode = domNode || null;
-  this.id = id || domNode.id;
-  if (!this.id) { throw new Error('Glyph must have an id.'); }
-  // Positioning fu
-  this.top = 0;
-  this.left = 0;
-  this.width = 0;
-  this.height = 0;
-  // Data
-  this.data = null;
-  // Hierarchicalness
-  this.parent = null;
-  this.children = [];
-  // Flag for init-only code that has to run
-  this.hasBeenRendered = false;
-  // Visibility flag
-  this.visible = true;
-  // List of Glyphes
-  fleegix.ui.GlyphRegistry[id] = this;
-  // Place to keep data
-  this.data = null;
-};
-fleegix.ui.Glyph.prototype = new function () {
-  this.cleanup =  function () {
-    this.domNode = null;
-  };
-  this.clearNode =  function (node, useInnerHTML) {
-    if (useInnerHTML) {
-      node.innerHTML = '';
-    }
-    else {
-      while (node.hasChildNodes()) {
-        node.removeChild(node.firstChild);
-      }
-    }
-  };
-  this.clearAll =  function () {
-    if (this.domNode) {
-      this.clearNode(this.domNode);
-    }
-    var ch = this.children;
-    if (ch &amp;&amp; ch.length) {
-      for (var i = 0; i &lt; ch.length; i++) {
-        ch[i].clearAll();
-      }
-    }
-  };
-  this.setPosition =  function (left, top) {
-    this.setTop(top);
-    this.setLeft(left);
-  };
-  this.setSize =  function (width, height) {
-    this.setWidth(width);
-    this.setHeight(height);
-  };
-  this.setTop =  function (top) {
-    if (typeof top != 'undefined') {
-      this.top = top;
-    }
-    n = this.top;
-    if (fleegix.ui.defaultUnits == 'px') {
-      n = parseInt(n, 10);
-    }
-    this.domNode.style.position = 'absolute';
-    this.domNode.style.top = n + fleegix.ui.defaultUnits;
-  };
-  this.setLeft =  function (left) {
-    if (typeof left != 'undefined') {
-      this.left = left;
-    }
-    n = this.left;
-    if (fleegix.ui.defaultUnits == 'px') {
-      n = parseInt(n, 10);
-    }
-    this.domNode.style.position = 'absolute';
-    this.domNode.style.left = n + fleegix.ui.defaultUnits;
-  };
-  this.setWidth =  function (width) {
-    if (typeof width != 'undefined') {
-      this.width = width;
-    }
-    n = this.width;
-    if (typeof n == 'number') {
-      if (fleegix.ui.defaultUnits == 'px') {
-        n = parseInt(n, 10);
-      }
-      n = n.toString() + fleegix.ui.defaultUnits
-    }
-    this.domNode.style.width = n;
-  };
-  this.setHeight =  function (height) {
-    if (typeof height != 'undefined') {
-      this.height = height;
-    }
-    n = this.height;
-    if (typeof n == 'number') {
-      if (fleegix.ui.defaultUnits == 'px') {
-        n = parseInt(n, 10);
-      }
-      n = n.toString() + fleegix.ui.defaultUnits
-    }
-    this.domNode.style.height = n;
-  };
-  this.appendToDomNode = function (node) {
-    if (!this.domNode) {
-      throw new Error('Glyph &quot;' + this.id + '&quot; has no domNode.');
-    }
-    else {
-      node.appendChild(this.domNode);
-    }
-  }
-  this.hide =  function (visOnly) {
-    if (visOnly) {
-      this.domNode.style.visibility = 'hidden';
-    }
-    else {
-      this.domNode.style.display = 'none';
-    }
-    this.visible = false;
-  };
-  this.show =  function (visOnly) {
-    if (visOnly) {
-      this.domNode.style.visibility = 'visible';
-    }
-    else {
-      this.domNode.style.display = 'block';
-    }
-    this.visible = true;
-  };
-  this.renderSelf =  function () {};
-  this.update = function (p) {
-    var params = p || {};
-    for (var n in params) { this[n] = params[n]; }
-  };
-  this.render = function () {
-    // Run the init function on first render if it's defined
-    if (!this.hasBeenRendered &amp;&amp; typeof this.init == 'function') {
-      this.init();
-    }
-    if (typeof this.renderSelf == 'function') {
-      this.renderSelf();
-    };
-    var children = this.children;
-    var child;
-    for (var i = 0; i &lt; children.length; i++) {
-      child = children[i];
-      child.render();
-    }
-    this.hasBeenRendered = true;
-  };
-  this.addChild = function (c) {
-    this.children.push(c);
-    c.parent = this;
-    this[c.id] = c;
-    this.domNode.appendChild(c.domNode);
-  };
-  this.center = function () {
-    if (!fleegix.dom) {
-      throw new Error('This method depends on the fleegix.dom module in fleegix.js base.');
-    }
-    else {
-      this.domNode.style.position = 'absolute';
-      fleegix.dom.center(this.domNode);
-    }
-  };
-};
-
-
-
-
-fleegix.i18n = new function () {
-  var _this = this;
-  this.localizedStrings = {};
-  this.getText = function () {
-    var args = Array.prototype.slice.apply(arguments);
-    var key = args.shift();
-    var str = _this.localizedStrings[key] || &quot;[[&quot; + key + &quot;]]&quot;;
-    for (var i = 0; i &lt; args.length; i++){
-        str = str.replace(new RegExp('\\{' + i + '\\}', 'g'), args[i]);
-    }
-    return str;
-  };
-  this.setLocalizedStrings = function (obj) {
-    this.localizedStrings = obj || {};
-  };
-};
-
-
-fleegix.html = new function () {
-  var _createElem = function (s) {
-    return document.createElement(s); };
-  var _createText = function (s) {
-    return document.createTextNode(s); };
-  this.createSelect = function (o) {
-    var sel = document.createElement('select');
-    var options = [];
-    var appendElem = null;
-
-    // createSelect({ name: 'foo', id: 'foo', multi: true,
-    //  options: [{ text: 'Howdy', value: '123' },
-    //  { text: 'Hey', value: 'ABC' }], className: 'fooFoo' });
-    appendElem = arguments[1];
-    options = o.options;
-    for (var p in o) {
-      if (p != 'options') {
-        sel[p] = o[p];
-      }
-    }
-    // Add the options for the select
-    if (options) {
-      this.setSelectOptions(sel, options);
-    }
-    return sel;
-  };
-
-  this.setSelectOptions = function (selectElement, options){
-    while (selectElement.firstChild){
-       selectElement.removeChild(selectElement.firstChild);
-    }
-    for (var i = 0; i &lt; options.length; i++) {
-      var opt = _createElem('option');
-      opt.value = options[i].value || '';
-      opt.appendChild(_createText(options[i].text));
-      selectElement.appendChild(opt);
-      if (options[i].selected){
-        selectElement.selectedIndex = i;
-      }
-    }
-  };
-
-  this.setSelect = function (sel, val) {
-    var index = 0;
-    var opts = sel.options;
-    for (var i = 0; i &lt; opts.length; i++) {
-      if (opts[i].value == val) {
-        index = i;
-        break;
-      }
-    }
-    sel.selectedIndex = index;
-  };
-
-  this.createInput = function (o) {
-    var input = null;
-    var str = '';
-
-    // createInput({ type: 'password', name: 'foo', id: 'foo',
-    //    value: 'asdf', className: 'fooFoo' });
-    // Neither IE nor Safari 2 can handle DOM-generated radio
-    // or checkbox inputs -- they stupidly assume name and id
-    // attributes should be identical. The solution: kick it
-    // old-skool with conditional branching and innerHTML
-    if ((document.all || navigator.userAgent.indexOf('Safari/41') &gt; -1) &amp;&amp;
-      (o.type == 'radio' || o.type == 'checkbox')) {
-      str = '&lt;input type=&quot;' + o.type + '&quot;' +
-        ' name=&quot;' + o.name + '&quot;' +
-        ' id =&quot;' + o.id + '&quot;';
-      if (o.value) {
-        str += ' value=&quot;' + o.value + '&quot;';
-      }
-      if (o.size) {
-        str += ' size=&quot;' + o.size + '&quot;';
-      }
-      if (o.maxlength) {
-        str += ' maxlength=&quot;' + o.maxlength + '&quot;';
-      }
-      if (o.checked) {
-        str += ' checked=&quot;checked&quot;';
-      }
-      if (o.className) {
-        str += ' class=&quot;' + o.className + '&quot;';
-      }
-      str += '/&gt;';
-
-      var s = _createElem('span');
-      s.innerHTML = str;
-      input = s.firstChild;
-      s.removeChild(input);
-    }
-    // Standards-compliant browsers -- all form inputs
-    // IE/Safari 2 -- everything but radio button and checkbox
-    else {
-      input = document.createElement('input');
-      for (var p in o) {
-        input[p] = o[p];
-      }
-
-    }
-    return input;
-  };
-
-};
-
-if (typeof fleegix.drag == 'undefined') { fleegix.drag = {}; }
-fleegix.drag.xPos = null;
-fleegix.drag.yPos = null;
-// Manager singleton
-fleegix.drag.DragManager = new function () {
-  var _this = this;
-  this.registry = [];
-  this.raiseMap = {};
-  this.dragMap = {};
-  this.currentDraggable = null;
-  this.currentZIndex = 99999;
-  this.addDragWindow = function (containerNode, handleNode, shadowNode) {
-    if (!containerNode.id) {
-      throw('Draggable DOM nodes must have an id'); }
-    if (!handleNode) { handleNode = containerNode; }
-    var setupDrag =
-      function (e) { _this.setUpDrag.apply(_this, [e]); };
-    fleegix.event.listen(handleNode, 'onmousedown', setupDrag);
-    var raiseDraggable =
-      function (e) { _this.raiseDraggable.apply(_this, [e]); };
-    fleegix.event.listen(containerNode,
-      'onmousedown', raiseDraggable);
-    var d = new fleegix.drag.DragWindow({
-      containerNode: containerNode, shadowNode: shadowNode });
-    this.registry.push(d);
-    this.raiseMap[containerNode.id] = d;
-    this.dragMap[handleNode.id] = d;
-    this.raiseDraggable(containerNode.id);
-  };
-  this.setUpDrag = function (e) {
-    var elem = e.target;
-    var d = this.dragMap[elem.id];
-    // Look up the DOM hierarchy until we find
-    //something in the map of raiseable nodes
-    while (!d &amp;&amp; elem != document.body) {
-      if (elem.parentNode) {
-        elem = elem.parentNode;
-        d = this.dragMap[elem.id];
-      }
-    }
-    if (d) {
-      this.currentDraggable = d;
-      this.currentDraggable.startDrag();
-    }
-  };
-  this.raiseDraggable = function (p) {
-    var key = '';
-    if (typeof p == 'string') {
-      var d = this.raiseMap[p];
-    }
-    else {
-      var elem = p.target;
-      var d = this.raiseMap[elem.id];
-      // Look up the DOM hierarchy until we find
-      //something in the map of raiseable nodes
-      while (!d &amp;&amp; elem != document.body) {
-        if (elem.parentNode) {
-          elem = elem.parentNode;
-          d = this.raiseMap[elem.id];
-        }
-      }
-    }
-    this.currentZIndex++;
-    d.containerNode.style.zIndex = this.currentZIndex;
-    if (d.shadowNode) {
-      d.shadowNode.style.zIndex = this.currentZIndex - 1; 
-    }
-  };
-  this.mouseMoveHandler = function (e) {
-    var d = fleegix.drag;
-    d.xPos = e.clientX;
-    d.yPos = e.clientY;
-    if (_this.currentDraggable) {
-      _this.currentDraggable.drag();
-    }
-  };
-  this.mouseUpHandler = function (e) {
-    if (_this.currentDraggable) {
-      _this.currentDraggable.drop();
-      _this.currentDraggable = null;
-    }
-  };
-};
-// Draggable DragWindow pseudoclass
-fleegix.drag.DragWindow = function (p) {
-  var params = p || {};
-  this.containerNode = null;
-  this.shadowNode = null;
-  this.handleNode = null;
-  this.clickOffsetX = 0;
-  this.clickOffsetY = 0;
-  for (var n in params) { this[n] = params[n] }
-};
-fleegix.drag.DragWindow.prototype.startDrag = function () {
-  var d = fleegix.drag;
-  this.clickOffsetX = d.xPos -
-    parseInt(this.containerNode.style.left);
-  this.clickOffsetY = d.yPos -
-    parseInt(this.containerNode.style.top);
-  // Turn off text selection in IE while dragging
-  document.onselectstart = function () { return false; };
-};
-fleegix.drag.DragWindow.prototype.drag = function () {
-  var d = fleegix.drag;
-  var x = (d.xPos - this.clickOffsetX) + 'px';
-  var y = (d.yPos - this.clickOffsetY) + 'px';
-  this.containerNode.style.left = x;
-  this.containerNode.style.top = y;
-  if (this.shadowNode) {
-    this.shadowNode.style.left = x;
-    this.shadowNode.style.top = y;
-  }
-  // Hacky way of preventing text selection in FF
-  // for the entire doc -- inserting a CSS rule for
-  // -moz-user-select for all elements or something
-  // seems like a lot of work
-  document.body.focus();
-};
-fleegix.drag.DragWindow.prototype.drop = function () {
-  // Re-enable text selection in IE
-  document.onselectstart = null;
-};
-// Event listeners for dragging, raising DragWindow, dropping
-fleegix.event.listen(document, 'onmousemove',
-  fleegix.drag.DragManager, 'mouseMoveHandler');
-fleegix.event.listen(document, 'onmouseup',
-  fleegix.drag.DragManager, 'mouseUpHandler');
-
-/*
- * Copyright 2009 Matthew Eernisse (mde@fleegix.org)
- *
- * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
-*/
-if (typeof fleegix == 'undefined') { throw('Requires fleegix base namespace.'); }
-if (typeof fleegix.xhr == 'undefined') { throw('Requires fleegix.xhr namespace.'); }
-if (typeof fleegix.template == 'undefined') { fleegix.template = {}; }
-// single params Object can have the following properties:
-// markup -- String, a string of markup with vars to interpolate
-//    if this exists, markupFile will be ignored
-// markupFile -- String, a path to a file containing string data
-//    then used to set the markup prop
-// data -- Object, keyword/vals to use for the variable substitution
-// requireAllKeys -- Boolean, if set to true, any variables in the
-//    template file that don't have corresponding keys in the
-//    data object will still show in the template as
-//    ${ variable_name }. If set to false, those variables in
-//    the template are replaced with empty strings
-// preventCache -- Boolean, setting to true will always pull
-//    down a fresh copy of the template -- otherwise the template
-//    string gets stored in fleegix.template.templateTextCache so that
-//    different UI elements sharing the same template file won't
-//    all have to make the server round-trip to get their template
-//    string.
-fleegix.template.Templater = function (p) {
-  var params = p || {};
-  var opts = params.options || {};
-  this.markup = params.markup || '';
-  this.markupFile = '';
-  this.data = params.data || {};
-  this.requireAllKeys = typeof params.requireAllKeys == 'boolean' ?
-    params.requireAllKeys : true;
-  if (!this.markup) {
-    var _this = this;
-    var noCache = typeof this.preventCache == 'undefined' ?
-      false : this.preventCache;
-    this.markupFile = params.markupFile;
-    var s = fleegix.template.templateTextCache[this.markupFile];
-    if (!s || noCache) {
-      var p = {
-        url: this.markupFile,
-        method: 'GET',
-        preventCache: noCache,
-        async: false
-      };
-      s = fleegix.xhr.doReq(p);
-      fleegix.template.templateTextCache[this.markupFile] = s;
-    }
-    this.markup = s;
-  }
-};
-fleegix.template.Templater.prototype.templatize =
-  function (domNode) {
-  var str = this.getTemplatedMarkup();
-  domNode.innerHTML = str;
-  return domNode;
-};
-fleegix.template.Templater.prototype.getTemplatedMarkup =
-  function () {
-  var pat = /\$\{ *(.*?) *\}/g;
-  var subPat = /[${} ]/g;
-  var str = this.markup;
-  var match = str.match(pat);
-  if (match) {
-    for (var i = 0; i &lt; match.length; i++) {
-      m = match[i];
-      key = m.replace(subPat, '');
-      var data = this.data[key] ? this.data[key] : '';
-      if (data || !this.requireAllKeys) {
-        str = str.replace(m, data);
-      }
-    }
-  }
-  return str;
-};
-fleegix.template.templateTextCache = {};
-
-
-
-/*
- * Copyright 2009 Matthew Eernisse (mde@fleegix.org)
- *
- * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
-*/
-if (typeof fleegix == 'undefined') { fleegix = {}; }
-
-fleegix.ejs = {};
-
-fleegix.ejs.templateTextCache = {};
-
-fleegix.ejs.Template = function (p) {
-  var UNDEF;
-  var params = p || {};
-
-  this.mode = null;
-  this.templateText = params.text ||
-    // If you don't want to use Fleegix.js,
-    // override getTemplateTextFromNode to use
-    // textarea node value for template text
-    this.getTemplateTextFromNode(params.node);
-  this.afterLoaded = params.afterLoaded;
-  this.source = '';
-  this.markup = UNDEF;
-  // Try to get from URL
-  if (typeof this.templateText == 'undefined') {
-    // If you don't want to use Fleegix.js,
-    // override getTemplateTextFromUrl to use
-    // files for template text
-    this.getTemplateTextFromUrl(params);
-  }
-};
-
-fleegix.ejs.Template.prototype = new function () {
-  var _REGEX = /(&lt;%%)|(%%&gt;)|(&lt;%=)|(&lt;%#)|(&lt;%)|(%&gt;\n)|(%&gt;)|(\n)/;
-  this.modes = {
-    EVAL: 'eval',
-    OUTPUT: 'output',
-    APPEND: 'append',
-    COMMENT: 'comment',
-    LITERAL: 'literal'
-  };
-  this.getTemplateTextFromNode = function (node) {
-    // Requires the fleegix.xhr module
-    if (typeof fleegix.string == 'undefined') {
-      throw('Requires fleegix.string module.'); }
-    var ret;
-    if (node) {
-      ret = node.value;
-      ret = fleegix.string.unescapeXML(ret);
-      ret = fleegix.string.trim(ret);
-    }
-    return ret;
-  };
-  this.getTemplateTextFromUrl = function (params) {
-    // Requires the fleegix.xhr module
-    if (typeof fleegix.xhr == 'undefined') {
-      throw('Requires fleegix.xhr module.'); }
-    var _this = this;
-    var url = params.url;
-    var noCache = params.preventCache || false;
-    var text = fleegix.ejs.templateTextCache[url];
-    // Found text in cache, and caching is turned on
-    if (text &amp;&amp; !noCache) {
-      this.templateText = text;
-    }
-    // Otherwise go grab the text
-    else {
-      // Callback for setting templateText and caching --
-      // used for both sync and async loading
-      var callback = function (s) {
-        _this.templateText = s;
-        fleegix.ejs.templateTextCache[url] = s;
-        // Use afterLoaded hook if set
-        if (typeof _this.afterLoaded == 'function') {
-          _this.afterLoaded();
-        }
-      };
-      var opts;
-      if (params.async) {
-        opts = {
-          url: url,
-          method: 'GET',
-          preventCache: noCache,
-          async: true,
-          handleSuccess: callback
-        };
-        // Get templ text asynchronously, wait for
-        // loading to exec the callback
-        fleegix.xhr.send(opts);
-      }
-      else {
-        opts = {
-          url: url,
-          method: 'GET',
-          preventCache: noCache,
-          async: false
-        };
-        // Get the templ text inline and pass directly to
-        // the callback
-        text = fleegix.xhr.send(opts);
-        callback(text);
-      }
-    }
-  };
-  this.process = function (p) {
-    var params = p || {};
-    this.data = params.data || {};
-    var domNode = params.node;
-    // Cache/reuse the generated template source for speed
-    this.source = this.source || '';
-    if (!this.source) { this.generateSource(); }
-    
-    // Eval the template with the passed data
-    // Use 'with' to give local scoping to data obj props
-    // ========================
-    var _output = ''; // Inner scope var for eval output
-    with (this.data) {
-      eval(this.source); 
-    }
-    this.markup = _output;
-
-    if (domNode) {
-      domNode.innerHTML = this.markup;
-    }
-    return this.markup;
-  };
-  this.generateSource = function () {
-    var line = '';
-    var matches = this.parseTemplateText();
-    if (matches) {
-      for (var i = 0; i &lt; matches.length; i++) {
-        line = matches[i];
-        if (line) {
-          this.scanLine(line);
-        }
-      }
-    }
-  };
-  this.parseTemplateText = function() {
-    var str = this.templateText;
-    var pat = _REGEX;
-    var result = pat.exec(str);
-    var arr = [];
-    while (result) {
-      var firstPos = result.index;
-      var lastPos = pat.lastIndex;
-      if (firstPos !== 0) {
-        arr.push(str.substring(0, firstPos));
-        str = str.slice(firstPos);
-      }
-      arr.push(result[0]);
-      str = str.slice(result[0].length);
-      result = pat.exec(str);
-    }
-    if (str !== '') {
-      arr.push(str);
-    }
-    return arr;
-  };
-  this.scanLine = function (line) {
-    var _this = this;
-    var _addOutput = function () {
-      line = line.replace(/\n/, '\\n');
-      line = line.replace(/&quot;/g, '\\&quot;');
-      _this.source += '_output += &quot;' + line + '&quot;;';
-    };
-    switch (line) {
-      case '&lt;%':
-        this.mode = this.modes.EVAL;
-        break;
-      case '&lt;%=':
-        this.mode = this.modes.OUTPUT;
-        break;
-      case '&lt;%#':
-        this.mode = this.modes.COMMENT;
-        break;
-      case '&lt;%%':
-        this.mode = this.modes.LITERAL;
-        this.source += '_output += &quot;' + line + '&quot;;';
-        break;
-      case '%&gt;':
-      case '%&gt;\n':
-        if (this.mode == this.modes.LITERAL) {
-          _addOutput();
-        }
-        this.mode = null;
-        break;
-      default:
-        // In script mode, depends on type of tag
-        if (this.mode) {
-          switch (this.mode) {
-            // Just executing code
-            case this.modes.EVAL:
-              this.source += line;
-              break;
-            // Exec and output
-            case this.modes.OUTPUT:
-              // Add the exec'd result to the output
-              this.source += '_output += ' + line + ';';
-              break;
-            case this.modes.COMMENT:
-              // Do nothing
-              break;
-            // Literal &lt;%% mode, append as raw output
-            case this.modes.LITERAL:
-              _addOutput();
-              break;
-          }
-        }
-        // In string mode, just add the output
-        else {
-          _addOutput();
-        }
-    }
-  };
-};
-
-
-
-if (typeof fleegix.form == 'undefined') { fleegix.form = {}; }
-if (typeof fleegix.form.toObject == 'undefined') {
-  throw('fleegix.form.diff depends on the base fleegix.form module in fleegix.js.'); }
-
-fleegix.form.diff = function (formUpdated, formOrig, opts) {
-  var o = opts || {};
-  // Accept either form or hash-conversion of form
-  var hUpdated = formUpdated.elements ?
-    fleegix.form.toObject(formUpdated) : formUpdated;
-  var hOrig = formOrig.elements ?
-    fleegix.form.toObject(formOrig) : formOrig;
-  var diffs = [];
-  var count = 0;
-
-  function addDiff(n, hA, hB, secondPass) {
-    if (!diffs[n]) {
-      count++;
-      diffs[n] = secondPass?
-        { origVal: hB[n], newVal: hA[n] } :
-        { origVal: hA[n], newVal: hB[n] };
-    }
-  }
-
-  function diffSweep(hA, hB, secondPass) {
-    for (n in hA) {
-      // Elem doesn't exist in B
-      if (typeof hB[n] == 'undefined') {
-        // If intersectionOnly flag set, ignore stuff that's
-        // not in both sets
-        if (o.intersectionOnly) { continue; };
-        // Otherwise we want the union, note the diff
-        addDiff(n, hA, hB, secondPass);
-      }
-      // Elem exists in both
-      else {
-        v = hA[n];
-        // Multi-value -- array, hA[n] actually has values
-        if (v instanceof Array) {
-          if (!hB[n] || (hB[n].toString() != v.toString())) {
-            addDiff(n, hA, hB, secondPass);
-          }
-        }
-        // Single value -- null or string
-        else {
-          if (hB[n] != v) {
-            addDiff(n, hA, hB, secondPass);
-          }
-        }
-      }
-    }
-  }
-  // First sweep check all items in updated
-  diffSweep(hUpdated, hOrig, false);
-  // Second sweep, check all items in orig
-  diffSweep(hOrig, hUpdated, true);
-
-  // Return an obj with the count and the hash of diffs
-  return {
-    count: count,
-    diffs: diffs
-  };
-};
-
-
-
-fleegix.xml = new function () {
-  var pat = /^[\s\n\r\t]+|[\s\n\r\t]+$/g;
-  var expandToArr = function (orig, val) {
-    if (orig) {
-      var r = null;
-      if (orig instanceof Array == false) {
-        r = [];
-        r.push(orig);
-      }
-      else { r = orig; }
-      r.push(val);
-      return r;
-    }
-    else { return val; }
-  };
-  // Parses an XML doc or doc fragment into a JS obj
-  // Values for multiple same-named tags a placed in
-  // an array -- ideas for improvement to hierarchical
-  // parsing from Kevin Faulhaber (kjf@kjfx.net)
-  this.parse = function (node, tagName) {
-    var obj = {};
-    var kids = [];
-    var k;
-    var key;
-    var t;
-    var val;
-    if (tagName) {
-      kids = node.getElementsByTagName(tagName);
-    }
-    else {
-      kids = node.childNodes;
-    }
-    for (var i = 0; i &lt; kids.length; i++) {
-      k = kids[i];
-      // Element nodes (blow by the stupid Mozilla linebreak nodes)
-      if (k.nodeType == 1) {
-        key = k.tagName;
-        // Tags with content
-        if (k.firstChild) {
-          // Node has only one child
-          if(k.childNodes.length == 1) {
-            t =  k.firstChild.nodeType;
-            // Leaf nodes - text, CDATA, comment
-            if (t == 3 || t == 4 || t == 8) {
-              // Either set plain value, or if this is a same-named
-              // tag, start stuffing values into an array
-              val = k.firstChild.nodeValue.replace(pat, '');
-              obj[key] = expandToArr(obj[key], val);
-            }
-            // Node has a single child branch node, recurse
-            else if (t == 1) {
-              // Rinse and repeat
-              obj[key] = expandToArr(obj[key], this.parse(k.firstChild));
-            }
-          }
-          // Node has children branch nodes, recurse
-          else {
-            // Rinse and repeat
-            obj[key] = expandToArr(obj[key], this.parse(k));
-          }
-        }
-        // Empty tags -- create an empty entry
-        else {
-          obj[key] = expandToArr(obj[key], null);
-        }
-      }
-    }
-    return obj;
-  };
-  // Create an XML document from string
-  this.createDoc = function (str) {
-    // Mozilla
-    if (typeof DOMParser != &quot;undefined&quot;) {
-      return (new DOMParser()).parseFromString(str, &quot;application/xml&quot;);
-    }
-    // Internet Explorer
-    else if (typeof ActiveXObject != &quot;undefined&quot;) {
-      var doc = XML.newDocument( );
-      doc.loadXML(str);
-      return doc;
-    }
-    else {
-      // Try loading the document from a data: URL
-      // Credits: Sarissa library (sarissa.sourceforge.net)
-      var url = &quot;data:text/xml;charset=utf-8,&quot; + encodeURIComponent(str);
-      var request = new XMLHttpRequest();
-      request.open(&quot;GET&quot;, url, false);
-      request.send(null);
-      return request.responseXML;
-    }
-  };
-  // Returns a single, top-level XML document node
-  // Ideal for grabbing embedded XML data from a page
-  // (i.e., XML 'data islands')
-  this.getXMLDoc = function (id, tagName) {
-    var arr = [];
-    var doc = null;
-    if (document.all) {
-      var str = document.getElementById(id).innerHTML;
-      doc = new ActiveXObject(&quot;Microsoft.XMLDOM&quot;);
-      doc.loadXML(str);
-      doc = doc.documentElement;
-    }
-    // Moz/compat can access elements directly
-    else {
-      arr =
-        window.document.body.getElementsByTagName(tagName);
-      doc = arr[0];
-    }
-    return doc;
-  };
-};
-
-
-if (typeof fleegix.event == 'undefined') {
-  throw('fleegix.event.delegator depends on the base fleegix.event module in fleegix.js.'); }
-
-fleegix.event.Delegator = function (containerNode, actions,
-  options) {
-  var _this = this;
-  this.containerNode = containerNode;
-  // List of CSS class names and their corresponding
-  // click-actions
-  this.actions = actions || {};
-  // Optional execution context for called actions
-  var opts = options || {};
-  this.context = opts.context || null;
-  // Assume we want to stop any further action
-  this.stopPropagation =
-    typeof opts.stopPropagation != 'undefined' ?
-    opts.stopPropagation : true;
-  this.preventDefault =
-    typeof opts.preventDefault != 'undefined' ?
-    opts.preventDefault : true;
-
-  // Add another action
-  this.addClickAction = function (className, act) {
-    this.actions[className] = act;
-  };
-  this.getClickAction = function (e) {
-    var actions = this.actions;
-    var containerNode = this.containerNode;
-    var node = e.target;
-    var topNode = containerNode || document.body;
-    // Look upward from the click target to the
-    // a predefined parent -- if any of the parentNodes
-    // have an action class attached, return the
-    // class and bail out
-    while (node.parentNode &amp;&amp; node != topNode) {
-      if (node.className) {
-        for (var c in actions) {
-          // Look through class name(s) set on the node
-          var names = node.className.split(' ');
-          for (var i = 0; i &lt; names.length; i++) {
-            if (names[i] == c) {
-              return c;
-            }
-          }
-        }
-      }
-      node = node.parentNode;
-    }
-    return null;
-  };
-  this.handleClick = function (e) {
-    var context = this.context;
-    var key = _this.getClickAction(e);
-    // If there's a CSS class in the click chain with
-    // a matching action, exec the action
-    if (key) {
-      var act = this.actions[key];
-      if (context) {
-        act.call(context, e);
-      }
-      else {
-        act(e);
-      }
-      if (this.stopPropagation) {
-        fleegix.event.stopPropagation(e);
-      }
-      if (this.preventDefault) {
-        fleegix.event.preventDefault(e);
-      }
-    }
-  };
-  fleegix.event.listen(containerNode, 'onclick',
-    this, 'handleClick');
-};
-
-
-if (typeof fleegix.event == 'undefined') {
-  throw('fleegix.event.delegator depends on the base fleegix.event module in fleegix.js.'); }
-
-fleegix.event.Periodic = function () {
-  var _this = this;
-  var _paused = false;
-
-  var args = Array.prototype.slice.apply(arguments);
-  var context;
-  var methodName;
-  if (typeof args[0] != 'function') {
-    context = args.shift();
-    methodName = args.shift();
-  }
-  else {
-    var func = args.shift();
-  }
-  var interval = args.shift();
-  var waitFirst = args.shift();
-
-  this.context = context || null;
-  this.methodName = methodName || null;
-  this.func = func || null;
-  this.interval = interval || null;
-  this.waitFirst = waitFirst || false;
-  this.start = function (waitFirst) {
-    this.waitFirst = waitFirst || this.waitFirst;
-    if (this.waitFirst) {
-      setTimeout(this.run, this.interval);
-    }
-    else {
-      this.run();
-    }
-  };
-  this.run = function () {
-    if (!_paused) {
-      if (_this.context) {
-        _this.context[_this.methodName].call(_this.context);
-      }
-      else {
-        _this.func();
-      }
-      setTimeout(_this.run, _this.interval);
-    }
-  };
-  this.pause = function () {
-    _paused = true;
-  };
-  this.resume = function () {
-    _paused = false;
-    this.run();
-  };
-};
-
-// Clean up listeners
-fleegix.event.listen(window, 'onunload', function () {
-  try {
-    fleegix.event.flush();
-  }
-  catch (e) {} // Squelch
-});
-
-/*
- * Copyright 2009 Matthew Eernisse (mde@fleegix.org)
- *
- * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-if (typeof fleegix == 'undefined') {
-  throw new Error('fleegix.history depends on fleegix base module.');
-}
-fleegix.history = new function () {
-  var _this = this;
-  // Private vars
-  var _historyCheck;
-  var _ieHistory = 0;
-
-  // Public vars
-  this.index = 0;
-  this.currentStep = 0;
-  this.entries = [];
-  this.entriesMap = {};
-  this.ieKeyArray = [];
-  this.bookmarkable = true;
-  this.domain = null;
-
-  // Private methods
-  var _getHistoryDoc = function () {
-    var doc;
-    if (fleegix.ua.isIE) {
-      doc = document.getElementById(
-        &quot;historyFrame&quot;).contentWindow.document;
-    }
-    else {
-      // Show the hash in the main document
-      if (_this.bookmarkable) {
-        doc = document;
-      }
-      // Hide the hash in the iframe
-      else {
-        doc = document.getElementById(
-          &quot;historyFrame&quot;).contentDocument;
-      }
-    }
-    return doc;
-  };
-  var _getHistoryStep = function () {
-    var ret;
-    if (fleegix.ua.isIE) {
-      ret = _ieHistory;
-    }
-    else {
-      ret = _getHistoryDoc().location.hash.replace('#', '');
-      ret = _this.entriesMap[ret];
-    }
-    if (!isNaN(ret)) {
-      ret = parseInt(ret, 10);
-    }
-    else {
-      ret = 0;
-    }
-    return ret;
-  };
-  var _doHistoryCheck = function () {
-    var step = _getHistoryStep();
-    var entry;
-    if (step != fleegix.history.currentStep) {
-      fleegix.history.currentStep = _getHistoryStep();
-      entry = _this.getEntry(fleegix.history.currentStep);
-      fleegix.history.onchange(entry);
-    }
-    _historyCheck = null;
-    _historyCheck = window.setTimeout(_doHistoryCheck, 200);
-  };
-
-  // Public methods
-  this.init = function (entry) {
-    var form = $('historyForm');
-    var entries = form.historyEntries.value;
-    if (entries.length) {
-      var deserial = fleegix.json.parse(entries);
-      for (var p in deserial) {
-        this[p] = deserial[p];
-      }
-    }
-    else {
-      this.addEntry(entry);
-    }
-    if (!document.getElementById(&quot;historyFrame&quot;)) {
-      throw new Error(
-        'This history code requires an iframe with the id of ' +
-        '&quot;historyFrame&quot; to exist in the initial page load.');
-    }
-    // Set-up the polling:
-    _historyCheck = window.setTimeout(_doHistoryCheck, 200);
-    fleegix.event.listen(window, 'onbeforeunload', fleegix.history,
-      'finish');
-  };
-
-  this.addEntry = function () {
-    var key;
-    var entry;
-    if (arguments.length == 1) {
-      entry = arguments[0];
-    }
-    else {
-      key = arguments[0];
-      entry = arguments[1];
-    }
-    var curr = this.currentStep;
-    var start = curr + 1;
-    var removeCount = this.entries.length - curr;
-    this.entries.splice(start, removeCount);
-    this.entries.push(entry);
-    this.index = this.entries.length - 1;
-    key = key || this.index;
-    return this.incrementHistory(key);
-  };
-  this.getEntry = function (i) {
-    return this.entries[i];
-  };
-  this.incrementHistory = function (key) {
-    var doc = _getHistoryDoc();
-    this.currentStep = this.index;
-    this.entriesMap[key] = this.index;
-    // Use the document.write hack to avoid needless
-    // round-trip in IE
-    if (fleegix.ua.isIE) {
-      var docDomain = this.domain ?
-          'document.domain=&quot;' + this.domain + '&quot;;' : '';
-      _this.ieKeyArray[this.index] = key;
-      doc.open(&quot;javascript:'&lt;html&gt;&lt;/html&gt;'&quot;);
-      doc.write('&lt;html&gt;&lt;head&gt;&lt;scri' +
-        'pt type=&quot;text/javascript&quot;&gt;' + docDomain +
-        'parent.fleegix.history.' +
-        'onIncremented(' + this.index + ');&lt;/scri' +
-        'pt&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;');
-      doc.close();
-    }
-    // Safari doesn't update the history for changes
-    // to iframe hashes -- doing a fake form post
-    // to the hash gets around this. No round-trip
-    // seems to occur here
-    else if (fleegix.ua.isSafari &amp;&amp; !this.bookmarkable) {
-      doc.body.innerHTML = '&lt;form name=&quot;x&quot; action=&quot;#' +
-        this.index + '&quot; method=&quot;GET&quot;&gt;&lt;/form&gt;';
-      doc.forms[0].submit();
-    }
-    else {
-      if (key != 0) {
-        doc.location.hash = '#' + key;
-      }
-    }
-    this.index++;
-    _this.serializeHistory();
-    return true;
-  };
-  this.onIncremented = function (i) {
-    _ieHistory = i;
-    if (_this.bookmarkable) {
-      if (i == 0) {
-        location.hash = '';
-      }
-      else {
-        location.hash = '#' + _this.ieKeyArray[i];
-      }
-    }
-  };
-  this.serializeHistory = function () {
-    if (_this.entries.length &gt; 0) {
-      var form = $('historyForm');
-      var serial = {
-        entries: _this.entries,
-        entriesMap: _this.entriesMap,
-        ieKeyArray: _this.ieKeyArray
-      };
-      serial = fleegix.json.serialize(serial);
-      form.historyEntries.value = serial;
-    }
-  };
-  this.finish = function () {
-    _this.serializeHistory();
-    if (_historyCheck) {
-      window.clearTimeout(_historyCheck);
-    }
-  };
-  this.onchange = function () {};
-};
-
-
-if (typeof fleegix.string == 'undefined') { fleegix.string = {}; }
-fleegix.string.hotlink = new function () {
-  var _this = this;
-  var _hrefPat = /(https?:\/\/|www.)([-\w]+(?:\.[-\w]+)*(:\d+)?(\/(([~\w\+%-]|([,.;@:][^\s$]))+)?)*((\?|;)[\w\+%&amp;=.;:-]+)?(\#[\w\-\.]*)?)/g;
-  var _emailPat = /[\w\.\+-=]+@[\w\.-]+\.[\w]{2,3}/g;
-  this.url = function (str) {
-    var t = str || '';
-    ret = t.replace(_hrefPat, function (s) {
-      // Prepend http:// for www-only URLs
-      var href = s.indexOf('www') === 0 ? 'http://' + s : s;
-      return '&lt;a href=&quot;' + href + '&quot;&gt;' + s + '&lt;/a&gt;';
-    });
-    return ret;
-  };
-  this.email = function (str) {
-    var t = str || '';
-    ret = t.replace(_emailPat, function (s) {
-      return '&lt;a href=&quot;mailto:' + s + '&quot;&gt;' + s + '&lt;/a&gt;';
-    });
-    return ret;
-  };
-  this.all = function (str) {
-    var t = str || '';
-    t = _this.url(t);
-    t = _this.email(t);
-    return t;
-  };
-};
-
-
-
-if (typeof fleegix.string == 'undefined') { fleegix.string = {}; }
-
-fleegix.string.truncate = function (str, len, tail) {
-  var t = tail || '';
-  if (str.length &gt; len) {
-    return str.substr(0, (len - t.length)) + t;
-  }
-  else {
-    return str;
-  }
-};
-
-fleegix.string.truncateHTML = function (str, len, tail) {
-  // The returned string of content
-  var s = '';
-  // Any tail to append after truncation -- e.g. ellipses
-  var t = tail || '';
-  // Split pattern for HTML tags
-  var pat = /(&lt;[^&gt;]*&gt;)/;
-  // Opening HTML tag -- used as a flag that there's an
-  // HTML tag sitting open when truncation happens
-  var openTag = null;
-  // Used to close any open tag
-  var closeTag = '';
-  // An array of merged content and tags, e.g., ['foo',
-  // '&lt;strong&gt;', 'bar', '&lt;/strong&gt;']
-  var arr = [];
-  // Current length of the string to return
-  var currLen = 0;
-  // Lookahead to see if we'll overshoot the max length
-  var nextLen = 0;
-  // Truncated final segment of the string
-  var trunc;
-  // Each item in the merged tag/content array
-  var item;
-
-  // Build the merged array of tags/content
-  var result = pat.exec(str);
-  while (result) {
-    var firstPos = result.index;
-    var lastPos = pat.lastIndex;
-    if (firstPos !== 0) {
-      arr.push(str.substring(0, firstPos));
-      str = str.slice(firstPos);
-    }
-    arr.push(result[0]);
-    str = str.slice(result[0].length);
-    result = pat.exec(str);
-  }
-  if (str !== '') {
-    arr.push(str);
-  }
-
-  // Parse each item in the tag/content array
-  // Have to parse in all cases -- no simple test to see
-  // if you can just return the entire string
-  // Global regex replace would work, but who knows
-  // how much if any faster that is
-  for (var i = 0; i &lt; arr.length; i++) {
-    item = arr[i];
-    switch (true) {
-      // Closing tag
-      case item.indexOf('&lt;/') == 0:
-        s += item;
-        openTag = null;
-        break;
-      // Opening tag
-      case item.indexOf('&lt;') == 0:
-        s += item;
-        openTag = item;
-        break;
-      // Text
-      default:
-        nextLen += item.length;
-        // If adding the content will overshoot the limit
-        // use the truncation fu
-        if (nextLen &gt;= len) {
-          // Chop the string to the amount needed to complete
-          // the max length, minus the amount for the tail string if any
-          // NOTE: Content segment can be less than the length of the
-          // tail string -- this can result in a fudge factor of the length
-          // of the tail for the entire string
-          trunc = item.substr(0, (len - currLen) - t.length);
-          s += trunc;
-          // If we're sitting on an open HTML tag
-          if (openTag) {
-            // If there's content in the final truncated string,
-            // just append a closing tag of the same kind as
-            // the opening tag
-            if (trunc.length) {
-              closeTag = openTag.split(
-                  /\s|&gt;/)[0].replace('&lt;', '&lt;/') + '&gt;';
-              s += closeTag;
-            }
-            // If there's no content in the truncated string,
-            // just strip out the previous open tag
-            else {
-              s = s.replace(openTag, '');
-            }
-          }
-          // Append the tail, if any, and return
-          s += t;
-          return s;
-        }
-        else {
-          s += item;
-        }
-        currLen = nextLen;
-      }
-  }
-  return s;
-};
-
-</diff>
      <filename>fleegix.js.uncompressed.js</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>3279a5ea499ac5248c2ff5ca137c0a7458a65d77</id>
    </parent>
  </parents>
  <author>
    <name>mde</name>
    <email>mde@fleegix.org</email>
  </author>
  <url>http://github.com/mde/fleegix-js-javascript-toolkit/commit/5466a8986aa9fd1d6b19ebd867cf91b7f9f73078</url>
  <id>5466a8986aa9fd1d6b19ebd867cf91b7f9f73078</id>
  <committed-date>2009-03-22T21:25:27-07:00</committed-date>
  <authored-date>2009-03-22T21:25:27-07:00</authored-date>
  <message>Added revamped Web site to RCS.</message>
  <tree>3a98e2bc1b25a16d23b2bfc33a58881981132ce6</tree>
  <committer>
    <name>mde</name>
    <email>mde@fleegix.org</email>
  </committer>
</commit>
