(function ($) { $.fn.extend({ slimScroll: function (options) { var defaults = { width: "auto", height: "250px", size: "7px", color: "#000", position: "right", distance: "1px", start: "top", opacity: .4, alwaysVisible: false, disableFadeOut: false, railVisible: false, railColor: "#333", railOpacity: .2, railDraggable: true, railClass: "slimScrollRail", barClass: "slimScrollBar", wrapperClass: "slimScrollDiv", allowPageScroll: false, wheelStep: 20, touchScrollStep: 200, borderRadius: "7px", railBorderRadius: "7px" }; var o = $.extend(defaults, options); this.each(function () { var isOverPanel, isOverBar, isDragg, queueHide, touchDif, barHeight, percentScroll, lastScroll, divS = "<div></div>", minBarHeight = 30, releaseScroll = false; var me = $(this); if (me.parent().hasClass(o.wrapperClass)) { var offset = me.scrollTop(); bar = me.parent().find("." + o.barClass); rail = me.parent().find("." + o.railClass); getBarHeight(); if ($.isPlainObject(options)) { 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) { offset = parseInt(o.scrollTo) } else if ("scrollBy" in options) { offset += parseInt(o.scrollBy) } else if ("destroy" in options) { bar.remove(); rail.remove(); me.unwrap(); return } scrollContent(offset, false, true) } return } else if ($.isPlainObject(options)) { if ("destroy" in options) { return } } o.height = o.height == "auto" ? me.parent().height() : o.height; var wrapper = $(divS).addClass(o.wrapperClass).css({ position: "relative", overflow: "hidden", width: o.width, height: o.height }); me.css({overflow: "hidden", width: o.width, height: o.height, "-ms-touch-action": "none"}); 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 }); 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 }); var posCss = o.position == "right" ? {right: o.distance} : {left: o.distance}; rail.css(posCss); bar.css(posCss); me.wrap(wrapper); me.parent().append(bar); me.parent().append(rail); 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) }); $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 }) } rail.hover(function () { showBar() }, function () { hideBar() }); bar.hover(function () { isOverBar = true }, function () { isOverBar = false }); me.hover(function () { isOverPanel = true; showBar(); hideBar() }, function () { isOverPanel = false; hideBar() }); if (window.navigator.msPointerEnabled) { me.bind("MSPointerDown", function (e, b) { if (e.originalEvent.targetTouches.length) { touchDif = e.originalEvent.targetTouches[0].pageY } }); me.bind("MSPointerMove", function (e) { e.originalEvent.preventDefault(); if (e.originalEvent.targetTouches.length) { var diff = (touchDif - e.originalEvent.targetTouches[0].pageY) / o.touchScrollStep; scrollContent(diff, true); touchDif = e.originalEvent.targetTouches[0].pageY } }) } else { me.bind("touchstart", function (e, b) { if (e.originalEvent.touches.length) { touchDif = e.originalEvent.touches[0].pageY } }); me.bind("touchmove", function (e) { if (!releaseScroll) { e.originalEvent.preventDefault() } if (e.originalEvent.touches.length) { var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep; scrollContent(diff, true); touchDif = e.originalEvent.touches[0].pageY } }) } getBarHeight(); if (o.start === "bottom") { bar.css({top: me.outerHeight() - bar.outerHeight()}); scrollContent(0, true) } else if (o.start !== "top") { scrollContent($(o.start).position().top, null, true); if (!o.alwaysVisible) { bar.hide() } } attachWheel(); function _onWheel(e) { 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())) { scrollContent(delta, true) } 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) { delta = parseInt(bar.css("top")) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight(); delta = Math.min(Math.max(delta, 0), maxTop); delta = y > 0 ? Math.ceil(delta) : Math.floor(delta); bar.css({top: delta + "px"}) } 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"}) } me.scrollTop(delta); me.trigger("slimscrolling", ~~delta); showBar(); hideBar() } function attachWheel() { if (window.addEventListener) { this.addEventListener("DOMMouseScroll", _onWheel, false); this.addEventListener("mousewheel", _onWheel, false) } else { document.attachEvent("onmousewheel", _onWheel) } } function getBarHeight() { barHeight = Math.max(me.outerHeight() / me[0].scrollHeight * me.outerHeight(), minBarHeight); bar.css({height: barHeight + "px"}); var display = barHeight == me.outerHeight() ? "none" : "block"; bar.css({display: display}) } function showBar() { getBarHeight(); clearTimeout(queueHide); if (percentScroll == ~~percentScroll) { releaseScroll = o.allowPageScroll; if (lastScroll != percentScroll) { var msg = ~~percentScroll == 0 ? "top" : "bottom"; me.trigger("slimscroll", msg) } } else { releaseScroll = false } lastScroll = percentScroll; if (barHeight >= me.outerHeight()) { releaseScroll = true; return } bar.stop(true, true).fadeIn("fast"); if (o.railVisible) { rail.stop(true, true).fadeIn("fast") } } function hideBar() { if (!o.alwaysVisible) { queueHide = setTimeout(function () { if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg) { bar.fadeOut("slow"); rail.fadeOut("slow") } }, 1e3) } } }); return this } }); $.fn.extend({slimscroll: $.fn.slimScroll}) })(jQuery);