var Slider=new Class({Implements:[Events,Options],Binds:["clickedElement","draggedKnob","syncOrder","scrolledElement"],options:{onTick:function(position){if(this.options.snap){position=this.toPosition(this.step)}this.knob.setStyle(this.property,position)},snap:false,offset:0,range:false,wheel:false,steps:100,mode:"horizontal",multiKnob:false,measure:false},initialize:function(element,knob,options){this.setOptions(options);this.element=document.id(element);this.knobSpacing=this.options.knobSpacing;this.knob=document.id(knob).store("slider",this);this.previousChange=this.previousEnd=this.step=-1;var offset,limit={},modifiers={x:false,y:false};switch(this.options.mode){case"vertical":this.axis="y";this.property="top";offset="offsetHeight";break;case"horizontal":this.axis="x";this.property="left";offset="offsetWidth"}if(this.options.measure){this.full=this.element.measure(function(){this.half=this.knob[offset]/2;return this.element[offset]-this.knob[offset]+(this.options.offset*2)}.bind(this))}else{this.full=this.element[offset]-this.knob[offset]+(this.options.offset*2);this.half=this.knob[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);var elementPosition=this.element.getStyle("position");if(elementPosition!="relative"||elementPosition!="absolute"){this.element.setStyle("position","relative")}this.knob.setStyle("position",(this.options.multiKnob)?"absolute":"relative").setStyle(this.property,-this.options.offset);modifiers[this.axis]=this.property;limit[this.axis]=[-this.options.offset,this.full-this.options.offset];this.bound={clickedElement:this.clickedElement.bind(this),scrolledElement:this.scrolledElement.bindWithEvent(this),draggedKnob:this.draggedKnob.bind(this)};var dragOptions={snap:0,limit:limit,modifiers:modifiers,onDrag:this.bound.draggedKnob,onStart:this.bound.draggedKnob,onBeforeStart:(function(){this.isDragging=true}).bind(this),onComplete:function(){this.isDragging=false;this.draggedKnob();this.knob.removeClass("collided");this.drag.firstStep=true;this.syncOrder();this.end()}.bind(this)};if(this.options.snap){dragOptions.grid=Math.ceil(this.stepWidth);dragOptions.limit[this.axis][1]=this.full}this.drag=new Drag(this.knob,dragOptions),this.drag.firstStep=true;this.attach()},attach:function(){if(!this.options.multiKnob){this.element.addEvent("mousedown",this.bound.clickedElement);if(this.options.wheel){this.element.addEvent("mousewheel",this.bound.scrolledElement)}}this.drag.attach();return this},detach:function(){this.element.removeEvent("mousedown",this.bound.clickedElement);this.element.removeEvent("mousewheel",this.bound.scrolledElement);this.drag.detach();return this},set:function(step){if(!((this.range>0)^(step<this.min))){step=this.min}if(!((this.range>0)^(step>this.max))){step=this.max}var instances=this.element.getChildren().retrieve("slider").erase(this).filter(function(e){return e!=null}),hitKnobs=[];instances.each(function(e,i){var knobSpacing=Math.max(this.knobSpacing,e.knobSpacing);if($defined(this.knobSpacing)&&$defined(e.knobSpacing)&&step>e.step-knobSpacing&&step<e.step+knobSpacing){hitKnobs.push(e.knob)}}.bind(this));if(hitKnobs.length>0){this.fireEvent("setCollision",[this.knob,hitKnobs]);return}else{this.step=Math.round(step);this.checkStep();this.fireEvent("tick",this.toPosition(this.step));this.syncOrder();this.end();return this}},clickedElement:function(event){if(this.isDragging||event.target==this.knob){return}var dir=this.range<0?-1:1;var position=event.page[this.axis]-this.element.getPosition()[this.axis]-this.half;position=position.limit(-this.options.offset,this.full-this.options.offset);this.step=Math.round(this.min+dir*this.toStep(position));this.checkStep();this.fireEvent("tick",position);this.end()},scrolledElement:function(event){var mode=(this.options.mode=="horizontal")?(event.wheel<0):(event.wheel>0);this.set(mode?this.step-this.stepSize:this.step+this.stepSize);event.stop()},draggedKnob:function(){var dir=this.range<0?-1:1;var position=this.drag.value.now[this.axis];var lastKnob=this.knob.getAllPrevious(),lastKnob=lastKnob.filter(function(e,i,a){return e.retrieve("slider").knobSpacing!=null})[0];var nextKnob=this.knob.getAllNext(),nextKnob=nextKnob.filter(function(e,i,a){return e.retrieve("slider").knobSpacing!=null})[0];var lastSlider=(lastKnob)?lastKnob.retrieve("slider"):{},nextSlider=(nextKnob)?nextKnob.retrieve("slider"):{};position=position.limit(-this.options.offset,this.full-this.options.offset);if(this.step>this.toStep(position)){var knobSpacing=Math.max(this.knobSpacing,lastSlider.knobSpacing);if($defined(lastSlider.knobSpacing)&&$defined(this.knobSpacing)&&position<lastSlider.step*lastSlider.stepWidth+knobSpacing*lastSlider.stepWidth){this.set(lastSlider.step+knobSpacing);if(!this.knob.hasClass("collided")&&!this.drag.firstStep){this.knob.addClass("collided");this.fireEvent("dragCollision",[this.knob,lastKnob])}this.drag.firstStep=false}else{this.knob.removeClass("collided");this.step=Math.round(this.min+dir*this.toStep(position))}}else{var knobSpacing=Math.max(this.knobSpacing,nextSlider.knobSpacing);if($defined(nextSlider.knobSpacing)&&$defined(this.knobSpacing)&&position>nextSlider.step*nextSlider.stepWidth-knobSpacing*nextSlider.stepWidth){this.set(nextSlider.step-knobSpacing);if(!this.knob.hasClass("collided")&&!this.drag.firstStep){this.knob.addClass("collided");this.fireEvent("dragCollision",[this.knob,nextKnob])}this.drag.firstStep=false}else{this.knob.removeClass("collided");this.step=Math.round(this.min+dir*this.toStep(position))}}this.checkStep()},syncOrder:function(){var pinhash=$H();var sorted=this.element.getChildren().retrieve("slider").filter(function(e){return e!=null}).map(function(e){pinhash.include(e.step,e.knob);return e.step}).sort(function(a,b){return a-b});pinhash.each(function(v,k,h){var pin=h.get(sorted[0]);if(pin){pin.inject(this.element,"bottom");sorted.shift()}}.bind(this))},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(position){var step=(position+this.options.offset)*this.stepSize/this.full*this.steps;return this.options.steps?Math.round(step-=step%this.stepSize):step},toPosition:function(step){return(this.full*Math.abs(this.min-step))/(this.steps*this.stepSize)-this.options.offset}});
