/*
用途项目：自定义滚动条实现
*/
(function(win, doc, $){
  // 定义的滚动条的构造函数
  function CusScrollBar(options) {
    // 函数的调用
    this._init(options);
  }
  // 对象的合并
  $.extend(CusScrollBar.prototype, {
    _init: function(options){
      // 闭包
      var self = this;
      // 初始化参数
      self.options = {
        scrollDir: 'Y',       //滚动的方向
        contentSelector: '',  //滚动内容区选择器
        barSelector: '',      //滚动条选择器
        sliderSelector: '',   //滚动滑块选择器
        wheelStep: 20,        //滚动步长（鼠标移动一下，内容滚动的幅度）
      }
      // 覆盖参数
      $.extend(true, self.options, options||{});
      self._initDomEvent();
      return self;
    },

    /**
     * 初始化DOM引用
     * @method _initDomEvent
     * @return {CusScrollBar}
     */
     _initDomEvent: function() {
      var opts = this.options;
      // 滚动内容区对象，必填项
      this.$cont = $(opts.contentSelector);
      // 滚动条滑块对象，必须项
      this.$slider = $(opts.sliderSelector);
      // 滚动条对象
      this.$bar = opts.barSelector ? $(opts.barSelector) : self.$slider.parent();
      // 获取文档对象
      this.$doc = $(doc);
      // 获取初始化滑块拖动功能
      this._initSliderDragEvent();
      // 获取同步滑块的位置
      this._bindContentScroll();
      // 获取鼠标滚轮事件
      this._bindMousewheel();
      // 获取内容来定义滑块的高度
      this._initSliderHeight();

     },
     // 根据内容来定义滑块的高度
     _initSliderHeight: function() {
      var rate = this.$cont.height()/this.$cont[0].scrollHeight;
      var sliderHeight = rate*this.$bar.height();
      this.$slider.css('height',sliderHeight);
     },
     

     /**
      * 初始化滑块拖动功能
      * @return {[Object]} [this]
      */
    _initSliderDragEvent: function() {
      var self = this;
      // 滑块元素
      var slider = this.$slider,
          sliderEl = slider[0];
      // 如果元素存在
      if (sliderEl) {
        var doc = this.$doc,
            dragStartPagePostion,
            dragStartScrollPostion,
            dragContBarRate;
        function mousemoveHandler(e) {
          e.preventDefault();
          if (dragStartPagePostion == null) {
            return;
          }
          //内容开始卷曲的高度+rate*(鼠标释放的位置-开始的位置) == 就是内容滑动的位置
          self.scrollTo(dragStartScrollPostion + (e.pageY - dragStartPagePostion)*dragContBarRate);
        }
        slider.on('mousedown', function(e){
          e.preventDefault();
          // 获取鼠标的点击的开始位置
          dragStartPagePostion = e.pageY;
          // 获取内容区域的向上卷区的高度
          dragStartScrollPostion = self.$cont[0].scrollTop;
          dragContBarRate = self.getMaxScrollPosition()/self.getMaxSliderPosition();
          // 监听的document对象
          doc.on('mousemove.scroll', mousemoveHandler).on('mouseup.scroll',function(){
            doc.off('.scroll');
          });
        });
        return self;
      }
    },
    
    // 计算滑块的当前位置
    getSliderPosition: function() {
      var self = this,
      // 滑块可以移动的距离
          maxSliderPosition = self.getMaxSliderPosition();
          // 滑块移动的距离
      return Math.min(maxSliderPosition, maxSliderPosition*self.$cont[0].scrollTop/self.getMaxScrollPosition());
    },

    // 内容可滚动的高度
    getMaxScrollPosition: function() {
      var self = this;
      return Math.max(self.$cont.height(), self.$cont[0].scrollHeight) - self.$cont.height();
    
    },

    //滑块可移动的距离
    getMaxSliderPosition: function(){
      var self = this;
      return self.$bar.height() - self.$slider.height();
    },

    // 监听内容的滚动，同步滑块的位置
    _bindContentScroll: function() {
      var self = this;
      self.$cont.on('scroll', function(){
        var sliderEl = self.$slider && self.$slider[0];
        if (sliderEl) {
          // 设置滑块的位置
          sliderEl.style.top = self.getSliderPosition() + 'px';
        }
      });
      return self;
    },

    // 鼠标滚轮事件
    _bindMousewheel: function() {
      var self = this;
      // on监听事件，多个事件利用空格分开
      self.$cont.on('mousewheel DOMMouseScroll',function(e){
        e.preventDefault();
        // 判断原生事件对象的属性
        var oEv = e.originalEvent,
        //原生事件对象,（其他浏览器负数向下，firefox正数向下,所以在wheelDelta前面有负数）
        // 想要达到的效果，鼠标向下滚动，内容向下走
            wheelRange = oEv.wheelDelta ? -oEv.wheelDelta/120 : (oEv.detail || 0)/3;
            // 调用scrollTo方法。
            self.scrollTo(self.$cont[0].scrollTop + wheelRange*self.options.wheelStep)
      });
    },

    // 内容的滑动
    scrollTo: function(positonVal) {
      var self = this;
      self.$cont.scrollTop(positonVal);
    }
  });

  win.CusScrollBar = CusScrollBar;
})(window,document,jQuery)