//
//ʾ:http://demos.mootools.net/Slider
var Slider = new Class({

 //̳ʵEventsOptions,UI
 Implements: [Events, Options],

 options: {/*
  //λøı¼
  onChange: $empty,
  //϶ıλ¼
  onComplete: $empty,*/
  //ÿһ¼
  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'
 },

 //캯,Ҫ
 //elementΪ,knobΪ
 initialize: function(element, knob, options){
  //ϲ
  this.setOptions(options);
  //ȡڵ
  this.element = $(element);
  //
  this.knob = $(knob);
  //ʼλñǱ
  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 offset, limit = {}, modifiers = {'x': false, 'y': false};
  //ݲͬģʽʼֵ
  switch (this.options.mode){
   //򻬶ʱ
   case 'vertical':
    //Ϊy᷽
    this.axis = 'y';
    //ʱҪҪı们CSSеtop
    this.property = 'top';
    //ʱҪȡֵΪoffsetHeiht
    offset = 'offsetHeight';
    break;
   //򻬶ʱ
   case 'horizontal':
    //Ϊx᷽
    this.axis = 'x';
    //ʱҪҪı们CSSеleft
    this.property = 'left';
    //ʱҪȡֵΪoffsetWidth
    offset = 'offsetWidth';
  }
  //ȡڵǰϵĳߴһ
  this.half = this.knob[offset] / 2;
  //㻬ƶܾ
  this.full = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
  //ȡΧ,ĬΪ0
  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;
  //ܲ,stepsֵΪ0,Ϊƶܾ
  this.steps = this.options.steps || this.full;
  //ÿһľ
  this.stepSize = Math.abs(this.range) / this.steps;
  //ÿһռĿ(ĵȼ,ﲻֱthis.stepWidth = this.full/this.steps)
  this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ;
  
  //ΪԶλ
  this.knob.setStyle('position', 'relative').setStyle(this.property, - this.options.offset);
  //ǰ϶Ӧ,תDragĲ
  modifiers[this.axis] = this.property;
  //귶Χ
  limit[this.axis] = [- this.options.offset, this.full - this.options.offset];
  //ʹ϶
  this.drag = new Drag(this.knob, {
   snap: 0,
   //Ŀ϶Χ
   limit: limit,
   //ָ϶ķ򼰶Ӧ
   modifiers: modifiers,
   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(step){
  //Χ޴СҵǰֵС,򵱷Χ޴ӴСҵǰֵʱ,òֵΪֵ
  if (!((this.range > 0) ^ (step < this.min))) step = this.min;
  //Χ޴Сҵǰֵ,򵱷Χ޴ӴСҵǰֵСʱ,òֵΪֵ
  if (!((this.range > 0) ^ (step > this.max))) step = this.max;
  
  //㲽
  this.step = Math.round(step);
  //鲽仯,ԾǷ񴥷¼
  this.checkStep();
  //
  this.end();
  //¼
  this.fireEvent('onTick', this.toPosition(this.step));
  return this;
 },

 //ֱָλ
 clickedElement: function(event){
  //жϷ
  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.end();
  //¼
  this.fireEvent('onTick', position);
 },
 
 //ùָλ
 scrolledElement: function(event){
  //򻬶򻬶ʱ,ǰͺµĻı仯෴
  var mode = (this.options.mode == 'horizontal') ? (event.wheel < 0) : (event.wheel > 0);
  //modeΪСֵ(),ֵ֮()
  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];
  //߽紦
  position = position.limit(-this.options.offset, this.full -this.options.offset);
  //㵱ǰĲ
  this.step = Math.round(this.min + dir * this.toStep(position));
  //黬λޱ仯
  this.checkStep();
 },

 //鲽ޱ仯
 checkStep: function(){
  //ֵ˵иı
  if (this.previousChange != this.step){
   //¾ֵ
   this.previousChange = this.step;
   //onChange¼,͵ǰ
   this.fireEvent('onChange', this.step);
  }
 },

 //,鲽ޱ仯
 end: function(){
  //ֵ˵иı
  if (this.previousEnd !== this.step){
   //¾ֵ
   this.previousEnd = this.step;
   //onComplete¼,͵ǰ
   this.fireEvent('onComplete', 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;
 }

});

