| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 | /*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. * * Version: 1.3.3 * */(function ($) {  $.fn.extend({    slimScroll: function (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: .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: .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);        // 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.parent().find('.' + o.barClass);          rail = me.parent().find('.' + 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().height();              me.parent().css('height', height);              me.css('height', height);            }            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().height() : 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,          //Fix for IE10          "-ms-touch-action": "none"        });        // 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: 90                });        // 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: 99                });        // 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);        // make it draggable and no longer dependent on the jqueryUI        if (o.railDraggable) {          bar.bind("mousedown", function (e) {            var $doc = $(document);            isDragg = true;            t = parseFloat(bar.css('top'));            pageY = e.pageY;            $doc.bind("mousemove.slimscroll", function (e) {              currTop = t + e.pageY - pageY;              bar.css('top', currTop);              scrollContent(0, bar.position().top, false);// scroll content            });            $doc.bind("mouseup.slimscroll", function (e) {              isDragg = false;              hideBar();              $doc.unbind('.slimscroll');            });            return false;          }).bind("selectstart.slimscroll", function (e) {            e.stopPropagation();            e.preventDefault();            return false;          });        }        // on rail over        rail.hover(function () {          showBar();        }, function () {          hideBar();        });        // on bar over        bar.hover(function () {          isOverBar = true;        }, function () {          isOverBar = false;        });        // show on parent mouseover        me.hover(function () {          isOverPanel = true;          showBar();          hideBar();        }, function () {          isOverPanel = false;          hideBar();        });        if (window.navigator.msPointerEnabled) {                    // support for mobile          me.bind('MSPointerDown', function (e, b) {            if (e.originalEvent.targetTouches.length)            {              // record where touch started              touchDif = e.originalEvent.targetTouches[0].pageY;            }          });          me.bind('MSPointerMove', function (e) {            // prevent scrolling the page if necessary            e.originalEvent.preventDefault();            if (e.originalEvent.targetTouches.length)            {              // see how far user swiped              var diff = (touchDif - e.originalEvent.targetTouches[0].pageY) / o.touchScrollStep;              // scroll content              scrollContent(diff, true);              touchDif = e.originalEvent.targetTouches[0].pageY;                          }          });        } else {          // support for mobile          me.bind('touchstart', function (e, b) {            if (e.originalEvent.touches.length)            {              // record where touch started              touchDif = e.originalEvent.touches[0].pageY;            }          });          me.bind('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;            }          });        }        // 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();        function _onWheel(e)        {          // use mouse wheel only when mouse is over          if (!isOverPanel) {            return;          }          var 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());          if (isJump)          {            delta = y;            var offsetTop = delta / me[0].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()        {          if (window.addEventListener)          {            this.addEventListener('DOMMouseScroll', _onWheel, false);            this.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[0].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');          if (o.railVisible) {            rail.stop(true, true).fadeIn('fast');          }        }        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');              }            }, 1000);          }        }      });      // maintain chainability      return this;    }  });  $.fn.extend({    slimscroll: $.fn.slimScroll  });})(jQuery);
 |