123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- var SlimScroll = (function () {
- function $(el) {
- if (!(this instanceof $)) {
- return new $(el)
- }
- if (typeof el === 'string') {
- var r = /<(\w+)><\/\1>$/.exec(el)
- if (r) {
- el = document.createElement(r[1])
- } else {
- el = document.querySelector(el)
- }
- }
- this.el = (el && el.nodeType === 1) ? el : document.documentElement
- return this
- }
- $.prototype = {
- parent: function () {
- return $(this.el.parentNode || this.el.parentElement)
- },
- closest: function (selector) {
- if (!selector) return $(document)
- var parent = this.parent()
- while (parent.el !== $(selector).el) {
- parent = parent.parent()
- }
- return parent
- },
- is: function (obj) {
- if (this.el === obj.el) {
- return true
- }
- return false
- },
- hasClass: function (className) {
- if (this.el.className.indexOf(className) >= 0) {
- return true
- }
- return false
- },
- addClass: function (className) {
- if (!className || typeof className === 'undefined') return
- if (this.hasClass(className)) return
- var cls = this.el.className.split(' ')
- cls.push(className)
- this.el.className = cls.join(' ').trim()
- return this
- },
- css: function (styleObj) {
- if (typeof styleObj === 'string') {
- return this.el.style[styleObj].replace('px', '')
- }
- for (var key in styleObj) {
- if (typeof styleObj[key] === 'number' && parseInt(styleObj[key])) styleObj[key] = parseInt(styleObj[key]) + 'px'
- if (key === 'zIndex') styleObj[key] = parseInt(styleObj[key])
- this.el.style[key] = styleObj[key]
- }
- return this
- },
- show: function () {
- this.el.style.display = 'block'
- },
- hide: function () {
- this.el.style.display = 'none'
- },
- wrap: function (obj) {
- this.parent().el.insertBefore(obj.el, this.el)
- obj.append(this)
- return this
- },
- append: function (obj) {
- this.el.appendChild(obj.el)
- return this
- },
- scrollTop: function (y) {
- if (typeof y !== 'undefined') {
- this.el.scrollTop = parseInt(y)
- return this
- }
- return this.el.scrollTop
- },
- outerHeight: function () {
- return this.el.offsetHeight || this.el.clientHeight
- },
- hover: function (hoverIn, hoverOut) {
- this.bind('mouseenter', hoverIn)
- this.bind('mouseleave', hoverOut)
- },
- bind: function (type, fn, capture) {
- var el = this.el;
- if (window.addEventListener) {
- el.addEventListener(type, fn, capture);
- var ev = document.createEvent('HTMLEvents');
- ev.initEvent(type, capture || false, false);
- // 在元素上存储创建的事件,方便自定义触发
- if (!el['ev' + type]) {
- el['ev' + type] = ev;
- }
- } else if (window.attachEvent) {
- el.attachEvent('on' + type, fn);
- if (isNaN(el['cu' + type])) {
- // 自定义属性,触发事件用
- el['cu' + type] = 0;
- }
- var fnEv = function (event) {
- if (event.propertyName === 'cu' + type) {
- fn.call(el);
- }
- };
- el.attachEvent('onpropertychange', fnEv);
- // 在元素上存储绑定的propertychange事件,方便删除
- if (!el['ev' + type]) {
- el['ev' + type] = [fnEv];
- } else {
- el['ev' + type].push(fnEv);
- }
- }
- return this;
- },
- trigger: function (type) {
- var el = this.el;
- if (typeof type === 'string') {
- if (document.dispatchEvent) {
- if (el['ev' + type]) {
- el.dispatchEvent(el['ev' + type]);
- }
- } else if (document.attachEvent) {
- // 改变对应自定义属性,触发自定义事件
- el['cu' + type]++;
- }
- }
- return this;
- },
- unbind: function (type, fn, capture) {
- var el = this.el;
- if (window.removeEventListener) {
- el.removeEventListener(type, fn, capture || false);
- } else if (document.attachEvent) {
- el.detachEvent('on' + type, fn);
- var arrEv = el['ev' + type];
- if (arrEv instanceof Array) {
- for (var i = 0; i < arrEv.length; i += 1) {
- // 删除该方法名下所有绑定的propertychange事件
- el.detachEvent('onpropertychange', arrEv[i]);
- }
- }
- }
- return this;
- }
- }
- $.extend = function (deep) {
- var start = 1
- if (typeof deep === 'object') {
- start = 0
- }
- var objs = Array.prototype.slice.call(arguments, start),
- newObj = {}
- for (var i = 0; i < objs.length; i++) {
- if (typeof objs !== 'object') return
- for (var key in objs[i]) {
- newObj[key] = typeof objs[i][key] === 'object' && deep === true ? $.extend(true, objs[i][key]) : objs[i][key]
- }
- }
- return newObj
- }
- $.isPlainObject = function (obj) {
- return typeof obj === 'object' && !(obj instanceof Array)
- }
- function SlimScroll(el, options) {
- var defaults = {
- // width in pixels of the visible scroll area
- width: 'auto',
- // height in pixels of the visible scroll area
- height: '250px',
- // width in pixels of the scrollbar and rail
- size: '7px',
- // scrollbar color, accepts any hex/color value
- color: '#000',
- // scrollbar position - left/right
- position: 'right',
- // distance in pixels between the side edge and the scrollbar
- distance: '1px',
- // default scroll position on load - top / bottom / $('selector')
- start: 'top',
- // sets scrollbar opacity
- opacity: 0.4,
- // enables always-on mode for the scrollbar
- alwaysVisible: false,
- // check if we should hide the scrollbar when user is hovering over
- disableFadeOut: false,
- // sets visibility of the rail
- railVisible: false,
- // sets rail color
- railColor: '#333',
- // sets rail opacity
- railOpacity: 0.2,
- // whether we should use jQuery UI Draggable to enable bar dragging
- railDraggable: true,
- // defautlt CSS class of the slimscroll rail
- railClass: 'slimScrollRail',
- // defautlt CSS class of the slimscroll bar
- barClass: 'slimScrollBar',
- // defautlt CSS class of the slimscroll wrapper
- wrapperClass: 'slimScrollDiv',
- // check if mousewheel should scroll the window if we reach top/bottom
- allowPageScroll: false,
- // scroll amount applied to each mouse wheel step
- wheelStep: 20,
- // scroll amount applied when user is using gestures
- touchScrollStep: 200,
- // sets border radius
- borderRadius: '7px',
- // sets border radius of the rail
- railBorderRadius: '7px'
- };
- var o = $.extend(defaults, options)
- // do it for every element that matches selector
- // this.each(function () {
- var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
- barHeight, percentScroll, lastScroll,
- divS = '<div></div>',
- minBarHeight = 30,
- releaseScroll = false;
- // used in event handlers and for better minification
- // var me = $(this);
- var me = $(el);
- // ensure we are not binding it again
- if (me.parent().hasClass(o.wrapperClass)) {
- // start from last bar position
- var offset = me.scrollTop();
- // find bar and rail
- bar = me.siblings('.' + o.barClass);
- rail = me.siblings('.' + o.railClass);
- getBarHeight();
- // check if we should scroll existing instance
- if ($.isPlainObject(options)) {
- // Pass height: auto to an existing slimscroll object to force a resize after contents have changed
- if ('height' in options && options.height === 'auto') {
- me.parent().css({ height: 'auto' });
- me.css({ height: 'auto' });
- var height = me.parent().parent().outerHeight();
- me.parent().css({ height: height });
- me.css({ height: height });
- } else if ('height' in options) {
- var h = options.height;
- me.parent().css({ height: h });
- me.css({ height: h });
- }
- if ('scrollTo' in options) {
- // jump to a static point
- offset = parseInt(o.scrollTo);
- }
- else if ('scrollBy' in options) {
- // jump by value pixels
- offset += parseInt(o.scrollBy);
- }
- else if ('destroy' in options) {
- // remove slimscroll elements
- bar.remove();
- rail.remove();
- me.unwrap();
- return;
- }
- // scroll content by the given offset
- scrollContent(offset, false, true);
- }
- return;
- } else if ($.isPlainObject(options)) {
- if ('destroy' in options) {
- return;
- }
- }
- // optionally set height to the parent's height
- o.height = (o.height === 'auto') ? me.parent().outerHeight() : o.height;
- // wrap content
- var wrapper = $(divS)
- .addClass(o.wrapperClass)
- .css({
- position: 'relative',
- overflow: 'hidden',
- width: o.width,
- height: o.height
- });
- // update style for the div
- me.css({
- overflow: 'hidden',
- width: o.width,
- height: o.height
- });
- // create scrollbar rail
- var rail = $(divS)
- .addClass(o.railClass)
- .css({
- width: o.size,
- height: '100%',
- position: 'absolute',
- top: 0,
- display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',
- 'border-radius': o.railBorderRadius,
- background: o.railColor,
- opacity: o.railOpacity,
- zIndex: 998
- });
- // create scrollbar
- var bar = $(divS)
- .addClass(o.barClass)
- .css({
- background: o.color,
- width: o.size,
- position: 'absolute',
- top: 0,
- opacity: o.opacity,
- display: o.alwaysVisible ? 'block' : 'none',
- 'border-radius': o.borderRadius,
- BorderRadius: o.borderRadius,
- MozBorderRadius: o.borderRadius,
- WebkitBorderRadius: o.borderRadius,
- zIndex: 999
- });
- // set position
- var posCss = (o.position === 'right') ? { right: o.distance } : { left: o.distance };
- rail.css(posCss);
- bar.css(posCss);
- // wrap it
- me.wrap(wrapper);
- // append to parent div
- me.parent().append(bar);
- me.parent().append(rail);
- //all binding events callback
- var events = {
- touchStart: function (e, b) {
- if (e.originalEvent.touches.length) {
- // record where touch started
- touchDif = e.originalEvent.touches[0].pageY;
- }
- },
- touchMove: function (e) {
- // prevent scrolling the page if necessary
- if (!releaseScroll) {
- e.originalEvent.preventDefault();
- }
- if (e.originalEvent.touches.length) {
- // see how far user swiped
- var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;
- // scroll content
- scrollContent(diff, true);
- touchDif = e.originalEvent.touches[0].pageY;
- }
- },
- hoverIn: function () {
- isOverPanel = true;
- showBar();
- hideBar();
- },
- hoverOut: function () {
- isOverPanel = false;
- hideBar();
- },
- barHoverIn: function () {
- isOverBar = true;
- },
- barHoverOut: function () {
- isOverBar = false;
- },
- railHoverIn: function () {
- showBar();
- },
- railHoverOut: function () {
- hideBar();
- },
- barMouseDown: function (e) {
- var $doc = $(document);
- var t = parseFloat(bar.css('top'));
- var pageY = e.pageY;
- isDragg = true;
- function mousemove(e) {
- var currTop = t + e.pageY - pageY;
- bar.css({ top: currTop });
- scrollContent(0, currTop, false);// scroll content
- }
- function mouseup(e) {
- isDragg = false; hideBar();
- $doc.unbind('mousemove', mousemove);
- $doc.unbind('mouseup', mouseup);
- }
- $doc.bind('mousemove', mousemove);
- $doc.bind('mouseup', mouseup);
- return false;
- },
- barSelectedStart: function (e) {
- e.stopPropagation();
- e.preventDefault();
- return false;
- }
- }
- // make it draggable and no longer dependent on the jqueryUI
- if (o.railDraggable) {
- bar.bind('mousedown', events.barMouseDown).bind('selectstart', events.barSelectedStart);
- }
- // on rail over
- rail.hover(events.railHoverIn, events.railHoverOut);
- // on bar over
- bar.hover(events.barHoverIn, events.barHoverOut);
- // show on parent mouseover
- me.hover(events.hoverIn, events.hoverOut);
- // support for mobile
- me.bind('touchstart', events.touchStart);
- me.bind('touchmove', events.touchMove);
- // set up initial height
- getBarHeight();
- // check start position
- if (o.start === 'bottom') {
- // scroll content to bottom
- bar.css({ top: me.outerHeight() - bar.outerHeight() });
- scrollContent(0, true);
- }
- else if (o.start !== 'top') {
- // assume jQuery selector
- scrollContent($(o.start).position().top, null, true);
- // make sure bar stays hidden
- if (!o.alwaysVisible) { bar.hide(); }
- }
- // attach scroll events
- attachWheel(el);
- function _onWheel(e) {
- // use mouse wheel only when mouse is over
- if (!isOverPanel) { return; }
- e = e || window.event;
- var delta = 0;
- if (e.wheelDelta) { delta = -e.wheelDelta / 120; }
- if (e.detail) { delta = e.detail / 3; }
- var target = e.target || e.srcTarget || e.srcElement;
- if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {
- // scroll content
- scrollContent(delta, true);
- }
- // stop window scroll
- if (e.preventDefault && !releaseScroll) { e.preventDefault(); }
- if (!releaseScroll) { e.returnValue = false; }
- }
- function scrollContent(y, isWheel, isJump) {
- releaseScroll = false;
- var delta = y;
- var maxTop = me.outerHeight() - bar.outerHeight();
- if (isWheel) {
- // move bar with mouse wheel
- delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
- // move bar, make sure it doesn't go out
- delta = Math.min(Math.max(delta, 0), maxTop);
- // if scrolling down, make sure a fractional change to the
- // scroll position isn't rounded away when the scrollbar's CSS is set
- // this flooring of delta would happened automatically when
- // bar.css is set below, but we floor here for clarity
- delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
- // scroll the scrollbar
- bar.css({ top: delta + 'px' });
- }
- // calculate actual scroll amount
- percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight());
- // delta = percentScroll * (me[0].scrollHeight - me.outerHeight());
- delta = percentScroll * (me.el.scrollHeight - me.outerHeight());
- if (isJump) {
- delta = y;
- // var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
- var offsetTop = delta / me.el.scrollHeight * me.outerHeight();
- offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
- bar.css({ top: offsetTop + 'px' });
- }
- // scroll content
- me.scrollTop(delta);
- // fire scrolling event
- me.trigger('slimscrolling', ~~delta);
- // ensure bar is visible
- showBar();
- // trigger hide when scroll is stopped
- hideBar();
- }
- function attachWheel(target) {
- if (window.addEventListener) {
- target.addEventListener('DOMMouseScroll', _onWheel, false);
- target.addEventListener('mousewheel', _onWheel, false);
- }
- else {
- document.attachEvent('onmousewheel', _onWheel)
- }
- }
- function getBarHeight() {
- // calculate scrollbar height and make sure it is not too small
- barHeight = Math.max((me.outerHeight() / me.el.scrollHeight) * me.outerHeight(), minBarHeight);
- bar.css({ height: barHeight + 'px' });
- // hide scrollbar if content is not long enough
- var display = barHeight == me.outerHeight() ? 'none' : 'block';
- bar.css({ display: display });
- }
- function showBar() {
- // recalculate bar height
- getBarHeight();
- clearTimeout(queueHide);
- // when bar reached top or bottom
- if (percentScroll == ~~percentScroll) {
- //release wheel
- releaseScroll = o.allowPageScroll;
- // publish approporiate event
- if (lastScroll != percentScroll) {
- var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
- me.trigger('slimscroll', msg);
- }
- }
- else {
- releaseScroll = false;
- }
- lastScroll = percentScroll;
- // show only when required
- if (barHeight >= me.outerHeight()) {
- //allow window scroll
- releaseScroll = true;
- return;
- }
- // bar.stop(true, true).fadeIn('fast');
- bar.show()
- // if (o.railVisible) { rail.stop(true, true).fadeIn('fast'); }
- if (o.railVisible) { rail.show(); }
- }
- function hideBar() {
- // only hide when options allow it
- if (!o.alwaysVisible) {
- queueHide = setTimeout(function () {
- if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg) {
- // bar.fadeOut('slow');
- // rail.fadeOut('slow');
- bar.hide()
- rail.hide()
- }
- }, 1000);
- }
- }
- // });
- function unbind() {
- // make it draggable and no longer dependent on the jqueryUI
- bar.unbind('mousedown', events.barMouseDown).unbind('selectstart', events.barSelectedStart);
- // on rail over
- rail.unbind('mouseenter', events.railHoverIn).unbind('mouseleave', events.railHoverOut);
- // on bar over
- bar.unbind('mouseenter', events.barHoverIn).unbind('mouseleave', events.barHoverOut);
- // show on parent mouseover
- me.unbind('mouseenter', events.hoverIn).unbind('mouseleave', events.hoverOut);
- // support for mobile
- me.unbind('touchstart', events.touchStart);
- me.unbind('touchmove', events.touchMove);
- }
- return {
- unbind: function () {
- bar.unbind('mousedown', events.barMouseDown)
- .unbind('mouseenter', events.barHoverIn)
- .unbind('mouseleave', events.barHoverOut)
- .unbind('selectstart', events.barSelectedStart);
- rail.unbind('mouseenter', events.railHoverIn)
- .unbind('mouseleave', events.railHoverOut);
- bar.unbind('mouseenter', events.barHoverIn)
- .unbind('mouseleave', events.barHoverOut);
- me.unbind('mouseenter', events.hoverIn)
- .unbind('mouseleave', events.hoverOut)
- .unbind('touchstart', events.touchStart)
- .unbind('touchmove', events.touchMove);
- }
- }
- }
- return SlimScroll
- })()
- var VueSlimScroll = {}
- VueSlimScroll.install = function (Vue) {
- var ss
- Vue.directive('slimscroll', {
- inserted: function (el, binding) {
- ss = SlimScroll(el, binding.value)
- },
- unbind: function () {
- ss.unbind()
- }
- })
- }
- if (typeof exports == "object") {
- module.exports = VueSlimScroll
- } else if (window.Vue) {
- window.VueSlimScroll = VueSlimScroll
- Vue.use(VueSlimScroll)
- }
|