var Prototype={Version:"1.6.0",Browser:{IE:!!(window.attachEvent&&!window.opera),Opera:!!window.opera,WebKit:navigator.userAgent.indexOf("AppleWebKit/")>-1,Gecko:navigator.userAgent.indexOf("Gecko")>-1&&navigator.userAgent.indexOf("KHTML")==-1,MobileSafari:!!navigator.userAgent.match(/Apple.*Mobile.*Safari/)},BrowserFeatures:{XPath:!!document.evaluate,ElementExtensions:!!window.HTMLElement,SpecificElementExtensions:document.createElement("div").__proto__&&document.createElement("div").__proto__!==document.createElement("form").__proto__},ScriptFragment:"<script[^>]*>([\\S\\s]*?)<\/script>",JSONFilter:/^\/\*-secure-([\s\S]*)\*\/\s*$/,emptyFunction:function(){},K:function(A){return A;}};if(Prototype.Browser.MobileSafari){Prototype.BrowserFeatures.SpecificElementExtensions=false;}if(Prototype.Browser.WebKit){Prototype.BrowserFeatures.XPath=false;}var Class={create:function(){var E=null,D=$A(arguments);if(Object.isFunction(D[0])){E=D.shift();}function A(){this.initialize.apply(this,arguments);}Object.extend(A,Class.Methods);A.superclass=E;A.subclasses=[];if(E){var B=function(){};B.prototype=E.prototype;A.prototype=new B;E.subclasses.push(A);}for(var C=0;C<D.length;C++){A.addMethods(D[C]);}if(!A.prototype.initialize){A.prototype.initialize=Prototype.emptyFunction;}A.prototype.constructor=A;return A;}};Class.Methods={addMethods:function(G){var C=this.superclass&&this.superclass.prototype;var B=Object.keys(G);if(!Object.keys({toString:true}).length){B.push("toString","valueOf");}for(var A=0,D=B.length;A<D;A++){var F=B[A],E=G[F];if(C&&Object.isFunction(E)&&E.argumentNames().first()=="$super"){var H=E,E=Object.extend((function(I){return function(){return C[I].apply(this,arguments);};})(F).wrap(H),{valueOf:function(){return H;},toString:function(){return H.toString();}});}this.prototype[F]=E;}return this;}};var Abstract={};Object.extend=function(A,C){for(var B in C){A[B]=C[B];}return A;};Object.extend(Object,{inspect:function(A){try{if(A===undefined){return"undefined";}if(A===null){return"null";}return A.inspect?A.inspect():A.toString();}catch(B){if(B instanceof RangeError){return"...";}throw B;}},toJSON:function(A){var C=typeof A;switch(C){case"undefined":case"function":case"unknown":return ;case"boolean":return A.toString();}if(A===null){return"null";}if(A.toJSON){return A.toJSON();}if(Object.isElement(A)){return ;}var B=[];for(var E in A){var D=Object.toJSON(A[E]);if(D!==undefined){B.push(E.toJSON()+": "+D);}}return"{"+B.join(", ")+"}";},toQueryString:function(A){return $H(A).toQueryString();},toHTML:function(A){return A&&A.toHTML?A.toHTML():String.interpret(A);},keys:function(A){var B=[];for(var C in A){B.push(C);}return B;},values:function(B){var A=[];for(var C in B){A.push(B[C]);}return A;},clone:function(A){return Object.extend({},A);},isElement:function(A){return A&&A.nodeType==1;},isArray:function(A){return A&&A.constructor===Array;},isHash:function(A){return A instanceof Hash;},isFunction:function(A){return typeof A=="function";},isString:function(A){return typeof A=="string";},isNumber:function(A){return typeof A=="number";},isUndefined:function(A){return typeof A=="undefined";}});Object.extend(Function.prototype,{argumentNames:function(){var A=this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");return A.length==1&&!A[0]?[]:A;},bind:function(){if(arguments.length<2&&arguments[0]===undefined){return this;}var A=this,C=$A(arguments),B=C.shift();return function(){return A.apply(B,C.concat($A(arguments)));};},bindAsEventListener:function(){var A=this,C=$A(arguments),B=C.shift();return function(D){return A.apply(B,[D||window.event].concat(C));};},curry:function(){if(!arguments.length){return this;}var A=this,B=$A(arguments);return function(){return A.apply(this,B.concat($A(arguments)));};},delay:function(){var A=this,B=$A(arguments),C=B.shift()*1000;return window.setTimeout(function(){return A.apply(A,B);},C);},wrap:function(B){var A=this;return function(){return B.apply(this,[A.bind(this)].concat($A(arguments)));};},methodize:function(){if(this._methodized){return this._methodized;}var A=this;return this._methodized=function(){return A.apply(null,[this].concat($A(arguments)));};}});Function.prototype.defer=Function.prototype.delay.curry(0.01);Date.prototype.toJSON=function(){return'"'+this.getUTCFullYear()+"-"+(this.getUTCMonth()+1).toPaddedString(2)+"-"+this.getUTCDate().toPaddedString(2)+"T"+this.getUTCHours().toPaddedString(2)+":"+this.getUTCMinutes().toPaddedString(2)+":"+this.getUTCSeconds().toPaddedString(2)+'Z"';};var Try={these:function(){var C;for(var B=0,D=arguments.length;B<D;B++){var A=arguments[B];try{C=A();break;}catch(E){}}return C;}};RegExp.prototype.match=RegExp.prototype.test;RegExp.escape=function(A){return String(A).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1");};var PeriodicalExecuter=Class.create({initialize:function(B,A){this.callback=B;this.frequency=A;this.currentlyExecuting=false;this.registerCallback();},registerCallback:function(){this.timer=setInterval(this.onTimerEvent.bind(this),this.frequency*1000);},execute:function(){this.callback(this);},stop:function(){if(!this.timer){return ;}clearInterval(this.timer);this.timer=null;},onTimerEvent:function(){if(!this.currentlyExecuting){try{this.currentlyExecuting=true;this.execute();}finally{this.currentlyExecuting=false;}}}});Object.extend(String,{interpret:function(A){return A==null?"":String(A);},specialChar:{"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r","\\":"\\\\"}});Object.extend(String.prototype,{gsub:function(E,C){var A="",D=this,B;C=arguments.callee.prepareReplacement(C);while(D.length>0){if(B=D.match(E)){A+=D.slice(0,B.index);A+=String.interpret(C(B));D=D.slice(B.index+B[0].length);}else{A+=D,D="";}}return A;},sub:function(C,A,B){A=this.gsub.prepareReplacement(A);B=B===undefined?1:B;return this.gsub(C,function(D){if(--B<0){return D[0];}return A(D);});},scan:function(B,A){this.gsub(B,A);return String(this);},truncate:function(B,A){B=B||30;A=A===undefined?"...":A;return this.length>B?this.slice(0,B-A.length)+A:String(this);},strip:function(){return this.replace(/^\s+/,"").replace(/\s+$/,"");},stripTags:function(){return this.replace(/<\/?[^>]+>/gi,"");},stripScripts:function(){return this.replace(new RegExp(Prototype.ScriptFragment,"img"),"");},extractScripts:function(){var B=new RegExp(Prototype.ScriptFragment,"img");var A=new RegExp(Prototype.ScriptFragment,"im");return(this.match(B)||[]).map(function(C){return(C.match(A)||["",""])[1];});},evalScripts:function(){return this.extractScripts().map(function(script){return eval(script);});},escapeHTML:function(){var A=arguments.callee;A.text.data=this;return A.div.innerHTML;},unescapeHTML:function(){var A=new Element("div");A.innerHTML=this.stripTags();return A.childNodes[0]?(A.childNodes.length>1?$A(A.childNodes).inject("",function(B,C){return B+C.nodeValue;}):A.childNodes[0].nodeValue):"";},toQueryParams:function(B){var A=this.strip().match(/([^?#]*)(#.*)?$/);if(!A){return{};}return A[1].split(B||"&").inject({},function(E,F){if((F=F.split("="))[0]){var C=decodeURIComponent(F.shift());var D=F.length>1?F.join("="):F[0];if(D!=undefined){D=decodeURIComponent(D);}if(C in E){if(!Object.isArray(E[C])){E[C]=[E[C]];}E[C].push(D);}else{E[C]=D;}}return E;});},toArray:function(){return this.split("");},succ:function(){return this.slice(0,this.length-1)+String.fromCharCode(this.charCodeAt(this.length-1)+1);},times:function(A){return A<1?"":new Array(A+1).join(this);},camelize:function(){var D=this.split("-"),A=D.length;if(A==1){return D[0];}var C=this.charAt(0)=="-"?D[0].charAt(0).toUpperCase()+D[0].substring(1):D[0];for(var B=1;B<A;B++){C+=D[B].charAt(0).toUpperCase()+D[B].substring(1);}return C;},capitalize:function(){return this.charAt(0).toUpperCase()+this.substring(1).toLowerCase();},underscore:function(){return this.gsub(/::/,"/").gsub(/([A-Z]+)([A-Z][a-z])/,"#{1}_#{2}").gsub(/([a-z\d])([A-Z])/,"#{1}_#{2}").gsub(/-/,"_").toLowerCase();},dasherize:function(){return this.gsub(/_/,"-");},inspect:function(B){var A=this.gsub(/[\x00-\x1f\\]/,function(C){var D=String.specialChar[C[0]];return D?D:"\\u00"+C[0].charCodeAt().toPaddedString(2,16);});if(B){return'"'+A.replace(/"/g,'\\"')+'"';}return"'"+A.replace(/'/g,"\\'")+"'";},toJSON:function(){return this.inspect(true);},unfilterJSON:function(A){return this.sub(A||Prototype.JSONFilter,"#{1}");},isJSON:function(){var A=this.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"/g,"");return(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(A);},evalJSON:function(sanitize){var json=this.unfilterJSON();try{if(!sanitize||json.isJSON()){return eval("("+json+")");}}catch(e){}throw new SyntaxError("Badly formed JSON string: "+this.inspect());},include:function(A){return this.indexOf(A)>-1;},startsWith:function(A){return this.indexOf(A)===0;},endsWith:function(A){var B=this.length-A.length;return B>=0&&this.lastIndexOf(A)===B;},empty:function(){return this=="";},blank:function(){return/^\s*$/.test(this);},interpolate:function(A,B){return new Template(this,B).evaluate(A);}});if(Prototype.Browser.WebKit||Prototype.Browser.IE){Object.extend(String.prototype,{escapeHTML:function(){return this.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");},unescapeHTML:function(){return this.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">");}});}String.prototype.gsub.prepareReplacement=function(B){if(Object.isFunction(B)){return B;}var A=new Template(B);return function(C){return A.evaluate(C);};};String.prototype.parseQuery=String.prototype.toQueryParams;Object.extend(String.prototype.escapeHTML,{div:document.createElement("div"),text:document.createTextNode("")});with(String.prototype.escapeHTML){div.appendChild(text);}var Template=Class.create({initialize:function(A,B){this.template=A.toString();this.pattern=B||Template.Pattern;},evaluate:function(A){if(Object.isFunction(A.toTemplateReplacements)){A=A.toTemplateReplacements();}return this.template.gsub(this.pattern,function(D){if(A==null){return"";}var F=D[1]||"";if(F=="\\"){return D[2];}var B=A,G=D[3];var E=/^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/,D=E.exec(G);if(D==null){return F;}while(D!=null){var C=D[1].startsWith("[")?D[2].gsub("\\\\]","]"):D[1];B=B[C];if(null==B||""==D[3]){break;}G=G.substring("["==D[3]?D[1].length:D[0].length);D=E.exec(G);}return F+String.interpret(B);}.bind(this));}});Template.Pattern=/(^|.|\r|\n)(#\{(.*?)\})/;var $break={};var Enumerable={each:function(C,B){var A=0;C=C.bind(B);try{this._each(function(E){C(E,A++);});}catch(D){if(D!=$break){throw D;}}return this;},eachSlice:function(D,C,B){C=C?C.bind(B):Prototype.K;var A=-D,E=[],F=this.toArray();while((A+=D)<F.length){E.push(F.slice(A,A+D));}return E.collect(C,B);},all:function(C,B){C=C?C.bind(B):Prototype.K;var A=true;this.each(function(E,D){A=A&&!!C(E,D);if(!A){throw $break;}});return A;},any:function(C,B){C=C?C.bind(B):Prototype.K;var A=false;this.each(function(E,D){if(A=!!C(E,D)){throw $break;}});return A;},collect:function(C,B){C=C?C.bind(B):Prototype.K;var A=[];this.each(function(E,D){A.push(C(E,D));});return A;},detect:function(C,B){C=C.bind(B);var A;this.each(function(E,D){if(C(E,D)){A=E;throw $break;}});return A;},findAll:function(C,B){C=C.bind(B);var A=[];this.each(function(E,D){if(C(E,D)){A.push(E);}});return A;},grep:function(D,C,B){C=C?C.bind(B):Prototype.K;var A=[];if(Object.isString(D)){D=new RegExp(D);}this.each(function(F,E){if(D.match(F)){A.push(C(F,E));}});return A;},include:function(A){if(Object.isFunction(this.indexOf)){if(this.indexOf(A)!=-1){return true;}}var B=false;this.each(function(C){if(C==A){B=true;throw $break;}});return B;},inGroupsOf:function(B,A){A=A===undefined?null:A;return this.eachSlice(B,function(C){while(C.length<B){C.push(A);}return C;});},inject:function(A,C,B){C=C.bind(B);this.each(function(E,D){A=C(A,E,D);});return A;},invoke:function(B){var A=$A(arguments).slice(1);return this.map(function(C){return C[B].apply(C,A);});},max:function(C,B){C=C?C.bind(B):Prototype.K;var A;this.each(function(E,D){E=C(E,D);if(A==undefined||E>=A){A=E;}});return A;},min:function(C,B){C=C?C.bind(B):Prototype.K;var A;this.each(function(E,D){E=C(E,D);if(A==undefined||E<A){A=E;}});return A;},partition:function(D,B){D=D?D.bind(B):Prototype.K;var C=[],A=[];this.each(function(F,E){(D(F,E)?C:A).push(F);});return[C,A];},pluck:function(B){var A=[];this.each(function(C){A.push(C[B]);});return A;},reject:function(C,B){C=C.bind(B);var A=[];this.each(function(E,D){if(!C(E,D)){A.push(E);}});return A;},sortBy:function(B,A){B=B.bind(A);return this.map(function(D,C){return{value:D,criteria:B(D,C)};}).sort(function(F,E){var D=F.criteria,C=E.criteria;return D<C?-1:D>C?1:0;}).pluck("value");},toArray:function(){return this.map();},zip:function(){var B=Prototype.K,A=$A(arguments);if(Object.isFunction(A.last())){B=A.pop();}var C=[this].concat(A).map($A);return this.map(function(E,D){return B(C.pluck(D));});},size:function(){return this.toArray().length;},inspect:function(){return"#<Enumerable:"+this.toArray().inspect()+">";}};Object.extend(Enumerable,{map:Enumerable.collect,find:Enumerable.detect,select:Enumerable.findAll,filter:Enumerable.findAll,member:Enumerable.include,entries:Enumerable.toArray,every:Enumerable.all,some:Enumerable.any});function $A(C){if(!C){return[];}if(C.toArray){return C.toArray();}var B=C.length,A=new Array(B);while(B--){A[B]=C[B];}return A;}if(Prototype.Browser.WebKit){function $A(C){if(!C){return[];}if(!(Object.isFunction(C)&&C=="[object NodeList]")&&C.toArray){return C.toArray();}var B=C.length,A=new Array(B);while(B--){A[B]=C[B];}return A;}}Array.from=$A;Object.extend(Array.prototype,Enumerable);if(!Array.prototype._reverse){Array.prototype._reverse=Array.prototype.reverse;}Object.extend(Array.prototype,{_each:function(B){for(var A=0,C=this.length;A<C;A++){B(this[A]);}},clear:function(){this.length=0;return this;},first:function(){return this[0];},last:function(){return this[this.length-1];},compact:function(){return this.select(function(A){return A!=null;});},flatten:function(){return this.inject([],function(B,A){return B.concat(Object.isArray(A)?A.flatten():[A]);});},without:function(){var A=$A(arguments);return this.select(function(B){return !A.include(B);});},reverse:function(A){return(A!==false?this:this.toArray())._reverse();},reduce:function(){return this.length>1?this:this[0];},uniq:function(A){return this.inject([],function(D,C,B){if(0==B||(A?D.last()!=C:!D.include(C))){D.push(C);}return D;});},intersect:function(A){return this.uniq().findAll(function(B){return A.detect(function(C){return B===C;});});},clone:function(){return[].concat(this);},size:function(){return this.length;},inspect:function(){return"["+this.map(Object.inspect).join(", ")+"]";},toJSON:function(){var A=[];this.each(function(B){var C=Object.toJSON(B);if(C!==undefined){A.push(C);}});return"["+A.join(", ")+"]";}});if(Object.isFunction(Array.prototype.forEach)){Array.prototype._each=Array.prototype.forEach;}if(!Array.prototype.indexOf){Array.prototype.indexOf=function(C,A){A||(A=0);var B=this.length;if(A<0){A=B+A;}for(;A<B;A++){if(this[A]===C){return A;}}return -1;};}if(!Array.prototype.lastIndexOf){Array.prototype.lastIndexOf=function(B,A){A=isNaN(A)?this.length:(A<0?this.length+A:A)+1;var C=this.slice(0,A).reverse().indexOf(B);return(C<0)?C:A-C-1;};}Array.prototype.toArray=Array.prototype.clone;function $w(A){if(!Object.isString(A)){return[];}A=A.strip();return A?A.split(/\s+/):[];}if(Prototype.Browser.Opera){Array.prototype.concat=function(){var E=[];for(var B=0,C=this.length;B<C;B++){E.push(this[B]);}for(var B=0,C=arguments.length;B<C;B++){if(Object.isArray(arguments[B])){for(var A=0,D=arguments[B].length;A<D;A++){E.push(arguments[B][A]);}}else{E.push(arguments[B]);}}return E;};}Object.extend(Number.prototype,{toColorPart:function(){return this.toPaddedString(2,16);},succ:function(){return this+1;},times:function(A){$R(0,this,true).each(A);return this;},toPaddedString:function(C,B){var A=this.toString(B||10);return"0".times(C-A.length)+A;},toJSON:function(){return isFinite(this)?this.toString():"null";}});$w("abs round ceil floor").each(function(A){Number.prototype[A]=Math[A].methodize();});function $H(A){return new Hash(A);}var Hash=Class.create(Enumerable,(function(){if(function(){var C=0,E=function(F){this.key=F;};E.prototype.key="foo";for(var D in new E("bar")){C++;}return C>1;}()){function B(E){var C=[];for(var D in this._object){var F=this._object[D];if(C.include(D)){continue;}C.push(D);var G=[D,F];G.key=D;G.value=F;E(G);}}}else{function B(D){for(var C in this._object){var E=this._object[C],F=[C,E];F.key=C;F.value=E;D(F);}}}function A(C,D){if(Object.isUndefined(D)){return C;}return C+"="+encodeURIComponent(String.interpret(D));}return{initialize:function(C){this._object=Object.isHash(C)?C.toObject():Object.clone(C);},_each:B,set:function(C,D){return this._object[C]=D;},get:function(C){return this._object[C];},unset:function(C){var D=this._object[C];delete this._object[C];return D;},toObject:function(){return Object.clone(this._object);},keys:function(){return this.pluck("key");},values:function(){return this.pluck("value");},index:function(D){var C=this.detect(function(E){return E.value===D;});return C&&C.key;},merge:function(C){return this.clone().update(C);},update:function(C){return new Hash(C).inject(this,function(D,E){D.set(E.key,E.value);return D;});},toQueryString:function(){return this.map(function(E){var D=encodeURIComponent(E.key),C=E.value;if(C&&typeof C=="object"){if(Object.isArray(C)){return C.map(A.curry(D)).join("&");}}return A(D,C);}).join("&");},inspect:function(){return"#<Hash:{"+this.map(function(C){return C.map(Object.inspect).join(": ");}).join(", ")+"}>";},toJSON:function(){return Object.toJSON(this.toObject());},clone:function(){return new Hash(this);}};})());Hash.prototype.toTemplateReplacements=Hash.prototype.toObject;Hash.from=$H;var ObjectRange=Class.create(Enumerable,{initialize:function(C,A,B){this.start=C;this.end=A;this.exclusive=B;},_each:function(A){var B=this.start;while(this.include(B)){A(B);B=B.succ();}},include:function(A){if(A<this.start){return false;}if(this.exclusive){return A<this.end;}return A<=this.end;}});var $R=function(C,A,B){return new ObjectRange(C,A,B);};var Ajax={getTransport:function(){return Try.these(function(){return new XMLHttpRequest();},function(){return new ActiveXObject("Msxml2.XMLHTTP");},function(){return new ActiveXObject("Microsoft.XMLHTTP");})||false;},activeRequestCount:0};Ajax.Responders={responders:[],_each:function(A){this.responders._each(A);},register:function(A){if(!this.include(A)){this.responders.push(A);}},unregister:function(A){this.responders=this.responders.without(A);},dispatch:function(D,B,C,A){this.each(function(E){if(Object.isFunction(E[D])){try{E[D].apply(E,[B,C,A]);}catch(F){}}});}};Object.extend(Ajax.Responders,Enumerable);Ajax.Responders.register({onCreate:function(){Ajax.activeRequestCount++;},onComplete:function(){Ajax.activeRequestCount--;}});Ajax.Base=Class.create({initialize:function(A){this.options={method:"post",asynchronous:true,contentType:"application/x-www-form-urlencoded",encoding:"UTF-8",parameters:"",evalJSON:true,evalJS:true};Object.extend(this.options,A||{});this.options.method=this.options.method.toLowerCase();if(Object.isString(this.options.parameters)){this.options.parameters=this.options.parameters.toQueryParams();}}});Ajax.Request=Class.create(Ajax.Base,{_complete:false,initialize:function($super,B,A){$super(A);this.transport=Ajax.getTransport();this.request(B);},request:function(B){this.url=B;this.method=this.options.method;var D=Object.clone(this.options.parameters);if(!["get","post"].include(this.method)){D["_method"]=this.method;this.method="post";}this.parameters=D;if(D=Object.toQueryString(D)){if(this.method=="get"){this.url+=(this.url.include("?")?"&":"?")+D;}else{if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){D+="&_=";}}}try{var A=new Ajax.Response(this);if(this.options.onCreate){this.options.onCreate(A);}Ajax.Responders.dispatch("onCreate",this,A);this.transport.open(this.method.toUpperCase(),this.url,this.options.asynchronous);if(this.options.asynchronous){this.respondToReadyState.bind(this).defer(1);}this.transport.onreadystatechange=this.onStateChange.bind(this);this.setRequestHeaders();this.body=this.method=="post"?(this.options.postBody||D):null;this.transport.send(this.body);if(!this.options.asynchronous&&this.transport.overrideMimeType){this.onStateChange();}}catch(C){this.dispatchException(C);}},onStateChange:function(){var A=this.transport.readyState;if(A>1&&!((A==4)&&this._complete)){this.respondToReadyState(this.transport.readyState);}},setRequestHeaders:function(){var E={"X-Requested-With":"XMLHttpRequest","X-Prototype-Version":Prototype.Version,"Accept":"text/javascript, text/html, application/xml, text/xml, */*"};if(this.method=="post"){E["Content-type"]=this.options.contentType+(this.options.encoding?"; charset="+this.options.encoding:"");if(this.transport.overrideMimeType&&(navigator.userAgent.match(/Gecko\/(\d{4})/)||[0,2005])[1]<2005){E["Connection"]="close";}}if(typeof this.options.requestHeaders=="object"){var C=this.options.requestHeaders;if(Object.isFunction(C.push)){for(var B=0,D=C.length;B<D;B+=2){E[C[B]]=C[B+1];}}else{$H(C).each(function(F){E[F.key]=F.value;});}}for(var A in E){this.transport.setRequestHeader(A,E[A]);}},success:function(){var A=this.getStatus();return !A||(A>=200&&A<300);},getStatus:function(){try{return this.transport.status||0;}catch(A){return 0;}},respondToReadyState:function(A){var C=Ajax.Request.Events[A],B=new Ajax.Response(this);if(C=="Complete"){try{this._complete=true;(this.options["on"+B.status]||this.options["on"+(this.success()?"Success":"Failure")]||Prototype.emptyFunction)(B,B.headerJSON);}catch(D){this.dispatchException(D);}var E=B.getHeader("Content-type");if(this.options.evalJS=="force"||(this.options.evalJS&&E&&E.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))){this.evalResponse();}}try{(this.options["on"+C]||Prototype.emptyFunction)(B,B.headerJSON);Ajax.Responders.dispatch("on"+C,this,B,B.headerJSON);}catch(D){this.dispatchException(D);}if(C=="Complete"){this.transport.onreadystatechange=Prototype.emptyFunction;}},getHeader:function(A){try{return this.transport.getResponseHeader(A);}catch(B){return null;}},evalResponse:function(){try{return eval((this.transport.responseText||"").unfilterJSON());}catch(e){this.dispatchException(e);}},dispatchException:function(A){(this.options.onException||Prototype.emptyFunction)(this,A);Ajax.Responders.dispatch("onException",this,A);}});Ajax.Request.Events=["Uninitialized","Loading","Loaded","Interactive","Complete"];Ajax.Response=Class.create({initialize:function(C){this.request=C;var D=this.transport=C.transport,A=this.readyState=D.readyState;if((A>2&&!Prototype.Browser.IE)||A==4){this.status=this.getStatus();this.statusText=this.getStatusText();this.responseText=String.interpret(D.responseText);this.headerJSON=this._getHeaderJSON();}if(A==4){var B=D.responseXML;this.responseXML=B===undefined?null:B;this.responseJSON=this._getResponseJSON();}},status:0,statusText:"",getStatus:Ajax.Request.prototype.getStatus,getStatusText:function(){try{return this.transport.statusText||"";}catch(A){return"";}},getHeader:Ajax.Request.prototype.getHeader,getAllHeaders:function(){try{return this.getAllResponseHeaders();}catch(A){return null;}},getResponseHeader:function(A){return this.transport.getResponseHeader(A);},getAllResponseHeaders:function(){return this.transport.getAllResponseHeaders();},_getHeaderJSON:function(){var A=this.getHeader("X-JSON");if(!A){return null;}A=decodeURIComponent(escape(A));try{return A.evalJSON(this.request.options.sanitizeJSON);}catch(B){this.request.dispatchException(B);}},_getResponseJSON:function(){var A=this.request.options;if(!A.evalJSON||(A.evalJSON!="force"&&!(this.getHeader("Content-type")||"").include("application/json"))){return null;}try{return this.transport.responseText.evalJSON(A.sanitizeJSON);}catch(B){this.request.dispatchException(B);}}});Ajax.Updater=Class.create(Ajax.Request,{initialize:function($super,A,C,B){this.container={success:(A.success||A),failure:(A.failure||(A.success?null:A))};B=B||{};var D=B.onComplete;B.onComplete=(function(E,F){this.updateContent(E.responseText);if(Object.isFunction(D)){D(E,F);}}).bind(this);$super(C,B);},updateContent:function(D){var C=this.container[this.success()?"success":"failure"],A=this.options;if(!A.evalScripts){D=D.stripScripts();}if(C=$(C)){if(A.insertion){if(Object.isString(A.insertion)){var B={};B[A.insertion]=D;C.insert(B);}else{A.insertion(C,D);}}else{C.update(D);}}if(this.success()){if(this.onComplete){this.onComplete.bind(this).defer();}}}});Ajax.PeriodicalUpdater=Class.create(Ajax.Base,{initialize:function($super,A,C,B){$super(B);this.onComplete=this.options.onComplete;this.frequency=(this.options.frequency||2);this.decay=(this.options.decay||1);this.updater={};this.container=A;this.url=C;this.start();},start:function(){this.options.onComplete=this.updateComplete.bind(this);this.onTimerEvent();},stop:function(){this.updater.options.onComplete=undefined;clearTimeout(this.timer);(this.onComplete||Prototype.emptyFunction).apply(this,arguments);},updateComplete:function(A){if(this.options.decay){this.decay=(A.responseText==this.lastText?this.decay*this.options.decay:1);this.lastText=A.responseText;}this.timer=this.onTimerEvent.bind(this).delay(this.decay*this.frequency);},onTimerEvent:function(){this.updater=new Ajax.Updater(this.container,this.url,this.options);}});function $(B){if(arguments.length>1){for(var A=0,D=[],C=arguments.length;A<C;A++){D.push($(arguments[A]));}return D;}if(Object.isString(B)){B=document.getElementById(B);}return Element.extend(B);}if(Prototype.BrowserFeatures.XPath){document._getElementsByXPath=function(F,A){var C=[];var E=document.evaluate(F,$(A)||document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(var B=0,D=E.snapshotLength;B<D;B++){C.push(Element.extend(E.snapshotItem(B)));}return C;};}if(!window.Node){var Node={};}if(!Node.ELEMENT_NODE){Object.extend(Node,{ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12});}(function(){var A=this.Element;this.Element=function(D,C){C=C||{};D=D.toLowerCase();var B=Element.cache;if(Prototype.Browser.IE&&C.name){D="<"+D+' name="'+C.name+'">';delete C.name;return Element.writeAttribute(document.createElement(D),C);}if(!B[D]){B[D]=Element.extend(document.createElement(D));}return Element.writeAttribute(B[D].cloneNode(false),C);};Object.extend(this.Element,A||{});}).call(window);Element.cache={};Element.Methods={visible:function(A){return $(A).style.display!="none";},toggle:function(A){A=$(A);Element[Element.visible(A)?"hide":"show"](A);return A;},hide:function(A){$(A).style.display="none";return A;},show:function(A){$(A).style.display="";return A;},remove:function(A){A=$(A);A.parentNode.removeChild(A);return A;},update:function(A,B){A=$(A);if(B&&B.toElement){B=B.toElement();}if(Object.isElement(B)){return A.update().insert(B);}B=Object.toHTML(B);A.innerHTML=B.stripScripts();B.evalScripts.bind(B).defer();return A;},replace:function(B,C){B=$(B);if(C&&C.toElement){C=C.toElement();}else{if(!Object.isElement(C)){C=Object.toHTML(C);var A=B.ownerDocument.createRange();A.selectNode(B);C.evalScripts.bind(C).defer();C=A.createContextualFragment(C.stripScripts());}}B.parentNode.replaceChild(C,B);return B;},insert:function(C,E){C=$(C);if(Object.isString(E)||Object.isNumber(E)||Object.isElement(E)||(E&&(E.toElement||E.toHTML))){E={bottom:E};}var D,B,A;for(position in E){D=E[position];position=position.toLowerCase();B=Element._insertionTranslations[position];if(D&&D.toElement){D=D.toElement();}if(Object.isElement(D)){B.insert(C,D);continue;}D=Object.toHTML(D);A=C.ownerDocument.createRange();B.initializeRange(C,A);B.insert(C,A.createContextualFragment(D.stripScripts()));D.evalScripts.bind(D).defer();}return C;},wrap:function(B,C,A){B=$(B);if(Object.isElement(C)){$(C).writeAttribute(A||{});}else{if(Object.isString(C)){C=new Element(C,A);}else{C=new Element("div",C);}}if(B.parentNode){B.parentNode.replaceChild(C,B);}C.appendChild(B);return C;},inspect:function(B){B=$(B);var A="<"+B.tagName.toLowerCase();$H({"id":"id","className":"class"}).each(function(F){var E=F.first(),C=F.last();var D=(B[E]||"").toString();if(D){A+=" "+C+"="+D.inspect(true);}});return A+">";},recursivelyCollect:function(A,C){A=$(A);var B=[];while(A=A[C]){if(A.nodeType==1){B.push(Element.extend(A));}}return B;},ancestors:function(A){return $(A).recursivelyCollect("parentNode");},descendants:function(A){return $A($(A).getElementsByTagName("*")).each(Element.extend);},firstDescendant:function(A){A=$(A).firstChild;while(A&&A.nodeType!=1){A=A.nextSibling;}return $(A);},immediateDescendants:function(A){if(!(A=$(A).firstChild)){return[];}while(A&&A.nodeType!=1){A=A.nextSibling;}if(A){return[A].concat($(A).nextSiblings());}return[];},previousSiblings:function(A){return $(A).recursivelyCollect("previousSibling");},nextSiblings:function(A){return $(A).recursivelyCollect("nextSibling");},siblings:function(A){A=$(A);return A.previousSiblings().reverse().concat(A.nextSiblings());},match:function(B,A){if(Object.isString(A)){A=new Selector(A);}return A.match($(B));},up:function(B,D,A){B=$(B);if(arguments.length==1){return $(B.parentNode);}var C=B.ancestors();return D?Selector.findElement(C,D,A):C[A||0];},down:function(B,C,A){B=$(B);if(arguments.length==1){return B.firstDescendant();}var D=B.descendants();return C?Selector.findElement(D,C,A):D[A||0];},previous:function(B,D,A){B=$(B);if(arguments.length==1){return $(Selector.handlers.previousElementSibling(B));}var C=B.previousSiblings();return D?Selector.findElement(C,D,A):C[A||0];},next:function(C,D,B){C=$(C);if(arguments.length==1){return $(Selector.handlers.nextElementSibling(C));}var A=C.nextSiblings();return D?Selector.findElement(A,D,B):A[B||0];},select:function(){var A=$A(arguments),B=$(A.shift());return Selector.findChildElements(B,A);},adjacent:function(){var A=$A(arguments),B=$(A.shift());return Selector.findChildElements(B.parentNode,A).without(B);},identify:function(B){B=$(B);var C=B.readAttribute("id"),A=arguments.callee;if(C){return C;}do{C="anonymous_element_"+A.counter++;}while($(C));B.writeAttribute("id",C);return C;},readAttribute:function(C,A){C=$(C);if(Prototype.Browser.IE){var B=Element._attributeTranslations.read;if(B.values[A]){return B.values[A](C,A);}if(B.names[A]){A=B.names[A];}if(A.include(":")){return(!C.attributes||!C.attributes[A])?null:C.attributes[A].value;}}return C.getAttribute(A);},writeAttribute:function(E,C,F){E=$(E);var B={},D=Element._attributeTranslations.write;if(typeof C=="object"){B=C;}else{B[C]=F===undefined?true:F;}for(var A in B){var C=D.names[A]||A,F=B[A];if(D.values[A]){C=D.values[A](E,F);}if(F===false||F===null){E.removeAttribute(C);}else{if(F===true){E.setAttribute(C,C);}else{E.setAttribute(C,F);}}}return E;},getHeight:function(A){return $(A).getDimensions().height;},getWidth:function(A){return $(A).getDimensions().width;},classNames:function(A){return new Element.ClassNames(A);},hasClassName:function(A,B){if(!(A=$(A))){return ;}var C=A.className;return(C.length>0&&(C==B||new RegExp("(^|\\s)"+B+"(\\s|$)").test(C)));},addClassName:function(A,B){if(!(A=$(A))){return ;}if(!A.hasClassName(B)){A.className+=(A.className?" ":"")+B;}return A;},removeClassName:function(A,B){if(!(A=$(A))){return ;}A.className=A.className.replace(new RegExp("(^|\\s+)"+B+"(\\s+|$)")," ").strip();return A;},toggleClassName:function(A,B){if(!(A=$(A))){return ;}return A[A.hasClassName(B)?"removeClassName":"addClassName"](B);},cleanWhitespace:function(B){B=$(B);var C=B.firstChild;while(C){var A=C.nextSibling;if(C.nodeType==3&&!/\S/.test(C.nodeValue)){B.removeChild(C);}C=A;}return B;},empty:function(A){return $(A).innerHTML.blank();},descendantOf:function(D,C){D=$(D),C=$(C);if(D.compareDocumentPosition){return(D.compareDocumentPosition(C)&8)===8;}if(D.sourceIndex&&!Prototype.Browser.Opera){var E=D.sourceIndex,B=C.sourceIndex,A=C.nextSibling;if(!A){do{C=C.parentNode;}while(!(A=C.nextSibling)&&C.parentNode);}if(A){return(E>B&&E<A.sourceIndex);}}while(D=D.parentNode){if(D==C){return true;}}return false;},scrollTo:function(A){A=$(A);var B=A.cumulativeOffset();window.scrollTo(B[0],B[1]);return A;},getStyle:function(B,C){B=$(B);C=C=="float"?"cssFloat":C.camelize();var D=B.style[C];if(!D){var A=document.defaultView.getComputedStyle(B,null);D=A?A[C]:null;}if(C=="opacity"){return D?parseFloat(D):1;}return D=="auto"?null:D;},getOpacity:function(A){return $(A).getStyle("opacity");},setStyle:function(B,C){B=$(B);var E=B.style,A;if(Object.isString(C)){B.style.cssText+=";"+C;return C.include("opacity")?B.setOpacity(C.match(/opacity:\s*(\d?\.?\d*)/)[1]):B;}for(var D in C){if(D=="opacity"){B.setOpacity(C[D]);}else{E[(D=="float"||D=="cssFloat")?(E.styleFloat===undefined?"cssFloat":"styleFloat"):D]=C[D];}}return B;},setOpacity:function(A,B){A=$(A);A.style.opacity=(B==1||B==="")?"":(B<0.00001)?0:B;return A;},getDimensions:function(C){C=$(C);var G=$(C).getStyle("display");if(G!="none"&&G!=null){return{width:C.offsetWidth,height:C.offsetHeight};}var B=C.style;var F=B.visibility;var D=B.position;var A=B.display;B.visibility="hidden";B.position="absolute";B.display="block";var H=C.clientWidth;var E=C.clientHeight;B.display=A;B.position=D;B.visibility=F;return{width:H,height:E};},makePositioned:function(A){A=$(A);var B=Element.getStyle(A,"position");if(B=="static"||!B){A._madePositioned=true;A.style.position="relative";if(window.opera){A.style.top=0;A.style.left=0;}}return A;},undoPositioned:function(A){A=$(A);if(A._madePositioned){A._madePositioned=undefined;A.style.position=A.style.top=A.style.left=A.style.bottom=A.style.right="";}return A;},makeClipping:function(A){A=$(A);if(A._overflow){return A;}A._overflow=Element.getStyle(A,"overflow")||"auto";if(A._overflow!=="hidden"){A.style.overflow="hidden";}return A;},undoClipping:function(A){A=$(A);if(!A._overflow){return A;}A.style.overflow=A._overflow=="auto"?"":A._overflow;A._overflow=null;return A;},cumulativeOffset:function(B){var A=0,C=0;do{A+=B.offsetTop||0;C+=B.offsetLeft||0;B=B.offsetParent;}while(B);return Element._returnOffset(C,A);},positionedOffset:function(B){var A=0,D=0;do{A+=B.offsetTop||0;D+=B.offsetLeft||0;B=B.offsetParent;if(B){if(B.tagName=="BODY"){break;}var C=Element.getStyle(B,"position");if(C=="relative"||C=="absolute"){break;}}}while(B);return Element._returnOffset(D,A);},absolutize:function(B){B=$(B);if(B.getStyle("position")=="absolute"){return ;}var D=B.positionedOffset();var F=D[1];var E=D[0];var C=B.clientWidth;var A=B.clientHeight;B._originalLeft=E-parseFloat(B.style.left||0);B._originalTop=F-parseFloat(B.style.top||0);B._originalWidth=B.style.width;B._originalHeight=B.style.height;B.style.position="absolute";B.style.top=F+"px";B.style.left=E+"px";B.style.width=C+"px";B.style.height=A+"px";return B;},relativize:function(A){A=$(A);if(A.getStyle("position")=="relative"){return ;}A.style.position="relative";var C=parseFloat(A.style.top||0)-(A._originalTop||0);var B=parseFloat(A.style.left||0)-(A._originalLeft||0);A.style.top=C+"px";A.style.left=B+"px";A.style.height=A._originalHeight;A.style.width=A._originalWidth;return A;},cumulativeScrollOffset:function(B){var A=0,C=0;do{A+=B.scrollTop||0;C+=B.scrollLeft||0;B=B.parentNode;}while(B);return Element._returnOffset(C,A);},getOffsetParent:function(A){if(A.offsetParent){return $(A.offsetParent);}if(A==document.body){return $(A);}while((A=A.parentNode)&&A!=document.body){if(Element.getStyle(A,"position")!="static"){return $(A);}}return $(document.body);},viewportOffset:function(D){var A=0,C=0;var B=D;do{A+=B.offsetTop||0;C+=B.offsetLeft||0;if(B.offsetParent==document.body&&Element.getStyle(B,"position")=="absolute"){break;}}while(B=B.offsetParent);B=D;do{if(!Prototype.Browser.Opera||B.tagName=="BODY"){A-=B.scrollTop||0;C-=B.scrollLeft||0;}}while(B=B.parentNode);return Element._returnOffset(C,A);},clonePosition:function(B,D){var A=Object.extend({setLeft:true,setTop:true,setWidth:true,setHeight:true,offsetTop:0,offsetLeft:0},arguments[2]||{});D=$(D);var E=D.viewportOffset();B=$(B);var F=[0,0];var C=null;if(Element.getStyle(B,"position")=="absolute"){C=B.getOffsetParent();F=C.viewportOffset();}if(C==document.body){F[0]-=document.body.offsetLeft;F[1]-=document.body.offsetTop;}if(A.setLeft){B.style.left=(E[0]-F[0]+A.offsetLeft)+"px";}if(A.setTop){B.style.top=(E[1]-F[1]+A.offsetTop)+"px";}if(A.setWidth){B.style.width=D.offsetWidth+"px";}if(A.setHeight){B.style.height=D.offsetHeight+"px";}return B;}};Element.Methods.identify.counter=1;Object.extend(Element.Methods,{getElementsBySelector:Element.Methods.select,childElements:Element.Methods.immediateDescendants});Element._attributeTranslations={write:{names:{className:"class",htmlFor:"for"},values:{}}};if(!document.createRange||Prototype.Browser.Opera){Element.Methods.insert=function(E,G){E=$(E);if(Object.isString(G)||Object.isNumber(G)||Object.isElement(G)||(G&&(G.toElement||G.toHTML))){G={bottom:G};}var D=Element._insertionTranslations,F,B,H,C;for(B in G){F=G[B];B=B.toLowerCase();H=D[B];if(F&&F.toElement){F=F.toElement();}if(Object.isElement(F)){H.insert(E,F);continue;}F=Object.toHTML(F);C=((B=="before"||B=="after")?E.parentNode:E).tagName.toUpperCase();if(D.tags[C]){var A=Element._getContentFromAnonymousElement(C,F.stripScripts());if(B=="top"||B=="after"){A.reverse();}A.each(H.insert.curry(E));}else{E.insertAdjacentHTML(H.adjacency,F.stripScripts());}F.evalScripts.bind(F).defer();}return E;};}if(Prototype.Browser.Opera){Element.Methods._getStyle=Element.Methods.getStyle;Element.Methods.getStyle=function(A,B){switch(B){case"left":case"top":case"right":case"bottom":if(Element._getStyle(A,"position")=="static"){return null;}default:return Element._getStyle(A,B);}};Element.Methods._readAttribute=Element.Methods.readAttribute;Element.Methods.readAttribute=function(A,B){if(B=="title"){return A.title;}return Element._readAttribute(A,B);};}else{if(Prototype.Browser.IE){$w("positionedOffset getOffsetParent viewportOffset").each(function(A){Element.Methods[A]=Element.Methods[A].wrap(function(D,C){C=$(C);var B=C.getStyle("position");if(B!="static"){return D(C);}C.setStyle({position:"relative"});var E=D(C);C.setStyle({position:B});return E;});});Element.Methods.getStyle=function(A,B){A=$(A);B=(B=="float"||B=="cssFloat")?"styleFloat":B.camelize();var C=A.style[B];if(!C&&A.currentStyle){C=A.currentStyle[B];}if(B=="opacity"){if(C=(A.getStyle("filter")||"").match(/alpha\(opacity=(.*)\)/)){if(C[1]){return parseFloat(C[1])/100;}}return 1;}if(C=="auto"){if((B=="width"||B=="height")&&(A.getStyle("display")!="none")){return A["offset"+B.capitalize()]+"px";}return null;}return C;};Element.Methods.setOpacity=function(B,E){function F(G){return G.replace(/alpha\([^\)]*\)/gi,"");}B=$(B);var A=B.currentStyle;if((A&&!A.hasLayout)||(!A&&B.style.zoom=="normal")){B.style.zoom=1;}var D=B.getStyle("filter"),C=B.style;if(E==1||E===""){(D=F(D))?C.filter=D:C.removeAttribute("filter");return B;}else{if(E<0.00001){E=0;}}C.filter=F(D)+"alpha(opacity="+(E*100)+")";return B;};Element._attributeTranslations={read:{names:{"class":"className","for":"htmlFor"},values:{_getAttr:function(A,B){return A.getAttribute(B,2);},_getAttrNode:function(A,C){var B=A.getAttributeNode(C);return B?B.value:"";},_getEv:function(A,B){var B=A.getAttribute(B);return B?B.toString().slice(23,-2):null;},_flag:function(A,B){return $(A).hasAttribute(B)?B:null;},style:function(A){return A.style.cssText.toLowerCase();},title:function(A){return A.title;}}}};Element._attributeTranslations.write={names:Object.clone(Element._attributeTranslations.read.names),values:{checked:function(A,B){A.checked=!!B;},style:function(A,B){A.style.cssText=B?B:"";}}};Element._attributeTranslations.has={};$w("colSpan rowSpan vAlign dateTime accessKey tabIndex encType maxLength readOnly longDesc").each(function(A){Element._attributeTranslations.write.names[A.toLowerCase()]=A;Element._attributeTranslations.has[A.toLowerCase()]=A;});(function(A){Object.extend(A,{href:A._getAttr,src:A._getAttr,type:A._getAttr,action:A._getAttrNode,disabled:A._flag,checked:A._flag,readonly:A._flag,multiple:A._flag,onload:A._getEv,onunload:A._getEv,onclick:A._getEv,ondblclick:A._getEv,onmousedown:A._getEv,onmouseup:A._getEv,onmouseover:A._getEv,onmousemove:A._getEv,onmouseout:A._getEv,onfocus:A._getEv,onblur:A._getEv,onkeypress:A._getEv,onkeydown:A._getEv,onkeyup:A._getEv,onsubmit:A._getEv,onreset:A._getEv,onselect:A._getEv,onchange:A._getEv});})(Element._attributeTranslations.read.values);}else{if(Prototype.Browser.Gecko&&/rv:1\.8\.0/.test(navigator.userAgent)){Element.Methods.setOpacity=function(A,B){A=$(A);A.style.opacity=(B==1)?0.999999:(B==="")?"":(B<0.00001)?0:B;return A;};}else{if(Prototype.Browser.WebKit){Element.Methods.setOpacity=function(A,B){A=$(A);A.style.opacity=(B==1||B==="")?"":(B<0.00001)?0:B;if(B==1){if(A.tagName=="IMG"&&A.width){A.width++;A.width--;}else{try{var D=document.createTextNode(" ");A.appendChild(D);A.removeChild(D);}catch(C){}}}return A;};Element.Methods.cumulativeOffset=function(B){var A=0,C=0;do{A+=B.offsetTop||0;C+=B.offsetLeft||0;if(B.offsetParent==document.body){if(Element.getStyle(B,"position")=="absolute"){break;}}B=B.offsetParent;}while(B);return Element._returnOffset(C,A);};}}}}if(Prototype.Browser.IE||Prototype.Browser.Opera){Element.Methods.update=function(B,C){B=$(B);if(C&&C.toElement){C=C.toElement();}if(Object.isElement(C)){return B.update().insert(C);}C=Object.toHTML(C);var A=B.tagName.toUpperCase();if(A in Element._insertionTranslations.tags){$A(B.childNodes).each(function(D){B.removeChild(D);});Element._getContentFromAnonymousElement(A,C.stripScripts()).each(function(D){B.appendChild(D);});}else{B.innerHTML=C.stripScripts();}C.evalScripts.bind(C).defer();return B;};}if(document.createElement("div").outerHTML){Element.Methods.replace=function(C,E){C=$(C);if(E&&E.toElement){E=E.toElement();}if(Object.isElement(E)){C.parentNode.replaceChild(E,C);return C;}E=Object.toHTML(E);var D=C.parentNode,B=D.tagName.toUpperCase();if(Element._insertionTranslations.tags[B]){var F=C.next();var A=Element._getContentFromAnonymousElement(B,E.stripScripts());D.removeChild(C);if(F){A.each(function(G){D.insertBefore(G,F);});}else{A.each(function(G){D.appendChild(G);});}}else{C.outerHTML=E.stripScripts();}E.evalScripts.bind(E).defer();return C;};}Element._returnOffset=function(B,C){var A=[B,C];A.left=B;A.top=C;return A;};Element._getContentFromAnonymousElement=function(C,B){var D=new Element("div"),A=Element._insertionTranslations.tags[C];D.innerHTML=A[0]+B+A[1];A[2].times(function(){D=D.firstChild;});return $A(D.childNodes);};Element._insertionTranslations={before:{adjacency:"beforeBegin",insert:function(A,B){A.parentNode.insertBefore(B,A);},initializeRange:function(B,A){A.setStartBefore(B);}},top:{adjacency:"afterBegin",insert:function(A,B){A.insertBefore(B,A.firstChild);},initializeRange:function(B,A){A.selectNodeContents(B);A.collapse(true);}},bottom:{adjacency:"beforeEnd",insert:function(A,B){A.appendChild(B);}},after:{adjacency:"afterEnd",insert:function(A,B){A.parentNode.insertBefore(B,A.nextSibling);},initializeRange:function(B,A){A.setStartAfter(B);}},tags:{TABLE:["<table>","</table>",1],TBODY:["<table><tbody>","</tbody></table>",2],TR:["<table><tbody><tr>","</tr></tbody></table>",3],TD:["<table><tbody><tr><td>","</td></tr></tbody></table>",4],SELECT:["<select>","</select>",1]}};(function(){this.bottom.initializeRange=this.top.initializeRange;Object.extend(this.tags,{THEAD:this.tags.TBODY,TFOOT:this.tags.TBODY,TH:this.tags.TD});}).call(Element._insertionTranslations);Element.Methods.Simulated={hasAttribute:function(A,C){C=Element._attributeTranslations.has[C]||C;var B=$(A).getAttributeNode(C);return B&&B.specified;}};Element.Methods.ByTag={};Object.extend(Element,Element.Methods);if(!Prototype.BrowserFeatures.ElementExtensions&&document.createElement("div").__proto__){window.HTMLElement={};window.HTMLElement.prototype=document.createElement("div").__proto__;Prototype.BrowserFeatures.ElementExtensions=true;}Element.extend=(function(){if(Prototype.BrowserFeatures.SpecificElementExtensions){return Prototype.K;}var A={},B=Element.Methods.ByTag;var C=Object.extend(function(F){if(!F||F._extendedByPrototype||F.nodeType!=1||F==window){return F;}var D=Object.clone(A),E=F.tagName,H,G;if(B[E]){Object.extend(D,B[E]);}for(H in D){G=D[H];if(Object.isFunction(G)&&!(H in F)){F[H]=G.methodize();}}F._extendedByPrototype=Prototype.emptyFunction;return F;},{refresh:function(){if(!Prototype.BrowserFeatures.ElementExtensions){Object.extend(A,Element.Methods);Object.extend(A,Element.Methods.Simulated);}}});C.refresh();return C;})();Element.hasAttribute=function(A,B){if(A.hasAttribute){return A.hasAttribute(B);}return Element.Methods.Simulated.hasAttribute(A,B);};Element.addMethods=function(C){var I=Prototype.BrowserFeatures,D=Element.Methods.ByTag;if(!C){Object.extend(Form,Form.Methods);Object.extend(Form.Element,Form.Element.Methods);Object.extend(Element.Methods.ByTag,{"FORM":Object.clone(Form.Methods),"INPUT":Object.clone(Form.Element.Methods),"SELECT":Object.clone(Form.Element.Methods),"TEXTAREA":Object.clone(Form.Element.Methods)});}if(arguments.length==2){var B=C;C=arguments[1];}if(!B){Object.extend(Element.Methods,C||{});}else{if(Object.isArray(B)){B.each(H);}else{H(B);}}function H(F){F=F.toUpperCase();if(!Element.Methods.ByTag[F]){Element.Methods.ByTag[F]={};}Object.extend(Element.Methods.ByTag[F],C);}function A(L,K,F){F=F||false;for(var N in L){var M=L[N];if(!Object.isFunction(M)){continue;}if(!F||!(N in K)){K[N]=M.methodize();}}}function E(L){var F;var K={"OPTGROUP":"OptGroup","TEXTAREA":"TextArea","P":"Paragraph","FIELDSET":"FieldSet","UL":"UList","OL":"OList","DL":"DList","DIR":"Directory","H1":"Heading","H2":"Heading","H3":"Heading","H4":"Heading","H5":"Heading","H6":"Heading","Q":"Quote","INS":"Mod","DEL":"Mod","A":"Anchor","IMG":"Image","CAPTION":"TableCaption","COL":"TableCol","COLGROUP":"TableCol","THEAD":"TableSection","TFOOT":"TableSection","TBODY":"TableSection","TR":"TableRow","TH":"TableCell","TD":"TableCell","FRAMESET":"FrameSet","IFRAME":"IFrame"};if(K[L]){F="HTML"+K[L]+"Element";}if(window[F]){return window[F];}F="HTML"+L+"Element";if(window[F]){return window[F];}F="HTML"+L.capitalize()+"Element";if(window[F]){return window[F];}window[F]={};window[F].prototype=document.createElement(L).__proto__;return window[F];}if(I.ElementExtensions){A(Element.Methods,HTMLElement.prototype);A(Element.Methods.Simulated,HTMLElement.prototype,true);}if(I.SpecificElementExtensions){for(var J in Element.Methods.ByTag){var G=E(J);if(Object.isUndefined(G)){continue;}A(D[J],G.prototype);}}Object.extend(Element,Element.Methods);delete Element.ByTag;if(Element.extend.refresh){Element.extend.refresh();}Element.cache={};};document.viewport={getDimensions:function(){var A={};$w("width height").each(function(C){var B=C.capitalize();A[C]=self["inner"+B]||(document.documentElement["client"+B]||document.body["client"+B]);});return A;},getWidth:function(){return this.getDimensions().width;},getHeight:function(){return this.getDimensions().height;},getScrollOffsets:function(){return Element._returnOffset(window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft,window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop);}};var Selector=Class.create({initialize:function(A){this.expression=A.strip();this.compileMatcher();},compileMatcher:function(){if(Prototype.BrowserFeatures.XPath&&!(/(\[[\w-]*?:|:checked)/).test(this.expression)){return this.compileXPathMatcher();}var e=this.expression,ps=Selector.patterns,h=Selector.handlers,c=Selector.criteria,le,p,m;if(Selector._cache[e]){this.matcher=Selector._cache[e];return ;}this.matcher=["this.matcher = function(root) {","var r = root, h = Selector.handlers, c = false, n;"];while(e&&le!=e&&(/\S/).test(e)){le=e;for(var i in ps){p=ps[i];if(m=e.match(p)){this.matcher.push(Object.isFunction(c[i])?c[i](m):new Template(c[i]).evaluate(m));e=e.replace(m[0],"");break;}}}this.matcher.push("return h.unique(n);\n}");eval(this.matcher.join("\n"));Selector._cache[this.expression]=this.matcher;},compileXPathMatcher:function(){var E=this.expression,F=Selector.patterns,B=Selector.xpath,D,A;if(Selector._cache[E]){this.xpath=Selector._cache[E];return ;}this.matcher=[".//*"];while(E&&D!=E&&(/\S/).test(E)){D=E;for(var C in F){if(A=E.match(F[C])){this.matcher.push(Object.isFunction(B[C])?B[C](A):new Template(B[C]).evaluate(A));E=E.replace(A[0],"");break;}}}this.xpath=this.matcher.join("");Selector._cache[this.expression]=this.xpath;},findElements:function(A){A=A||document;if(this.xpath){return document._getElementsByXPath(this.xpath,A);}return this.matcher(A);},match:function(H){this.tokens=[];var L=this.expression,A=Selector.patterns,E=Selector.assertions;var B,D,F;while(L&&B!==L&&(/\S/).test(L)){B=L;for(var I in A){D=A[I];if(F=L.match(D)){if(E[I]){this.tokens.push([I,Object.clone(F)]);L=L.replace(F[0],"");}else{return this.findElements(document).include(H);}}}}var K=true,C,J;for(var I=0,G;G=this.tokens[I];I++){C=G[0],J=G[1];if(!Selector.assertions[C](H,J)){K=false;break;}}return K;},toString:function(){return this.expression;},inspect:function(){return"#<Selector:"+this.expression.inspect()+">";}});Object.extend(Selector,{_cache:{},xpath:{descendant:"//*",child:"/*",adjacent:"/following-sibling::*[1]",laterSibling:"/following-sibling::*",tagName:function(A){if(A[1]=="*"){return"";}return"[local-name()='"+A[1].toLowerCase()+"' or local-name()='"+A[1].toUpperCase()+"']";},className:"[contains(concat(' ', @class, ' '), ' #{1} ')]",id:"[@id='#{1}']",attrPresence:"[@#{1}]",attr:function(A){A[3]=A[5]||A[6];return new Template(Selector.xpath.operators[A[2]]).evaluate(A);},pseudo:function(A){var B=Selector.xpath.pseudos[A[1]];if(!B){return"";}if(Object.isFunction(B)){return B(A);}return new Template(Selector.xpath.pseudos[A[1]]).evaluate(A);},operators:{"=":"[@#{1}='#{3}']","!=":"[@#{1}!='#{3}']","^=":"[starts-with(@#{1}, '#{3}')]","$=":"[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']","*=":"[contains(@#{1}, '#{3}')]","~=":"[contains(concat(' ', @#{1}, ' '), ' #{3} ')]","|=":"[contains(concat('-', @#{1}, '-'), '-#{3}-')]"},pseudos:{"first-child":"[not(preceding-sibling::*)]","last-child":"[not(following-sibling::*)]","only-child":"[not(preceding-sibling::* or following-sibling::*)]","empty":"[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]","checked":"[@checked]","disabled":"[@disabled]","enabled":"[not(@disabled)]","not":function(B){var H=B[6],G=Selector.patterns,A=Selector.xpath,E,B,C;var F=[];while(H&&E!=H&&(/\S/).test(H)){E=H;for(var D in G){if(B=H.match(G[D])){C=Object.isFunction(A[D])?A[D](B):new Template(A[D]).evaluate(B);F.push("("+C.substring(1,C.length-1)+")");H=H.replace(B[0],"");break;}}}return"[not("+F.join(" and ")+")]";},"nth-child":function(A){return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ",A);},"nth-last-child":function(A){return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ",A);},"nth-of-type":function(A){return Selector.xpath.pseudos.nth("position() ",A);},"nth-last-of-type":function(A){return Selector.xpath.pseudos.nth("(last() + 1 - position()) ",A);},"first-of-type":function(A){A[6]="1";return Selector.xpath.pseudos["nth-of-type"](A);},"last-of-type":function(A){A[6]="1";return Selector.xpath.pseudos["nth-last-of-type"](A);},"only-of-type":function(A){var B=Selector.xpath.pseudos;return B["first-of-type"](A)+B["last-of-type"](A);},nth:function(E,C){var F,G=C[6],B;if(G=="even"){G="2n+0";}if(G=="odd"){G="2n+1";}if(F=G.match(/^(\d+)$/)){return"["+E+"= "+F[1]+"]";}if(F=G.match(/^(-?\d*)?n(([+-])(\d+))?/)){if(F[1]=="-"){F[1]=-1;}var D=F[1]?Number(F[1]):1;var A=F[2]?Number(F[2]):0;B="[((#{fragment} - #{b}) mod #{a} = 0) and ((#{fragment} - #{b}) div #{a} >= 0)]";return new Template(B).evaluate({fragment:E,a:D,b:A});}}}},criteria:{tagName:'n = h.tagName(n, r, "#{1}", c); c = false;',className:'n = h.className(n, r, "#{1}", c); c = false;',id:'n = h.id(n, r, "#{1}", c); c = false;',attrPresence:'n = h.attrPresence(n, r, "#{1}"); c = false;',attr:function(A){A[3]=(A[5]||A[6]);return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(A);},pseudo:function(A){if(A[6]){A[6]=A[6].replace(/"/g,'\\"');}return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(A);},descendant:'c = "descendant";',child:'c = "child";',adjacent:'c = "adjacent";',laterSibling:'c = "laterSibling";'},patterns:{laterSibling:/^\s*~\s*/,child:/^\s*>\s*/,adjacent:/^\s*\+\s*/,descendant:/^\s/,tagName:/^\s*(\*|[\w\-]+)(\b|$)?/,id:/^#([\w\-\*]+)(\b|$)/,className:/^\.([\w\-\*]+)(\b|$)/,pseudo:/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,attrPresence:/^\[([\w]+)\]/,attr:/\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/},assertions:{tagName:function(A,B){return B[1].toUpperCase()==A.tagName.toUpperCase();},className:function(A,B){return Element.hasClassName(A,B[1]);},id:function(A,B){return A.id===B[1];},attrPresence:function(A,B){return Element.hasAttribute(A,B[1]);},attr:function(B,C){var A=Element.readAttribute(B,C[1]);return Selector.operators[C[2]](A,C[3]);}},handlers:{concat:function(B,A){for(var C=0,D;D=A[C];C++){B.push(D);}return B;},mark:function(A){for(var B=0,C;C=A[B];B++){C._counted=true;}return A;},unmark:function(A){for(var B=0,C;C=A[B];B++){C._counted=undefined;}return A;},index:function(A,D,G){A._counted=true;if(D){for(var B=A.childNodes,E=B.length-1,C=1;E>=0;E--){var F=B[E];if(F.nodeType==1&&(!G||F._counted)){F.nodeIndex=C++;}}}else{for(var E=0,C=1,B=A.childNodes;F=B[E];E++){if(F.nodeType==1&&(!G||F._counted)){F.nodeIndex=C++;}}}},unique:function(B){if(B.length==0){return B;}var D=[],E;for(var C=0,A=B.length;C<A;C++){if(!(E=B[C])._counted){E._counted=true;D.push(Element.extend(E));}}return Selector.handlers.unmark(D);},descendant:function(A){var D=Selector.handlers;for(var C=0,B=[],E;E=A[C];C++){D.concat(B,E.getElementsByTagName("*"));}return B;},child:function(A){var F=Selector.handlers;for(var E=0,D=[],G;G=A[E];E++){for(var B=0,C=[],H;H=G.childNodes[B];B++){if(H.nodeType==1&&H.tagName!="!"){D.push(H);}}}return D;},adjacent:function(A){for(var C=0,B=[],E;E=A[C];C++){var D=this.nextElementSibling(E);if(D){B.push(D);}}return B;},laterSibling:function(A){var D=Selector.handlers;for(var C=0,B=[],E;E=A[C];C++){D.concat(B,Element.nextSiblings(E));}return B;},nextElementSibling:function(A){while(A=A.nextSibling){if(A.nodeType==1){return A;}}return null;},previousElementSibling:function(A){while(A=A.previousSibling){if(A.nodeType==1){return A;}}return null;},tagName:function(B,A,E,H){E=E.toUpperCase();var D=[],F=Selector.handlers;if(B){if(H){if(H=="descendant"){for(var C=0,G;G=B[C];C++){F.concat(D,G.getElementsByTagName(E));}return D;}else{B=this[H](B);}if(E=="*"){return B;}}for(var C=0,G;G=B[C];C++){if(G.tagName.toUpperCase()==E){D.push(G);}}return D;}else{return A.getElementsByTagName(E);}},id:function(B,A,H,F){var G=$(H),D=Selector.handlers;if(!G){return[];}if(!B&&A==document){return[G];}if(B){if(F){if(F=="child"){for(var C=0,E;E=B[C];C++){if(G.parentNode==E){return[G];}}}else{if(F=="descendant"){for(var C=0,E;E=B[C];C++){if(Element.descendantOf(G,E)){return[G];}}}else{if(F=="adjacent"){for(var C=0,E;E=B[C];C++){if(Selector.handlers.previousElementSibling(G)==E){return[G];}}}else{B=D[F](B);}}}}for(var C=0,E;E=B[C];C++){if(E==G){return[G];}}return[];}return(G&&Element.descendantOf(G,A))?[G]:[];},className:function(B,A,C,D){if(B&&D){B=this[D](B);}return Selector.handlers.byClassName(B,A,C);},byClassName:function(C,B,F){if(!C){C=Selector.handlers.descendant([B]);}var H=" "+F+" ";for(var E=0,D=[],G,A;G=C[E];E++){A=G.className;if(A.length==0){continue;}if(A==F||(" "+A+" ").include(H)){D.push(G);}}return D;},attrPresence:function(C,B,A){if(!C){C=B.getElementsByTagName("*");}var E=[];for(var D=0,F;F=C[D];D++){if(Element.hasAttribute(F,A)){E.push(F);}}return E;},attr:function(A,H,G,I,B){if(!A){A=H.getElementsByTagName("*");}var J=Selector.operators[B],D=[];for(var E=0,C;C=A[E];E++){var F=Element.readAttribute(C,G);if(F===null){continue;}if(J(F,I)){D.push(C);}}return D;},pseudo:function(B,C,E,A,D){if(B&&D){B=this[D](B);}if(!B){B=A.getElementsByTagName("*");}return Selector.pseudos[C](B,E,A);}},pseudos:{"first-child":function(B,F,A){for(var D=0,C=[],E;E=B[D];D++){if(Selector.handlers.previousElementSibling(E)){continue;}C.push(E);}return C;},"last-child":function(B,F,A){for(var D=0,C=[],E;E=B[D];D++){if(Selector.handlers.nextElementSibling(E)){continue;}C.push(E);}return C;},"only-child":function(B,G,A){var E=Selector.handlers;for(var D=0,C=[],F;F=B[D];D++){if(!E.previousElementSibling(F)&&!E.nextElementSibling(F)){C.push(F);}}return C;},"nth-child":function(B,C,A){return Selector.pseudos.nth(B,C,A);},"nth-last-child":function(B,C,A){return Selector.pseudos.nth(B,C,A,true);},"nth-of-type":function(B,C,A){return Selector.pseudos.nth(B,C,A,false,true);},"nth-last-of-type":function(B,C,A){return Selector.pseudos.nth(B,C,A,true,true);},"first-of-type":function(B,C,A){return Selector.pseudos.nth(B,"1",A,false,true);},"last-of-type":function(B,C,A){return Selector.pseudos.nth(B,"1",A,true,true);},"only-of-type":function(B,D,A){var C=Selector.pseudos;return C["last-of-type"](C["first-of-type"](B,D,A),D,A);},getIndices:function(B,A,C){if(B==0){return A>0?[A]:[];}return $R(1,C).inject([],function(D,E){if(0==(E-A)%B&&(E-A)/B>=0){D.push(E);}return D;});},nth:function(A,L,N,K,C){if(A.length==0){return[];}if(L=="even"){L="2n+0";}if(L=="odd"){L="2n+1";}var J=Selector.handlers,I=[],B=[],E;J.mark(A);for(var H=0,D;D=A[H];H++){if(!D.parentNode._counted){J.index(D.parentNode,K,C);B.push(D.parentNode);}}if(L.match(/^\d+$/)){L=Number(L);for(var H=0,D;D=A[H];H++){if(D.nodeIndex==L){I.push(D);}}}else{if(E=L.match(/^(-?\d*)?n(([+-])(\d+))?/)){if(E[1]=="-"){E[1]=-1;}var O=E[1]?Number(E[1]):1;var M=E[2]?Number(E[2]):0;var P=Selector.pseudos.getIndices(O,M,A.length);for(var H=0,D,F=P.length;D=A[H];H++){for(var G=0;G<F;G++){if(D.nodeIndex==P[G]){I.push(D);}}}}}J.unmark(A);J.unmark(B);return I;},"empty":function(B,F,A){for(var D=0,C=[],E;E=B[D];D++){if(E.tagName=="!"||(E.firstChild&&!E.innerHTML.match(/^\s*$/))){continue;}C.push(E);}return C;},"not":function(A,D,I){var G=Selector.handlers,J,C;var H=new Selector(D).findElements(I);G.mark(H);for(var F=0,E=[],B;B=A[F];F++){if(!B._counted){E.push(B);}}G.unmark(H);return E;},"enabled":function(B,F,A){for(var D=0,C=[],E;E=B[D];D++){if(!E.disabled){C.push(E);}}return C;},"disabled":function(B,F,A){for(var D=0,C=[],E;E=B[D];D++){if(E.disabled){C.push(E);}}return C;},"checked":function(B,F,A){for(var D=0,C=[],E;E=B[D];D++){if(E.checked){C.push(E);}}return C;}},operators:{"=":function(B,A){return B==A;},"!=":function(B,A){return B!=A;},"^=":function(B,A){return B.startsWith(A);},"$=":function(B,A){return B.endsWith(A);},"*=":function(B,A){return B.include(A);},"~=":function(B,A){return(" "+B+" ").include(" "+A+" ");},"|=":function(B,A){return("-"+B.toUpperCase()+"-").include("-"+A.toUpperCase()+"-");}},matchElements:function(F,G){var E=new Selector(G).findElements(),D=Selector.handlers;D.mark(E);for(var C=0,B=[],A;A=F[C];C++){if(A._counted){B.push(A);}}D.unmark(E);return B;},findElement:function(B,C,A){if(Object.isNumber(C)){A=C;C=false;}return Selector.matchElements(B,C||"*")[A||0];},findChildElements:function(E,G){var H=G.join(","),G=[];H.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/,function(I){G.push(I[1].strip());});var D=[],F=Selector.handlers;for(var C=0,B=G.length,A;C<B;C++){A=new Selector(G[C].strip());F.concat(D,A.findElements(E));}return(B>1)?F.unique(D):D;}});function $$(){return Selector.findChildElements(document,$A(arguments));}var Form={reset:function(A){$(A).reset();return A;},serializeElements:function(G,B){if(typeof B!="object"){B={hash:!!B};}else{if(B.hash===undefined){B.hash=true;}}var C,F,A=false,E=B.submit;var D=G.inject({},function(H,I){if(!I.disabled&&I.name){C=I.name;F=$(I).getValue();if(F!=null&&(I.type!="submit"||(!A&&E!==false&&(!E||C==E)&&(A=true)))){if(C in H){if(!Object.isArray(H[C])){H[C]=[H[C]];}H[C].push(F);}else{H[C]=F;}}}return H;});return B.hash?D:Object.toQueryString(D);}};Form.Methods={serialize:function(B,A){return Form.serializeElements(Form.getElements(B),A);},getElements:function(A){return $A($(A).getElementsByTagName("*")).inject([],function(B,C){if(Form.Element.Serializers[C.tagName.toLowerCase()]){B.push(Element.extend(C));}return B;});},getInputs:function(G,C,D){G=$(G);var A=G.getElementsByTagName("input");if(!C&&!D){return $A(A).map(Element.extend);}for(var E=0,H=[],F=A.length;E<F;E++){var B=A[E];if((C&&B.type!=C)||(D&&B.name!=D)){continue;}H.push(Element.extend(B));}return H;},disable:function(A){A=$(A);Form.getElements(A).invoke("disable");return A;},enable:function(A){A=$(A);Form.getElements(A).invoke("enable");return A;},findFirstElement:function(B){var C=$(B).getElements().findAll(function(D){return"hidden"!=D.type&&!D.disabled;});var A=C.findAll(function(D){return D.hasAttribute("tabIndex")&&D.tabIndex>=0;}).sortBy(function(D){return D.tabIndex;}).first();return A?A:C.find(function(D){return["input","select","textarea"].include(D.tagName.toLowerCase());});},focusFirstElement:function(A){A=$(A);A.findFirstElement().activate();return A;},request:function(B,A){B=$(B),A=Object.clone(A||{});var D=A.parameters,C=B.readAttribute("action")||"";if(C.blank()){C=window.location.href;}A.parameters=B.serialize(true);if(D){if(Object.isString(D)){D=D.toQueryParams();}Object.extend(A.parameters,D);}if(B.hasAttribute("method")&&!A.method){A.method=B.method;}return new Ajax.Request(C,A);}};Form.Element={focus:function(A){$(A).focus();return A;},select:function(A){$(A).select();return A;}};Form.Element.Methods={serialize:function(A){A=$(A);if(!A.disabled&&A.name){var B=A.getValue();if(B!=undefined){var C={};C[A.name]=B;return Object.toQueryString(C);}}return"";},getValue:function(A){A=$(A);var B=A.tagName.toLowerCase();return Form.Element.Serializers[B](A);},setValue:function(A,B){A=$(A);var C=A.tagName.toLowerCase();Form.Element.Serializers[C](A,B);return A;},clear:function(A){$(A).value="";return A;},present:function(A){return $(A).value!="";},activate:function(A){A=$(A);try{A.focus();if(A.select&&(A.tagName.toLowerCase()!="input"||!["button","reset","submit"].include(A.type))){A.select();}}catch(B){}return A;},disable:function(A){A=$(A);A.blur();A.disabled=true;return A;},enable:function(A){A=$(A);A.disabled=false;return A;}};var Field=Form.Element;var $F=Form.Element.Methods.getValue;Form.Element.Serializers={input:function(A,B){switch(A.type.toLowerCase()){case"checkbox":case"radio":return Form.Element.Serializers.inputSelector(A,B);default:return Form.Element.Serializers.textarea(A,B);}},inputSelector:function(A,B){if(B===undefined){return A.checked?A.value:null;}else{A.checked=!!B;}},textarea:function(A,B){if(B===undefined){return A.value;}else{A.value=B;}},select:function(D,A){if(A===undefined){return this[D.type=="select-one"?"selectOne":"selectMany"](D);}else{var C,F,G=!Object.isArray(A);for(var B=0,E=D.length;B<E;B++){C=D.options[B];F=this.optionValue(C);if(G){if(F==A){C.selected=true;return ;}}else{C.selected=A.include(F);}}}},selectOne:function(B){var A=B.selectedIndex;return A>=0?this.optionValue(B.options[A]):null;},selectMany:function(D){var A,E=D.length;if(!E){return null;}for(var C=0,A=[];C<E;C++){var B=D.options[C];if(B.selected){A.push(this.optionValue(B));}}return A;},optionValue:function(A){return Element.extend(A).hasAttribute("value")?A.value:A.text;}};Abstract.TimedObserver=Class.create(PeriodicalExecuter,{initialize:function($super,A,B,C){$super(C,B);this.element=$(A);this.lastValue=this.getValue();},execute:function(){var A=this.getValue();if(Object.isString(this.lastValue)&&Object.isString(A)?this.lastValue!=A:String(this.lastValue)!=String(A)){this.callback(this.element,A);this.lastValue=A;}}});Form.Element.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.Element.getValue(this.element);}});Form.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.serialize(this.element);}});Abstract.EventObserver=Class.create({initialize:function(A,B){this.element=$(A);this.callback=B;this.lastValue=this.getValue();if(this.element.tagName.toLowerCase()=="form"){this.registerFormCallbacks();}else{this.registerCallback(this.element);}},onElementEvent:function(){var A=this.getValue();if(this.lastValue!=A){this.callback(this.element,A);this.lastValue=A;}},registerFormCallbacks:function(){Form.getElements(this.element).each(this.registerCallback,this);},registerCallback:function(A){if(A.type){switch(A.type.toLowerCase()){case"checkbox":case"radio":Event.observe(A,"click",this.onElementEvent.bind(this));break;default:Event.observe(A,"change",this.onElementEvent.bind(this));break;}}}});Form.Element.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.Element.getValue(this.element);}});Form.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.serialize(this.element);}});if(!window.Event){var Event={};}Object.extend(Event,{KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,KEY_HOME:36,KEY_END:35,KEY_PAGEUP:33,KEY_PAGEDOWN:34,KEY_INSERT:45,cache:{},relatedTarget:function(B){var A;switch(B.type){case"mouseover":A=B.fromElement;break;case"mouseout":A=B.toElement;break;default:return null;}return Element.extend(A);}});Event.Methods=(function(){var A;if(Prototype.Browser.IE){var B={0:1,1:4,2:2};A=function(D,C){return D.button==B[C];};}else{if(Prototype.Browser.WebKit){A=function(D,C){switch(C){case 0:return D.which==1&&!D.metaKey;case 1:return D.which==1&&D.metaKey;default:return false;}};}else{A=function(D,C){return D.which?(D.which===C+1):(D.button===C);};}}return{isLeftClick:function(C){return A(C,0);},isMiddleClick:function(C){return A(C,1);},isRightClick:function(C){return A(C,2);},element:function(D){var C=Event.extend(D).target;return Element.extend(C.nodeType==Node.TEXT_NODE?C.parentNode:C);},findElement:function(D,E){var C=Event.element(D);return C.match(E)?C:C.up(E);},pointer:function(C){return{x:C.pageX||(C.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft)),y:C.pageY||(C.clientY+(document.documentElement.scrollTop||document.body.scrollTop))};},pointerX:function(C){return Event.pointer(C).x;},pointerY:function(C){return Event.pointer(C).y;},stop:function(C){Event.extend(C);C.preventDefault();C.stopPropagation();C.stopped=true;}};})();Event.extend=(function(){var A=Object.keys(Event.Methods).inject({},function(B,C){B[C]=Event.Methods[C].methodize();return B;});if(Prototype.Browser.IE){Object.extend(A,{stopPropagation:function(){this.cancelBubble=true;},preventDefault:function(){this.returnValue=false;},inspect:function(){return"[object Event]";}});return function(B){if(!B){return false;}if(B._extendedByPrototype){return B;}B._extendedByPrototype=Prototype.emptyFunction;var C=Event.pointer(B);Object.extend(B,{target:B.srcElement,relatedTarget:Event.relatedTarget(B),pageX:C.x,pageY:C.y});return Object.extend(B,A);};}else{Event.prototype=Event.prototype||document.createEvent("HTMLEvents").__proto__;Object.extend(Event.prototype,A);return Prototype.K;}})();Object.extend(Event,(function(){var B=Event.cache;function C(J){if(J._eventID){return J._eventID;}arguments.callee.id=arguments.callee.id||1;return J._eventID=++arguments.callee.id;}function G(J){if(J&&J.include(":")){return"dataavailable";}return J;}function A(J){return B[J]=B[J]||{};}function F(L,J){var K=A(L);return K[J]=K[J]||[];}function H(K,J,L){var O=C(K);var N=F(O,J);if(N.pluck("handler").include(L)){return false;}var M=function(P){if(!Event||!Event.extend||(P.eventName&&P.eventName!=J)){return false;}Event.extend(P);L.call(K,P);};M.handler=L;N.push(M);return M;}function I(M,J,K){var L=F(M,J);return L.find(function(N){return N.handler==K;});}function D(M,J,K){var L=A(M);if(!L[J]){return false;}L[J]=L[J].without(I(M,J,K));}function E(){for(var K in B){for(var J in B[K]){B[K][J]=null;}}}if(window.attachEvent){window.attachEvent("onunload",E);}return{observe:function(L,J,M){L=$(L);var K=G(J);var N=H(L,J,M);if(!N){return L;}if(L.addEventListener){L.addEventListener(K,N,false);}else{L.attachEvent("on"+K,N);}return L;},stopObserving:function(L,J,M){L=$(L);var O=C(L),K=G(J);if(!M&&J){F(O,J).each(function(P){L.stopObserving(J,P.handler);});return L;}else{if(!J){Object.keys(A(O)).each(function(P){L.stopObserving(P);});return L;}}var N=I(O,J,M);if(!N){return L;}if(L.removeEventListener){L.removeEventListener(K,N,false);}else{L.detachEvent("on"+K,N);}D(O,J,M);return L;},fire:function(L,K,J){L=$(L);if(L==document&&document.createEvent&&!L.dispatchEvent){L=document.documentElement;}if(document.createEvent){var M=document.createEvent("HTMLEvents");M.initEvent("dataavailable",true,true);}else{var M=document.createEventObject();M.eventType="ondataavailable";}M.eventName=K;M.memo=J||{};if(document.createEvent){L.dispatchEvent(M);}else{L.fireEvent(M.eventType,M);}return M;}};})());Object.extend(Event,Event.Methods);Element.addMethods({fire:Event.fire,observe:Event.observe,stopObserving:Event.stopObserving});Object.extend(document,{fire:Element.Methods.fire.methodize(),observe:Element.Methods.observe.methodize(),stopObserving:Element.Methods.stopObserving.methodize()});(function(){var C,B=false;function A(){if(B){return ;}if(C){window.clearInterval(C);}document.fire("dom:loaded");B=true;}if(document.addEventListener){if(Prototype.Browser.WebKit){C=window.setInterval(function(){if(/loaded|complete/.test(document.readyState)){A();}},0);Event.observe(window,"load",A);}else{document.addEventListener("DOMContentLoaded",A,false);}}else{document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");$("__onDOMContentLoaded").onreadystatechange=function(){if(this.readyState=="complete"){this.onreadystatechange=null;A();}};}})();Hash.toQueryString=Object.toQueryString;var Toggle={display:Element.toggle};Element.Methods.childOf=Element.Methods.descendantOf;var Insertion={Before:function(A,B){return Element.insert(A,{before:B});},Top:function(A,B){return Element.insert(A,{top:B});},Bottom:function(A,B){return Element.insert(A,{bottom:B});},After:function(A,B){return Element.insert(A,{after:B});}};var $continue=new Error('"throw $continue" is deprecated, use "return" instead');var Position={includeScrollOffsets:false,prepare:function(){this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;},within:function(B,A,C){if(this.includeScrollOffsets){return this.withinIncludingScrolloffsets(B,A,C);}this.xcomp=A;this.ycomp=C;this.offset=Element.cumulativeOffset(B);return(C>=this.offset[1]&&C<this.offset[1]+B.offsetHeight&&A>=this.offset[0]&&A<this.offset[0]+B.offsetWidth);},withinIncludingScrolloffsets:function(B,A,D){var C=Element.cumulativeScrollOffset(B);this.xcomp=A+C[0]-this.deltaX;this.ycomp=D+C[1]-this.deltaY;this.offset=Element.cumulativeOffset(B);return(this.ycomp>=this.offset[1]&&this.ycomp<this.offset[1]+B.offsetHeight&&this.xcomp>=this.offset[0]&&this.xcomp<this.offset[0]+B.offsetWidth);},overlap:function(B,A){if(!B){return 0;}if(B=="vertical"){return((this.offset[1]+A.offsetHeight)-this.ycomp)/A.offsetHeight;}if(B=="horizontal"){return((this.offset[0]+A.offsetWidth)-this.xcomp)/A.offsetWidth;}},cumulativeOffset:Element.Methods.cumulativeOffset,positionedOffset:Element.Methods.positionedOffset,absolutize:function(A){Position.prepare();return Element.absolutize(A);},relativize:function(A){Position.prepare();return Element.relativize(A);},realOffset:Element.Methods.cumulativeScrollOffset,offsetParent:Element.Methods.getOffsetParent,page:Element.Methods.viewportOffset,clone:function(B,C,A){A=A||{};return Element.clonePosition(C,B,A);}};if(!document.getElementsByClassName){document.getElementsByClassName=function(B){function A(C){return C.blank()?null:"[contains(concat(' ', @class, ' '), ' "+C+" ')]";}B.getElementsByClassName=Prototype.BrowserFeatures.XPath?function(C,E){E=E.toString().strip();var D=/\s/.test(E)?$w(E).map(A).join(""):A(E);return D?document._getElementsByXPath(".//*"+D,C):[];}:function(E,F){F=F.toString().strip();var G=[],H=(/\s/.test(F)?$w(F):null);if(!H&&!F){return G;}var C=$(E).getElementsByTagName("*");F=" "+F+" ";for(var D=0,J,I;J=C[D];D++){if(J.className&&(I=" "+J.className+" ")&&(I.include(F)||(H&&H.all(function(K){return !K.toString().blank()&&I.include(" "+K+" ");})))){G.push(Element.extend(J));}}return G;};return function(D,C){return $(C||document.body).getElementsByClassName(D);};}(Element.Methods);}Element.ClassNames=Class.create();Element.ClassNames.prototype={initialize:function(A){this.element=$(A);},_each:function(A){this.element.className.split(/\s+/).select(function(B){return B.length>0;})._each(A);},set:function(A){this.element.className=A;},add:function(A){if(this.include(A)){return ;}this.set($A(this).concat(A).join(" "));},remove:function(A){if(!this.include(A)){return ;}this.set($A(this).without(A).join(" "));},toString:function(){return $A(this).join(" ");}};Object.extend(Element.ClassNames.prototype,Enumerable);Element.addMethods();
/*
* Really easy field validation with Prototype
* http://tetlaw.id.au/view/javascript/really-easy-field-validation
* Andrew Tetlaw
* Version 1.5.4.1 (2007-01-05)
*
* Copyright (c) 2007 Andrew Tetlaw
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
var Validator = Class.create();

Validator.prototype = {
 initialize : function(className, error, test, options) {
 if(typeof test == 'function'){
 this.options = $H(options);
 this._test = test;
 } else {
 this.options = $H(test);
 this._test = function(){return true};
 }
 this.error = error || 'Validation failed.';
 this.className = className;
 },
 test : function(v, elm) {
 return (this._test(v,elm) && this.options.all(function(p){
 return Validator.methods[p.key] ? Validator.methods[p.key](v,elm,p.value) : true;
 }));
 }
}
Validator.methods = {
 pattern : function(v,elm,opt) {return Validation.get('IsEmpty').test(v) || opt.test(v)},
 minLength : function(v,elm,opt) {return v.length >= opt},
 maxLength : function(v,elm,opt) {return v.length <= opt},
 min : function(v,elm,opt) {return v >= parseFloat(opt)},
 max : function(v,elm,opt) {return v <= parseFloat(opt)},
 notOneOf : function(v,elm,opt) {return $A(opt).all(function(value) {
 return v != value;
 })},
 oneOf : function(v,elm,opt) {return $A(opt).any(function(value) {
 return v == value;
 })},
 is : function(v,elm,opt) {return v == opt},
 isNot : function(v,elm,opt) {return v != opt},
 equalToField : function(v,elm,opt) {return v == $F(opt)},
 notEqualToField : function(v,elm,opt) {return v != $F(opt)},
 include : function(v,elm,opt) {return $A(opt).all(function(value) {
 return Validation.get(value).test(v,elm);
 })}
}

var Validation = Class.create();

Validation.prototype = {
 initialize : function(form, options){
 this.form = $(form);
 if (!this.form) {
 return;
 }
 this.options = Object.extend({
 onSubmit : true,
 stopOnFirst : false,
 immediate : false,
 focusOnError : true,
 useTitles : false,
 onFormValidate : function(result, form) {},
 onElementValidate : function(result, elm) {}
 }, options || {});
 if(this.options.onSubmit) Event.observe(this.form,'submit',this.onSubmit.bind(this),false);
 if(this.options.immediate) {
 var useTitles = this.options.useTitles;
 var callback = this.options.onElementValidate;
 Form.getElements(this.form).each(function(input) { // Thanks Mike!
 Event.observe(input, 'blur', function(ev) { Validation.validate(Event.element(ev),{useTitle : useTitles, onElementValidate : callback}); });
 });
 }
 },
 onSubmit : function(ev){
 if(!this.validate()) Event.stop(ev);
 },
 validate : function() {
 var result = false;
 var useTitles = this.options.useTitles;
 var callback = this.options.onElementValidate;
 try {
 if(this.options.stopOnFirst) {
 result = Form.getElements(this.form).all(function(elm) { return Validation.validate(elm,{useTitle : useTitles, onElementValidate : callback}); });
 } else {
 result = Form.getElements(this.form).collect(function(elm) { return Validation.validate(elm,{useTitle : useTitles, onElementValidate : callback}); }).all();
 }
 } catch (e) {

 }
 if(!result && this.options.focusOnError) {
 try{
 Form.getElements(this.form).findAll(function(elm){return $(elm).hasClassName('validation-failed')}).first().focus()
 }
 catch(e){

 }
 }
 this.options.onFormValidate(result, this.form);
 return result;
 },
 reset : function() {
 Form.getElements(this.form).each(Validation.reset);
 }
}

Object.extend(Validation, {
 validate : function(elm, options){
 options = Object.extend({
 useTitle : false,
 onElementValidate : function(result, elm) {}
 }, options || {});
 elm = $(elm);

 var cn = $w(elm.className);
 return result = cn.all(function(value) {
 var test = Validation.test(value,elm,options.useTitle);
 options.onElementValidate(test, elm);
 return test;
 });
 },
 insertAdvice : function(elm, advice){
 var container = $(elm).up('.field-row');
 if(container){
 Element.insert(container, {after: advice});
 }
 else if (elm.advaiceContainer && $(elm.advaiceContainer)) {
 $(elm.advaiceContainer).update(advice);
 }
 else {
 switch (elm.type.toLowerCase()) {
 case 'checkbox':
 case 'radio':
 var p = elm.parentNode;
 if(p) {
 Element.insert(p, {'bottom': advice});
 } else {
 Element.insert(elm, {'after': advice});
 }
 break;
 default:
 Element.insert(elm, {'after': advice});
 }
 }
 },
 showAdvice : function(elm, advice, adviceName){
 if(!elm.advices){
 elm.advices = new Hash();
 }
 else{
 elm.advices.each(function(pair){
 this.hideAdvice(elm, pair.value);
 }.bind(this));
 }
 elm.advices.set(adviceName, advice);
 if(typeof Effect == 'undefined') {
 advice.style.display = 'block';
 } else {
 if(!advice._adviceAbsolutize) {
 new Effect.Appear(advice, {duration : 1 });
 } else {
 Position.absolutize(advice);
 advice.show();
 advice.setStyle({
 'top':advice._adviceTop,
 'left': advice._adviceLeft,
 'width': advice._adviceWidth,
 'z-index': 1000
 });
 advice.addClassName('advice-absolute');
 }
 }
 },
 hideAdvice : function(elm, advice){
 if(advice != null) advice.hide();
 },
 updateCallback : function(elm, status) {
 if (typeof elm.callbackFunction != 'undefined') {
 eval(elm.callbackFunction+'(\''+elm.id+'\',\''+status+'\')');
 }
 },
 ajaxError : function(elm, errorMsg) {
 var name = 'validate-ajax';
 var advice = Validation.getAdvice(name, elm);
 if (advice == null) {
 advice = this.createAdvice(name, elm, false, errorMsg);
 }
 this.showAdvice(elm, advice, 'validate-ajax');
 this.updateCallback(elm, 'failed');

 elm.addClassName('validation-failed');
 elm.addClassName('validate-ajax');
 },
 test : function(name, elm, useTitle) {
 var v = Validation.get(name);
 var prop = '__advice'+name.camelize();
 try {
 if(Validation.isVisible(elm) && !v.test($F(elm), elm)) {
 //if(!elm[prop]) {
 var advice = Validation.getAdvice(name, elm);
 if (advice == null) {
 advice = this.createAdvice(name, elm, useTitle);
 }
 this.showAdvice(elm, advice, name);
 this.updateCallback(elm, 'failed');
 //}
 elm[prop] = 1;
 if (!elm.advaiceContainer) {
 elm.removeClassName('validation-passed');
 elm.addClassName('validation-failed');
 }
 return false;
 } else {
 var advice = Validation.getAdvice(name, elm);
 this.hideAdvice(elm, advice);
 this.updateCallback(elm, 'passed');
 elm[prop] = '';
 elm.removeClassName('validation-failed');
 elm.addClassName('validation-passed');
 return true;
 }
 } catch(e) {
 throw(e)
 }
 },
 isVisible : function(elm) {
 while(elm.tagName != 'BODY') {
 if(!$(elm).visible()) return false;
 elm = elm.parentNode;
 }
 return true;
 },
 getAdvice : function(name, elm) {
 return $('advice-' + name + '-' + Validation.getElmID(elm)) || $('advice-' + Validation.getElmID(elm));
 },
 createAdvice : function(name, elm, useTitle, customError) {
 var v = Validation.get(name);
 var errorMsg = useTitle ? ((elm && elm.title) ? elm.title : v.error) : v.error;
 if (customError) {
 errorMsg = customError;
 }
 try {
 if (Translator){
 errorMsg = Translator.translate(errorMsg);
 }
 }
 catch(e){}

 advice = '<div class="validation-advice" id="advice-' + name + '-' + Validation.getElmID(elm) +'" style="display:none">' + errorMsg + '</div>'


 Validation.insertAdvice(elm, advice);
 advice = Validation.getAdvice(name, elm);
 if($(elm).hasClassName('absolute-advice')) {
 var dimensions = $(elm).getDimensions();
 var originalPosition = Position.cumulativeOffset(elm);

 advice._adviceTop = (originalPosition[1] + dimensions.height) + 'px';
 advice._adviceLeft = (originalPosition[0]) + 'px';
 advice._adviceWidth = (dimensions.width) + 'px';
 advice._adviceAbsolutize = true;
 }
 return advice;
 },
 getElmID : function(elm) {
 return elm.id ? elm.id : elm.name;
 },
 reset : function(elm) {
 elm = $(elm);
 var cn = $w(elm.className);
 cn.each(function(value) {
 var prop = '__advice'+value.camelize();
 if(elm[prop]) {
 var advice = Validation.getAdvice(value, elm);
 advice.hide();
 elm[prop] = '';
 }
 elm.removeClassName('validation-failed');
 elm.removeClassName('validation-passed');
 });
 },
 add : function(className, error, test, options) {
 var nv = {};
 nv[className] = new Validator(className, error, test, options);
 Object.extend(Validation.methods, nv);
 },
 addAllThese : function(validators) {
 var nv = {};
 $A(validators).each(function(value) {
 nv[value[0]] = new Validator(value[0], value[1], value[2], (value.length > 3 ? value[3] : {}));
 });
 Object.extend(Validation.methods, nv);
 },
 get : function(name) {
 return Validation.methods[name] ? Validation.methods[name] : Validation.methods['_LikeNoIDIEverSaw_'];
 },
 methods : {
 '_LikeNoIDIEverSaw_' : new Validator('_LikeNoIDIEverSaw_','',{})
 }
});

Validation.add('IsEmpty', '', function(v) {
 return (v == '' || (v == null) || (v.length == 0) || /^\s+$/.test(v)); // || /^\s+$/.test(v));
});

Validation.addAllThese([
 ['validate-select', 'Please select an option.', function(v) {
 return ((v != "none") && (v != null) && (v.length != 0));
 }],
 ['required-entry', 'This is a required field.', function(v) {
 return !Validation.get('IsEmpty').test(v);
 }],
 ['validate-number', 'Please enter a valid number in this field.', function(v) {
 return Validation.get('IsEmpty').test(v) || (!isNaN(parseNumber(v)) && !/^\s+$/.test(parseNumber(v)));
 }],
 ['validate-digits', 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.', function(v) {
 return Validation.get('IsEmpty').test(v) || !/[^\d]/.test(v);
 }],
 ['validate-alpha', 'Please use letters only (a-z or A-Z) in this field.', function (v) {
 return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)
 }],
 ['validate-code', 'Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.', function (v) {
 return Validation.get('IsEmpty').test(v) || /^[a-z]+[a-z0-9_]+$/.test(v)
 }],
 ['validate-alphanum', 'Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed.', function(v) {
 return Validation.get('IsEmpty').test(v) || /^[a-zA-Z0-9]+$/.test(v) /*!/\W/.test(v)*/
 }],
 ['validate-street', 'Please use only letters (a-z or A-Z) or numbers (0-9) or spaces and # only in this field.', function(v) {
 return Validation.get('IsEmpty').test(v) || /^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(v)
 }],
 ['validate-phoneStrict', 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.', function(v) {
 return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v);
 }],
 ['validate-phoneLax', 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.', function(v) {
 return Validation.get('IsEmpty').test(v) || /^((\d[-. ]?)?((\(\d{3}\))|\d{3}))?[-. ]?\d{3}[-. ]?\d{4}$/.test(v);
 }],
 ['validate-fax', 'Please enter a valid fax number. For example (123) 456-7890 or 123-456-7890.', function(v) {
 return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v);
 }],
 ['validate-date', 'Please enter a valid date.', function(v) {
 var test = new Date(v);
 return Validation.get('IsEmpty').test(v) || !isNaN(test);
 }],
 ['validate-email', 'Please enter a valid email address. For example johndoe@domain.com.', function (v) {
 //return Validation.get('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)
 //return Validation.get('IsEmpty').test(v) || /^[\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9][\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9\.]{1,30}[\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9]@([a-z0-9_-]{1,30}\.){1,5}[a-z]{2,4}$/i.test(v)
 return Validation.get('IsEmpty').test(v) || /^[a-z0-9,!\#\$%&'\*\+/=\?\^_`\{\|}~-]+(\.[a-z0-9,!#\$%&'\*\+/=\?\^_`\{\|}~-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,})/i.test(v)
 }],
 ['validate-password', 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.', function(v) {
 var pass=v.strip(); /*strip leading and trailing spaces*/
 return !(pass.length>0 && pass.length < 6);
 }],
 ['validate-cpassword', 'Please make sure your passwords match.', function(v) {
 var pass = $('password') ? $('password') : $$('.validate-password')[0];
 var conf = $('confirmation') ? $('confirmation') : $$('.validate-cpassword')[0];
 return (pass.value == conf.value);
 }],
 ['validate-url', 'Please enter a valid URL. http:// is required', function (v) {
 return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(v)
 }],
 ['validate-clean-url', 'Please enter a valid URL. For example http://www.example.com or www.example.com', function (v) {
 return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v) || /^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v)
 }],
 ['validate-identifier', 'Please enter a valid Identifier. For example example-page, example-page.html or anotherlevel/example-page', function (v) {
 return Validation.get('IsEmpty').test(v) || /^[A-Z0-9][A-Z0-9_\/-]+(\.[A-Z0-9_-]+)*$/i.test(v)
 }],
 ['validate-xml-identifier', 'Please enter a valid XML-identifier. For example something_1, block5, id-4', function (v) {
 return Validation.get('IsEmpty').test(v) || /^[A-Z][A-Z0-9_\/-]*$/i.test(v)
 }],
 ['validate-ssn', 'Please enter a valid social security number. For example 123-45-6789.', function(v) {
 return Validation.get('IsEmpty').test(v) || /^\d{3}-?\d{2}-?\d{4}$/.test(v);
 }],
 ['validate-zip', 'Please enter a valid zip code. For example 90602 or 90602-1234.', function(v) {
 return Validation.get('IsEmpty').test(v) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(v);
 }],
 ['validate-zip-international', 'Please enter a valid zip code.', function(v) {
 //return Validation.get('IsEmpty').test(v) || /(^[A-z0-9]{2,10}([\s]{0,1}|[\-]{0,1})[A-z0-9]{2,10}$)/.test(v);
 return true;
 }],
 ['validate-date-au', 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.', function(v) {
 if(Validation.get('IsEmpty').test(v)) return true;
 var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
 if(!regex.test(v)) return false;
 var d = new Date(v.replace(regex, '$2/$1/$3'));
 return ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) ) &&
 (parseInt(RegExp.$1, 10) == d.getDate()) &&
 (parseInt(RegExp.$3, 10) == d.getFullYear() );
 }],
 ['validate-currency-dollar', 'Please enter a valid $ amount. For example $100.00.', function(v) {
 // [$]1[##][,###]+[.##]
 // [$]1###+[.##]
 // [$]0.##
 // [$].##
 return Validation.get('IsEmpty').test(v) || /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v)
 }],
 ['validate-one-required', 'Please select one of the above options.', function (v,elm) {
 var p = elm.parentNode;
 var options = p.getElementsByTagName('INPUT');
 return $A(options).any(function(elm) {
 return $F(elm);
 });
 }],
 ['validate-one-required-by-name', 'Please select one of the options.', function (v,elm) {
 var inputs = $$('input');
 var error = 1;
 for( i in inputs ) {
 if( inputs[i].checked == true && inputs[i].name == elm.name ) {
 error = 0;
 }
 }

 if( error == 0 ) {
 return true;
 } else {
 return false;
 }
 }],
 ['validate-not-negative-number', 'Please enter a valid number in this field.', function(v) {
 v = parseNumber(v);
 return (!isNaN(v) && v>=0);
 }],
 ['validate-state', 'Please select State/Province.', function(v) {
 return (v!=0 || v == '');
 }],

 ['validate-new-password', 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.', function(v) {
 if (!Validation.get('validate-password').test(v)) return false;
 if (Validation.get('IsEmpty').test(v) && v != '') return false;
 return true;
 }],
 ['validate-greater-than-zero', 'Please enter a number greater than 0 in this field.', function(v) {
 if(v.length)
 return parseFloat(v) > 0;
 else
 return true;
 }],
 ['validate-zero-or-greater', 'Please enter a number 0 or greater in this field.', function(v) {
 if(v.length)
 return parseFloat(v) >= 0;
 else
 return true;
 }],
 ['validate-cc-number', 'Please enter a valid credit card number.', function(v, elm) {
 // remove non-numerics
 var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_number')) + '_cc_type');
 if (ccTypeContainer && typeof Validation.creditCartTypes.get(ccTypeContainer.value) != 'undefined'
 && Validation.creditCartTypes.get(ccTypeContainer.value)[2] == false) {
 if (!Validation.get('IsEmpty').test(v) && Validation.get('validate-digits').test(v)) {
 return true;
 } else {
 return false;
 }
 }
 return validateCreditCard(v);
 }],
 ['validate-cc-type', 'Credit card number doesn\'t match credit card type', function(v, elm) {
 // remove credit card number delimiters such as "-" and space
 elm.value = removeDelimiters(elm.value);
 v = removeDelimiters(v);

 var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_number')) + '_cc_type');
 if (!ccTypeContainer) {
 return true;
 }
 var ccType = ccTypeContainer.value;

 if (typeof Validation.creditCartTypes.get(ccType) == 'undefined') {
 return false;
 }

 // Other card type or switch or solo card
 if (Validation.creditCartTypes.get(ccType)[0]==false) {
 return true;
 }

 // Matched credit card type
 var ccMatchedType = '';

 Validation.creditCartTypes.each(function (pair) {
 if (pair.value[0] && v.match(pair.value[0])) {
 ccMatchedType = pair.key;
 throw $break;
 }
 });

 if(ccMatchedType != ccType) {
 return false;
 }

 return true;
 }],
 ['validate-cc-type-select', 'Card type doesn\'t match credit card number', function(v, elm) {
 var ccNumberContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_type')) + '_cc_number');
 return Validation.get('validate-cc-type').test(ccNumberContainer.value, ccNumberContainer);
 }],
 ['validate-cc-exp', 'Incorrect credit card expiration date', function(v, elm) {
 var ccExpMonth = v;
 var ccExpYear = $('ccsave_expiration_yr').value;
 var currentTime = new Date();
 var currentMonth = currentTime.getMonth() + 1;
 var currentYear = currentTime.getFullYear();
 if (ccExpMonth < currentMonth && ccExpYear == currentYear) {
 return false;
 }
 return true;
 }],
 ['validate-cc-cvn', 'Please enter a valid credit card verification number.', function(v, elm) {
 var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_cid')) + '_cc_type');
 if (!ccTypeContainer) {
 return true;
 }
 var ccType = ccTypeContainer.value;

 if (typeof Validation.creditCartTypes.get(ccType) == 'undefined') {
 return false;
 }

 var re = Validation.creditCartTypes.get(ccType)[1];

 if (v.match(re)) {
 return true;
 }

 return false;
 }],
 ['validate-ajax', '', function(v, elm) { return true; }],
 ['validate-data', 'Please use only letters (a-z or A-Z), numbers (0-9) or underscore(_) in this field, first character should be a letter.', function (v) {
 if(v != '' && v) {
 return /^[A-Za-z]+[A-Za-z0-9_]+$/.test(v);
 }
 return true;
 }],
 ['validate-css-length', 'Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%', function (v) {
 if (v != '' && v) {
 return /^[0-9\.]+(px|pt|em|ex|%)?$/.test(v) && (!(/\..*\./.test(v))) && !(/\.$/.test(v));
 }
 return true;
 }],
 ['validate-length', 'Maximum length exceeded.', function (v, elm) {
 var re = new RegExp(/^maximum-length-[0-9]+$/);
 var result = true;
 $w(elm.className).each(function(name, index) {
 if (name.match(re) && result) {
 var length = name.split('-')[2];
 result = (v.length <= length);
 }
 });
 return result;
 }]
]);


// Credit Card Validation Javascript
// copyright 12th May 2003, by Stephen Chapman, Felgall Pty Ltd

// You have permission to copy and use this javascript provided that
// the content of the script is not changed in any way.

function validateCreditCard(s) {
 // remove non-numerics
 var v = "0123456789";
 var w = "";
 for (i=0; i < s.length; i++) {
 x = s.charAt(i);
 if (v.indexOf(x,0) != -1)
 w += x;
 }
 // validate number
 j = w.length / 2;
 k = Math.floor(j);
 m = Math.ceil(j) - k;
 c = 0;
 for (i=0; i<k; i++) {
 a = w.charAt(i*2+m) * 2;
 c += a > 9 ? Math.floor(a/10 + a%10) : a;
 }
 for (i=0; i<k+m; i++) c += w.charAt(i*2+1-m) * 1;
 return (c%10 == 0);
}

function removeDelimiters (v) {
 v = v.replace(/\s/g, '');
 v = v.replace(/\-/g, '');
 return v;
}

function parseNumber(v)
{
 if (typeof v != 'string') {
 return parseFloat(v);
 }

 var isDot = v.indexOf('.');
 var isComa = v.indexOf(',');

 if (isDot != -1 && isComa != -1) {
 if (isComa > isDot) {
 v = v.replace('.', '').replace(',', '.');
 }
 else {
 v = v.replace(',', '');
 }
 }
 else if (isComa != -1) {
 v = v.replace(',', '.');
 }

 return parseFloat(v);
}

/**
 * Hash with credit card types wich can be simply extended in payment modules
 * 0 - regexp for card number
 * 1 - regexp for cvn
 * 2 - check or not credit card number trough Luhn algorithm by
 * function validateCreditCard wich you can find above in this file
 */
Validation.creditCartTypes = $H({
 'VI': [new RegExp('^4[0-9]{12}([0-9]{3})?$'), new RegExp('^[0-9]{3}$'), true],
 'MC': [new RegExp('^5[1-5][0-9]{14}$'), new RegExp('^[0-9]{3}$'), true],
 'AE': [new RegExp('^3[47][0-9]{13}$'), new RegExp('^[0-9]{4}$'), true],
 'DI': [new RegExp('^6011[0-9]{12}$'), new RegExp('^[0-9]{3}$'), true],
 'SS': [new RegExp('^((6759[0-9]{12})|(49[013][1356][0-9]{13})|(633[34][0-9]{12})|(633110[0-9]{10})|(564182[0-9]{10}))([0-9]{2,3})?$'), new RegExp('^([0-9]{3}|[0-9]{4})?$'), true],
 'OT': [false, new RegExp('^([0-9]{3}|[0-9]{4})?$'), false]
});
// script.aculo.us builder.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007

// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

var Builder = {
 NODEMAP: {
 AREA: 'map',
 CAPTION: 'table',
 COL: 'table',
 COLGROUP: 'table',
 LEGEND: 'fieldset',
 OPTGROUP: 'select',
 OPTION: 'select',
 PARAM: 'object',
 TBODY: 'table',
 TD: 'table',
 TFOOT: 'table',
 TH: 'table',
 THEAD: 'table',
 TR: 'table'
 },
 // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
 // due to a Firefox bug
 node: function(elementName) {
 elementName = elementName.toUpperCase();
 
 // try innerHTML approach
 var parentTag = this.NODEMAP[elementName] || 'div';
 var parentElement = document.createElement(parentTag);
 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
 parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
 } catch(e) {}
 var element = parentElement.firstChild || null;
 
 // see if browser added wrapping tags
 if(element && (element.tagName.toUpperCase() != elementName))
 element = element.getElementsByTagName(elementName)[0];
 
 // fallback to createElement approach
 if(!element) element = document.createElement(elementName);
 
 // abort if nothing could be created
 if(!element) return;

 // attributes (or text)
 if(arguments[1])
 if(this._isStringOrNumber(arguments[1]) ||
 (arguments[1] instanceof Array) ||
 arguments[1].tagName) {
 this._children(element, arguments[1]);
 } else {
 var attrs = this._attributes(arguments[1]);
 if(attrs.length) {
 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
 parentElement.innerHTML = "<" +elementName + " " +
 attrs + "></" + elementName + ">";
 } catch(e) {}
 element = parentElement.firstChild || null;
 // workaround firefox 1.0.X bug
 if(!element) {
 element = document.createElement(elementName);
 for(attr in arguments[1]) 
 element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
 }
 if(element.tagName.toUpperCase() != elementName)
 element = parentElement.getElementsByTagName(elementName)[0];
 }
 } 

 // text, or array of children
 if(arguments[2])
 this._children(element, arguments[2]);

 return element;
 },
 _text: function(text) {
 return document.createTextNode(text);
 },

 ATTR_MAP: {
 'className': 'class',
 'htmlFor': 'for'
 },

 _attributes: function(attributes) {
 var attrs = [];
 for(attribute in attributes)
 attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
 '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
 return attrs.join(" ");
 },
 _children: function(element, children) {
 if(children.tagName) {
 element.appendChild(children);
 return;
 }
 if(typeof children=='object') { // array can hold nodes and text
 children.flatten().each( function(e) {
 if(typeof e=='object')
 element.appendChild(e)
 else
 if(Builder._isStringOrNumber(e))
 element.appendChild(Builder._text(e));
 });
 } else
 if(Builder._isStringOrNumber(children))
 element.appendChild(Builder._text(children));
 },
 _isStringOrNumber: function(param) {
 return(typeof param=='string' || typeof param=='number');
 },
 build: function(html) {
 var element = this.node('div');
 $(element).update(html.strip());
 return element.down();
 },
 dump: function(scope) { 
 if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope 
 
 var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
 "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
 "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
 "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
 "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
 "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
 
 tags.each( function(tag){ 
 scope[tag] = function() { 
 return Builder.node.apply(Builder, [tag].concat($A(arguments))); 
 } 
 });
 }
}
// script.aculo.us effects.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007

// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
// Martin Bialasinki
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

// converts rgb() and #xxx to #xxxxxx format,
// returns self (or first argument) if not convertable
String.prototype.parseColor = function() {
 var color = '#';
 if(this.slice(0,4) == 'rgb(') {
 var cols = this.slice(4,this.length-1).split(',');
 var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
 } else {
 if(this.slice(0,1) == '#') {
 if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
 if(this.length==7) color = this.toLowerCase();
 }
 }
 return(color.length==7 ? color : (arguments[0] || this));
}

/*--------------------------------------------------------------------------*/

Element.collectTextNodes = function(element) {
 return $A($(element).childNodes).collect( function(node) {
 return (node.nodeType==3 ? node.nodeValue :
 (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
 }).flatten().join('');
}

Element.collectTextNodesIgnoreClass = function(element, className) {
 return $A($(element).childNodes).collect( function(node) {
 return (node.nodeType==3 ? node.nodeValue :
 ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
 Element.collectTextNodesIgnoreClass(node, className) : ''));
 }).flatten().join('');
}

Element.setContentZoom = function(element, percent) {
 element = $(element);
 element.setStyle({fontSize: (percent/100) + 'em'});
 if(Prototype.Browser.WebKit) window.scrollBy(0,0);
 return element;
}

Element.getInlineOpacity = function(element){
 return $(element).style.opacity || '';
}

Element.forceRerendering = function(element) {
 try {
 element = $(element);
 var n = document.createTextNode(' ');
 element.appendChild(n);
 element.removeChild(n);
 } catch(e) { }
};

/*--------------------------------------------------------------------------*/

Array.prototype.call = function() {
 var args = arguments;
 this.each(function(f){ f.apply(this, args) });
}

/*--------------------------------------------------------------------------*/

var Effect = {
 _elementDoesNotExistError: {
 name: 'ElementDoesNotExistError',
 message: 'The specified DOM element does not exist, but is required for this effect to operate'
 },
 tagifyText: function(element) {
 if(typeof Builder == 'undefined')
 throw("Effect.tagifyText requires including script.aculo.us' builder.js library");

 var tagifyStyle = 'position:relative';
 if(Prototype.Browser.IE) tagifyStyle += ';zoom:1';

 element = $(element);
 $A(element.childNodes).each( function(child) {
 if(child.nodeType==3) {
 child.nodeValue.toArray().each( function(character) {
 element.insertBefore(
 Builder.node('span',{style: tagifyStyle},
 character == ' ' ? String.fromCharCode(160) : character),
 child);
 });
 Element.remove(child);
 }
 });
 },
 multiple: function(element, effect) {
 var elements;
 if(((typeof element == 'object') ||
 (typeof element == 'function')) &&
 (element.length))
 elements = element;
 else
 elements = $(element).childNodes;

 var options = Object.extend({
 speed: 0.1,
 delay: 0.0
 }, arguments[2] || {});
 var masterDelay = options.delay;

 $A(elements).each( function(element, index) {
 new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
 });
 },
 PAIRS: {
 'slide': ['SlideDown','SlideUp'],
 'blind': ['BlindDown','BlindUp'],
 'appear': ['Appear','Fade']
 },
 toggle: function(element, effect) {
 element = $(element);
 effect = (effect || 'appear').toLowerCase();
 var options = Object.extend({
 queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
 }, arguments[2] || {});
 Effect[element.visible() ?
 Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
 }
};

var Effect2 = Effect; // deprecated

/* ------------- transitions ------------- */

Effect.Transitions = {
 linear: Prototype.K,
 sinoidal: function(pos) {
 return (-Math.cos(pos*Math.PI)/2) + 0.5;
 },
 reverse: function(pos) {
 return 1-pos;
 },
 flicker: function(pos) {
 var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
 return (pos > 1 ? 1 : pos);
 },
 wobble: function(pos) {
 return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
 },
 pulse: function(pos, pulses) {
 pulses = pulses || 5;
 return (
 Math.round((pos % (1/pulses)) * pulses) == 0 ?
 ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
 );
 },
 none: function(pos) {
 return 0;
 },
 full: function(pos) {
 return 1;
 }
};

/* ------------- core effects ------------- */

Effect.ScopedQueue = Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
 initialize: function() {
 this.effects = [];
 this.interval = null;
 },
 _each: function(iterator) {
 this.effects._each(iterator);
 },
 add: function(effect) {
 var timestamp = new Date().getTime();

 var position = (typeof effect.options.queue == 'string') ?
 effect.options.queue : effect.options.queue.position;

 switch(position) {
 case 'front':
 // move unstarted effects after this effect
 this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
 e.startOn += effect.finishOn;
 e.finishOn += effect.finishOn;
 });
 break;
 case 'with-last':
 timestamp = this.effects.pluck('startOn').max() || timestamp;
 break;
 case 'end':
 // start effect after last queued effect has finished
 timestamp = this.effects.pluck('finishOn').max() || timestamp;
 break;
 }

 effect.startOn += timestamp;
 effect.finishOn += timestamp;

 if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
 this.effects.push(effect);

 if(!this.interval)
 this.interval = setInterval(this.loop.bind(this), 15);
 },
 remove: function(effect) {
 this.effects = this.effects.reject(function(e) { return e==effect });
 if(this.effects.length == 0) {
 clearInterval(this.interval);
 this.interval = null;
 }
 },
 loop: function() {
 var timePos = new Date().getTime();
 for(var i=0, len=this.effects.length;i<len;i++)
 this.effects[i] && this.effects[i].loop(timePos);
 }
});

Effect.Queues = {
 instances: $H(),
 get: function(queueName) {
 if(typeof queueName != 'string') return queueName;

 if(!this.instances[queueName])
 this.instances[queueName] = new Effect.ScopedQueue();

 return this.instances[queueName];
 }
}
Effect.Queue = Effect.Queues.get('global');

Effect.DefaultOptions = {
 transition: Effect.Transitions.sinoidal,
 duration: 1.0, // seconds
 fps: 100, // 100= assume 66fps max.
 sync: false, // true for combining
 from: 0.0,
 to: 1.0,
 delay: 0.0,
 queue: 'parallel'
}

Effect.Base = function() {};
Effect.Base.prototype = {
 position: null,
 start: function(options) {
 function codeForEvent(options,eventName){
 return (
 (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
 (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
 );
 }
 if(options.transition === false) options.transition = Effect.Transitions.linear;
 this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
 this.currentFrame = 0;
 this.state = 'idle';
 this.startOn = this.options.delay*1000;
 this.finishOn = this.startOn+(this.options.duration*1000);
 this.fromToDelta = this.options.to-this.options.from;
 this.totalTime = this.finishOn-this.startOn;
 this.totalFrames = this.options.fps*this.options.duration;

 eval('this.render = function(pos){ '+
 'if(this.state=="idle"){this.state="running";'+
 codeForEvent(options,'beforeSetup')+
 (this.setup ? 'this.setup();':'')+
 codeForEvent(options,'afterSetup')+
 '};if(this.state=="running"){'+
 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
 'this.position=pos;'+
 codeForEvent(options,'beforeUpdate')+
 (this.update ? 'this.update(pos);':'')+
 codeForEvent(options,'afterUpdate')+
 '}}');

 this.event('beforeStart');
 if(!this.options.sync)
 Effect.Queues.get(typeof this.options.queue == 'string' ?
 'global' : this.options.queue.scope).add(this);
 },
 loop: function(timePos) {
 if(timePos >= this.startOn) {
 if(timePos >= this.finishOn) {
 this.render(1.0);
 this.cancel();
 this.event('beforeFinish');
 if(this.finish) this.finish();
 this.event('afterFinish');
 return;
 }
 var pos = (timePos - this.startOn) / this.totalTime,
 frame = Math.round(pos * this.totalFrames);
 if(frame > this.currentFrame) {
 this.render(pos);
 this.currentFrame = frame;
 }
 }
 },
 cancel: function() {
 if(!this.options.sync)
 Effect.Queues.get(typeof this.options.queue == 'string' ?
 'global' : this.options.queue.scope).remove(this);
 this.state = 'finished';
 },
 event: function(eventName) {
 if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
 if(this.options[eventName]) this.options[eventName](this);
 },
 inspect: function() {
 var data = $H();
 for(property in this)
 if(typeof this[property] != 'function') data[property] = this[property];
 return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
 }
}

Effect.Parallel = Class.create();
Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
 initialize: function(effects) {
 this.effects = effects || [];
 this.start(arguments[1]);
 },
 update: function(position) {
 this.effects.invoke('render', position);
 },
 finish: function(position) {
 this.effects.each( function(effect) {
 effect.render(1.0);
 effect.cancel();
 effect.event('beforeFinish');
 if(effect.finish) effect.finish(position);
 effect.event('afterFinish');
 });
 }
});

Effect.Event = Class.create();
Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
 initialize: function() {
 var options = Object.extend({
 duration: 0
 }, arguments[0] || {});
 this.start(options);
 },
 update: Prototype.emptyFunction
});

Effect.Opacity = Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
 initialize: function(element) {
 this.element = $(element);
 if(!this.element) throw(Effect._elementDoesNotExistError);
 // make this work on IE on elements without 'layout'
 if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
 this.element.setStyle({zoom: 1});
 var options = Object.extend({
 from: this.element.getOpacity() || 0.0,
 to: 1.0
 }, arguments[1] || {});
 this.start(options);
 },
 update: function(position) {
 this.element.setOpacity(position);
 }
});

Effect.Move = Class.create();
Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
 initialize: function(element) {
 this.element = $(element);
 if(!this.element) throw(Effect._elementDoesNotExistError);
 var options = Object.extend({
 x: 0,
 y: 0,
 mode: 'relative'
 }, arguments[1] || {});
 this.start(options);
 },
 setup: function() {
 // Bug in Opera: Opera returns the "real" position of a static element or
 // relative element that does not have top/left explicitly set.
 // ==> Always set top and left for position relative elements in your stylesheets
 // (to 0 if you do not need them)
 this.element.makePositioned();
 this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
 this.originalTop = parseFloat(this.element.getStyle('top') || '0');
 if(this.options.mode == 'absolute') {
 // absolute movement, so we need to calc deltaX and deltaY
 this.options.x = this.options.x - this.originalLeft;
 this.options.y = this.options.y - this.originalTop;
 }
 },
 update: function(position) {
 this.element.setStyle({
 left: Math.round(this.options.x * position + this.originalLeft) + 'px',
 top: Math.round(this.options.y * position + this.originalTop) + 'px'
 });
 }
});

// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
 return new Effect.Move(element,
 Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
};

Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
 initialize: function(element, percent) {
 this.element = $(element);
 if(!this.element) throw(Effect._elementDoesNotExistError);
 var options = Object.extend({
 scaleX: true,
 scaleY: true,
 scaleContent: true,
 scaleFromCenter: false,
 scaleMode: 'box', // 'box' or 'contents' or {} with provided values
 scaleFrom: 100.0,
 scaleTo: percent
 }, arguments[2] || {});
 this.start(options);
 },
 setup: function() {
 this.restoreAfterFinish = this.options.restoreAfterFinish || false;
 this.elementPositioning = this.element.getStyle('position');

 this.originalStyle = {};
 ['top','left','width','height','fontSize'].each( function(k) {
 this.originalStyle[k] = this.element.style[k];
 }.bind(this));

 this.originalTop = this.element.offsetTop;
 this.originalLeft = this.element.offsetLeft;

 var fontSize = this.element.getStyle('font-size') || '100%';
 ['em','px','%','pt'].each( function(fontSizeType) {
 if(fontSize.indexOf(fontSizeType)>0) {
 this.fontSize = parseFloat(fontSize);
 this.fontSizeType = fontSizeType;
 }
 }.bind(this));

 this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;

 this.dims = null;
 if(this.options.scaleMode=='box')
 this.dims = [this.element.offsetHeight, this.element.offsetWidth];
 if(/^content/.test(this.options.scaleMode))
 this.dims = [this.element.scrollHeight, this.element.scrollWidth];
 if(!this.dims)
 this.dims = [this.options.scaleMode.originalHeight,
 this.options.scaleMode.originalWidth];
 },
 update: function(position) {
 var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
 if(this.options.scaleContent && this.fontSize)
 this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
 this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
 },
 finish: function(position) {
 if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
 },
 setDimensions: function(height, width) {
 var d = {};
 if(this.options.scaleX) d.width = Math.round(width) + 'px';
 if(this.options.scaleY) d.height = Math.round(height) + 'px';
 if(this.options.scaleFromCenter) {
 var topd = (height - this.dims[0])/2;
 var leftd = (width - this.dims[1])/2;
 if(this.elementPositioning == 'absolute') {
 if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
 if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
 } else {
 if(this.options.scaleY) d.top = -topd + 'px';
 if(this.options.scaleX) d.left = -leftd + 'px';
 }
 }
 this.element.setStyle(d);
 }
});

Effect.Highlight = Class.create();
Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
 initialize: function(element) {
 this.element = $(element);
 if(!this.element) throw(Effect._elementDoesNotExistError);
 var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
 this.start(options);
 },
 setup: function() {
 // Prevent executing on elements not in the layout flow
 if(this.element.getStyle('display')=='none') { this.cancel(); return; }
 // Disable background image during the effect
 this.oldStyle = {};
 if (!this.options.keepBackgroundImage) {
 this.oldStyle.backgroundImage = this.element.getStyle('background-image');
 this.element.setStyle({backgroundImage: 'none'});
 }
 if(!this.options.endcolor)
 this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
 if(!this.options.restorecolor)
 this.options.restorecolor = this.element.getStyle('background-color');
 // init color calculations
 this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
 this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
 },
 update: function(position) {
 this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
 return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
 },
 finish: function() {
 this.element.setStyle(Object.extend(this.oldStyle, {
 backgroundColor: this.options.restorecolor
 }));
 }
});

Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
 initialize: function(element) {
 this.element = $(element);
 this.start(arguments[1] || {});
 },
 setup: function() {
 Position.prepare();
 var offsets = Position.cumulativeOffset(this.element);
 if(this.options.offset) offsets[1] += this.options.offset;
 var max = window.innerHeight ?
 window.height - window.innerHeight :
 document.body.scrollHeight -
 (document.documentElement.clientHeight ?
 document.documentElement.clientHeight : document.body.clientHeight);
 this.scrollStart = Position.deltaY;
 this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
 },
 update: function(position) {
 Position.prepare();
 window.scrollTo(Position.deltaX,
 this.scrollStart + (position*this.delta));
 }
});

/* ------------- combination effects ------------- */

Effect.Fade = function(element) {
 element = $(element);
 var oldOpacity = element.getInlineOpacity();
 var options = Object.extend({
 from: element.getOpacity() || 1.0,
 to: 0.0,
 afterFinishInternal: function(effect) {
 if(effect.options.to!=0) return;
 effect.element.hide().setStyle({opacity: oldOpacity});
 }}, arguments[1] || {});
 return new Effect.Opacity(element,options);
}

Effect.Appear = function(element) {
 element = $(element);
 var options = Object.extend({
 from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
 to: 1.0,
 // force Safari to render floated elements properly
 afterFinishInternal: function(effect) {
 effect.element.forceRerendering();
 },
 beforeSetup: function(effect) {
 effect.element.setOpacity(effect.options.from).show();
 }}, arguments[1] || {});
 return new Effect.Opacity(element,options);
}

Effect.Puff = function(element) {
 element = $(element);
 var oldStyle = {
 opacity: element.getInlineOpacity(),
 position: element.getStyle('position'),
 top: element.style.top,
 left: element.style.left,
 width: element.style.width,
 height: element.style.height
 };
 return new Effect.Parallel(
 [ new Effect.Scale(element, 200,
 { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
 new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
 Object.extend({ duration: 1.0,
 beforeSetupInternal: function(effect) {
 Position.absolutize(effect.effects[0].element)
 },
 afterFinishInternal: function(effect) {
 effect.effects[0].element.hide().setStyle(oldStyle); }
 }, arguments[1] || {})
 );
}

Effect.BlindUp = function(element) {
 element = $(element);
 element.makeClipping();
 return new Effect.Scale(element, 0,
 Object.extend({ scaleContent: false,
 scaleX: false,
 restoreAfterFinish: true,
 afterFinishInternal: function(effect) {
 effect.element.hide().undoClipping();
 }
 }, arguments[1] || {})
 );
}

Effect.BlindDown = function(element) {
 element = $(element);
 var elementDimensions = element.getDimensions();
 return new Effect.Scale(element, 100, Object.extend({
 scaleContent: false,
 scaleX: false,
 scaleFrom: 0,
 scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
 restoreAfterFinish: true,
 afterSetup: function(effect) {
 effect.element.makeClipping().setStyle({height: '0px'}).show();
 },
 afterFinishInternal: function(effect) {
 effect.element.undoClipping();
 }
 }, arguments[1] || {}));
}

Effect.SwitchOff = function(element) {
 element = $(element);
 var oldOpacity = element.getInlineOpacity();
 return new Effect.Appear(element, Object.extend({
 duration: 0.4,
 from: 0,
 transition: Effect.Transitions.flicker,
 afterFinishInternal: function(effect) {
 new Effect.Scale(effect.element, 1, {
 duration: 0.3, scaleFromCenter: true,
 scaleX: false, scaleContent: false, restoreAfterFinish: true,
 beforeSetup: function(effect) {
 effect.element.makePositioned().makeClipping();
 },
 afterFinishInternal: function(effect) {
 effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
 }
 })
 }
 }, arguments[1] || {}));
}

Effect.DropOut = function(element) {
 element = $(element);
 var oldStyle = {
 top: element.getStyle('top'),
 left: element.getStyle('left'),
 opacity: element.getInlineOpacity() };
 return new Effect.Parallel(
 [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
 new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
 Object.extend(
 { duration: 0.5,
 beforeSetup: function(effect) {
 effect.effects[0].element.makePositioned();
 },
 afterFinishInternal: function(effect) {
 effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
 }
 }, arguments[1] || {}));
}

Effect.Shake = function(element) {
 element = $(element);
 var oldStyle = {
 top: element.getStyle('top'),
 left: element.getStyle('left') };
 return new Effect.Move(element,
 { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
 new Effect.Move(effect.element,
 { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
 new Effect.Move(effect.element,
 { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
 new Effect.Move(effect.element,
 { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
 new Effect.Move(effect.element,
 { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
 new Effect.Move(effect.element,
 { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
 effect.element.undoPositioned().setStyle(oldStyle);
 }}) }}) }}) }}) }}) }});
}

Effect.SlideDown = function(element) {
 element = $(element).cleanWhitespace();
 // SlideDown need to have the content of the element wrapped in a container element with fixed height!
 var oldInnerBottom = element.down().getStyle('bottom');
 var elementDimensions = element.getDimensions();
 return new Effect.Scale(element, 100, Object.extend({
 scaleContent: false,
 scaleX: false,
 scaleFrom: window.opera ? 0 : 1,
 scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
 restoreAfterFinish: true,
 afterSetup: function(effect) {
 effect.element.makePositioned();
 effect.element.down().makePositioned();
 if(window.opera) effect.element.setStyle({top: ''});
 effect.element.makeClipping().setStyle({height: '0px'}).show();
 },
 afterUpdateInternal: function(effect) {
 effect.element.down().setStyle({bottom:
 (effect.dims[0] - effect.element.clientHeight) + 'px' });
 },
 afterFinishInternal: function(effect) {
 effect.element.undoClipping().undoPositioned();
 effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
 }, arguments[1] || {})
 );
}

Effect.SlideUp = function(element) {
 element = $(element).cleanWhitespace();
 var oldInnerBottom = element.down().getStyle('bottom');
 return new Effect.Scale(element, window.opera ? 0 : 1,
 Object.extend({ scaleContent: false,
 scaleX: false,
 scaleMode: 'box',
 scaleFrom: 100,
 restoreAfterFinish: true,
 beforeStartInternal: function(effect) {
 effect.element.makePositioned();
 effect.element.down().makePositioned();
 if(window.opera) effect.element.setStyle({top: ''});
 effect.element.makeClipping().show();
 },
 afterUpdateInternal: function(effect) {
 effect.element.down().setStyle({bottom:
 (effect.dims[0] - effect.element.clientHeight) + 'px' });
 },
 afterFinishInternal: function(effect) {
 effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
 effect.element.down().undoPositioned();
 }
 }, arguments[1] || {})
 );
}

// Bug in opera makes the TD containing this element expand for a instance after finish
Effect.Squish = function(element) {
 return new Effect.Scale(element, window.opera ? 1 : 0, {
 restoreAfterFinish: true,
 beforeSetup: function(effect) {
 effect.element.makeClipping();
 },
 afterFinishInternal: function(effect) {
 effect.element.hide().undoClipping();
 }
 });
}

Effect.Grow = function(element) {
 element = $(element);
 var options = Object.extend({
 direction: 'center',
 moveTransition: Effect.Transitions.sinoidal,
 scaleTransition: Effect.Transitions.sinoidal,
 opacityTransition: Effect.Transitions.full
 }, arguments[1] || {});
 var oldStyle = {
 top: element.style.top,
 left: element.style.left,
 height: element.style.height,
 width: element.style.width,
 opacity: element.getInlineOpacity() };

 var dims = element.getDimensions();
 var initialMoveX, initialMoveY;
 var moveX, moveY;

 switch (options.direction) {
 case 'top-left':
 initialMoveX = initialMoveY = moveX = moveY = 0;
 break;
 case 'top-right':
 initialMoveX = dims.width;
 initialMoveY = moveY = 0;
 moveX = -dims.width;
 break;
 case 'bottom-left':
 initialMoveX = moveX = 0;
 initialMoveY = dims.height;
 moveY = -dims.height;
 break;
 case 'bottom-right':
 initialMoveX = dims.width;
 initialMoveY = dims.height;
 moveX = -dims.width;
 moveY = -dims.height;
 break;
 case 'center':
 initialMoveX = dims.width / 2;
 initialMoveY = dims.height / 2;
 moveX = -dims.width / 2;
 moveY = -dims.height / 2;
 break;
 }

 return new Effect.Move(element, {
 x: initialMoveX,
 y: initialMoveY,
 duration: 0.01,
 beforeSetup: function(effect) {
 effect.element.hide().makeClipping().makePositioned();
 },
 afterFinishInternal: function(effect) {
 new Effect.Parallel(
 [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
 new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
 new Effect.Scale(effect.element, 100, {
 scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
 sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
 ], Object.extend({
 beforeSetup: function(effect) {
 effect.effects[0].element.setStyle({height: '0px'}).show();
 },
 afterFinishInternal: function(effect) {
 effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
 }
 }, options)
 )
 }
 });
}

Effect.Shrink = function(element) {
 element = $(element);
 var options = Object.extend({
 direction: 'center',
 moveTransition: Effect.Transitions.sinoidal,
 scaleTransition: Effect.Transitions.sinoidal,
 opacityTransition: Effect.Transitions.none
 }, arguments[1] || {});
 var oldStyle = {
 top: element.style.top,
 left: element.style.left,
 height: element.style.height,
 width: element.style.width,
 opacity: element.getInlineOpacity() };

 var dims = element.getDimensions();
 var moveX, moveY;

 switch (options.direction) {
 case 'top-left':
 moveX = moveY = 0;
 break;
 case 'top-right':
 moveX = dims.width;
 moveY = 0;
 break;
 case 'bottom-left':
 moveX = 0;
 moveY = dims.height;
 break;
 case 'bottom-right':
 moveX = dims.width;
 moveY = dims.height;
 break;
 case 'center':
 moveX = dims.width / 2;
 moveY = dims.height / 2;
 break;
 }

 return new Effect.Parallel(
 [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
 new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
 new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
 ], Object.extend({
 beforeStartInternal: function(effect) {
 effect.effects[0].element.makePositioned().makeClipping();
 },
 afterFinishInternal: function(effect) {
 effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
 }, options)
 );
}

Effect.Pulsate = function(element) {
 element = $(element);
 var options = arguments[1] || {};
 var oldOpacity = element.getInlineOpacity();
 var transition = options.transition || Effect.Transitions.sinoidal;
 var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
 reverser.bind(transition);
 return new Effect.Opacity(element,
 Object.extend(Object.extend({ duration: 2.0, from: 0,
 afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
 }, options), {transition: reverser}));
}

Effect.Fold = function(element) {
 element = $(element);
 var oldStyle = {
 top: element.style.top,
 left: element.style.left,
 width: element.style.width,
 height: element.style.height };
 element.makeClipping();
 return new Effect.Scale(element, 5, Object.extend({
 scaleContent: false,
 scaleX: false,
 afterFinishInternal: function(effect) {
 new Effect.Scale(element, 1, {
 scaleContent: false,
 scaleY: false,
 afterFinishInternal: function(effect) {
 effect.element.hide().undoClipping().setStyle(oldStyle);
 } });
 }}, arguments[1] || {}));
};

Effect.Morph = Class.create();
Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
 initialize: function(element) {
 this.element = $(element);
 if(!this.element) throw(Effect._elementDoesNotExistError);
 var options = Object.extend({
 style: {}
 }, arguments[1] || {});
 if (typeof options.style == 'string') {
 if(options.style.indexOf(':') == -1) {
 var cssText = '', selector = '.' + options.style;
 $A(document.styleSheets).reverse().each(function(styleSheet) {
 if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
 else if (styleSheet.rules) cssRules = styleSheet.rules;
 $A(cssRules).reverse().each(function(rule) {
 if (selector == rule.selectorText) {
 cssText = rule.style.cssText;
 throw $break;
 }
 });
 if (cssText) throw $break;
 });
 this.style = cssText.parseStyle();
 options.afterFinishInternal = function(effect){
 effect.element.addClassName(effect.options.style);
 effect.transforms.each(function(transform) {
 if(transform.style != 'opacity')
 effect.element.style[transform.style] = '';
 });
 }
 } else this.style = options.style.parseStyle();
 } else this.style = $H(options.style)
 this.start(options);
 },
 setup: function(){
 function parseColor(color){
 if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
 color = color.parseColor();
 return $R(0,2).map(function(i){
 return parseInt( color.slice(i*2+1,i*2+3), 16 )
 });
 }
 this.transforms = this.style.map(function(pair){
 var property = pair[0], value = pair[1], unit = null;

 if(value.parseColor('#zzzzzz') != '#zzzzzz') {
 value = value.parseColor();
 unit = 'color';
 } else if(property == 'opacity') {
 value = parseFloat(value);
 if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
 this.element.setStyle({zoom: 1});
 } else if(Element.CSS_LENGTH.test(value)) {
 var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
 value = parseFloat(components[1]);
 unit = (components.length == 3) ? components[2] : null;
 }

 var originalValue = this.element.getStyle(property);
 return {
 style: property.camelize(),
 originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
 targetValue: unit=='color' ? parseColor(value) : value,
 unit: unit
 };
 }.bind(this)).reject(function(transform){
 return (
 (transform.originalValue == transform.targetValue) ||
 (
 transform.unit != 'color' &&
 (isNaN(transform.originalValue) || isNaN(transform.targetValue))
 )
 )
 });
 },
 update: function(position) {
 var style = {}, transform, i = this.transforms.length;
 while(i--)
 style[(transform = this.transforms[i]).style] =
 transform.unit=='color' ? '#'+
 (Math.round(transform.originalValue[0]+
 (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
 (Math.round(transform.originalValue[1]+
 (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
 (Math.round(transform.originalValue[2]+
 (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
 transform.originalValue + Math.round(
 ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
 this.element.setStyle(style, true);
 }
});

Effect.Transform = Class.create();
Object.extend(Effect.Transform.prototype, {
 initialize: function(tracks){
 this.tracks = [];
 this.options = arguments[1] || {};
 this.addTracks(tracks);
 },
 addTracks: function(tracks){
 tracks.each(function(track){
 var data = $H(track).values().first();
 this.tracks.push($H({
 ids: $H(track).keys().first(),
 effect: Effect.Morph,
 options: { style: data }
 }));
 }.bind(this));
 return this;
 },
 play: function(){
 return new Effect.Parallel(
 this.tracks.map(function(track){
 var elements = [$(track.ids) || $$(track.ids)].flatten();
 return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
 }).flatten(),
 this.options
 );
 }
});

Element.CSS_PROPERTIES = $w(
 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
 'fontSize fontWeight height left letterSpacing lineHeight ' +
 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
 'right textIndent top width wordSpacing zIndex');

Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;

String.prototype.parseStyle = function(){
 var element = document.createElement('div');
 element.innerHTML = '<div style="' + this + '"></div>';
 var style = element.childNodes[0].style, styleRules = $H();

 Element.CSS_PROPERTIES.each(function(property){
 if(style[property]) styleRules[property] = style[property];
 });
 if(Prototype.Browser.IE && this.indexOf('opacity') > -1) {
 styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
 }
 return styleRules;
};

Element.morph = function(element, style) {
 new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
 return element;
};

['getInlineOpacity','forceRerendering','setContentZoom',
 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(
 function(f) { Element.Methods[f] = Element[f]; }
);

Element.Methods.visualEffect = function(element, effect, options) {
 s = effect.dasherize().camelize();
 effect_class = s.charAt(0).toUpperCase() + s.substring(1);
 new Effect[effect_class](element, options);
 return $(element);
};

Element.addMethods();// script.aculo.us dragdrop.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007

// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
// 
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

if(typeof Effect == 'undefined')
 throw("dragdrop.js requires including script.aculo.us' effects.js library");

var Droppables = {
 drops: [],

 remove: function(element) {
 this.drops = this.drops.reject(function(d) { return d.element==$(element) });
 },

 add: function(element) {
 element = $(element);
 var options = Object.extend({
 greedy: true,
 hoverclass: null,
 tree: false
 }, arguments[1] || {});

 // cache containers
 if(options.containment) {
 options._containers = [];
 var containment = options.containment;
 if((typeof containment == 'object') && 
 (containment.constructor == Array)) {
 containment.each( function(c) { options._containers.push($(c)) });
 } else {
 options._containers.push($(containment));
 }
 }
 
 if(options.accept) options.accept = [options.accept].flatten();

 Element.makePositioned(element); // fix IE
 options.element = element;

 this.drops.push(options);
 },
 
 findDeepestChild: function(drops) {
 deepest = drops[0];
 
 for (i = 1; i < drops.length; ++i)
 if (Element.isParent(drops[i].element, deepest.element))
 deepest = drops[i];
 
 return deepest;
 },

 isContained: function(element, drop) {
 var containmentNode;
 if(drop.tree) {
 containmentNode = element.treeNode; 
 } else {
 containmentNode = element.parentNode;
 }
 return drop._containers.detect(function(c) { return containmentNode == c });
 },
 
 isAffected: function(point, element, drop) {
 return (
 (drop.element!=element) &&
 ((!drop._containers) ||
 this.isContained(element, drop)) &&
 ((!drop.accept) ||
 (Element.classNames(element).detect( 
 function(v) { return drop.accept.include(v) } ) )) &&
 Position.within(drop.element, point[0], point[1]) );
 },

 deactivate: function(drop) {
 if(drop.hoverclass)
 Element.removeClassName(drop.element, drop.hoverclass);
 this.last_active = null;
 },

 activate: function(drop) {
 if(drop.hoverclass)
 Element.addClassName(drop.element, drop.hoverclass);
 this.last_active = drop;
 },

 show: function(point, element) {
 if(!this.drops.length) return;
 var affected = [];
 
 if(this.last_active) this.deactivate(this.last_active);
 this.drops.each( function(drop) {
 if(Droppables.isAffected(point, element, drop))
 affected.push(drop);
 });
 
 if(affected.length>0) {
 drop = Droppables.findDeepestChild(affected);
 Position.within(drop.element, point[0], point[1]);
 if(drop.onHover)
 drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
 
 Droppables.activate(drop);
 }
 },

 fire: function(event, element) {
 if(!this.last_active) return;
 Position.prepare();

 if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
 if (this.last_active.onDrop) {
 this.last_active.onDrop(element, this.last_active.element, event); 
 return true; 
 }
 },

 reset: function() {
 if(this.last_active)
 this.deactivate(this.last_active);
 }
}

var Draggables = {
 drags: [],
 observers: [],
 
 register: function(draggable) {
 if(this.drags.length == 0) {
 this.eventMouseUp = this.endDrag.bindAsEventListener(this);
 this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
 this.eventKeypress = this.keyPress.bindAsEventListener(this);
 
 Event.observe(document, "mouseup", this.eventMouseUp);
 Event.observe(document, "mousemove", this.eventMouseMove);
 Event.observe(document, "keypress", this.eventKeypress);
 }
 this.drags.push(draggable);
 },
 
 unregister: function(draggable) {
 this.drags = this.drags.reject(function(d) { return d==draggable });
 if(this.drags.length == 0) {
 Event.stopObserving(document, "mouseup", this.eventMouseUp);
 Event.stopObserving(document, "mousemove", this.eventMouseMove);
 Event.stopObserving(document, "keypress", this.eventKeypress);
 }
 },
 
 activate: function(draggable) {
 if(draggable.options.delay) { 
 this._timeout = setTimeout(function() { 
 Draggables._timeout = null; 
 window.focus(); 
 Draggables.activeDraggable = draggable; 
 }.bind(this), draggable.options.delay); 
 } else {
 window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
 this.activeDraggable = draggable;
 }
 },
 
 deactivate: function() {
 this.activeDraggable = null;
 },
 
 updateDrag: function(event) {
 if(!this.activeDraggable) return;
 var pointer = [Event.pointerX(event), Event.pointerY(event)];
 // Mozilla-based browsers fire successive mousemove events with
 // the same coordinates, prevent needless redrawing (moz bug?)
 if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
 this._lastPointer = pointer;
 
 this.activeDraggable.updateDrag(event, pointer);
 },
 
 endDrag: function(event) {
 if(this._timeout) { 
 clearTimeout(this._timeout); 
 this._timeout = null; 
 }
 if(!this.activeDraggable) return;
 this._lastPointer = null;
 this.activeDraggable.endDrag(event);
 this.activeDraggable = null;
 },
 
 keyPress: function(event) {
 if(this.activeDraggable)
 this.activeDraggable.keyPress(event);
 },
 
 addObserver: function(observer) {
 this.observers.push(observer);
 this._cacheObserverCallbacks();
 },
 
 removeObserver: function(element) { // element instead of observer fixes mem leaks
 this.observers = this.observers.reject( function(o) { return o.element==element });
 this._cacheObserverCallbacks();
 },
 
 notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
 if(this[eventName+'Count'] > 0)
 this.observers.each( function(o) {
 if(o[eventName]) o[eventName](eventName, draggable, event);
 });
 if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
 },
 
 _cacheObserverCallbacks: function() {
 ['onStart','onEnd','onDrag'].each( function(eventName) {
 Draggables[eventName+'Count'] = Draggables.observers.select(
 function(o) { return o[eventName]; }
 ).length;
 });
 }
}

/*--------------------------------------------------------------------------*/

var Draggable = Class.create();
Draggable._dragging = {};

Draggable.prototype = {
 initialize: function(element) {
 var defaults = {
 handle: false,
 reverteffect: function(element, top_offset, left_offset) {
 var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
 new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
 queue: {scope:'_draggable', position:'end'}
 });
 },
 endeffect: function(element) {
 var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0;
 new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, 
 queue: {scope:'_draggable', position:'end'},
 afterFinish: function(){ 
 Draggable._dragging[element] = false 
 }
 }); 
 },
 zindex: 1000,
 revert: false,
 quiet: false,
 scroll: false,
 scrollSensitivity: 20,
 scrollSpeed: 15,
 snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
 delay: 0
 };
 
 if(!arguments[1] || typeof arguments[1].endeffect == 'undefined')
 Object.extend(defaults, {
 starteffect: function(element) {
 element._opacity = Element.getOpacity(element);
 Draggable._dragging[element] = true;
 new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); 
 }
 });
 
 var options = Object.extend(defaults, arguments[1] || {});

 this.element = $(element);
 
 if(options.handle && (typeof options.handle == 'string'))
 this.handle = this.element.down('.'+options.handle, 0);
 
 if(!this.handle) this.handle = $(options.handle);
 if(!this.handle) this.handle = this.element;
 
 if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
 options.scroll = $(options.scroll);
 this._isScrollChild = Element.childOf(this.element, options.scroll);
 }

 Element.makePositioned(this.element); // fix IE 

 this.delta = this.currentDelta();
 this.options = options;
 this.dragging = false; 

 this.eventMouseDown = this.initDrag.bindAsEventListener(this);
 Event.observe(this.handle, "mousedown", this.eventMouseDown);
 
 Draggables.register(this);
 },
 
 destroy: function() {
 Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
 Draggables.unregister(this);
 },
 
 currentDelta: function() {
 return([
 parseInt(Element.getStyle(this.element,'left') || '0'),
 parseInt(Element.getStyle(this.element,'top') || '0')]);
 },
 
 initDrag: function(event) {
 if(typeof Draggable._dragging[this.element] != 'undefined' &&
 Draggable._dragging[this.element]) return;
 if(Event.isLeftClick(event)) { 
 // abort on form elements, fixes a Firefox issue
 var src = Event.element(event);
 if((tag_name = src.tagName.toUpperCase()) && (
 tag_name=='INPUT' ||
 tag_name=='SELECT' ||
 tag_name=='OPTION' ||
 tag_name=='BUTTON' ||
 tag_name=='TEXTAREA')) return;
 
 var pointer = [Event.pointerX(event), Event.pointerY(event)];
 var pos = Position.cumulativeOffset(this.element);
 this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
 
 Draggables.activate(this);
 Event.stop(event);
 }
 },
 
 startDrag: function(event) {
 this.dragging = true;
 
 if(this.options.zindex) {
 this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
 this.element.style.zIndex = this.options.zindex;
 }
 
 if(this.options.ghosting) {
 this._clone = this.element.cloneNode(true);
 Position.absolutize(this.element);
 this.element.parentNode.insertBefore(this._clone, this.element);
 }
 
 if(this.options.scroll) {
 if (this.options.scroll == window) {
 var where = this._getWindowScroll(this.options.scroll);
 this.originalScrollLeft = where.left;
 this.originalScrollTop = where.top;
 } else {
 this.originalScrollLeft = this.options.scroll.scrollLeft;
 this.originalScrollTop = this.options.scroll.scrollTop;
 }
 }
 
 Draggables.notify('onStart', this, event);
 
 if(this.options.starteffect) this.options.starteffect(this.element);
 },
 
 updateDrag: function(event, pointer) {
 if(!this.dragging) this.startDrag(event);
 
 if(!this.options.quiet){
 Position.prepare();
 Droppables.show(pointer, this.element);
 }
 
 Draggables.notify('onDrag', this, event);
 
 this.draw(pointer);
 if(this.options.change) this.options.change(this);
 
 if(this.options.scroll) {
 this.stopScrolling();
 
 var p;
 if (this.options.scroll == window) {
 with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
 } else {
 p = Position.page(this.options.scroll);
 p[0] += this.options.scroll.scrollLeft + Position.deltaX;
 p[1] += this.options.scroll.scrollTop + Position.deltaY;
 p.push(p[0]+this.options.scroll.offsetWidth);
 p.push(p[1]+this.options.scroll.offsetHeight);
 }
 var speed = [0,0];
 if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
 if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
 if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
 if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
 this.startScrolling(speed);
 }
 
 // fix AppleWebKit rendering
 if(Prototype.Browser.WebKit) window.scrollBy(0,0);
 
 Event.stop(event);
 },
 
 finishDrag: function(event, success) {
 this.dragging = false;
 
 if(this.options.quiet){
 Position.prepare();
 var pointer = [Event.pointerX(event), Event.pointerY(event)];
 Droppables.show(pointer, this.element);
 }

 if(this.options.ghosting) {
 Position.relativize(this.element);
 Element.remove(this._clone);
 this._clone = null;
 }

 var dropped = false; 
 if(success) { 
 dropped = Droppables.fire(event, this.element); 
 if (!dropped) dropped = false; 
 }
 if(dropped && this.options.onDropped) this.options.onDropped(this.element);
 Draggables.notify('onEnd', this, event);

 var revert = this.options.revert;
 if(revert && typeof revert == 'function') revert = revert(this.element);
 
 var d = this.currentDelta();
 if(revert && this.options.reverteffect) {
 if (dropped == 0 || revert != 'failure')
 this.options.reverteffect(this.element,
 d[1]-this.delta[1], d[0]-this.delta[0]);
 } else {
 this.delta = d;
 }

 if(this.options.zindex)
 this.element.style.zIndex = this.originalZ;

 if(this.options.endeffect) 
 this.options.endeffect(this.element);
 
 Draggables.deactivate(this);
 Droppables.reset();
 },
 
 keyPress: function(event) {
 if(event.keyCode!=Event.KEY_ESC) return;
 this.finishDrag(event, false);
 Event.stop(event);
 },
 
 endDrag: function(event) {
 if(!this.dragging) return;
 this.stopScrolling();
 this.finishDrag(event, true);
 Event.stop(event);
 },
 
 draw: function(point) {
 var pos = Position.cumulativeOffset(this.element);
 if(this.options.ghosting) {
 var r = Position.realOffset(this.element);
 pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
 }
 
 var d = this.currentDelta();
 pos[0] -= d[0]; pos[1] -= d[1];
 
 if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
 pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
 pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
 }
 
 var p = [0,1].map(function(i){ 
 return (point[i]-pos[i]-this.offset[i]) 
 }.bind(this));
 
 if(this.options.snap) {
 if(typeof this.options.snap == 'function') {
 p = this.options.snap(p[0],p[1],this);
 } else {
 if(this.options.snap instanceof Array) {
 p = p.map( function(v, i) {
 return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
 } else {
 p = p.map( function(v) {
 return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
 }
 }}
 
 var style = this.element.style;
 if((!this.options.constraint) || (this.options.constraint=='horizontal'))
 style.left = p[0] + "px";
 if((!this.options.constraint) || (this.options.constraint=='vertical'))
 style.top = p[1] + "px";
 
 if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
 },
 
 stopScrolling: function() {
 if(this.scrollInterval) {
 clearInterval(this.scrollInterval);
 this.scrollInterval = null;
 Draggables._lastScrollPointer = null;
 }
 },
 
 startScrolling: function(speed) {
 if(!(speed[0] || speed[1])) return;
 this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
 this.lastScrolled = new Date();
 this.scrollInterval = setInterval(this.scroll.bind(this), 10);
 },
 
 scroll: function() {
 var current = new Date();
 var delta = current - this.lastScrolled;
 this.lastScrolled = current;
 if(this.options.scroll == window) {
 with (this._getWindowScroll(this.options.scroll)) {
 if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
 var d = delta / 1000;
 this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
 }
 }
 } else {
 this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
 this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
 }
 
 Position.prepare();
 Droppables.show(Draggables._lastPointer, this.element);
 Draggables.notify('onDrag', this);
 if (this._isScrollChild) {
 Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
 Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
 Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
 if (Draggables._lastScrollPointer[0] < 0)
 Draggables._lastScrollPointer[0] = 0;
 if (Draggables._lastScrollPointer[1] < 0)
 Draggables._lastScrollPointer[1] = 0;
 this.draw(Draggables._lastScrollPointer);
 }
 
 if(this.options.change) this.options.change(this);
 },
 
 _getWindowScroll: function(w) {
 var T, L, W, H;
 with (w.document) {
 if (w.document.documentElement && documentElement.scrollTop) {
 T = documentElement.scrollTop;
 L = documentElement.scrollLeft;
 } else if (w.document.body) {
 T = body.scrollTop;
 L = body.scrollLeft;
 }
 if (w.innerWidth) {
 W = w.innerWidth;
 H = w.innerHeight;
 } else if (w.document.documentElement && documentElement.clientWidth) {
 W = documentElement.clientWidth;
 H = documentElement.clientHeight;
 } else {
 W = body.offsetWidth;
 H = body.offsetHeight
 }
 }
 return { top: T, left: L, width: W, height: H };
 }
}

/*--------------------------------------------------------------------------*/

var SortableObserver = Class.create();
SortableObserver.prototype = {
 initialize: function(element, observer) {
 this.element = $(element);
 this.observer = observer;
 this.lastValue = Sortable.serialize(this.element);
 },
 
 onStart: function() {
 this.lastValue = Sortable.serialize(this.element);
 },
 
 onEnd: function() {
 Sortable.unmark();
 if(this.lastValue != Sortable.serialize(this.element))
 this.observer(this.element)
 }
}

var Sortable = {
 SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
 
 sortables: {},
 
 _findRootElement: function(element) {
 while (element.tagName.toUpperCase() != "BODY") { 
 if(element.id && Sortable.sortables[element.id]) return element;
 element = element.parentNode;
 }
 },

 options: function(element) {
 element = Sortable._findRootElement($(element));
 if(!element) return;
 return Sortable.sortables[element.id];
 },
 
 destroy: function(element){
 var s = Sortable.options(element);
 
 if(s) {
 Draggables.removeObserver(s.element);
 s.droppables.each(function(d){ Droppables.remove(d) });
 s.draggables.invoke('destroy');
 
 delete Sortable.sortables[s.element.id];
 }
 },

 create: function(element) {
 element = $(element);
 var options = Object.extend({ 
 element: element,
 tag: 'li', // assumes li children, override with tag: 'tagname'
 dropOnEmpty: false,
 tree: false,
 treeTag: 'ul',
 overlap: 'vertical', // one of 'vertical', 'horizontal'
 constraint: 'vertical', // one of 'vertical', 'horizontal', false
 containment: element, // also takes array of elements (or id's); or false
 handle: false, // or a CSS class
 only: false,
 delay: 0,
 hoverclass: null,
 ghosting: false,
 quiet: false, 
 scroll: false,
 scrollSensitivity: 20,
 scrollSpeed: 15,
 format: this.SERIALIZE_RULE,
 
 // these take arrays of elements or ids and can be 
 // used for better initialization performance
 elements: false,
 handles: false,
 
 onChange: Prototype.emptyFunction,
 onUpdate: Prototype.emptyFunction
 }, arguments[1] || {});

 // clear any old sortable with same element
 this.destroy(element);

 // build options for the draggables
 var options_for_draggable = {
 revert: true,
 quiet: options.quiet,
 scroll: options.scroll,
 scrollSpeed: options.scrollSpeed,
 scrollSensitivity: options.scrollSensitivity,
 delay: options.delay,
 ghosting: options.ghosting,
 constraint: options.constraint,
 handle: options.handle };

 if(options.starteffect)
 options_for_draggable.starteffect = options.starteffect;

 if(options.reverteffect)
 options_for_draggable.reverteffect = options.reverteffect;
 else
 if(options.ghosting) options_for_draggable.reverteffect = function(element) {
 element.style.top = 0;
 element.style.left = 0;
 };

 if(options.endeffect)
 options_for_draggable.endeffect = options.endeffect;

 if(options.zindex)
 options_for_draggable.zindex = options.zindex;

 // build options for the droppables 
 var options_for_droppable = {
 overlap: options.overlap,
 containment: options.containment,
 tree: options.tree,
 hoverclass: options.hoverclass,
 onHover: Sortable.onHover
 }
 
 var options_for_tree = {
 onHover: Sortable.onEmptyHover,
 overlap: options.overlap,
 containment: options.containment,
 hoverclass: options.hoverclass
 }

 // fix for gecko engine
 Element.cleanWhitespace(element); 

 options.draggables = [];
 options.droppables = [];

 // drop on empty handling
 if(options.dropOnEmpty || options.tree) {
 Droppables.add(element, options_for_tree);
 options.droppables.push(element);
 }

 (options.elements || this.findElements(element, options) || []).each( function(e,i) {
 var handle = options.handles ? $(options.handles[i]) :
 (options.handle ? $(e).getElementsByClassName(options.handle)[0] : e); 
 options.draggables.push(
 new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
 Droppables.add(e, options_for_droppable);
 if(options.tree) e.treeNode = element;
 options.droppables.push(e); 
 });
 
 if(options.tree) {
 (Sortable.findTreeElements(element, options) || []).each( function(e) {
 Droppables.add(e, options_for_tree);
 e.treeNode = element;
 options.droppables.push(e);
 });
 }

 // keep reference
 this.sortables[element.id] = options;

 // for onupdate
 Draggables.addObserver(new SortableObserver(element, options.onUpdate));

 },

 // return all suitable-for-sortable elements in a guaranteed order
 findElements: function(element, options) {
 return Element.findChildren(
 element, options.only, options.tree ? true : false, options.tag);
 },
 
 findTreeElements: function(element, options) {
 return Element.findChildren(
 element, options.only, options.tree ? true : false, options.treeTag);
 },

 onHover: function(element, dropon, overlap) {
 if(Element.isParent(dropon, element)) return;

 if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
 return;
 } else if(overlap>0.5) {
 Sortable.mark(dropon, 'before');
 if(dropon.previousSibling != element) {
 var oldParentNode = element.parentNode;
 element.style.visibility = "hidden"; // fix gecko rendering
 dropon.parentNode.insertBefore(element, dropon);
 if(dropon.parentNode!=oldParentNode) 
 Sortable.options(oldParentNode).onChange(element);
 Sortable.options(dropon.parentNode).onChange(element);
 }
 } else {
 Sortable.mark(dropon, 'after');
 var nextElement = dropon.nextSibling || null;
 if(nextElement != element) {
 var oldParentNode = element.parentNode;
 element.style.visibility = "hidden"; // fix gecko rendering
 dropon.parentNode.insertBefore(element, nextElement);
 if(dropon.parentNode!=oldParentNode) 
 Sortable.options(oldParentNode).onChange(element);
 Sortable.options(dropon.parentNode).onChange(element);
 }
 }
 },
 
 onEmptyHover: function(element, dropon, overlap) {
 var oldParentNode = element.parentNode;
 var droponOptions = Sortable.options(dropon);
 
 if(!Element.isParent(dropon, element)) {
 var index;
 
 var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
 var child = null;
 
 if(children) {
 var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
 
 for (index = 0; index < children.length; index += 1) {
 if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
 offset -= Element.offsetSize (children[index], droponOptions.overlap);
 } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
 child = index + 1 < children.length ? children[index + 1] : null;
 break;
 } else {
 child = children[index];
 break;
 }
 }
 }
 
 dropon.insertBefore(element, child);
 
 Sortable.options(oldParentNode).onChange(element);
 droponOptions.onChange(element);
 }
 },

 unmark: function() {
 if(Sortable._marker) Sortable._marker.hide();
 },

 mark: function(dropon, position) {
 // mark on ghosting only
 var sortable = Sortable.options(dropon.parentNode);
 if(sortable && !sortable.ghosting) return; 

 if(!Sortable._marker) {
 Sortable._marker = 
 ($('dropmarker') || Element.extend(document.createElement('DIV'))).
 hide().addClassName('dropmarker').setStyle({position:'absolute'});
 document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
 } 
 var offsets = Position.cumulativeOffset(dropon);
 Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
 
 if(position=='after')
 if(sortable.overlap == 'horizontal') 
 Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
 else
 Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
 
 Sortable._marker.show();
 },
 
 _tree: function(element, options, parent) {
 var children = Sortable.findElements(element, options) || [];
 
 for (var i = 0; i < children.length; ++i) {
 var match = children[i].id.match(options.format);

 if (!match) continue;
 
 var child = {
 id: encodeURIComponent(match ? match[1] : null),
 element: element,
 parent: parent,
 children: [],
 position: parent.children.length,
 container: $(children[i]).down(options.treeTag)
 }
 
 /* Get the element containing the children and recurse over it */
 if (child.container)
 this._tree(child.container, options, child)
 
 parent.children.push (child);
 }

 return parent; 
 },

 tree: function(element) {
 element = $(element);
 var sortableOptions = this.options(element);
 var options = Object.extend({
 tag: sortableOptions.tag,
 treeTag: sortableOptions.treeTag,
 only: sortableOptions.only,
 name: element.id,
 format: sortableOptions.format
 }, arguments[1] || {});
 
 var root = {
 id: null,
 parent: null,
 children: [],
 container: element,
 position: 0
 }
 
 return Sortable._tree(element, options, root);
 },

 /* Construct a [i] index for a particular node */
 _constructIndex: function(node) {
 var index = '';
 do {
 if (node.id) index = '[' + node.position + ']' + index;
 } while ((node = node.parent) != null);
 return index;
 },

 sequence: function(element) {
 element = $(element);
 var options = Object.extend(this.options(element), arguments[1] || {});
 
 return $(this.findElements(element, options) || []).map( function(item) {
 return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
 });
 },

 setSequence: function(element, new_sequence) {
 element = $(element);
 var options = Object.extend(this.options(element), arguments[2] || {});
 
 var nodeMap = {};
 this.findElements(element, options).each( function(n) {
 if (n.id.match(options.format))
 nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
 n.parentNode.removeChild(n);
 });
 
 new_sequence.each(function(ident) {
 var n = nodeMap[ident];
 if (n) {
 n[1].appendChild(n[0]);
 delete nodeMap[ident];
 }
 });
 },
 
 serialize: function(element) {
 element = $(element);
 var options = Object.extend(Sortable.options(element), arguments[1] || {});
 var name = encodeURIComponent(
 (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
 
 if (options.tree) {
 return Sortable.tree(element, arguments[1]).children.map( function (item) {
 return [name + Sortable._constructIndex(item) + "[id]=" + 
 encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
 }).flatten().join('&');
 } else {
 return Sortable.sequence(element, arguments[1]).map( function(item) {
 return name + "[]=" + encodeURIComponent(item);
 }).join('&');
 }
 }
}

// Returns true if child is contained within element
Element.isParent = function(child, element) {
 if (!child.parentNode || child == element) return false;
 if (child.parentNode == element) return true;
 return Element.isParent(child.parentNode, element);
}

Element.findChildren = function(element, only, recursive, tagName) { 
 if(!element.hasChildNodes()) return null;
 tagName = tagName.toUpperCase();
 if(only) only = [only].flatten();
 var elements = [];
 $A(element.childNodes).each( function(e) {
 if(e.tagName && e.tagName.toUpperCase()==tagName &&
 (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
 elements.push(e);
 if(recursive) {
 var grandchildren = Element.findChildren(e, only, recursive, tagName);
 if(grandchildren) elements.push(grandchildren);
 }
 });

 return (elements.length>0 ? elements.flatten() : []);
}

Element.offsetSize = function (element, type) {
 return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
}
// script.aculo.us controls.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007

// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
// 
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

// Autocompleter.Base handles all the autocompletion functionality 
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least, 
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method 
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most 
// useful when one of the tokens is \n (a newline), as it 
// allows smart autocompletion after linebreaks.

if(typeof Effect == 'undefined')
 throw("controls.js requires including script.aculo.us' effects.js library");

var Autocompleter = {}
Autocompleter.Base = function() {};
Autocompleter.Base.prototype = {
 baseInitialize: function(element, update, options) {
 element = $(element)
 this.element = element; 
 this.update = $(update); 
 this.hasFocus = false; 
 this.changed = false; 
 this.active = false; 
 this.index = 0; 
 this.entryCount = 0;

 if(this.setOptions)
 this.setOptions(options);
 else
 this.options = options || {};

 this.options.paramName = this.options.paramName || this.element.name;
 this.options.tokens = this.options.tokens || [];
 this.options.frequency = this.options.frequency || 0.4;
 this.options.minChars = this.options.minChars || 1;
 this.options.onShow = this.options.onShow || 
 function(element, update){ 
 if(!update.style.position || update.style.position=='absolute') {
 update.style.position = 'absolute';
 Position.clone(element, update, {
 setHeight: false, 
 offsetTop: element.offsetHeight
 });
 }
 Effect.Appear(update,{duration:0.15});
 };
 this.options.onHide = this.options.onHide || 
 function(element, update){ new Effect.Fade(update,{duration:0.15}) };

 if(typeof(this.options.tokens) == 'string') 
 this.options.tokens = new Array(this.options.tokens);

 this.observer = null;
 
 this.element.setAttribute('autocomplete','off');

 Element.hide(this.update);

 Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
 Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this));

 // Turn autocomplete back on when the user leaves the page, so that the
 // field's value will be remembered on Mozilla-based browsers.
 Event.observe(window, 'beforeunload', function(){ 
 element.setAttribute('autocomplete', 'on'); 
 });
 },

 show: function() {
 if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
 if(!this.iefix && 
 (Prototype.Browser.IE) &&
 (Element.getStyle(this.update, 'position')=='absolute')) {
 new Insertion.After(this.update, 
 '<iframe id="' + this.update.id + '_iefix" '+
 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
 this.iefix = $(this.update.id+'_iefix');
 }
 if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
 },
 
 fixIEOverlapping: function() {
 Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
 this.iefix.style.zIndex = 1;
 this.update.style.zIndex = 2;
 Element.show(this.iefix);
 },

 hide: function() {
 this.stopIndicator();
 if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
 if(this.iefix) Element.hide(this.iefix);
 },

 startIndicator: function() {
 if(this.options.indicator) Element.show(this.options.indicator);
 },

 stopIndicator: function() {
 if(this.options.indicator) Element.hide(this.options.indicator);
 },

 onKeyPress: function(event) {
 if(this.active)
 switch(event.keyCode) {
 case Event.KEY_TAB:
 case Event.KEY_RETURN:
 this.selectEntry();
 Event.stop(event);
 case Event.KEY_ESC:
 this.hide();
 this.active = false;
 Event.stop(event);
 return;
 case Event.KEY_LEFT:
 case Event.KEY_RIGHT:
 return;
 case Event.KEY_UP:
 this.markPrevious();
 this.render();
 if(Prototype.Browser.WebKit) Event.stop(event);
 return;
 case Event.KEY_DOWN:
 this.markNext();
 this.render();
 if(Prototype.Browser.WebKit) Event.stop(event);
 return;
 }
 else 
 if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 
 (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;

 this.changed = true;
 this.hasFocus = true;

 if(this.observer) clearTimeout(this.observer);
 this.observer = 
 setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
 },

 activate: function() {
 this.changed = false;
 this.hasFocus = true;
 this.getUpdatedChoices();
 },

 onHover: function(event) {
 var element = Event.findElement(event, 'LI');
 if(this.index != element.autocompleteIndex) 
 {
 this.index = element.autocompleteIndex;
 this.render();
 }
 Event.stop(event);
 },
 
 onClick: function(event) {
 var element = Event.findElement(event, 'LI');
 this.index = element.autocompleteIndex;
 this.selectEntry();
 this.hide();
 },
 
 onBlur: function(event) {
 // needed to make click events working
 setTimeout(this.hide.bind(this), 250);
 this.hasFocus = false;
 this.active = false; 
 }, 
 
 render: function() {
 if(this.entryCount > 0) {
 for (var i = 0; i < this.entryCount; i++)
 this.index==i ? 
 Element.addClassName(this.getEntry(i),"selected") : 
 Element.removeClassName(this.getEntry(i),"selected");
 if(this.hasFocus) { 
 this.show();
 this.active = true;
 }
 } else {
 this.active = false;
 this.hide();
 }
 },
 
 markPrevious: function() {
 if(this.index > 0) this.index--
 else this.index = this.entryCount-1;
 this.getEntry(this.index).scrollIntoView(true);
 },
 
 markNext: function() {
 if(this.index < this.entryCount-1) this.index++
 else this.index = 0;
 this.getEntry(this.index).scrollIntoView(false);
 },
 
 getEntry: function(index) {
 return this.update.firstChild.childNodes[index];
 },
 
 getCurrentEntry: function() {
 return this.getEntry(this.index);
 },
 
 selectEntry: function() {
 this.active = false;
 this.updateElement(this.getCurrentEntry());
 },

 updateElement: function(selectedElement) {
 if (this.options.updateElement) {
 this.options.updateElement(selectedElement);
 return;
 }
 var value = '';
 if (this.options.select) {
 var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
 if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
 } else
 value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
 
 var lastTokenPos = this.findLastToken();
 if (lastTokenPos != -1) {
 var newValue = this.element.value.substr(0, lastTokenPos + 1);
 var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
 if (whitespace)
 newValue += whitespace[0];
 this.element.value = newValue + value;
 } else {
 this.element.value = value;
 }
 this.element.focus();
 
 if (this.options.afterUpdateElement)
 this.options.afterUpdateElement(this.element, selectedElement);
 },

 updateChoices: function(choices) {
 if(!this.changed && this.hasFocus) {
 this.update.innerHTML = choices;
 Element.cleanWhitespace(this.update);
 Element.cleanWhitespace(this.update.down());

 if(this.update.firstChild && this.update.down().childNodes) {
 this.entryCount = 
 this.update.down().childNodes.length;
 for (var i = 0; i < this.entryCount; i++) {
 var entry = this.getEntry(i);
 entry.autocompleteIndex = i;
 this.addObservers(entry);
 }
 } else { 
 this.entryCount = 0;
 }

 this.stopIndicator();
 this.index = 0;
 
 if(this.entryCount==1 && this.options.autoSelect) {
 this.selectEntry();
 this.hide();
 } else {
 this.render();
 }
 }
 },

 addObservers: function(element) {
 Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
 Event.observe(element, "click", this.onClick.bindAsEventListener(this));
 },

 onObserverEvent: function() {
 this.changed = false; 
 if(this.getToken().length>=this.options.minChars) {
 this.getUpdatedChoices();
 } else {
 this.active = false;
 this.hide();
 }
 },

 getToken: function() {
 var tokenPos = this.findLastToken();
 if (tokenPos != -1)
 var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
 else
 var ret = this.element.value;

 return /\n/.test(ret) ? '' : ret;
 },

 findLastToken: function() {
 var lastTokenPos = -1;

 for (var i=0; i<this.options.tokens.length; i++) {
 var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
 if (thisTokenPos > lastTokenPos)
 lastTokenPos = thisTokenPos;
 }
 return lastTokenPos;
 }
}

Ajax.Autocompleter = Class.create();
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
 initialize: function(element, update, url, options) {
 this.baseInitialize(element, update, options);
 this.options.asynchronous = true;
 this.options.onComplete = this.onComplete.bind(this);
 this.options.defaultParams = this.options.parameters || null;
 this.url = url;
 },

 getUpdatedChoices: function() {
 this.startIndicator();
 
 var entry = encodeURIComponent(this.options.paramName) + '=' + 
 encodeURIComponent(this.getToken());

 this.options.parameters = this.options.callback ?
 this.options.callback(this.element, entry) : entry;

 if(this.options.defaultParams) 
 this.options.parameters += '&' + this.options.defaultParams;
 
 new Ajax.Request(this.url, this.options);
 },

 onComplete: function(request) {
 this.updateChoices(request.responseText);
 }

});

// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
// text only at the beginning of strings in the 
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
// search anywhere in the string, additionally set
// the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
// a partial match (unlike minChars, which defines
// how many characters are required to do any match
// at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
// It's possible to pass in a custom function as the 'selector' 
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.

Autocompleter.Local = Class.create();
Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
 initialize: function(element, update, array, options) {
 this.baseInitialize(element, update, options);
 this.options.array = array;
 },

 getUpdatedChoices: function() {
 this.updateChoices(this.options.selector(this));
 },

 setOptions: function(options) {
 this.options = Object.extend({
 choices: 10,
 partialSearch: true,
 partialChars: 2,
 ignoreCase: true,
 fullSearch: false,
 selector: function(instance) {
 var ret = []; // Beginning matches
 var partial = []; // Inside matches
 var entry = instance.getToken();
 var count = 0;

 for (var i = 0; i < instance.options.array.length && 
 ret.length < instance.options.choices ; i++) { 

 var elem = instance.options.array[i];
 var foundPos = instance.options.ignoreCase ? 
 elem.toLowerCase().indexOf(entry.toLowerCase()) : 
 elem.indexOf(entry);

 while (foundPos != -1) {
 if (foundPos == 0 && elem.length != entry.length) { 
 ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 
 elem.substr(entry.length) + "</li>");
 break;
 } else if (entry.length >= instance.options.partialChars && 
 instance.options.partialSearch && foundPos != -1) {
 if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
 partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
 elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
 foundPos + entry.length) + "</li>");
 break;
 }
 }

 foundPos = instance.options.ignoreCase ? 
 elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 
 elem.indexOf(entry, foundPos + 1);

 }
 }
 if (partial.length)
 ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
 return "<ul>" + ret.join('') + "</ul>";
 }
 }, options || {});
 }
});

// AJAX in-place editor
//
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor

// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
 setTimeout(function() {
 Field.activate(field);
 }, 1);
}

Ajax.InPlaceEditor = Class.create();
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
Ajax.InPlaceEditor.prototype = {
 initialize: function(element, url, options) {
 this.url = url;
 this.element = $(element);

 this.options = Object.extend({
 paramName: "value",
 okButton: true,
 okLink: false,
 okText: "ok",
 cancelButton: false,
 cancelLink: true,
 cancelText: "cancel",
 textBeforeControls: '',
 textBetweenControls: '',
 textAfterControls: '',
 savingText: "Saving...",
 clickToEditText: "Click to edit",
 okText: "ok",
 rows: 1,
 onComplete: function(transport, element) {
 new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
 },
 onFailure: function(transport) {
 alert("Error communicating with the server: " + transport.responseText.stripTags());
 },
 callback: function(form) {
 return Form.serialize(form);
 },
 handleLineBreaks: true,
 loadingText: 'Loading...',
 savingClassName: 'inplaceeditor-saving',
 loadingClassName: 'inplaceeditor-loading',
 formClassName: 'inplaceeditor-form',
 highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
 highlightendcolor: "#FFFFFF",
 externalControl: null,
 submitOnBlur: false,
 ajaxOptions: {},
 evalScripts: false
 }, options || {});

 if(!this.options.formId && this.element.id) {
 this.options.formId = this.element.id + "-inplaceeditor";
 if ($(this.options.formId)) {
 // there's already a form with that name, don't specify an id
 this.options.formId = null;
 }
 }
 
 if (this.options.externalControl) {
 this.options.externalControl = $(this.options.externalControl);
 }
 
 this.originalBackground = Element.getStyle(this.element, 'background-color');
 if (!this.originalBackground) {
 this.originalBackground = "transparent";
 }
 
 this.element.title = this.options.clickToEditText;
 
 this.onclickListener = this.enterEditMode.bindAsEventListener(this);
 this.mouseoverListener = this.enterHover.bindAsEventListener(this);
 this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
 Event.observe(this.element, 'click', this.onclickListener);
 Event.observe(this.element, 'mouseover', this.mouseoverListener);
 Event.observe(this.element, 'mouseout', this.mouseoutListener);
 if (this.options.externalControl) {
 Event.observe(this.options.externalControl, 'click', this.onclickListener);
 Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
 Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
 }
 },
 enterEditMode: function(evt) {
 if (this.saving) return;
 if (this.editing) return;
 this.editing = true;
 this.onEnterEditMode();
 if (this.options.externalControl) {
 Element.hide(this.options.externalControl);
 }
 Element.hide(this.element);
 this.createForm();
 this.element.parentNode.insertBefore(this.form, this.element);
 if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);
 // stop the event to avoid a page refresh in Safari
 if (evt) {
 Event.stop(evt);
 }
 return false;
 },
 createForm: function() {
 this.form = document.createElement("form");
 this.form.id = this.options.formId;
 Element.addClassName(this.form, this.options.formClassName)
 this.form.onsubmit = this.onSubmit.bind(this);

 this.createEditField();

 if (this.options.textarea) {
 var br = document.createElement("br");
 this.form.appendChild(br);
 }
 
 if (this.options.textBeforeControls)
 this.form.appendChild(document.createTextNode(this.options.textBeforeControls));

 if (this.options.okButton) {
 var okButton = document.createElement("input");
 okButton.type = "submit";
 okButton.value = this.options.okText;
 okButton.className = 'editor_ok_button';
 this.form.appendChild(okButton);
 }
 
 if (this.options.okLink) {
 var okLink = document.createElement("a");
 okLink.href = "#";
 okLink.appendChild(document.createTextNode(this.options.okText));
 okLink.onclick = this.onSubmit.bind(this);
 okLink.className = 'editor_ok_link';
 this.form.appendChild(okLink);
 }
 
 if (this.options.textBetweenControls && 
 (this.options.okLink || this.options.okButton) && 
 (this.options.cancelLink || this.options.cancelButton))
 this.form.appendChild(document.createTextNode(this.options.textBetweenControls));
 
 if (this.options.cancelButton) {
 var cancelButton = document.createElement("input");
 cancelButton.type = "submit";
 cancelButton.value = this.options.cancelText;
 cancelButton.onclick = this.onclickCancel.bind(this);
 cancelButton.className = 'editor_cancel_button';
 this.form.appendChild(cancelButton);
 }

 if (this.options.cancelLink) {
 var cancelLink = document.createElement("a");
 cancelLink.href = "#";
 cancelLink.appendChild(document.createTextNode(this.options.cancelText));
 cancelLink.onclick = this.onclickCancel.bind(this);
 cancelLink.className = 'editor_cancel editor_cancel_link'; 
 this.form.appendChild(cancelLink);
 }
 
 if (this.options.textAfterControls)
 this.form.appendChild(document.createTextNode(this.options.textAfterControls));
 },
 hasHTMLLineBreaks: function(string) {
 if (!this.options.handleLineBreaks) return false;
 return string.match(/<br/i) || string.match(/<p>/i);
 },
 convertHTMLLineBreaks: function(string) {
 return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
 },
 createEditField: function() {
 var text;
 if(this.options.loadTextURL) {
 text = this.options.loadingText;
 } else {
 text = this.getText();
 }

 var obj = this;
 
 if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
 this.options.textarea = false;
 var textField = document.createElement("input");
 textField.obj = this;
 textField.type = "text";
 textField.name = this.options.paramName;
 textField.value = text;
 textField.style.backgroundColor = this.options.highlightcolor;
 textField.className = 'editor_field';
 var size = this.options.size || this.options.cols || 0;
 if (size != 0) textField.size = size;
 if (this.options.submitOnBlur)
 textField.onblur = this.onSubmit.bind(this);
 this.editField = textField;
 } else {
 this.options.textarea = true;
 var textArea = document.createElement("textarea");
 textArea.obj = this;
 textArea.name = this.options.paramName;
 textArea.value = this.convertHTMLLineBreaks(text);
 textArea.rows = this.options.rows;
 textArea.cols = this.options.cols || 40;
 textArea.className = 'editor_field'; 
 if (this.options.submitOnBlur)
 textArea.onblur = this.onSubmit.bind(this);
 this.editField = textArea;
 }
 
 if(this.options.loadTextURL) {
 this.loadExternalText();
 }
 this.form.appendChild(this.editField);
 },
 getText: function() {
 return this.element.innerHTML;
 },
 loadExternalText: function() {
 Element.addClassName(this.form, this.options.loadingClassName);
 this.editField.disabled = true;
 new Ajax.Request(
 this.options.loadTextURL,
 Object.extend({
 asynchronous: true,
 onComplete: this.onLoadedExternalText.bind(this)
 }, this.options.ajaxOptions)
 );
 },
 onLoadedExternalText: function(transport) {
 Element.removeClassName(this.form, this.options.loadingClassName);
 this.editField.disabled = false;
 this.editField.value = transport.responseText.stripTags();
 Field.scrollFreeActivate(this.editField);
 },
 onclickCancel: function() {
 this.onComplete();
 this.leaveEditMode();
 return false;
 },
 onFailure: function(transport) {
 this.options.onFailure(transport);
 if (this.oldInnerHTML) {
 this.element.innerHTML = this.oldInnerHTML;
 this.oldInnerHTML = null;
 }
 return false;
 },
 onSubmit: function() {
 // onLoading resets these so we need to save them away for the Ajax call
 var form = this.form;
 var value = this.editField.value;
 
 // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
 // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
 // to be displayed indefinitely
 this.onLoading();
 
 if (this.options.evalScripts) {
 new Ajax.Request(
 this.url, Object.extend({
 parameters: this.options.callback(form, value),
 onComplete: this.onComplete.bind(this),
 onFailure: this.onFailure.bind(this),
 asynchronous:true, 
 evalScripts:true
 }, this.options.ajaxOptions));
 } else {
 new Ajax.Updater(
 { success: this.element,
 // don't update on failure (this could be an option)
 failure: null }, 
 this.url, Object.extend({
 parameters: this.options.callback(form, value),
 onComplete: this.onComplete.bind(this),
 onFailure: this.onFailure.bind(this)
 }, this.options.ajaxOptions));
 }
 // stop the event to avoid a page refresh in Safari
 if (arguments.length > 1) {
 Event.stop(arguments[0]);
 }
 return false;
 },
 onLoading: function() {
 this.saving = true;
 this.removeForm();
 this.leaveHover();
 this.showSaving();
 },
 showSaving: function() {
 this.oldInnerHTML = this.element.innerHTML;
 this.element.innerHTML = this.options.savingText;
 Element.addClassName(this.element, this.options.savingClassName);
 this.element.style.backgroundColor = this.originalBackground;
 Element.show(this.element);
 },
 removeForm: function() {
 if(this.form) {
 if (this.form.parentNode) Element.remove(this.form);
 this.form = null;
 }
 },
 enterHover: function() {
 if (this.saving) return;
 this.element.style.backgroundColor = this.options.highlightcolor;
 if (this.effect) {
 this.effect.cancel();
 }
 Element.addClassName(this.element, this.options.hoverClassName)
 },
 leaveHover: function() {
 if (this.options.backgroundColor) {
 this.element.style.backgroundColor = this.oldBackground;
 }
 Element.removeClassName(this.element, this.options.hoverClassName)
 if (this.saving) return;
 this.effect = new Effect.Highlight(this.element, {
 startcolor: this.options.highlightcolor,
 endcolor: this.options.highlightendcolor,
 restorecolor: this.originalBackground
 });
 },
 leaveEditMode: function() {
 Element.removeClassName(this.element, this.options.savingClassName);
 this.removeForm();
 this.leaveHover();
 this.element.style.backgroundColor = this.originalBackground;
 Element.show(this.element);
 if (this.options.externalControl) {
 Element.show(this.options.externalControl);
 }
 this.editing = false;
 this.saving = false;
 this.oldInnerHTML = null;
 this.onLeaveEditMode();
 },
 onComplete: function(transport) {
 this.leaveEditMode();
 this.options.onComplete.bind(this)(transport, this.element);
 },
 onEnterEditMode: function() {},
 onLeaveEditMode: function() {},
 dispose: function() {
 if (this.oldInnerHTML) {
 this.element.innerHTML = this.oldInnerHTML;
 }
 this.leaveEditMode();
 Event.stopObserving(this.element, 'click', this.onclickListener);
 Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
 Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
 if (this.options.externalControl) {
 Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
 Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
 Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
 }
 }
};

Ajax.InPlaceCollectionEditor = Class.create();
Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
 createEditField: function() {
 if (!this.cached_selectTag) {
 var selectTag = document.createElement("select");
 var collection = this.options.collection || [];
 var optionTag;
 collection.each(function(e,i) {
 optionTag = document.createElement("option");
 optionTag.value = (e instanceof Array) ? e[0] : e;
 if((typeof this.options.value == 'undefined') && 
 ((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true;
 if(this.options.value==optionTag.value) optionTag.selected = true;
 optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
 selectTag.appendChild(optionTag);
 }.bind(this));
 this.cached_selectTag = selectTag;
 }

 this.editField = this.cached_selectTag;
 if(this.options.loadTextURL) this.loadExternalText();
 this.form.appendChild(this.editField);
 this.options.callback = function(form, value) {
 return "value=" + encodeURIComponent(value);
 }
 }
});

// Delayed observer, like Form.Element.Observer, 
// but waits for delay after last key input
// Ideal for live-search fields

Form.Element.DelayedObserver = Class.create();
Form.Element.DelayedObserver.prototype = {
 initialize: function(element, delay, callback) {
 this.delay = delay || 0.5;
 this.element = $(element);
 this.callback = callback;
 this.timer = null;
 this.lastValue = $F(this.element); 
 Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
 },
 delayedListener: function(event) {
 if(this.lastValue == $F(this.element)) return;
 if(this.timer) clearTimeout(this.timer);
 this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
 this.lastValue = $F(this.element);
 },
 onTimerEvent: function() {
 this.timer = null;
 this.callback(this.element, $F(this.element));
 }
};
// script.aculo.us slider.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007

// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs 
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

if(!Control) var Control = {};
Control.Slider = Class.create();

// options:
// axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
// onChange(value)
// onSlide(value)
Control.Slider.prototype = {
 initialize: function(handle, track, options) {
 var slider = this;
 
 if(handle instanceof Array) {
 this.handles = handle.collect( function(e) { return $(e) });
 } else {
 this.handles = [$(handle)];
 }
 
 this.track = $(track);
 this.options = options || {};

 this.axis = this.options.axis || 'horizontal';
 this.increment = this.options.increment || 1;
 this.step = parseInt(this.options.step || '1');
 this.range = this.options.range || $R(0,1);
 
 this.value = 0; // assure backwards compat
 this.values = this.handles.map( function() { return 0 });
 this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
 this.options.startSpan = $(this.options.startSpan || null);
 this.options.endSpan = $(this.options.endSpan || null);

 this.restricted = this.options.restricted || false;

 this.maximum = this.options.maximum || this.range.end;
 this.minimum = this.options.minimum || this.range.start;

 // Will be used to align the handle onto the track, if necessary
 this.alignX = parseInt(this.options.alignX || '0');
 this.alignY = parseInt(this.options.alignY || '0');
 
 this.trackLength = this.maximumOffset() - this.minimumOffset();

 this.handleLength = this.isVertical() ? 
 (this.handles[0].offsetHeight != 0 ? 
 this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : 
 (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : 
 this.handles[0].style.width.replace(/px$/,""));

 this.active = false;
 this.dragging = false;
 this.disabled = false;

 if(this.options.disabled) this.setDisabled();

 // Allowed values array
 this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
 if(this.allowedValues) {
 this.minimum = this.allowedValues.min();
 this.maximum = this.allowedValues.max();
 }

 this.eventMouseDown = this.startDrag.bindAsEventListener(this);
 this.eventMouseUp = this.endDrag.bindAsEventListener(this);
 this.eventMouseMove = this.update.bindAsEventListener(this);

 // Initialize handles in reverse (make sure first handle is active)
 this.handles.each( function(h,i) {
 i = slider.handles.length-1-i;
 slider.setValue(parseFloat(
 (slider.options.sliderValue instanceof Array ? 
 slider.options.sliderValue[i] : slider.options.sliderValue) || 
 slider.range.start), i);
 Element.makePositioned(h); // fix IE
 Event.observe(h, "mousedown", slider.eventMouseDown);
 });
 
 Event.observe(this.track, "mousedown", this.eventMouseDown);
 Event.observe(document, "mouseup", this.eventMouseUp);
 Event.observe(document, "mousemove", this.eventMouseMove);
 
 this.initialized = true;
 },
 dispose: function() {
 var slider = this; 
 Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
 Event.stopObserving(document, "mouseup", this.eventMouseUp);
 Event.stopObserving(document, "mousemove", this.eventMouseMove);
 this.handles.each( function(h) {
 Event.stopObserving(h, "mousedown", slider.eventMouseDown);
 });
 },
 setDisabled: function(){
 this.disabled = true;
 },
 setEnabled: function(){
 this.disabled = false;
 }, 
 getNearestValue: function(value){
 if(this.allowedValues){
 if(value >= this.allowedValues.max()) return(this.allowedValues.max());
 if(value <= this.allowedValues.min()) return(this.allowedValues.min());
 
 var offset = Math.abs(this.allowedValues[0] - value);
 var newValue = this.allowedValues[0];
 this.allowedValues.each( function(v) {
 var currentOffset = Math.abs(v - value);
 if(currentOffset <= offset){
 newValue = v;
 offset = currentOffset;
 } 
 });
 return newValue;
 }
 if(value > this.range.end) return this.range.end;
 if(value < this.range.start) return this.range.start;
 return value;
 },
 setValue: function(sliderValue, handleIdx){
 if(!this.active) {
 this.activeHandleIdx = handleIdx || 0;
 this.activeHandle = this.handles[this.activeHandleIdx];
 this.updateStyles();
 }
 handleIdx = handleIdx || this.activeHandleIdx || 0;
 if(this.initialized && this.restricted) {
 if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
 sliderValue = this.values[handleIdx-1];
 if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
 sliderValue = this.values[handleIdx+1];
 }
 sliderValue = this.getNearestValue(sliderValue);
 this.values[handleIdx] = sliderValue;
 this.value = this.values[0]; // assure backwards compat
 
 this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 
 this.translateToPx(sliderValue);
 
 this.drawSpans();
 if(!this.dragging || !this.event) this.updateFinished();
 },
 setValueBy: function(delta, handleIdx) {
 this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 
 handleIdx || this.activeHandleIdx || 0);
 },
 translateToPx: function(value) {
 return Math.round(
 ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 
 (value - this.range.start)) + "px";
 },
 translateToValue: function(offset) {
 return ((offset/(this.trackLength-this.handleLength) * 
 (this.range.end-this.range.start)) + this.range.start);
 },
 getRange: function(range) {
 var v = this.values.sortBy(Prototype.K); 
 range = range || 0;
 return $R(v[range],v[range+1]);
 },
 minimumOffset: function(){
 return(this.isVertical() ? this.alignY : this.alignX);
 },
 maximumOffset: function(){
 return(this.isVertical() ? 
 (this.track.offsetHeight != 0 ? this.track.offsetHeight :
 this.track.style.height.replace(/px$/,"")) - this.alignY : 
 (this.track.offsetWidth != 0 ? this.track.offsetWidth : 
 this.track.style.width.replace(/px$/,"")) - this.alignY);
 }, 
 isVertical: function(){
 return (this.axis == 'vertical');
 },
 drawSpans: function() {
 var slider = this;
 if(this.spans)
 $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
 if(this.options.startSpan)
 this.setSpan(this.options.startSpan,
 $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
 if(this.options.endSpan)
 this.setSpan(this.options.endSpan, 
 $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
 },
 setSpan: function(span, range) {
 if(this.isVertical()) {
 span.style.top = this.translateToPx(range.start);
 span.style.height = this.translateToPx(range.end - range.start + this.range.start);
 } else {
 span.style.left = this.translateToPx(range.start);
 span.style.width = this.translateToPx(range.end - range.start + this.range.start);
 }
 },
 updateStyles: function() {
 this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
 Element.addClassName(this.activeHandle, 'selected');
 },
 startDrag: function(event) {
 if(Event.isLeftClick(event)) {
 if(!this.disabled){
 this.active = true;
 
 var handle = Event.element(event);
 var pointer = [Event.pointerX(event), Event.pointerY(event)];
 var track = handle;
 if(track==this.track) {
 var offsets = Position.cumulativeOffset(this.track); 
 this.event = event;
 this.setValue(this.translateToValue( 
 (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
 ));
 var offsets = Position.cumulativeOffset(this.activeHandle);
 this.offsetX = (pointer[0] - offsets[0]);
 this.offsetY = (pointer[1] - offsets[1]);
 } else {
 // find the handle (prevents issues with Safari)
 while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
 handle = handle.parentNode;
 
 if(this.handles.indexOf(handle)!=-1) {
 this.activeHandle = handle;
 this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
 this.updateStyles();
 
 var offsets = Position.cumulativeOffset(this.activeHandle);
 this.offsetX = (pointer[0] - offsets[0]);
 this.offsetY = (pointer[1] - offsets[1]);
 }
 }
 }
 Event.stop(event);
 }
 },
 update: function(event) {
 if(this.active) {
 if(!this.dragging) this.dragging = true;
 this.draw(event);
 if(Prototype.Browser.WebKit) window.scrollBy(0,0);
 Event.stop(event);
 }
 },
 draw: function(event) {
 var pointer = [Event.pointerX(event), Event.pointerY(event)];
 var offsets = Position.cumulativeOffset(this.track);
 pointer[0] -= this.offsetX + offsets[0];
 pointer[1] -= this.offsetY + offsets[1];
 this.event = event;
 this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
 if(this.initialized && this.options.onSlide)
 this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
 },
 endDrag: function(event) {
 if(this.active && this.dragging) {
 this.finishDrag(event, true);
 Event.stop(event);
 }
 this.active = false;
 this.dragging = false;
 }, 
 finishDrag: function(event, success) {
 this.active = false;
 this.dragging = false;
 this.updateFinished();
 },
 updateFinished: function() {
 if(this.initialized && this.options.onChange) 
 this.options.onChange(this.values.length>1 ? this.values : this.value, this);
 this.event = null;
 }
}/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
 * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 */
function popWin(url,win,para) {
 var win = window.open(url,win,para);
 win.focus();
}

function setLocation(url){
 window.location.href = url;
}

function setPLocation(url, setFocus){
 if( setFocus ) {
 window.opener.focus();
 }
 window.opener.location.href = url;
}

function setLanguageCode(code, fromCode){
 //TODO: javascript cookies have different domain and path than php cookies
 var href = window.location.href;
 var after = '', dash;
 if (dash = href.match(/\#(.*)$/)) {
 href = href.replace(/\#(.*)$/, '');
 after = dash[0];
 }

 if (href.match(/[?]/)) {
 var re = /([?&]store=)[a-z0-9_]*/;
 if (href.match(re)) {
 href = href.replace(re, '$1'+code);
 } else {
 href += '&store='+code;
 }

 var re = /([?&]from_store=)[a-z0-9_]*/;
 if (href.match(re)) {
 href = href.replace(re, '');
 }
 } else {
 href += '?store='+code;
 }
 if (typeof(fromCode) != 'undefined') {
 href += '&from_store='+fromCode;
 }
 href += after;

 setLocation(href);
}

/**
 * Add classes to specified elements.
 * Supported classes are: 'odd', 'even', 'first', 'last'
 *
 * @param elements - array of elements to be decorated
 * [@param decorateParams] - array of classes to be set. If omitted, all available will be used
 */
function decorateGeneric(elements, decorateParams)
{
 var allSupportedParams = ['odd', 'even', 'first', 'last'];
 var _decorateParams = {};
 var total = elements.length;

 if (total) {
 // determine params called
 if (typeof(decorateParams) == 'undefined') {
 decorateParams = allSupportedParams;
 }
 if (!decorateParams.length) {
 return;
 }
 for (var k in allSupportedParams) {
 _decorateParams[allSupportedParams[k]] = false;
 }
 for (var k in decorateParams) {
 _decorateParams[decorateParams[k]] = true;
 }

 // decorate elements
 // elements[0].addClassName('first'); // will cause bug in IE (#5587)
 if (_decorateParams.first) {
 Element.addClassName(elements[0], 'first');
 }
 if (_decorateParams.last) {
 Element.addClassName(elements[total-1], 'last');
 }
 for (var i = 0; i < total; i++) {
 if ((i + 1) % 2 == 0) {
 if (_decorateParams.even) {
 Element.addClassName(elements[i], 'even');
 }
 }
 else {
 if (_decorateParams.odd) {
 Element.addClassName(elements[i], 'odd');
 }
 }
 }
 }
}

/**
 * Decorate table rows and cells, tbody etc
 * @see decorateGeneric()
 */
function decorateTable(table, options) {
 var table = $(table);
 if (table) {
 // set default options
 var _options = {
 'tbody' : false,
 'tbody tr' : ['odd', 'even', 'first', 'last'],
 'thead tr' : ['first', 'last'],
 'tfoot tr' : ['first', 'last'],
 'tr td' : ['last']
 };
 // overload options
 if (typeof(options) != 'undefined') {
 for (var k in options) {
 _options[k] = options[k];
 }
 }
 // decorate
 if (_options['tbody']) {
 decorateGeneric(table.select('tbody'), _options['tbody']);
 }
 if (_options['tbody tr']) {
 decorateGeneric(table.select('tbody tr'), _options['tbody tr']);
 }
 if (_options['thead tr']) {
 decorateGeneric(table.select('thead tr'), _options['thead tr']);
 }
 if (_options['tfoot tr']) {
 decorateGeneric(table.select('tfoot tr'), _options['tfoot tr']);
 }
 if (_options['tr td']) {
 var allRows = table.select('tr');
 if (allRows.length) {
 for (var i = 0; i < allRows.length; i++) {
 decorateGeneric(allRows[i].getElementsByTagName('TD'), _options['tr td']);
 }
 }
 }
 }
}

/**
 * Set "odd", "even" and "last" CSS classes for list items
 * @see decorateGeneric()
 */
function decorateList(list, nonRecursive) {
 if ($(list)) {
 if (typeof(nonRecursive) == 'undefined') {
 var items = $(list).select('li')
 }
 else {
 var items = $(list).childElements();
 }
 decorateGeneric(items, ['odd', 'even', 'last']);
 }
}

/**
 * Set "odd", "even" and "last" CSS classes for list items
 * @see decorateGeneric()
 */
function decorateDataList(list) {
 list = $(list);
 if (list) {
 decorateGeneric(list.select('dt'), ['odd', 'even', 'last']);
 decorateGeneric(list.select('dd'), ['odd', 'even', 'last']);
 }
}

/**
 * Formats currency using patern
 * format - JSON (pattern, decimal, decimalsDelimeter, groupsDelimeter)
 * showPlus - true (always show '+'or '-'),
 * false (never show '-' even if number is negative)
 * null (show '-' if number is negative)
 */

function formatCurrency(price, format, showPlus){
 precision = isNaN(format.precision = Math.abs(format.precision)) ? 2 : format.precision;
 requiredPrecision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision;

 //precision = (precision > requiredPrecision) ? precision : requiredPrecision;
 //for now we don't need this difference so precision is requiredPrecision
 precision = requiredPrecision;

 integerRequired = isNaN(format.integerRequired = Math.abs(format.integerRequired)) ? 1 : format.integerRequired;

 decimalSymbol = format.decimalSymbol == undefined ? "," : format.decimalSymbol;
 groupSymbol = format.groupSymbol == undefined ? "." : format.groupSymbol;
 groupLength = format.groupLength == undefined ? 3 : format.groupLength;

 if (showPlus == undefined || showPlus == true) {
 s = price < 0 ? "-" : ( showPlus ? "+" : "");
 } else if (showPlus == false) {
 s = '';
 }

 i = parseInt(price = Math.abs(+price || 0).toFixed(precision)) + "";
 pad = (i.length < integerRequired) ? (integerRequired - i.length) : 0;
 while (pad) { i = '0' + i; pad--; }

 j = (j = i.length) > groupLength ? j % groupLength : 0;
 re = new RegExp("(\\d{" + groupLength + "})(?=\\d)", "g");

 /**
 * replace(/-/, 0) is only for fixing Safari bug which appears
 * when Math.abs(0).toFixed() executed on "0" number.
 * Result is "0.-0" :(
 */
 r = (j ? i.substr(0, j) + groupSymbol : "") + i.substr(j).replace(re, "$1" + groupSymbol) + (precision ? decimalSymbol + Math.abs(price - i).toFixed(precision).replace(/-/, 0).slice(2) : "")

 if (format.pattern.indexOf('{sign}') == -1) {
 pattern = s + format.pattern;
 } else {
 pattern = format.pattern.replace('{sign}', s);
 }

 return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
};

function expandDetails(el, childClass) {
 if (Element.hasClassName(el,'show-details')) {
 $$(childClass).each(function(item){item.hide()});
 Element.removeClassName(el,'show-details');
 }
 else {
 $$(childClass).each(function(item){item.show()});
 Element.addClassName(el,'show-details');
 }
}

// Version 1.0
var isIE = navigator.appVersion.match(/MSIE/) == "MSIE";

if (!window.Varien)
 var Varien = new Object();

Varien.showLoading = function(){
 Element.show('loading-process');
}
Varien.hideLoading = function(){
 Element.hide('loading-process');
}
Varien.GlobalHandlers = {
 onCreate: function() {
 Varien.showLoading();
 },

 onComplete: function() {
 if(Ajax.activeRequestCount == 0) {
 Varien.hideLoading();
 }
 }
};

Ajax.Responders.register(Varien.GlobalHandlers);

/**
 * Quick Search form client model
 */
Varien.searchForm = Class.create();
Varien.searchForm.prototype = {
 initialize : function(form, field, emptyText){
 this.form = $(form);
 this.field = $(field);
 this.emptyText = emptyText;

 Event.observe(this.form, 'submit', this.submit.bind(this));
 Event.observe(this.field, 'focus', this.focus.bind(this));
 Event.observe(this.field, 'blur', this.blur.bind(this));
 this.blur();
 },

 submit : function(event){
 if (this.field.value == this.emptyText || this.field.value == ''){
 Event.stop(event);
 return false;
 }
 return true;
 },

 focus : function(event){
 if(this.field.value==this.emptyText){
 this.field.value='';
 }

 },

 blur : function(event){
 if(this.field.value==''){
 this.field.value=this.emptyText;
 }
 },

 initAutocomplete : function(url, destinationElement){
 new Ajax.Autocompleter(
 this.field,
 destinationElement,
 url,
 {
 paramName: this.field.name,
 minChars: 2,
 updateElement: this._selectAutocompleteItem.bind(this)
 }
 );
 },

 _selectAutocompleteItem : function(element){
 if(element.title){
 this.field.value = element.title;
 }
 this.submit();
 }
}

Varien.Tabs = Class.create();
Varien.Tabs.prototype = {
 initialize: function(selector) {
 var self=this;
 $$(selector+' a').each(this.initTab.bind(this));
 },

 initTab: function(el) {
 el.href = 'javascript:void(0)';
 if ($(el.parentNode).hasClassName('active')) {
 this.showContent(el);
 }
 el.observe('click', this.showContent.bind(this, el));
 },

 showContent: function(a) {
 var li = $(a.parentNode), ul = $(li.parentNode);
 ul.getElementsBySelector('li', 'ol').each(function(el){
 var contents = $(el.id+'_contents');
 if (el==li) {
 el.addClassName('active');
 contents.show();
 } else {
 el.removeClassName('active');
 contents.hide();
 }
 });
 }
}

Varien.DOB = Class.create();
Varien.DOB.prototype = {
 initialize: function(selector, required) {
 var el = $$(selector)[0];
 this.day = $(el).getElementsBySelector('.dob-day input')[0];
 this.month = $(el).getElementsBySelector('.dob-month input')[0];
 this.year = $(el).getElementsBySelector('.dob-year input')[0];
 this.dob = $(el).getElementsBySelector('.dob-full input')[0];
 this.advice = $(el).getElementsBySelector('.validation-advice')[0];
 this.required = required;

 this.day.validate = this.validate.bind(this);
 this.month.validate = this.validate.bind(this);
 this.year.validate = this.validate.bind(this);

 this.advice.hide();
 },

 validate: function() {
 var error = false;

 if (this.day.value=='' && this.month.value=='' && this.year.value=='') {
 if (this.required) {
 error = 'This date is a required value.';
 } else {
 this.dob.value = '';
 }
 } else if (this.day.value=='' || this.month.value=='' || this.year.value=='') {
 error = 'Please enter a valid full date.';
 } else {
 var date = new Date();
 if (this.day.value<1 || this.day.value>31) {
 error = 'Please enter a valid day (1-31).';
 } else if (this.month.value<1 || this.month.value>12) {
 error = 'Please enter a valid month (1-12).';
 } else if (this.year.value<1900 || this.year.value>date.getFullYear()) {
 error = 'Please enter a valid year (1900-'+date.getFullYear()+').';
 } else {
 this.dob.value = this.month.value+'/'+this.day.value+'/'+this.year.value;
 var test = new Date(this.dob.value);
 if (isNaN(test)) {
 error = 'Please enter a valid date.';
 }
 }
 }

 if (error !== false) {
 this.advice.innerHTML = Translator.translate(error);
 this.advice.show();
 return false;
 }

 this.advice.hide();
 return true;
 }
}

Validation.addAllThese([
 ['validate-custom', ' ', function(v,elm) {
 return elm.validate();
 }]
]);

function truncateOptions() {
 $$('.truncated').each(function(element){
 Event.observe(element, 'mouseover', function(){
 if (element.down('div.truncated_full_value')) {
 element.down('div.truncated_full_value').addClassName('show')
 }
 });
 Event.observe(element, 'mouseout', function(){
 if (element.down('div.truncated_full_value')) {
 element.down('div.truncated_full_value').removeClassName('show')
 }
 });

 });
}
Event.observe(window, 'load', function(){
 truncateOptions();
});/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
 * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 */
VarienForm = Class.create();
VarienForm.prototype = {
 initialize: function(formId, firstFieldFocus){
 this.form = $(formId);
 if (!this.form) {
 return;
 }
 this.cache = $A();
 this.currLoader = false;
 this.currDataIndex = false;
 this.validator = new Validation(this.form);
 this.elementFocus = this.elementOnFocus.bindAsEventListener(this);
 this.elementBlur = this.elementOnBlur.bindAsEventListener(this);
 this.childLoader = this.onChangeChildLoad.bindAsEventListener(this);
 this.highlightClass = 'highlight';
 this.extraChildParams = '';
 this.firstFieldFocus= firstFieldFocus || false;
 this.bindElements();
 if(this.firstFieldFocus){
 try{
 Form.Element.focus(Form.findFirstElement(this.form))
 }
 catch(e){}
 }
 },

 submit : function(url){
 if(this.validator && this.validator.validate()){
 this.form.submit();
 }
 return false;
 },

 bindElements:function (){
 var elements = Form.getElements(this.form);
 for (var row in elements) {
 if (elements[row].id) {
 Event.observe(elements[row],'focus',this.elementFocus);
 Event.observe(elements[row],'blur',this.elementBlur);
 }
 }
 },

 elementOnFocus: function(event){
 var element = Event.findElement(event, 'fieldset');
 if(element && element.className){
 Element.addClassName(element, this.highlightClass);
 }
 },

 elementOnBlur: function(event){
 var element = Event.findElement(event, 'fieldset');
 if(element && element.className){
 Element.removeClassName(element, this.highlightClass);
 }
 },

 setElementsRelation: function(parent, child, dataUrl, first){
 if (parent=$(parent)) {
 // TODO: array of relation and caching
 if (!this.cache[parent.id]){
 this.cache[parent.id] = $A();
 this.cache[parent.id]['child'] = child;
 this.cache[parent.id]['dataUrl'] = dataUrl;
 this.cache[parent.id]['data'] = $A();
 this.cache[parent.id]['first'] = first || false;
 }
 Event.observe(parent,'change',this.childLoader);
 }
 },

 onChangeChildLoad: function(event){
 element = Event.element(event);
 this.elementChildLoad(element);
 },

 elementChildLoad: function(element, callback){
 this.callback = callback || false;
 if (element.value) {
 this.currLoader = element.id;
 this.currDataIndex = element.value;
 if (this.cache[element.id]['data'][element.value]) {
 this.setDataToChild(this.cache[element.id]['data'][element.value]);
 }
 else{
 new Ajax.Request(this.cache[this.currLoader]['dataUrl'],{
 method: 'post',
 parameters: {"parent":element.value},
 onComplete: this.reloadChildren.bind(this)
 });
 }
 }
 },

 reloadChildren: function(transport){
 var data = eval('(' + transport.responseText + ')');
 this.cache[this.currLoader]['data'][this.currDataIndex] = data;
 this.setDataToChild(data);
 },

 setDataToChild: function(data){
 if (data.length) {
 var child = $(this.cache[this.currLoader]['child']);
 if (child){
 var html = '<select name="'+child.name+'" id="'+child.id+'" class="'+child.className+'" title="'+child.title+'" '+this.extraChildParams+'>';
 if(this.cache[this.currLoader]['first']){
 html+= '<option value="">'+this.cache[this.currLoader]['first']+'</option>';
 }
 for (var i in data){
 if(data[i].value) {
 html+= '<option value="'+data[i].value+'"';
 if(child.value && (child.value == data[i].value || child.value == data[i].label)){
 html+= ' selected';
 }
 html+='>'+data[i].label+'</option>';
 }
 }
 html+= '</select>';
 Element.insert(child, {before: html});
 Element.remove(child);
 }
 }
 else{
 var child = $(this.cache[this.currLoader]['child']);
 if (child){
 var html = '<input type="text" name="'+child.name+'" id="'+child.id+'" class="'+child.className+'" title="'+child.title+'" '+this.extraChildParams+'>';
 Element.insert(child, {before: html});
 Element.remove(child);
 }
 }

 this.bindElements();
 if (this.callback) {
 this.callback();
 }
 }
}

RegionUpdater = Class.create();
RegionUpdater.prototype = {
 initialize: function (countryEl, regionTextEl, regionSelectEl, regions, disableAction)
 {
 this.countryEl = $(countryEl);
 this.regionTextEl = $(regionTextEl);
 this.regionSelectEl = $(regionSelectEl);
 this.regions = regions;

 this.disableAction = (typeof disableAction=='undefined') ? 'hide' : disableAction;

 if (this.regionSelectEl.options.length<=1) {
 this.update();
 }

 Event.observe(this.countryEl, 'change', this.update.bind(this));
 },

 update: function()
 {
 if (this.regions[this.countryEl.value]) {
 var i, option, region, def;

 if (this.regionTextEl) {
 def = this.regionTextEl.value.toLowerCase();
 this.regionTextEl.value = '';
 }
 if (!def) {
 def = this.regionSelectEl.getAttribute('defaultValue');
 }

 this.regionSelectEl.options.length = 1;
 for (regionId in this.regions[this.countryEl.value]) {
 region = this.regions[this.countryEl.value][regionId];

 option = document.createElement('OPTION');
 option.value = regionId;
 option.text = region.name;

 if (this.regionSelectEl.options.add) {
 this.regionSelectEl.options.add(option);
 } else {
 this.regionSelectEl.appendChild(option);
 }

 if (regionId==def || region.name.toLowerCase()==def || region.code.toLowerCase()==def) {
 this.regionSelectEl.value = regionId;
 }
 }

 if (this.disableAction=='hide') {
 if (this.regionTextEl) {
 this.regionTextEl.style.display = 'none';
 }

 this.regionSelectEl.style.display = '';
 } else if (this.disableAction=='disable') {
 if (this.regionTextEl) {
 this.regionTextEl.disabled = true;
 }
 this.regionSelectEl.disabled = false;
 }
 this.setMarkDisplay(this.regionSelectEl, true);
 } else {
 if (this.disableAction=='hide') {
 if (this.regionTextEl) {
 this.regionTextEl.style.display = '';
 }
 this.regionSelectEl.style.display = 'none';
 Validation.reset(this.regionSelectEl);
 } else if (this.disableAction=='disable') {
 if (this.regionTextEl) {
 this.regionTextEl.disabled = false;
 }
 this.regionSelectEl.disabled = true;
 } else if (this.disableAction=='nullify') {
 this.regionSelectEl.options.length = 1;
 this.regionSelectEl.value = '';
 this.regionSelectEl.selectedIndex = 0;
 this.lastCountryId = '';
 }
 this.setMarkDisplay(this.regionSelectEl, false);
 }
 },

 setMarkDisplay: function(elem, display){
 if(elem.parentNode){
 var marks = Element.select(elem.parentNode, '.required');
 if(marks[0]){
 display ? marks[0].show() : marks[0].hide();
 }
 }
 }
}/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
 * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 */
function toggleMenu(el, over)
{
 if (over) {
 Element.addClassName(el, 'over');
 }
 else {
 Element.removeClassName(el, 'over');
 }
}
/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @category Mage
 * @package Js
 * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
 * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 */

var Translate = Class.create();
Translate.prototype = {
 initialize: function(data){
 this.data = $H(data);
 },

 translate : function(){
 var args = arguments;
 var text = arguments[0];

 if(this.data.get(text)){
 return this.data.get(text);
 }
 return text;
 },
 add : function() {
 if (arguments.length > 1) {
 this.data.set(arguments[0], arguments[1]);
 } else if (typeof arguments[0] =='object') {
 $H(arguments[0]).each(function (pair){
 this.data.set(pair.key, pair.value);
 }.bind(this));
 }
 }
}/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
 * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 */
// old school cookie functions grabbed off the web

if (!window.Mage) var Mage = {};

Mage.Cookies = {};
Mage.Cookies.set = function(name, value){
 var argv = arguments;
 var argc = arguments.length;
 var expires = (argc > 2) ? argv[2] : null;
 var path = (argc > 3) ? argv[3] : '/';
 var domain = (argc > 4) ? argv[4] : null;
 var secure = (argc > 5) ? argv[5] : false;
 document.cookie = name + "=" + escape (value) +
 ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
 ((path == null) ? "" : ("; path=" + path)) +
 ((domain == null) ? "" : ("; domain=" + domain)) +
 ((secure == true) ? "; secure" : "");
};

Mage.Cookies.get = function(name){
 var arg = name + "=";
 var alen = arg.length;
 var clen = document.cookie.length;
 var i = 0;
 var j = 0;
 while(i < clen){
 j = i + alen;
 if (document.cookie.substring(i, j) == arg)
 return Cookies.getCookieVal(j);
 i = document.cookie.indexOf(" ", i) + 1;
 if(i == 0)
 break;
 }
 return null;
};

Mage.Cookies.clear = function(name) {
 if(Cookies.get(name)){
 document.cookie = name + "=" +
 "; expires=Thu, 01-Jan-70 00:00:01 GMT";
 }
};

Mage.Cookies.getCookieVal = function(offset){
 var endstr = document.cookie.indexOf(";", offset);
 if(endstr == -1){
 endstr = document.cookie.length;
 }
 return unescape(document.cookie.substring(offset, endstr));
};/*
*
* Funções de validação customizadas
* Data da Criação: 30/01/2009
* Jonathan Moratelli de Carvalho
* Versão: 0.1
*
*/


function validaCPF(cpf)
{
 if (cpf.length < 11)
 return false;

 var nonNumbers = /\D/;

 if (nonNumbers.test(cpf))
 return false;

 if (cpf == "00000000000" || cpf == "11111111111" || cpf == "22222222222" || cpf == "33333333333" || cpf == "44444444444" || cpf == "55555555555" || cpf == "66666666666" || cpf == "77777777777" || cpf == "88888888888" || cpf == "99999999999")
 return false;

 var a = [];
 var b = new Number;
 var c = 11;

 for (i=0; i<11; i++)
 {
 a[i] = cpf.charAt(i);
 if (i < 9)
 b += (a[i] * --c);
 }

 if ((x = b % 11) < 2)
 a[9] = 0;
 else
 a[9] = 11-x;

 b = 0;
 c = 11;

 for (y=0; y<10; y++)
 b += (a[y] * c--);

 if ((x = b % 11) < 2)
 a[10] = 0;
 else
 a[10] = 11-x;

 if ((cpf.charAt(9) != a[9]) || (cpf.charAt(10) != a[10]))
 return false;

 return true;
}