/* == malihu jquery custom scrollbars plugin == version: 2.8.1 author: malihu (http://manos.malihu.gr) plugin home: http://manos.malihu.gr/jquery-custom-content-scroller */ /* Copyright 2010-2013 Manos Malihutsakis This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ (function ($) { /*plugin script*/ var methods = { init: function (options) { var defaults = { set_width: false, /*optional element width: boolean, pixels, percentage*/ set_height: false, /*optional element height: boolean, pixels, percentage*/ horizontalScroll: false, /*scroll horizontally: boolean*/ scrollInertia: 950, /*scrolling inertia: integer (milliseconds)*/ mouseWheel: true, /*mousewheel support: boolean*/ mouseWheelPixels: "auto", /*mousewheel pixels amount: integer, "auto"*/ autoDraggerLength: true, /*auto-adjust scrollbar dragger length: boolean*/ autoHideScrollbar: false, /*auto-hide scrollbar when idle*/ scrollButtons: { /*scroll buttons*/ enable: false, /*scroll buttons support: boolean*/ scrollType: "continuous", /*scroll buttons scrolling type: "continuous", "pixels"*/ scrollSpeed: "auto", /*scroll buttons continuous scrolling speed: integer, "auto"*/ scrollAmount: 40 /*scroll buttons pixels scroll amount: integer (pixels)*/ }, advanced: { updateOnBrowserResize: true, /*update scrollbars on browser resize (for layouts based on percentages): boolean*/ updateOnContentResize: false, /*auto-update scrollbars on content resize (for dynamic content): boolean*/ autoExpandHorizontalScroll: false, /*auto-expand width for horizontal scrolling: boolean*/ autoScrollOnFocus: true, /*auto-scroll on focused elements: boolean*/ normalizeMouseWheelDelta: false /*normalize mouse-wheel delta (-1/1)*/ }, contentTouchScroll: true, /*scrolling by touch-swipe content: boolean*/ callbacks: { onScrollStart: function () { }, /*user custom callback function on scroll start event*/ onScroll: function () { }, /*user custom callback function on scroll event*/ onTotalScroll: function () { }, /*user custom callback function on scroll end reached event*/ onTotalScrollBack: function () { }, /*user custom callback function on scroll begin reached event*/ onTotalScrollOffset: 0, /*scroll end reached offset: integer (pixels)*/ onTotalScrollBackOffset: 0, /*scroll begin reached offset: integer (pixels)*/ whileScrolling: function () { } /*user custom callback function on scrolling event*/ }, theme: "light" /*"light", "dark", "light-2", "dark-2", "light-thick", "dark-thick", "light-thin", "dark-thin"*/ }, options = $.extend(true, defaults, options); return this.each(function () { var $this = $(this); /*set element width/height, create markup for custom scrollbars, add classes*/ if (options.set_width) { $this.css("width", options.set_width); } if (options.set_height) { $this.css("height", options.set_height); } if (!$(document).data("mCustomScrollbar-index")) { $(document).data("mCustomScrollbar-index", "1"); } else { var mCustomScrollbarIndex = parseInt($(document).data("mCustomScrollbar-index")); $(document).data("mCustomScrollbar-index", mCustomScrollbarIndex + 1); } $this.wrapInner("
").addClass("mCustomScrollbar _mCS_" + $(document).data("mCustomScrollbar-index")); var mCustomScrollBox = $this.children(".mCustomScrollBox"); if (options.horizontalScroll) { mCustomScrollBox.addClass("mCSB_horizontal").wrapInner("
"); var mCSB_h_wrapper = mCustomScrollBox.children(".mCSB_h_wrapper"); mCSB_h_wrapper.wrapInner("
").children(".mCSB_container").css({ "width": mCSB_h_wrapper.children().outerWidth(), "position": "relative" }).unwrap(); } else { mCustomScrollBox.wrapInner("
"); } var mCSB_container = mCustomScrollBox.children(".mCSB_container"); if ($.support.touch) { mCSB_container.addClass("mCS_touch"); } mCSB_container.after("
"); var mCSB_scrollTools = mCustomScrollBox.children(".mCSB_scrollTools"), mCSB_draggerContainer = mCSB_scrollTools.children(".mCSB_draggerContainer"), mCSB_dragger = mCSB_draggerContainer.children(".mCSB_dragger"); if (options.horizontalScroll) { mCSB_dragger.data("minDraggerWidth", mCSB_dragger.width()); } else { mCSB_dragger.data("minDraggerHeight", mCSB_dragger.height()); } if (options.scrollButtons.enable) { if (options.horizontalScroll) { mCSB_scrollTools.prepend("").append(""); } else { mCSB_scrollTools.prepend("").append(""); } } /*mCustomScrollBox scrollTop and scrollLeft is always 0 to prevent browser focus scrolling*/ mCustomScrollBox.bind("scroll", function () { if (!$this.is(".mCS_disabled")) { /*native focus scrolling for disabled scrollbars*/ mCustomScrollBox.scrollTop(0).scrollLeft(0); } }); /*store options, global vars/states, intervals*/ $this.data({ /*init state*/ "mCS_Init": true, /*instance index*/ "mCustomScrollbarIndex": $(document).data("mCustomScrollbar-index"), /*option parameters*/ "horizontalScroll": options.horizontalScroll, "scrollInertia": options.scrollInertia, "scrollEasing": "mcsEaseOut", "mouseWheel": options.mouseWheel, "mouseWheelPixels": options.mouseWheelPixels, "autoDraggerLength": options.autoDraggerLength, "autoHideScrollbar": options.autoHideScrollbar, "scrollButtons_enable": options.scrollButtons.enable, "scrollButtons_scrollType": options.scrollButtons.scrollType, "scrollButtons_scrollSpeed": options.scrollButtons.scrollSpeed, "scrollButtons_scrollAmount": options.scrollButtons.scrollAmount, "autoExpandHorizontalScroll": options.advanced.autoExpandHorizontalScroll, "autoScrollOnFocus": options.advanced.autoScrollOnFocus, "normalizeMouseWheelDelta": options.advanced.normalizeMouseWheelDelta, "contentTouchScroll": options.contentTouchScroll, "onScrollStart_Callback": options.callbacks.onScrollStart, "onScroll_Callback": options.callbacks.onScroll, "onTotalScroll_Callback": options.callbacks.onTotalScroll, "onTotalScrollBack_Callback": options.callbacks.onTotalScrollBack, "onTotalScroll_Offset": options.callbacks.onTotalScrollOffset, "onTotalScrollBack_Offset": options.callbacks.onTotalScrollBackOffset, "whileScrolling_Callback": options.callbacks.whileScrolling, /*events binding state*/ "bindEvent_scrollbar_drag": false, "bindEvent_content_touch": false, "bindEvent_scrollbar_click": false, "bindEvent_mousewheel": false, "bindEvent_buttonsContinuous_y": false, "bindEvent_buttonsContinuous_x": false, "bindEvent_buttonsPixels_y": false, "bindEvent_buttonsPixels_x": false, "bindEvent_focusin": false, "bindEvent_autoHideScrollbar": false, /*buttons intervals*/ "mCSB_buttonScrollRight": false, "mCSB_buttonScrollLeft": false, "mCSB_buttonScrollDown": false, "mCSB_buttonScrollUp": false }); /*max-width/max-height*/ if (options.horizontalScroll) { if ($this.css("max-width") !== "none") { if (!options.advanced.updateOnContentResize) { /*needs updateOnContentResize*/ options.advanced.updateOnContentResize = true; } } } else { if ($this.css("max-height") !== "none") { var percentage = false, maxHeight = parseInt($this.css("max-height")); if ($this.css("max-height").indexOf("%") >= 0) { percentage = maxHeight, maxHeight = $this.parent().height() * percentage / 100; } $this.css("overflow", "hidden"); mCustomScrollBox.css("max-height", maxHeight); } } $this.mCustomScrollbar("update"); /*window resize fn (for layouts based on percentages)*/ if (options.advanced.updateOnBrowserResize) { var mCSB_resizeTimeout, currWinWidth = $(window).width(), currWinHeight = $(window).height(); $(window).bind("resize." + $this.data("mCustomScrollbarIndex"), function () { if (mCSB_resizeTimeout) { clearTimeout(mCSB_resizeTimeout); } mCSB_resizeTimeout = setTimeout(function () { if (!$this.is(".mCS_disabled") && !$this.is(".mCS_destroyed")) { var winWidth = $(window).width(), winHeight = $(window).height(); if (currWinWidth !== winWidth || currWinHeight !== winHeight) { /*ie8 fix*/ if ($this.css("max-height") !== "none" && percentage) { mCustomScrollBox.css("max-height", $this.parent().height() * percentage / 100); } $this.mCustomScrollbar("update"); currWinWidth = winWidth; currWinHeight = winHeight; } } }, 150); }); } /*content resize fn (for dynamically generated content)*/ if (options.advanced.updateOnContentResize) { var mCSB_onContentResize; if (options.horizontalScroll) { var mCSB_containerOldSize = mCSB_container.outerWidth(); } else { var mCSB_containerOldSize = mCSB_container.outerHeight(); } mCSB_onContentResize = setInterval(function () { if (options.horizontalScroll) { if (options.advanced.autoExpandHorizontalScroll) { mCSB_container.css({ "position": "absolute", "width": "auto" }).wrap("
").css({ "width": mCSB_container.outerWidth(), "position": "relative" }).unwrap(); } var mCSB_containerNewSize = mCSB_container.outerWidth(); } else { var mCSB_containerNewSize = mCSB_container.outerHeight(); } if (mCSB_containerNewSize != mCSB_containerOldSize) { $this.mCustomScrollbar("update"); mCSB_containerOldSize = mCSB_containerNewSize; } }, 300); } }); }, update: function () { var $this = $(this), mCustomScrollBox = $this.children(".mCustomScrollBox"), mCSB_container = mCustomScrollBox.children(".mCSB_container"); mCSB_container.removeClass("mCS_no_scrollbar"); $this.removeClass("mCS_disabled mCS_destroyed"); mCustomScrollBox.scrollTop(0).scrollLeft(0); /*reset scrollTop/scrollLeft to prevent browser focus scrolling*/ var mCSB_scrollTools = mCustomScrollBox.children(".mCSB_scrollTools"), mCSB_draggerContainer = mCSB_scrollTools.children(".mCSB_draggerContainer"), mCSB_dragger = mCSB_draggerContainer.children(".mCSB_dragger"); if ($this.data("horizontalScroll")) { var mCSB_buttonLeft = mCSB_scrollTools.children(".mCSB_buttonLeft"), mCSB_buttonRight = mCSB_scrollTools.children(".mCSB_buttonRight"), mCustomScrollBoxW = mCustomScrollBox.width(); if ($this.data("autoExpandHorizontalScroll")) { mCSB_container.css({ "position": "absolute", "width": "auto" }).wrap("
").css({ "width": mCSB_container.outerWidth(), "position": "relative" }).unwrap(); } var mCSB_containerW = mCSB_container.outerWidth(); } else { var mCSB_buttonUp = mCSB_scrollTools.children(".mCSB_buttonUp"), mCSB_buttonDown = mCSB_scrollTools.children(".mCSB_buttonDown"), mCustomScrollBoxH = mCustomScrollBox.height(), mCSB_containerH = mCSB_container.outerHeight(); } if (mCSB_containerH > mCustomScrollBoxH && !$this.data("horizontalScroll")) { /*content needs vertical scrolling*/ mCSB_scrollTools.css("display", "block"); var mCSB_draggerContainerH = mCSB_draggerContainer.height(); /*auto adjust scrollbar dragger length analogous to content*/ if ($this.data("autoDraggerLength")) { var draggerH = Math.round(mCustomScrollBoxH / mCSB_containerH * mCSB_draggerContainerH), minDraggerH = mCSB_dragger.data("minDraggerHeight"); if (draggerH <= minDraggerH) { /*min dragger height*/ mCSB_dragger.css({"height": minDraggerH}); } else if (draggerH >= mCSB_draggerContainerH - 10) { /*max dragger height*/ var mCSB_draggerContainerMaxH = mCSB_draggerContainerH - 10; mCSB_dragger.css({"height": mCSB_draggerContainerMaxH}); } else { mCSB_dragger.css({"height": draggerH}); } mCSB_dragger.children(".mCSB_dragger_bar").css({"line-height": mCSB_dragger.height() + "px"}); } var mCSB_draggerH = mCSB_dragger.height(), /*calculate and store scroll amount, add scrolling*/ scrollAmount = (mCSB_containerH - mCustomScrollBoxH) / (mCSB_draggerContainerH - mCSB_draggerH); $this.data("scrollAmount", scrollAmount).mCustomScrollbar("scrolling", mCustomScrollBox, mCSB_container, mCSB_draggerContainer, mCSB_dragger, mCSB_buttonUp, mCSB_buttonDown, mCSB_buttonLeft, mCSB_buttonRight); /*scroll*/ var mCSB_containerP = Math.abs(mCSB_container.position().top); $this.mCustomScrollbar("scrollTo", mCSB_containerP, {scrollInertia: 0, trigger: "internal"}); } else if (mCSB_containerW > mCustomScrollBoxW && $this.data("horizontalScroll")) { /*content needs horizontal scrolling*/ mCSB_scrollTools.css("display", "block"); var mCSB_draggerContainerW = mCSB_draggerContainer.width(); /*auto adjust scrollbar dragger length analogous to content*/ if ($this.data("autoDraggerLength")) { var draggerW = Math.round(mCustomScrollBoxW / mCSB_containerW * mCSB_draggerContainerW), minDraggerW = mCSB_dragger.data("minDraggerWidth"); if (draggerW <= minDraggerW) { /*min dragger height*/ mCSB_dragger.css({"width": minDraggerW}); } else if (draggerW >= mCSB_draggerContainerW - 10) { /*max dragger height*/ var mCSB_draggerContainerMaxW = mCSB_draggerContainerW - 10; mCSB_dragger.css({"width": mCSB_draggerContainerMaxW}); } else { mCSB_dragger.css({"width": draggerW}); } } var mCSB_draggerW = mCSB_dragger.width(), /*calculate and store scroll amount, add scrolling*/ scrollAmount = (mCSB_containerW - mCustomScrollBoxW) / (mCSB_draggerContainerW - mCSB_draggerW); $this.data("scrollAmount", scrollAmount).mCustomScrollbar("scrolling", mCustomScrollBox, mCSB_container, mCSB_draggerContainer, mCSB_dragger, mCSB_buttonUp, mCSB_buttonDown, mCSB_buttonLeft, mCSB_buttonRight); /*scroll*/ var mCSB_containerP = Math.abs(mCSB_container.position().left); $this.mCustomScrollbar("scrollTo", mCSB_containerP, {scrollInertia: 0, trigger: "internal"}); } else { /*content does not need scrolling*/ /*unbind events, reset content position, hide scrollbars, remove classes*/ mCustomScrollBox.unbind("mousewheel focusin"); if ($this.data("horizontalScroll")) { mCSB_dragger.add(mCSB_container).css("left", 0); } else { mCSB_dragger.add(mCSB_container).css("top", 0); } mCSB_scrollTools.css("display", "none"); mCSB_container.addClass("mCS_no_scrollbar"); $this.data({"bindEvent_mousewheel": false, "bindEvent_focusin": false}); } }, scrolling: function (mCustomScrollBox, mCSB_container, mCSB_draggerContainer, mCSB_dragger, mCSB_buttonUp, mCSB_buttonDown, mCSB_buttonLeft, mCSB_buttonRight) { var $this = $(this); /*scrollbar drag scrolling*/ if (!$this.data("bindEvent_scrollbar_drag")) { var mCSB_draggerDragY, mCSB_draggerDragX; if ($.support.msPointer) { /*MSPointer*/ mCSB_dragger.bind("MSPointerDown", function (e) { e.preventDefault(); $this.data({"on_drag": true}); mCSB_dragger.addClass("mCSB_dragger_onDrag"); var elem = $(this), elemOffset = elem.offset(), x = e.originalEvent.pageX - elemOffset.left, y = e.originalEvent.pageY - elemOffset.top; if (x < elem.width() && x > 0 && y < elem.height() && y > 0) { mCSB_draggerDragY = y; mCSB_draggerDragX = x; } }); $(document).bind("MSPointerMove." + $this.data("mCustomScrollbarIndex"), function (e) { e.preventDefault(); if ($this.data("on_drag")) { var elem = mCSB_dragger, elemOffset = elem.offset(), x = e.originalEvent.pageX - elemOffset.left, y = e.originalEvent.pageY - elemOffset.top; scrollbarDrag(mCSB_draggerDragY, mCSB_draggerDragX, y, x); } }).bind("MSPointerUp." + $this.data("mCustomScrollbarIndex"), function (e) { $this.data({"on_drag": false}); mCSB_dragger.removeClass("mCSB_dragger_onDrag"); }); } else { /*mouse/touch*/ mCSB_dragger.bind("mousedown touchstart", function (e) { e.preventDefault(); e.stopImmediatePropagation(); var elem = $(this), elemOffset = elem.offset(), x, y; if (e.type === "touchstart") { var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; x = touch.pageX - elemOffset.left; y = touch.pageY - elemOffset.top; } else { $this.data({"on_drag": true}); mCSB_dragger.addClass("mCSB_dragger_onDrag"); x = e.pageX - elemOffset.left; y = e.pageY - elemOffset.top; } if (x < elem.width() && x > 0 && y < elem.height() && y > 0) { mCSB_draggerDragY = y; mCSB_draggerDragX = x; } }).bind("touchmove", function (e) { e.preventDefault(); e.stopImmediatePropagation(); var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], elem = $(this), elemOffset = elem.offset(), x = touch.pageX - elemOffset.left, y = touch.pageY - elemOffset.top; scrollbarDrag(mCSB_draggerDragY, mCSB_draggerDragX, y, x); }); $(document).bind("mousemove." + $this.data("mCustomScrollbarIndex"), function (e) { if ($this.data("on_drag")) { var elem = mCSB_dragger, elemOffset = elem.offset(), x = e.pageX - elemOffset.left, y = e.pageY - elemOffset.top; scrollbarDrag(mCSB_draggerDragY, mCSB_draggerDragX, y, x); } }).bind("mouseup." + $this.data("mCustomScrollbarIndex"), function (e) { $this.data({"on_drag": false}); mCSB_dragger.removeClass("mCSB_dragger_onDrag"); }); } $this.data({"bindEvent_scrollbar_drag": true}); } function scrollbarDrag(mCSB_draggerDragY, mCSB_draggerDragX, y, x) { if ($this.data("horizontalScroll")) { $this.mCustomScrollbar("scrollTo", (mCSB_dragger.position().left - (mCSB_draggerDragX)) + x, { moveDragger: true, trigger: "internal" }); } else { $this.mCustomScrollbar("scrollTo", (mCSB_dragger.position().top - (mCSB_draggerDragY)) + y, { moveDragger: true, trigger: "internal" }); } } /*content touch-drag*/ if ($.support.touch && $this.data("contentTouchScroll")) { if (!$this.data("bindEvent_content_touch")) { var touch, elem, elemOffset, y, x, mCSB_containerTouchY, mCSB_containerTouchX; mCSB_container.bind("touchstart", function (e) { e.stopImmediatePropagation(); touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; elem = $(this); elemOffset = elem.offset(); x = touch.pageX - elemOffset.left; y = touch.pageY - elemOffset.top; mCSB_containerTouchY = y; mCSB_containerTouchX = x; }); mCSB_container.bind("touchmove", function (e) { e.preventDefault(); e.stopImmediatePropagation(); touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; elem = $(this).parent(); elemOffset = elem.offset(); x = touch.pageX - elemOffset.left; y = touch.pageY - elemOffset.top; if ($this.data("horizontalScroll")) { $this.mCustomScrollbar("scrollTo", mCSB_containerTouchX - x, {trigger: "internal"}); } else { $this.mCustomScrollbar("scrollTo", mCSB_containerTouchY - y, {trigger: "internal"}); } }); } } /*dragger rail click scrolling*/ if (!$this.data("bindEvent_scrollbar_click")) { mCSB_draggerContainer.bind("click", function (e) { var scrollToPos = (e.pageY - mCSB_draggerContainer.offset().top) * $this.data("scrollAmount"), target = $(e.target); if ($this.data("horizontalScroll")) { scrollToPos = (e.pageX - mCSB_draggerContainer.offset().left) * $this.data("scrollAmount"); } if (target.hasClass("mCSB_draggerContainer") || target.hasClass("mCSB_draggerRail")) { $this.mCustomScrollbar("scrollTo", scrollToPos, {trigger: "internal", scrollEasing: "draggerRailEase"}); } }); $this.data({"bindEvent_scrollbar_click": true}); } /*mousewheel scrolling*/ if ($this.data("mouseWheel")) { if (!$this.data("bindEvent_mousewheel")) { mCustomScrollBox.bind("mousewheel", function (e, delta) { var scrollTo, mouseWheelPixels = $this.data("mouseWheelPixels"), absPos = Math.abs(mCSB_container.position().top), draggerPos = mCSB_dragger.position().top, limit = mCSB_draggerContainer.height() - mCSB_dragger.height(); if ($this.data("normalizeMouseWheelDelta")) { if (delta < 0) { delta = -1; } else { delta = 1; } } if (mouseWheelPixels === "auto") { mouseWheelPixels = 100 + Math.round($this.data("scrollAmount") / 2); } if ($this.data("horizontalScroll")) { draggerPos = mCSB_dragger.position().left; limit = mCSB_draggerContainer.width() - mCSB_dragger.width(); absPos = Math.abs(mCSB_container.position().left); } if ((delta > 0 && draggerPos !== 0) || (delta < 0 && draggerPos !== limit)) { e.preventDefault(); e.stopImmediatePropagation(); } scrollTo = absPos - (delta * mouseWheelPixels); $this.mCustomScrollbar("scrollTo", scrollTo, {trigger: "internal"}); }); $this.data({"bindEvent_mousewheel": true}); } } /*buttons scrolling*/ if ($this.data("scrollButtons_enable")) { if ($this.data("scrollButtons_scrollType") === "pixels") { /*scroll by pixels*/ if ($this.data("horizontalScroll")) { mCSB_buttonRight.add(mCSB_buttonLeft).unbind("mousedown touchstart MSPointerDown mouseup MSPointerUp mouseout MSPointerOut touchend", mCSB_buttonRight_stop, mCSB_buttonLeft_stop); $this.data({"bindEvent_buttonsContinuous_x": false}); if (!$this.data("bindEvent_buttonsPixels_x")) { /*scroll right*/ mCSB_buttonRight.bind("click", function (e) { e.preventDefault(); PixelsScrollTo(Math.abs(mCSB_container.position().left) + $this.data("scrollButtons_scrollAmount")); }); /*scroll left*/ mCSB_buttonLeft.bind("click", function (e) { e.preventDefault(); PixelsScrollTo(Math.abs(mCSB_container.position().left) - $this.data("scrollButtons_scrollAmount")); }); $this.data({"bindEvent_buttonsPixels_x": true}); } } else { mCSB_buttonDown.add(mCSB_buttonUp).unbind("mousedown touchstart MSPointerDown mouseup MSPointerUp mouseout MSPointerOut touchend", mCSB_buttonRight_stop, mCSB_buttonLeft_stop); $this.data({"bindEvent_buttonsContinuous_y": false}); if (!$this.data("bindEvent_buttonsPixels_y")) { /*scroll down*/ mCSB_buttonDown.bind("click", function (e) { e.preventDefault(); PixelsScrollTo(Math.abs(mCSB_container.position().top) + $this.data("scrollButtons_scrollAmount")); }); /*scroll up*/ mCSB_buttonUp.bind("click", function (e) { e.preventDefault(); PixelsScrollTo(Math.abs(mCSB_container.position().top) - $this.data("scrollButtons_scrollAmount")); }); $this.data({"bindEvent_buttonsPixels_y": true}); } } function PixelsScrollTo(to) { if (!mCSB_dragger.data("preventAction")) { mCSB_dragger.data("preventAction", true); $this.mCustomScrollbar("scrollTo", to, {trigger: "internal"}); } } } else { /*continuous scrolling*/ if ($this.data("horizontalScroll")) { mCSB_buttonRight.add(mCSB_buttonLeft).unbind("click"); $this.data({"bindEvent_buttonsPixels_x": false}); if (!$this.data("bindEvent_buttonsContinuous_x")) { /*scroll right*/ mCSB_buttonRight.bind("mousedown touchstart MSPointerDown", function (e) { e.preventDefault(); var scrollButtonsSpeed = ScrollButtonsSpeed(); $this.data({ "mCSB_buttonScrollRight": setInterval(function () { $this.mCustomScrollbar("scrollTo", Math.abs(mCSB_container.position().left) + scrollButtonsSpeed, { trigger: "internal", scrollEasing: "easeOutCirc" }); }, 17) }); }); var mCSB_buttonRight_stop = function (e) { e.preventDefault(); clearInterval($this.data("mCSB_buttonScrollRight")); } mCSB_buttonRight.bind("mouseup touchend MSPointerUp mouseout MSPointerOut", mCSB_buttonRight_stop); /*scroll left*/ mCSB_buttonLeft.bind("mousedown touchstart MSPointerDown", function (e) { e.preventDefault(); var scrollButtonsSpeed = ScrollButtonsSpeed(); $this.data({ "mCSB_buttonScrollLeft": setInterval(function () { $this.mCustomScrollbar("scrollTo", Math.abs(mCSB_container.position().left) - scrollButtonsSpeed, { trigger: "internal", scrollEasing: "easeOutCirc" }); }, 17) }); }); var mCSB_buttonLeft_stop = function (e) { e.preventDefault(); clearInterval($this.data("mCSB_buttonScrollLeft")); } mCSB_buttonLeft.bind("mouseup touchend MSPointerUp mouseout MSPointerOut", mCSB_buttonLeft_stop); $this.data({"bindEvent_buttonsContinuous_x": true}); } } else { mCSB_buttonDown.add(mCSB_buttonUp).unbind("click"); $this.data({"bindEvent_buttonsPixels_y": false}); if (!$this.data("bindEvent_buttonsContinuous_y")) { /*scroll down*/ mCSB_buttonDown.bind("mousedown touchstart MSPointerDown", function (e) { e.preventDefault(); var scrollButtonsSpeed = ScrollButtonsSpeed(); $this.data({ "mCSB_buttonScrollDown": setInterval(function () { $this.mCustomScrollbar("scrollTo", Math.abs(mCSB_container.position().top) + scrollButtonsSpeed, { trigger: "internal", scrollEasing: "easeOutCirc" }); }, 17) }); }); var mCSB_buttonDown_stop = function (e) { e.preventDefault(); clearInterval($this.data("mCSB_buttonScrollDown")); } mCSB_buttonDown.bind("mouseup touchend MSPointerUp mouseout MSPointerOut", mCSB_buttonDown_stop); /*scroll up*/ mCSB_buttonUp.bind("mousedown touchstart MSPointerDown", function (e) { e.preventDefault(); var scrollButtonsSpeed = ScrollButtonsSpeed(); $this.data({ "mCSB_buttonScrollUp": setInterval(function () { $this.mCustomScrollbar("scrollTo", Math.abs(mCSB_container.position().top) - scrollButtonsSpeed, { trigger: "internal", scrollEasing: "easeOutCirc" }); }, 17) }); }); var mCSB_buttonUp_stop = function (e) { e.preventDefault(); clearInterval($this.data("mCSB_buttonScrollUp")); } mCSB_buttonUp.bind("mouseup touchend MSPointerUp mouseout MSPointerOut", mCSB_buttonUp_stop); $this.data({"bindEvent_buttonsContinuous_y": true}); } } function ScrollButtonsSpeed() { var speed = $this.data("scrollButtons_scrollSpeed"); if ($this.data("scrollButtons_scrollSpeed") === "auto") { speed = Math.round(($this.data("scrollInertia") + 100) / 40); } return speed; } } } /*scrolling on element focus (e.g. via TAB key)*/ if ($this.data("autoScrollOnFocus")) { if (!$this.data("bindEvent_focusin")) { mCustomScrollBox.bind("focusin", function () { mCustomScrollBox.scrollTop(0).scrollLeft(0); var focusedElem = $(document.activeElement); if (focusedElem.is("input,textarea,select,button,a[tabindex],area,object")) { var mCSB_containerPos = mCSB_container.position().top, focusedElemPos = focusedElem.position().top, visibleLimit = mCustomScrollBox.height() - focusedElem.outerHeight(); if ($this.data("horizontalScroll")) { mCSB_containerPos = mCSB_container.position().left; focusedElemPos = focusedElem.position().left; visibleLimit = mCustomScrollBox.width() - focusedElem.outerWidth(); } if (mCSB_containerPos + focusedElemPos < 0 || mCSB_containerPos + focusedElemPos > visibleLimit) { $this.mCustomScrollbar("scrollTo", focusedElemPos, {trigger: "internal"}); } } }); $this.data({"bindEvent_focusin": true}); } } /*auto-hide scrollbar*/ if ($this.data("autoHideScrollbar")) { if (!$this.data("bindEvent_autoHideScrollbar")) { mCustomScrollBox.bind("mouseenter", function (e) { mCustomScrollBox.addClass("mCS-mouse-over"); functions.showScrollbar.call(mCustomScrollBox.children(".mCSB_scrollTools")); }).bind("mouseleave touchend", function (e) { mCustomScrollBox.removeClass("mCS-mouse-over"); if (e.type === "mouseleave") { functions.hideScrollbar.call(mCustomScrollBox.children(".mCSB_scrollTools")); } }); $this.data({"bindEvent_autoHideScrollbar": true}); } } }, scrollTo: function (scrollTo, options) { var $this = $(this), defaults = { moveDragger: false, trigger: "external", callbacks: true, scrollInertia: $this.data("scrollInertia"), scrollEasing: $this.data("scrollEasing") }, options = $.extend(defaults, options), draggerScrollTo, mCustomScrollBox = $this.children(".mCustomScrollBox"), mCSB_container = mCustomScrollBox.children(".mCSB_container"), mCSB_scrollTools = mCustomScrollBox.children(".mCSB_scrollTools"), mCSB_draggerContainer = mCSB_scrollTools.children(".mCSB_draggerContainer"), mCSB_dragger = mCSB_draggerContainer.children(".mCSB_dragger"), contentSpeed = draggerSpeed = options.scrollInertia, scrollBeginning, scrollBeginningOffset, totalScroll, totalScrollOffset; if (!mCSB_container.hasClass("mCS_no_scrollbar")) { $this.data({"mCS_trigger": options.trigger}); if ($this.data("mCS_Init")) { options.callbacks = false; } if (scrollTo || scrollTo === 0) { if (typeof(scrollTo) === "number") { /*if integer, scroll by number of pixels*/ if (options.moveDragger) { /*scroll dragger*/ draggerScrollTo = scrollTo; if ($this.data("horizontalScroll")) { scrollTo = mCSB_dragger.position().left * $this.data("scrollAmount"); } else { scrollTo = mCSB_dragger.position().top * $this.data("scrollAmount"); } draggerSpeed = 0; } else { /*scroll content by default*/ draggerScrollTo = scrollTo / $this.data("scrollAmount"); } } else if (typeof(scrollTo) === "string") { /*if string, scroll by element position*/ var target; if (scrollTo === "top") { /*scroll to top*/ target = 0; } else if (scrollTo === "bottom" && !$this.data("horizontalScroll")) { /*scroll to bottom*/ target = mCSB_container.outerHeight() - mCustomScrollBox.height(); } else if (scrollTo === "left") { /*scroll to left*/ target = 0; } else if (scrollTo === "right" && $this.data("horizontalScroll")) { /*scroll to right*/ target = mCSB_container.outerWidth() - mCustomScrollBox.width(); } else if (scrollTo === "first") { /*scroll to first element position*/ target = $this.find(".mCSB_container").find(":first"); } else if (scrollTo === "last") { /*scroll to last element position*/ target = $this.find(".mCSB_container").find(":last"); } else { /*scroll to element position*/ target = $this.find(scrollTo); } if (target.length === 1) { /*if such unique element exists, scroll to it*/ if ($this.data("horizontalScroll")) { scrollTo = target.position().left; } else { scrollTo = target.position().top; } draggerScrollTo = scrollTo / $this.data("scrollAmount"); } else { draggerScrollTo = scrollTo = target; } } /*scroll to*/ if ($this.data("horizontalScroll")) { if ($this.data("onTotalScrollBack_Offset")) { /*scroll beginning offset*/ scrollBeginningOffset = -$this.data("onTotalScrollBack_Offset"); } if ($this.data("onTotalScroll_Offset")) { /*total scroll offset*/ totalScrollOffset = mCustomScrollBox.width() - mCSB_container.outerWidth() + $this.data("onTotalScroll_Offset"); } if (draggerScrollTo < 0) { /*scroll start position*/ draggerScrollTo = scrollTo = 0; clearInterval($this.data("mCSB_buttonScrollLeft")); if (!scrollBeginningOffset) { scrollBeginning = true; } } else if (draggerScrollTo >= mCSB_draggerContainer.width() - mCSB_dragger.width()) { /*scroll end position*/ draggerScrollTo = mCSB_draggerContainer.width() - mCSB_dragger.width(); scrollTo = mCustomScrollBox.width() - mCSB_container.outerWidth(); clearInterval($this.data("mCSB_buttonScrollRight")); if (!totalScrollOffset) { totalScroll = true; } } else { scrollTo = -scrollTo; } /*scrolling animation*/ functions.mTweenAxis.call(this, mCSB_dragger[0], "left", Math.round(draggerScrollTo), draggerSpeed, options.scrollEasing); functions.mTweenAxis.call(this, mCSB_container[0], "left", Math.round(scrollTo), contentSpeed, options.scrollEasing, { onStart: function () { if (options.callbacks && !$this.data("mCS_tweenRunning")) { callbacks("onScrollStart"); } if ($this.data("autoHideScrollbar")) { functions.showScrollbar.call(mCSB_scrollTools); } }, onUpdate: function () { if (options.callbacks) { callbacks("whileScrolling"); } }, onComplete: function () { if (options.callbacks) { callbacks("onScroll"); if (scrollBeginning || (scrollBeginningOffset && mCSB_container.position().left >= scrollBeginningOffset)) { callbacks("onTotalScrollBack"); } if (totalScroll || (totalScrollOffset && mCSB_container.position().left <= totalScrollOffset)) { callbacks("onTotalScroll"); } } mCSB_dragger.data("preventAction", false); $this.data("mCS_tweenRunning", false); if ($this.data("autoHideScrollbar")) { if (!mCustomScrollBox.hasClass("mCS-mouse-over")) { functions.hideScrollbar.call(mCSB_scrollTools); } } } }); } else { if ($this.data("onTotalScrollBack_Offset")) { /*scroll beginning offset*/ scrollBeginningOffset = -$this.data("onTotalScrollBack_Offset"); } if ($this.data("onTotalScroll_Offset")) { /*total scroll offset*/ totalScrollOffset = mCustomScrollBox.height() - mCSB_container.outerHeight() + $this.data("onTotalScroll_Offset"); } if (draggerScrollTo < 0) { /*scroll start position*/ draggerScrollTo = scrollTo = 0; clearInterval($this.data("mCSB_buttonScrollUp")); if (!scrollBeginningOffset) { scrollBeginning = true; } } else if (draggerScrollTo >= mCSB_draggerContainer.height() - mCSB_dragger.height()) { /*scroll end position*/ draggerScrollTo = mCSB_draggerContainer.height() - mCSB_dragger.height(); scrollTo = mCustomScrollBox.height() - mCSB_container.outerHeight(); clearInterval($this.data("mCSB_buttonScrollDown")); if (!totalScrollOffset) { totalScroll = true; } } else { scrollTo = -scrollTo; } /*scrolling animation*/ functions.mTweenAxis.call(this, mCSB_dragger[0], "top", Math.round(draggerScrollTo), draggerSpeed, options.scrollEasing); functions.mTweenAxis.call(this, mCSB_container[0], "top", Math.round(scrollTo), contentSpeed, options.scrollEasing, { onStart: function () { if (options.callbacks && !$this.data("mCS_tweenRunning")) { callbacks("onScrollStart"); } if ($this.data("autoHideScrollbar")) { functions.showScrollbar.call(mCSB_scrollTools); } }, onUpdate: function () { if (options.callbacks) { callbacks("whileScrolling"); } }, onComplete: function () { if (options.callbacks) { callbacks("onScroll"); if (scrollBeginning || (scrollBeginningOffset && mCSB_container.position().top >= scrollBeginningOffset)) { callbacks("onTotalScrollBack"); } if (totalScroll || (totalScrollOffset && mCSB_container.position().top <= totalScrollOffset)) { callbacks("onTotalScroll"); } } mCSB_dragger.data("preventAction", false); $this.data("mCS_tweenRunning", false); if ($this.data("autoHideScrollbar")) { if (!mCustomScrollBox.hasClass("mCS-mouse-over")) { functions.hideScrollbar.call(mCSB_scrollTools); } } } }); } if ($this.data("mCS_Init")) { $this.data({"mCS_Init": false}); } } } /*callbacks*/ function callbacks(cb) { this.mcs = { top: mCSB_container.position().top, left: mCSB_container.position().left, draggerTop: mCSB_dragger.position().top, draggerLeft: mCSB_dragger.position().left, topPct: Math.round((100 * Math.abs(mCSB_container.position().top)) / Math.abs(mCSB_container.outerHeight() - mCustomScrollBox.height())), leftPct: Math.round((100 * Math.abs(mCSB_container.position().left)) / Math.abs(mCSB_container.outerWidth() - mCustomScrollBox.width())) }; switch (cb) { /*start scrolling callback*/ case "onScrollStart": $this.data("mCS_tweenRunning", true).data("onScrollStart_Callback").call($this, this.mcs); break; case "whileScrolling": $this.data("whileScrolling_Callback").call($this, this.mcs); break; case "onScroll": $this.data("onScroll_Callback").call($this, this.mcs); break; case "onTotalScrollBack": $this.data("onTotalScrollBack_Callback").call($this, this.mcs); break; case "onTotalScroll": $this.data("onTotalScroll_Callback").call($this, this.mcs); break; } } }, stop: function () { var $this = $(this), mCSB_container = $this.children().children(".mCSB_container"), mCSB_dragger = $this.children().children().children().children(".mCSB_dragger"); functions.mTweenAxisStop.call(this, mCSB_container[0]); functions.mTweenAxisStop.call(this, mCSB_dragger[0]); }, disable: function (resetScroll) { var $this = $(this), mCustomScrollBox = $this.children(".mCustomScrollBox"), mCSB_container = mCustomScrollBox.children(".mCSB_container"), mCSB_scrollTools = mCustomScrollBox.children(".mCSB_scrollTools"), mCSB_dragger = mCSB_scrollTools.children().children(".mCSB_dragger"); mCustomScrollBox.unbind("mousewheel focusin mouseenter mouseleave touchend"); mCSB_container.unbind("touchstart touchmove") if (resetScroll) { if ($this.data("horizontalScroll")) { mCSB_dragger.add(mCSB_container).css("left", 0); } else { mCSB_dragger.add(mCSB_container).css("top", 0); } } mCSB_scrollTools.css("display", "none"); mCSB_container.addClass("mCS_no_scrollbar"); $this.data({ "bindEvent_mousewheel": false, "bindEvent_focusin": false, "bindEvent_content_touch": false, "bindEvent_autoHideScrollbar": false }).addClass("mCS_disabled"); }, destroy: function () { var $this = $(this); $this.removeClass("mCustomScrollbar _mCS_" + $this.data("mCustomScrollbarIndex")).addClass("mCS_destroyed").children().children(".mCSB_container").unwrap().children().unwrap().siblings(".mCSB_scrollTools").remove(); $(document).unbind("mousemove." + $this.data("mCustomScrollbarIndex") + " mouseup." + $this.data("mCustomScrollbarIndex") + " MSPointerMove." + $this.data("mCustomScrollbarIndex") + " MSPointerUp." + $this.data("mCustomScrollbarIndex")); $(window).unbind("resize." + $this.data("mCustomScrollbarIndex")); } }, functions = { /*hide/show scrollbar*/ showScrollbar: function () { this.stop().animate({opacity: 1}, "fast"); }, hideScrollbar: function () { this.stop().animate({opacity: 0}, "fast"); }, /*js animation tween*/ mTweenAxis: function (el, prop, to, duration, easing, callbacks) { var callbacks = callbacks || {}, onStart = callbacks.onStart || function () { }, onUpdate = callbacks.onUpdate || function () { }, onComplete = callbacks.onComplete || function () { }; var startTime = _getTime(), _delay, progress = 0, from = el.offsetTop, elStyle = el.style; if (prop === "left") { from = el.offsetLeft; } var diff = to - from; _cancelTween(); _startTween(); function _getTime() { if (window.performance && window.performance.now) { return window.performance.now(); } else { if (window.performance && window.performance.webkitNow) { return window.performance.webkitNow(); } else { if (Date.now) { return Date.now(); } else { return new Date().getTime(); } } } } function _step() { if (!progress) { onStart.call(); } progress = _getTime() - startTime; _tween(); if (progress >= el._time) { el._time = (progress > el._time) ? progress + _delay - (progress - el._time) : progress + _delay - 1; if (el._time < progress + 1) { el._time = progress + 1; } } if (el._time < duration) { el._id = _request(_step); } else { onComplete.call(); } } function _tween() { if (duration > 0) { el.currVal = _ease(el._time, from, diff, duration, easing); elStyle[prop] = Math.round(el.currVal) + "px"; } else { elStyle[prop] = to + "px"; } onUpdate.call(); } function _startTween() { _delay = 1000 / 60; el._time = progress + _delay; _request = (!window.requestAnimationFrame) ? function (f) { _tween(); return setTimeout(f, 0.01); } : window.requestAnimationFrame; el._id = _request(_step); } function _cancelTween() { if (el._id == null) { return; } if (!window.requestAnimationFrame) { clearTimeout(el._id); } else { window.cancelAnimationFrame(el._id); } el._id = null; } function _ease(t, b, c, d, type) { switch (type) { case "linear": return c * t / d + b; break; case "easeOutQuad": t /= d; return -c * t * (t - 2) + b; break; case "easeInOutQuad": t /= d / 2; if (t < 1) return c / 2 * t * t + b; t--; return -c / 2 * (t * (t - 2) - 1) + b; break; case "easeOutCubic": t /= d; t--; return c * (t * t * t + 1) + b; break; case "easeOutQuart": t /= d; t--; return -c * (t * t * t * t - 1) + b; break; case "easeOutQuint": t /= d; t--; return c * (t * t * t * t * t + 1) + b; break; case "easeOutCirc": t /= d; t--; return c * Math.sqrt(1 - t * t) + b; break; case "easeOutSine": return c * Math.sin(t / d * (Math.PI / 2)) + b; break; case "easeOutExpo": return c * ( -Math.pow(2, -10 * t / d) + 1 ) + b; break; case "mcsEaseOut": var ts = (t /= d) * t, tc = ts * t; return b + c * (0.499999999999997 * tc * ts + -2.5 * ts * ts + 5.5 * tc + -6.5 * ts + 4 * t); break; case "draggerRailEase": t /= d / 2; if (t < 1) return c / 2 * t * t * t + b; t -= 2; return c / 2 * (t * t * t + 2) + b; break; } } }, /*stop js animation tweens*/ mTweenAxisStop: function (el) { if (el._id == null) { return; } if (!window.requestAnimationFrame) { clearTimeout(el._id); } else { window.cancelAnimationFrame(el._id); } el._id = null; }, /*detect requestAnimationFrame and polyfill*/ rafPolyfill: function () { var pfx = ["ms", "moz", "webkit", "o"], i = pfx.length; while (--i > -1 && !window.requestAnimationFrame) { window.requestAnimationFrame = window[pfx[i] + "RequestAnimationFrame"]; window.cancelAnimationFrame = window[pfx[i] + "CancelAnimationFrame"] || window[pfx[i] + "CancelRequestAnimationFrame"]; } } } /*detect features*/ functions.rafPolyfill.call(); /*requestAnimationFrame*/ $.support.touch = !!('ontouchstart' in window); /*touch*/ $.support.msPointer = window.navigator.msPointerEnabled; /*MSPointer support*/ /*plugin dependencies*/ var _dlp = ("https:" == document.location.protocol) ? "https:" : "http:"; $.event.special.mousewheel || document.write('