/* 
-------------------------------------------------------------
	moo.rd plus MooTools
-------------------------------------------------------------
	moo.rd 1.3.2 Copyright (c) 2007 by Riccardo Degni
	MooTools 1.2 Copyright (c) 2006-2007 by Valerio Proietti
-------------------------------------------------------------
*/

//MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006-2007 Valerio Proietti, <http://mad4milk.net>, MIT Style License.

var MooTools={version:"1.2dev",build:"1553"};var Native=function(J){J=J||{};var F=J.afterImplement||function(){};var G=J.generics;G=(G!==false);var H=J.legacy;
var E=J.initialize;var B=J.protect;var A=J.name;var C=E||H;C.constructor=Native;C.$family={name:"native"};if(H&&E){C.prototype=H.prototype;}C.prototype.constructor=C;
if(A){var D=A.toLowerCase();C.prototype.$family={name:D};Native.typize(C,D);}var I=function(M,K,N,L){if(!B||L||!M.prototype[K]){M.prototype[K]=N;}if(G){Native.genericize(M,K,B);
}F.call(M,K,N);return M;};C.implement=function(L,K,N){if(typeof L=="string"){return I(this,L,K,N);}for(var M in L){I(this,M,L[M],K);}return this;};C.alias=function(M,K,N){if(typeof M=="string"){M=this.prototype[M];
if(M){I(this,K,M,N);}}else{for(var L in M){this.alias(L,M[L],K);}}return this;};return C;};Native.implement=function(D,C){for(var B=0,A=D.length;B<A;B++){D[B].implement(C);
}};Native.genericize=function(B,C,A){if((!A||!B[C])&&typeof B.prototype[C]=="function"){B[C]=function(){var D=Array.prototype.slice.call(arguments);return B.prototype[C].apply(D.shift(),D);
};}};Native.typize=function(A,B){if(!A.type){A.type=function(C){return($type(C)===B);};}};Native.alias=function(E,B,A,F){for(var D=0,C=E.length;D<C;D++){E[D].alias(B,A,F);
}};(function(B){for(var A in B){Native.typize(B[A],A);}})({"boolean":Boolean,"native":Native,object:Object});(function(B){for(var A in B){new Native({name:A,initialize:B[A],protect:true});
}})({String:String,Function:Function,Number:Number,Array:Array,RegExp:RegExp,Date:Date});(function(B,A){for(var C=A.length;C--;C){Native.genericize(B,A[C],true);
}return arguments.callee;})(Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","toString","valueOf","indexOf","lastIndexOf"])(String,["charAt","charCodeAt","concat","indexOf","lastIndexOf","match","replace","search","slice","split","substr","substring","toLowerCase","toUpperCase","valueOf"]);
function $chk(A){return !!(A||A===0);}function $clear(A){clearTimeout(A);clearInterval(A);return null;}function $defined(A){return(A!=undefined);}function $empty(){}function $arguments(A){return function(){return arguments[A];
};}function $lambda(A){return(typeof A=="function")?A:function(){return A;};}function $extend(C,A){for(var B in (A||{})){C[B]=A[B];}return C;}function $unlink(C){var B;
switch($type(C)){case"object":B={};for(var E in C){B[E]=$unlink(C[E]);}break;case"hash":B=$unlink(C.getClean());break;case"array":B=[];for(var D=0,A=C.length;
D<A;D++){B[D]=$unlink(C[D]);}break;default:return C;}return B;}function $merge(){var E={};for(var D=0,A=arguments.length;D<A;D++){var B=arguments[D];if($type(B)!="object"){continue;
}for(var C in B){var G=B[C],F=E[C];E[C]=(F&&$type(G)=="object"&&$type(F)=="object")?$merge(F,G):$unlink(G);}}return E;}function $pick(){for(var B=0,A=arguments.length;
B<A;B++){if(arguments[B]!=undefined){return arguments[B];}}return null;}function $random(B,A){return Math.floor(Math.random()*(A-B+1)+B);}function $splat(B){var A=$type(B);
return(A)?((A!="array"&&A!="arguments")?[B]:B):[];}var $time=Date.now||function(){return new Date().getTime();};function $try(){for(var B=0,A=arguments.length;
B<A;B++){try{return arguments[B]();}catch(C){}}return null;}function $type(A){if(A==undefined){return false;}if(A.$family){return(A.$family.name=="number"&&!isFinite(A))?false:A.$family.name;
}if(A.nodeName){switch(A.nodeType){case 1:return"element";case 3:return(/\S/).test(A.nodeValue)?"textnode":"whitespace";}}else{if(typeof A.length=="number"){if(A.callee){return"arguments";
}else{if(A.item){return"collection";}}}}return typeof A;}var Hash=new Native({name:"Hash",initialize:function(A){if($type(A)=="hash"){A=$unlink(A.getClean());
}for(var B in A){this[B]=A[B];}return this;}});Hash.implement({getLength:function(){var B=0;for(var A in this){if(this.hasOwnProperty(A)){B++;}}return B;
},forEach:function(B,C){for(var A in this){if(this.hasOwnProperty(A)){B.call(C,this[A],A,this);}}},getClean:function(){var B={};for(var A in this){if(this.hasOwnProperty(A)){B[A]=this[A];
}}return B;}});Hash.alias("forEach","each");function $H(A){return new Hash(A);}Array.implement({forEach:function(C,D){for(var B=0,A=this.length;B<A;B++){C.call(D,this[B],B,this);
}}});Array.alias("forEach","each");function $A(C){if(C.item){var D=[];for(var B=0,A=C.length;B<A;B++){D[B]=C[B];}return D;}return Array.prototype.slice.call(C);
}function $each(C,B,D){var A=$type(C);((A=="arguments"||A=="collection"||A=="array")?Array:Hash).each(C,B,D);}var Browser=new Hash({Engine:{name:"unknown",version:""},Platform:{name:(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase()},Features:{xpath:!!(document.evaluate),air:!!(window.runtime)},Plugins:{}});
if(window.opera){Browser.Engine={name:"presto",version:(document.getElementsByClassName)?950:925};}else{if(window.ActiveXObject){Browser.Engine={name:"trident",version:(window.XMLHttpRequest)?5:4};
}else{if(!navigator.taintEnabled){Browser.Engine={name:"webkit",version:(Browser.Features.xpath)?420:419};}else{if(document.getBoxObjectFor!=null){Browser.Engine={name:"gecko",version:(document.getElementsByClassName)?19:18};
}}}}Browser.Engine[Browser.Engine.name]=Browser.Engine[Browser.Engine.name+Browser.Engine.version]=true;if(window.orientation!=undefined){Browser.Platform.name="ipod";
}Browser.Platform[Browser.Platform.name]=true;Browser.Request=function(){return $try(function(){return new XMLHttpRequest();},function(){return new ActiveXObject("MSXML2.XMLHTTP");
});};Browser.Features.xhr=!!(Browser.Request());Browser.Plugins.Flash=(function(){var A=($try(function(){return navigator.plugins["Shockwave Flash"].description;
},function(){return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");})||"0 r0").match(/\d+/g);return{version:parseInt(A[0]||0+"."+A[1]||0),build:parseInt(A[2]||0)};
})();function $exec(B){if(!B){return B;}if(window.execScript){window.execScript(B);}else{var A=document.createElement("script");A.setAttribute("type","text/javascript");
A.text=B;document.head.appendChild(A);document.head.removeChild(A);}return B;}Native.UID=1;var $uid=(Browser.Engine.trident)?function(A){return(A.uid||(A.uid=[Native.UID++]))[0];
}:function(A){return A.uid||(A.uid=Native.UID++);};var Window=new Native({name:"Window",legacy:(Browser.Engine.trident)?null:window.Window,initialize:function(A){$uid(A);
if(!A.Element){A.Element=$empty;if(Browser.Engine.webkit){A.document.createElement("iframe");}A.Element.prototype=(Browser.Engine.webkit)?window["[[DOMElement.prototype]]"]:{};
}return $extend(A,Window.Prototype);},afterImplement:function(B,A){window[B]=Window.Prototype[B]=A;}});Window.Prototype={$family:{name:"window"}};new Window(window);
var Document=new Native({name:"Document",legacy:(Browser.Engine.trident)?null:window.Document,initialize:function(A){$uid(A);A.head=A.getElementsByTagName("head")[0];
A.html=A.getElementsByTagName("html")[0];A.window=A.defaultView||A.parentWindow;if(Browser.Engine.trident4){$try(function(){A.execCommand("BackgroundImageCache",false,true);
});}return $extend(A,Document.Prototype);},afterImplement:function(B,A){document[B]=Document.Prototype[B]=A;}});Document.Prototype={$family:{name:"document"}};
new Document(document);Array.implement({every:function(C,D){for(var B=0,A=this.length;B<A;B++){if(!C.call(D,this[B],B,this)){return false;}}return true;
},filter:function(D,E){var C=[];for(var B=0,A=this.length;B<A;B++){if(D.call(E,this[B],B,this)){C.push(this[B]);}}return C;},clean:function(){return this.filter($defined);
},indexOf:function(C,D){var A=this.length;for(var B=(D<0)?Math.max(0,A+D):D||0;B<A;B++){if(this[B]===C){return B;}}return -1;},map:function(D,E){var C=[];
for(var B=0,A=this.length;B<A;B++){C[B]=D.call(E,this[B],B,this);}return C;},some:function(C,D){for(var B=0,A=this.length;B<A;B++){if(C.call(D,this[B],B,this)){return true;
}}return false;},associate:function(C){var D={},B=Math.min(this.length,C.length);for(var A=0;A<B;A++){D[C[A]]=this[A];}return D;},link:function(C){var A={};
for(var E=0,B=this.length;E<B;E++){for(var D in C){if(C[D](this[E])){A[D]=this[E];delete C[D];break;}}}return A;},contains:function(A,B){return this.indexOf(A,B)!=-1;
},extend:function(C){for(var B=0,A=C.length;B<A;B++){this.push(C[B]);}return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[$random(0,this.length-1)]:null;
},include:function(A){if(!this.contains(A)){this.push(A);}return this;},combine:function(C){for(var B=0,A=C.length;B<A;B++){this.include(C[B]);}return this;
},erase:function(B){for(var A=this.length;A--;A){if(this[A]===B){this.splice(A,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var D=[];
for(var B=0,A=this.length;B<A;B++){var C=$type(this[B]);if(!C){continue;}D=D.concat((C=="array"||C=="collection"||C=="arguments")?Array.flatten(this[B]):this[B]);
}return D;},hexToRgb:function(B){if(this.length!=3){return null;}var A=this.map(function(C){if(C.length==1){C+=C;}return C.toInt(16);});return(B)?A:"rgb("+A+")";
},rgbToHex:function(D){if(this.length<3){return null;}if(this.length==4&&this[3]==0&&!D){return"transparent";}var B=[];for(var A=0;A<3;A++){var C=(this[A]-0).toString(16);
B.push((C.length==1)?"0"+C:C);}return(D)?B:"#"+B.join("");}});Function.implement({extend:function(A){for(var B in A){this[B]=A[B];}return this;},create:function(B){var A=this;
B=B||{};return function(D){var C=B.arguments;C=(C!=undefined)?$splat(C):Array.slice(arguments,(B.event)?1:0);if(B.event){C=[D||window.event].extend(C);
}var E=function(){return A.apply(B.bind||null,C);};if(B.delay){return setTimeout(E,B.delay);}if(B.periodical){return setInterval(E,B.periodical);}if(B.attempt){return $try(E);
}return E();};},pass:function(A,B){return this.create({arguments:A,bind:B});},attempt:function(A,B){return this.create({arguments:A,bind:B,attempt:true})();
},bind:function(B,A){return this.create({bind:B,arguments:A});},bindWithEvent:function(B,A){return this.create({bind:B,event:true,arguments:A});},delay:function(B,C,A){return this.create({delay:B,bind:C,arguments:A})();
},periodical:function(A,C,B){return this.create({periodical:A,bind:C,arguments:B})();},run:function(A,B){return this.apply(B,$splat(A));}});Number.implement({limit:function(B,A){return Math.min(A,Math.max(B,this));
},round:function(A){A=Math.pow(10,A||0);return Math.round(this*A)/A;},times:function(B,C){for(var A=0;A<this;A++){B.call(C,A,this);}},toFloat:function(){return parseFloat(this);
},toInt:function(A){return parseInt(this,A||10);}});Number.alias("times","each");(function(B){var A={};B.each(function(C){if(!Number[C]){A[C]=function(){return Math[C].apply(null,[this].concat($A(arguments)));
};}});Number.implement(A);})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);String.implement({test:function(A,B){return((typeof A=="string")?new RegExp(A,B):A).test(this);
},contains:function(A,B){return(B)?(B+this+B).indexOf(B+A+B)>-1:this.indexOf(A)>-1;},trim:function(){return this.replace(/^\s+|\s+$/g,"");},clean:function(){return this.replace(/\s+/g," ").trim();
},camelCase:function(){return this.replace(/-\D/g,function(A){return A.charAt(1).toUpperCase();});},hyphenate:function(){return this.replace(/[A-Z]/g,function(A){return("-"+A.charAt(0).toLowerCase());
});},capitalize:function(){return this.replace(/\b[a-z]/g,function(A){return A.toUpperCase();});},escapeRegExp:function(){return this.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");
},toInt:function(A){return parseInt(this,A||10);},toFloat:function(){return parseFloat(this);},hexToRgb:function(B){var A=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
return(A)?A.slice(1).hexToRgb(B):null;},rgbToHex:function(B){var A=this.match(/\d{1,3}/g);return(A)?A.rgbToHex(B):null;},stripScripts:function(B){var A="";
var C=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(){A+=arguments[1]+"\n";return"";});if(B===true){$exec(A);}else{if($type(B)=="function"){B(A,C);
}}return C;},substitute:function(A,B){return this.replace(B||(/\\?\{([^}]+)\}/g),function(D,C){if(D.charAt(0)=="\\"){return D.slice(1);}return(A[C]!=undefined)?A[C]:"";
});}});Hash.implement({has:Object.prototype.hasOwnProperty,keyOf:function(B){for(var A in this){if(this.hasOwnProperty(A)&&this[A]===B){return A;}}return null;
},hasValue:function(A){return(Hash.keyOf(this,A)!==null);},extend:function(A){Hash.each(A,function(C,B){Hash.set(this,B,C);},this);return this;},combine:function(A){Hash.each(A,function(C,B){Hash.include(this,B,C);
},this);return this;},erase:function(A){if(this.hasOwnProperty(A)){delete this[A];}return this;},get:function(A){return(this.hasOwnProperty(A))?this[A]:null;
},set:function(A,B){if(!this[A]||this.hasOwnProperty(A)){this[A]=B;}return this;},empty:function(){Hash.each(this,function(B,A){delete this[A];},this);
return this;},include:function(B,C){var A=this[B];if(A==undefined){this[B]=C;}return this;},map:function(B,C){var A=new Hash;Hash.each(this,function(E,D){A.set(D,B.call(C,E,D,this));
},this);return A;},filter:function(B,C){var A=new Hash;Hash.each(this,function(E,D){if(B.call(C,E,D,this)){A.set(D,E);}},this);return A;},every:function(B,C){for(var A in this){if(this.hasOwnProperty(A)&&!B.call(C,this[A],A)){return false;
}}return true;},some:function(B,C){for(var A in this){if(this.hasOwnProperty(A)&&B.call(C,this[A],A)){return true;}}return false;},getKeys:function(){var A=[];
Hash.each(this,function(C,B){A.push(B);});return A;},getValues:function(){var A=[];Hash.each(this,function(B){A.push(B);});return A;},toQueryString:function(A){var B=[];
Hash.each(this,function(F,E){if(A){E=A+"["+E+"]";}var D;switch($type(F)){case"object":D=Hash.toQueryString(F,E);break;case"array":var C={};F.each(function(H,G){C[G]=H;
});D=Hash.toQueryString(C,E);break;default:D=E+"="+encodeURIComponent(F);}if(F!=undefined){B.push(D);}});return B.join("&");}});Hash.alias({keyOf:"indexOf",hasValue:"contains"});
var Event=new Native({name:"Event",initialize:function(A,F){F=F||window;var K=F.document;A=A||F.event;if(A.$extended){return A;}this.$extended=true;var J=A.type;
var G=A.target||A.srcElement;while(G&&G.nodeType==3){G=G.parentNode;}if(J.test(/key/)){var B=A.which||A.keyCode;var M=Event.Keys.keyOf(B);if(J=="keydown"){var D=B-111;
if(D>0&&D<13){M="f"+D;}}M=M||String.fromCharCode(B).toLowerCase();}else{if(J.match(/(click|mouse|menu)/i)){K=(!K.compatMode||K.compatMode=="CSS1Compat")?K.html:K.body;
var I={x:A.pageX||A.clientX+K.scrollLeft,y:A.pageY||A.clientY+K.scrollTop};var C={x:(A.pageX)?A.pageX-F.pageXOffset:A.clientX,y:(A.pageY)?A.pageY-F.pageYOffset:A.clientY};
if(J.match(/DOMMouseScroll|mousewheel/)){var H=(A.wheelDelta)?A.wheelDelta/120:-(A.detail||0)/3;}var E=(A.which==3)||(A.button==2);var L=null;if(J.match(/over|out/)){switch(J){case"mouseover":L=A.relatedTarget||A.fromElement;
break;case"mouseout":L=A.relatedTarget||A.toElement;}if(!(function(){while(L&&L.nodeType==3){L=L.parentNode;}return true;}).create({attempt:Browser.Engine.gecko})()){L=false;
}}}}return $extend(this,{event:A,type:J,page:I,client:C,rightClick:E,wheel:H,relatedTarget:L,target:G,code:B,key:M,shift:A.shiftKey,control:A.ctrlKey,alt:A.altKey,meta:A.metaKey});
}});Event.Keys=new Hash({enter:13,up:38,down:40,left:37,right:39,esc:27,space:32,backspace:8,tab:9,"delete":46});Event.implement({stop:function(){return this.stopPropagation().preventDefault();
},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault();
}else{this.event.returnValue=false;}return this;}});var Class=new Native({name:"Class",initialize:function(B){B=B||{};var A=function(E){for(var D in this){this[D]=$unlink(this[D]);
}for(var F in Class.Mutators){if(!this[F]){continue;}Class.Mutators[F](this,this[F]);delete this[F];}this.constructor=A;if(E===$empty){return this;}var C=(this.initialize)?this.initialize.apply(this,arguments):this;
if(this.options&&this.options.initialize){this.options.initialize.call(this);}return C;};$extend(A,this);A.constructor=Class;A.prototype=B;return A;}});
Class.implement({implement:function(){Class.Mutators.Implements(this.prototype,Array.slice(arguments));return this;}});Class.Mutators={Implements:function(A,B){$splat(B).each(function(C){$extend(A,($type(C)=="class")?new C($empty):C);
});},Extends:function(self,klass){var instance=new klass($empty);delete instance.parent;delete instance.parentOf;for(var key in instance){var current=self[key],previous=instance[key];
if(current==undefined){self[key]=previous;continue;}var ctype=$type(current),ptype=$type(previous);if(ctype!=ptype){continue;}switch(ctype){case"function":if(!arguments.callee.caller){self[key]=eval("("+String(current).replace(/\bthis\.parent\(\s*(\))?/g,function(full,close){return"arguments.callee._parent_.call(this"+(close||", ");
})+")");}self[key]._parent_=previous;break;case"object":self[key]=$merge(previous,current);}}self.parent=function(){return arguments.callee.caller._parent_.apply(this,arguments);
};self.parentOf=function(descendant){return descendant._parent_.apply(this,Array.slice(arguments,1));};}};var Chain=new Class({chain:function(){this.$chain=(this.$chain||[]).extend(arguments);
return this;},callChain:function(){return(this.$chain&&this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){if(this.$chain){this.$chain.empty();
}return this;}});var Events=new Class({addEvent:function(C,B,A){C=Events.removeOn(C);if(B!=$empty){this.$events=this.$events||{};this.$events[C]=this.$events[C]||[];
this.$events[C].include(B);if(A){B.internal=true;}}return this;},addEvents:function(A){for(var B in A){this.addEvent(B,A[B]);}return this;},fireEvent:function(C,B,A){C=Events.removeOn(C);
if(!this.$events||!this.$events[C]){return this;}this.$events[C].each(function(D){D.create({bind:this,delay:A,"arguments":B})();},this);return this;},removeEvent:function(B,A){B=Events.removeOn(B);
if(!this.$events||!this.$events[B]){return this;}if(!A.internal){this.$events[B].erase(A);}return this;},removeEvents:function(C){for(var D in this.$events){if(C&&C!=D){continue;
}var B=this.$events[D];for(var A=B.length;A--;A){this.removeEvent(D,B[A]);}}return this;}});Events.removeOn=function(A){return A.replace(/^on([A-Z])/,function(B,C){return C.toLowerCase();
});};var Options=new Class({setOptions:function(){this.options=$merge.run([this.options].extend(arguments));if(!this.addEvent){return this;}for(var A in this.options){if($type(this.options[A])!="function"||!(/^on[A-Z]/).test(A)){continue;
}this.addEvent(A,this.options[A]);delete this.options[A];}return this;}});Document.implement({newElement:function(A,B){if(Browser.Engine.trident&&B){["name","type","checked"].each(function(C){if(!B[C]){return ;
}A+=" "+C+'="'+B[C]+'"';if(C!="checked"){delete B[C];}});A="<"+A+">";}return $.element(this.createElement(A)).set(B);},newTextNode:function(A){return this.createTextNode(A);
},getDocument:function(){return this;},getWindow:function(){return this.defaultView||this.parentWindow;},purge:function(){var C=this.getElementsByTagName("*");
for(var B=0,A=C.length;B<A;B++){Browser.freeMem(C[B]);}}});var Element=new Native({name:"Element",legacy:window.Element,initialize:function(A,B){var C=Element.Constructors.get(A);
if(C){return C(B);}if(typeof A=="string"){return document.newElement(A,B);}return $(A).set(B);},afterImplement:function(A,B){if(!Array[A]){Elements.implement(A,Elements.multi(A));
}Element.Prototype[A]=B;}});Element.Prototype={$family:{name:"element"}};Element.Constructors=new Hash;var IFrame=new Native({name:"IFrame",generics:false,initialize:function(){var E=Array.link(arguments,{properties:Object.type,iframe:$defined});
var C=E.properties||{};var B=$(E.iframe)||false;var D=C.onload||$empty;delete C.onload;C.id=C.name=$pick(C.id,C.name,B.id,B.name,"IFrame_"+$time());B=new Element(B||"iframe",C);
var A=function(){var F=$try(function(){return B.contentWindow.location.host;});if(F&&F==window.location.host){var H=new Window(B.contentWindow);var G=new Document(B.contentWindow.document);
$extend(H.Element.prototype,Element.Prototype);}D.call(B.contentWindow,B.contentWindow.document);};(!window.frames[C.id])?B.addListener("load",A):A();return B;
}});var Elements=new Native({initialize:function(F,B){B=$extend({ddup:true,cash:true},B);F=F||[];if(B.ddup||B.cash){var G={},E=[];for(var C=0,A=F.length;
C<A;C++){var D=$.element(F[C],!B.cash);if(B.ddup){if(G[D.uid]){continue;}G[D.uid]=true;}E.push(D);}F=E;}return(B.cash)?$extend(F,this):F;}});Elements.implement({filter:function(A,B){if(!A){return this;
}return new Elements(Array.filter(this,(typeof A=="string")?function(C){return C.match(A);}:A,B));}});Elements.multi=function(A){return function(){var B=[];
var F=true;for(var D=0,C=this.length;D<C;D++){var E=this[D][A].apply(this[D],arguments);B.push(E);if(F){F=($type(E)=="element");}}return(F)?new Elements(B):B;
};};Window.implement({$:function(B,C){if(B&&B.$family&&B.uid){return B;}var A=$type(B);return($[A])?$[A](B,C,this.document):null;},$$:function(A){if(arguments.length==1&&typeof A=="string"){return this.document.getElements(A);
}var F=[];var C=Array.flatten(arguments);for(var D=0,B=C.length;D<B;D++){var E=C[D];switch($type(E)){case"element":E=[E];break;case"string":E=this.document.getElements(E,true);
break;default:E=false;}if(E){F.extend(E);}}return new Elements(F);},getDocument:function(){return this.document;},getWindow:function(){return this;}});
$.string=function(C,B,A){C=A.getElementById(C);return(C)?$.element(C,B):null;};$.element=function(A,D){$uid(A);if(!D&&!A.$family&&!(/^object|embed$/i).test(A.tagName)){var B=Element.Prototype;
for(var C in B){A[C]=B[C];}}return A;};$.object=function(B,C,A){if(B.toElement){return $.element(B.toElement(A),C);}return null;};$.textnode=$.whitespace=$.window=$.document=$arguments(0);
Native.implement([Element,Document],{getElement:function(A,B){return $(this.getElements(A,true)[0]||null,B);},getElements:function(A,D){A=A.split(",");
var C=[];var B=(A.length>1);A.each(function(E){var F=this.getElementsByTagName(E.trim());(B)?C.extend(F):C=F;},this);return new Elements(C,{ddup:B,cash:!D});
}});Element.Storage={get:function(A){return(this[A]||(this[A]={}));}};Element.Inserters=new Hash({before:function(B,A){if(A.parentNode){A.parentNode.insertBefore(B,A);
}},after:function(B,A){if(!A.parentNode){return ;}var C=A.nextSibling;(C)?A.parentNode.insertBefore(B,C):A.parentNode.appendChild(B);},bottom:function(B,A){A.appendChild(B);
},top:function(B,A){var C=A.firstChild;(C)?A.insertBefore(B,C):A.appendChild(B);}});Element.Inserters.inside=Element.Inserters.bottom;Element.Inserters.each(function(C,B){var A=B.capitalize();
Element.implement("inject"+A,function(D){C(this,$(D,true));return this;});Element.implement("grab"+A,function(D){C($(D,true),this);return this;});});Element.implement({getDocument:function(){return this.ownerDocument;
},getWindow:function(){return this.ownerDocument.getWindow();},getElementById:function(D,C){var B=this.ownerDocument.getElementById(D);if(!B){return null;
}for(var A=B.parentNode;A!=this;A=A.parentNode){if(!A){return null;}}return $.element(B,C);},set:function(D,B){switch($type(D)){case"object":for(var C in D){this.set(C,D[C]);
}break;case"string":var A=Element.Properties.get(D);(A&&A.set)?A.set.apply(this,Array.slice(arguments,1)):this.setProperty(D,B);}return this;},get:function(B){var A=Element.Properties.get(B);
return(A&&A.get)?A.get.apply(this,Array.slice(arguments,1)):this.getProperty(B);},erase:function(B){var A=Element.Properties.get(B);(A&&A.erase)?A.erase.apply(this,Array.slice(arguments,1)):this.removeProperty(B);
return this;},match:function(A){return(!A||Element.get(this,"tag")==A);},inject:function(B,A){Element.Inserters.get(A||"bottom")(this,$(B,true));return this;
},wraps:function(B,A){B=$(B,true);return this.replaces(B).grab(B,A);},grab:function(B,A){Element.Inserters.get(A||"bottom")($(B,true),this);return this;
},appendText:function(B,A){return this.grab(this.getDocument().newTextNode(B),A);},adopt:function(){Array.flatten(arguments).each(function(A){A=$(A,true);
if(A){this.appendChild(A);}},this);return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},clone:function(D,C){switch($type(this)){case"element":var H={};
for(var G=0,E=this.attributes.length;G<E;G++){var B=this.attributes[G],L=B.nodeName.toLowerCase();if(Browser.Engine.trident&&(/input/i).test(this.tagName)&&(/width|height/).test(L)){continue;
}var K=(L=="style"&&this.style)?this.style.cssText:B.nodeValue;if(!$chk(K)||L=="uid"||(L=="id"&&!C)){continue;}if(K!="inherit"&&["string","number"].contains($type(K))){H[L]=K;
}}var J=new Element(this.nodeName.toLowerCase(),H);if(D!==false){for(var I=0,F=this.childNodes.length;I<F;I++){var A=Element.clone(this.childNodes[I],true,C);
if(A){J.grab(A);}}}return J;case"textnode":return document.newTextNode(this.nodeValue);}return null;},replaces:function(A){A=$(A,true);A.parentNode.replaceChild(this,A);
return this;},hasClass:function(A){return this.className.contains(A," ");},addClass:function(A){if(!this.hasClass(A)){this.className=(this.className+" "+A).clean();
}return this;},removeClass:function(A){this.className=this.className.replace(new RegExp("(^|\\s)"+A+"(?:\\s|$)"),"$1").clean();return this;},toggleClass:function(A){return this.hasClass(A)?this.removeClass(A):this.addClass(A);
},getComputedStyle:function(B){if(this.currentStyle){return this.currentStyle[B.camelCase()];}var A=this.getWindow().getComputedStyle(this,null);return(A)?A.getPropertyValue([B.hyphenate()]):null;
},empty:function(){$A(this.childNodes).each(function(A){Browser.freeMem(A);Element.empty(A);Element.dispose(A);},this);return this;},destroy:function(){Browser.freeMem(this.empty().dispose());
return null;},getSelected:function(){return new Elements($A(this.options).filter(function(A){return A.selected;}));},toQueryString:function(){var A=[];
this.getElements("input, select, textarea").each(function(B){if(!B.name||B.disabled){return ;}var C=(B.tagName.toLowerCase()=="select")?Element.getSelected(B).map(function(D){return D.value;
}):((B.type=="radio"||B.type=="checkbox")&&!B.checked)?null:B.value;$splat(C).each(function(D){if(D){A.push(B.name+"="+encodeURIComponent(D));}});});return A.join("&");
},getProperty:function(C){var B=Element.Attributes,A=B.Props[C];var D=(A)?this[A]:this.getAttribute(C,2);return(B.Bools[C])?!!D:(A)?D:D||null;},getProperties:function(){var A=$A(arguments);
return A.map(function(B){return this.getProperty(B);},this).associate(A);},setProperty:function(D,E){var C=Element.Attributes,B=C.Props[D],A=$defined(E);
if(B&&C.Bools[D]){E=(E||!A)?true:false;}else{if(!A){return this.removeProperty(D);}}(B)?this[B]=E:this.setAttribute(D,E);return this;},setProperties:function(A){for(var B in A){this.setProperty(B,A[B]);
}return this;},removeProperty:function(D){var C=Element.Attributes,B=C.Props[D],A=(B&&C.Bools[D]);(B)?this[B]=(A)?false:"":this.removeAttribute(D);return this;
},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;}});(function(){var A=function(D,B,I,C,F,H){var E=D[I||B];var G=[];
while(E){if(E.nodeType==1&&(!C||Element.match(E,C))){G.push(E);if(!F){break;}}E=E[B];}return(F)?new Elements(G,{ddup:false,cash:!H}):$(G[0],H);};Element.implement({getPrevious:function(B,C){return A(this,"previousSibling",null,B,false,C);
},getAllPrevious:function(B,C){return A(this,"previousSibling",null,B,true,C);},getNext:function(B,C){return A(this,"nextSibling",null,B,false,C);},getAllNext:function(B,C){return A(this,"nextSibling",null,B,true,C);
},getFirst:function(B,C){return A(this,"nextSibling","firstChild",B,false,C);},getLast:function(B,C){return A(this,"previousSibling","lastChild",B,false,C);
},getParent:function(B,C){return A(this,"parentNode",null,B,false,C);},getParents:function(B,C){return A(this,"parentNode",null,B,true,C);},getChildren:function(B,C){return A(this,"nextSibling","firstChild",B,true,C);
},hasChild:function(B){B=$(B,true);return(!!B&&$A(this.getElementsByTagName(B.tagName)).contains(B));}});})();Element.Properties=new Hash;Element.Properties.style={set:function(A){this.style.cssText=A;
},get:function(){return this.style.cssText;},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();
}};Element.Properties.href={get:function(){return(!this.href)?null:this.href.replace(new RegExp("^"+document.location.protocol+"//"+document.location.host),"");
}};Element.Properties.html={set:function(){return this.innerHTML=Array.flatten(arguments).join("");}};Native.implement([Element,Window,Document],{addListener:function(B,A){if(this.addEventListener){this.addEventListener(B,A,false);
}else{this.attachEvent("on"+B,A);}return this;},removeListener:function(B,A){if(this.removeEventListener){this.removeEventListener(B,A,false);}else{this.detachEvent("on"+B,A);
}return this;},retrieve:function(B,A){var D=Element.Storage.get(this.uid);var C=D[B];if($defined(A)&&!$defined(C)){C=D[B]=A;}return $pick(C);},store:function(B,A){var C=Element.Storage.get(this.uid);
C[B]=A;return this;},eliminate:function(A){var B=Element.Storage.get(this.uid);delete B[A];return this;}});Element.Attributes=new Hash({Props:{html:"innerHTML","class":"className","for":"htmlFor",text:(Browser.Engine.trident)?"innerText":"textContent"},Bools:["compact","nowrap","ismap","declare","noshade","checked","disabled","readonly","multiple","selected","noresize","defer"],Camels:["value","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","maxLength","readOnly","rowSpan","tabIndex","useMap"]});
Browser.freeMem=function(A){if(!A){return ;}if(Browser.Engine.trident&&(/object/i).test(A.tagName)){for(var B in A){if(typeof A[B]=="function"){A[B]=$empty;
}}Element.dispose(A);}if(A.uid&&A.removeEvents){A.removeEvents();}};(function(B){var C=B.Bools,A=B.Camels;B.Bools=C=C.associate(C);Hash.extend(Hash.combine(B.Props,C),A.associate(A.map(function(D){return D.toLowerCase();
})));B.erase("Camels");})(Element.Attributes);window.addListener("unload",function(){window.removeListener("unload",arguments.callee);document.purge();
if(Browser.Engine.trident){CollectGarbage();}});Element.Properties.events={set:function(A){this.addEvents(A);}};Native.implement([Element,Window,Document],{addEvent:function(E,G){var H=this.retrieve("events",{});
H[E]=H[E]||{keys:[],values:[]};if(H[E].keys.contains(G)){return this;}H[E].keys.push(G);var F=E,A=Element.Events.get(E),C=G,I=this;if(A){if(A.onAdd){A.onAdd.call(this,G);
}if(A.condition){C=function(J){if(A.condition.call(this,J)){return G.call(this,J);}return false;};}F=A.base||F;}var D=function(){return G.call(I);};var B=Element.NativeEvents[F]||0;
if(B){if(B==2){D=function(J){J=new Event(J,I.getWindow());if(C.call(I,J)===false){J.stop();}};}this.addListener(F,D);}H[E].values.push(D);return this;},removeEvent:function(D,C){var B=this.retrieve("events");
if(!B||!B[D]){return this;}var G=B[D].keys.indexOf(C);if(G==-1){return this;}var A=B[D].keys.splice(G,1)[0];var F=B[D].values.splice(G,1)[0];var E=Element.Events.get(D);
if(E){if(E.onRemove){E.onRemove.call(this,C);}D=E.base||D;}return(Element.NativeEvents[D])?this.removeListener(D,F):this;},addEvents:function(A){for(var B in A){this.addEvent(B,A[B]);
}return this;},removeEvents:function(B){var A=this.retrieve("events");if(!A){return this;}if(!B){for(var C in A){this.removeEvents(C);}A=null;}else{if(A[B]){while(A[B].keys[0]){this.removeEvent(B,A[B].keys[0]);
}A[B]=null;}}return this;},fireEvent:function(D,B,A){var C=this.retrieve("events");if(!C||!C[D]){return this;}C[D].keys.each(function(E){E.create({bind:this,delay:A,"arguments":B})();
},this);return this;},cloneEvents:function(D,A){D=$(D);var C=D.retrieve("events");if(!C){return this;}if(!A){for(var B in C){this.cloneEvents(D,B);}}else{if(C[A]){C[A].keys.each(function(E){this.addEvent(A,E);
},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,load:1,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1};
(function(){var A=function(B){var C=B.relatedTarget;if(C==undefined){return true;}if(C===false){return false;}return($type(this)!="document"&&C!=this&&C.prefix!="xul"&&!this.hasChild(C));
};Element.Events=new Hash({mouseenter:{base:"mouseover",condition:A},mouseleave:{base:"mouseout",condition:A},mousewheel:{base:(Browser.Engine.gecko)?"DOMMouseScroll":"mousewheel"}});
})();Element.Properties.styles={set:function(A){this.setStyles(A);}};Element.Properties.opacity={set:function(A,B){if(!B){if(A==0){if(this.style.visibility!="hidden"){this.style.visibility="hidden";
}}else{if(this.style.visibility!="visible"){this.style.visibility="visible";}}}if(!this.currentStyle||!this.currentStyle.hasLayout){this.style.zoom=1;}if(Browser.Engine.trident){this.style.filter=(A==1)?"":"alpha(opacity="+A*100+")";
}this.style.opacity=A;this.store("opacity",A);},get:function(){return this.retrieve("opacity",1);}};Element.implement({setOpacity:function(A){return this.set("opacity",A,true);
},getOpacity:function(){return this.get("opacity");},setStyle:function(B,A){switch(B){case"opacity":return this.set("opacity",parseFloat(A));case"float":B=(Browser.Engine.trident)?"styleFloat":"cssFloat";
}B=B.camelCase();if($type(A)!="string"){var C=(Element.Styles.get(B)||"@").split(" ");A=$splat(A).map(function(E,D){if(!C[D]){return"";}return($type(E)=="number")?C[D].replace("@",Math.round(E)):E;
}).join(" ");}else{if(A==String(Number(A))){A=Math.round(A);}}this.style[B]=A;return this;},getStyle:function(G){switch(G){case"opacity":return this.get("opacity");
case"float":G=(Browser.Engine.trident)?"styleFloat":"cssFloat";}G=G.camelCase();var A=this.style[G];if(!$chk(A)){A=[];for(var F in Element.ShortStyles){if(G!=F){continue;
}for(var E in Element.ShortStyles[F]){A.push(this.getStyle(E));}return A.join(" ");}A=this.getComputedStyle(G);}if(A){A=String(A);var C=A.match(/rgba?\([\d\s,]+\)/);
if(C){A=A.replace(C[0],C[0].rgbToHex());}}if(Browser.Engine.presto||(Browser.Engine.trident&&!$chk(parseInt(A)))){if(G.test(/^(height|width)$/)){var B=(G=="width")?["left","right"]:["top","bottom"],D=0;
B.each(function(H){D+=this.getStyle("border-"+H+"-width").toInt()+this.getStyle("padding-"+H).toInt();},this);return this["offset"+G.capitalize()]-D+"px";
}if(Browser.Engine.presto&&String(A).test("px")){return A;}if(G.test(/(border(.+)Width|margin|padding)/)){return"0px";}}return A;},setStyles:function(B){for(var A in B){this.setStyle(A,B[A]);
}return this;},getStyles:function(){var A={};Array.each(arguments,function(B){A[B]=this.getStyle(B);},this);return A;}});Element.Styles=new Hash({left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"});
Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(G){var F=Element.ShortStyles;
var B=Element.Styles;["margin","padding"].each(function(H){var I=H+G;F[H][I]=B[I]="@px";});var E="border"+G;F.border[E]=B[E]="@px @ rgb(@, @, @)";var D=E+"Width",A=E+"Style",C=E+"Color";
F[E]={};F.borderWidth[D]=F[E][D]=B[D]="@px";F.borderStyle[A]=F[E][A]=B[A]="@";F.borderColor[C]=F[E][C]=B[C]="rgb(@, @, @)";});(function(){Element.implement({scrollTo:function(H,I){if(B(this)){this.getWindow().scrollTo(H,I);
}else{this.scrollLeft=H;this.scrollTop=I;}return this;},getSize:function(){if(B(this)){return this.getWindow().getSize();}return{x:this.offsetWidth,y:this.offsetHeight};
},getScrollSize:function(){if(B(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};},getScroll:function(){if(B(this)){return this.getWindow().getScroll();
}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var I=this,H={x:0,y:0};while(I&&!B(I)){H.x+=I.scrollLeft;H.y+=I.scrollTop;I=I.parentNode;
}return H;},getOffsetParent:function(){var H=this;if(B(H)){return null;}if(!Browser.Engine.trident){return H.offsetParent;}while((H=H.parentNode)&&!B(H)){if(D(H,"position")!="static"){return H;
}}return null;},getOffsets:function(){var I=this,H={x:0,y:0};if(B(this)){return H;}while(I&&!B(I)){H.x+=I.offsetLeft;H.y+=I.offsetTop;if(Browser.Engine.gecko){if(!F(I)){H.x+=C(I);
H.y+=G(I);}var J=I.parentNode;if(J&&D(J,"overflow")!="visible"){H.x+=C(J);H.y+=G(J);}}else{if(I!=this&&(Browser.Engine.trident||Browser.Engine.webkit)){H.x+=C(I);
H.y+=G(I);}}I=I.offsetParent;if(Browser.Engine.trident){while(I&&!I.currentStyle.hasLayout){I=I.offsetParent;}}}if(Browser.Engine.gecko&&!F(this)){H.x-=C(this);
H.y-=G(this);}return H;},getPosition:function(K){if(B(this)){return{x:0,y:0};}var L=this.getOffsets(),I=this.getScrolls();var H={x:L.x-I.x,y:L.y-I.y};var J=(K&&(K=$(K)))?K.getPosition():{x:0,y:0};
return{x:H.x-J.x,y:H.y-J.y};},getCoordinates:function(J){if(B(this)){return this.getWindow().getCoordinates();}var H=this.getPosition(J),I=this.getSize();
var K={left:H.x,top:H.y,width:I.x,height:I.y};K.right=K.left+K.width;K.bottom=K.top+K.height;return K;},computePosition:function(H){return{left:H.x-E(this,"margin-left"),top:H.y-E(this,"margin-top")};
},position:function(H){return this.setStyles(this.computePosition(H));}});Native.implement([Document,Window],{getSize:function(){var I=this.getWindow();
if(Browser.Engine.presto||Browser.Engine.webkit){return{x:I.innerWidth,y:I.innerHeight};}var H=A(this);return{x:H.clientWidth,y:H.clientHeight};},getScroll:function(){var I=this.getWindow();
var H=A(this);return{x:I.pageXOffset||H.scrollLeft,y:I.pageYOffset||H.scrollTop};},getScrollSize:function(){var I=A(this);var H=this.getSize();return{x:Math.max(I.scrollWidth,H.x),y:Math.max(I.scrollHeight,H.y)};
},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var H=this.getSize();return{top:0,left:0,bottom:H.y,right:H.x,height:H.y,width:H.x};
}});var D=Element.getComputedStyle;function E(H,I){return D(H,I).toInt()||0;}function F(H){return D(H,"-moz-box-sizing")=="border-box";}function G(H){return E(H,"border-top-width");
}function C(H){return E(H,"border-left-width");}function B(H){return(/^(?:body|html)$/i).test(H.tagName);}function A(H){var I=H.getDocument();return(!I.compatMode||I.compatMode=="CSS1Compat")?I.html:I.body;
}})();Native.implement([Window,Document,Element],{getHeight:function(){return this.getSize().y;},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y;
},getScrollLeft:function(){return this.getScroll().x;},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x;
},getTop:function(){return this.getPosition().y;},getLeft:function(){return this.getPosition().x;}});Native.implement([Document,Element],{getElements:function(H,G){H=H.split(",");
var C,E={};for(var D=0,B=H.length;D<B;D++){var A=H[D],F=Selectors.Utils.search(this,A,E);if(D!=0&&F.item){F=$A(F);}C=(D==0)?F:(C.item)?$A(C).concat(F):C.concat(F);
}return new Elements(C,{ddup:(H.length>1),cash:!G});}});Element.implement({match:function(B){if(!B){return true;}var D=Selectors.Utils.parseTagAndID(B);
var A=D[0],E=D[1];if(!Selectors.Filters.byID(this,E)||!Selectors.Filters.byTag(this,A)){return false;}var C=Selectors.Utils.parseSelector(B);return(C)?Selectors.Utils.filter(this,C,{}):true;
}});var Selectors={Cache:{nth:{},parsed:{}}};Selectors.RegExps={id:(/#([\w-]+)/),tag:(/^(\w+|\*)/),quick:(/^(\w+|\*)$/),splitter:(/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),combined:(/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)};
Selectors.Utils={chk:function(B,C){if(!C){return true;}var A=$uid(B);if(!C[A]){return C[A]=true;}return false;},parseNthArgument:function(F){if(Selectors.Cache.nth[F]){return Selectors.Cache.nth[F];
}var C=F.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);if(!C){return false;}var E=parseInt(C[1]);var B=(E||E===0)?E:1;var D=C[2]||false;var A=parseInt(C[3])||0;
if(B!=0){A--;while(A<1){A+=B;}while(A>=B){A-=B;}}else{B=A;D="index";}switch(D){case"n":C={a:B,b:A,special:"n"};break;case"odd":C={a:2,b:0,special:"n"};
break;case"even":C={a:2,b:1,special:"n"};break;case"first":C={a:0,special:"index"};break;case"last":C={special:"last-child"};break;case"only":C={special:"only-child"};
break;default:C={a:(B-1),special:"index"};}return Selectors.Cache.nth[F]=C;},parseSelector:function(E){if(Selectors.Cache.parsed[E]){return Selectors.Cache.parsed[E];
}var D,H={classes:[],pseudos:[],attributes:[]};while((D=Selectors.RegExps.combined.exec(E))){var I=D[1],G=D[2],F=D[3],B=D[4],C=D[5],J=D[6];if(I){H.classes.push(I);
}else{if(C){var A=Selectors.Pseudo.get(C);if(A){H.pseudos.push({parser:A,argument:J});}else{H.attributes.push({name:C,operator:"=",value:J});}}else{if(G){H.attributes.push({name:G,operator:F,value:B});
}}}}if(!H.classes.length){delete H.classes;}if(!H.attributes.length){delete H.attributes;}if(!H.pseudos.length){delete H.pseudos;}if(!H.classes&&!H.attributes&&!H.pseudos){H=null;
}return Selectors.Cache.parsed[E]=H;},parseTagAndID:function(B){var A=B.match(Selectors.RegExps.tag);var C=B.match(Selectors.RegExps.id);return[(A)?A[1]:"*",(C)?C[1]:false];
},filter:function(F,C,E){var D;if(C.classes){for(D=C.classes.length;D--;D){var G=C.classes[D];if(!Selectors.Filters.byClass(F,G)){return false;}}}if(C.attributes){for(D=C.attributes.length;
D--;D){var B=C.attributes[D];if(!Selectors.Filters.byAttribute(F,B.name,B.operator,B.value)){return false;}}}if(C.pseudos){for(D=C.pseudos.length;D--;D){var A=C.pseudos[D];
if(!Selectors.Filters.byPseudo(F,A.parser,A.argument,E)){return false;}}}return true;},getByTagAndID:function(B,A,D){if(D){var C=(B.getElementById)?B.getElementById(D,true):Element.getElementById(B,D,true);
return(C&&Selectors.Filters.byTag(C,A))?[C]:[];}else{return B.getElementsByTagName(A);}},search:function(J,I,O){var B=[];var C=I.trim().replace(Selectors.RegExps.splitter,function(Z,Y,X){B.push(Y);
return":)"+X;}).split(":)");var K,F,E,V;for(var U=0,Q=C.length;U<Q;U++){var T=C[U];if(U==0&&Selectors.RegExps.quick.test(T)){K=J.getElementsByTagName(T);
continue;}var A=B[U-1];var L=Selectors.Utils.parseTagAndID(T);var W=L[0],M=L[1];if(U==0){K=Selectors.Utils.getByTagAndID(J,W,M);}else{var D={},H=[];for(var S=0,R=K.length;
S<R;S++){H=Selectors.Getters[A](H,K[S],W,M,D);}K=H;}var G=Selectors.Utils.parseSelector(T);if(G){E=[];for(var P=0,N=K.length;P<N;P++){V=K[P];if(Selectors.Utils.filter(V,G,O)){E.push(V);
}}K=E;}}return K;}};Selectors.Getters={" ":function(H,G,I,A,E){var D=Selectors.Utils.getByTagAndID(G,I,A);for(var C=0,B=D.length;C<B;C++){var F=D[C];if(Selectors.Utils.chk(F,E)){H.push(F);
}}return H;},">":function(H,G,I,A,F){var C=Selectors.Utils.getByTagAndID(G,I,A);for(var E=0,D=C.length;E<D;E++){var B=C[E];if(B.parentNode==G&&Selectors.Utils.chk(B,F)){H.push(B);
}}return H;},"+":function(C,B,A,E,D){while((B=B.nextSibling)){if(B.nodeType==1){if(Selectors.Utils.chk(B,D)&&Selectors.Filters.byTag(B,A)&&Selectors.Filters.byID(B,E)){C.push(B);
}break;}}return C;},"~":function(C,B,A,E,D){while((B=B.nextSibling)){if(B.nodeType==1){if(!Selectors.Utils.chk(B,D)){break;}if(Selectors.Filters.byTag(B,A)&&Selectors.Filters.byID(B,E)){C.push(B);
}}}return C;}};Selectors.Filters={byTag:function(B,A){return(A=="*"||(B.tagName&&B.tagName.toLowerCase()==A));},byID:function(A,B){return(!B||(A.id&&A.id==B));
},byClass:function(B,A){return(B.className&&B.className.contains(A," "));},byPseudo:function(A,D,C,B){return D.call(A,C,B);},byAttribute:function(C,D,B,E){var A=Element.prototype.getProperty.call(C,D);
if(!A){return false;}if(!B||E==undefined){return true;}switch(B){case"=":return(A==E);case"*=":return(A.contains(E));case"^=":return(A.substr(0,E.length)==E);
case"$=":return(A.substr(A.length-E.length)==E);case"!=":return(A!=E);case"~=":return A.contains(E," ");case"|=":return A.contains(E,"-");}return false;
}};Selectors.Pseudo=new Hash({empty:function(){return !(this.innerText||this.textContent||"").length;},not:function(A){return !Element.match(this,A);},contains:function(A){return(this.innerText||this.textContent||"").contains(A);
},"first-child":function(){return Selectors.Pseudo.index.call(this,0);},"last-child":function(){var A=this;while((A=A.nextSibling)){if(A.nodeType==1){return false;
}}return true;},"only-child":function(){var B=this;while((B=B.previousSibling)){if(B.nodeType==1){return false;}}var A=this;while((A=A.nextSibling)){if(A.nodeType==1){return false;
}}return true;},"nth-child":function(G,E){G=(G==undefined)?"n":G;var C=Selectors.Utils.parseNthArgument(G);if(C.special!="n"){return Selectors.Pseudo[C.special].call(this,C.a,E);
}var F=0;E.positions=E.positions||{};var D=$uid(this);if(!E.positions[D]){var B=this;while((B=B.previousSibling)){if(B.nodeType!=1){continue;}F++;var A=E.positions[$uid(B)];
if(A!=undefined){F=A+F;break;}}E.positions[D]=F;}return(E.positions[D]%C.a==C.b);},index:function(A){var B=this,C=0;while((B=B.previousSibling)){if(B.nodeType==1&&++C>A){return false;
}}return(C==A);},even:function(B,A){return Selectors.Pseudo["nth-child"].call(this,"2n+1",A);},odd:function(B,A){return Selectors.Pseudo["nth-child"].call(this,"2n",A);
}});Element.Events.domready={onAdd:function(A){if(Browser.loaded){A.call(this);}}};(function(){var B=function(){if(Browser.loaded){return ;}Browser.loaded=true;
window.fireEvent("domready");document.fireEvent("domready");};switch(Browser.Engine.name){case"webkit":(function(){(["loaded","complete"].contains(document.readyState))?B():arguments.callee.delay(50);
})();break;case"trident":var A=document.createElement("div");(function(){($try(function(){A.doScroll("left");return $(A).inject(document.body).set("html","temp").dispose();
}))?B():arguments.callee.delay(50);})();break;default:window.addEvent("load",B);document.addEvent("DOMContentLoaded",B);}})();var JSON=new Hash({encode:function(B){switch($type(B)){case"string":return'"'+B.replace(/[\x00-\x1f\\"]/g,JSON.$replaceChars)+'"';
case"array":return"["+String(B.map(JSON.encode).filter($defined))+"]";case"object":case"hash":var A=[];Hash.each(B,function(E,D){var C=JSON.encode(E);if(C){A.push(JSON.encode(D)+":"+C);
}});return"{"+A+"}";case"number":case"boolean":return String(B);case false:return"null";}return null;},$specialChars:{"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},$replaceChars:function(A){return JSON.$specialChars[A]||"\\u00"+Math.floor(A.charCodeAt()/16).toString(16)+(A.charCodeAt()%16).toString(16);
},decode:function(string,secure){if($type(string)!="string"||!string.length){return null;}if(secure&&!(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"/g,""))){return null;
}return eval("("+string+")");}});Native.implement([Hash,Array,String,Number],{toJSON:function(){return JSON.encode(this);}});var Cookie=new Class({Implements:Options,options:{path:false,domain:false,duration:false,secure:false,document:document},initialize:function(B,A){this.key=B;
this.setOptions(A);},write:function(B){B=encodeURIComponent(B);if(this.options.domain){B+="; domain="+this.options.domain;}if(this.options.path){B+="; path="+this.options.path;
}if(this.options.duration){var A=new Date();A.setTime(A.getTime()+this.options.duration*24*60*60*1000);B+="; expires="+A.toGMTString();}if(this.options.secure){B+="; secure";
}this.options.document.cookie=this.key+"="+B;return this;},read:function(){var A=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)");
return(A)?decodeURIComponent(A[1]):null;},dispose:function(){new Cookie(this.key,$merge(this.options,{duration:-1})).write("");return this;}});Cookie.write=function(B,C,A){return new Cookie(B,A).write(C);
};Cookie.read=function(A){return new Cookie(A).read();};Cookie.dispose=function(B,A){return new Cookie(B,A).dispose();};var Swiff=new Class({Implements:[Options],options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"transparent",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object;
},initialize:function(L,M){this.instance="Swiff_"+$time();this.setOptions(M);M=this.options;var B=this.id=M.id||this.instance;var A=$(M.container);Swiff.CallBacks[this.instance]={};
var E=M.params,G=M.vars,F=M.callBacks;var H=$extend({height:M.height,width:M.width},M.properties);var K=this;for(var D in F){Swiff.CallBacks[this.instance][D]=(function(N){return function(){return N.apply(K.object,arguments);
};})(F[D]);G[D]="Swiff.CallBacks."+this.instance+"."+D;}E.flashVars=Hash.toQueryString(G);if(Browser.Engine.trident){H.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
E.movie=L;}else{H.type="application/x-shockwave-flash";H.data=L;}var J='<object id="'+B+'"';for(var I in H){J+=" "+I+'="'+H[I]+'"';}J+=">";for(var C in E){if(E[C]){J+='<param name="'+C+'" value="'+E[C]+'" />';
}}J+="</object>";this.object=((A)?A.empty():new Element("div")).set("html",J).firstChild;},replaces:function(A){A=$(A,true);A.parentNode.replaceChild(this.toElement(),A);
return this;},inject:function(A){$(A,true).appendChild(this.toElement());return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].extend(arguments));
}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>");
return eval(rs);};var Fx=new Class({Implements:[Chain,Events,Options],options:{fps:50,unit:false,duration:500,link:"ignore",transition:function(A){return -(Math.cos(Math.PI*A)-1)/2;
}},initialize:function(A){this.subject=this.subject||this;this.setOptions(A);this.options.duration=Fx.Durations[this.options.duration]||this.options.duration.toInt();
var B=this.options.wait;if(B===false){this.options.link="cancel";}},step:function(){var A=$time();if(A<this.time+this.options.duration){var B=this.options.transition((A-this.time)/this.options.duration);
this.set(this.compute(this.from,this.to,B));}else{this.set(this.compute(this.from,this.to,1));this.complete();}},set:function(A){return A;},compute:function(C,B,A){return Fx.compute(C,B,A);
},check:function(A){if(!this.timer){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(A.bind(this,Array.slice(arguments,1)));
return false;}return false;},start:function(B,A){if(!this.check(arguments.callee,B,A)){return this;}this.from=B;this.to=A;this.time=0;this.startTimer();
this.onStart();return this;},complete:function(){if(this.stopTimer()){this.onComplete();}return this;},cancel:function(){if(this.stopTimer()){this.onCancel();
}return this;},onStart:function(){this.fireEvent("start",this.subject);},onComplete:function(){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject);
}},onCancel:function(){this.fireEvent("cancel",this.subject).clearChain();},pause:function(){this.stopTimer();return this;},resume:function(){this.startTimer();
return this;},stopTimer:function(){if(!this.timer){return false;}this.time=$time()-this.time;this.timer=$clear(this.timer);return true;},startTimer:function(){if(this.timer){return false;
}this.time=$time()-this.time;this.timer=this.step.periodical(Math.round(1000/this.options.fps),this);return true;}});Fx.compute=function(C,B,A){return(B-C)*A+C;
};Fx.Durations={"short":250,normal:500,"long":1000};Fx.CSS=new Class({Extends:Fx,prepare:function(D,E,B){B=$splat(B);var C=B[1];if(!$chk(C)){B[1]=B[0];
B[0]=D.getStyle(E);}var A=B.map(this.parse);return{from:A[0],to:A[1]};},parse:function(A){A=$lambda(A)();A=(typeof A=="string")?A.split(" "):$splat(A);
return A.map(function(C){C=String(C);var B=false;Fx.CSS.Parsers.each(function(F,E){if(B){return ;}var D=F.parse(C);if($chk(D)){B={value:D,parser:F};}});
B=B||{value:C,parser:Fx.CSS.Parsers.String};return B;});},compute:function(D,C,B){var A=[];(Math.min(D.length,C.length)).times(function(E){A.push({value:D[E].parser.compute(D[E].value,C[E].value,B),parser:D[E].parser});
});A.$family={name:"fx:css:value"};return A;},serve:function(C,B){if($type(C)!="fx:css:value"){C=this.parse(C);}var A=[];C.each(function(D){A=A.concat(D.parser.serve(D.value,B));
});return A;},render:function(A,D,C,B){A.setStyle(D,this.serve(C,B));},search:function(A){if(Fx.CSS.Cache[A]){return Fx.CSS.Cache[A];}var B={};Array.each(document.styleSheets,function(E,D){var C=E.href;
if(C&&C.contains("://")&&!C.contains(document.domain)){return ;}var F=E.rules||E.cssRules;Array.each(F,function(I,G){if(!I.style){return ;}var H=(I.selectorText)?I.selectorText.replace(/^\w+/,function(J){return J.toLowerCase();
}):null;if(!H||!H.test("^"+A+"$")){return ;}Element.Styles.each(function(K,J){if(!I.style[J]||Element.ShortStyles[J]){return ;}K=String(I.style[J]);B[J]=(K.test(/^rgb/))?K.rgbToHex():K;
});});});return Fx.CSS.Cache[A]=B;}});Fx.CSS.Cache={};Fx.CSS.Parsers=new Hash({Color:{parse:function(A){if(A.match(/^#[0-9a-f]{3,6}$/i)){return A.hexToRgb(true);
}return((A=A.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[A[1],A[2],A[3]]:false;},compute:function(C,B,A){return C.map(function(E,D){return Math.round(Fx.compute(C[D],B[D],A));
});},serve:function(A){return A.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(B,A){return(A)?B+A:B;}},String:{parse:$lambda(false),compute:$arguments(1),serve:$arguments(0)}});
Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(B,A){this.element=this.subject=$(B);this.parent(A);},set:function(B,A){if(arguments.length==1){A=B;
B=this.property||this.options.property;}this.render(this.element,B,A,this.options.unit);return this;},start:function(C,E,D){if(!this.check(arguments.callee,C,E,D)){return this;
}var B=Array.flatten(arguments);this.property=this.options.property||B.shift();var A=this.prepare(this.element,this.property,B);return this.parent(A.from,A.to);
}});Element.Properties.tween={set:function(A){var B=this.retrieve("tween");if(B){B.cancel();}return this.eliminate("tween").store("tween:options",$extend({link:"cancel"},A));
},get:function(A){if(A||!this.retrieve("tween")){if(A||!this.retrieve("tween:options")){this.set("tween",A);}this.store("tween",new Fx.Tween(this,this.retrieve("tween:options")));
}return this.retrieve("tween");}};Element.implement({tween:function(A,C,B){this.get("tween").start(arguments);return this;},fade:function(C){var E=this.get("tween"),D="opacity",A;
C=$pick(C,"toggle");switch(C){case"in":E.start(D,1);break;case"out":E.start(D,0);break;case"show":E.set(D,1);break;case"hide":E.set(D,0);break;case"toggle":var B=this.retrieve("fade:flag",this.get("opacity")==1);
E.start(D,(B)?0:1);this.store("fade:flag",!B);A=true;break;default:E.start(D,arguments);}if(!A){this.eliminate("fade:flag");}return this;},highlight:function(C,A){if(!A){A=this.retrieve("highlight:original",this.getStyle("background-color"));
A=(A=="transparent")?"#fff":A;}var B=this.get("tween");B.start("background-color",C||"#ffff88",A).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original"));
B.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(B,A){this.element=this.subject=$(B);this.parent(A);},set:function(A){if(typeof A=="string"){A=this.search(A);
}for(var B in A){this.render(this.element,B,A[B],this.options.unit);}return this;},compute:function(E,D,C){var A={};for(var B in E){A[B]=this.parent(E[B],D[B],C);
}return A;},start:function(B){if(!this.check(arguments.callee,B)){return this;}if(typeof B=="string"){B=this.search(B);}var E={},D={};for(var C in B){var A=this.prepare(this.element,C,B[C]);
E[C]=A.from;D[C]=A.to;}return this.parent(E,D);}});Element.Properties.morph={set:function(A){var B=this.retrieve("morph");if(B){B.cancel();}return this.eliminate("morph").store("morph:options",$extend({link:"cancel"},A));
},get:function(A){if(A||!this.retrieve("morph")){if(A||!this.retrieve("morph:options")){this.set("morph",A);}this.store("morph",new Fx.Morph(this,this.retrieve("morph:options")));
}return this.retrieve("morph");}};Element.implement({morph:function(A){this.get("morph").start(A);return this;}});(function(){var A=Fx.prototype.initialize;
Fx.prototype.initialize=function(B){A.call(this,B);var C=this.options.transition;if(typeof C=="string"&&(C=C.split(":"))){var D=Fx.Transitions;D=D[C[0]]||D[C[0].capitalize()];
if(C[1]){D=D["ease"+C[1].capitalize()+(C[2]?C[2].capitalize():"")];}this.options.transition=D;}};})();Fx.Transition=function(B,A){A=$splat(A);return $extend(B,{easeIn:function(C){return B(C,A);
},easeOut:function(C){return 1-B(1-C,A);},easeInOut:function(C){return(C<=0.5)?B(2*C,A)/2:(2-B(2*(1-C),A))/2;}});};Fx.Transitions=new Hash({linear:$arguments(0)});
Fx.Transitions.extend=function(A){for(var B in A){Fx.Transitions[B]=new Fx.Transition(A[B]);}};Fx.Transitions.extend({Pow:function(B,A){return Math.pow(B,A[0]||6);
},Expo:function(A){return Math.pow(2,8*(A-1));},Circ:function(A){return 1-Math.sin(Math.acos(A));},Sine:function(A){return 1-Math.sin((1-A)*Math.PI/2);
},Back:function(B,A){A=A[0]||1.618;return Math.pow(B,2)*((A+1)*B-A);},Bounce:function(D){var C;for(var B=0,A=1;1;B+=A,A/=2){if(D>=(7-4*B)/11){C=-Math.pow((11-6*B-11*D)/4,2)+A*A;
break;}}return C;},Elastic:function(B,A){return Math.pow(2,10*--B)*Math.cos(20*B*Math.PI*(A[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(B,A){Fx.Transitions[B]=new Fx.Transition(function(C){return Math.pow(C,[A+2]);
});});var Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false},initialize:function(A){this.xhr=new Browser.Request();
this.setOptions(A);this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.headers=new Hash(this.options.headers);},onStateChange:function(){if(this.xhr.readyState!=4||!this.running){return ;
}this.running=false;this.status=0;$try(function(){this.status=this.xhr.status;}.bind(this));if(this.options.isSuccess.call(this,this.status)){this.response={text:this.xhr.responseText,xml:this.xhr.responseXML};
this.success(this.response.text,this.response.xml);}else{this.response={text:null,xml:null};this.failure();}this.xhr.onreadystatechange=$empty;},isSuccess:function(){return((this.status>=200)&&(this.status<300));
},processScripts:function(A){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return $exec(A);}return A.stripScripts(this.options.evalScripts);
},success:function(B,A){this.onSuccess(this.processScripts(B),A);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain();
},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},setHeader:function(A,B){this.headers.set(A,B);
return this;},getHeader:function(A){return $try(function(){return this.xhr.getResponseHeader(A);}.bind(this));},check:function(A){if(!this.running){return true;
}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(A.bind(this,Array.slice(arguments,1)));return false;}return false;
},send:function(I){if(!this.check(arguments.callee,I)){return this;}this.running=true;var G=$type(I);if(G=="string"||G=="element"){I={data:I};}var D=this.options;
I=$extend({data:D.data,url:D.url,method:D.method},I);var E=I.data,B=I.url,A=I.method;switch($type(E)){case"element":E=$(E).toQueryString();break;case"object":case"hash":E=Hash.toQueryString(E);
}if(this.options.format){var H="format="+this.options.format;E=(E)?H+"&"+E:H;}if(this.options.emulation&&["put","delete"].contains(A)){var F="_method="+A;
E=(E)?F+"&"+E:F;A="post";}if(this.options.urlEncoded&&A=="post"){var C=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers.set("Content-type","application/x-www-form-urlencoded"+C);
}if(E&&A=="get"){B=B+(B.contains("?")?"&":"?")+E;E=null;}this.xhr.open(A.toUpperCase(),B,this.options.async);this.xhr.onreadystatechange=this.onStateChange.bind(this);
this.headers.each(function(K,J){if(!$try(function(){this.xhr.setRequestHeader(J,K);return true;}.bind(this))){this.fireEvent("exception",[J,K]);}},this);
this.fireEvent("request");this.xhr.send(E);if(!this.options.async){this.onStateChange();}return this;},cancel:function(){if(!this.running){return this;
}this.running=false;this.xhr.abort();this.xhr.onreadystatechange=$empty;this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});(function(){var A={};
["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(B){A[B]=function(){var C=Array.link(arguments,{url:String.type,data:$defined});
return this.send($extend(C,{method:B.toLowerCase()}));};});Request.implement(A);})();Element.Properties.send={set:function(A){var B=this.retrieve("send");
if(B){B.cancel();}return this.eliminate("send").store("send:options",$extend({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")},A));
},get:function(A){if(A||!this.retrieve("send")){if(A||!this.retrieve("send:options")){this.set("send",A);}this.store("send",new Request(this.retrieve("send:options")));
}return this.retrieve("send");}};Element.implement({send:function(A){var B=this.get("send");B.send({data:this,url:A||B.options.url});return this;}});Request.HTML=new Class({Extends:Request,options:{update:false,evalScripts:true,filter:false},processHTML:function(C){var B=C.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
C=(B)?B[1]:C;var A=new Element("div");return $try(function(){var D="<root>"+C+"</root>",G;if(Browser.Engine.trident){G=new ActiveXObject("Microsoft.XMLDOM");
G.async=false;G.loadXML(D);}else{G=new DOMParser().parseFromString(D,"text/xml");}D=G.getElementsByTagName("root")[0];for(var F=0,E=D.childNodes.length;
F<E;F++){var H=Element.clone(D.childNodes[F],true,true);if(H){A.grab(H);}}return A;})||A.set("html",C);},success:function(D){var C=this.options,B=this.response;
B.html=D.stripScripts(function(E){B.javascript=E;});var A=this.processHTML(B.html);B.tree=A.childNodes;B.elements=A.getElements("*");if(C.filter){B.tree=B.elements.filter(C.filter);
}if(C.update){$(C.update).empty().adopt(B.tree);}if(C.evalScripts){$exec(B.javascript);}this.onSuccess(B.tree,B.elements,B.html,B.javascript);}});Element.Properties.load={set:function(A){var B=this.retrieve("load");
if(B){send.cancel();}return this.eliminate("load").store("load:options",$extend({data:this,link:"cancel",update:this,method:"get"},A));},get:function(A){if(A||!this.retrieve("load")){if(A||!this.retrieve("load:options")){this.set("load",A);
}this.store("load",new Request.HTML(this.retrieve("load:options")));}return this.retrieve("load");}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Object.type,url:String.type}));
return this;}});Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(A){this.parent(A);this.headers.extend({Accept:"application/json","X-Request":"JSON"});
},success:function(A){this.response.json=JSON.decode(A,this.options.secure);this.onSuccess(this.response.json,A);}});Fx.Slide=new Class({Extends:Fx,options:{mode:"vertical"},initialize:function(B,A){this.addEvent("complete",function(){this.open=(this.wrapper["offset"+this.layout.capitalize()]!=0);
if(this.open&&Browser.Engine.webkit419){this.element.dispose().inject(this.wrapper);}},true);this.element=this.subject=$(B);this.parent(A);var C=this.element.retrieve("wrapper");
this.wrapper=C||new Element("div",{styles:$extend(this.element.getStyles("margin","position"),{overflow:"hidden"})}).wraps(this.element);this.element.store("wrapper",this.wrapper).setStyle("margin",0);
this.now=[];this.open=true;},vertical:function(){this.margin="margin-top";this.layout="height";this.offset=this.element.offsetHeight;},horizontal:function(){this.margin="margin-left";
this.layout="width";this.offset=this.element.offsetWidth;},set:function(A){this.element.setStyle(this.margin,A[0]);this.wrapper.setStyle(this.layout,A[1]);
return this;},compute:function(E,D,C){var B=[];var A=2;A.times(function(F){B[F]=Fx.compute(E[F],D[F],C);});return B;},start:function(B,E){if(!this.check(arguments.callee,B,E)){return this;
}this[E||this.options.mode]();var D=this.element.getStyle(this.margin).toInt();var C=this.wrapper.getStyle(this.layout).toInt();var A=[[D,C],[0,this.offset]];
var G=[[D,C],[-this.offset,0]];var F;switch(B){case"in":F=A;break;case"out":F=G;break;case"toggle":F=(this.wrapper["offset"+this.layout.capitalize()]==0)?A:G;
}return this.parent(F[0],F[1]);},slideIn:function(A){return this.start("in",A);},slideOut:function(A){return this.start("out",A);},hide:function(A){this[A||this.options.mode]();
this.open=false;return this.set([-this.offset,0]);},show:function(A){this[A||this.options.mode]();this.open=true;return this.set([0,this.offset]);},toggle:function(A){return this.start("toggle",A);
}});Element.Properties.slide={set:function(B){var A=this.retrieve("slide");if(A){A.cancel();}return this.eliminate("slide").store("slide:options",$extend({link:"cancel"},B));
},get:function(A){if(A||!this.retrieve("slide")){if(A||!this.retrieve("slide:options")){this.set("slide",A);}this.store("slide",new Fx.Slide(this,this.retrieve("slide:options")));
}return this.retrieve("slide");}};Element.implement({slide:function(D,E){D=D||"toggle";var B=this.get("slide"),A;switch(D){case"hide":B.hide(E);break;case"show":B.show(E);
break;case"toggle":var C=this.retrieve("slide:flag",B.open);B[(C)?"slideOut":"slideIn"](E);this.store("slide:flag",!C);A=true;break;default:B.start(D,E);
}if(!A){this.eliminate("slide:flag");}return this;}});Fx.Scroll=new Class({Extends:Fx,options:{offset:{x:0,y:0},wheelStops:true},initialize:function(B,A){this.element=this.subject=$(B);
this.parent(A);var D=this.cancel.bind(this,false);if($type(this.element)!="element"){this.element=$(this.element.getDocument().body);}var C=this.element;
if(this.options.wheelStops){this.addEvent("start",function(){C.addEvent("mousewheel",D);},true);this.addEvent("complete",function(){C.removeEvent("mousewheel",D);
},true);}},set:function(){var A=Array.flatten(arguments);this.element.scrollTo(A[0],A[1]);},compute:function(E,D,C){var B=[];var A=2;A.times(function(F){B.push(Fx.compute(E[F],D[F],C));
});return B;},start:function(C,H){if(!this.check(arguments.callee,C,H)){return this;}var E=this.element.getSize(),F=this.element.getScrollSize();var B=this.element.getScroll(),D={x:C,y:H};
for(var G in D){var A=F[G]-E[G];if($chk(D[G])){D[G]=($type(D[G])=="number")?D[G].limit(0,A):A;}else{D[G]=B[G];}D[G]+=this.options.offset[G];}return this.parent([B.x,B.y],[D.x,D.y]);
},toTop:function(){return this.start(false,0);},toLeft:function(){return this.start(0,false);},toRight:function(){return this.start("right",false);},toBottom:function(){return this.start(false,"bottom");
},toElement:function(B){var A=$(B).getPosition(this.element);return this.start(A.x,A.y);}});Fx.Elements=new Class({Extends:Fx.CSS,initialize:function(B,A){this.elements=this.subject=$$(B);
this.parent(A);},compute:function(G,H,I){var C={};for(var D in G){var A=G[D],E=H[D],F=C[D]={};for(var B in A){F[B]=this.parent(A[B],E[B],I);}}return C;
},set:function(B){for(var C in B){var A=B[C];for(var D in A){this.render(this.elements[C],D,A[D],this.options.unit);}}return this;},start:function(C){if(!this.check(arguments.callee,C)){return this;
}var H={},I={};for(var D in C){var F=C[D],A=H[D]={},G=I[D]={};for(var B in F){var E=this.prepare(this.elements[D],B,F[B]);A[B]=E.from;G[B]=E.to;}}return this.parent(H,I);
}});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,modifiers:{x:"left",y:"top"}},initialize:function(){var B=Array.link(arguments,{options:Object.type,element:$defined});
this.element=$(B.element);this.document=this.element.getDocument();this.setOptions(B.options||{});var A=$type(this.options.handle);this.handles=(A=="array"||A=="collection")?$$(this.options.handle):$(this.options.handle)||this.element;
this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.Engine.trident)?"selectstart":"mousedown";this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:$lambda(false)};
this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start);
return this;},start:function(C){if(this.options.preventDefault){C.preventDefault();}this.fireEvent("beforeStart",this.element);this.mouse.start=C.page;
var A=this.options.limit;this.limit={x:[],y:[]};for(var D in this.options.modifiers){if(!this.options.modifiers[D]){continue;}if(this.options.style){this.value.now[D]=this.element.getStyle(this.options.modifiers[D]).toInt();
}else{this.value.now[D]=this.element[this.options.modifiers[D]];}if(this.options.invert){this.value.now[D]*=-1;}this.mouse.pos[D]=C.page[D]-this.value.now[D];
if(A&&A[D]){for(var B=2;B--;B){if($chk(A[D][B])){this.limit[D][B]=$lambda(A[D][B])();}}}}if($type(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid};
}this.document.addEvents({mousemove:this.bound.check,mouseup:this.bound.cancel});this.document.addEvent(this.selection,this.bound.eventStop);},check:function(A){if(this.options.preventDefault){A.preventDefault();
}var B=Math.round(Math.sqrt(Math.pow(A.page.x-this.mouse.start.x,2)+Math.pow(A.page.y-this.mouse.start.y,2)));if(B>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop});
this.fireEvent("start",this.element).fireEvent("snap",this.element);}},drag:function(A){if(this.options.preventDefault){A.preventDefault();}this.mouse.now=A.page;
for(var B in this.options.modifiers){if(!this.options.modifiers[B]){continue;}this.value.now[B]=this.mouse.now[B]-this.mouse.pos[B];if(this.options.invert){this.value.now[B]*=-1;
}if(this.options.limit&&this.limit[B]){if($chk(this.limit[B][1])&&(this.value.now[B]>this.limit[B][1])){this.value.now[B]=this.limit[B][1];}else{if($chk(this.limit[B][0])&&(this.value.now[B]<this.limit[B][0])){this.value.now[B]=this.limit[B][0];
}}}if(this.options.grid[B]){this.value.now[B]-=(this.value.now[B]%this.options.grid[B]);}if(this.options.style){this.element.setStyle(this.options.modifiers[B],this.value.now[B]+this.options.unit);
}else{this.element[this.options.modifiers[B]]=this.value.now[B];}}this.fireEvent("drag",this.element);},cancel:function(A){this.document.removeEvent("mousemove",this.bound.check);
this.document.removeEvent("mouseup",this.bound.cancel);if(A){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element);
}},stop:function(A){this.document.removeEvent(this.selection,this.bound.eventStop);this.document.removeEvent("mousemove",this.bound.drag);this.document.removeEvent("mouseup",this.bound.stop);
if(A){this.fireEvent("complete",this.element);}}});Element.implement({makeResizable:function(A){return new Drag(this,$merge({modifiers:{x:"width",y:"height"}},A));
}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false},initialize:function(C,B){this.parent(C,B);this.droppables=$$(this.options.droppables);
this.container=$(this.options.container);if(this.container&&$type(this.container)!="element"){this.container=$(this.container.getDocument().body);}C=this.element;
var D=C.getStyle("position");var A=(D!="static")?D:"absolute";if(C.getStyle("left")=="auto"||C.getStyle("top")=="auto"){C.position(C.getPosition(C.offsetParent));
}C.setStyle("position",A);this.addEvent("start",function(){this.checkDroppables();},true);},start:function(B){if(this.container){var D=this.element,J=this.container,E=J.getCoordinates(D.offsetParent),F={},A={};
["top","right","bottom","left"].each(function(K){F[K]=J.getStyle("padding-"+K).toInt();A[K]=D.getStyle("margin-"+K).toInt();},this);var C=D.offsetWidth+A.left+A.right,I=D.offsetHeight+A.top+A.bottom;
var H=[E.left+F.left,E.right-F.right-C];var G=[E.top+F.top,E.bottom-F.bottom-I];this.options.limit={x:H,y:G};}this.parent(B);},checkAgainst:function(B){B=B.getCoordinates();
var A=this.mouse.now;return(A.x>B.left&&A.x<B.right&&A.y<B.bottom&&A.y>B.top);},checkDroppables:function(){var A=this.droppables.filter(this.checkAgainst,this).getLast();
if(this.overed!=A){if(this.overed){this.fireEvent("leave",[this.element,this.overed]);}if(A){this.overed=A;this.fireEvent("enter",[this.element,A]);}else{this.overed=null;
}}},drag:function(A){this.parent(A);if(this.droppables.length){this.checkDroppables();}},stop:function(A){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed]);
this.overed=null;return this.parent(A);}});Element.implement({makeDraggable:function(A){return new Drag.Move(this,A);}});var Color=new Native({initialize:function(B,C){if(arguments.length>=3){C="rgb";
B=Array.slice(arguments,0,3);}else{if(typeof B=="string"){if(B.match(/rgb/)){B=B.rgbToHex().hexToRgb(true);}else{if(B.match(/hsb/)){B=B.hsbToRgb();}else{B=B.hexToRgb(true);
}}}}C=C||"rgb";switch(C){case"hsb":var A=B;B=B.hsbToRgb();B.hsb=A;break;case"hex":B=B.hexToRgb(true);break;}B.rgb=B.slice(0,3);B.hsb=B.hsb||B.rgbToHsb();
B.hex=B.rgbToHex();return $extend(B,this);}});Color.implement({mix:function(){var A=Array.slice(arguments);var C=($type(A.getLast())=="number")?A.pop():50;
var B=this.slice();A.each(function(D){D=new Color(D);for(var E=0;E<3;E++){B[E]=Math.round((B[E]/100*(100-C))+(D[E]/100*C));}});return new Color(B,"rgb");
},invert:function(){return new Color(this.map(function(A){return 255-A;}));},setHue:function(A){return new Color([A,this.hsb[1],this.hsb[2]],"hsb");},setSaturation:function(A){return new Color([this.hsb[0],A,this.hsb[2]],"hsb");
},setBrightness:function(A){return new Color([this.hsb[0],this.hsb[1],A],"hsb");}});function $RGB(C,B,A){return new Color([C,B,A],"rgb");}function $HSB(C,B,A){return new Color([C,B,A],"hsb");
}function $HEX(A){return new Color(A,"hex");}Array.implement({rgbToHsb:function(){var B=this[0],C=this[1],J=this[2];var G,F,H;var I=Math.max(B,C,J),E=Math.min(B,C,J);
var K=I-E;H=I/255;F=(I!=0)?K/I:0;if(F==0){G=0;}else{var D=(I-B)/K;var A=(I-C)/K;var L=(I-J)/K;if(B==I){G=L-A;}else{if(C==I){G=2+D-L;}else{G=4+A-D;}}G/=6;
if(G<0){G++;}}return[Math.round(G*360),Math.round(F*100),Math.round(H*100)];},hsbToRgb:function(){var C=Math.round(this[2]/100*255);if(this[1]==0){return[C,C,C];
}else{var A=this[0]%360;var E=A%60;var F=Math.round((this[2]*(100-this[1]))/10000*255);var D=Math.round((this[2]*(6000-this[1]*E))/600000*255);var B=Math.round((this[2]*(6000-this[1]*(60-E)))/600000*255);
switch(Math.floor(A/60)){case 0:return[C,B,F];case 1:return[D,C,F];case 2:return[F,C,B];case 3:return[F,D,C];case 4:return[B,F,C];case 5:return[C,F,D];
}}return false;}});String.implement({rgbToHsb:function(){var A=this.match(/\d{1,3}/g);return(A)?hsb.rgbToHsb():null;},hsbToRgb:function(){var A=this.match(/\d{1,3}/g);
return(A)?A.hsbToRgb():null;}});var Group=new Class({initialize:function(){this.instances=Array.flatten(arguments);this.events={};this.checker={};},addEvent:function(B,A){this.checker[B]=this.checker[B]||{};
this.events[B]=this.events[B]||[];if(this.events[B].contains(A)){return false;}else{this.events[B].push(A);}this.instances.each(function(C,D){C.addEvent(B,this.check.bind(this,[B,C,D]));
},this);return this;},check:function(C,A,B){this.checker[C][B]=true;var D=this.instances.every(function(F,E){return this.checker[C][E]||false;},this);if(!D){return ;
}this.checker[C]={};this.events[C].each(function(E){E.call(this,this.instances,A);},this);}});Hash.Cookie=new Class({Extends:Cookie,options:{autoSave:true},initialize:function(B,A){this.parent(B,A);
this.load();},save:function(){var A=JSON.encode(this.hash);if(!A||A.length>4096){return false;}if(A=="{}"){this.dispose();}else{this.write(A);}return true;
},load:function(){this.hash=new Hash(JSON.decode(this.read(),true));return this;}});Hash.Cookie.implement((function(){var A={};Hash.each(Hash.prototype,function(C,B){A[B]=function(){var D=C.apply(this.hash,arguments);
if(this.options.autoSave){this.save();}return D;};});return A;})());var Sortables=new Class({Implements:[Events,Options],options:{snap:4,opacity:1,clone:false,revert:false,handle:false,constrain:false},initialize:function(A,B){this.setOptions(B);
this.elements=[];this.lists=[];this.idle=true;this.addLists($$($(A)||A));if(!this.options.clone){this.options.revert=false;}if(this.options.revert){this.effect=new Fx.Morph(null,$merge({duration:250,link:"cancel"},this.options.revert));
}},attach:function(){this.addLists(this.lists);return this;},detach:function(){this.lists=this.removeLists(this.lists);return this;},addItems:function(){Array.flatten(arguments).each(function(A){this.elements.push(A);
var B=A.retrieve("sortables:start",this.start.bindWithEvent(this,A));(this.options.handle?A.getElement(this.options.handle)||A:A).addEvent("mousedown",B);
},this);return this;},addLists:function(){Array.flatten(arguments).each(function(A){this.lists.push(A);this.addItems(A.getChildren());},this);return this;
},removeItems:function(){var A=[];Array.flatten(arguments).each(function(B){A.push(B);this.elements.erase(B);var C=B.retrieve("sortables:start");(this.options.handle?B.getElement(this.options.handle)||B:B).removeEvent("mousedown",C);
},this);return $$(A);},removeLists:function(){var A=[];Array.flatten(arguments).each(function(B){A.push(B);this.lists.erase(B);this.removeItems(B.getChildren());
},this);return $$(A);},getClone:function(B,A){if(!this.options.clone){return new Element("div").inject(document.body);}if($type(this.options.clone)=="function"){return this.options.clone.call(this,B,A,this.list);
}return A.clone(true).setStyles({margin:"0px",position:"absolute",visibility:"hidden",width:A.getStyle("width")}).inject(this.list).position(A.getPosition(A.getOffsetParent()));
},getDroppables:function(){var A=this.list.getChildren();if(!this.options.constrain){A=this.lists.concat(A).erase(this.list);}return A.erase(this.clone).erase(this.element);
},insert:function(C,B){var A="inside";if(this.lists.contains(B)){this.list=B;this.drag.droppables=this.getDroppables();}else{A=this.element.getAllPrevious().contains(B)?"before":"after";
}this.element.inject(B,A);this.fireEvent("sort",[this.element,this.clone]);},start:function(B,A){if(!this.idle){return ;}this.idle=false;this.element=A;
this.opacity=A.get("opacity");this.list=A.getParent();this.clone=this.getClone(B,A);this.drag=new Drag.Move(this.clone,{snap:this.options.snap,container:this.options.constrain&&this.element.getParent(),droppables:this.getDroppables(),onSnap:function(){B.stop();
this.clone.setStyle("visibility","visible");this.element.set("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone]);}.bind(this),onEnter:this.insert.bind(this),onCancel:this.reset.bind(this),onComplete:this.end.bind(this)});
this.clone.inject(this.element,"before");this.drag.start(B);},end:function(){this.drag.detach();this.element.set("opacity",this.opacity);if(this.effect){var A=this.element.getStyles("width","height");
var B=this.clone.computePosition(this.element.getPosition(this.clone.offsetParent));this.effect.element=this.clone;this.effect.start({top:B.top,left:B.left,width:A.width,height:A.height,opacity:0.25}).chain(this.reset.bind(this));
}else{this.reset();}},reset:function(){this.idle=true;this.clone.destroy();this.fireEvent("complete",this.element);},serialize:function(){var C=Array.link(arguments,{modifier:Function.type,index:$defined});
var B=this.lists.map(function(D){return D.getChildren().map(C.modifier||function(E){return E.get("id");},this);},this);var A=C.index;if(this.lists.length==1){A=0;
}return $chk(A)&&A>=0&&A<this.lists.length?B[A]:B;}});var Tips=new Class({Implements:[Events,Options],options:{onShow:function(A){A.setStyle("visibility","visible");
},onHide:function(A){A.setStyle("visibility","hidden");},showDelay:100,hideDelay:100,className:null,offsets:{x:16,y:16},fixed:false},initialize:function(){var C=Array.link(arguments,{options:Object.type,elements:$defined});
this.setOptions(C.options||null);this.tip=new Element("div").inject(document.body);if(this.options.className){this.tip.addClass(this.options.className);
}var B=new Element("div",{"class":"tip-top"}).inject(this.tip);this.container=new Element("div",{"class":"tip"}).inject(this.tip);var A=new Element("div",{"class":"tip-bottom"}).inject(this.tip);
this.tip.setStyles({position:"absolute",top:0,left:0,visibility:"hidden"});if(C.elements){this.attach(C.elements);}},attach:function(A){$$(A).each(function(D){var G=D.retrieve("tip:title",D.get("title"));
var F=D.retrieve("tip:text",D.get("rel")||D.get("href"));var E=D.retrieve("tip:enter",this.elementEnter.bindWithEvent(this,D));var C=D.retrieve("tip:leave",this.elementLeave.bindWithEvent(this,D));
D.addEvents({mouseenter:E,mouseleave:C});if(!this.options.fixed){var B=D.retrieve("tip:move",this.elementMove.bindWithEvent(this,D));D.addEvent("mousemove",B);
}D.store("tip:native",D.get("title"));D.erase("title");},this);return this;},detach:function(A){$$(A).each(function(C){C.removeEvent("mouseenter",C.retrieve("tip:enter")||$empty);
C.removeEvent("mouseleave",C.retrieve("tip:leave")||$empty);C.removeEvent("mousemove",C.retrieve("tip:move")||$empty);C.eliminate("tip:enter").eliminate("tip:leave").eliminate("tip:move");
var B=C.retrieve("tip:native");if(B){C.set("title",B);}});return this;},elementEnter:function(B,A){$A(this.container.childNodes).each(Element.dispose);
var D=A.retrieve("tip:title");if(D){this.titleElement=new Element("div",{"class":"tip-title"}).inject(this.container);this.fill(this.titleElement,D);}var C=A.retrieve("tip:text");
if(C){this.textElement=new Element("div",{"class":"tip-text"}).inject(this.container);this.fill(this.textElement,C);}this.timer=$clear(this.timer);this.timer=this.show.delay(this.options.showDelay,this);
this.position((!this.options.fixed)?B:{page:A.getPosition()});},elementLeave:function(A){$clear(this.timer);this.timer=this.hide.delay(this.options.hideDelay,this);
},elementMove:function(A){this.position(A);},position:function(D){var B=window.getSize(),A=window.getScroll();var E={x:this.tip.offsetWidth,y:this.tip.offsetHeight};
var C={x:"left",y:"top"};for(var F in C){var G=D.page[F]+this.options.offsets[F];if((G+E[F]-A[F])>B[F]){G=D.page[F]-this.options.offsets[F]-E[F];}this.tip.setStyle(C[F],G);
}},fill:function(A,B){(typeof B=="string")?A.set("html",B):A.adopt(B);},show:function(){this.fireEvent("show",this.tip);},hide:function(){this.fireEvent("hide",this.tip);
}});var SmoothScroll=new Class({Extends:Fx.Scroll,initialize:function(B,C){C=C||document;var E=C.getDocument(),D=C.getWindow();this.parent(E,B);this.links=(this.options.links)?$$(this.options.links):$$(E.links);
var A=D.location.href.match(/^[^#]*/)[0]+"#";this.links.each(function(G){if(G.href.indexOf(A)!=0){return ;}var F=G.href.substr(A.length);if(F&&$(F)){this.useLink(G,F);
}},this);if(!Browser.Engine.webkit419){this.addEvent("complete",function(){D.location.hash=this.anchor;},true);}},useLink:function(B,A){B.addEvent("click",function(C){this.anchor=A;
this.toElement(A);C.stop();}.bind(this));}});var Slider=new Class({Implements:[Events,Options],options:{onTick:function(A){if(this.options.snap){A=this.toPosition(this.step);
}this.knob.setStyle(this.property,A);},snap:false,offset:0,range:false,wheel:false,steps:100,mode:"horizontal"},initialize:function(E,A,D){this.setOptions(D);
this.element=$(E);this.knob=$(A);this.previousChange=this.previousEnd=this.step=-1;this.element.addEvent("mousedown",this.clickedElement.bind(this));if(this.options.wheel){this.element.addEvent("mousewheel",this.scrolledElement.bindWithEvent(this));
}var F,B={},C={x:false,y:false};switch(this.options.mode){case"vertical":this.axis="y";this.property="top";F="offsetHeight";break;case"horizontal":this.axis="x";
this.property="left";F="offsetWidth";}this.half=this.knob[F]/2;this.full=this.element[F]-this.knob[F]+(this.options.offset*2);this.min=$chk(this.options.range[0])?this.options.range[0]:0;
this.max=$chk(this.options.range[1])?this.options.range[1]:this.options.steps;this.range=this.max-this.min;this.steps=this.options.steps||this.full;this.stepSize=Math.abs(this.range)/this.steps;
this.stepWidth=this.stepSize*this.full/Math.abs(this.range);this.knob.setStyle("position","relative").setStyle(this.property,-this.options.offset);C[this.axis]=this.property;
B[this.axis]=[-this.options.offset,this.full-this.options.offset];this.drag=new Drag(this.knob,{snap:0,limit:B,modifiers:C,onDrag:this.draggedKnob.bind(this),onStart:this.draggedKnob.bind(this),onComplete:function(){this.draggedKnob();
this.end();}.bind(this)});if(this.options.snap){this.drag.options.grid=Math.ceil(this.stepWidth);this.drag.options.limit[this.axis][1]=this.full;}},set:function(A){if(!((this.range>0)^(A<this.min))){A=this.min;
}if(!((this.range>0)^(A>this.max))){A=this.max;}this.step=Math.round(A);this.checkStep();this.end();this.fireEvent("tick",this.toPosition(this.step));return this;
},clickedElement:function(C){var B=this.range<0?-1:1;var A=C.page[this.axis]-this.element.getPosition()[this.axis]-this.half;A=A.limit(-this.options.offset,this.full-this.options.offset);
this.step=Math.round(this.min+B*this.toStep(A));this.checkStep();this.end();this.fireEvent("tick",A);},scrolledElement:function(A){var B=(this.options.mode=="horizontal")?(A.wheel<0):(A.wheel>0);
this.set(B?this.step-this.stepSize:this.step+this.stepSize);A.stop();},draggedKnob:function(){var B=this.range<0?-1:1;var A=this.drag.value.now[this.axis];
A=A.limit(-this.options.offset,this.full-this.options.offset);this.step=Math.round(this.min+B*this.toStep(A));this.checkStep();},checkStep:function(){if(this.previousChange!=this.step){this.previousChange=this.step;
this.fireEvent("change",this.step);}},end:function(){if(this.previousEnd!==this.step){this.previousEnd=this.step;this.fireEvent("complete",this.step+"");
}},toStep:function(A){var B=(A+this.options.offset)*this.stepSize/this.full*this.steps;return this.options.steps?Math.round(B-=B%this.stepSize):B;},toPosition:function(A){return(this.full*Math.abs(this.min-A))/(this.steps*this.stepSize)-this.options.offset;
}});var Scroller=new Class({Implements:[Events,Options],options:{area:20,velocity:1,onChange:function(A,B){this.element.scrollTo(A,B);}},initialize:function(B,A){this.setOptions(A);
this.element=$(B);this.listener=($type(this.element)!="element")?$(this.element.getDocument().body):this.element;this.timer=null;this.coord=this.getCoords.bind(this);
},start:function(){this.listener.addEvent("mousemove",this.coord);},stop:function(){this.listener.removeEvent("mousemove",this.coord);this.timer=$clear(this.timer);
},getCoords:function(A){this.page=(this.listener.get("tag")=="body")?A.client:A.page;if(!this.timer){this.timer=this.scroll.periodical(50,this);}},scroll:function(){var B=this.element.getSize(),A=this.element.getScroll(),E=this.element.getPosition(),D={x:0,y:0};
for(var C in this.page){if(this.page[C]<(this.options.area+E[C])&&A[C]!=0){D[C]=(this.page[C]-this.options.area-E[C])*this.options.velocity;}else{if(this.page[C]+this.options.area>(B[C]+E[C])&&B[C]+B[C]!=A[C]){D[C]=(this.page[C]-B[C]+this.options.area-E[C])*this.options.velocity;
}}}if(D.y||D.x){this.fireEvent("change",[A.x+D.x,A.y+D.y]);}}});var Asset=new Hash({javascript:function(F,D){D=$extend({onload:$empty,document:document,check:$lambda(true)},D);
var B=new Element("script",{src:F,type:"text/javascript"});var E=D.onload.bind(B),A=D.check,G=D.document;delete D.onload;delete D.check;delete D.document;
B.addEvents({load:E,readystatechange:function(){if(["loaded","complete"].contains(this.readyState)){E();}}}).setProperties(D);if(Browser.Engine.webkit419){var C=(function(){if(!$try(A)){return ;
}$clear(C);E();}).periodical(50);}return B.inject(G.head);},css:function(B,A){return new Element("link",$merge({rel:"stylesheet",media:"screen",type:"text/css",href:B},A)).inject(document.head);
},image:function(C,B){B=$merge({onload:$empty,onabort:$empty,onerror:$empty},B);var D=new Image();var A=$(D)||new Element("img");["load","abort","error"].each(function(E){var F="on"+E;
var G=B[F];delete B[F];D[F]=function(){if(!D){return ;}if(!A.parentNode){A.width=D.width;A.height=D.height;}D=D.onload=D.onabort=D.onerror=null;G.delay(1,A,A);
A.fireEvent(E,A,1);};});D.src=A.src=C;if(D&&D.complete){D.onload.delay(1);}return A.setProperties(B);},images:function(D,C){C=$merge({onComplete:$empty,onProgress:$empty},C);
if(!D.push){D=[D];}var A=[];var B=0;D.each(function(F){var E=new Asset.image(F,{onload:function(){C.onProgress.call(this,B,D.indexOf(F));B++;if(B==D.length){C.onComplete();
}}});A.push(E);});return new Elements(A);}});var Accordion=new Class({Extends:Fx.Elements,options:{display:0,show:false,height:true,width:false,opacity:true,fixedHeight:false,fixedWidth:false,wait:false,alwaysHide:false},initialize:function(){var C=Array.link(arguments,{container:Element.type,options:Object.type,togglers:$defined,elements:$defined});
this.parent(C.elements,C.options);this.togglers=$$(C.togglers);this.container=$(C.container);this.previous=-1;if(this.options.alwaysHide){this.options.wait=true;
}if($chk(this.options.show)){this.options.display=false;this.previous=this.options.show;}if(this.options.start){this.options.display=false;this.options.show=false;
}this.effects={};if(this.options.opacity){this.effects.opacity="fullOpacity";}if(this.options.width){this.effects.width=this.options.fixedWidth?"fullWidth":"offsetWidth";
}if(this.options.height){this.effects.height=this.options.fixedHeight?"fullHeight":"scrollHeight";}for(var B=0,A=this.togglers.length;B<A;B++){this.addSection(this.togglers[B],this.elements[B]);
}this.elements.each(function(E,D){if(this.options.show===D){this.fireEvent("active",[this.togglers[D],E]);}else{for(var F in this.effects){E.setStyle(F,0);
}}},this);if($chk(this.options.display)){this.display(this.options.display);}},addSection:function(E,C,G){E=$(E);C=$(C);var F=this.togglers.contains(E);
var B=this.togglers.length;this.togglers.include(E);this.elements.include(C);if(B&&(!F||G)){G=$pick(G,B-1);E.inject(this.togglers[G],"before");C.inject(E,"after");
}else{if(this.container&&!F){E.inject(this.container);C.inject(this.container);}}var A=this.togglers.indexOf(E);E.addEvent("click",this.display.bind(this,A));
if(this.options.height){C.setStyles({"padding-top":0,"border-top":"none","padding-bottom":0,"border-bottom":"none"});}if(this.options.width){C.setStyles({"padding-left":0,"border-left":"none","padding-right":0,"border-right":"none"});
}C.fullOpacity=1;if(this.options.fixedWidth){C.fullWidth=this.options.fixedWidth;}if(this.options.fixedHeight){C.fullHeight=this.options.fixedHeight;}C.setStyle("overflow","hidden");
if(!F){for(var D in this.effects){C.setStyle(D,0);}}return this;},display:function(A){A=($type(A)=="element")?this.elements.indexOf(A):A;if((this.timer&&this.options.wait)||(A===this.previous&&!this.options.alwaysHide)){return this;
}this.previous=A;var B={};this.elements.each(function(E,D){B[D]={};var C=(D!=A)||(this.options.alwaysHide&&(E.offsetHeight>0));this.fireEvent(C?"background":"active",[this.togglers[D],E]);
for(var F in this.effects){B[D][F]=C?0:E[this.effects[F]];}},this);return this.start(B);}});

/*
	Filename: moo.rd - A lightweight Mootools extension
	
	Author: Riccardo Degni, <http://www.riccardodegni.it/> and the moo.rd Team
	
	License: GNU GPL License
	
	Copyright: copyright 2007 Riccardo Degni
	
	[Credits]
		[li] moo.rd is based on the MooTools framework <http://mootools.net/>, and uses the MooTools syntax
		[li] moo.rd constructors extends some of the MooTools Classes
		[li] moo.rd Documentation is written by Riccardo Degni
	[/Credits]
*/

var Moo = {};

Moo.Rd = {
	version: '1.3.2',
	author: 'Riccardo Degni',
	members: [
		'Cristiano Fino',
		'Moocha'
	]
};

/*
	Filename: constructors.js
	
	[Description] 
		Contains some of the moo.rd native Constructors based on the MooTools Class. It permits a major modularity.
	[/Description]
	
	Contains: Class Table, Class Make
*/
/*
	Class: Table
	Description: Allows you to customize tables, tables rows, cells and columns 
*/
var Table = new Class({	
	initialize: function(element) {
		this.element = $(element);
		this.rows = this.element.getElements('tr');
		this.cells = this.element.getElements('tr').getElements('td');
	}
});

/*
	Class: Make
	Description: Wrapper to create Classes that make dinamically Elements.  
*/
var Make = new Class({
	Implements: [Options],
	options: {
		content: 'text'
	}
});

/*
	Filename: type.js
	
	[Description]
		Contains shortcut functions to detect the type of an object using the $type function and the $dump function to detect the value and the type of every objects
	[/Description]
	
	Contains: A collection of functions based on the $type function plus the $dump function
	
	[Functions]
		$dump --- returns the value and the type of the object passed in
		$string --- returns true if the object is a string
		$int --- returns true if the object is a number
		$array --- returns true if the object is an array
		$object --- returns true if the object is an object
		$function --- returns true if the object is a function
		$date --- returns true if the object is a date
		$class --- returns true if the object is a class
		$element --- returns true if the object is an element
		$collection --- returns true if the object is a collection
		$arguments --- returns true if the object is the arguments object
		$textnode --- returns true if the object is a textnode
		$whitespace --- returns true if the object is a whitespace
		$window --- returns true if the object is the window object
		$document --- returns true if the object is the document object
	[/Functions]
*/
/*
	Function: $dump
	Description: returns the value and the type of the object passed in
	[Arguments]
		obj :: the object to analize
		results :: optional. the element to put the results to. If false returns the result string.
	[/Arguments]
	[Example] 
		> var s = 'some data';
		>
		> $dump(s, 'box');
		> // returns
		> '(
		>   Value: some data
		>   Type: string
		> )'
		>
		> var a = ['a', 'b', 'c', 'd'];
		>
		> $dump(a, 'box');
		> // returns
		> '(
		>   Value: a, b, c, d
		>   Type: array
		> )'
	[/Example]
*/
function $dump(obj, result) {
	var r = '(' + '<br />';
	var tinyspaces = '&nbsp;&nbsp;';
	r += tinyspaces + 'Value: ' + obj.toString() + '<br />';
	r += tinyspaces + 'Type: ' + $type(obj) + '<br />';
	r += ')';
	return (result) ? $(result).set('html', r) : r;
}

/*
	Function: $string
	Description: returns true if the object is a string
*/
function $string(obj) {
	return $type(obj) == 'string';
}

/*
	Function: $int
	Description: returns true if the object is a number
*/
function $int(obj) {
	return $type(obj) == 'number';
}

/*
	Function: $array
	Description: returns true if the object is an array
*/
function $array(obj) {
	return $type(obj) == 'array';
}

/*
	Function: $object
	Description: returns true if the object is an object
*/
function $object(obj) {
	return $type(obj) == 'object';
}

/*
	Function: $function
	Description: returns true if the object is a function
*/
function $function(obj) {
	return $type(obj) == 'function';
}

/*
	Function: $date
	Description: returns true if the object is a date
*/
function $date(obj) {
	return $type(obj) == 'date';
}

/*
	Function: $class
	Description: returns true if the object is a class
*/
function $class(obj) {
	return $type(obj) == 'class';
}

/*
	Function: $element
	Description: returns true if the object is an element
*/
function $element(obj) {
	return $type(obj) == 'element';
}

/*
	Function: $collection
	Description: returns true if the object is a collection
*/
function $collection(obj) {
	return $type(obj) == 'collection';
}

/*
	Function: $arguments
	Description: returns true if the object is the arguments object
*/
function $arguments(obj) {
	return $type(obj) == 'arguments';
}

/*
	Function: $textnode
	Description: returns true if the object is a textnode
*/
function $textnode(obj) {
	return $type(obj) == 'textnode';
}

/*
	Function: $whitespace
	Description: returns true if the object is a whitespace
*/
function $whitespace(obj) {
	return $type(obj) == 'whitespace';
}

/*
	Function: $window
	Description: returns true if the object is the window object
*/
function $window(obj) {
	return $type(obj) == 'window';
}

/*
	Function: $document
	Description: returns true if the object is the document object
*/
function $document(obj) {
	return $type(obj) == 'document';
}

/*
	Filename: browser.js
	
	[Description]
		Contains some Browser properties to ease the detection of the browser which is working
	[/Description]
	
	Contains: Hash Browser
	
	[Summary]
		Browser ::: Extends the Browser Hash with new properties 
	[/Summary]
*/
/*
	Hash: Browser
	
	[Description]  
		Extends the Browser Hash with new properties, to speed up and ease the detection of the browser which is working.
	[/Description]
	
	[Hash]
		 Browser.ie : alias of Browser.Engine.trident
		 Browser.ie6 : alias of Browser.Engine.trident4
		 Browser.ie7 : alias of Browser.Engine.trident5
		 Browser.firefox : alias of Browser.Engine.gecko
		 Browser.safari : alias of Browser.Engine.webkit
		 Browser.safari2 : alias of Browser.Engine.webkit419
		 Browser.safari3 : alias of Browser.Engine.webkit420
		 Browser.opera : alias of Browser.Engine.presto
		 Browser.opera925 : alias of Browser.Engine.presto925
		 Browser.opera950 : alias of Browser.Engine.presto950
	[/Hash]
*/
Browser.ie = Browser.Engine.trident;
Browser.ie6 = Browser.Engine.trident4;
Browser.ie7 = Browser.Engine.trident5;
Browser.firefox = Browser.Engine.gecko;
Browser.safari = Browser.Engine.webkit;
Browser.safari2 = Browser.Engine.webkit419;
Browser.safari3 = Browser.Engine.webkit420;
Browser.opera = Browser.Engine.presto;
Browser.opera925 = Browser.Engine.presto925;
Browser.opera950 = Browser.Engine.presto950;

/*
	Filename: overlay.js
	
	[Description]
		Contains the Overlay Utility Class, that can be implemented with Implements property into any Class
	[/Description]
	
	Contains: Class Overlay
	
	Requires: browser.js
	
	[Summary]
		Overlay ::: Utility Class for creating customized and advanced overlays
	[/Summary]
*/
/*
	Class: Overlay
	
	[Description]  
		Utility Class for creating customized and advanced overlays. Adds the Overlay properties to the Classes
	[/Description]
	
	Constructor: new Overlay()
	
	[Methods]
		createOverlay -- creates the overlay property which represents the overlay
		createFullPage -- creates the full page overlay which represents the upper level
		setLight -- sets the light of the overlay. Can be 'draken', 'lighten', false or a color
		injectOverlay -- injects the overlay and indicates that the overlay is active
		removeOverlay -- removes the overlay with additional controls for IE 6
	[/Methods]
*/
var Overlay = new Class({
						
	/*
	Method: createOverlay
	Description:  creates the overlay property which represents the overlay
	[Arguments]
		id :: the overlay id
		light :: the overlay light. It can be 'darken' 'lighten', false or a color
	[/Arguments]
	*/
	createOverlay: function(id, light) {
		this.overlay = new Element('div', {
			'id': id || 'overlay',
			'styles': {
				'position': (Browser.ie6) ? 'absolute' : 'fixed',
				'top': '0px',
				'left': '0px',
				'width': (Browser.ie6) ? window.getWidth() : '100%',
				'height': '100%',
				'background-image':'url(g.gif)',
				'z-index': 800
			}
		});
		
		if(Browser.Engine.presto) this.overlay.setStyle('overflow', 'hidden');  
	
		this.setLight(light);
		
		return this;
	},
	
	/*
	Method: createFullPage
	Description:  creates the full page overlay which represents the upper level
	[Arguments]
		id :: the fullpage id
	[/Arguments]
	*/
	createFullPage: function(id) {
		this.fullpage = new Element('div', {
			'id': id || 'fullpage',
			'styles': {
				'position': (Browser.ie6) ? 'absolute' : 'fixed',
				'top': '0px',
				'left': '0px',
				'width': (Browser.ie6) ? window.getWidth() : '100%',
				'height': '100%',
				'background-image':'url(g.gif)',
				'z-index': 900
			}
		});
		
		if(Browser.Engine.presto) this.fullpage.setStyle('overflow', 'hidden');  
		
		return this;
	},
	
	/*
	Method: setLight
	Description:  sets the light of the overlay. Can be 'darken', 'lighten', false or a color
	[Arguments]
		light :: the light of the overlay 
		opacity :: optional. the opacity value of the overlay
	[/Arguments]
	*/
	setLight: function(light, opacity) {
		switch(light) {
			case 'darken': 
				var color = 'rgb(0, 153, 0)';
				break;
			case 'lighten':
				var color = 'rgb(0, 153, 0)';
				break;
			case false:
				var color = 'transparent';
				break;
			default: 
				var color = light;
				break;
		};
		this.overlay.setStyles({
			'background-color': color,
			'opacity': opacity || '0.6'			   
		});
		
		return this;
	},
	
	/*
	Method: injectOverlay
	Description:  injects the overlay and indicates that the overlay is active
	[Arguments]
		fullpage :: if true the fullpage will be injected too
	[/Arguments]
	*/
	injectOverlay: function(fullpage) {
		this.overlay.inject(document.body);
		if(fullpage) this.fullpage.inject(document.body);
		this.overlayActive = true;
		this.fixOverlay();
		return this;
	},
	
	/*
	Method: removeOverlay
	Description:  removes the overlay with additional controls for IE 6
	*/
	removeOverlay: function() {
		this.overlay.dispose();
		this.fullpage.dispose();
		if(Browser.ie6) {
			document.body.setStyles({'height': this.bodyHeightTrident4, 'overflow': this.bodyOverflowTrident4});
		}
		this.overlayActive = false;
		return this;
	},
	
	fixOverlay: function() {
		if(Browser.ie6) {
			if(!this.bodyHeightTrident4) this.bodyHeightTrident4 = $(document.body).getStyle('height');
			this.bodyOverflowTrident4 = $(document.body).getStyle('overflow');
			
			$$(this.overlay, this.fullpage).setStyle('overflow', 'hidden');
			
			$$(window, document.body).setStyles({
				'height': '100%',
				'overflow': 'auto',
				'margin': 0,
				'padding': 0
			});
		}
		return this;
	}
});

/*
	Filename: custom_base.js
	
	[Description] 
		Contains a powerful wrapper which allows to create modal, draggable and fully-customizable boxes.
		It is used to create the Custom.Alert, Custom.Confirm and Custom.Prompt Classes 
	[/Description]
	
	Contains: Class Custom
	
	Requires: overlay.js
	
	[Summary]
		Custom ::: A powerful wrapper which allows you to create modal boxes
	[/Summary]
*/
/*
	Class: Custom
	
	[Description]  
		The Custom Class is a powerful wrapper which allows you to create modal boxes.
	 	You can completely customize this boxes in all its features: styles, zones, events, texts and many more.
		You can decide which zones must be injected and which mustn't be.
		In addiction, you can decide the overlay light, whether enabling drag or not, the drag opacity, 
		whether enabling fade transitions or not.
	[/Description]
	
	Implements: Overlay
	
	Constructor: new Custom (title, text, options)
	
	[Properties] 
		title - a string represents the title of the box
		text - a string represents the content text of the box
		options - optional. an object which permits to customize the box
	[/Properties]
	
	[Options]
		enable : an object which allows to decide which zones and events must be created
		zones : an object which contains the class names of the box zones
		buttons : an object which contains the buttons css classes
		text : an object which contains the buttons contents
		height : the box height. Default is 'auto'
		width : the box width. Default is '300px'
		opacify : if true the box appears and disappears with an opacity transition. Default is true
		content : 'text' or 'html', the content types of the box title, the box box and the box buttons. Default is 'text'
		draggable : if true the box will be draggable. Default is true
		dragOpacity : if true the box will be affected by a fade effect on drag
		adjustStyles : if true adjusts the position of the box on window resize. Default is true
		promptType : an object which contains the prompt settings
		overlay : the type of the overlay. 'lighten', 'darken', color or false (default)
	[/Options]
	
	>> enable:
		[List]
			[li] closeButton: if true the close button will be added
			[li] confirmButton: if true the confirm button will be added
			[li] cancelButton: if true the cancel button will be added
			[li] textBox: if true the prompt will be displayed (can be an input or a textarea)
	 		[li] onConfirm: if true the onConfirm event will be fired
			[li] onCancel: if true the onCancel event will be fired
		[/List]
	
	>> zones:
		[List]
			[li] box: is the box that contains the other zones
			[li] head: is the header of the box. (contains the title)
			[li] body: is the main content of the box
	 		[li] buttonBox: the zone which contains the confirm and cancel buttons
			[li] promptBox: the zone which contains the prompt (input or textarea) 
		[/List]
	
	>> buttons:
		[List]
			[li] confirmButton: the confirm button class name
			[li] closeButton: the close button class name
			[li] cancelButton: the cancel button class name
		[/List]
		
	>> text:
		[List]
			[li] confirmButtonText: the text of the confirm button. Defaults to 'OK'
			[li] closeButtonText: the text of the close button. Defaults to 'X'
			[li] cancelButtonText: the text of the cancel button. Defaults to 'Cancel'
		[/List]
		
	>> promptType:
		[List]
			[li] box: 'single' or 'multi'. Default is 'single'
			[li] lines: if box is 'multi' represents the number of lines. Default is 4 
			[li] startValue: the start value. Default is ''
			[li] search: where to search your value. Can be 'google', 'yahoo', 'wikipedia' or false (default)
			[li] target: indicates if open another window for the custom search. Can be 'new' (default) or 'same'
		[/List]
		
	[Events]
		onConfirm : function fired when users confirm
		onCancel : function fired when users cancel
	[/Events]
	
	[Methods]
		create -- creates the custom box
		setText -- sets the text of the custom box
		setTitle -- sets the title of the custom box
		setIDs -- sets the id value respectively for the box, the overlay and the fullpage at once
	[/Methods]
*/
var Custom = new Class({
		
	Implements: [Options, Events, Overlay],
		
	options: {
		height: 'auto',
		width: '300px',
		overlay: false,
		opacify: true,
		draggable: true,
		dragOpacity: false,
		adjustStyles: true,
		promptType: {
			box: 'single',
			lines: 1,
			startValue: '',
			search: false,
			target: 'new'
		},
		content: 'text',
		enable: {
			closeButton: true,
			confirmButton: true,
			cancelButton: true,
			onConfirm: true,
			onCancel: true,
			textBox: false
		},
		text: {
			confirmButtonText: 'OK',
			closeButtonText: 'X',
			cancelButtonText: 'Cancel'
		},
		zones: {
			box: null,
			head: null,
			body: null,
			buttonBox: '',
			promptBox: ''
		},
		buttons: {
			closeButton: '',
			confirmButton: '',
			cancelButton: ''
		},
		onConfirm: $empty,
		onCancel: $empty
	},
	
	initialize: function(title, text, options) {
		this.title = title;
		this.text = text;
		this.setOptions(options);
		this.box = new Element('div', {
			'id': 'customBox',
			'styles': {
				'position': (!Browser.Engine.trident4) ? 'fixed' : 'absolute',
				'top': '50%',
				'left': '50%',
				'z-index': 1000,
				'height': this.options.height,
				'width': this.options.width
			}
		});
		this.createOverlay('customBoxOverlay', this.options.overlay);
		this.createFullPage('customBoxfullpage');
		this.mechanize();
		this.box.set('tween', {duration: 1000});
		this.dragOptions = {container: this.fullpage};
		if(this.options.dragOpacity) 
			this.dragOptions = $merge(this.dragOptions, {
				onDrag: function(element) {
					element.set('opacity', 0.6);
				},
				onComplete: function(element) {
					element.set('opacity', 1);
				}
			});
	},
	
	/*
	Method: create
	Description:  creates the custom box
	[Example]  
		> var cc = new Custom.Confirm('custom confirm', 'Do you want to submit?', 
		> {box:'ccbox', head: 'cchead', body: 'ccbody'});
		> 
		> cc.create();
	[/Example]
	*/
	create: function() {
		this.customize();
	},
	
	mechanize: function() {
		if(this.options.zones['box']) this.box.addClass(this.options.zones['box']);
		
		this.head = new Element('div').injectInside(this.box);
		if(this.options.zones.head) this.head.addClass(this.options.zones['head']);
		this.head.set(this.options.content, this.title);
		
		if(this.options.enable.closeButton) {
			this.closebutton = new Element('a', {'id': 'customCloseButton', 'class': this.options.buttons.closeButton}).injectInside(this.head);
			this.closebutton.setProperty('href', '#');
			this.closebutton.set(this.options.content, this.options.text.closeButtonText);
			this.closebutton.addEvent('click', function(event) {
				event.preventDefault();
			});
			this.closebutton.addEvent('click', this.cancelRemove.bind(this));
		}
		
		this.content = new Element('div').injectInside(this.box);
		if(this.options.zones.body) this.content.addClass(this.options.zones['body']);
		this.content.set(this.options.content, this.text);
		
		if(this.options.enable.textBox) {	
			this.promptbox = new Element('div', {
				'id': 'customPromptTextBox', 'class': this.options.zones.promptBox}).inject(this.box);
			this.form = new Element('form', {'id': 'customPromptTextForm', 'action': '#'}).inject(this.promptbox);
			
			switch(this.options.promptType.box) {
				case 'single':  this.input = new Element('input', {'type': 'text', 'value': this.options.promptType.startValue}).inject(this.form);
								break;
				case 'multi':	this.input = new Element('textarea', {'value': this.options.promptType.startValue}).inject(this.form).inject(this.form).setProperty('rows', this.options.promptType.lines);
								break;
			}
			
			switch(this.options.promptType.search) {
				case 'google':
					this.addEvent('onConfirm', function(event) {
						if(this.options.promptType.target == 'same')
							location.href = 'http://www.google.it/search?q=' + this.input.get('value');
						else if(this.options.promptType.target == 'new')
							window.open('http://www.google.it/search?q=' + this.input.get('value'));
					});
					break;
				case 'yahoo':
					this.addEvent('onConfirm', function(event) {
						if(this.options.promptType.target == 'same')
							location.href = 'http://search.yahoo.com/search?p=' + this.input.get('value');
						else if(this.options.promptType.target == 'new')
							window.open('http://search.yahoo.com/search?p=' + this.input.get('value'));
					});
					break;
				case 'wikipedia':
					this.addEvent('onConfirm', function(event) {
						if(this.options.promptType.target == 'same')
							location.href = 'http://en.wikipedia.org/wiki/' + this.input.get('value');
						else if(this.options.promptType.target == 'new')
							window.open('http://en.wikipedia.org/wiki/' + this.input.get('value'));
					});
					break;
			}
		}
	
		this.closebox = new Element('div', {'id': 'customButtonBox', 'class': this.options.zones.buttonBox}).injectInside(this.box);
	
		if(this.options.enable.confirmButton) {
			this.button = new Element('a', {'id': 'customButton', 'class': this.options.buttons.confirmButton}).injectInside(this.closebox);
			this.button.setProperty('href', '#');
			this.button.set(this.options.content, this.options.text.confirmButtonText);
			this.button.addEvent('click', function(event) {
				event.preventDefault();
			});
			
			this.button.addEvent('click', this.confirmRemove.bind(this));
		}
		
		if(this.options.enable.cancelButton) {
			this.cancelButton = new Element('a', {'id': 'customCancelButton', 'class': this.options.buttons.cancelButton}).injectInside(this.closebox);
			this.cancelButton.setProperty('href', '#');
			this.cancelButton.set(this.options.content, this.options.text.cancelButtonText);
			this.cancelButton.addEvent('click', function(event) {
				event.preventDefault();
			});
			
			this.cancelButton.addEvent('click', this.cancelRemove.bind(this));
		}
	},
	
	customize: function() {
		if($(this.box.get('id')))  return;
		
		if(this.options.opacify)	this.box.set('opacity', 0);
		
		this.box.injectInside(this.fullpage);
		this.injectOverlay(true);
		
		var dimensions = this.dimensions = { 
			top: this.box.getSize().y/2,
			left: this.box.getSize().x/2,
			fullTop: this.fullpage.getSize().y.toInt()/2,
			fullLeft: this.fullpage.getSize().x.toInt()/2
		};
		
		this.box.setStyles({
			'margin-left': -dimensions.left,
			'margin-top': -dimensions.top,
			'top': dimensions.fullTop,
			'left': dimensions.fullLeft 
		});
		
		if(this.options.opacify)	this.box.fade('in');
		
		if(this.options.draggable) this.drag = new Drag.Move(this.box, this.dragOptions);
		
		if(this.options.adjustStyles) {
			this.newsizes = function() {
				this.box.setStyles({
					'top': window.getSize().y.toInt()/2,
					'left': window.getSize().x.toInt()/2
				});
				if(this.options.draggable) this.drag = new Drag.Move(this.box, this.dragOptions);
			};
			this.boundsizes = this.newsizes.bind(this);
			window.addEvent('resize', this.boundsizes);
		}
	},
	
	remove: function() {
		this.box.dispose();
		this.fullpage.dispose();
		this.removeOverlay();
		window.removeEvent('resize', this.boundsizes);
	},
	
	checkremove: function() {
		if(this.options.opacify) {
			this.box.fade('out');
			this.remove.delay(this.box.get('tween').options.duration.toInt(), this);
		}
		else {
			this.remove();
		}
	},
	
	confirmRemove: function() {
		if(this.options.enable.onConfirm) (this.input) ? this.fireEvent('onConfirm', this.input.get('value')) : this.fireEvent('onConfirm');
		this.checkremove();
	},
	
	cancelRemove: function() {
		if(this.options.enable.onCancel) this.fireEvent('onCancel');
		this.checkremove();
	},
	
	/*
	Method: setText
	Description:  sets the text of the custom box
	[Arguments]
		text :: the new content value. The content you can set depends on the 'content' options
	[/Arguments]
	[Example]  
		> // change the previous text
		> box.setText('Custom Alert/Confirm with some new text');
	[/Example]
	*/
	setText: function(text) {
		this.text = text;
		this.content.set(this.options.content, this.text);
		return this;
	},
	
	/*
	Method: setTitle
	Description:  sets the title of the custom box
	[Arguments]
		title :: the new title value. The content you can set depends on the 'content' options
	[/Arguments]
	[Example]  
		> // change the previous title
		> box.setTitle('A new Custom Alert/Confirm title');
	[/Example]
	*/
	setTitle: function(title) {
		this.title = title;	
		this.head.set(this.options.content, this.title);
		return this;
	},
	
	/*
	Method: setIDs
	Description:  sets the id value respectively for the box, the overlay and the fullpage at once
	[Arguments]
		box :: the new box id
		overlay :: the new overlay id
		fullpage :: the new fullpage id
	[/Arguments]
	[Example]  
		> box.setIDs('myNewBoxID', 'myNewOverlayID', 'myNewFullPageID');
	[/Example]
	*/
	setIDs: function(box, overlay, fullpage) {
		this.box.set('id', box);
		this.overlay.set('id', overlay);
		this.fullpage.set('id', fullpage);
	}
});

/*
	Filename: custom_windows.js
	
	[Description] 
		Contains three extensions for the Custom Class: Custom.Alert, Custom.Confirm and Custom.Prompt.
		They allow to create powerful, fully-customizable and flexible standard windows without overwriting
		the standard methods.
	[/Description]
	
	Contains: Class Custom.Alert, Class Custom.Confirm, Class Custom.Prompt
	
	Requires: custom_base.js
	
	[Summary]
		Custom.Alert ::: Class for creating customized alert boxes
		Custom.Confirm ::: Class for creating customized confirm boxes
		Custom.Prompt ::: Class for creating customized prompt boxes
	[/Summary]
*/
/*
	Class: Custom.Alert
	
	[Description]  
		Allows to create fully-customized alert, without overwriting the standard window.alert method.
		You can works with all Custom parameters and methods and you can have many different alerts in the
		same page as you want.
	[/Description]
	
	Extends: Custom
	
	Constructor: new Custom.Alert (title, text, options)
	
	[Properties] 
		title - a string represents the title of the alert
		text - a string represents the content text of the alert
		options - optional. an object which permits to customize the alert
	[/Properties]
	
	[Options]
		Custom options : all the Custom Options
	[/Options]
*/
Custom.Alert = new Class({
						   
	Extends: Custom,
						   
	options: {
		enable: {
			closeButton: true,
			confirmButton: true,
			cancelButton: false,
			onConfirm: false,
			onCancel: false
		}
	},
	
	initialize: function(title, text, options) {
		this.parent(title, text, options);
		this.setIDs('customAlertBox', 'customAlertOverlay', 'customAlertFullpage');
	}
});

/*
	Class: Custom.Confirm
	
	[Description]  
		Allows to create fully-customized confirm, without overwriting the standard window.confirm method.
		You can works with all Custom parameters and methods and you can have many different confirms in the
		same page as you want.
	[/Description]
	
	Extends: Custom
	
	Constructor: new Custom.Confirm (title, text, options)
	
	[Properties] 
		title - a string represents the title of the confirm
		text - a string represents the content text of the confirm
		options - optional. an object which permits to customize the confirm
	[/Properties]
	
	[Options]
		Custom options : all the Custom Options
	[/Options]
*/
Custom.Confirm = new Class({
						   
	Extends: Custom,
						   
	options: {
		enable: {
			closeButton: true,
			confirmButton: true,
			cancelButton: true,
			onConfirm: true,
			onCancel: true
		}
	},
	
	initialize: function(title, text, options) {
		this.parent(title, text, options);
		this.setIDs('customConfirmBox', 'customConfirmOverlay', 'customConfirmFullpage');
	}
});

/*
	Class: Custom.Prompt
	
	[Description]  
		Allows to create fully-customized prompt (single or multi), without overwriting the standard window.prompt method.
		You can works with all Custom parameters and methods and you can have many different prompts in the
		same page as you want.
	[/Description]
	
	Extends: Custom
	
	Constructor: new Custom.Prompt (title, text, options)
	
	[Properties] 
		title - a string represents the title of the prompt
		text - a string represents the content text of the prompt
		options - optional. an object which permits to customize the prompt
	[/Properties]
	
	[Options]
		Custom options : all the Custom Options
	[/Options]
*/
Custom.Prompt = new Class({
						   
	Extends: Custom,
						   
	options: {
		enable: {
			closeButton: true,
			confirmButton: true,
			cancelButton: true,
			onConfirm: true,
			onCancel: true,
			textBox: true
		}
	},
	
	initialize: function(title, text, options) {
		this.parent(title, text, options);
		this.setIDs('customPromptBox', 'customPromptOverlay', 'customPromptFullpage');
	}
});

/*
	Filename: effects_base.js
	
	[Description] 
		Contains a collection of methods and utilities to work with effects based on Fx Classes.
	[/Description]
	
	[Credits]
		[li] some Fx Classes of the moo.rd Fx Repository are slightly inspired on those found in the Script.aculo.us library
	[/Credits]
	
	Contains: Class Fx, Class Element, Function fxToHash
	
	Requires: string.js
	
	[Summary]
		Fx ::: Extends the Fx Class for creating the moo.rd Effects Repository and fully-customizable effects
		Element ::: Adds Fx utility methods to the Element prototypes
		fxToHash --- Extends the Element.Properties Hash for using all the Fx effects as Element's dynamic shortcuts
	[/Summary]
*/
/*
	Class: Fx
	
	Description: Extends the Fx Class for creating the moo.rd Effects Repository and fully-customizable effects. 
	
	Extends: Class Fx
	
	[Methods]
		initStyles -- initializes all the styles you want for later usages
		removeAuto -- removes the 'auto' value from all the styles you want, to obtain a cross-browser feeling
		setPosition -- sets position's value to 'relative' if the element isn't positioned
	[/Methods]
*/
Fx.implement({
	
	/*
	Method: initStyles
	Description:  initializes all the styles you want for later usages
	*/
	initStyles: function() {
		this.init = {};
		$A(arguments).each(function(a) {
			if(a == 'opacity') this.init['opacity'] = this.element.get('opacity');
			else (this.element.getStyle(a).test('px')) ? this.init[a] = this.element.getStyle(a).toInt() : this.init[a] = this.element.getStyle(a);
		}, this);
		return this;
	},
	
	/*
	Method: removeAuto
	Description:  removes the 'auto' value from all the styles you want, to obtain a cross-browser feeling
	*/
	removeAuto: function() {
		if(!this.init) this.init = {};
		$A(arguments).each(function(a) {
			if(this.element.getStyle(a) == 'auto') { 
				this.element.setStyle(a, '0px');
				this.init[a] = 0;
			}
		}, this);
		return this;
	},
	
	/*
	Method: setPosition
	Description:  sets position's value to 'relative' if the element isn't positioned
	*/
	setPosition: function() {
		if(this.element.getStyle('position') == 'static') this.element.setStyle('position', 'relative');	
		return this;
	}
});

/*
	Class: Element
	
	[Description] 
		Adds Fx utility methods to the Element prototypes
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		fx -- returns a determinate Fx instance you can pick out from the moo.rd Effects Repository
		effect -- sets a determinate Fx instance and start the effect immediately. Returns the element instead of fx method which returns an instance
		removeAuto -- removes the 'auto' value from all the styles you want of this element
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: fx
	Description:  returns a determinate Fx instance you can pick out from the moo.rd Effects Repository
	[Arguments]
		eff :: the fx effect
		options :: optional. the effect options. Either if you use this argument or not, the instance will be the same
	[/Arguments]
	[Example]  
		> // use Fx.Fade
		> var fade = element.fx('fade');
		> fade.start('toggle');
		>  
		> // use Fx.Move
		> var move = element.fx('move', {duration:2000});
		> move.start(120, 58);
	[/Example]
	*/
	fx: function(eff, options) {
		if(!this.retrieve(eff)) this.store(eff, new Fx[eff.upperFirst()](this, options));
		return this.retrieve(eff);
	},
	
	/*
	Method: effect
	Description:  sets a determinate Fx instance and start the effect immediately. Returns the element instead of fx method which returns an instance
	[Arguments]
		eff :: the fx effect
		arguments :: the arguments to apply to the start method
	[/Arguments]
	[Example]  
		> // call an effect immediately
		> el.effect('fade');
		>
		> // set the instance options first
		> el.set('fade', {duration: 2000});
		> // call the effect later
		> el.effect('fade');
		> el.effect('fade', 'toggle');
		>
		> // move an element immediately
		> el.effect('move', 40, 440);
	[/Example]
	*/
	effect: function(fx) {
		this.get(fx).start.pass(Array.slice(arguments, 1), this.get(fx))();
		return this;
	},
	
	/*
	Method: removeAuto
	Description:  removes the 'auto' value from all the styles you want of this element.
	*/
	removeAuto: function() {
		$A(arguments).each(function(a) {
			if(this.element.getStyle(a) == 'auto') this.element.setStyle(a, '0px');
		}, this);
		return this;
	}
});

/*
	Function: fxToHash
	Description: Extends the Element.Properties Hash for using all the Fx effects as Element's dynamic shortcuts
	[Example]  
		> var el = $('element');
		>
		> // sets a Fx.Pulsate instance for later usage
		> el.set('pulsate', {times: 24});
		> // pulsate an element 24 times
		> el.effect('pulsate');
		>
		> // sets a Fx.SwitchOff instance an use it immediately
		> el.get('switchOff', {duration: 2000}).start();
	[/Example]
*/
var fxToHash = function(hash, effects) {
	Array.each(effects, function(fx, i) {
		var fx = fx.toString();
		var props = {
			set: function(options) {
				var tween = this.retrieve(fx);
				if (tween) tween.cancel();
				return this.eliminate(fx).store(fx + ':options', options);
			},
			
			get: function(options){
				if (options || !this.retrieve(fx)){
					if (options || !this.retrieve(fx + ':options')) this.set(fx, options);
					this.store(fx, new Fx[fx.upperFirst()](this, this.retrieve(fx + ':options')));
				}
				return this.retrieve(fx);
			}
		};
		hash.set(fx, props);
	});
};

/*
	Filename: effects_morph.js
	
	[Description] 
		Contains a collection of effects based on morph transitions, which alter the element's styles.
	[/Description]
	
	Contains: Class Fx.Fold, Class Fx.Shrink, Class Fx.Grow, Class Fx.Scale, Class Element
	
	Requires: effects_base.js
	
	[Summary]
		Fx.Fold ::: Closes an element like a folder
		Fx.Shrink ::: Shrinks the styles of an element
		Fx.Grow ::: Enlarges the styles of an element
		Fx.Scale ::: Alters the styles you want of an element following a given scale
		Element ::: Extends the Element Class with Fx shortcuts
		Element.Properties ::: Extends the Element.Properties Hash with effects_morph.js Fx effects
	[/Summary]
*/
/*
	Class: Fx.Fold
	
	[Description] 
		Closes an element like a folder
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Fold (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options plus 'mode'
	[/Properties]
	
	[Options]
		mode : the effect mode. Can be 'vertical' (height transition, default) or 'horizontal' (width transition)
	[/Options]
	
	[Methods]
		start -- starts the Fx.Fold effect
	[/Methods]

	Method: start
	Description:  starts the Fx.Fold effect
	[Arguments]
		mode :: optional. the effect mode
	[/Arguments]
	[Example]  
		> var fx = new Fx.Fold('box');
		> fx.start();
	[/Example]
*/
Fx.Fold = new Class({
					
	Extends: Fx.Morph,
	
	options: {
		mode: 'vertical'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.element.setStyle('overflow', 'hidden');
	},
	
	start: function(mode) {
		var mode = mode || this.options.mode;
		switch(mode) {
			case 'vertical':  var styles = { first: {'height':0}, last: {'width': 0}};
					   break;
			case 'horizontal':  var styles = { first: {'width':0}, last: {'height': 0}};
					   break;
		};
		
		var superMethod = arguments.callee;
		this.parent(styles.first).chain(
			function() { this.parentOf(superMethod, styles.last); }
		);
	}		
});

/*
	Class: Fx.Shrink
	
	[Description] 
		Shrinks the styles of an element
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Shrink (element, options)
	
	[Properties] 
		element - the element
		options - the Fx options
	[/Properties]
	
	[Methods]
		start -- starts the Fx.Shrink effect
	[/Methods]

	Method: start
	Description:  starts the Fx.Shrink effect
	[Example]  
		> var fx = new Fx.Shrink('box');
		> fx.start();
	[/Example]
*/
Fx.Shrink = new Class({
					  
	Extends: Fx.Morph,
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.initStyles('fontSize');
		this.element.setStyles({overflow: 'hidden'});
	},
	
	start: function() {
		this.parent({
			'height': 0,
			'width': 0,
			'font-size': [this.init.fontSize, 0]
		});
	}		
});

/*
	Class: Fx.Grow
	
	[Description] 
		Enlarges the styles of an element
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Grow (element, options, values)
	
	[Properties] 
		element - the element
		options - the Fx options
		values - an object with 'height', 'width' and 'fontsize' keys as final values
	[/Properties]
	
	[Methods]
		start -- starts the Fx.Grow effect
	[/Methods]

	Method: start
	Description:  starts the Fx.Grow effect
	[Arguments]
		values :: optional. the same as the values option. You can use the properties you want, with no obligation to use all of them
	[/Arguments]
	[Example]  
		> var fx = new Fx.Grow('box');
		> fx.start();
	[/Example]
*/
Fx.Grow = new Class({
					
	Extends: Fx.Morph,
	
	initialize: function(element, options, values) {
		this.parent(element, options);
		this.values = values || {height: 200, width: 200, fontsize: 10};
		this.element.setStyle('overflow', 'hidden');
	},
	
	start: function(values) {
		var values = values || this.values;
		this.parent({
			'height': [0, values.height || this.values.height],
			'width': [0, values.width || this.values.width],
			'font-size': [0, values.fontsize || this.values.fontsize]
		});
	}	
});

/*
	Class: Fx.Scale
	
	[Description] 
		Alters the styles you want of an element following a given scale
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Scale (element, options)
	
	[Properties] 
		element - the element
		options - the Fx options plus 'scale'
	[/Properties]
	
	[Options]
		scale : the scale. Default is 1.3
	[/Options]
	
	[Methods]
		start -- starts the Fx.Scale effect
	[/Methods]

	Method: start
	Description:  starts the Fx.Scale effect
	[Arguments]
		properties :: an array which represents the properties to apply the scale to
		scale :: optional. The scale value
	[/Arguments]
	[Example]  
		> var fx = new Fx.Scale('box');
		> fx.start(['width', 'height'], 1.4);
	[/Example]
*/
Fx.Scale = new Class({
					
	Extends: Fx.Morph,
	
	options: {
		scale: 1.3
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.element.setStyle('overflow', 'hidden');
	},
	
	start: function(properties, scale) {
		var scale = scale || this.options.scale;
		if($type(properties)=='array') {
			var obj = {};
			properties.each(function(p, i) {
				obj[p] = [this.element.getStyle(p).toInt(), this.element.getStyle(p).toInt()*scale];
			}, this);
			this.parent(obj);
		}
	}	
});

/*
	Class: Element
	
	[Description] 
		Extends the Element Class with Fx shortcuts. 
		All these methods accept the same arguments of the relative Fx effect (obviously without the element)
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		fold -- returns an Fx.Fold instance
		shrink -- returns an Fx.Shrink instance
		grow -- returns an Fx.Grow instance
		scale -- returns an Fx.Scale instance
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: fold
	Description:  returns an Fx.Fold instance
	*/
	fold: function(options) {
		return new Fx.Fold(this, options);	
	},
	
	/*
	Method: shrink
	Description:  returns an Fx.Shrink instance
	*/
	shrink: function(options) {
		return new Fx.Shrink(this, options);	
	},
	
	/*
	Method: grow
	Description:  returns an Fx.Grow instance
	*/
	grow: function(options, values) {
		return new Fx.Grow(this, options, values);	
	},
	
	/*
	Method: scale
	Description:  returns an Fx.Scale instance
	*/
	scale: function(options) {
		return new Fx.Scale(this, options);	
	}
});

/*
	Hash: Element.Properties
	Description: Extends the Element.Properties Hash for using the effects_morph.js Fx Classes as Element's dynamic shortcuts with the Element.effect method
*/
fxToHash(Element.Properties, ['fold', 'shrink', 'grow', 'scale']);

/*
	Filename: effects_fade.js
	
	[Description] 
		Contains a collection of effects based on fade transitions, for all fade needs.
	[/Description]
	
	Contains: Class Fx.Bubble, Class Fx.Fade, Class Fx.DropOut, Class Fx.Squish, Class Fx.Puff, Class Element
	
	Requires: effects_base.js
	
	[Summary]
		Fx.Bubble ::: Smoothly fades and close an element horizontally or vertically
		Fx.Fade ::: Smoothly fades the element in, out or toggle. Provides a similar functionality to Element.fade but as Class
		Fx.DropOut ::: Smoothly drops an element out, either down or up
		Fx.Squish ::: Smoothly resizes an element with a 'squish' transition
		Fx.Puff ::: Smoothly fades an element with a 'puff' transition
		Element ::: Extends the Element Class with Fx shortcuts
		Element.Properties ::: Extends the Element.Properties Hash with effects_fade.js Fx effects
	[/Summary]
*/
/*
	Class: Fx.Bubble
	
	[Description] 
		Smoothly fades and close an element horizontally or vertically
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Bubble (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options plus 'mode'
	[/Properties]
	
	[Options]
		mode : the effect mode. Can be 'vertical' (height transition, default) or 'horizontal' (width transition)
	[/Options]
	
	[Methods]
		start -- starts the Fx.Bubble effect
	[/Methods]

	Method: start
	Description:  starts the Fx.Bubble effect
	[Arguments]
		mode :: optional. the effect mode
	[/Arguments]
	[Example]  
		> var fx = new Fx.Bubble('box');
		> fx.start();
	[/Example]
*/
Fx.Bubble = new Class({
					   
	Extends: Fx.Morph,
	
	options: {
		mode: 'vertical',
		duration: 3000
	},
					   
	initialize: function(element, options) {
		this.parent(element, $merge(this.options, options));
		this.element.setStyle('overflow', 'hidden');
	},
	
	start: function(mode) {
		var mode = mode || this.options.mode;
		var styles = {'font-size': 0, 'opacity': 0};
		switch(mode) {
			case 'vertical':
				this.parent($merge({'height': 0}, styles));
				break;
			case 'horizontal':
				this.parent($merge({'width': 0}, styles));
				break;
		}
	}
});

/*
	Class: Fx.Fade
	
	[Description] 
		Smoothly fades the element in, out or toggle. Provides a similar functionality of Element.fade but as Class
	[/Description]
	
	Extends: Fx.Tween
	
	Constructor: new Fx.Fade (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options
	[/Properties]
	
	[Methods]
		start -- starts the Fx.Fade effect
	[/Methods]

	Method: start
	Description:  starts the Fx.Fade effect
	[Arguments]
		where :: a string which can be 'in', 'out' or 'toggle' (default)
	[/Arguments]
	[Example]  
		> var fx = new Fx.Fade('box');
		> // fade in
		> fx.start('in');
		> // fade out
		> fx.start('out');
		> // fade toggle
		> fx.start('toggle');
	[/Example]
*/
Fx.Fade = new Class({
					
	Extends: Fx.Tween,
	
	initialize: function(element, options) {
		this.parent(element, options);
	},
	
	start: function(where) {
		switch(where) {
			case 'in': this.parent('opacity', 1); 
					   break;
			case 'out': this.parent('opacity', 0); 
					   break;
			case 'toggle': 
			default: this.parent('opacity', (this.element.get('opacity') == 0) ? 1 : 0); 
					   break;
		}
	}
});

/*
	Class: Fx.DropOut
	
	[Description] 
		Smoothly drops an element out, either down or up
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.DropOut (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options plus some others
	[/Properties]
	
	[Options]
		size : how far the element will be dropped. Default is 40
		where : the direction of the effect. Can be 'down' (default) or 'up'
	[/Options]
	
	[Methods]
		start -- starts the Fx.DropOut effect
	[/Methods]

	Method: start
	Description:  starts the Fx.DropOut effect
	[Arguments]
		where :: optional. Identical to the where option
	[/Arguments]
	[Example]  
		>  var fx = new Fx.DropOut('box', {where:'up', size:140});
		>  fx.start();
	[/Example]
*/
Fx.DropOut = new Class({
					   
	Extends: Fx.Morph,
	
	options: {
		size: 40,
		where: 'down'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.setPosition().initStyles('top').removeAuto('top');
	},
	
	start: function(where) {
		var where = where || this.options.where;
		switch(where) {
			case 'down':
				var fullTop = this.init.top + this.options.size;
				break;
			case 'up':
				var fullTop = this.init.top - this.options.size;
				break;
		}
		this.parent({
			'top': fullTop,
			'opacity': 0
		});
	}
});

/*
	Class: Fx.Squish
	
	[Description] 
		Smoothly resizes an element with a 'squish' transition
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Squish (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options
	[/Properties]
	
	[Methods]
		start -- starts the Fx.Squish effect
	[/Methods]

	Method: start
	Description:  starts the Fx.Squish effect
	[Example]  
		>  var fx = new Fx.Squish('box', {duration:2000});
		>  fx.start();
	[/Example]
*/
Fx.Squish = new Class({
					  
	Extends: Fx.Morph,
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.initStyles('fontSize').setPosition();
		this.element.setStyles({overflow: 'hidden'});
	},
	
	start: function() {
		this.parent({
			'height': 0,
			'width': 0,
			'opacity': 0,
			'font-size': [this.init.fontSize, 0]
		});
	}		
});

/*
	Class: Fx.Puff
	
	[Description] 
		Smoothly fades an element with a 'puff' transition
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Puff (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options plus 'increase'
	[/Properties]
	
	[Options]
		increase : The amount for increasing css properties. Default is 1.3
	[/Options]
	
	[Methods]
		start -- starts the Fx.Puff effect
	[/Methods]

	Method: start
	Description:  starts the Fx.Puff effect
	[Arguments]
		increase :: optional. The amount for increasing css properties
	[/Arguments]
	[Example]  
		>  var fx = new Fx.Puff('box', {increase: 1.6});
		>  fx.start();
	[/Example]
*/
Fx.Puff = new Class({
					
	Extends: Fx.Morph,
	
	options: {
		increase: 1.3
	},
					
	initialize: function(element, options) {
		this.parent(element, options);
		this.initStyles('height', 'width', 'fontSize').setPosition();
		this.element.setStyles({overflow: 'hidden'});
	},
	
	start: function(increase) {
		var increase = increase || this.options.increase;
		this.parent({
			'height': [this.init.height*increase],
			'width': [this.init.width*increase],
			'font-size': [this.init.fontSize*increase],
			'opacity': 0
		}).chain(function() { this.element.setStyle('display', 'none'); });
	}			
});

/*
	Class: Element
	
	[Description] 
		Extends the Element Class with Fx shortcuts. 
		All these methods accept the same arguments of the relative Fx effect (obviously without the element)
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		bubble -- returns an Fx.Bubble instance
		fading -- returns an Fx.Fade instance
		dropOut -- returns an Fx.DropOut instance
		squish -- returns an Fx.Squish instance
		puff -- return an Fx.Puff instance
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: bubble
	Description:  returns an Fx.Bubble instance
	*/
	bubble: function(options) {
		return new Fx.Bubble(this, options);	
	},
	
	/*
	Method: fading
	Description:  returns an Fx.Fade instance (note that this method is called 'fading' and doesn't overwrite the 'fade' method)
	*/
	fading: function(options) {
		return new Fx.Fade(this, options);	
	},
	
	/*
	Method: dropOut
	Description:  returns an Fx.DropOut instance
	*/
	dropOut: function(options) {
		return new Fx.DropOut(this, options);	
	},
	
	/*
	Method: squish
	Description:  returns an Fx.Squish instance
	*/
	squish: function(options) {
		return new Fx.Squish(this, options);	
	},
	
	/*
	Method: puff
	Description:  returns an Fx.Puff instance
	*/
	puff: function(options) {
		return new Fx.Puff(this, options);	
	}
});

/*
	Hash: Element.Properties
	Description: Extends the Element.Properties Hash for using the effects_fade.js Fx Classes as Element's dynamic shortcuts with the Element.effect method
*/
fxToHash(Element.Properties, ['bubble', 'fading', 'dropOut', 'squish', 'puff']);

/*
	Filename: effects_move.js
	
	[Description] 
		Contains a collection of effects based on the elements movement.
	[/Description]
	
	Contains: Class Fx.Shake, Class Fx.Move, Class Fx.Rumble, Class Fx.ScrollOut, Class Element
	
	Requires: effects_base.js
	
	[Summary]
		Fx.Shake ::: Shakes the element for a determinate number of times horizontally or vertically
		Fx.Move ::: Moves the element wherever you want
		Fx.Rumble ::: Enables a particular drag mode on the element
		Fx.ScrollOut ::: Scrolls an element out of his viewport
		Element ::: Extends the Element Class with Fx shortcuts
		Element.Properties ::: Extends the Element.Properties Hash with effects_move.js Fx effects
	[/Summary]
*/
/*
	Class: Fx.Shake
	
	[Description] 
		Shakes the element for a determinate number of times horizontally or vertically
	[/Description]
	
	Extends: Fx.Tween
	
	Constructor: new Fx.Shake (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options plus the following
	[/Properties]
	
	[Options]
		mode : the effect mode. Can be 'vertical' (height/top transition, default) or 'horizontal' (width/left transition)
		size : how far the element will be shaken in each direction. Default is 10
		times : how many tmes the element will be shaken. Default is 14  
	[/Options]
	
	[Methods]
		start -- starts the Fx.Shake effect
	[/Methods]

	Method: start
	Description: starts the Fx.Shake effect
	[Arguments]
		mode :: optional. the effect mode
	[/Arguments]
	[Example]  
		> var fx = new Fx.Shake('box');
		> fx.start();
	[/Example]
*/
Fx.Shake = new Class({
					 
	Extends: Fx.Tween,
	
	options: {
		mode: 'vertical',
		size: 10,
		link: 'chain',
		times: 14
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		switch(this.options.mode) {
			case 'horizontal': this.prop = 'left';
					  break;
			case 'vertical': this.prop = 'top';
					  break;
		};
		this.setPosition();
		this.element.setStyles({'overflow': 'hidden'});
		this.initStyles('top', 'left').removeAuto('top', 'left');
	},
	
	start: function(mode) {
		if(!mode) (this.options.mode == 'horizontal') ? this.prop = 'left' : this.prop = 'top';
		if(mode == 'vertical') this.prop = 'top';
		if(mode == 'horizontal') this.prop = 'left';
		for(var i=0; i<this.options.times; i++) {
			this.parent(this.prop, (i%2 == 0) ? this.options.size : -this.options.size);
		}
		this.parent(this.prop, 0);
	}
});

/*
	Class: Fx.Move
	
	[Description] 
		Moves the element wherever you want
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Move (element, options)
	
	[Properties] 
		options - the Fx Options
	[/Properties]
	
	[Methods]
		start -- starts the Fx.Move effect
	[/Methods]

	Method: start
	Description: starts the Fx.Move effect
	[Arguments]
		top :: the value of the top direction
		left :: the value of the left direction
	[/Arguments]
	[Example]  
		> var fx = new Fx.Move('box');
		> fx.start(20, 400);
	[/Example]
*/
Fx.Move = new Class({
					
	Extends: Fx.Morph,				
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.setPosition().initStyles('top', 'left').removeAuto('top', 'left');
	},
	
	start: function(top, left) {
		if(!this.check(arguments.callee, top, left)) return this;
		return this.parent({
			'top': top,
			'left': left
		});
	}
});

/*
	Class: Fx.Rumble
	
	[Description] 
		Enables a particular drag mode on the element. When it will be released, an elastic transition will be fired
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Rumble (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options
	[/Properties]
	
	[Methods]
		start -- starts the Fx.Rumble effect
	[/Methods]

	Method: start
	Description: starts the Fx.Rumble effect
	[Example]  
		>  var fx = new Fx.Rumble('box');
		>  fx.start();
	[/Example]
	
	Method: detach
	Description: detaches the drag instance
	[Example]  
		>  fx.detach();
	[/Example]
*/
Fx.Rumble = new Class({
					  
	Extends: Fx.Morph,
	
	options: {
		duration: 800,
		transition: 'elastic:out'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.setPosition();
		this.initStyles('top', 'left', 'cursor').removeAuto('top', 'left');
		this.obj = {'top': this.init.top, 
					'left': this.init.left
		};
	},

	start: function() {
		this.element.setStyle('cursor', 'move');
		var top = this.init.top; var left = this.init.left;
		var superMethod = arguments.callee;
		
		(!this.drag) ?
		this.drag = new Drag.Move(this.element, {
				onComplete: function() { 
					this.parentOf(superMethod, this.obj); 
				}.bind(this)
		}) : this.drag.attach();	
	},
	
	detach: function() {
		if(this.drag) this.drag.detach();	
		this.element.setStyle('cursor', this.init.cursor);
	}	
});

/*
	Class: Fx.ScollOut
	
	[Description] 
		Scrolls an element out of his viewport
	[/Description]
	
	Extends: Fx.Tween
	
	Constructor: new Fx.ScrollOut (element, options)
	
	[Properties] 
		options - the Fx Options
	[/Properties]
	
	[Methods]
		start -- starts the Fx.ScrollOut effect
	[/Methods]

	Method: start
	Description: starts the Fx.ScrollOut effect
	[Arguments]
		where :: The direction. Can be 'up' (default), 'down', 'left' or 'right'. If you pass 'reset' the position will be resetted
	[/Arguments]
	[Example]  
		> var fx = new Fx.ScrollOut('box');
		> // scroll up
		> fx.start('up');
		> // scroll left
		> fx.start('left');
	[/Example]
*/
Fx.ScrollOut = new Class({
					
	Extends: Fx.Tween,		
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.setPosition();
		this.initStyles('top', 'left').removeAuto('top', 'left');
		this.wrapper = new Element('div', {
		'styles': {'overflow': 'hidden', 'width': this.element.getWidth(), 'position': 'relative'}}).wraps(this.element);
	},
	
	start: function(where) {
		if (!this.check(arguments.callee, where)) return this;
		if(where == 'up' || !where) return this.parent('top', -this.element.getHeight());
		if(where == 'down') return this.parent('top', this.element.getHeight());
		if(where == 'left') return this.parent('left', -this.element.getWidth());
		if(where == 'right') return this.parent('left', this.element.getWidth());
		if(where == 'reset') {
			if(this.element.getStyle('top').toInt() != this.init.top) return this.parent('top', this.init.top);
			if(this.element.getStyle('left').toInt() != this.init.left) return this.parent('left', this.init.left);	
		}
	}
});

/*
	Class: Element
	
	[Description] 
		Extends the Element Class with Fx shortcuts. 
		All these methods accept the same arguments of the relative Fx effect (obviously without the element)
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		shake -- returns an Fx.Shake instance
		move -- returns an Fx.Move instance
		rumble -- returns an Fx.Rumble instance
		scrollOut -- returns an Fx.ScrollOut instance
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: shake
	Description:  returns an Fx.Shake instance
	*/
	shake: function(options) {
		return new Fx.Shake(this, options);	
	},
	
	/*
	Method: move
	Description:  returns an Fx.Move instance
	*/
	move: function(options) {
		return new Fx.Move(this, options);	
	},
	
	/*
	Method: rumble
	Description:  returns an Fx.Rumble instance
	*/
	rumble: function(options) {
		return new Fx.Rumble(this, options);	
	},
	
	/*
	Method: scrollOut
	Description:  returns an Fx.ScrollOut instance
	*/
	scrollOut: function(options) {
		return new Fx.ScrollOut(this, options);	
	}
});

/*
	Hash: Element.Properties
	Description: Extends the Element.Properties Hash for using the effects_move.js Fx Classes as Element's dynamic shortcuts with the Element.effect method
*/
fxToHash(Element.Properties, ['shake', 'move', 'rumble', 'scrollOut']);

/*
	Filename: effects_extra.js
	
	[Description] 
		Contains a collection of miscellanous effects.
	[/Description]
	
	Contains: Class Fx.Pulsate, Class Fx.SwitchOff, Class Fx.Gradient, Class Element
	
	Requires: effects_base.js
	
	[Summary]
		Fx.Pulsate ::: Pulsates the element for a determinate number of times
		Fx.SwitchOff ::: Switch an element off vertically or horizontally
		Fx.Gradient ::: Transition the background-color or the color of an element how many times you want
		Element ::: Extends the Element Class with Fx shortcuts
		Element.Properties ::: Extends the Element.Properties Hash with effects_extra.js Fx effects
	[/Summary]
*/
/*
	Class: Fx.Pulsate
	
	[Description] 
		Pulsates the element for a determinate number of times
	[/Description]
	
	Extends: Fx.Tween
	
	Constructor: new Fx.Pulsate (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options plus the following
	[/Properties]
	
	[Options]
		times : how many tmes the element will be pulsated. Default is 14  
	[/Options]
	
	[Methods]
		start -- starts the Fx.Pulsate effect
	[/Methods]

	Method: start
	Description: starts the Fx.Pulsate effect
	[Arguments]
		last :: optional. the last value of the opacity. Default is 1.
	[/Arguments]
	[Example]  
		> var fx = new Fx.Pulsate('box');
		> fx.start();
	[/Example]
*/
Fx.Pulsate = new Class({
					 
	Extends: Fx.Tween,
	
	options: {
		duration: 200,
		link: 'chain',
		times: 14
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
	},
	
	start: function(last) {
		var last = ($type(last) == 'number') ? last : 1;
		for(var i=0; i<this.options.times; i++) {
			this.parent('opacity', (i%2 == 0) ? 0 : 1);
		}
		this.parent('opacity', last);
	}
});

/*
	Class: Fx.SwitchOff
	
	[Description] 
		Switch an element off vertically or horizontally
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.SwitchOff (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options plus the following
	[/Properties]
	
	[Options]
		mode : the effect mode. Can be 'vertical' (height transition, default) or 'horizontal' (width transition)
		switchDuration : the duration of the switch. Default is 100
	[/Options]
	
	[Methods]
		start -- starts the Fx.SwitchOff effect
	[/Methods]

	Method: start
	Description:  starts the Fx.SwitchOff effect
	[Arguments]
		mode :: optional. the effect mode
	[/Arguments]
	[Example]  
		> var fx = new Fx.SwitchOff('box');
		> fx.start();
	[/Example]
*/
Fx.SwitchOff = new Class({
					
	Extends: Fx.Morph,
	
	options: {
		mode: 'vertical',
		switchDuration: 100
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.element.setStyle('overflow', 'hidden');
	},
	
	start: function(mode) {
		var mode = mode || this.options.mode;
		switch(mode) {
			case 'vertical':  var last = {'height': 0};
					   break;
			case 'horizontal':  var last = {'width': 0};
					   break;
		};
		this.duration = this.options.duration;
		this.options.duration = this.options.switchDuration;
		
		var superMethod = arguments.callee;
		this.parent({'opacity': 0}).chain(
			function() { this.parentOf(superMethod, {'opacity': 1}); },
			function() { this.options.duration = this.duration; this.parentOf(superMethod, last); }
		);
	}		
});

/*
	Class: Fx.Gradient
	
	[Description] 
		Transition the background-color or the color of an element how many times you want
	[/Description]
	
	Extends: Fx.Tween
	
	Constructor: new Fx.Gradient (element, options)
	
	[Properties] 
		element - the element
		options - the Fx Options plus the following
	[/Properties]
	
	[Options]
		end : if true will be added a final transition which set the background-color to its original value
		gradient : the property to alter, can be 'background-color' (default) or 'color'
	[/Options]
	
	[Methods]
		start -- starts the Fx.Gradient effect
	[/Methods]

	Method: start
	Description: starts the Fx.Gradient effect
	[Arguments]
		colors :: an array of colors
		gradient :: optional. The property to alter, can be 'background-color' or 'color'
	[/Arguments]
	[Example]  
		> var fx = new Fx.Gradient('box');
		> // two transitions
		> fx.start(['#56617D', '#78ba91']);
		> // six transitions
		> fx.start(['#56617D', '#78ba91', '#8eaeaf', '#9a6f1b', '#a87aad', '#eeaba8']);
	[/Example]
*/
Fx.Gradient = new Class({
					 
	Extends: Fx.Tween,
	
	options: {
		duration: 1000,
		link: 'chain',
		end: true,
		gradient: 'background-color'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.initStyles('backgroundColor', 'color');
	},
	
	start: function(colors, gradient) {
		if(!gradient) var gradient = this.options.gradient;
		else if(gradient != 'background-color' && gradient != 'color') var gradient = 'background-color';
		var superMethod = arguments.callee;
		var length = colors.length-1;
		colors.each(function(color, i) {
			this.parentOf(superMethod, [gradient, color]);
			if(i == length && this.options.end)
				this.parentOf(superMethod, [gradient, (gradient == 'background-color') ? this.init.backgroundColor : this.init.color]);
		}, this);
	}
});

/*
	Class: Element
	
	[Description] 
		Extends the Element Class with Fx shortcuts. 
		All these methods accept the same arguments of the relative Fx effect (obviously without the element)
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		pulsate -- returns an Fx.Pulsate instance
		switchOff -- returns an Fx.SwitchOff instance
		gradient -- returns an Fx.Gradient instance
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: pulsate
	Description:  returns an Fx.Pulsate instance
	*/
	pulsate: function(options) {
		return new Fx.Pulsate(this, options);	
	},
	
	/*
	Method: switchOff
	Description:  returns an Fx.SwitchOff instance
	*/
	switchOff: function(options) {
		return new Fx.SwitchOff(this, options);	
	},
	
	/*
	Method: gradient
	Description:  returns an Fx.Gradient instance
	*/
	gradient: function(options) {
		return new Fx.Gradient(this, options);	
	}
});

/*
	Hash: Element.Properties
	Description: Extends the Element.Properties Hash for using the effects_extra.js Fx Classes as Element's dynamic shortcuts with the Element.effect method
*/
fxToHash(Element.Properties, ['pulsate', 'switchOff', 'gradient']);

/*
	Filename: effects_toggle.js
	
	[Description]
		Contains the Fx.Toggle Class and the Element toggle method
	[/Description]
	
	Contains: Class Fx.Toggle, Class Element
	
	Requires: constructors.js, type.js, effects_base.js
	
	[Summary]
		Fx.Toggle ::: allows you to toggle everything
		Element ::: contains the Element.toggle method
	[/Summary]
*/
/*
	Class: Fx.Toggle
	
	[Description]
		Allows to toggle all the properties you want, either integers or strings.
	[/Description]
	
	Extends: Fx.Tween
	
	Constructor: new Fx.Toggle (element, options)
	
	[Properties] 
		element - the $(element) to apply the toggle to
		options - optional. the Fx options
	[/Properties]
	
	[Methods]
		toggleHeight -- toggles the height property
		toggleWidth -- toggles the width property
		toggleOpacity -- toggles the opacity property
		toggleProperty -- toggles a specified CSS property, string or integer, from one value to another
		toggle -- shortcut to toggle some togglables properties
	[/Methods]
*/

Fx.Toggle = new Class({
					  
	Extends: Fx.Tween,
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.initStyles('height', 'width', 'opacity');
		this.element.setStyle('overflow', 'hidden');
	},
	
	/*
	Method: toggleHeight
	Description: toggles the height property
	[Example]  
		> var fx = new Fx.Toggle('element'); 
		> fx.toggleHeight();
	[/Example]
	*/
	toggleHeight: function() {
		(this.element.getStyle('height').toInt() > 0) ? this.start('height', 0) : this.start('height', this.init.height);
		return this;
	},
	
	/*
	Method: toggleWidth
	Description: toggles the width property
	[Example]  
		> var fx = new Fx.Toggle('element'); 
		> fx.toggleWidth();
	[/Example]
	*/
	toggleWidth: function() {
		(this.element.getStyle('width').toInt() > 0) ? this.start('width', 0) : this.start('width', this.init.width);
		return this;
	},
	
	/*
	Method: toggleOpacity
	Description: toggles the opacity property
	[Example]  
		> var fx = new Fx.Toggle('element'); 
		> fx.toggleOpacity();
	[/Example]
	*/
	toggleOpacity: function() {
		(this.element.getStyle('opacity').toInt() > 0) ? this.start('opacity', 0) : this.start('opacity', this.init.opacity);
		return this;
	},
	
	/*
	Method: toggleDisplay
	Description: toggles the display property
	[Example]  
		> var fx = new Fx.Toggle('element'); 
		> fx.toggleDisplay();
	[/Example]
	*/
	toggleDisplay: function() {
		this.toggleProperty('display', 'none', 'block');
		return this;
	},
	
	/*
	Method: toggleVisibility
	Description: toggles the visibility property
	[Example]  
		> var fx = new Fx.Toggle('element'); 
		> fx.toggleVisibility();
	[/Example]
	*/
	toggleVisibility: function() {
		this.toggleProperty('visibility', 'hidden', 'visible');
		return this;
	},
	
	/*
	Method: toggleProperty
	Description: toggles a specified CSS property, string or integer, from one value to another
	[Arguments]
		property :: the property to toggle
		from :: the start value of the property. It can be different from it real start value
		to :: the final value of the property
		fx :: optional. if true the property changes with a transition
	[/Arguments]
	[Example]  
		> var fx = new Fx.Toggle('element'); 
		> fx.toggleProperty('color', 'blue', 'green');
		> fx.toggleProperty('color', 'blue', 'green', true);
	[/Example]
	*/
	toggleProperty: function(property, from, to, fx) {
		if($string(from) && $string(to)) {
			if(!fx)
				(this.element.getStyle(property) == from.toLowerCase()) ? this.element.setStyle(property, to) : this.element.setStyle(property, from);
			else
				(this.element.getStyle(property) == from.toLowerCase()) ? this.start(property, to) : this.start(property, from);
		}
		else if($int(from) && $int(to)) {
			if(!fx)
				(this.element.getStyle(property).toInt() == from) ? this.set(property, to) : this.set(property, from);
			else
				(this.element.getStyle(property).toInt() == from) ? this.start(property, to) : this.start(property, from);
		}
		return this;
	},
	
	/*
	Method: toggle
	Description: shortcut to toggle some togglables properties
	[Arguments]
		property :: the property to toggle
	[/Arguments]
	[Example]  
		> var fx = new Fx.Toggle('fx');
		>
		> // toggle height
		> fx.toggle('height');
		> // toggle width
		> fx.toggle('width');
		> // toggle opacity
		> fx.toggle('opacity');
		> // toggle display
		> fx.toggle('display');
		> // toggle visibility
		> fx.toggle('visibility');
	[/Example]
	*/
	toggle: function(property) {
		switch(property) {
			case 'height': this.toggleHeight();
						break;
			case 'width': this.toggleWidth();
						break;
			case 'opacity': this.toggleOpacity();
						break;
			case 'display': this.toggleDisplay();
						break;
			case 'visibility': this.toggleVisibility();
						break;
		}
		return this;
	}
});
			
/*
	Class: Element
	
	Description: Contains the Element.toggle method
	
	Extends: Class Element
	
	[Methods]
		toggle -- returns an Fx.Toggle instance
	[/Methods]
*/
Element.extend({
	/*
	Method: toggle
	Description: returns an Fx.Toggle instance
	[Example]  
		> $('element').toggle({duration:2000}).toggleProperty('color', '#6666FF', '#000000', true);
	[/Example]
	*/
	toggle: function(options) {
		return new Fx.Toggle(this, options);
	}
});

/*
	Filename: effects_cycle.js
	
	[Description] 
		Contains the Fx.Cycle Class and the Fx.Cycle extensions for creating powerful cycle effects, based on different 
		style transitions.
	[/Description]
	
	Contains: Class Fx.Cycle and its extensions, Class Element
	
	[Summary]
		Fx.Cycle ::: A wrapper which allows you to create powerful cycle effects
		Element ::: Contains the cycle method which returns a determinate Fx.Cycle instance
	[/Summary]
*/
/*
	Class: Fx.Cycle
	
	[Description]  
		With the Fx.Cycle extensions, you can create the "cycle effect" which means a slideshow based on a particular
		style transition. This file contains 14 Fx.Cycle extensions, like Fx.Cycle.zoom and Fx.Cycle.fade.
		In addiction, you can create your own cycle effect, either customizing an existing one or creating a new one.
		Below you can find all the Fx.Cycle extensions.
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Cycle.cycleType (element, options)
	
	[Properties] 
		element - the wrapper which contains your slides
		options - optional. The Fx options plus those described below
	[/Properties]
	
	[Options]
		animeOut : an object whose properties are the styles to alter when the slide gets out.
		animeIn : an object whose properties are the styles to alter when the slide comes in.
		cssBefore : an object whose properties are the styles to alter immediately before the slide comes in.
		animeInType : indicates the method to use with the animeIn object. It can be 'set' (default) or 'start' 
		overflow : the overflow of the wrapper. Depends on the type of cycle effect.
		steps : the timer used by autostart to change periodically the slides. Default is 2000 ms
		handles : an object which attaches events to elements passed in as values. The keywords represent the Fx.Cycle's methods
		autostart : if true the slides will be changed automatically. Deafult is true
		enable : an object containing some keywords to enable extra features. See below.
	[/Options]
	
	>> enable:
	[List]
		[li] keyboard: if true you can navigate with the keyboard too. In addition to the arrows, you can use the following keys. 'a' for autostart, 's' for stop, 'f' to go to the first slide and 'l' to go to the last slide. 
	[/List]
	
	[Events]
		onAnimeIn : function fired immediately before the element is animed in. The current and the next slide will be passed in
		onAnimeOut : function fired immediately before the element is animed out. The current and the next slide will be passed in
	[/Events]
	
	[Methods]
		next -- switches to the next slide
		prev -- switches to the previous slide
		goTo -- swicthes to the given slide
		toFirst -- switches to the first slide
		toLast -- switches to the last slide
		autostart -- enables the cycle slideshow
		stop -- stops the slideshow either if start method has been called or autostart option has been enabled
		animeIn -- sets the animeIn properties
		animeOut -- sets the animeOut properties
		cssBefore -- sets the cssBefore properties
	[/Methods]
	
	[Note]
		You can use the keywords 'this.height' and 'this.width' into the animeIn, animeOut and cssBefore methods,
		to refer respectively to the images' height and width. Using the keyword 'this.parentHeight' and 'this.parentWidth'
		you can refer to the parent element dimensions.
		In addiction, you can use the keywords 'this.currSlide' and 'this.nextSlide' to refer respectively to the current and
		the next slide.
	[/Note]
	
	Method: next
	Description:  switches to the next slide
	[Example]  
		> fx.next();
	[/Example]
	
	Method: prev
	Description:  switches to the previous slide
	[Example]  
		> fx.prev();
	[/Example]
	
	Method: goTo
	Description:  swicthes to the given slide
	[Arguments]
		num :: the position of the needed slide
	[/Arguments]
	[Example]  
		> fx.goTo(2);
	[/Example]
	
	Method: toFirst
	Description:  switches to the first slide
	[Example]  
		> fx.toFirst();
	[/Example]
	
	Method: toLast
	Description:  switches to the last slide
	[Example]  
		> fx.toLast();
	[/Example]
	
	Method: autostart
	Description:  enables the cycle slideshow
	[Example]  
		> fx.autostart();
	[/Example]
	
	Method: stop
	Description:  stops the slideshow either if start method has been called or autostart option has been enabled
	[Example]  
		> fx.stop();
	[/Example]
	
	Method: animeIn
	Description:  sets the animeIn properties
	[Arguments]
		styles :: an object which contains the animeIn css styles
	[/Arguments]
	[Example]  
		> fx.animeIn({top: 200, left: 200});
	[/Example]
	
	Method: animeOut
	Description:  sets the animeOut properties
	[Arguments]
		styles :: an object which contains the animeOut css styles
	[/Arguments]
	[Example]  
		> fx.animeOut({top: -200, opacity: 0});
	[/Example]
	
	Method: cssBefore
	Description:  sets the cssBefore properties
	[Arguments]
		styles :: an object which contains the cssBefore css styles
	[/Arguments]
	[Example]  
		> fx.cssBefore({left: 200, opacity: 1, height: 0, width: 0});
	[/Example]
*/
Fx.Cycle = new Class({
	
	Extends: Fx.Morph,
	
	options: {
		animeOut: {},
		animeIn: {},
		cssBefore: {},
		//cssAfter: {},
		animeInType: 'set',
		overflow: 'visible',
		autostart: true,
		steps: 2000,
		handles: {
			next: false,
			prev: false,
			toFirst: false,
			toLast: false,
			autostart: false,
			stop: false
		},
		enable: {
			keyboard: false	
		},
		onAnimeIn: $empty,
		onAnimeOut: $empty
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.imgs = this.element.getChildren();
		this.uimgs = this.element.getChildren().reverse();
		this.element.setStyles({'position': 'relative', 'overflow': this.options.overflow});
		this.first = this.element.getFirst();
		
		this.height = this.first.getStyle('height').toInt();
		this.width = this.first.getStyle('width').toInt();
		this.parentHeight = this.element.getStyle('height').toInt();
		this.parentWidth = this.element.getStyle('width').toInt();
		
		this.uimgs.each(function(img, i) {
			img.setStyles({'position': 'absolute', 'top': '0px', 'left': '0px', 'z-index': i});
		}, this);
		this.count = 0;
		this.length = this.imgs.length-1;
		this.fullLength = this.imgs.length;
		if(this.options.autostart) this._autostart = this.next.periodical(this.options.steps, this);
		this.attachHandles();
		if(this.options.enable.keyboard) this.attachKeys.bindWithEvent(this)();
	},
	
	next: function() {
		if(!this.timer) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			(this.count != this.length) ? this.count++ : this.count = 0;
			this.main();
		}
	},
	
	prev: function() {
		if(!this.timer) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			(this.count == 0) ? this.count = this.length : this.count--;
			this.main();
		}
	},
	
	goTo: function(to) {
		if(!this.timer && to != this.count) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.count = to;
			this.main();
		}
	},
	
	toFirst: function() {
		if(!this.timer && this.count != 0) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.count = 0;
			this.main();
		}
	},
	
	toLast: function() {
		if(!this.timer && this.count != this.length) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.count = this.length;
			this.main();
		}
	},
	
	autostart: function() {
		this._autostart = this.next.periodical(this.options.steps, this);
	},
	
	stop: function() {
		this._autostart = $clear(this._autostart);	
	},
	
	checkAutostart: function() {
		if(this._autostart) {
			this._autostart = $clear(this._autostart);
			this._autostart = this.next.periodical(this.options.steps, this);
		}
	},
	
	attachHandles: function() {
		for(var mtd in this.options.handles) {
			var method = mtd.toString();
			if(this.options.handles[mtd] && $function(this[method])) {
				$(this.options.handles[mtd]).addEvent('click', function(event, method) {
					event.preventDefault();	
					this[method]();
				}.bindWithEvent(this, method));	
			}
		}
	},
	
	attachKeys: function(event) {
		$(document).addEvent('keydown', function(event) {
			switch(event.key) {
				case 'left': this.prev();
					break;
				case 'right': this.next();
					break;
				case 'a': this.autostart();
					break;
				case 's': this.stop();
					break;
				case 'f': this.toFirst();
					break;
				case 'l': this.toLast();
					break;
			}
		}.bind(this));
	},
	
	main: function() {
		this.element.setStyle('z-index', this.fullLength);
		this.imgs[this.count].setStyle('z-index', 1);
		
		this.currSlide = this.element;
		this.nextSlide = this.imgs[this.count];
		
		this.fireEvent('onAnimeOut', [this.currSlide, this.nextSlide]);
		this.start(this.options.animeOut).chain(
			function() {
				var type = this.options.animeInType;
				if(type == 'set') this.fireEvent('onAnimeIn', [this.currSlide, this.nextSlide]);
				this.element.setStyle('z-index', 0);
				this.imgs.each(function(img, i) {
					if(i != this.count) img.setStyle('z-index', 0).setStyles(this.options.cssBefore);
				}, this);
				if(type == 'set') this[type](this.options.animeIn); // set instead of start
				if(type == 'start') this[type](this.options.animeIn).chain(function() { this.fireEvent('onAnimeIn', [this.currSlide, this.nextSlide]); });
			}
		);
	}
					 
});

(function() {
var methods = {};

['animeOut', 'animeIn', 'cssBefore'].each(function(method) {
	methods[method] = function(styles) {
		for(var style in styles)
			if($defined(styles[style])) this.options[method][style] = styles[style]; 
	}					
});

Fx.Cycle.implement(methods);
})();

/* 
Class: Fx.Cycle.shuffle 
*/
Fx.Cycle.shuffle = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeInType: 'start',
		animeIn: {
			top: 0,
			left: 0
		},
		sizes: [20, -110]
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: this.options.sizes[0], left: this.options.sizes[1]});
	}
});

/* 
Class: Fx.Cycle.fade 
*/
Fx.Cycle.fade = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeOut: {
			opacity: 0
		},
		cssBefore: {
			opacity: 1	
		}
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
	}
});

/* 
Class: Fx.Cycle.slideUp 
*/
Fx.Cycle.slideUp = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left:0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: -this.parentHeight});
	}
});

/* 
Class: Fx.Cycle.slideDown 
*/
Fx.Cycle.slideDown = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left:0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: this.parentHeight});
	}
});

/* 
Class: Fx.Cycle.slideRight 
*/
Fx.Cycle.slideRight = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left:0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({left: this.parentWidth});
	}
});

/* 
Class: Fx.Cycle.slideLeft 
*/
Fx.Cycle.slideLeft = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left:0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({left: -this.parentWidth});
	}
});

/* 
Class: Fx.Cycle.foldUp 
*/
Fx.Cycle.foldUp = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeOut: {
			height: 0
		},
		animeIn: {
			left: 0, top: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.cssBefore({top: 0, height: this.height});
	}
});

/* 
Class: Fx.Cycle.foldDown 
*/
Fx.Cycle.foldDown = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeIn: {
			left: 0, top: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({height: 0, top: this.height});
		this.cssBefore({top: 0, height: this.height});
	}
});

/* 
Class: Fx.Cycle.foldRight 
*/
Fx.Cycle.foldRight = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeOut: {
			width: 0
		},
		animeIn: {
			left: 0, top: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.cssBefore({top: 0, width: this.width});
	}
});

/* 
Class: Fx.Cycle.foldLeft 
*/
Fx.Cycle.foldLeft = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeIn: {
			left: 0, top: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({width: 0, left: this.width});
		this.cssBefore({top: 0, width: this.width});
	}
});

/* 
Class: Fx.Cycle.zoom 
*/
Fx.Cycle.zoom = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({width: 0, height: 0, top: this.height/2, left: this.width/2});
		this.animeIn({top: 0, left: 0, width: this.height, height: this.width});
	}
});

/* 
Class: Fx.Cycle.diagonalUp
*/
Fx.Cycle.diagonalUp = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeIn: {
			top: 0, left: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: -this.parentHeight, left: -this.parentWidth});
	}
});

/* 
Class: Fx.Cycle.diagonalDown
*/
Fx.Cycle.diagonalDown = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeIn: {
			top: 0, left: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: this.parentHeight, left: this.parentWidth});
	}
});

/* 
Class: Fx.Cycle.linear 
*/
Fx.Cycle.linear = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeOut: {
			display: 'none'
		},
		cssBefore: {
			display: 'block'
		}
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
	}
});

/*
	Class: Element
	
	[Description] 
		Contains the cycle method which returns a determinate Fx.Cycle instance
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		cycle -- returns an Fx.Cycle instance of the given type
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: cycle
	Description:  returns an Fx.Cycle instance of the given type
	[Arguments]
		type :: the Fx.Cycle transition
		options :: the Fx.Cycle options
	[/Arguments]
	[Example]  
		> // slideUp instance
		> var slideUp = $('myElement').cycle('slideUp');
		> // diagonalUp instance
		> var diagonalUp = $('myElement').cycle('diagonalUp', {duration: 4000, steps: 4000});
	[/Example]
	*/
	cycle: function(type, options) {
		return new Fx.Cycle[type](this, options);
	}				  

});

/*
	Filename: effects_cycles.js
	
	[Description] 
		Contains the Fx.Cycles Class and the Fx.Cycles extensions to create powerful cycle slideshows which alter 
		two slides at once
	[/Description]
	
	Contains: Class Fx.Cycles and its extensions, Class Element
	
	[Summary]
		Fx.Cycles ::: A wrapper which allows you to create powerful cycle effects
		Element ::: Contains the cycles method which returns a determinate Fx.Cycles instance
	[/Summary]
*/
/*
	Class: Fx.Cycles
	
	[Description]  
		The Fx.Cycles Class provides a similar functionality to the Fx.Cycle Class. With the Fx.Cycles Class however,
		you can "cycle" two slides at once, to create more complex transitions. There are 13 transitions created by default,
		but you can create your own as with the Fx.Cycle Class.
	[/Description]
	
	Extends: Fx.Elements
	
	Constructor: new Fx.Cycles.cycleType (element, options)
	
	[Properties] 
		element - the wrapper which contains your slides
		options - optional. The Fx options
	[/Properties]
	
	[Options]
		animeOut : an object whose properties are the styles to alter when the slide gets out.
		animeIn : an object whose properties are the styles to alter when the slide comes in.
		cssBefore : an object whose properties are the styles to alter immediately before the slide comes in.
		cssAfter : an object whose properties are the styles to alter immediately after the slide has come in.
		reset : an object whose properties are the styles to reset to the next slide.
		overflow : the overflow of the wrapper. Depends on the type of cycle effect.
		steps : the timer used by autostart to change periodically the slides. Default is 2000 ms
		handles : an object which attaches events to elements passed in as values. The keywords represent the Fx.Cycles's methods
		autostart : if true the slides will be changed automatically. Deafult is true
		enable : an object containing some keywords to enable extra features. See below.
	[/Options]
	
	>> enable:
	[List]
		[li] keyboard: if true you can navigate with the keyboard too. In addition to the arrows, you can use the following keys. 'a' for autostart, 's' for stop, 'f' to go to the first slide and 'l' to go to the last slide. 
	[/List]
	
	[Events]
		onAnimeIn : function fired immediately before the element is animed in. The current and the next slide will be passed in
		onAnimeOut : function fired immediately before the element is animed out. The current and the next slide will be passed in
	[/Events]
	
	[Methods]
		next -- switches to the next slide
		prev -- switches to the previous slide
		goTo -- swicthes to the given slide
		toFirst -- switches to the first slide
		toLast -- switches to the last slide
		autostart -- enables the cycle slideshow
		stop -- stops the slideshow either if start method has been called or autostart option has been enabled
		animeIn -- sets the animeIn properties
		animeOut -- sets the animeOut properties
		cssBefore -- sets the cssBefore properties
		cssAfter -- sets the cssAfter properties
		reset -- sets the reset properties
	[/Methods]
	
	[Note]
		You can use the keywords 'this.height' and 'this.width' into the animeIn, animeOut, cssBefore, cssAfter and reset methods,
		to refer respectively to the images' height and width. Using the keyword 'this.parentHeight' and 'this.parentWidth'
		you can refer to the parent element dimensions.
		In addiction, you can use the keywords 'this.currSlide' and 'this.nextSlide' to refer respectively to the current and
		the next slide.
	[/Note]
	
	Method: next
	Description:  switches to the next slide
	[Example]  
		> fx.next();
	[/Example]
	
	Method: prev
	Description:  switches to the previous slide
	[Example]  
		> fx.prev();
	[/Example]
	
	Method: goTo
	Description:  swicthes to the given slide
	[Arguments]
		num :: the position of the needed slide
	[/Arguments]
	[Example]  
		> fx.goTo(2);
	[/Example]
	
	Method: toFirst
	Description:  switches to the first slide
	[Example]  
		> fx.toFirst();
	[/Example]
	
	Method: toLast
	Description:  switches to the last slide
	[Example]  
		> fx.toLast();
	[/Example]
	
	Method: autostart
	Description:  enables the cycle slideshow
	[Example]  
		> fx.autostart();
	[/Example]
	
	Method: stop
	Description:  stops the slideshow either if start method has been called or autostart option has been enabled
	[Example]  
		> fx.stop();
	[/Example]
	
	Method: animeIn
	Description:  sets the animeIn properties
	[Arguments]
		styles :: an object which contains the animeIn css styles
	[/Arguments]
	[Example]  
		> fx.animeIn({top: 200, left: 200});
	[/Example]
	
	Method: animeOut
	Description:  sets the animeOut properties
	[Arguments]
		styles :: an object which contains the animeOut css styles
	[/Arguments]
	[Example]  
		> fx.animeOut({top: -200, opacity: 0});
	[/Example]
	
	Method: cssBefore
	Description:  sets the cssBefore properties
	[Arguments]
		styles :: an object which contains the cssBefore css styles
	[/Arguments]
	[Example]  
		> fx.cssBefore({left: 200, opacity: 1, height: 0, width: 0});
	[/Example]
	
	Method: cssAfter
	Description:  sets the cssAfter properties
	[Arguments]
		styles :: an object which contains the cssAfter css styles
	[/Arguments]
	[Example]  
		> fx.cssAfter({left: 0, opacity: 0, height: 200});
	[/Example]
	
	Method: reset
	Description:  sets the reset properties
	[Arguments]
		styles :: an object which contains the reset css styles
	[/Arguments]
	[Example]  
		> fx.reset({top: 200, opacity: 1, width: 0});
	[/Example]
*/
Fx.Cycles = new Class({
	
	Extends: Fx.Elements,
	
	options: {
		animeOut: {},
		animeIn: {},
		cssBefore: {},
		cssAfter: {},
		reset: {},
		overflow: 'visible',
		autostart: true,
		steps: 2000,
		duration: 3000,
		handles: {
			next: false,
			prev: false,
			toFirst: false,
			toLast: false,
			autostart: false,
			stop: false
		},
		enable: {
			keyboard: false	
		},
		onAnimeIn: $empty,
		onAnimeOut: $empty
	},
	
	initialize: function(element, options) {
		this.element = $(element);
		this.elements = this.element.getChildren();
		this.parent($$(this.elements), options);
		this.imgs = this.element.getChildren();
		this.uimgs = this.element.getChildren().reverse();
		this.element.setStyles({'position': 'relative', 'overflow': this.options.overflow});
		this.first = this.element.getFirst();
		
		this.height = this.first.getStyle('height').toInt();
		this.width = this.first.getStyle('width').toInt();
		this.parentHeight = this.element.getStyle('height').toInt();
		this.parentWidth = this.element.getStyle('width').toInt();
		
		this.uimgs.each(function(img, i) {
			img.setStyles({'position': 'absolute', 'top': '0px', 'left': '0px', 'z-index': i});
		}, this);
		this.count = 0;
		this.where = -1;
		this.length = this.imgs.length-1;
		this.fullLength = this.imgs.length;
		if(this.options.autostart) this._autostart = this.next.periodical(this.options.steps, this);
		this.attachHandles();
		if(!this.options.enable.keyboard) this.attachKeys.bindWithEvent(this)();
	},
	
	next: function() {
		if(!this.timer) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			(this.count != this.length) ? this.count++ : this.count = 0;
			(this.where == -1) ? this.where = 0 : (this.count == 0) ? this.where = this.length : this.where = this.count-1;
			this.main();
		}
	},
	
	prev: function() {
		if(!this.timer) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			(this.count == 0) ? this.count = this.length : this.count--;
			(this.where == -1) ? this.where = 0 : (this.count == this.length) ? this.where = 0 : this.where = this.count+1;
			this.main();
		}
	},
	
	goTo: function(to) {
		if(!this.timer && to != this.count) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.where = this.count;
			this.count = to;
			this.main();
		}
	},
	
	toFirst: function() {
		if(!this.timer && this.count != 0) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.where = this.count;
			this.count = 0;
			this.main();
		}
	},
	
	toLast: function() {
		if(!this.timer && this.count != this.length) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.where = this.count;
			this.count = this.length;
			this.main();
		}
	},
	
	autostart: function() {
		this._autostart = this.next.periodical(this.options.steps, this);
	},
	
	stop: function() {
		this._autostart = $clear(this._autostart);	
	},
	
	checkAutostart: function() {
		if(this._autostart) {
			this._autostart = $clear(this._autostart);
			this._autostart = this.next.periodical(this.options.steps, this);
		}
	},
	
	attachHandles: function() {
		for(var mtd in this.options.handles) {
			var method = mtd.toString();
			if(this.options.handles[mtd] && $function(this[method])) {
				$(this.options.handles[mtd]).addEvent('click', function(event, method) {
					event.preventDefault();	
					this[method]();
				}.bindWithEvent(this, method));	
			}
		}
	},
	
	attachKeys: function(event) {
		$(document).addEvent('keydown', function(event) {
			switch(event.key) {
				case 'left': this.prev();
					break;
				case 'right': this.next();
					break;
				case 'a': this.autostart();
					break;
				case 's': this.stop();
					break;
				case 'f': this.toFirst();
					break;
				case 'l': this.toLast();
					break;
			}
		}.bind(this));
	},
	
	main: function() {
		this.element.setStyle('z-index', this.fullLength);
		this.imgs[this.count].setStyle('z-index', 1).setStyles(this.options.current);
		
		this.imgs.each(function(img, i) {
				if(i!=this.where)
					img.setStyles(this.options.cssBefore);
		}, this);
		
		var o = {};

		var curr = this.where;
		var next = this.count;
		
		this.currSlide = this.imgs[curr];
		this.nextSlide = this.imgs[next];
			
		o[curr] = this.options.animeOut;
		o[next] = this.options.animeIn;
		
		this.fireEvent('onAnimeOut', [this.currSlide, this.nextSlide]);
		this.imgs[next].setStyles(this.options.reset);
		this.start(o).chain(function() {
			this.imgs[curr].setStyles(this.options.cssAfter); 
			this.fireEvent('onAnimeIn', [this.currSlide, this.nextSlide]);	
		});
	}
					 
});

(function() {
var methods = {};

['animeOut', 'animeIn', 'cssBefore', 'cssAfter', 'reset'].each(function(method) {
	methods[method] = function(styles) {
		for(var style in styles)
			if($defined(styles[style])) this.options[method][style] = styles[style]; 
	}					
});

Fx.Cycles.implement(methods);
})();

/* 
Class: Fx.Cycles.scrollUp 
*/
Fx.Cycles.scrollUp = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: [0, -this.parentHeight]});
		this.animeIn({top: [this.parentHeight, 0]});
	}
});

/* 
Class: Fx.Cycles.scrollDown 
*/
Fx.Cycles.scrollDown = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: [0, this.parentHeight]});
		this.animeIn({top: [-this.parentHeight, 0]});
	}
});

/* 
Class: Fx.Cycles.scrollLeft
*/
Fx.Cycles.scrollLeft = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({left: [0, -this.parentWidth]});
		this.animeIn({left: [this.parentWidth, 0]});
	}
});

/* 
Class: Fx.Cycles.scrollRight
*/
Fx.Cycles.scrollRight = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({left: [0, this.parentWidth]});
		this.animeIn({left: [-this.parentWidth, 0]});
	}
});

/* 
Class: Fx.Cycles.fadeZoom
*/
Fx.Cycles.fadeZoom = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({opacity: [1, 0], display: 'block'});
		this.animeIn({left: [this.width/2, 0], top: [this.height/2, 0], width: [0, this.width], height: [0, this.height], display: 'block'});
		this.cssBefore({height: 0, width: 0, display: 'none'});
		this.reset({height: this.height, width: this.width, opacity: 1, top: this.height/2, left: this.width/2, display: 'none'});
	}
});

/* 
Class: Fx.Cycles.turnDown
*/
Fx.Cycles.turnDown = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({height: [this.height, 0], top: [0, this.height]});
		this.animeIn({height: [0, this.height]});
		this.reset({display: 'block', height: this.height, width: this.width, top: 0, left: 0});
		this.cssAfter({display: 'none', width: 0});
	}
});

/* 
Class: Fx.Cycles.turnUp
*/
Fx.Cycles.turnUp = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({height: [this.height, 0], top: 0});
		this.animeIn({height: [0, this.height], top: 0});
		this.reset({display: 'block', top: this.height, width: this.width});
		this.cssAfter({display: 'none', width: 0});
	}
});

/* 
Class: Fx.Cycles.turnLeft
*/
Fx.Cycles.turnLeft = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({width: [this.width, 0], left: 0});
		this.animeIn({width: [0, this.width], left: [this.width, 0]});
		this.reset({display: 'block', left: this.width, width: this.width});
		this.cssAfter({display: 'none', width: 0});
	}
});

/* 
Class: Fx.Cycles.turnRight
*/
Fx.Cycles.turnRight = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({width: [this.width, 0], left: [0, this.width]});
		this.animeIn({width: [0, this.width], left: 0});
		this.reset({display: 'block', left: 0, width: this.width});
		this.cssAfter({display: 'none', width: 0});
	}
});

/* 
Class: Fx.Cycles.inOutLeft
*/
Fx.Cycles.inOutLeft = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: this.parentHeight, left: this.parentWidth});
		this.animeIn({top:0, left: 0});
		this.cssBefore({display: 'none'});
		this.reset({top: -this.parentHeight, left: this.parentWidth, display: 'block'});
	}
});

/* 
Class: Fx.Cycles.inOutRight
*/
Fx.Cycles.inOutRight = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: -this.parentHeight, left: -this.parentWidth});
		this.animeIn({top:0, left: 0});
		this.cssBefore({display: 'none'});
		this.reset({top: this.parentHeight, left: -this.parentWidth, display: 'block'});
	}
});

/* 
Class: Fx.Cycles.inOutUp
*/
Fx.Cycles.inOutUp = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: -this.parentHeight});
		this.animeIn({left: 0});
		this.cssBefore({display: 'none'});
		this.reset({top: 0, left: this.parentWidth, display: 'block'});
	}
});

/* 
Class: Fx.Cycles.inOutDown
*/
Fx.Cycles.inOutDown = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: this.parentHeight});
		this.animeIn({left: 0});
		this.cssBefore({display: 'none'});
		this.reset({top: 0, left: this.parentWidth, display: 'block'});
	}
});

/*
	Class: Element
	
	[Description] 
		Contains the cycles method which returns a determinate Fx.Cycles instance
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		cycles -- returns an Fx.Cycles instance of the given type
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: cycles
	Description:  returns an Fx.Cycles instance of the given type
	[Arguments]
		type :: the Fx.Cycles transition
		options :: the Fx.Cycles options
	[/Arguments]
	[Example]  
		> // scrollUp instance
		> var scrollUp = $('myElement').cycles('scrollUp');
		> // turnUp instance
		> var turnUp = $('myElement').cycles('turnUp', {duration: 2000, steps: 4000});
	[/Example]
	*/
	cycles: function(type, options) {
		return new Fx.Cycles[type](this, options);
	}				  

});

/*
	Filename: virtual_base.js
	
	[Description]
		Contains the Virtual Class which is a wrapper for creating complex virtual modal boxes
	[/Description]
	
	Contains: Class Virtual, Class Virtual.single
	
	Requires: overlay.js, browser.js, type.js
	
	[Summary]
		Virtual ::: A wrapper for creating virtual contents like Virtual.Box and Virtual.Ajax Classes
		Virtual.single ::: Utility Wrapper to create single virtual boxes. Implemented by the other virtual single Classes
	[/Summary]
*/
/*
	Class: Virtual
	
	Description: A wrapper for creating virtual contents like Virtual.Box and Virtual.Ajax Classes
	
	Implements: Overlay, Options, Events
	
	Constructor: new Virtual (options)
	
	[Options]
		enable : an object which allows you to decide which features must be enabled
		effect : the effect type. Can be 'open' (default), 'slide:vertical' (or 'slide'), 'slide:horizontal', 'fold' or 'fix'
		effectOptions : the main Fx effect options
		style : if true the boxes will be styled with the custom styles
		adjustStyles : if true the virtual box will be placed in the middle when user resize the window. Default is true.
		zones : an object which allows to set the class names for some zones of the virtual box
		arrowsBoxText : the text of the arrows box
		leftArrowText : the text of the left arrow. Default is 'prev'
		rightArrowText : the text of the right arrow. Default is 'next'
		closeButtonText : the text of the close button. Default is 'close'
		captionOpacity : the caption's opacity. Default is 0.4
	[/Options]
	
	>> enable:
		[List]
			[li] arrows: if true the arrows will be enabled
			[li] closeButton: if true the closeButton will be enabled. Otherwise you can close the box clicking on the overlay
			[li] arrowsKeyboard: if true you can change the virtual box with the arrows of the keyboard
			[li] closeKeyboard: if true you can remove the virtual box by pressing the 'esc' key
			[li] caption: if true the caption will be enabled, and it will have a title an a content catched by the title property of the respective link
		[/List]
	
	[Events]
		onShow : function fired when a new virtual box comes in
		onClose : function fired when the virtual box is closed
		onNext : function fired when the next virtual box comes in
		onPrev : function fired when the previous virtual box comes in
	[/Events]
	
	[Methods]
		setEffect -- sets the type of the entry effect
		virtualStyle -- injects a css file dedicated to virtual box / virtual ajax
		setIDs -- sets the id property to the specified zones
	[/Methods]
	
	Method: setEffect
	Description:  sets the type of the entry effect
	[Arguments]
		effect :: the effect
	[/Arguments]
	[Example]
		> // open effect
		> virtual.setEffect('open');
		> // fix effect
		> virtual.setEffect('fix');
	[/Example]
	
	Method: virtualStyle
	Description:  injects a css file dedicated to virtual box / virtual ajax
	[Arguments]
		path :: the file path
	[/Arguments]
	[Example]
		> virtual.virtualStyle('myPath/virtual_style.css');
	[/Example]

	Method: setIDs
	Description:  sets the id property to the specified zones
	[Arguments]
		zones :: an object with keywords as zones and values as id values
	[/Arguments]
*/
var Virtual = new Class({
		
	Implements: [Overlay, Options, Events],
	
	options: {
		enable: {
			arrows: true,
			closeButton: true,
			arrowsKeyboard: true,
			closeKeyboard: true,
			caption: true
		},
		effect: 'open',
		effectOptions: {
			duration: 1000	
		},
		style: true,
		adjustStyles: true,
		zones: {
			main: '',
			wrapper: '',
			caption: '',
			captionText: '',
			captionTextTitle: '',
			captionTextContent: '',
			arrowsBox: '',
			arrowsBoxText: '',
			leftArrow: '',
			rightArrow: ''
		},
		arrowsBoxText: false,
		leftArrowText: 'prev',
		rightArrowText: 'next',
		closeButtonText: 'close',
		captionOpacity: 0.4,
		imageText: false,
		onShow: $empty,
		onClose: $empty,
		onNext: $empty,
		onPrev: $empty
	},	
	
	initialize: function(options) {
		this.setOptions(options);
		this.effects = {
			main: new Fx.Elements(null, $merge(this.options.effectOptions, {link: 'ignore'})),
			caption: new Fx.Elements(null, {duration: 1000, link: 'ignore'})	
		};
		this.fullWidth = [];
		this.fullHeight = [];
		this.captionHeight = [];
	},
	
	mechanize: function() {
		this.createOverlay('virtualBoxOverlay', 'darken');
		this.createFullPage('virtualBoxFullPage');
		
		this.main = new Element('div', {
			'id': 'virtualMain',
			'class': this.options.zones.main
		});
		
		if(this.options.style)
			this.main.setStyles({
				'background-color': '#FFFFFF',
				'padding': '8px'
			});
		
		this.wrapper = new Element('div', {
			'id': 'virtualBox',
			'class': this.options.zones.wrapper,
			'styles': {
				'position': 'relative',
				'overflow': 'hidden'
			}
		}).inject(this.main);
		
		if(this.options.enable.caption) {
			this.caption = new Element('div', {
				'id': 'virtualCaption',	
				'class': this.options.zones.caption,
				'styles': {
					'position': 'absolute',
					'bottom': '0px',
					'opacity': this.options.captionOpacity,
					'z-index': 1,
					'overflow': 'hidden',
					'visibility': 'hidden'
				}
			}).inject(this.wrapper);
			
			if(this.options.style) this.caption.setStyles({'background-color': '#CCCCCC'});
			
			this.captionText = new Element('div', {
				'id': 'virtualCaptionText',	
				'class': this.options.zones.captionText,
				'styles': {
					'position': 'absolute',
					'bottom': '0px',
					'opacity': 1,
					'z-index': 2,
					'overflow': 'hidden',
					'visibility': 'hidden'
				}
			}).inject(this.wrapper);
			
			this.captionTextTitle = new Element('p', {
				'id': 'virtualCaptionTitle',
				'class': this.options.zones.captionTextTitle
			}).inject(this.captionText);
			
			this.captionTextContent = new Element('p', {
				'id': 'virtualCaptionContent',
				'class': this.options.zones.captionTextContent
			}).inject(this.captionText);
		}
		
		if(this.options.enable.arrows) {
			this.arrowsBox = new Element('div', {
				'id': 'virtualArrowsBox',	
				'class': this.options.zones.arrowsBox,
				 'styles': {
					 'position': 'absolute',
					 'bottom': '0px',
					 'visibility': 'hidden' 
				 }
			});
			
			this.arrowsBoxText = new Element('div', {
				'id': 'virtualArrowsBoxText', 
				'class': this.options.zones.arrowsBoxText,
				'styles': {
					'display': 'block',
					'visibility': 'hidden'
				}
			}).inject(this.arrowsBox);
			
			this.leftArrow = new Element('a', {
				'id': 'virtualLeftArrow',
				'class': this.options.zones.leftArrow,
				'href': '#'
			}).set('html', this.options.leftArrowText);
			
			this.rightArrow = new Element('a', {
				'id': 'virtualRightArrow',
				'class': this.options.zones.rightArrow,
				'href': '#'
			}).set('html', this.options.rightArrowText);
			
			this.leftArrow.addEvent('click', function(event) {
				event.preventDefault();
				this.prev();
			}.bind(this));
			
			this.rightArrow.addEvent('click', function(event) {
				event.preventDefault();
				this.next();
			}.bind(this));
			
			$$(this.leftArrow, this.rightArrow).inject(this.arrowsBox);
			
			if(this.options.enable.closeButton) {
				this.closeButton = new Element('a', {
					'id': 'virtualCloseButton',
					'class': this.options.zones.closeButton,
					'href': '#'
				}).set('html', this.options.closeButtonText).addEvent('click', function(event) {
					event.preventDefault();
					this.closeBox();
				}.bind(this));
				this.closeButton.inject(this.arrowsBox);
			}
			else {
				this.attachCloseEvent();
			}
		}
		
		if(this.options.enable.closeKeyboard) document.addEvent('keydown', this.keyboardClose.bind(this));
		if(!this.options.enable.arrows || !this.options.enable.closeButton) this.attachCloseEvent();
		if(this.options.enable.arrowsKeyboard) document.addEvent('keydown', this.keyboard.bindWithEvent(this));
		
		if(this.options.adjustStyles) {
			this.newsizes = function() {
				$$(this.main).setStyles({
					'top': window.getSize().y.toInt()/2,
					'left': window.getSize().x.toInt()/2
				});
			};
			window.addEvent('resize', this.newsizes.bind(this));
		}
	},
	
	createArrowsBox: function() {
		this.arrowsBox.inject(this.main);
		this.main.inject(this.fullpage);
		this.arrowsBoxHeight = this.arrowsBox.getSize().y + this.arrowsBoxText.getSize().y;
		this.arrowsBoxHalfHeight = this.arrowsBox.getHeight().toInt();
		this.main.setStyles({
			'position': 'absolute',
			'top': window.getSize().y.toInt()/2,
			'left': window.getSize().x.toInt()/2,
			'height': this.sizes.height+this.arrowsBoxHeight,
			'margin-top': -((this.sizes.height+this.arrowsBoxHeight)/2),
			'margin-left': -((this.sizes.width+this.arrowsBoxHeight)/2)
		});
	},
	
	setArrowsBoxText: function(text) {
		if(this.options.enable.arrows) { 
			var arrowsBoxText = this.options.arrowsBoxText || text;
			this.arrowsBoxText.set('html', arrowsBoxText).inject(this.main);
		}
	},
	
	reset: function() {
		$$(this.caption, this.captionText, this.arrowsBox, this.arrowsBoxText).setStyle('visibility', 'hidden');
		if(this.options.enable.caption) {
			this.captionText.dispose().setStyle('height', '0px');
			$$(this.captionTextTitle, this.captionTextContent).empty();
		}
	},
	
	makeCaptionEffect: function(i) {
		if(this.options.enable.caption) {
			this.captionText.inject(this.caption, 'after');
			if(!this.captionPadding) this.captionPadding = (this.captionText.getStyle('padding-top').toInt() + this.captionText.getStyle('padding-bottom').toInt());
			
			this.captionText.setStyle('height', 'auto');
			this.captionTextTitle.set('html', this.sizes.title).inject(this.captionText);
			this.captionTextContent.set('html', this.sizes.text).inject(this.captionText);
			
			if(!this.captionHeight[i]) this.captionHeight[i] = this.captionText.getSize().y - this.captionPadding;
			
			$$(this.caption, this.captionText).setStyles({'height': '0px', 'visibility': 'visible'});
			
			switch(this.options.effect) {
				case 'open':
				case 'slide:vertical':
				case 'slide:horizontal':
				case 'slide': this.captionDelay = this.effects.main.options.duration.toInt();
								break;
				case 'fix': this.captionDelay = 0;
							break;
				case 'fold': this.captionDelay = this.effects.main.options.duration.toInt()*2;
								break;
			}
			
			this.effects.caption.elements = $$(this.caption, this.captionText);
			this.effects.caption.start.delay(this.captionDelay, this.effects.caption, {
				'0': { height: [0, this.captionHeight[i]]},	
				'1': { height: [0, this.captionHeight[i]]}
			});
		}
	},
	
	next: function() {
		if(this.effects.main.timer || this.effects.caption.timer) return;
		(this.count != this.length) ? this.count++ : this.count = 0;
		this.attach(this.count);
		this.fireEvent('onNext', [this.count, this.fullLength]);
	},
	
	prev: function() {
		if(this.effects.main.timer || this.effects.caption.timer) return;
		(this.count == 0) ? this.count = this.length : this.count--;
		this.attach(this.count);
		this.fireEvent('onPrev', [this.count, this.fullLength]);
	},
	
	keyboard: function(event) {
		if(this.overlayActive) {
			if(event.key == 'right') {
				this.next();
			}
			else if(event.key == 'left') {
				this.prev();
			}
		}
	},
	
	keyboardClose: function(event) {
		if(this.overlayActive) {
			if(event.key == 'esc') this.closeBoxWithKeyboard();
		}
	},
	
	setEffect: function(mode) {
		this.options.effect = mode;
	},
	
	remove: function() {
		this.main.dispose();
		this.removeOverlay();
	},
	
	attachCloseEvent: function() {
		if(Browser.firefox) {
			this.overlay.addEvent('click', this.closeBox.bindWithEvent(this, 'overlay'));
			this.fullpage.addEvent('click', this.closeBox.bindWithEvent(this, 'fullpage'));
		}
		else {
			this.fullpage.addEvent('click', this.closeBox.bindWithEvent(this, 'fullpage'));
		}
	},
	
	closeBox: function(event, zone) {
		if(this.effects.main.timer || this.effects.caption.timer) return;
		if((!this.options.enable.arrows || !this.options.enable.closeButton) && event.target != this[zone]) return;
		this.fireEvent('onClose', [this.count, this.length]);
		this.count = 0;
		this.remove();
	},
	
	closeBoxWithKeyboard: function() {
		if(this.effects.main.timer || this.effects.caption.timer) return;
		this.fireEvent('onClose', [this.count, this.length]);
		this.count = 0;
		this.remove();
	},
	
	makeEffect: function(i) {
		if(this.options.effect == 'open') {
			if(Browser.firefox) this.fullpage.setStyle('height', 'auto');
			if(this.options.enable.arrows) this.createArrowsBox();
			else this.main.inject(this.fullpage);
			
			if(!this.fullWidth[i]) this.fullWidth[i] = this.main.getStyle('width').toInt();
			if(!this.fullHeight[i]) this.fullHeight[i] = (!this.arrowsBoxHeight) ? this.sizes.height : this.sizes.height+this.arrowsBoxHeight;
			
			$$(this.main, this.wrapper).setStyles({'visibility': 'visible', 'height': '0px', 'width': '0px'});
			$$(this.arrowsBox).setStyle('width', this.fullWidth[i]);
			
			this.effects.main.elements = $$(this.main, this.wrapper);
			this.effects.main.start({
				'0': {
					'width': this.fullWidth[i],	
					'height': this.fullHeight[i]
				},
				'1': {
					'width': this.fullWidth[i],	
					'height': this.sizes.height
				}
			}).chain(function() {
				if(this.options.enable.arrows) $$(this.arrowsBox, this.arrowsBoxText).setStyle('visibility', 'visible');	
			}.bind(this));
		}
		else if(this.options.effect == 'fix') {
			if(Browser.firefox) this.fullpage.setStyle('height', 'auto');
			if(this.options.enable.arrows) { 
				this.createArrowsBox();
				if(!this.fullWidth[i]) this.fullWidth[i] = this.main.getStyle('width').toInt();
				if(!this.fullHeight[i]) this.fullHeight[i] = (!this.arrowsBoxHeight) ? this.sizes.height : this.sizes.height+this.arrowsBoxHeight;
				$$(this.arrowsBox, this.arrowsBoxText).setStyle('visibility', 'visible');
				$$(this.arrowsBox).setStyle('width', this.fullWidth[i]);
			}
			else this.main.inject(this.fullpage);
		}
		else if(this.options.effect == 'fold') {
			if(Browser.firefox) this.fullpage.setStyle('height', 'auto');
			if(this.options.enable.arrows) this.createArrowsBox();
			else this.main.inject(this.fullpage);
			
			$$(this.main).setStyle('overflow', 'hidden');
			
			if(!this.fullWidth[i]) this.fullWidth[i] = this.main.getStyle('width').toInt();
			if(!this.fullHeight[i]) this.fullHeight[i] = (!this.arrowsBoxHeight) ? this.sizes.height : this.sizes.height+this.arrowsBoxHeight;
			
			$$(this.main, this.wrapper).setStyles({'visibility': 'visible', 'height': '0px', 'width': '0px'});
			$$(this.arrowsBox).setStyles({'height': '0px', 'width': '0px'});
			//$$(this.arrowsBox).setStyle('width', this.fullWidth[i]);
			
			this.effects.main.elements = (this.options.enable.arrows) ? $$(this.main, this.wrapper, this.arrowsBox) : $$(this.main, this.wrapper);
			
			var width = {
				'0': { 'width': [this.main.getStyle('width').toInt(), this.fullWidth[i]] },
				'1': { 'width': [this.main.getStyle('width').toInt(), this.fullWidth[i]] }
			};
			
			var height = {
				'0': { 'height': [this.main.getStyle('height').toInt(), this.fullHeight[i]] },
				'1': { 'height': [this.main.getStyle('height').toInt(), this.sizes.height] }
			};
			
			if(this.options.enable.arrows) {
				var arrwidth = { '2': { 'width': this.fullWidth[i] } };
				var arrheight = { '2': { 'height': [0, this.arrowsBoxHalfHeight] } };
			}
			
			this.effects.main.start((arrwidth) ? $merge(width, arrwidth) : width).chain(function() {
				this.effects.main.start((arrheight) ? $merge(height, arrheight) : height);
			}.bind(this)).chain(function() {
				if(this.options.enable.arrows) $$(this.arrowsBox, this.arrowsBoxText).setStyle('visibility', 'visible');	
			}.bind(this));
		}
		else if(this.options.effect == 'slide:vertical' || this.options.effect == 'slide:horizontal' || this.options.effect == 'slide') {
			if(Browser.firefox) this.fullpage.setStyle('height', 'auto');
			if(this.options.enable.arrows) this.createArrowsBox();
			else this.main.inject(this.fullpage);
			
			if(!this.fullWidth[i]) this.fullWidth[i] = this.main.getStyle('width').toInt();
			if(!this.fullHeight[i]) this.fullHeight[i] = (!this.arrowsBoxHeight) ? this.sizes.height : this.sizes.height+this.arrowsBoxHeight;
			
			var direction = this.options.effect.split(':')[1] || 'vertical';
			
			if(direction == 'vertical')
				$$(this.main).setStyles({'visibility': 'visible', 'height': this.fullHeight[i], 'width': this.fullWidth[i], 'top': -1000});
			else if(direction == 'horizontal')
				$$(this.main).setStyles({'visibility': 'visible', 'height': this.fullHeight[i], 'width': this.fullWidth[i], 'left': -1000});
			
			$$(this.arrowsBox).setStyle('width', this.fullWidth[i]);
			
			switch(direction) {
				case 'vertical': var styles = {'top': window.getSize().y.toInt()/2 };
								break;
				case 'horizontal': var styles = {'left': window.getSize().x.toInt()/2 };
								break;
			}
	
			this.effects.main.elements = $$(this.main);
			this.effects.main.start({
				'0': styles
			}).chain(function() {
				if(this.options.enable.arrows) $$(this.arrowsBox, this.arrowsBoxText).setStyle('visibility', 'visible');	
			}.bind(this));
			
		}
	},
	
	virtualStyle: function(path) {
		new Asset.css(path, {id: 'virtualStyle'});
		return this;
	},
	
	setIDs: function(names) {
		if($object(names)) {
			for(var name in names) {
				if(this[name]) this[name].set('id', names[name]);
			}	
		}
		return this;
	}
});

/*
	Class: Virtual.single
	
	[Description] 
		Utility Wrapper to create single virtual boxes. Implemented by the other virtual single Classes.
	[/Description]
	
	[Methods]
		create -- calls the virtual box
	[/Methods]
	
	Method: create
	Description:  calls the virtual box
*/
Virtual.single = new Class({
						   
	attachElement: function() {
		this.element.addEvent('click', function(event) {
			event.preventDefault();
			this.attach(0);	
		}.bind(this));
	},
	
	create: function() {
		this.attach(0);	
	}
});

/*
	Filename: virtual_box.js
	
	[Description]
		Contains the Virtual.Box and Virtual.Box.single Classes to create customizable and flexible light boxes of images
	[/Description]
	
	Contains: Class Virtual.Box, Class Virtual.Box.single
	
	Requires: virtual_base.js, overlay.js, browser.js, type.js
	
	[Summary]
		Virtual.Box ::: Custom Class to create virtual boxes
		Virtual.Box.single ::: Custom Class to create single virtual boxes
	[/Summary]
*/
/*
	Class: Virtual.Box
	
	[Description] 
		Custom Class to create virtual boxes.
		Applies the virtual box effect to each link which has 'virtualbox' as value of the classname property.
	[/Description]
	
	Extends: Virtual
	
	Constructor: new Virtual.Box (options)
	
	[Properties] 
		options - optional. an object which permits to customize the virtual boxes
	[/Properties]
	
	[Options]
		Virtual Options : the options of the Virtual Class
	[/Options]
	
	[Note]
		You can set the contents of the caption by setting the title property of each link in this way: 
		'title :: content', where the separator is the ' :: ' string
	[/Note]
	
	[Example]
		> // applies the virtual box effect to each link which has 'virtualbox' as value of the classname property 
		> var virtual = new Virtual.Box({
		>	enable: {
		>		arrows: true,
		>		closeButton: true
		>	},
		>	effect: 'open',
		>	leftArrowText: '',
		>	rightArrowText: '',
		>	closeButtonText: '',
		>	captionOpacity: 0.6
		>	}
		> });
		>
		> // the HTML
		> <a href="flowers.jpg" class="virtualbox" title="My flowers">image 1</a>
	[/Example]
*/
Virtual.Box = new Class({
						
	Extends: Virtual,
	
	initialize: function(options, single) {
		this.links = $$('a[class=virtualbox]');
		this.preload = [];
		this.parent(options);
		
		this.mechanize();
		
		if(!single) {
			this.links.each(function(el, i) {
									 
				this.preload[i] = new Element('img');
				this.preload[i].src = el.getProperty('href');
		
				var fullText = el.getProperty('title').split(' :: ');
				
				this.preload[i].store('title', fullText[0]);
				this.preload[i].store('text', fullText[1]);
				
				el.addEvent('click', function(event) {
					event.preventDefault();
					this.attach(i);	
				}.bind(this));
				
			}, this);
		}
		
		this.count = 0;
		this.length = this.preload.length-1;
		this.fullLength = this.preload.length;
	},
	
	attach: function(i) {
		this.img = this.preload[i];
		this.count = i;
		
		if(!this.overlayActive) { 
			this.injectOverlay(true);
		}
		
		this.reset();
		
		this.prepareImage(i);
		this.makeCaptionEffect(i);
	},
	
	prepareImage: function(i) {
		this.sizes = {
			width: this.preload[i].width,
			height: this.preload[i].height,
			title: this.preload[i].retrieve('title'),
			text: this.preload[i].retrieve('text')
		};
		
		this.main.setStyles({
			'position': 'absolute',
			'width': this.sizes.width,
			'height': this.sizes.height,
			'top': window.getSize().y.toInt()/2,
			'left': window.getSize().x.toInt()/2,
			'margin-top': -(this.sizes.height/2),
			'margin-left': -(this.sizes.width/2)
		});
		
		this.wrapper.setStyles({
			'background-color': '#FFFFFF',
			'background-repeat': 'no-repeat',
			'background-image': 'url(' + this.preload[i].src + ')',
			'overflow': 'hidden',
			'width': this.sizes.width,
			'height': this.sizes.height			   
		});
		
		$$(this.caption, this.captionText).setStyles({'width': this.sizes.width});
		
		this.setArrowsBoxText('image ' + (i+1) + '/' + this.preload.length);
		this.fireEvent('onShow');
		this.makeEffect(i);
	}
});

/*
	Class: Virtual.Box.single
	
	[Description] 
		Custom Class to create single virtual boxes. Applies the virtual box effect to the given link.
	[/Description]
	
	Extends: Virtual.Box
	
	Implements: Virtual.single
	
	Constructor: new Virtual.Box.single (element, options)
	
	[Properties] 
		element - the element to apply the effect to
		options - optional. the options
	[/Properties]
	
	[Options]
		Virtual Options : the options of the Virtual Class
	[/Options]
	
	[Example]
		> // applies the virtual box effect to the 'myElement' link
		> var virtual = new Virtual.Box.single('myElement', {
		>	captionOpacity: 0.4,
		>	effect: 'fix'
		> });
		>
		> // the HTML
		> <a id="myElement" href="/my_imge.jpg" title="My Image :: One of the my collection of images">static content</a>
	[/Example]
*/
Virtual.Box.single = new Class({
								
	Extends: Virtual.Box,
	
	Implements: Virtual.single,
	
	initialize: function(element, options) {
		this.element = $(element);
		this.parent($merge(options, {enable: {arrows: false, arrowsKeyboard: false}}), true);
		this.preload[0] = new Element('img');
		var fullText = this.element.getProperty('title').split(' :: ');
	
		this.preload[0].src = this.element.getProperty('href');
		this.preload[0].store('title', fullText[0]);
		this.preload[0].store('text', fullText[1]);
			
		this.attachElement();
	}
});

/*
	Filename: virtual_ajax.js
	
	[Description]
		Contains the Virtual.Ajax and Virtual.Ajax.single Classes to create customizable and flexible light boxes of content loaded from the server
	[/Description]
	
	Contains: Class Virtual.Ajax, Class Virtual.Ajax.single
	
	Requires: virtual_base.js, overlay.js, browser.js, type.js
	
	[Summary]
		Virtual.Ajax ::: Custom Class to create ajax virtual boxes
		Virtual.Ajax.single ::: Custom Class to create single ajax virtual boxes
	[/Summary]
*/
/*
	Class: Virtual.Ajax
	
	[Description] 
		Custom Class to create ajax virtual boxes.
		Applies the virtual ajax effect to each link which has 'virtualajax' as value of the classname property.
	[/Description]
	
	Extends: Virtual
	
	Constructor: new Virtual.Ajax (options)
	
	[Properties] 
		options - optional. an object which permits to customize the virtual boxes
	[/Properties]
	
	[Options]
		Virtual Options : the options of the Virtual Class
	[/Options]
	
	[Note]
		You can set the dimensions of the virtual box and the contents of the caption by setting the title property of each link in this way: 
		'width :: height :: title :: content', where the separator is the ' :: ' string
	[/Note]
	
	[Example]
		> // applies the virtual ajax effect to each link which has 'virtualajax' as value of the classname property 
		> var virtual = new Virtual.Ajax({
		>	enable: {
		>		arrows: true,
		>		caption: false
		>	},
		>	effect: 'fix'
		> });
		>
		> // the HTML
		> <a href="my_page.php" class="virtualajax" title="460 :: 340">load my page</a>
	[/Example]
*/
Virtual.Ajax = new Class({
						
	Extends: Virtual,
	
	options: {
		width: 400,
		height: 300,
		requestOptions: {}
	},
	
	initialize: function(options, single) {
		this.links = $$('a[class=virtualajax]');
		this.preload = [];
		this.parent(options);
		this.request = new Request.HTML($merge(this.options.requestOptions, {update: this.wrapper}));
		
		this.mechanize();
		this.wrapreq = new Element('div').inject(this.wrapper, 'top');
		
		if(!single) {
			this.links.each(function(el, i) {				 
				this.preload[i] = new Hash();
				var fullText = el.getProperty('title').split(' :: ');
				
				this.preload[i].set('src',  el.get('href'));
				this.preload[i].set('width',  fullText[0].toInt() || this.options.width);
				this.preload[i].set('height',  fullText[1].toInt() || this.options.height);
				this.preload[i].set('title',  fullText[2]);
				this.preload[i].set('text', fullText[3]);
				
				el.addEvent('click', function(event) {
					event.preventDefault();
					this.attach(i);	
				}.bind(this));
			}, this);
		}
		
		this.count = 0;
		this.length = this.preload.length-1;
		this.fullLength = this.preload.length;
	},
	
	attach: function(i) {
		this.img = this.preload[i];
		this.count = i;
		
		if(!this.overlayActive) { 
			this.injectOverlay(true);
		}
		
		if(Browser.opera) this.main.dispose();
		this.reset();
		this.prepareRequest(i);
		this.makeCaptionEffect(i);
	},
	
	prepareRequest: function(i) {
		this.sizes = {
			width: this.preload[i].get('width'),
			height: this.preload[i].get('height'),
			title: this.preload[i].get('title'),
			text: this.preload[i].get('text')
		};
		
		this.main.setStyles({
			'position': 'absolute',
			'width': this.sizes.width,
			'height': this.sizes.height,
			'top': window.getSize().y.toInt()/2,
			'left': window.getSize().x.toInt()/2,
			'margin-top': -(this.sizes.height/2),
			'margin-left': -(this.sizes.width/2)
		});
		
		this.wrapper.setStyles({
			'width': this.sizes.width,
			'height': this.sizes.height
		});
		
		$$(this.caption, this.captionText).setStyles({'width': this.sizes.width});
		
		this.request.setOptions({url: this.preload[i].src, update: this.wrapreq,
			onSuccess: function() {
				if(this.options.enable.caption) {
					$$(this.caption, this.captionText).setStyles({
						'width': this.sizes.width				   
					}).inject(this.wrapper);
					this.captionTextTitle.set('html', this.sizes.title).inject(this.captionText);
					this.captionTextContent.set('html', this.sizes.text).inject(this.captionText);
				}		
			}.bind(this, i)
		}).post();
		
		this.setArrowsBoxText('Virtual Ajax ' + (i+1) + '/' + this.preload.length);
		this.fireEvent('onShow');
		this.makeEffect(i);
	}
});

/*
	Class: Virtual.Ajax.single
	
	[Description] 
		Custom Class to create single ajax virtual boxes. Applies the virtual ajax effect to the given link.
	[/Description]
	
	Extends: Virtual.Ajax
	
	Implements: Virtual.single
	
	Constructor: new Virtual.Ajax.single (element, options)
	
	[Properties] 
		element - the element to apply the effect to
		options - optional. the options
	[/Properties]
	
	[Options]
		Virtual Options : the options of the Virtual Class
	[/Options]
	
	[Example]
		> // applies the virtual ajax effect to the 'myElement' link
		> var virtual = new Virtual.Ajax.single('myElement', {
		>	style: false
		>	effect: 'open'
		> });
		>
		> // the HTML
		> <a id="myElement" href="/my_page.php" title="460 :: 340">static content</a>
	[/Example]
*/
Virtual.Ajax.single = new Class({
								
	Extends: Virtual.Ajax,
	
	Implements: Virtual.single,
	
	initialize: function(element, options) {
		this.element = $(element);
		this.parent($merge(options, {enable: {arrows: false, arrowsKeyboard: false}}), true);
		this.preload[0] = new Hash();
		var fullText = this.element.getProperty('title').split(' :: ');
		this.preload[0].set('src',  this.element.get('href'));
		this.preload[0].set('width',  fullText[0].toInt() || this.options.width);
		this.preload[0].set('height',  fullText[1].toInt() || this.options.height);
		this.preload[0].set('title',  fullText[2]);
		this.preload[0].set('text', fullText[3]);
			
		this.attachElement();
	}
});

/*
	Filename: virtual_html.js
	
	[Description]
		Contains the Virtual.HTML and Virtual.HTML.single Classes to create customizable and flexible light boxes of static HTML content
	[/Description]
	
	Contains: Class Virtual.HTML, Class Virtual.HTML.single
	
	Requires: virtual_base.js, overlay.js, browser.js, type.js
	
	[Summary]
		Virtual.HTML ::: Custom Class to create ajax virtual boxes
		Virtual.HTML.single ::: Custom Class to create single virtual html boxes
	[/Summary]
*/
/*
	Class: Virtual.HTML
	
	[Description] 
		Custom Class to create html virtual boxes.
		Applies the virtual html effect to each link which has 'virtualhtml' as value of the classname property.
	[/Description]
	
	Extends: Virtual
	
	Constructor: new Virtual.HTML (options)
	
	[Properties] 
		options - optional. an object which permits to customize the virtual boxes
	[/Properties]
	
	[Options]
		Virtual Options : the options of the Virtual Class
	[/Options]
	
	[Note]
		You can set the dimensions of the virtual box and the contents of the caption by setting the title property of each link in this way: 
		'width :: height :: title :: content', where the separator is the ' :: ' string
	[/Note]
	
	[Example]
		> // applies the virtual html effect to each link which has 'virtualajax' as value of the classname property 
		> var virtual = new Virtual.HTML({
		>	enable: {
		>		arrows: false,
		>		caption: false
		>	},
		>	effect: 'open',
		>	style: false,
		>	contents: ['<p>Simple Vitual.HTML</p>', '<div><b>More Complex <i>Virtual.HTML</i></b></div>']
		> });
		>
		> // the HTML
		> <a href="#" class="virtualhtml" title="460 :: 340">static content</a>
	[/Example]
*/
Virtual.HTML = new Class({
						
	Extends: Virtual,
	
	options: {
		width: 400,
		height: 300,
		contents: []
	},
	
	initialize: function(options, single) {
		this.links = $$('a[class=virtualhtml]');
		this.preload = [];
		this.parent(options);
		
		this.mechanize();
		this.content = new Element('div', {'id': 'virtualHTMLContent'});
		
		if(!single) {
			this.links.each(function(el, i) {
									 
				this.preload[i] = new Hash();
				var fullText = el.getProperty('title').split(' :: ');
				
				this.preload[i].set('width',  fullText[0].toInt() || this.options.width);
				this.preload[i].set('height',  fullText[1].toInt() || this.options.height);
				this.preload[i].set('title',  fullText[2]);
				this.preload[i].set('text', fullText[3]);
				
				el.addEvent('click', function(event) {
					event.preventDefault();
					this.attach(i);	
				}.bind(this));
				
			}, this);
		}
		
		this.count = 0;
		this.length = this.preload.length-1;
		this.fullLength = this.preload.length;
	},
	
	attach: function(i) {
		this.img = this.preload[i];
		this.count = i;
		
		if(!this.overlayActive) { 
			this.injectOverlay(true);
		}
		
		if(Browser.opera) this.main.dispose();
		this.reset();
		this.prepareContent(i);
		this.makeCaptionEffect(i);
	},
	
	prepareContent: function(i) {
		this.sizes = {
			width: this.preload[i].get('width'),
			height: this.preload[i].get('height'),
			title: this.preload[i].get('title'),
			text: this.preload[i].get('text')
		};
		
		this.main.setStyles({
			'position': 'absolute',
			'width': this.sizes.width,
			'height': this.sizes.height,
			'top': window.getSize().y.toInt()/2,
			'left': window.getSize().x.toInt()/2,
			'margin-top': -(this.sizes.height/2),
			'margin-left': -(this.sizes.width/2)
		});
		
		this.wrapper.setStyles({
			'width': this.sizes.width,
			'height': this.sizes.height
		});
		
		$$(this.caption, this.captionText).setStyles({'width': this.sizes.width});
		
		this.content.set('html', this.options.contents[i]).inject(this.wrapper, 'top');
		this.setArrowsBoxText('Virtual HTML ' + (i+1) + '/' + this.preload.length);
		this.fireEvent('onShow');
		this.makeEffect(i);
	}
});

/*
	Class: Virtual.HTML.single
	
	[Description] 
		Custom Class to create single virtual html boxes. Applies the virtual html effect to the given link.
	[/Description]
	
	Extends: Virtual.HTML
	
	Implements: Virtual.single
	
	Constructor: new Virtual.HTML.single (element, options)
	
	[Properties] 
		element - the element to apply the effect to
		options - optional. the options
	[/Properties]
	
	[Options]
		Virtual Options : the options of the Virtual Class
		content : the HTML content of the virtual box
	[/Options]
	
	[Example]
		> // applies the virtual html effect to the 'myElement' link
		> var virtual = new Virtual.HTML.single('myElement', {
		>	style: false
		>	effect: 'open',
		>	content: '<div><b>More Complex <i>Virtual.HTML</i></b></div>'
		> });
		>
		> // the HTML
		> <a id="myElement" href="#" title="460 :: 340">static content</a>
	[/Example]
*/
Virtual.HTML.single = new Class({
								
	Extends: Virtual.HTML,
	
	Implements: Virtual.single,
	
	options: {
		content: ''
	},
	
	initialize: function(element, options) {
		this.element = $(element);
		this.parent($merge(options, {enable: {arrows: false, arrowsKeyboard: false}}), true);
		this.preload[0] = new Hash();
		var fullText = this.element.getProperty('title').split(' :: ');
		this.preload[0].set('width',  fullText[0].toInt() || this.options.width);
		this.preload[0].set('height',  fullText[1].toInt() || this.options.height);
		this.preload[0].set('title',  fullText[2]);
		this.preload[0].set('text', fullText[3]);
		
		this.options.contents[0] = this.options.content;
		this.attachElement();
	}
});