123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831 |
- /**
- * jQuery CSS Customizable Scrollbar
- *
- * Copyright 2015, Yuriy Khabarov
- * Dual licensed under the MIT or GPL Version 2 licenses.
- *
- * If you found bug, please contact me via email <13real008@gmail.com>
- *
- * @author Yuriy Khabarov aka Gromo
- * @version 0.2.11
- * @url https://github.com/gromo/jquery.scrollbar/
- *
- */
- ;
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define(['jquery'], factory);
- } else if (typeof exports !== "undefined") {
- factory(require('jquery'));
- } else {
- factory(root.jQuery);
- }
- }(this, function ($) {
- 'use strict';
- // init flags & variables
- var debug = false;
- var browser = {
- data: {
- index: 0,
- name: 'scrollbar'
- },
- firefox: /firefox/i.test(navigator.userAgent),
- macosx: /mac/i.test(navigator.platform),
- msedge: /edge\/\d+/i.test(navigator.userAgent),
- msie: /(msie|trident)/i.test(navigator.userAgent),
- mobile: /android|webos|iphone|ipad|ipod|blackberry/i.test(navigator.userAgent),
- overlay: null,
- scroll: null,
- scrolls: [],
- webkit: /webkit/i.test(navigator.userAgent) && !/edge\/\d+/i.test(navigator.userAgent)
- };
- browser.scrolls.add = function (instance) {
- this.remove(instance).push(instance);
- };
- browser.scrolls.remove = function (instance) {
- while ($.inArray(instance, this) >= 0) {
- this.splice($.inArray(instance, this), 1);
- }
- return this;
- };
- var defaults = {
- autoScrollSize: true, // automatically calculate scrollsize
- autoUpdate: true, // update scrollbar if content/container size changed
- debug: false, // debug mode
- disableBodyScroll: false, // disable body scroll if mouse over container
- duration: 200, // scroll animate duration in ms
- ignoreMobile: false, // ignore mobile devices
- ignoreOverlay: false, // ignore browsers with overlay scrollbars (mobile, MacOS)
- isRtl: false, // is RTL
- scrollStep: 30, // scroll step for scrollbar arrows
- showArrows: false, // add class to show arrows
- stepScrolling: true, // when scrolling to scrollbar mousedown position
- scrollx: null, // horizontal scroll element
- scrolly: null, // vertical scroll element
- onDestroy: null, // callback function on destroy,
- onFallback: null, // callback function if scrollbar is not initialized
- onInit: null, // callback function on first initialization
- onScroll: null, // callback function on content scrolling
- onUpdate: null // callback function on init/resize (before scrollbar size calculation)
- };
- var BaseScrollbar = function (container) {
- if (!browser.scroll) {
- browser.overlay = isScrollOverlaysContent();
- browser.scroll = getBrowserScrollSize();
- updateScrollbars();
- $(window).resize(function () {
- var forceUpdate = false;
- if (browser.scroll && (browser.scroll.height || browser.scroll.width)) {
- var scroll = getBrowserScrollSize();
- if (scroll.height !== browser.scroll.height || scroll.width !== browser.scroll.width) {
- browser.scroll = scroll;
- forceUpdate = true; // handle page zoom
- }
- }
- updateScrollbars(forceUpdate);
- });
- }
- this.container = container;
- this.namespace = '.scrollbar_' + browser.data.index++;
- this.options = $.extend({}, defaults, window.jQueryScrollbarOptions || {});
- this.scrollTo = null;
- this.scrollx = {};
- this.scrolly = {};
- container.data(browser.data.name, this);
- browser.scrolls.add(this);
- };
- BaseScrollbar.prototype = {
- destroy: function () {
- if (!this.wrapper) {
- return;
- }
- this.container.removeData(browser.data.name);
- browser.scrolls.remove(this);
- // init variables
- var scrollLeft = this.container.scrollLeft();
- var scrollTop = this.container.scrollTop();
- this.container.insertBefore(this.wrapper).css({
- "height": "",
- "margin": "",
- "max-height": ""
- })
- .removeClass('scroll-content scroll-scrollx_visible scroll-scrolly_visible')
- .off(this.namespace)
- .scrollLeft(scrollLeft)
- .scrollTop(scrollTop);
- this.scrollx.scroll.removeClass('scroll-scrollx_visible').find('div').addBack().off(this.namespace);
- this.scrolly.scroll.removeClass('scroll-scrolly_visible').find('div').addBack().off(this.namespace);
- this.wrapper.remove();
- $(document).add('body').off(this.namespace);
- if ($.isFunction(this.options.onDestroy)) {
- this.options.onDestroy.apply(this, [this.container]);
- }
- },
- init: function (options) {
- // init variables
- var S = this,
- c = this.container,
- cw = this.containerWrapper || c,
- namespace = this.namespace,
- o = $.extend(this.options, options || {}),
- s = {x: this.scrollx, y: this.scrolly},
- w = this.wrapper,
- cssOptions = {};
- var initScroll = {
- scrollLeft: c.scrollLeft(),
- scrollTop: c.scrollTop()
- };
- // do not init if in ignorable browser
- if ((browser.mobile && o.ignoreMobile)
- || (browser.overlay && o.ignoreOverlay)
- || (browser.macosx && !browser.webkit) // still required to ignore nonWebKit browsers on Mac
- ) {
- if ($.isFunction(o.onFallback)) {
- o.onFallback.apply(this, [c]);
- }
- return false;
- }
- // init scroll container
- if (!w) {
- this.wrapper = w = $('<div>').addClass('scroll-wrapper').addClass(c.attr('class'))
- .css('position', c.css('position') === 'absolute' ? 'absolute' : 'relative')
- .insertBefore(c).append(c);
- if (o.isRtl) {
- w.addClass('scroll--rtl');
- }
- if (c.is('textarea')) {
- this.containerWrapper = cw = $('<div>').insertBefore(c).append(c);
- w.addClass('scroll-textarea');
- }
- cssOptions = {
- "height": "auto",
- "margin-bottom": browser.scroll.height * -1 + 'px',
- "max-height": ""
- };
- cssOptions[o.isRtl ? 'margin-left' : 'margin-right'] = browser.scroll.width * -1 + 'px';
- cw.addClass('scroll-content').css(cssOptions);
- c.on('scroll' + namespace, function (event) {
- var scrollLeft = c.scrollLeft();
- var scrollTop = c.scrollTop();
- if (o.isRtl) {
- // webkit 0:100
- // ie/edge 100:0
- // firefox -100:0
- switch (true) {
- case browser.firefox:
- scrollLeft = Math.abs(scrollLeft);
- case browser.msedge || browser.msie:
- scrollLeft = c[0].scrollWidth - c[0].clientWidth - scrollLeft;
- break;
- }
- }
- if ($.isFunction(o.onScroll)) {
- o.onScroll.call(S, {
- maxScroll: s.y.maxScrollOffset,
- scroll: scrollTop,
- size: s.y.size,
- visible: s.y.visible
- }, {
- maxScroll: s.x.maxScrollOffset,
- scroll: scrollLeft,
- size: s.x.size,
- visible: s.x.visible
- });
- }
- s.x.isVisible && s.x.scroll.bar.css('left', scrollLeft * s.x.kx + 'px');
- s.y.isVisible && s.y.scroll.bar.css('top', scrollTop * s.y.kx + 'px');
- });
- /* prevent native scrollbars to be visible on #anchor click */
- w.on('scroll' + namespace, function () {
- w.scrollTop(0).scrollLeft(0);
- });
- if (o.disableBodyScroll) {
- var handleMouseScroll = function (event) {
- isVerticalScroll(event) ?
- s.y.isVisible && s.y.mousewheel(event) :
- s.x.isVisible && s.x.mousewheel(event);
- };
- w.on('MozMousePixelScroll' + namespace, handleMouseScroll);
- w.on('mousewheel' + namespace, handleMouseScroll);
- if (browser.mobile) {
- w.on('touchstart' + namespace, function (event) {
- var touch = event.originalEvent.touches && event.originalEvent.touches[0] || event;
- var originalTouch = {
- pageX: touch.pageX,
- pageY: touch.pageY
- };
- var originalScroll = {
- left: c.scrollLeft(),
- top: c.scrollTop()
- };
- $(document).on('touchmove' + namespace, function (event) {
- var touch = event.originalEvent.targetTouches && event.originalEvent.targetTouches[0] || event;
- c.scrollLeft(originalScroll.left + originalTouch.pageX - touch.pageX);
- c.scrollTop(originalScroll.top + originalTouch.pageY - touch.pageY);
- event.preventDefault();
- });
- $(document).on('touchend' + namespace, function () {
- $(document).off(namespace);
- });
- });
- }
- }
- if ($.isFunction(o.onInit)) {
- o.onInit.apply(this, [c]);
- }
- } else {
- cssOptions = {
- "height": "auto",
- "margin-bottom": browser.scroll.height * -1 + 'px',
- "max-height": ""
- };
- cssOptions[o.isRtl ? 'margin-left' : 'margin-right'] = browser.scroll.width * -1 + 'px';
- cw.css(cssOptions);
- }
- // init scrollbars & recalculate sizes
- $.each(s, function (d, scrollx) {
- var scrollCallback = null;
- var scrollForward = 1;
- var scrollOffset = (d === 'x') ? 'scrollLeft' : 'scrollTop';
- var scrollStep = o.scrollStep;
- var scrollTo = function () {
- var currentOffset = c[scrollOffset]();
- c[scrollOffset](currentOffset + scrollStep);
- if (scrollForward == 1 && (currentOffset + scrollStep) >= scrollToValue)
- currentOffset = c[scrollOffset]();
- if (scrollForward == -1 && (currentOffset + scrollStep) <= scrollToValue)
- currentOffset = c[scrollOffset]();
- if (c[scrollOffset]() == currentOffset && scrollCallback) {
- scrollCallback();
- }
- }
- var scrollToValue = 0;
- if (!scrollx.scroll) {
- scrollx.scroll = S._getScroll(o['scroll' + d]).addClass('scroll-' + d);
- if (o.showArrows) {
- scrollx.scroll.addClass('scroll-element_arrows_visible');
- }
- scrollx.mousewheel = function (event) {
- if (!scrollx.isVisible || (d === 'x' && isVerticalScroll(event))) {
- return true;
- }
- if (d === 'y' && !isVerticalScroll(event)) {
- s.x.mousewheel(event);
- return true;
- }
- var delta = event.originalEvent.wheelDelta * -1 || event.originalEvent.detail;
- var maxScrollValue = scrollx.size - scrollx.visible - scrollx.offset;
- // fix new mozilla
- if (!delta) {
- if (d === 'x' && !!event.originalEvent.deltaX) {
- delta = event.originalEvent.deltaX * 40;
- } else if (d === 'y' && !!event.originalEvent.deltaY) {
- delta = event.originalEvent.deltaY * 40;
- }
- }
- if ((delta > 0 && scrollToValue < maxScrollValue) || (delta < 0 && scrollToValue > 0)) {
- scrollToValue = scrollToValue + delta;
- if (scrollToValue < 0)
- scrollToValue = 0;
- if (scrollToValue > maxScrollValue)
- scrollToValue = maxScrollValue;
- S.scrollTo = S.scrollTo || {};
- S.scrollTo[scrollOffset] = scrollToValue;
- setTimeout(function () {
- if (S.scrollTo) {
- c.stop().animate(S.scrollTo, 240, 'linear', function () {
- scrollToValue = c[scrollOffset]();
- });
- S.scrollTo = null;
- }
- }, 1);
- }
- event.preventDefault();
- return false;
- };
- scrollx.scroll
- .on('MozMousePixelScroll' + namespace, scrollx.mousewheel)
- .on('mousewheel' + namespace, scrollx.mousewheel)
- .on('mouseenter' + namespace, function () {
- scrollToValue = c[scrollOffset]();
- });
- // handle arrows & scroll inner mousedown event
- scrollx.scroll.find('.scroll-arrow, .scroll-element_track')
- .on('mousedown' + namespace, function (event) {
- if (event.which != 1) // lmb
- return true;
- scrollForward = 1;
- var data = {
- eventOffset: event[(d === 'x') ? 'pageX' : 'pageY'],
- maxScrollValue: scrollx.size - scrollx.visible - scrollx.offset,
- scrollbarOffset: scrollx.scroll.bar.offset()[(d === 'x') ? 'left' : 'top'],
- scrollbarSize: scrollx.scroll.bar[(d === 'x') ? 'outerWidth' : 'outerHeight']()
- };
- var timeout = 0, timer = 0;
- if ($(this).hasClass('scroll-arrow')) {
- scrollForward = $(this).hasClass("scroll-arrow_more") ? 1 : -1;
- scrollStep = o.scrollStep * scrollForward;
- scrollToValue = scrollForward > 0 ? data.maxScrollValue : 0;
- if (o.isRtl) {
- switch(true){
- case browser.firefox:
- scrollToValue = scrollForward > 0 ? 0: data.maxScrollValue * -1;
- break;
- case browser.msie || browser.msedge:
- break;
- }
- }
- } else {
- scrollForward = (data.eventOffset > (data.scrollbarOffset + data.scrollbarSize) ? 1
- : (data.eventOffset < data.scrollbarOffset ? -1 : 0));
- if(d === 'x' && o.isRtl && (browser.msie || browser.msedge))
- scrollForward = scrollForward * -1;
- scrollStep = Math.round(scrollx.visible * 0.75) * scrollForward;
- scrollToValue = (data.eventOffset - data.scrollbarOffset -
- (o.stepScrolling ? (scrollForward == 1 ? data.scrollbarSize : 0)
- : Math.round(data.scrollbarSize / 2)));
- scrollToValue = c[scrollOffset]() + (scrollToValue / scrollx.kx);
- }
- S.scrollTo = S.scrollTo || {};
- S.scrollTo[scrollOffset] = o.stepScrolling ? c[scrollOffset]() + scrollStep : scrollToValue;
- if (o.stepScrolling) {
- scrollCallback = function () {
- scrollToValue = c[scrollOffset]();
- clearInterval(timer);
- clearTimeout(timeout);
- timeout = 0;
- timer = 0;
- };
- timeout = setTimeout(function () {
- timer = setInterval(scrollTo, 40);
- }, o.duration + 100);
- }
- setTimeout(function () {
- if (S.scrollTo) {
- c.animate(S.scrollTo, o.duration);
- S.scrollTo = null;
- }
- }, 1);
- return S._handleMouseDown(scrollCallback, event);
- });
- // handle scrollbar drag'n'drop
- scrollx.scroll.bar.on('mousedown' + namespace, function (event) {
- if (event.which != 1) // lmb
- return true;
- var eventPosition = event[(d === 'x') ? 'pageX' : 'pageY'];
- var initOffset = c[scrollOffset]();
- scrollx.scroll.addClass('scroll-draggable');
- $(document).on('mousemove' + namespace, function (event) {
- var diff = parseInt((event[(d === 'x') ? 'pageX' : 'pageY'] - eventPosition) / scrollx.kx, 10);
- if (d === 'x' && o.isRtl && (browser.msie || browser.msedge))
- diff = diff * -1;
- c[scrollOffset](initOffset + diff);
- });
- return S._handleMouseDown(function () {
- scrollx.scroll.removeClass('scroll-draggable');
- scrollToValue = c[scrollOffset]();
- }, event);
- });
- }
- });
- // remove classes & reset applied styles
- $.each(s, function (d, scrollx) {
- var scrollClass = 'scroll-scroll' + d + '_visible';
- var scrolly = (d == "x") ? s.y : s.x;
- scrollx.scroll.removeClass(scrollClass);
- scrolly.scroll.removeClass(scrollClass);
- cw.removeClass(scrollClass);
- });
- // calculate init sizes
- $.each(s, function (d, scrollx) {
- $.extend(scrollx, (d == "x") ? {
- offset: parseInt(c.css('left'), 10) || 0,
- size: c.prop('scrollWidth'),
- visible: w.width()
- } : {
- offset: parseInt(c.css('top'), 10) || 0,
- size: c.prop('scrollHeight'),
- visible: w.height()
- });
- });
- // update scrollbar visibility/dimensions
- this._updateScroll('x', this.scrollx);
- this._updateScroll('y', this.scrolly);
- if ($.isFunction(o.onUpdate)) {
- o.onUpdate.apply(this, [c]);
- }
- // calculate scroll size
- $.each(s, function (d, scrollx) {
- var cssOffset = (d === 'x') ? 'left' : 'top';
- var cssFullSize = (d === 'x') ? 'outerWidth' : 'outerHeight';
- var cssSize = (d === 'x') ? 'width' : 'height';
- var offset = parseInt(c.css(cssOffset), 10) || 0;
- var AreaSize = scrollx.size;
- var AreaVisible = scrollx.visible + offset;
- var scrollSize = scrollx.scroll.size[cssFullSize]() + (parseInt(scrollx.scroll.size.css(cssOffset), 10) || 0);
- if (o.autoScrollSize) {
- scrollx.scrollbarSize = parseInt(scrollSize * AreaVisible / AreaSize, 10);
- scrollx.scroll.bar.css(cssSize, scrollx.scrollbarSize + 'px');
- }
- scrollx.scrollbarSize = scrollx.scroll.bar[cssFullSize]();
- scrollx.kx = ((scrollSize - scrollx.scrollbarSize) / (AreaSize - AreaVisible)) || 1;
- scrollx.maxScrollOffset = AreaSize - AreaVisible;
- });
- c.scrollLeft(initScroll.scrollLeft).scrollTop(initScroll.scrollTop).trigger('scroll');
- },
- /**
- * Get scrollx/scrolly object
- *
- * @param {Mixed} scroll
- * @returns {jQuery} scroll object
- */
- _getScroll: function (scroll) {
- var types = {
- advanced: [
- '<div class="scroll-element">',
- '<div class="scroll-element_corner"></div>',
- '<div class="scroll-arrow scroll-arrow_less"></div>',
- '<div class="scroll-arrow scroll-arrow_more"></div>',
- '<div class="scroll-element_outer">',
- '<div class="scroll-element_size"></div>', // required! used for scrollbar size calculation !
- '<div class="scroll-element_inner-wrapper">',
- '<div class="scroll-element_inner scroll-element_track">', // used for handling scrollbar click
- '<div class="scroll-element_inner-bottom"></div>',
- '</div>',
- '</div>',
- '<div class="scroll-bar">', // required
- '<div class="scroll-bar_body">',
- '<div class="scroll-bar_body-inner"></div>',
- '</div>',
- '<div class="scroll-bar_bottom"></div>',
- '<div class="scroll-bar_center"></div>',
- '</div>',
- '</div>',
- '</div>'
- ].join(''),
- simple: [
- '<div class="scroll-element">',
- '<div class="scroll-element_outer">',
- '<div class="scroll-element_size"></div>', // required! used for scrollbar size calculation !
- '<div class="scroll-element_track"></div>', // used for handling scrollbar click
- '<div class="scroll-bar"></div>', // required
- '</div>',
- '</div>'
- ].join('')
- };
- if (types[scroll]) {
- scroll = types[scroll];
- }
- if (!scroll) {
- scroll = types['simple'];
- }
- if (typeof (scroll) == 'string') {
- scroll = $(scroll).appendTo(this.wrapper);
- } else {
- scroll = $(scroll);
- }
- $.extend(scroll, {
- bar: scroll.find('.scroll-bar'),
- size: scroll.find('.scroll-element_size'),
- track: scroll.find('.scroll-element_track')
- });
- return scroll;
- },
- _handleMouseDown: function (callback, event) {
- var namespace = this.namespace;
- $(document).on('blur' + namespace, function () {
- $(document).add('body').off(namespace);
- callback && callback();
- });
- $(document).on('dragstart' + namespace, function (event) {
- event.preventDefault();
- return false;
- });
- $(document).on('mouseup' + namespace, function () {
- $(document).add('body').off(namespace);
- callback && callback();
- });
- $('body').on('selectstart' + namespace, function (event) {
- event.preventDefault();
- return false;
- });
- event && event.preventDefault();
- return false;
- },
- _updateScroll: function (d, scrollx) {
- var container = this.container,
- containerWrapper = this.containerWrapper || container,
- scrollClass = 'scroll-scroll' + d + '_visible',
- scrolly = (d === 'x') ? this.scrolly : this.scrollx,
- offset = parseInt(this.container.css((d === 'x') ? 'left' : 'top'), 10) || 0,
- wrapper = this.wrapper;
- var AreaSize = scrollx.size;
- var AreaVisible = scrollx.visible + offset;
- scrollx.isVisible = (AreaSize - AreaVisible) > 1; // bug in IE9/11 with 1px diff
- if (scrollx.isVisible) {
- scrollx.scroll.addClass(scrollClass);
- scrolly.scroll.addClass(scrollClass);
- containerWrapper.addClass(scrollClass);
- } else {
- scrollx.scroll.removeClass(scrollClass);
- scrolly.scroll.removeClass(scrollClass);
- containerWrapper.removeClass(scrollClass);
- }
- if (d === 'y') {
- if (container.is('textarea') || AreaSize < AreaVisible) {
- containerWrapper.css({
- "height": (AreaVisible + browser.scroll.height) + 'px',
- "max-height": "none"
- });
- } else {
- containerWrapper.css({
- //"height": "auto", // do not reset height value: issue with height:100%!
- "max-height": (AreaVisible + browser.scroll.height) + 'px'
- });
- }
- }
- if (scrollx.size != container.prop('scrollWidth')
- || scrolly.size != container.prop('scrollHeight')
- || scrollx.visible != wrapper.width()
- || scrolly.visible != wrapper.height()
- || scrollx.offset != (parseInt(container.css('left'), 10) || 0)
- || scrolly.offset != (parseInt(container.css('top'), 10) || 0)
- ) {
- $.extend(this.scrollx, {
- offset: parseInt(container.css('left'), 10) || 0,
- size: container.prop('scrollWidth'),
- visible: wrapper.width()
- });
- $.extend(this.scrolly, {
- offset: parseInt(container.css('top'), 10) || 0,
- size: this.container.prop('scrollHeight'),
- visible: wrapper.height()
- });
- this._updateScroll(d === 'x' ? 'y' : 'x', scrolly);
- }
- }
- };
- var CustomScrollbar = BaseScrollbar;
- /*
- * Extend jQuery as plugin
- *
- * @param {Mixed} command to execute
- * @param {Mixed} arguments as Array
- * @return {jQuery}
- */
- $.fn.scrollbar = function (command, args) {
- if (typeof command !== 'string') {
- args = command;
- command = 'init';
- }
- if (typeof args === 'undefined') {
- args = [];
- }
- if (!$.isArray(args)) {
- args = [args];
- }
- this.not('body, .scroll-wrapper').each(function () {
- var element = $(this),
- instance = element.data(browser.data.name);
- if (instance || command === 'init') {
- if (!instance) {
- instance = new CustomScrollbar(element);
- }
- if (instance[command]) {
- instance[command].apply(instance, args);
- }
- }
- });
- return this;
- };
- /**
- * Connect default options to global object
- */
- $.fn.scrollbar.options = defaults;
- /**
- * Check if scroll content/container size is changed
- */
- var updateScrollbars = (function () {
- var timer = 0,
- timerCounter = 0;
- return function (force) {
- var i, container, options, scroll, wrapper, scrollx, scrolly;
- for (i = 0; i < browser.scrolls.length; i++) {
- scroll = browser.scrolls[i];
- container = scroll.container;
- options = scroll.options;
- wrapper = scroll.wrapper;
- scrollx = scroll.scrollx;
- scrolly = scroll.scrolly;
- if (force || (options.autoUpdate && wrapper && wrapper.is(':visible') &&
- (container.prop('scrollWidth') != scrollx.size || container.prop('scrollHeight') != scrolly.size || wrapper.width() != scrollx.visible || wrapper.height() != scrolly.visible))) {
- scroll.init();
- if (options.debug) {
- window.console && console.log({
- scrollHeight: container.prop('scrollHeight') + ':' + scroll.scrolly.size,
- scrollWidth: container.prop('scrollWidth') + ':' + scroll.scrollx.size,
- visibleHeight: wrapper.height() + ':' + scroll.scrolly.visible,
- visibleWidth: wrapper.width() + ':' + scroll.scrollx.visible
- }, true);
- timerCounter++;
- }
- }
- }
- if (debug && timerCounter > 10) {
- window.console && console.log('Scroll updates exceed 10');
- updateScrollbars = function () {};
- } else {
- clearTimeout(timer);
- timer = setTimeout(updateScrollbars, 300);
- }
- };
- })();
- /* ADDITIONAL FUNCTIONS */
- /**
- * Get native browser scrollbar size (height/width)
- *
- * @param {Boolean} actual size or CSS size, default - CSS size
- * @returns {Object} with height, width
- */
- function getBrowserScrollSize(actualSize) {
- if (browser.webkit && !actualSize) {
- return {
- height: 0,
- width: 0
- };
- }
- if (!browser.data.outer) {
- var css = {
- "border": "none",
- "box-sizing": "content-box",
- "height": "200px",
- "margin": "0",
- "padding": "0",
- "width": "200px"
- };
- browser.data.inner = $("<div>").css($.extend({}, css));
- browser.data.outer = $("<div>").css($.extend({
- "left": "-1000px",
- "overflow": "scroll",
- "position": "absolute",
- "top": "-1000px"
- }, css)).append(browser.data.inner).appendTo("body");
- }
- browser.data.outer.scrollLeft(1000).scrollTop(1000);
- return {
- height: Math.ceil((browser.data.outer.offset().top - browser.data.inner.offset().top) || 0),
- width: Math.ceil((browser.data.outer.offset().left - browser.data.inner.offset().left) || 0)
- };
- }
- /**
- * Check if native browser scrollbars overlay content
- *
- * @returns {Boolean}
- */
- function isScrollOverlaysContent() {
- var scrollSize = getBrowserScrollSize(true);
- return !(scrollSize.height || scrollSize.width);
- }
- function isVerticalScroll(event) {
- var e = event.originalEvent;
- if (e.axis && e.axis === e.HORIZONTAL_AXIS)
- return false;
- if (e.wheelDeltaX)
- return false;
- return true;
- }
- /**
- * Extend AngularJS as UI directive
- * and expose a provider for override default config
- *
- */
- if (window.angular) {
- (function (angular) {
- angular.module('jQueryScrollbar', [])
- .provider('jQueryScrollbar', function () {
- var defaultOptions = defaults;
- return {
- setOptions: function (options) {
- angular.extend(defaultOptions, options);
- },
- $get: function () {
- return {
- options: angular.copy(defaultOptions)
- };
- }
- };
- })
- .directive('jqueryScrollbar', ['jQueryScrollbar', '$parse', function (jQueryScrollbar, $parse) {
- return {
- restrict: "AC",
- link: function (scope, element, attrs) {
- var model = $parse(attrs.jqueryScrollbar),
- options = model(scope);
- element.scrollbar(options || jQueryScrollbar.options)
- .on('$destroy', function () {
- element.scrollbar('destroy');
- });
- }
- };
- }]);
- })(window.angular);
- }
- }));
|