robot_wiki/amWiki/js/amWiki.scrollbar.js

288 lines
9.7 KiB
JavaScript

/**
* amWiki Web端 - 滚动条模块
* @author Tevin
*/
;
(function (win, $) {
'use strict';
//定时检测内容高度作为补充
var list = [];
setInterval(function () {
for (var i = 0, item; item = list[i]; i++) {
item.checkHeightWidth();
}
}, 500);
/**
* 页面滚动
* @param {Element} _this
* @constructor
*/
var Scroller = function (_this) {
this.$e = {
container: $(_this), //主容器
inner: null, //正文内容
barY: null, //垂直滚动条外层
boxY: null, //垂直滚动条
sliderY: null, //垂直滑块
barX: null, //水平滚动条外层
boxX: null, //水平滚动条
sliderX: null //水平滑块
};
this._data = {
xRolling: this.$e.container.attr('data-x-rolling') == 'true',
maxTop: 0, //最大top值
barH: 0, //滚动条高度
sliderH: 0, //滑块高度
contentH: 0, //内容高度
containerH: 0, //容器高度
contentHLast: 0, //上次内容高度
barW: 0, //滚动条宽度
sliderW: 0, //滑块宽度
contentW: 0, //内容宽度
containerW: 0, //容器宽度
contentWLast: 0 //上次内容宽度
};
this._init();
};
/**
* 初始化
* @private
*/
Scroller.prototype._init = function () {
var that = this;
var barHtml = '<div class="scrollbar scrollbar-y" onselectstart="return false"><div><i></i></div></div>';
barHtml += this._data.xRolling ?
'<div class="scrollbar scrollbar-x" onselectstart="return false"><div><i></i></div></div>' : '';
this.$e.container.append(barHtml);
//获取元素
this.$e.barY = this.$e.container.find('.scrollbar-y');
this.$e.boxY = this.$e.barY.children('div');
this.$e.sliderY = this.$e.barY.find('i');
if (this._data.xRolling) {
this.$e.barX = this.$e.container.find('.scrollbar-x');
this.$e.boxX = this.$e.barX.children('div');
this.$e.sliderX = this.$e.barX.find('i');
}
this.$e.inner = this.$e.container.children('.scroller-inner');
//绑定事件
this._onWinResize();
$(win).on('resize', function () {
that._onWinResize();
that.checkHeightWidth();
});
this.$e.container.on('scrollbar', function () {
that.checkHeightWidth();
});
this.$e.inner.on({
'click': function () {
that.checkHeightWidth();
},
'scroll': function () {
that._reScroll();
}
});
this.checkHeightWidth();
this._bindAction();
};
/**
* 滑块操作
* @private
*/
Scroller.prototype._bindAction = function () {
var that = this;
var onDrag = false;
var _y = 0,
top = 0,
_x = 0,
left = 0;
this.$e.body = $('body');
this.$e.boxY.on({
'mousedown': function (e) {
onDrag = 'y';
that.$e.body.attr('onselectstart', 'return false');
that.$e.barY.addClass('active');
_y = e.pageY;
top = parseFloat(that.$e.sliderY.css('top'));
if (that.$e.barY.parents('#main').length > 0) {
that.$e.body.children('aside').hide();
}
}
});
if (this._data.xRolling) {
this.$e.boxX.on({
'mousedown': function (e) {
onDrag = 'x';
that.$e.body.attr('onselectstart', 'return false');
that.$e.barX.addClass('active');
_x = e.pageX;
left = parseFloat(that.$e.sliderX.css('left'));
}
});
}
$(win.document).on({
'mousemove': function (e) {
if (onDrag == 'y') {
that.scrollYTo(top + e.pageY - _y);
} else if (onDrag == 'x') {
that.scrollXTo(left + e.pageX - _x);
}
},
'mouseup': function () {
that.$e.body.removeAttr('onselectstart', 'return false')
.children('aside').show();
if (onDrag == 'y') {
that.$e.barY.removeClass('active');
} else if (onDrag == 'x') {
that.$e.barX.removeClass('active');
}
onDrag = false;
}
});
};
/**
* 尺寸缩放
* @private
*/
Scroller.prototype._onWinResize = function () {
if (isMobi()) {
this.$e.inner.removeAttr('style').removeClass('on');
} else {
this.$e.inner.css({
width: this.$e.container.width() + 30,
paddingRight: 13,
paddingBottom: 16
}).addClass('on');
}
};
/**
* 重设滑块大小
* @private
*/
Scroller.prototype._resize = function () {
var that = this;
this._data.containerH = this.$e.inner.height();
//当内容高度小于等于容器时,不显示滚动条
if (this._data.contentH <= this._data.containerH) {
this._data.contentH = this._data.containerH;
this.$e.barY.addClass('off');
} else {
this.$e.barY.removeClass('off');
}
//设置滑块大小
this._data.barH = this.$e.boxY.height();
this._data.sliderH = this._data.containerH / that._data.contentH * this._data.barH;
this.$e.sliderY.height(this._data.sliderH);
//计算最大高度
this._data.maxTop = (this._data.barH - this._data.sliderH) / this._data.barH * this._data.contentH + 1;
//水平方向
if (this._data.xRolling) {
this._data.containerW = this.$e.inner.width();
//当内容宽度不超过容器时,不显示滚动条
if (this._data.contentW <= this._data.containerW) {
this._data.contentW = this._data.containerW;
this.$e.barX.addClass('off');
} else {
this.$e.barX.removeClass('off');
}
//设置滑块大小
this._data.barW = this.$e.boxX.width();
this._data.sliderW = this._data.containerW / that._data.contentW * this._data.barW;
this.$e.sliderX.width(this._data.sliderW);
}
};
/**
* 重设滑块顶部距离
* @private
*/
Scroller.prototype._reScroll = function () {
var that = this;
var top1 = this.$e.inner.scrollTop();
var barTop = top1 / this._data.contentH * this._data.barH;
//限制滑动边界 (由事件触发的滚动不会向上过界)
if (barTop + this._data.sliderH >= this._data.barH) {
barTop = this._data.barH - this._data.sliderH;
this.$e.sliderY.css('top', barTop);
this.$e.inner.scrollTop(this._data.maxTop);
} else {
this.$e.sliderY.css('top', barTop);
}
//水平方向
if (this._data.xRolling) {
var barLeft = this.$e.inner.scrollLeft() / this._data.contentW * this._data.barW;
//水平方向没有鼠标滚动事件
this.$e.sliderX.css('left', barLeft);
}
};
/**
* 垂直滚动到某位置
* @param {Number} num
* @public
*/
Scroller.prototype.scrollYTo = function (num) {
var barTop = num;
barTop = barTop < 0 ? 0 : barTop;
barTop = barTop + this._data.sliderH > this._data.barH ? this._data.barH - this._data.sliderH : barTop;
this.$e.sliderY.css('top', barTop);
this.$e.inner.scrollTop(barTop / this._data.barH * this._data.contentH);
};
/**
* 水平滚动到某位置
* @param {Number} num
* @public
*/
Scroller.prototype.scrollXTo = function (num) {
var barLeft = num;
barLeft = barLeft < 0 ? 0 : barLeft;
barLeft = barLeft + this._data.sliderW > this._data.barW ? this._data.barW - this._data.sliderW : barLeft;
this.$e.sliderX.css('left', barLeft);
this.$e.inner.scrollLeft(barLeft / this._data.barW * this._data.contentW);
};
/**
* 检查高度宽度
* @public
*/
Scroller.prototype.checkHeightWidth = function () {
var that = this;
this._data.contentH = 0;
this._data.contentW = 0;
this.$e.inner.children('.scroller-content').each(function () {
that._data.contentH += $(this).outerHeight();
that._data.contentW += $(this).outerWidth();
});
//修正 webkit 中滚动条本身占位
if (/webkit/.test(navigator.userAgent.toLowerCase())) {
that._data.contentH += 15;
}
//如果高度未改变不进行操作
if (this._data.contentH == this._data.contentHLast && this._data.contentW == this._data.contentWLast) {
return;
} else {
this._data.contentHLast = this._data.contentH;
this._data.contentWLast = this._data.contentW;
}
this._resize();
this._reScroll();
};
//注册到 jQuery
$.extend($.fn, {
scrollbar: function () {
return this.each(function () {
list.push(new Scroller(this));
});
}
});
})(window, jQuery);