//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2008 Valerio Proietti, <http://mad4milk.net>, MIT Style License.

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);}});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 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);}});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 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 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);}});

// Calendar: a Javascript class for Mootools that adds accessible and unobtrusive date pickers to your form elements <http://electricprism.com/aeron/calendar>
// Calendar RC4, Copyright (c) 2007 Aeron Glemann <http://electricprism.com/aeron>, MIT Style License.
// Mootools 1.2 compatibility by Davorin Å ego

var Calendar = new Class({	

	options: {
		blocked: [], // blocked dates 
		classes: [], // ['calendar', 'prev', 'next', 'month', 'year', 'today', 'invalid', 'valid', 'inactive', 'active', 'hover', 'hilite']
		days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // days of the week starting at sunday
		direction: 0, // -1 past, 0 past + future, 1 future
		draggable: true,
		months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
		navigation: 1, // 0 = no nav; 1 = single nav for month; 2 = dual nav for month and year
		offset: 0, // first day of the week: 0 = sunday, 1 = monday, etc..
		onHideStart: Class.empty,
		onHideComplete: Class.empty,
		onShowStart: Class.empty,
		onShowComplete: Class.empty,
		pad: 1, // padding between multiple calendars
		tweak: {x: 0, y: 0} // tweak calendar positioning
	},

	// initialize: calendar constructor
	// @param obj (obj) a js object containing the form elements and format strings { id: 'format', id: 'format' etc }
	// @param props (obj) optional properties

	initialize: function(obj, options) {
		// basic error checking
		if (!obj) { return false; }

		this.setOptions(options);

		// create our classes array
		var keys = ['calendar', 'prev', 'next', 'month', 'year', 'today', 'invalid', 'valid', 'inactive', 'active', 'hover', 'hilite'];

		var values = keys.map(function(key, i) {
			if (this.options.classes[i]) {
				if (this.options.classes[i].length) { key = this.options.classes[i]; }
			}
			return key;
		}, this);

		this.classes = values.associate(keys);

		// create cal element with css styles required for proper cal functioning
		this.calendar = new Element('div', { 
			'styles': { left: '-1000px', opacity: 0, position: 'absolute', top: '-1000px', zIndex: 1000 }
		}).addClass(this.classes.calendar).injectInside(document.body);

		// iex 6 needs a transparent iframe underneath the calendar in order to not allow select elements to render through
		if (window.ie6) {
			this.iframe = new Element('iframe', { 
				'styles': { left: '-1000px', position: 'absolute', top: '-1000px', zIndex: 999 }
			}).injectInside(document.body);
			this.iframe.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
		}

		// initialize fade method
		this.fx = new Fx.Tween(this.calendar, {
			onStart: function() { 
				if (this.calendar.getStyle('opacity') == 0) { // show
					if (window.ie6) { this.iframe.setStyle('display', 'block'); }
					this.calendar.setStyle('display', 'block');
					this.fireEvent('onShowStart', this.element);
				}
				else { // hide
					this.fireEvent('onHideStart', this.element);
				}
			}.bind(this),
			onComplete: function() { 
				if (this.calendar.getStyle('opacity') == 0) { // hidden
					this.calendar.setStyle('display', 'none');
					if (window.ie6) { this.iframe.setStyle('display', 'none'); }
					this.fireEvent('onHideComplete', this.element);
				}
				else { // shown
					this.fireEvent('onShowComplete', this.element);
				}
			}.bind(this)
		});

		// initialize drag method
		if (window.Drag && this.options.draggable) {
			this.drag = new Drag.Move(this.calendar, { 
				onDrag: function() {
					if (window.ie6) { this.iframe.setStyles({ left: this.calendar.style.left, top: this.calendar.style.top }); } 
				}.bind(this) 
			}); 
		}
		
		// create calendars array
		this.calendars = [];

		var id = 0;
		var d = new Date(); // today

		d.setDate(d.getDate() + this.options.direction.toInt()); // correct today for directional offset

		for (var i in obj) {
			var cal = { 
				button: new Element('button', { 'type': 'button' }),
				el: $(i),
				els: [],
				id: id++,
				month: d.getMonth(),
				visible: false,
				year: d.getFullYear()
			};

			// fix for bad element (naughty, naughty element!)
			if (!this.element(i, obj[i], cal)) { continue; }
			
			cal.el.addClass(this.classes.calendar);

			// create cal button
			cal.button.addClass(this.classes.calendar).addEvent('click', function(cal) { this.toggle(cal); }.pass(cal, this)).injectAfter(cal.el);

			// read in default value
			cal.val = this.read(cal);

			$extend(cal, this.bounds(cal)); // abs bounds of calendar

			$extend(cal, this.values(cal)); // valid days, months, years

			this.rebuild(cal);

			this.calendars.push(cal); // add to cals array		
		}	
	},


	// blocked: returns an array of blocked days for the month / year
	// @param cal (obj)
	// @returns blocked days (array)

	blocked: function(cal) {
		var blocked = [];
		var offset = new Date(cal.year, cal.month, 1).getDay(); // day of the week (offset)
		var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of this month
		
		this.options.blocked.each(function(date){
			var values = date.split(' ');
			
			// preparation
			for (var i = 0; i <= 3; i++){ 
				if (!values[i]){ values[i] = (i == 3) ? '' : '*'; } // make sure blocked date contains values for at least d, m and y
				values[i] = values[i].contains(',') ? values[i].split(',') : new Array(values[i]); // split multiple values
				var count = values[i].length - 1;
				for (var j = count; j >= 0; j--){
					if (values[i][j].contains('-')){ // a range
						var val = values[i][j].split('-');
						for (var k = val[0]; k <= val[1]; k++){
							if (!values[i].contains(k)){ values[i].push(k + ''); }
						}
						values[i].splice(j, 1);
					}
				}
			}

			// execution
			if (values[2].contains(cal.year + '') || values[2].contains('*')){
				if (values[1].contains(cal.month + 1 + '') || values[1].contains('*')){
					values[0].each(function(val){ // if blocked value indicates this month / year
						if (val > 0){ blocked.push(val.toInt()); } // add date to blocked array
					});

					if (values[3]){ // optional value for day of week
						for (var i = 0; i < last; i++){
								var day = (i + offset) % 7;
	
								if (values[3].contains(day + '')){ 
									blocked.push(i + 1); // add every date that corresponds to the blocked day of the week to the blocked array
								}
						}
					}
				}
			}
		}, this);

		return blocked;
	},


	// bounds: returns the start / end bounds of the calendar
	// @param cal (obj)
	// @returns obj	

	bounds: function(cal) {
		// 1. first we assume the calendar has no bounds (or a thousand years in either direction)
		
		// by default the calendar will accept a millennium in either direction
		var start = new Date(1000, 0, 1); // jan 1, 1000
		var end = new Date(2999, 11, 31); // dec 31, 2999

		// 2. but if the cal is one directional we adjust accordingly
		var date = new Date().getDate() + this.options.direction.toInt();

		if (this.options.direction > 0) {
			start = new Date();
			start.setDate(date + this.options.pad * cal.id);
		}
		
		if (this.options.direction < 0) {
			end = new Date();
			end.setDate(date - this.options.pad * (this.calendars.length - cal.id - 1));
		}

		// 3. then we can further filter the limits by using the pre-existing values in the selects
		cal.els.each(function(el) {	
			if (el.get('tag') == 'select') {		
				if (el.format.test('(y|Y)')) { // search for a year select
					var years = [];

					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);
	
						if (!years.contains(values[0])) { years.push(values[0]); } // add to years array
					}, this);
	
					years.sort(this.sort);
			
					if (years[0] > start.getFullYear()) { 
						d = new Date(years[0], start.getMonth() + 1, 0); // last day of new month
					
						if (start.getDate() > d.getDate()) { start.setDate(d.getDate()); }
	
						start.setYear(years[0]); 
					}
					
					if (years.getLast() < end.getFullYear()) { 
						d = new Date(years.getLast(), end.getMonth() + 1, 0); // last day of new month
					
						if (end.getDate() > d.getDate()) { end.setDate(d.getDate()); }
	
						end.setYear(years.getLast());
					}		
				}
	
				if (el.format.test('(F|m|M|n)')) { // search for a month select
					var months_start = [];
					var months_end = [];

					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);
	
						if ($type(values[0]) != 'number' || values[0] == years[0]) { // if it's a year / month combo for curr year, or simply a month select
							if (!months_start.contains(values[1])) { months_start.push(values[1]); } // add to months array
						}
	
						if ($type(values[0]) != 'number' || values[0] == years.getLast()) { // if it's a year / month combo for curr year, or simply a month select
							if (!months_end.contains(values[1])) { months_end.push(values[1]); } // add to months array
						}
					}, this);
	
					months_start.sort(this.sort);
					months_end.sort(this.sort);
					
					if (months_start[0] > start.getMonth()) { 
						d = new Date(start.getFullYear(), months_start[0] + 1, 0); // last day of new month
					
						if (start.getDate() > d.getDate()) { start.setDate(d.getDate()); }
	
						start.setMonth(months_start[0]); 
					}
					
					if (months_end.getLast() < end.getMonth()) { 
						d = new Date(start.getFullYear(), months_end.getLast() + 1, 0); // last day of new month
					
						if (end.getDate() > d.getDate()) { end.setDate(d.getDate()); }
	
						end.setMonth(months_end.getLast());
					}		
				}
			}
		}, this);
		
		return { 'start': start, 'end': end };
	},


	// caption: returns the caption element with header and navigation
	// @param cal (obj)
	// @returns caption (element)

	caption: function(cal) {
		// start by assuming navigation is allowed
		var navigation = {
			prev: { 'month': true, 'year': true },
			next: { 'month': true, 'year': true }
		};
		
		// if we're in an out of bounds year
		if (cal.year == cal.start.getFullYear()) { 
			navigation.prev.year = false; 
			if (cal.month == cal.start.getMonth() && this.options.navigation == 1) { 
				navigation.prev.month = false;
			}		
		}		
		if (cal.year == cal.end.getFullYear()) { 
			navigation.next.year = false; 
			if (cal.month == cal.end.getMonth() && this.options.navigation == 1) { 
				navigation.next.month = false;
			}
		}

		// special case of improved navigation but months array with only 1 month we can disable all month navigation
		if ($type(cal.months) == 'array') {
			if (cal.months.length == 1 && this.options.navigation == 2) {
				navigation.prev.month = navigation.next.month = false;
			}
		}

		var caption = new Element('caption');

		var prev = new Element('a').addClass(this.classes.prev).appendText('\x3c'); // <		
		var next = new Element('a').addClass(this.classes.next).appendText('\x3e'); // >

		if (this.options.navigation == 2) {
			var month = new Element('span').addClass(this.classes.month).injectInside(caption);
			
			if (navigation.prev.month) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', -1); }.pass(cal, this)).injectInside(month); }
			
			month.adopt(new Element('span').appendText(this.options.months[cal.month]));

			if (navigation.next.month) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', 1); }.pass(cal, this)).injectInside(month); }

			var year = new Element('span').addClass(this.classes.year).injectInside(caption);

			if (navigation.prev.year) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'y', -1); }.pass(cal, this)).injectInside(year); }
			
			year.adopt(new Element('span').appendText(cal.year));

			if (navigation.next.year) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'y', 1); }.pass(cal, this)).injectInside(year); }
		}
		else { // 1 or 0
			if (navigation.prev.month && this.options.navigation) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', -1); }.pass(cal, this)).injectInside(caption); }

			caption.adopt(new Element('span').addClass(this.classes.month).appendText(this.options.months[cal.month]));
			
			caption.adopt(new Element('span').addClass(this.classes.year).appendText(cal.year));
			
			if (navigation.next.month && this.options.navigation) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', 1); }.pass(cal, this)).injectInside(caption); }

		}

		return caption;
	},


	// changed: run when a select value is changed
	// @param cal (obj)

	changed: function(cal) {
		cal.val = this.read(cal); // update calendar val from inputs	

		$extend(cal, this.values(cal)); // update bounds - based on curr month

		this.rebuild(cal); // rebuild days select

		if (!cal.val) { return; } // in case the same date was clicked the cal has no set date we should exit		

		if (cal.val.getDate() < cal.days[0]) { cal.val.setDate(cal.days[0]); }
		if (cal.val.getDate() > cal.days.getLast()) { cal.val.setDate(cal.days.getLast()); }
		
		cal.els.each(function(el) {	// then we can set the value to the field
			el.value = this.format(cal.val, el.format); 		
		}, this);
		
		this.check(cal); // checks other cals

		this.calendars.each(function(kal) { // update cal graphic if visible
			if (kal.visible) { this.display(kal); }
		}, this);
	},


	// check: checks other calendars to make sure no overlapping values
	// @param cal (obj)

	check: function(cal) {
		this.calendars.each(function(kal, i) {
			if (kal.val) { // if calendar has value set
				var change = false;
			
				if (i < cal.id) { // preceding calendar
					var bound = new Date(Date.parse(cal.val));
					
					bound.setDate(bound.getDate() - (this.options.pad * (cal.id - i)));

					if (bound < kal.val) { change = true; }
				}
				if (i > cal.id) { // following calendar
					var bound = new Date(Date.parse(cal.val));
					
					bound.setDate(bound.getDate() + (this.options.pad * (i - cal.id)));
					
					if (bound > kal.val) { change = true; }
				}

				if (change) {
					if (kal.start > bound) { bound = kal.start; }
					if (kal.end < bound) { bound = kal.end; }

					kal.month = bound.getMonth();
					kal.year = bound.getFullYear();		

					$extend(kal, this.values(kal));			

					// TODO - IN THE CASE OF SELECT MOVE TO NEAREST VALID VALUE
					// IN THE CASE OF INPUT DISABLE

					// if new date is not valid better unset cal value
					// otherwise it would mean incrementally checking to find the nearest valid date which could be months / years away
					kal.val = kal.days.contains(bound.getDate()) ? bound : null;

					this.write(kal);

					if (kal.visible) { this.display(kal); } // update cal graphic if visible
				}
			}
			else {
				kal.month = cal.month;
				kal.year = cal.year;
			}
		}, this);
	},
	

	// clicked: run when a valid day is clicked in the calendar
	// @param cal (obj)

	clicked: function(td, day, cal) {
		cal.val = (this.value(cal) == day) ? null : new Date(cal.year, cal.month, day); // set new value - if same then disable

		this.write(cal); 

		// ok - in the special case that it's all selects and there's always a date no matter what (at least as far as the form is concerned)
		// we can't let the calendar undo a date selection - it's just not possible!!
		if (!cal.val) { cal.val = this.read(cal); }

		if (cal.val) {
			this.check(cal); // checks other cals						
			this.toggle(cal); // hide cal
		} 
		else { // remove active class and replace with valid
			td.addClass(this.classes.valid);
			td.removeClass(this.classes.active);
		}
	},
	

	// display: create calendar element
	// @param cal (obj)

	display: function(cal) {
		// 1. header and navigation
		this.calendar.empty(); // init div

		this.calendar.className = this.classes.calendar + ' ' + this.options.months[cal.month].toLowerCase();

		var div = new Element('div').injectInside(this.calendar); // a wrapper div to help correct browser css problems with the caption element

		var table = new Element('table').injectInside(div).adopt(this.caption(cal));
				
		// 2. day names		
		var thead = new Element('thead').injectInside(table);

		var tr = new Element('tr').injectInside(thead);
		
		for (var i = 0; i <= 6; i++) {
			var th = this.options.days[(i + this.options.offset) % 7];
			
			tr.adopt(new Element('th', { 'title': th }).appendText(th.substr(0, 1)));
		}

		// 3. day numbers
		var tbody = new Element('tbody').injectInside(table);
		var tr = new Element('tr').injectInside(tbody);

		var d = new Date(cal.year, cal.month, 1);
		var offset = ((d.getDay() - this.options.offset) + 7) % 7; // day of the week (offset)
		var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of this month
		var prev = new Date(cal.year, cal.month, 0).getDate(); // last day of previous month
		var active = this.value(cal); // active date (if set and within curr month)
		var valid = cal.days; // valid days for curr month
		var inactive = []; // active dates set by other calendars
		var hilited = [];
		this.calendars.each(function(kal, i) {
			if (kal != cal && kal.val) {
				if (cal.year == kal.val.getFullYear() && cal.month == kal.val.getMonth()) { inactive.push(kal.val.getDate()); }

				if (cal.val) {
					for (var day = 1; day <= last; day++) {
						d.setDate(day);
						
						if ((i < cal.id && d > kal.val && d < cal.val) || (i > cal.id && d > cal.val && d < kal.val)) { 
							if (!hilited.contains(day)) { hilited.push(day); }
						}
					}
				}
			}
		}, this);
		var d = new Date();
		var today = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime(); // today obv 
		
		for (var i = 1; i < 43; i++) { // 1 to 42 (6 x 7 or 6 weeks)
			if ((i - 1) % 7 == 0) { tr = new Element('tr').injectInside(tbody); } // each week is it's own table row

			var td = new Element('td').injectInside(tr);
						
			var day = i - offset;
			var date = new Date(cal.year, cal.month, day);
			
			var cls = '';
			
			if (day === active) { cls = this.classes.active; } // active
			else if (inactive.contains(day)) { cls = this.classes.inactive; } // inactive
			else if (valid.contains(day)) { cls = this.classes.valid; } // valid
			else if (day >= 1 && day <= last) { cls = this.classes.invalid; } // invalid

			if (date.getTime() == today) { cls = cls + ' ' + this.classes.today; } // adds class for today

			if (hilited.contains(day)) { cls = cls + ' ' + this.classes.hilite; } // adds class if hilited

			td.addClass(cls);

			if (valid.contains(day)) { // if it's a valid - clickable - day we add interaction
				td.setProperty('title', this.format(date, 'D M jS Y'));
				
				td.addEvents({
					'click': function(td, day, cal) { 
						this.clicked(td, day, cal); 
					}.pass([td, day, cal], this),
					'mouseover': function(td, cls) { 
						td.addClass(cls); 
					}.pass([td, this.classes.hover]),
					'mouseout': function(td, cls) { 
						td.removeClass(cls); 
					}.pass([td, this.classes.hover])
				});
			}

			// pad calendar with last days of prev month and first days of next month
			if (day < 1) { day = prev + day; }
			else if (day > last) { day = day - last; }

			td.appendText(day);
		}
	},


	// element: helper function
	// @param el (string) element id
	// @param f (string) format string
	// @param cal (obj)

	element: function(el, f, cal) {
		if ($type(f) == 'object') { // in the case of multiple inputs per calendar
			for (var i in f) { 
				if (!this.element(i, f[i], cal)) { return false; }		
			}
			
			return true;
		}

		el = $(el);

		if (!el) { return false; }
		
		el.format = f;
		
		if (el.get('tag') == 'select') { // select elements allow the user to manually set the date via select option
			el.addEvent('change', function(cal) { this.changed(cal); }.pass(cal, this));
		}
		else { // input (type text) elements restrict the user to only setting the date via the calendar
			el.readOnly = true;
			el.addEvent('focus', function(cal) { this.toggle(cal); }.pass(cal, this));
		}

		cal.els.push(el);

		return true;
	},


	// format: formats a date object according to passed in instructions
	// @param date (obj)
	// @param f (string) any combination of punctuation / separators and d, j, D, l, S, m, n, F, M, y, Y
	// @returns string

	format: function(date, format) {
		var str = '';
		
		if (date) {
			var j = date.getDate(); // 1 - 31
      var w = date.getDay(); // 0 - 6
			var l = this.options.days[w]; // Sunday - Saturday
			var n = date.getMonth() + 1; // 1 - 12
			var f = this.options.months[n - 1]; // January - December
			var y = date.getFullYear() + ''; // 19xx - 20xx
			
			for (var i = 0, len = format.length; i < len; i++) {
				var cha = format.charAt(i); // format char
				
				switch(cha) {
					// year cases
					case 'y': // xx - xx
						y = y.substr(2);
					case 'Y': // 19xx - 20xx
						str += y;
						break;
	
					// month cases
					case 'm': // 01 - 12
						if (n < 10) { n = '0' + n; }
					case 'n': // 1 - 12
						str += n;
						break;
	
					case 'M': // Jan - Dec
						f = f.substr(0, 3);
					case 'F': // January - December
						str += f;
						break;
	
					// day cases
					case 'd': // 01 - 31
						if (j < 10) { j = '0' + j; }
					case 'j': // 1 - 31
						str += j;
						break;
	
					case 'D': // Sun - Sat
						l = l.substr(0, 3);
					case 'l': // Sunday - Saturday
						str += l;
						break;
	
					case 'N': // 1 - 7
						w += 1;
					case 'w': // 0 - 6
						str += w;
						break;

					case 'S': // st, nd, rd or th (works well with j)
						if (j % 10 == 1 && j != '11') { str += 'st'; }
						else if (j % 10 == 2 && j != '12') { str += 'nd'; }
						else if (j % 10 == 3 && j != '13') { str += 'rd'; }
						else { str += 'th'; }
						break;
	
					default:
						str += cha;
				}
			}
		}

	  return str; //  return format with values replaced
	},


	// navigate: calendar navigation
	// @param cal (obj)
	// @param type (str) m or y for month or year
	// @param n (int) + or - for next or prev

	navigate: function(cal, type, n) {
		switch (type) {
			case 'm': // month
					if ($type(cal.months) == 'array') {
						var i = cal.months.indexOf(cal.month) + n; // index of current month
						
						if (i < 0 || i == cal.months.length) { // out of range
							if (this.options.navigation == 1) { // if type 1 nav we'll need to increment the year
								this.navigate(cal, 'y', n);		
							}
		
							i = (i < 0) ? cal.months.length - 1 : 0;
						}

						cal.month = cal.months[i];
					}
					else { 
						var i = cal.month + n;
		
						if (i < 0 || i == 12) {
							if (this.options.navigation == 1) {
								this.navigate(cal, 'y', n);	
							}
		
							i = (i < 0) ? 11 : 0;
						}
						
						cal.month = i;
					}		
					break;

				case 'y': // year
					if ($type(cal.years) == 'array') {
						var i = cal.years.indexOf(cal.year) + n;

						cal.year = cal.years[i]; 
					}
					else { 
						cal.year += n;
					}						
					break;		
		}

		$extend(cal, this.values(cal));

		if ($type(cal.months) == 'array') { // if the calendar has a months select
			var i = cal.months.indexOf(cal.month); // and make sure the curr months exists for the new year

			if (i < 0) { cal.month = cal.months[0]; } // otherwise we'll reset the month
		}


		this.display(cal);
	},


	// read: compiles cal value based on array of inputs passed in
	// @param cal (obj)
	// @returns date (obj) or (null)

	read: function(cal) {
		var arr = [null, null, null];

		cal.els.each(function(el) {
			// returns an array which may contain empty values
			var values = this.unformat(el.value, el.format);
			
			values.each(function(val, i) { 
				if ($type(val) == 'number') { arr[i] = val; }
			}); 
		}, this);

		// we can update the cals month and year values
		if ($type(arr[0]) == 'number') { cal.year = arr[0]; }
		if ($type(arr[1]) == 'number') { cal.month = arr[1]; }

		var val = null;

		if (arr.every(function(i) { return $type(i) == 'number'; })) { // if valid date
			var last = new Date(arr[0], arr[1] + 1, 0).getDate(); // last day of month

			if (arr[2] > last) { arr[2] = last; } // make sure we stay within the month (ex in case default day of select is 31 and month is feb)
			
			val = new Date(arr[0], arr[1], arr[2]);
		}

		return (cal.val == val) ? null : val; // if new date matches old return null (same date clicked twice = disable)
	},

	
	// rebuild: rebuilds days + months selects
	// @param cal (obj)

	rebuild: function(cal) {
		cal.els.each(function(el) {			
			/*
			if (el.get('tag') == 'select' && el.format.test('^(F|m|M|n)$')) { // special case for months-only select
				if (!cal.options) { cal.options = el.clone(); } // clone a copy of months select
			
				var val = (cal.val) ? cal.val.getMonth() : el.value.toInt();

				el.empty(); // initialize select

				cal.months.each(function(month) {
					// create an option element
					var option = new Element('option', {
						'selected': (val == month),
						'value': this.format(new Date(1, month, 1), el.format);
					}).appendText(day).injectInside(el);
				}, this);
			}
			*/

			if (el.get('tag') == 'select' && el.format.test('^(d|j)$')) { // special case for days-only select
				var d = this.value(cal);

				if (!d) { d = el.value.toInt(); } // if the calendar doesn't have a set value, try to use value from select

				el.empty(); // initialize select

				cal.days.each(function(day) {
					// create an option element
					var option = new Element('option', {
						'selected': (d == day),
						'value': ((el.format == 'd' && day < 10) ? '0' + day : day)
					}).appendText(day).injectInside(el);
				}, this);
			}
		}, this); 
	},


	// sort: helper function for numerical sorting

	sort: function(a, b) {
		return a - b;
	},


	// toggle: show / hide calendar 
	// @param cal (obj)

	toggle: function(cal) {
		document.removeEvent('mousedown', this.fn); // always remove the current mousedown script first
			
		if (cal.visible) { // simply hide curr cal						
			cal.visible = false;
			cal.button.removeClass(this.classes.active); // active
			
			this.fx.start('opacity', 1, 0);
		}
		else { // otherwise show (may have to hide others)
			// hide cal on out-of-bounds click
			this.fn = function(e, cal) { 
				var e = new Event(e);
			
				var el = e.target;

				var stop = false;
				
				while (el != document.body && el.nodeType == 1) {
					if (el == this.calendar) { stop = true; }
					this.calendars.each(function(kal) {
						if (kal.button == el || kal.els.contains(el)) { stop = true; }
					});

					if (stop) { 
						e.stop();
						return false;
					}
					else { el = el.parentNode; }
				}
				
				this.toggle(cal);
			}.create({ 'arguments': cal, 'bind': this, 'event': true });				

			document.addEvent('mousedown', this.fn);

			this.calendars.each(function(kal) {
				if (kal == cal) {
					kal.visible = true;
					kal.button.addClass(this.classes.active); // css c-icon-active
				}
				else {
					kal.visible = false;
					kal.button.removeClass(this.classes.active); // css c-icon-active
				}
			}, this);
			
			var size = window.getScrollSize();
			
			var coord = cal.button.getCoordinates();

			var x = coord.right + this.options.tweak.x;
			var y = coord.top + this.options.tweak.y;

			// make sure the calendar doesn't open off screen
			if (!this.calendar.coord) { this.calendar.coord = this.calendar.getCoordinates(); }

			if (x + this.calendar.coord.width > size.x) { x -= (x + this.calendar.coord.width - size.x); }
			if (y + this.calendar.coord.height > size.y) { y -= (y + this.calendar.coord.height - size.y); }
			
			this.calendar.setStyles({ left: x + 'px', top: y + 'px' });

			if (window.ie6) { 
				this.iframe.setStyles({ height: this.calendar.coord.height + 'px', left: x + 'px', top: y + 'px', width: this.calendar.coord.width + 'px' }); 
			}

			this.display(cal);
			
			this.fx.start('opacity', 0, 1);
		}
	},


	// unformat: takes a value from an input and parses the d, m and y elements
	// @param val (string)
	// @param f (string) any combination of punctuation / separators and d, j, D, l, S, m, n, F, M, y, Y
	// @returns array
	
	unformat: function(val, f) {
		f = f.escapeRegExp();
		
		var re = {
			d: '([0-9]{2})',
			j: '([0-9]{1,2})',
			D: '(' + this.options.days.map(function(day) { return day.substr(0, 3); }).join('|') + ')',					
			l: '(' + this.options.days.join('|') + ')',
			S: '(st|nd|rd|th)',
			F: '(' + this.options.months.join('|') + ')',
			m: '([0-9]{2})',
			M: '(' + this.options.months.map(function(month) { return month.substr(0, 3); }).join('|') + ')',					
			n: '([0-9]{1,2})',
			Y: '([0-9]{4})',
			y: '([0-9]{2})'
		}

		var arr = []; // array of indexes

		var g = '';

		// convert our format string to regexp
		for (var i = 0; i < f.length; i++) {
			var c = f.charAt(i);
			
			if (re[c]) {
				arr.push(c);

				g += re[c];
			}
			else {
				g += c;
			}
		}

		// match against date
		var matches = val.match('^' + g + '$');
		
		var dates = new Array(3);

		if (matches) {
			matches = matches.slice(1); // remove first match which is the date

			arr.each(function(c, i) {
				i = matches[i];
				
				switch(c) {
					// year cases
					case 'y':
						i = '19' + i; // 2 digit year assumes 19th century (same as JS)
					case 'Y':
						dates[0] = i.toInt();
						break;

					// month cases
					case 'F':
						i = i.substr(0, 3);
					case 'M':
						i = this.options.months.map(function(month) { return month.substr(0, 3); }).indexOf(i) + 1;
					case 'm':
					case 'n':
						dates[1] = i.toInt() - 1;
						break;

					// day cases
					case 'd':
					case 'j':
						dates[2] = i.toInt();
						break;
				}
			}, this);
		}

		return dates;
	},


	// value: returns day value of calendar if set
	// @param cal (obj)
	// @returns day (int) or null

	value: function(cal) {
		var day = null;

		if (cal.val) {
			if (cal.year == cal.val.getFullYear() && cal.month == cal.val.getMonth()) { day = cal.val.getDate(); }
		}

		return day;
	},
	

	// values: returns the years, months (for curr year) and days (for curr month and year) for the calendar
	// @param cal (obj)
	// @returns obj	

	values: function(cal) {
		var years, months, days;

		cal.els.each(function(el) {	
			if (el.get('tag') == 'select') {		
				if (el.format.test('(y|Y)')) { // search for a year select
					years = [];

					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);
	
						if (!years.contains(values[0])) { years.push(values[0]); } // add to years array
					}, this);
	
					years.sort(this.sort);
				}
	
				if (el.format.test('(F|m|M|n)')) { // search for a month select
					months = []; // 0 - 11 should be

					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);
	
						if ($type(values[0]) != 'number' || values[0] == cal.year) { // if it's a year / month combo for curr year, or simply a month select
							if (!months.contains(values[1])) { months.push(values[1]); } // add to months array
						}
					}, this);
	
					months.sort(this.sort);
				}
				
				if (el.format.test('(d|j)') && !el.format.test('^(d|j)$')) { // search for a day select, but NOT a days only select
					days = []; // 1 - 31
					
					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);

						// in the special case of days we dont want the value if its a days only select
						// otherwise that will screw up the options rebuilding
						// we will take the values if they are exact dates though
						if (values[0] == cal.year && values[1] == cal.month) {
							if (!days.contains(values[2])) { days.push(values[2]); } // add to days array
						}
					}, this);
				}
			}
		}, this);
		
		// we start with what would be the first and last days were there no restrictions
		var first = 1;
		var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of the month
		
		// if we're in an out of bounds year
		if (cal.year == cal.start.getFullYear()) {
			// in the special case of improved navigation but no months array, we'll need to construct one
			if (months == null && this.options.navigation == 2) {
				months = [];
				
				for (var i = 0; i < 12; i ++) { 
					if (i >= cal.start.getMonth()) { months.push(i); } 
				}
			}
			
			// if we're in an out of bounds month
			if (cal.month == cal.start.getMonth()) { 
				first = cal.start.getDate(); // first day equals day of bound
			}
		}		
		if (cal.year == cal.end.getFullYear()) {
			// in the special case of improved navigation but no months array, we'll need to construct one
			if (months == null && this.options.navigation == 2) {
				months = [];
				
				for (var i = 0; i < 12; i ++) { 
					if (i <= cal.end.getMonth()) { months.push(i); } 
				}
			}

			if (cal.month == cal.end.getMonth()) { 
				last = cal.end.getDate(); // last day equals day of bound
			}
		}

		// let's get our invalid days
		var blocked = this.blocked(cal);

		// finally we can prepare all the valid days in a neat little array
		if ($type(days) == 'array') { // somewhere there was a days select
			days = days.filter(function(day) {
				if (day >= first && day <= last && !blocked.contains(day)) { return day; }
			});
		}
		else { // no days select we'll need to construct a valid days array
			days = [];
			
			for (var i = first; i <= last; i++) { 
				if (!blocked.contains(i)) { days.push(i); }
			}
		}		

		days.sort(this.sort); // sorting our days will give us first and last of month

		return { 'days': days, 'months': months, 'years': years };
	},


	// write: sets calendars value to form elements
	// @param cal (obj)

	write: function(cal) {
		this.rebuild(cal);	 // in the case of options, we'll need to make sure we have the correct number of days available
		
		cal.els.each(function(el) {	// then we can set the value to the field
			el.value = this.format(cal.val, el.format); 		
		}, this);
	}
});

Calendar.implement(new Events, new Options);

/*
   SoundManager 2: Javascript Sound for the Web
   --------------------------------------------
   http://schillmania.com/projects/soundmanager2/

   Copyright (c) 2008, Scott Schiller. All rights reserved.
   Code licensed under the BSD License:
   http://schillmania.com/projects/soundmanager2/license.txt

   V2.92a.20081224
*/
var soundManager=null;function SoundManager(b,a){this.flashVersion=8;this.debugMode=false;this.useConsole=true;this.consoleOnly=false;this.waitForWindowLoad=false;this.nullURL="null.mp3";this.allowPolling=true;this.useMovieStar=false;this.useHighPerformance=true;this.bgColor="#ffffff";this.defaultOptions={autoLoad:false,stream:true,autoPlay:false,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onstop:null,onfinish:null,onbeforefinish:null,onbeforefinishtime:5000,onbeforefinishcomplete:null,onjustbeforefinish:null,onjustbeforefinishtime:200,multiShot:true,position:null,pan:0,volume:100};this.flash9Options={isMovieStar:null,usePeakData:false,useWaveformData:false,useEQData:false};this.movieStarOptions={onmetadata:null,useVideo:false};var f=null;var e=this;this.version=null;this.versionNumber="V2.92a.20081224";this.movieURL=null;this.url=null;this.altURL=null;this.swfLoaded=false;this.enabled=false;this.o=null;this.id=(a||"sm2movie");this.oMC=null;this.sounds={};this.soundIDs=[];this.muted=false;this.isIE=(navigator.userAgent.match(/MSIE/i));this.isSafari=(navigator.userAgent.match(/safari/i));this.isGecko=(navigator.userAgent.match(/gecko/i));this.debugID="soundmanager-debug";this._debugOpen=true;this._didAppend=false;this._appendSuccess=false;this._didInit=false;this._disabled=false;this._windowLoaded=false;this._hasConsole=(typeof console!="undefined"&&typeof console.log!="undefined");this._debugLevels=["log","info","warn","error"];this._defaultFlashVersion=8;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.netStreamTypes=["aac","flv","mov","mp4","m4v","f4v","m4a","mp4v","3gp","3g2"];this.netStreamPattern=new RegExp("\\.("+this.netStreamTypes.join("|")+")(\\?.*)?$","i");this.filePattern=null;this.features={peakData:false,waveformData:false,eqData:false};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local + internet access)"},description:null,noRemote:null,noLocal:null};this._setVersionInfo=function(){if(e.flashVersion!=8&&e.flashVersion!=9){alert('soundManager.flashVersion must be 8 or 9. "'+e.flashVersion+'" is invalid. Reverting to '+e._defaultFlashVersion+".");e.flashVersion=e._defaultFlashVersion}e.version=e.versionNumber+(e.flashVersion==9?" (AS3/Flash 9)":" (AS2/Flash 8)");if(e.flashVersion>8){e.defaultOptions=e._mergeObjects(e.defaultOptions,e.flash9Options)}if(e.flashVersion>8&&e.useMovieStar){e.defaultOptions=e._mergeObjects(e.defaultOptions,e.movieStarOptions);e.filePatterns.flash9=new RegExp("\\.(mp3|"+e.netStreamTypes.join("|")+")(\\?.*)?$","i")}else{e.useMovieStar=false}e.filePattern=e.filePatterns[(e.flashVersion!=8?"flash9":"flash8")];e.movieURL=(e.flashVersion==8?"soundmanager2.swf":"soundmanager2_flash9.swf");e.features.peakData=e.features.waveformData=e.features.eqData=(e.flashVersion==9)};this._overHTTP=(document.location?document.location.protocol.match(/http/i):null);this._waitingforEI=false;this._initPending=false;this._tryInitOnFocus=(this.isSafari&&typeof document.hasFocus=="undefined");this._isFocused=(typeof document.hasFocus!="undefined"?document.hasFocus():null);this._okToDisable=!this._tryInitOnFocus;this.useAltURL=!this._overHTTP;var d="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html";this.supported=function(){return(e._didInit&&!e._disabled)};this.getMovie=function(g){return e.isIE?window[g]:(e.isSafari?document.getElementById(g)||document[g]:document.getElementById(g))};this.loadFromXML=function(g){try{e.o._loadFromXML(g)}catch(h){e._failSafely();return true}};this.createSound=function(h){if(!e._didInit){throw new Error("soundManager.createSound(): Not loaded yet - wait for soundManager.onload() before calling sound-related methods")}if(arguments.length==2){h={id:arguments[0],url:arguments[1]}}var i=e._mergeObjects(h);var g=i;if(e._idCheck(g.id,true)){return e.sounds[g.id]}if(e.flashVersion>8&&e.useMovieStar){if(g.isMovieStar===null){g.isMovieStar=(g.url.match(e.netStreamPattern)?true:false)}if(g.isMovieStar&&(g.usePeakData||g.useWaveformData||g.useEQData)){g.usePeakData=false;g.useWaveformData=false;g.useEQData=false}}e.sounds[g.id]=new f(g);e.soundIDs[e.soundIDs.length]=g.id;if(e.flashVersion==8){e.o._createSound(g.id,g.onjustbeforefinishtime)}else{e.o._createSound(g.id,g.url,g.onjustbeforefinishtime,g.usePeakData,g.useWaveformData,g.useEQData,g.isMovieStar,(g.isMovieStar?g.useVideo:false))}if(g.autoLoad||g.autoPlay){if(e.sounds[g.id]){e.sounds[g.id].load(g)}}if(g.autoPlay){if(e.flashVersion==8){e.sounds[g.id].playState=1}else{e.sounds[g.id].play()}}return e.sounds[g.id]};this.createVideo=function(g){if(arguments.length==2){g={id:arguments[0],url:arguments[1]}}if(e.flashVersion>=9){g.isMovieStar=true;g.useVideo=true}else{return false}return e.createSound(g)};this.destroySound=function(h,g){if(!e._idCheck(h)){return false}for(var j=0;j<e.soundIDs.length;j++){if(e.soundIDs[j]==h){e.soundIDs.splice(j,1);continue}}e.sounds[h].unload();if(!g){e.sounds[h].destruct()}delete e.sounds[h]};this.destroyVideo=this.destroySound;this.load=function(g,h){if(!e._idCheck(g)){return false}e.sounds[g].load(h)};this.unload=function(g){if(!e._idCheck(g)){return false}e.sounds[g].unload()};this.play=function(g,h){if(!e._idCheck(g)){if(typeof h!="Object"){h={url:h}}if(h&&h.url){h.id=g;e.createSound(h)}else{return false}}e.sounds[g].play(h)};this.start=this.play;this.setPosition=function(g,h){if(!e._idCheck(g)){return false}e.sounds[g].setPosition(h)};this.stop=function(g){if(!e._idCheck(g)){return false}e.sounds[g].stop()};this.stopAll=function(){for(var g in e.sounds){if(e.sounds[g] instanceof f){e.sounds[g].stop()}}};this.pause=function(g){if(!e._idCheck(g)){return false}e.sounds[g].pause()};this.pauseAll=function(){for(var g=e.soundIDs.length;g--;){e.sounds[e.soundIDs[g]].pause()}};this.resume=function(g){if(!e._idCheck(g)){return false}e.sounds[g].resume()};this.resumeAll=function(){for(var g=e.soundIDs.length;g--;){e.sounds[e.soundIDs[g]].resume()}};this.togglePause=function(g){if(!e._idCheck(g)){return false}e.sounds[g].togglePause()};this.setPan=function(g,h){if(!e._idCheck(g)){return false}e.sounds[g].setPan(h)};this.setVolume=function(h,g){if(!e._idCheck(h)){return false}e.sounds[h].setVolume(g)};this.mute=function(g){if(typeof g!="string"){g=null}if(!g){for(var h=e.soundIDs.length;h--;){e.sounds[e.soundIDs[h]].mute()}e.muted=true}else{if(!e._idCheck(g)){return false}e.sounds[g].mute()}};this.muteAll=function(){e.mute()};this.unmute=function(g){if(typeof g!="string"){g=null}if(!g){for(var h=e.soundIDs.length;h--;){e.sounds[e.soundIDs[h]].unmute()}e.muted=false}else{if(!e._idCheck(g)){return false}e.sounds[g].unmute()}};this.unmuteAll=function(){e.unmute()};this.setPolling=function(g){if(!e.o||!e.allowPolling){return false}e.o._setPolling(g)};this.disable=function(g){if(e._disabled){return false}e._disabled=true;for(var h=e.soundIDs.length;h--;){e._disableObject(e.sounds[e.soundIDs[h]])}e.initComplete();e._disableObject(e)};this.canPlayURL=function(g){return(g?(g.match(e.filePattern)?true:false):null)};this.getSoundById=function(h,i){if(!h){throw new Error("SoundManager.getSoundById(): sID is null/undefined")}var g=e.sounds[h];return g};this.onload=function(){soundManager._wD("<em>Warning</em>: soundManager.onload() is undefined.",2)};this.onerror=function(){};this._idCheck=this.getSoundById;var c=function(){return false};c._protected=true;this._disableObject=function(h){for(var g in h){if(typeof h[g]=="function"&&typeof h[g]._protected=="undefined"){h[g]=c}}g=null};this._failSafely=function(){if(!e._disabled){e.disable()}};this._normalizeMovieURL=function(g){var h=null;if(g){if(g.match(/\.swf(\?.*)?$/i)){h=g.substr(g.toLowerCase().lastIndexOf(".swf?")+4);if(h){return g}}else{if(g.lastIndexOf("/")!=g.length-1){g=g+"/"}}}return(g&&g.lastIndexOf("/")!=-1?g.substr(0,g.lastIndexOf("/")+1):"./")+e.movieURL};this._getDocument=function(){return(document.body?document.body:(document.documentElement?document.documentElement:document.getElementsByTagName("div")[0]))};this._getDocument._protected=true;this._createMovie=function(m,k){if(e._didAppend&&e._appendSuccess){return false}if(window.location.href.indexOf("debug=1")+1){e.debugMode=true}e._didAppend=true;e._setVersionInfo();var q=(k?k:e.url);var j=(e.altURL?e.altURL:q);e.url=e._normalizeMovieURL(e._overHTTP?q:j);k=e.url;var l=null;if(e.useHighPerformance&&navigator.userAgent.match(/firefox\/2/i)){l="Warning: disabling highPerformance, incompatible with Firefox 2.x";e.useHighPerformance=false}if(e.useHighPerformance&&e.useMovieStar){l="Warning: disabling highPerformance, not applicable with movieStar mode on";e.useHighPerformance=false}var p={name:m,id:m,src:k,width:"100%",height:"100%",quality:"high",allowScriptAccess:"always",bgcolor:e.bgColor,pluginspage:"http://www.macromedia.com/go/getflashplayer",type:"application/x-shockwave-flash"};var t={id:m,data:k,type:"application/x-shockwave-flash",width:"100%",height:"100%"};var n={movie:k,AllowScriptAccess:"always",quality:"high",bgcolor:e.bgColor};if(e.useHighPerformance&&!e.useMovieStar){p.wmode="transparent";n.wmode="transparent"}var i=null;var o=null;if(e.isIE){i=document.createElement("div");var g='<object id="'+m+'" data="'+k+'" type="application/x-shockwave-flash" width="100%" height="100%"><param name="movie" value="'+k+'" /><param name="AllowScriptAccess" value="always" /><param name="quality" value="high" />'+(e.useHighPerformance&&!e.useMovieStar?'<param name="wmode" value="transparent" /> ':"")+'<param name="bgcolor" value="'+e.bgColor+'" /><!-- --></object>'}else{i=document.createElement("embed");for(o in p){if(p.hasOwnProperty(o)){i.setAttribute(o,p[o])}}}var h=e._getDocument();if(h){e.oMC=document.getElementById("sm2-container")?document.getElementById("sm2-container"):document.createElement("div");if(!e.oMC.id){e.oMC.id="sm2-container";e.oMC.className="movieContainer";var y=null;if(e.useHighPerformance){y={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",zIndex:-1}}else{y={position:"absolute",width:"1px",height:"1px",bottom:"0px",left:"0px"}}var v=null;for(v in y){if(y.hasOwnProperty(v)){e.oMC.style[v]=y[v]}}try{if(!e.isIE){e.oMC.appendChild(i)}h.appendChild(e.oMC);if(e.isIE){e.oMC.innerHTML=g}e._appendSuccess=true}catch(r){throw new Error(appXHTML)}}else{e.oMC.appendChild(i);if(e.isIE){e.oMC.innerHTML=g}e._appendSuccess=true}if(!document.getElementById(e.debugID)&&((!e._hasConsole||!e.useConsole)||(e.useConsole&&e._hasConsole&&!e.consoleOnly))){var w=document.createElement("div");w.id=e.debugID;w.style.display=(e.debugMode?"block":"none");if(e.debugMode){try{h.appendChild(oD)}catch(u){throw new Error(appXHTML)}}h.appendChild(w)}h=null}};this._writeDebug=function(g,i,h){};this._writeDebug._protected=true;this._wD=this._writeDebug;this._wDAlert=function(g){};this._toggleDebug=function(){};this._toggleDebug._protected=true;this._debug=function(){};this._mergeObjects=function(h,g){var l={};for(var j in h){if(h.hasOwnProperty(j)){l[j]=h[j]}}var k=(typeof g=="undefined"?e.defaultOptions:g);for(var m in k){if(k.hasOwnProperty(m)&&typeof l[m]=="undefined"){l[m]=k[m]}}return l};this.createMovie=function(g){if(g){e.url=g}e._initMovie()};this.go=this.createMovie;this._initMovie=function(){if(e.o){return false}e.o=e.getMovie(e.id);if(!e.o){e._createMovie(e.id,e.url);e.o=e.getMovie(e.id)}};this.waitForExternalInterface=function(){if(e._waitingForEI){return false}e._waitingForEI=true;if(e._tryInitOnFocus&&!e._isFocused){return false}setTimeout(function(){if(!e._didInit&&e._okToDisable){e._failSafely()}},750)};this.handleFocus=function(){if(e._isFocused||!e._tryInitOnFocus){return true}e._okToDisable=true;e._isFocused=true;if(e._tryInitOnFocus){window.removeEventListener("mousemove",e.handleFocus,false)}e._waitingForEI=false;setTimeout(e.waitForExternalInterface,500);if(window.removeEventListener){window.removeEventListener("focus",e.handleFocus,false)}else{if(window.detachEvent){window.detachEvent("onfocus",e.handleFocus)}}};this.initComplete=function(){if(e._didInit){return false}e._didInit=true;if(e._disabled){e.onerror.apply(window);return false}if(e.waitForWindowLoad&&!e._windowLoaded){if(window.addEventListener){window.addEventListener("load",e.initUserOnload,false)}else{if(window.attachEvent){window.attachEvent("onload",e.initUserOnload)}}return false}else{e.initUserOnload()}};this.initUserOnload=function(){e.onload.apply(window)};this.init=function(){e._initMovie();if(e._didInit){return false}if(window.removeEventListener){window.removeEventListener("load",e.beginDelayedInit,false)}else{if(window.detachEvent){window.detachEvent("onload",e.beginDelayedInit)}}try{e.o._externalInterfaceTest(false);if(!e.allowPolling){}e.setPolling(true);if(!e.debugMode){e.o._disableDebug()}e.enabled=true}catch(g){e._failSafely();e.initComplete();return false}e.initComplete()};this.beginDelayedInit=function(){e._windowLoaded=true;setTimeout(e.waitForExternalInterface,500);setTimeout(e.beginInit,20)};this.beginInit=function(){if(e._initPending){return false}e.createMovie();e._initMovie();e._initPending=true;return true};this.domContentLoaded=function(){if(document.removeEventListener){document.removeEventListener("DOMContentLoaded",e.domContentLoaded,false)}e.go()};this._externalInterfaceOK=function(){if(e.swfLoaded){return false}e.swfLoaded=true;e._tryInitOnFocus=false;if(e.isIE){setTimeout(e.init,100)}else{e.init()}};this._setSandboxType=function(g){var h=e.sandbox;h.type=g;h.description=h.types[(typeof h.types[g]!="undefined"?g:"unknown")];if(h.type=="localWithFile"){h.noRemote=true;h.noLocal=false}else{if(h.type=="localWithNetwork"){h.noRemote=false;h.noLocal=true}else{if(h.type=="localTrusted"){h.noRemote=false;h.noLocal=false}}}};this.destruct=function(){e.disable(true)};f=function(g){var h=this;this.sID=g.id;this.url=g.url;this.options=e._mergeObjects(g);this.instanceOptions=this.options;this._iO=this.instanceOptions;this._debug=function(){if(e.debugMode){var k=null;var m=[];var j=null;var l=null;var i=64;for(k in h.options){if(h.options[k]!==null){if(h.options[k] instanceof Function){j=h.options[k].toString();j=j.replace(/\s\s+/g," ");l=j.indexOf("{");m[m.length]=" "+k+": {"+j.substr(l+1,(Math.min(Math.max(j.indexOf("\n")-1,i),i))).replace(/\n/g,"")+"... }"}else{m[m.length]=" "+k+": "+h.options[k]}}}}};this._debug();this.id3={};this.resetProperties=function(i){h.bytesLoaded=null;h.bytesTotal=null;h.position=null;h.duration=null;h.durationEstimate=null;h.loaded=false;h.playState=0;h.paused=false;h.readyState=0;h.muted=false;h.didBeforeFinish=false;h.didJustBeforeFinish=false;h.instanceOptions={};h.instanceCount=0;h.peakData={left:0,right:0};h.waveformData=[];h.eqData=[]};h.resetProperties();this.load=function(i){if(typeof i!="undefined"){h._iO=e._mergeObjects(i);h.instanceOptions=h._iO}else{i=h.options;h._iO=i;h.instanceOptions=h._iO}if(typeof h._iO.url=="undefined"){h._iO.url=h.url}if(h._iO.url==h.url&&h.readyState!==0&&h.readyState!=2){return false}h.loaded=false;h.readyState=1;h.playState=(i.autoPlay?1:0);try{if(e.flashVersion==8){e.o._load(h.sID,h._iO.url,h._iO.stream,h._iO.autoPlay,(h._iO.whileloading?1:0))}else{e.o._load(h.sID,h._iO.url,h._iO.stream?true:false,h._iO.autoPlay?true:false);if(h._iO.isMovieStar&&h._iO.autoLoad&&!h._iO.autoPlay){h.pause()}}}catch(j){e.onerror();e.disable()}};this.unload=function(){if(h.readyState!==0){if(h.readyState!=2){h.setPosition(0,true)}e.o._unload(h.sID,e.nullURL);h.resetProperties()}};this.destruct=function(){e.o._destroySound(h.sID);e.destroySound(h.sID,true)};this.play=function(j){if(!j){j={}}h._iO=e._mergeObjects(j,h._iO);h._iO=e._mergeObjects(h._iO,h.options);h.instanceOptions=h._iO;if(h.playState==1){var i=h._iO.multiShot;if(!i){return false}else{}}if(!h.loaded){if(h.readyState===0){h._iO.stream=true;h._iO.autoPlay=true;h.load(h._iO)}else{if(h.readyState==2){return false}else{}}}else{}if(h.paused){h.resume()}else{h.playState=1;if(!h.instanceCount||e.flashVersion==9){h.instanceCount++}h.position=(typeof h._iO.position!="undefined"&&!isNaN(h._iO.position)?h._iO.position:0);if(h._iO.onplay){h._iO.onplay.apply(h)}h.setVolume(h._iO.volume);h.setPan(h._iO.pan);e.o._start(h.sID,h._iO.loop||1,(e.flashVersion==9?h.position:h.position/1000))}};this.start=this.play;this.stop=function(i){if(h.playState==1){h.playState=0;h.paused=false;if(h._iO.onstop){h._iO.onstop.apply(h)}e.o._stop(h.sID,i);h.instanceCount=0;h._iO={}}};this.setPosition=function(j,i){if(typeof j=="undefined"){j=0}var k=Math.min(h.duration,Math.max(j,0));h._iO.position=k;e.o._setPosition(h.sID,(e.flashVersion==9?h._iO.position:h._iO.position/1000),(h.paused||!h.playState))};this.pause=function(){if(h.paused||h.playState===0){return false}h.paused=true;e.o._pause(h.sID);if(h._iO.onpause){h._iO.onpause.apply(h)}};this.resume=function(){if(!h.paused||h.playState===0){return false}h.paused=false;e.o._pause(h.sID);if(h._iO.onresume){h._iO.onresume.apply(h)}};this.togglePause=function(){if(!h.playState){h.play({position:(e.flashVersion==9?h.position:h.position/1000)});return false}if(h.paused){h.resume()}else{h.pause()}};this.setPan=function(i){if(typeof i=="undefined"){i=0}e.o._setPan(h.sID,i);h._iO.pan=i};this.setVolume=function(i){if(typeof i=="undefined"){i=100}e.o._setVolume(h.sID,(e.muted&&!h.muted)||h.muted?0:i);h._iO.volume=i};this.mute=function(){h.muted=true;e.o._setVolume(h.sID,0)};this.unmute=function(){h.muted=false;e.o._setVolume(h.sID,typeof h._iO.volume!="undefined"?h._iO.volume:h.options.volume)};this._whileloading=function(i,j,k){if(!h._iO.isMovieStar){h.bytesLoaded=i;h.bytesTotal=j;h.duration=Math.floor(k);h.durationEstimate=parseInt((h.bytesTotal/h.bytesLoaded)*h.duration,10);if(h.readyState!=3&&h._iO.whileloading){h._iO.whileloading.apply(h)}}else{h.bytesLoaded=i;h.bytesTotal=j;h.duration=Math.floor(k);h.durationEstimate=h.duration;if(h.readyState!=3&&h._iO.whileloading){h._iO.whileloading.apply(h)}}};this._onid3=function(n,k){var o=[];for(var m=0,l=n.length;m<l;m++){o[n[m]]=k[m]}h.id3=e._mergeObjects(h.id3,o);if(h._iO.onid3){h._iO.onid3.apply(h)}};this._whileplaying=function(j,k,i,l){if(isNaN(j)||j===null){return false}h.position=j;if(h._iO.usePeakData&&typeof k!="undefined"&&k){h.peakData={left:k.leftPeak,right:k.rightPeak}}if(h._iO.useWaveformData&&typeof i!="undefined"&&i){h.waveformData=i}if(h._iO.useEQData&&typeof l!="undefined"&&l){h.eqData=l}if(h.playState==1){if(h._iO.whileplaying){h._iO.whileplaying.apply(h)}if(h.loaded&&h._iO.onbeforefinish&&h._iO.onbeforefinishtime&&!h.didBeforeFinish&&h.duration-h.position<=h._iO.onbeforefinishtime){h._onbeforefinish()}}};this._onload=function(i){i=(i==1?true:false);h.loaded=i;h.readyState=i?3:2;if(h._iO.onload){h._iO.onload.apply(h)}};this._onbeforefinish=function(){if(!h.didBeforeFinish){h.didBeforeFinish=true;if(h._iO.onbeforefinish){h._iO.onbeforefinish.apply(h)}}};this._onjustbeforefinish=function(i){if(!h.didJustBeforeFinish){h.didJustBeforeFinish=true;if(h._iO.onjustbeforefinish){h._iO.onjustbeforefinish.apply(h)}}};this._onfinish=function(){if(h._iO.onbeforefinishcomplete){h._iO.onbeforefinishcomplete.apply(h)}h.didBeforeFinish=false;h.didJustBeforeFinish=false;if(h.instanceCount){h.instanceCount--;if(!h.instanceCount){h.playState=0;h.paused=false;h.instanceCount=0;h.instanceOptions={};if(h._iO.onfinish){h._iO.onfinish.apply(h)}}}else{}};this._onmetadata=function(i){if(!i.width&&!i.height){i.width=320;i.height=240}h.metadata=i;h.width=i.width;h.height=i.height;if(h._iO.onmetadata){h._iO.onmetadata.apply(h)}}};if(window.addEventListener){window.addEventListener("focus",e.handleFocus,false);window.addEventListener("load",e.beginDelayedInit,false);window.addEventListener("unload",e.destruct,false);if(e._tryInitOnFocus){window.addEventListener("mousemove",e.handleFocus,false)}}else{if(window.attachEvent){window.attachEvent("onfocus",e.handleFocus);window.attachEvent("onload",e.beginDelayedInit);window.attachEvent("unload",e.destruct)}else{soundManager.onerror();soundManager.disable()}}if(document.addEventListener){document.addEventListener("DOMContentLoaded",e.domContentLoaded,false)}} /* soundManager=new SoundManager(); */


window.addEvent('domready', function() {
	Element.implement({
		show: function() {
			this.setStyle('display','');
		},
		hide: function() {
			this.setStyle('display','none');
		},
		toggle: function() {
			if (this.getStyle('display') == 'none') {
				this.show();
			} else {
				this.hide();
			}
		}
	});
});

var MuxForm = new Class({
	initialize: function(e){
		this.form = $(e);
		this.submit = this.form.getElement("input[type=submit]")
		this.submitting = false;

		this.form.addEvent('submit', function(e) {
			if (! this.isValid()) new Event(e).stop();
		}.bind(this));
	},

  // prevent the form from being submitted more than once
  disableButtons: function() {
    // clear the form's handler
		this.form.oldonsubmit = this.form.onsubmit;
    this.form.onsubmit = function(){ return false; };

    // disable just the buttons
    this.form.getElements().filter(function(e) {
      return ['button', 'reset', 'submit'].contains(e.getProperty('tag'));
    }).each(function(e) {
			e.set('disabled', true);
    });

    this.showSpinner();
  },
  
  showSpinner: function() {
    this.form.getElement('img.loading').setStyle('display', 'inline');
  },

  refresh: function() {
    this.submit.set('disabled', this.isValid() ? false : true);
  },

  isValid: function() {
    if (this.submitting) return false;
    return this.validate().length == 0;
  },

  submit: function(form) {
    if (this.isValid()) {
			this.submitting = true;
      this.disableButtons(form);
      return true;
    } else {
      return false;
    }
  }
});

var MuxRequest = new Class({
	Extends: Request,

	RETRY_TIME: 3000, // milliseconds
	RETRY_COUNT: 4, // times to re-try a request

	// requestInfo: where to show loading / retry / error messages, if desired
	// errorMessage: what to show if retries fail, if desired
	initialize: function(args){
		this.requestCount = 0;
		this.requested = false;
		this.requesting = false;
		
		if (args.requestInfo) this.requestInfo = args.requestInfo;
		if (args.errorMessage) {
			this.errorMessage = ": " + args.errorMessage;
		} else {
			this.errorMessage = "";
		}
		
		if (args.onRequest) this.originalOnRequest = args.onRequest;
		if (args.onSuccess) this.originalOnSuccess = args.onSuccess;
		if (args.onFailure) this.originalOnFailure = args.onFailure;

		args.onRequest = this.onRequest.bind(this);
		args.onSuccess = this.onSuccess.bind(this);
		args.onFailure = this.onFailure.bind(this);
		
		this.parent(args);
	},
	
	sendWithRetry: function(options){
		this.send(options);
	},
	
	onRequest: function(){
		if (this.requestInfo && this.requestInfo.get("html") != "RETRYING")
			this.requestInfo.set("html", "&mdash;");

		this.requesting = true;
		if (this.originalOnRequest) this.originalOnRequest();
	},
	
	onSuccess: function(response){
		if (this.requestInfo) this.requestInfo.set("html", "");

		this.requested = true;
		this.requesting = false;
		if (this.originalOnSuccess) this.originalOnSuccess(response);
	},
	
	onFailure: function(xhr){
		if (this.requestCount >= this.RETRY_COUNT) {
			if (this.requestInfo) this.requestInfo.set("html", "ERROR" + this.errorMessage);
			this.requesting = false;
		} else {
			if (this.requestInfo) this.requestInfo.set("html", "RETRYING");
			this.requestCount += 1;
			setTimeout(this.send.bind(this), this.RETRY_TIME);
		}

		if (this.originalOnFailure) this.originalOnFailure(xhr);
	}
});



var Drawer = new Class({
	initialize: function(e) {
		this.drawer = $(e);
		if (!this.drawer) return;
		
		this._selected = 0;
		this._menu_items = this.drawer.getElements('li.drawer_menu_item');
		this._content_items = this.drawer.getElements('li.drawer_content_item');
		
		if(this._menu_items.length && this._content_items.length) {
			this.selectMenuItem(this._selected);
			
			this._menu_items.addEvent('mousedown',function(evt) {
				this.selectMenuItem(this._menu_items.indexOf(evt.target));
			}.bind(this));
		}

		this.slide = new Fx.Slide(this.drawer, {
			mode: 'vertical',
			duration: 300,
			transition: Fx.Transitions.Quint.easeOut
		}).hide();
		this.drawer.setStyle('display','block');
		this.slide.hide();

		this.drawer.getElement('div.drawer_handle').addEvent('click',this.toggle.bind(this));
	},
	
	selectMenuItem: function(index) {
		if(!index) index = 0;
		this._selected = index;
		this.menuRedraw();
	},
	
	menuRedraw: function() {
		this._menu_items.removeClass('drawer_menu_item_selected');
		this._menu_items[this._selected].addClass('drawer_menu_item_selected');		
		this._content_items.setStyle('display','none');
		this._content_items[this._selected].setStyle('display','');		
		this.drawer.getParent().setStyle('height','');
	},
	
	toggle: function() {
		this.slide.toggle();
		this.activateForm();
	},
	
	activateForm: function() {
		this.form = this.drawer.getElement('form');
		if (!this.form) return;

		var texts = this.form.getElements('input').filter(function(e){
			return e.getProperty('type') == 'text';
		});
		
		if (!texts[0]) return;
		texts[0].focus();
	}
});

var MComponentsDraggingFlagUglyHack = false;
var MComponents = {
	initSort: function(id){
		$$('.muxtape_component').each(function(el) {
			el.getElement('.overlay').set('tween',{duration: 100});
			
			el.addEvent('mouseover',function() {
				if(!MComponentsDraggingFlagUglyHack) {
					el.getElement('.overlay').tween('opacity',1);
				}
			});			
			el.addEvent('mouseout',function() {
				if(!MComponentsDraggingFlagUglyHack) {
					el.getElement('.overlay').tween('opacity',0);
				}
			});
		});
		
		var sortable = new Sortables($(id), {
			constrain: true,
			onStart: function() {
				MComponentsDraggingFlagUglyHack = true;
			},
			onComplete: function(el) {
				MComponentsDraggingFlagUglyHack = false;	
					
				var order = this.serialize(function(e) {
					return e.id.replace("component_", "");
				});
				new MuxRequest({
					url: "/manage/components/sort",
					requestInfo: this.requestInfo,
					errorMessage: "could not reorder"
				}).sendWithRetry({ data: {
					"order": order
				}});
			}
		});
	}
}

var EventList = {
	showUpcoming: function() {
		$('events_upcoming_link').setStyle("font-weight", "bold");
		$('events_all_link').setStyle("font-weight", "normal");
		$$('tr.is_past').each(function(e){ e.hide(); });
		return false;
	},

	showAll: function() {
		$('events_all_link').setStyle("font-weight", "bold");
		$('events_upcoming_link').setStyle("font-weight", "normal");
		$$('tr.is_past.event').each(function(e){ e.show(); });
		return false;
	}
}

var MessageForm = new Class({
	Extends: MuxForm,

	initialize: function(e){
		this.container = $(e);
		this.parent(this.container.getElement('form'));

		this.body = this.form.getElement("textarea[id$=_body]");
    this.body.addEvent('keyup', this.refresh.bind(this));

		this.refresh();
  },

  validate: function() {
    var arrErrors = [];
    
    if (this.body.get('value').length == 0) {
      arrErrors.push("Body is required.");
    }

    return arrErrors;
  }
});

var ReplaceSongFileForm = new Class({
	Extends: MuxForm,

	initialize: function(e){
		this.parent(e);

		this.song = this.form.getElement("input[id$=_song]");
    this.song.addEvent('change', this.refresh.bind(this));

    this.song.addEvent('change', this.onSongChange.bind(this));

		this.refresh();
  },

	onSongChange: function() {
		if (this.isValid()) {
			this.submit.show();
		} else {
			this.submit.hide();
		}
	},

  validate: function() {
    var arrErrors = [];
    
	  if (this.song.get('value').length == 0) {
	    arrErrors.push("Song file is required.");
	  }
		if (! this.song.get('value').match(/\.mp3$/)) {
			arrErrors.push("The song file must be an MP3.");
		}

    return arrErrors;
  }
});

var NewSongForm = new Class({
	Extends: MuxForm,

	initialize: function(e){
		this.parent(e);

/*		this.name = this.form.getElement("input[id$=_name]");*/
		this.song = this.form.getElement("input[id$=_song]");

/*    this.name.addEvent('keyup', this.refresh.bind(this));*/
    this.song.addEvent('change', this.refresh.bind(this));

    this.song.addEvent('change', this.onSongChange.bind(this));

		this.refresh();
  },

	onSongChange: function() {
		if (this.name.get('value') != "") return;
		
		var filename = this.song.get('value');
		filename = filename.replace(/\.mp3$/, "");
		filename = filename.replace(/^.*[\\\/]/, "");
		this.name.set('value', filename);
		this.name.focus();

		this.refresh();
	},

  validate: function() {
    var arrErrors = [];
    
/*    if (this.name.get('value').length == 0) {
      arrErrors.push("Name is required.");
    }
*/    if (this.song.get('value').length == 0) {
      arrErrors.push("Song file is required.");
    }
		if (! this.song.get('value').match(/\.mp3$/)) {
			arrErrors.push("The song file must be an MP3.");
		}

    return arrErrors;
  }
});

window.addEvent('domready', function() {
	e = $("flash_error");
	if (e && e.innerHTML == "error: not logged in") menuDrawer.toggle();

	e = $("flash_notice");
	if (e) (function(){
		var noticeSlide = new Fx.Slide(this, {
			mode:'vertical',
			duration: 400,
			transition: Fx.Transitions.Quint.easeOut
		}).slideOut();
	}).delay(5000, e);

	if (e = $('events_upcoming_link')) e.addEvent('click', function(){ EventList.showUpcoming(); });
	if (e = $('events_all_link')) e.addEvent('click', function(){ EventList.showAll(); });
});


var sortMuxtape = new Sortables("ul.muxtape_songs", {
	constrain: true,
	handle: "span.handle",
	clone: true,
	onStart: function(e) {
		e.addClass("dragging");
	},
	onComplete: function(e) {
		e.removeClass("dragging");
		var songEntryKey = this.serialize(function(e){
			return e.id.replace("song_entry_", "");
		});
		new MuxRequest({
			url:"/manage/song_entries/sort",
			requestInfo: this.requestInfo,
			errorMessage: "could not reorder"
		}).sendWithRetry({ data: {
			"order": songEntryKey
		}});
	}
});

function openSongRow(songKey) {
	songKey = songKey.replace(/#/, '');
	var row = $$("tr." + songKey + "_row")[0];
	var exp = $$("tr." + songKey + "_expansion")[0];
	
	if(exp.getStyle('display') == 'none') {
    window.location.hash = songKey;
    row.getParent().getChildren('tr.expansion').each(function(e){
      e.getPrevious().removeClass('selected');
      e.setStyle('display', 'none');
    });
    row.addClass('selected');
    row.getNext().setStyle('display','');
		try {
			row.getNext().getElement('input.rename_song').focus();
		} catch(error) {}
  } else {
    window.location.hash = '';
    row.removeClass('selected');
    row.getNext().hide();
  }
  return false;
}

var ColorPicker = new Class({
	initialize: function(id) {
		this.div = $(id);
		this.text_field = this.div.getElement("input");
		this.hex = this.text_field.get("value"); // stored without a '#' character
		this.original_hex = this.hex;
		this.rgb = this.hex.hexToRgb(true);
		this.button = this.div.getElement("button");

		this.resetButton = this.div.getElement('.reset');
		this.resetButton.addEvent('click', this.reset.bind(this));

		this.sliders = [];
		this.div.getElements('div.slider').each(function(e, i){
			this.sliders[i] = new Slider(e, e.getElement('.knob'), {
				steps: 255,
				wheel: true,
				onChange: function(){
					this.draw();
				}.bind(this)
			});
			this.sliders[i].set(this.rgb[i]);
		}.bind(this));

		this.draw();
	},

	// slider -> rgb -> hex
	refresh: function() {
		this.sliders.each(function(e, i){
			this.rgb[i] = e.step;
		}.bind(this));
		this.hex = this.rgb.rgbToHex().substr(1,6);
	},
	
	draw: function() {
		this.refresh();

		this.text_field.set('value', this.hex);
		this.text_field.setStyle('background', "#" + this.hex);

		this.sliders.each(function(e, i){
			e.set(this.rgb[i]);
		}.bind(this));
	},
	
	reset: function() {
		this.hex = this.original_hex;
		this.rgb = this.hex.hexToRgb(true);
		this.sliders.each(function(e, i){
			e.set(this.rgb[i]);
		}.bind(this));
		this.draw();
	}
});


var EventForm = new Class({
	Extends: MuxForm,

	initialize: function(e){
		this.container = $(e);
		this.parent(this.container.getElement('form'));

		this.when_at_date = this.form.getElement("input[id$=_when_at_date]");
//		this.when_at_time = this.form.getElement("input[id$=_when_at_time]");
		this.title = this.form.getElement("input[id$=_title]");
		this.link = this.form.getElement("input[id$=_link]");
		this.submit = this.form.getElement("input[type=submit]")

    this.when_at_date.addEvent('change', this.refresh.bind(this));
    this.when_at_date.addEvent('keyup', this.refresh.bind(this));
//    this.when_at_time.addEvent('keyup', this.refresh.bind(this));
    this.title.addEvent('keyup', this.refresh.bind(this));
    this.link.addEvent('keyup', this.refresh.bind(this));

		this.refresh();
  },

	toggle: function() {
		if (this.container.getStyle('display') == 'none') {
	    this.refresh();
			this.container.show();
			this.title.focus();
		} else {
			this.container.hide();
		}
	},
  
  validate: function() {
    var arrErrors = [];
    
    if (this.when_at_date.get('value').length == 0) {
      arrErrors.push("Date is required.");
    }
//    if (this.when_at_time.get('value').length == 0) {
//      arrErrors.push("Time is required.");
//    }
    if (this.title.get('value').length == 0) {
      arrErrors.push("Title is required.");
    }

    return arrErrors;
  }
});


var togglers = $$('ul#mainmenu li.menutitle');
var elements = $$('ul#mainmenu li.section');
var options = {
	show: 0,
	duration: 200,
	opacity: false,
	wait: false,
	onActive: function(toggler,element) {
	
		this.togglers.addClass('pointer');
							
	
		toggler.removeClass('pointer');					
		
		this.togglers.setStyle("display", "block");
		this.elements.setStyle("display", "block");
	}
};

try {
	if (togglers.length > 0 && elements.length > 0) {
		var mainmenu = new Accordion(togglers,elements,options);
		var color = togglers[togglers.length - 1].getStyle("background-color");
		elements[elements.length - 1].setStyle("border-bottom", "1px solid " + color);
	}
} catch(e) {
}

var MegaMuxtape = new Class({
	initialize: function() {
		this.muxtape = document.getElement("ul.muxtape_song_list.full");
		if (!this.muxtape) return;
		this.songs = this.muxtape.getElements("li.song");
		this.removers = this.muxtape.getElements("li.song span.remover");
		this.handles = this.muxtape.getElements("li.song span.handle");
		this.sortable = new Sortables(this.muxtape, {
			constrain: true,
			handle: "span.handle",
			clone: true,
			onStart: function(e) {
				e.addClass("dragging");
			},
			onComplete: function(e) {
				e.removeClass("dragging");
				var order = this.serialize(function(e){
					return e.id.replace("song_", "");
				});
				new MuxRequest({
					url:"/song_entries/sort",
					requestInfo: this.requestInfo,
					errorMessage: "could not reorder"
				}).sendWithRetry({ data: {
					"order": order
				}});
			}
		});
	},
	
	toggle: function() {
		this.isEditing() ? this.done() : this.edit();
	},
	
	edit: function() {
		this.removers.each(function(e){
			e.setStyle("display", "inline");
		});
		this.handles.each(function(e){
			e.setStyle("display", "inline");
			e.addEvent("mousedown", function(){
				e.getParent("li").addClass("dragging");
			});
			e.addEvent("mouseup", function(){
				e.getParent("li").removeClass("dragging");
			});
		});
	},
	
	done: function() {
		this.removers.each(function(e){
			e.setStyle("display", "none");
		});
		this.handles.each(function(e){
			e.setStyle("display", "none");
		});
	},
	
	isEditing: function() {
		if (this.songs.length == 0) return false;
		if (this.songs[0].getElements("span.remover").getStyle("display") == "none") return false;
		return true;
	}
});

var megaMuxtape = new MegaMuxtape();


var PLAYED_TIME = 30; // seconds
var REQUEST_RETRY_TIME = 3000; // milliseconds
var REQUEST_TRY_COUNT = 4; // times to try a request

var bandolier = null;
var soundManager = null;

var Bandolier = new Class({
	initialize: function() {
		if (document.location.href.match(/\/manage\/components$/)) return;
		
		this.muxtapes = this.loadMuxtapes();
		this.songs = this.loadSongs();
		this.originalTitle = document.title;
		this.currentSong = null;

		document.addEvent('keydown', this.onKeyDown.bind(this));
	},

	reinit: function(currentSongEntryKey) {
		if (this.currentSong && currentSongEntryKey == this.currentSong.key) {
			soundManager.stopAll();
			this.currentSong = null;
		}

		this.muxtapes = this.loadMuxtapes();
		this.songs = this.loadSongs();
	},

	draw: function() {
		if (this.isPlaying()) {
			document.title = this.currentSong.account + " - " + this.currentSong.name + " (" + this.originalTitle + ")";
		} else {
			document.title = this.originalTitle;
		}

		this.muxtapes.each(function(m){ m.draw(); });
	},
	
	loadMuxtapes: function() {
		return document.getElements("ul.muxtape_song_list").map(function(e){
			var k = e.id.split("_");
			return new Muxtape(k[1]);
		});
	},
	
	loadSongs: function() {
		return this.muxtapes.map(function(m){
			return m.songs;
		}).flatten();
	},
	
	onKeyDown: function(event) {
		if (event.key == 'enter') {
			if (this.isPlaying()) {
				this.currentSong.pause();
			} else {
				this.enterPlay();
			}
		}
		if (event.key == 'left') {
			if (! this.currentSong) return;
			if (this.currentSong.position > 2) {
				this.currentSong.play();
			} else {
				this.playPrevious(this.currentSong);
			}
		}
		if (event.key == 'right') {
			if (! this.currentSong) return;
			this.playNext(this.currentSong);
		}
	},

	isPlaying: function() {
		return this.muxtapes.some(function(m){
			return m.isPlaying();
		})
	},
	
	enterPlay: function() {
		if (this.currentSong && this.currentSong.sound.position > 0) {
			this.currentSong.playOrResume();
		} else {
			this.playFirst();
		}
	},

	play: function(song) {
		soundManager.stopAll();
		song.sound.play({ url: song.url });
		
		var e = song.li.getParent("li.section");
		if (mainmenu && e && e.getStyle("height").toInt() == 0) {
			var i = togglers.indexOf(e.getPrevious("li.menutitle"));
			mainmenu.display(i);
		}
	},
	
	playFirst: function() {
		if (this.songs.length == 0) return;
		this.songs[0].play();
	},
	
	playNext: function(current) {
		var keys = this.songs.map(function(s){return s.key});
		var i = keys.indexOf(current.key);
		if (i + 1 == this.songs.length) return;

		this.songs[i + 1].play();
	},
	
	playPrevious: function(current) {
		var keys = this.songs.map(function(s){return s.key});
		var i = keys.indexOf(current.key);
		if (i == 0) return;

		this.songs[i - 1].play();
	}
});


var Muxtape = new Class({
	initialize: function(key) {
		this.key = key;
		this.ul = $('muxtape_' + this.key);
		this.songs = this.ul.getChildren("li.song").map(function(e){
			var k = e.id.split("_");
			return new Song(k[1]);
		});
	},
	
	isPlaying: function() {
		return this.songs.some(function(s){
			return s.isPlaying();
		})
	},
	
	draw: function() {
		this.songs.each(function(s){ s.draw(); });
	}
});


var Song = new Class({
	initialize: function(key) {
		this.key = key;
		this.li = $('song_' + this.key);
		this.url = "";
		this.percentage = 0; // integer, % bytes loaded
		this.position = 0; // integer in seconds
		this.playing = false;
		this.played = false;

		this.requestInfo = this.li.getElement('.request_info');
		this.positionSpan = this.li.getElement('.position');
		this.percentageSpan = this.li.getElement('.percentage');
//		this.adder = this.li.getElement('.adder');
		this.remover = this.li.getElement('.remover');
		this.account = this.li.getElement('span.account').get('text').trim();
		this.name = this.li.getElement('span.name').get('text').trim();

		this.playRetryCount = 0;
		this.playReported = false;
		this.playReporting = false;
		
		this.sound = soundManager.createSound({
			id: this.key,
			url: "",
			whileloading: this.onWhileLoading.bind(this),
			onload: this.onLoad.bind(this),
			whileplaying: this.onWhilePlaying.bind(this),
			onfinish: this.onFinish.bind(this)
		});

		this.li.addEvent('click', this.onClick.bind(this));
		this.li.addEvent('mouseover', this.onMouseOver.bind(this));
		this.li.addEvent('mouseout', this.onMouseOut.bind(this));
		
//		this.adder.addEvent("click", this.songEntryCreate.bind(this));
		if (this.remover) this.remover.addEvent("click", this.songEntryDestroy.bind(this));
	},
	
	getMuxtape: function() {
		var muxtapeUl = this.li.getParent("ul.muxtape_song_list");

		return bandolier.muxtapes.filter(function(muxtape){
			if (muxtape.ul.id == muxtapeUl.id) return true;
		})[0];
	},
	
	// is the song in 'play' mode, playing or/and buffering
	isPlaying: function() {
		if (this.sound.paused) return false;
		if (this.sound.readyState == 0 || this.sound.readyState == 2) return false; // uninitialised || failed/error

		return this.sound.playState == 1; // playing or buffering
	},

	onClick: function(event) {
		if (event.target.tagName != 'A' && !event.target.hasClass('fauxlink')) {

			if (this.sound.paused) {
				this.resume();
			} else if (this.isPlaying()) {
				this.pause();
			} else {
				if (bandolier.currentSong) bandolier.currentSong.stop();
				this.play();
			}
		}
	},
	
	onMouseOver: function(event) {
		this.li.addClass('hover');
	},
	
	onMouseOut: function(event) {
		this.li.removeClass('hover');
	},

	refresh: function() {
		if (this.played && this.sound.bytesTotal > 0) {
			this.percentage = Math.ceil(this.sound.bytesLoaded / this.sound.bytesTotal * 100);
		} else {
			this.percentage = 0;
		}

		this.position = Math.floor(this.sound.position / 1000);
	},
	
	draw: function() {
		this.refresh();

		// stripe color
		if (this.isPlaying() || this.sound.paused) {
			this.li.addClass('hilite');
		} else {
			this.li.removeClass('hilite');
		}

		// percent loaded
		if (this.played && this.percentage > 0) {
			this.percentageSpan.set("html", this.percentage.toString() + '%');
		}
		
		// position content
		if ((this.isPlaying() && this.sound.position > 0) || this.sound.paused) {
			this.positionSpan.set('html', this.secondsToMinutes(this.position));
		} else if (this.playing) {
			this.positionSpan.set('html', '&mdash;');
		} else {
			this.positionSpan.set('html', '');
		}

		// position style
		if (this.isPlaying() && this.sound.position > 0) {
			this.positionSpan.removeClass('grey').addClass('green');
		} else {
			this.positionSpan.removeClass('green').addClass('grey');
		}
	},
	
	isLoaded: function() {
		return this.sound.readyState == 3;
	},
	
	onWhileLoading: function(event) {
		bandolier.draw();
	},

	onLoad: function(event) {
		bandolier.draw();
	},
	
	onWhilePlaying: function(event) {
		if (this.position > PLAYED_TIME) this.reportPlay();
		bandolier.draw();
	},
	
	play: function() {
		if (bandolier.currentSong) bandolier.currentSong.stop();
		bandolier.currentSong = this;

		this.playReported = false;
		this.played = true;
		this.playing = true;

		if (this.url) {
			bandolier.play(this);
		} else {
			new MuxRequest({
				url: '/song_entries/' + this.key + '.json',
				method: 'get',
				headers: { 'X-Muxtape-Agent': 'Bandolier', 'X-Muxtape': 'Alive', 'Accept-Language': 'mx' },
				requestInfo: this.requestInfo,
				errorMessage: "could not stream",
				onComplete: function(response){
					bandolier.draw();
				}.bind(this),
				onSuccess: function(response){
					var r = JSON.decode(response);
					this.url = r["song_entry"]["aws_url"];
					bandolier.play(this);
				}.bind(this)
			}).sendWithRetry();
		}

		bandolier.draw();
	},
	
	resume: function() {
		if (! this.sound.paused) return;

		this.sound.resume();
		
		bandolier.draw();
	},
	
	playOrResume: function() {
		this.sound.paused ? this.resume() : this.play();
	},
	
	pause: function() {
		this.sound.pause();

		bandolier.draw();
	},

	stop: function() {
		this.playing = false;
		this.sound.stop();

		bandolier.draw();
	},
	
	// when the sound is done playing
	onFinish: function() {
		this.reportPlay();
		this.playing = false;
		bandolier.playNext(bandolier.currentSong);
		
		bandolier.draw();
	},
	
	reportPlay: function() {
		if (this.playReported) return;
		if (this.playReporting) return;
		if (this.playRetryCount >= REQUEST_TRY_COUNT) return;
		this.playReporting = true;

		this.doReportPlay();
	},
	
	doReportPlay: function() {
		new MuxRequest({
			url: '/plays',
			headers: { 'X-Muxtape-Agent': 'Bandolier' },
			onSuccess: function(){
				this.playReported = true;
				this.playReporting = false;
			}.bind(this),
			onComplete: function(){
			}.bind(this),
			onFailure: function(){
				if (this.playRetryCount >= REQUEST_TRY_COUNT) {
					this.playReporting = false;
				} else {
					this.playRetryCount += 1;
					setTimeout(this.doReportPlay.bind(this), REQUEST_RETRY_TIME);
				}
			}.bind(this)
		}).sendWithRetry({ data: {
			"play[song_entry_key]": this.key,
			"play[via_id]":         playVias[this.getMuxtape().key][0],
			"play[via_type]":       playVias[this.getMuxtape().key][1]
		}});
	},
	
	songEntryCreate: function() {
		new MuxRequest({
			url: '/song_entries',
			requestInfo: this.requestInfo,
			errorMessage: "could not add",
			onRequest: function(){
				// this.adder.addClass("adding");
			}.bind(this),
			onSuccess: function(){
				// this.adder.removeClass("adding");
			}.bind(this),
			onFailure: function(){
				// this.adder.removeClass("adding").addClass("error");
			}.bind(this)
		}).sendWithRetry({ data: {
			'song_entry[song_entry_key]': this.key
		}});
	},
	
	songEntryDestroy: function() {
		new MuxRequest({
			url: '/song_entries/' + this.key,
			method: 'delete',
			requestInfo: this.requestInfo,
			errorMessage: "could not remove",
			onRequest: function(){
				if (this.remover) this.remover.addClass("removing");
			}.bind(this),
			onSuccess: function(){
				new Fx.Slide("song_" + this.key).slideOut();
				bandolier.reinit(this.key);
			}.bind(this),
			onFailure: function(){
				if (this.remover) this.remover.removeClass("removing").addClass("error");
			}.bind(this)
		}).sendWithRetry();
	},
	
	secondsToMinutes: function(seconds) {
		var string = '';

		if ($type(seconds) == 'number') {
			var sec = seconds % 60;
			var min = (seconds - sec) / 60;
			var min_formatted = min ? min + ':' : '';
			var sec_formatted = min ? (sec < 10 ? '0'+sec : sec) : sec;
			string = min_formatted + sec_formatted;
		}
		
		return string;
	},
	
	position: function() {
		return this.sound.position;
	}
});

window.addEvent('domready', function() {
	soundManager = new SoundManager();

	// soundmanager config
	soundManager.url = '/flash';
	soundManager.waitForWindowLoad = true;
	soundManager.consoleOnly = true;
	soundManager.debugMode = false;
	soundManager.onload = function(){ bandolier = new Bandolier(); };
	soundManager.beginDelayedInit();
});
