Skip to content

Instantly share code, notes, and snippets.

@rw1
Created January 9, 2013 04:28
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save rw1/4490579 to your computer and use it in GitHub Desktop.
Save rw1/4490579 to your computer and use it in GitHub Desktop.
/*
== malihu jquery custom scrollbars plugin ==
version: 2.3.2
author: malihu (http://manos.malihu.gr)
plugin home: http://manos.malihu.gr/jquery-custom-content-scroller
*/
(function($){
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:550, /*scrolling inertia: integer (milliseconds)*/
scrollEasing:"easeOutCirc", /*scrolling easing: string*/
mouseWheel:"pixels", /*mousewheel support and velocity: boolean, "auto", integer, "pixels"*/
mouseWheelPixels:60, /*mousewheel pixels amount: integer*/
autoDraggerLength:true, /*auto-adjust scrollbar dragger length: boolean*/
scrollButtons:{ /*scroll buttons*/
enable:false, /*scroll buttons support: boolean*/
scrollType:"continuous", /*scroll buttons scrolling type: "continuous", "pixels"*/
scrollSpeed:20, /*scroll buttons continuous scrolling speed: integer*/
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*/
},
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)*/
whileScrolling:false, /*user custom callback function on scrolling event*/
whileScrollingInterval:30 /*interval for calling whileScrolling callback: integer (milliseconds)*/
}
},
options=$.extend(true,defaults,options);
/*check for touch device*/
$(document).data("mCS-is-touch-device",false);
if(is_touch_device()){
$(document).data("mCS-is-touch-device",true);
}
function is_touch_device(){
return !!("ontouchstart" in window) ? 1 : 0;
}
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("<div class='mCustomScrollBox' id='mCSB_"+$(document).data("mCustomScrollbar-index")+"' style='position:relative; height:100%; overflow:hidden; max-width:100%;' />").addClass("mCustomScrollbar _mCS_"+$(document).data("mCustomScrollbar-index"));
var mCustomScrollBox=$this.children(".mCustomScrollBox");
if(options.horizontalScroll){
mCustomScrollBox.addClass("mCSB_horizontal").wrapInner("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />");
var mCSB_h_wrapper=mCustomScrollBox.children(".mCSB_h_wrapper");
mCSB_h_wrapper.wrapInner("<div class='mCSB_container' style='position:absolute; left:0;' />").children(".mCSB_container").css({"width":mCSB_h_wrapper.children().outerWidth(),"position":"relative"}).unwrap();
}else{
mCustomScrollBox.wrapInner("<div class='mCSB_container' style='position:relative; top:0;' />");
}
var mCSB_container=mCustomScrollBox.children(".mCSB_container");
if($(document).data("mCS-is-touch-device")){
mCSB_container.addClass("mCS_touch");
}
mCSB_container.after("<div class='mCSB_scrollTools' style='position:absolute;'><div class='mCSB_draggerContainer' style='position:relative;'><div class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' style='position:relative;'></div></div><div class='mCSB_draggerRail'></div></div></div>");
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("<a class='mCSB_buttonLeft' style='display:block; position:relative;'></a>").append("<a class='mCSB_buttonRight' style='display:block; position:relative;'></a>");
}else{
mCSB_scrollTools.prepend("<a class='mCSB_buttonUp' style='display:block; position:relative;'></a>").append("<a class='mCSB_buttonDown' style='display:block; position:relative;'></a>");
}
}
/*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 and update element*/
$this.data({
/*init state*/
"mCS_Init":true,
/*option parameters*/
"horizontalScroll":options.horizontalScroll,
"scrollInertia":options.scrollInertia,
"scrollEasing":options.scrollEasing,
"mouseWheel":options.mouseWheel,
"mouseWheelPixels":options.mouseWheelPixels,
"autoDraggerLength":options.autoDraggerLength,
"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,
"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,
"whileScrolling_Callback":options.callbacks.whileScrolling,
"whileScrolling_Interval":options.callbacks.whileScrollingInterval,
/*events binding state*/
"bindEvent_scrollbar_click":false,
"bindEvent_mousewheel":false,
"bindEvent_focusin":false,
"bindEvent_buttonsContinuous_y":false,
"bindEvent_buttonsContinuous_x":false,
"bindEvent_buttonsPixels_y":false,
"bindEvent_buttonsPixels_x":false,
"bindEvent_scrollbar_touch":false,
"bindEvent_content_touch":false,
/*buttons intervals*/
"mCSB_buttonScrollRight":false,
"mCSB_buttonScrollLeft":false,
"mCSB_buttonScrollDown":false,
"mCSB_buttonScrollUp":false,
/*callback intervals*/
"whileScrolling":false
}).mCustomScrollbar("update");
/*detect max-width*/
if(options.horizontalScroll){
if($this.css("max-width")!=="none"){
if(!options.advanced.updateOnContentResize){ /*needs updateOnContentResize*/
options.advanced.updateOnContentResize=true;
}
$this.data({"mCS_maxWidth":parseInt($this.css("max-width")),"mCS_maxWidth_Interval":setInterval(function(){
if(mCSB_container.outerWidth()>$this.data("mCS_maxWidth")){
clearInterval($this.data("mCS_maxWidth_Interval"));
$this.mCustomScrollbar("update");
}
},150)});
}
}else{
/*detect max-height*/
if($this.css("max-height")!=="none"){
$this.data({"mCS_maxHeight":parseInt($this.css("max-height")),"mCS_maxHeight_Interval":setInterval(function(){
mCustomScrollBox.css("max-height",$this.data("mCS_maxHeight"));
if(mCSB_container.outerHeight()>$this.data("mCS_maxHeight")){
clearInterval($this.data("mCS_maxHeight_Interval"));
$this.mCustomScrollbar("update");
}
},150)});
}
}
/*window resize fn (for layouts based on percentages)*/
if(options.advanced.updateOnBrowserResize){
var mCSB_resizeTimeout;
$(window).resize(function(){
if(mCSB_resizeTimeout){
clearTimeout(mCSB_resizeTimeout);
}
mCSB_resizeTimeout=setTimeout(function(){
if(!$this.is(".mCS_disabled") && !$this.is(".mCS_destroyed")){
$this.mCustomScrollbar("update");
}
},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("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").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("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").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(Math.round(mCSB_container.position().top));
$this.mCustomScrollbar("scrollTo",mCSB_containerP,{callback:false});
}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(Math.round(mCSB_container.position().left));
$this.mCustomScrollbar("scrollTo",mCSB_containerP,{callback:false});
}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);
/*while scrolling callback*/
$this.mCustomScrollbar("callbacks","whileScrolling");
/*drag scrolling*/
if(!mCSB_dragger.hasClass("ui-draggable")){ /*apply drag function once*/
if($this.data("horizontalScroll")){
var draggableAxis="x";
}else{
var draggableAxis="y";
}
mCSB_dragger.draggable({
axis:draggableAxis,
containment:"parent",
drag:function(event,ui){
$this.mCustomScrollbar("scroll");
mCSB_dragger.addClass("mCSB_dragger_onDrag");
},
stop:function(event,ui){
mCSB_dragger.removeClass("mCSB_dragger_onDrag");
}
});
}
if(!$this.data("bindEvent_scrollbar_click")){ /*bind once*/
mCSB_draggerContainer.bind("click",function(e){
if($this.data("horizontalScroll")){
var mouseCoord=(e.pageX-mCSB_draggerContainer.offset().left);
if(mouseCoord<mCSB_dragger.position().left || mouseCoord>(mCSB_dragger.position().left+mCSB_dragger.width())){
var scrollToPos=mouseCoord;
if(scrollToPos>=mCSB_draggerContainer.width()-mCSB_dragger.width()){ /*max dragger position is bottom*/
scrollToPos=mCSB_draggerContainer.width()-mCSB_dragger.width();
}
mCSB_dragger.css("left",scrollToPos);
$this.mCustomScrollbar("scroll");
}
}else{
var mouseCoord=(e.pageY-mCSB_draggerContainer.offset().top);
if(mouseCoord<mCSB_dragger.position().top || mouseCoord>(mCSB_dragger.position().top+mCSB_dragger.height())){
var scrollToPos=mouseCoord;
if(scrollToPos>=mCSB_draggerContainer.height()-mCSB_dragger.height()){ /*max dragger position is bottom*/
scrollToPos=mCSB_draggerContainer.height()-mCSB_dragger.height();
}
mCSB_dragger.css("top",scrollToPos);
$this.mCustomScrollbar("scroll");
}
}
});
$this.data({"bindEvent_scrollbar_click":true});
}
/*mousewheel scrolling*/
if($this.data("mouseWheel")){
var mousewheelVel=$this.data("mouseWheel");
if($this.data("mouseWheel")==="auto"){
mousewheelVel=8; /*default mousewheel velocity*/
/*check for safari browser on mac osx to lower mousewheel velocity*/
var os=navigator.userAgent;
if(os.indexOf("Mac")!=-1 && os.indexOf("Safari")!=-1 && os.indexOf("AppleWebKit")!=-1 && os.indexOf("Chrome")==-1){
mousewheelVel=1;
}
}
if(!$this.data("bindEvent_mousewheel")){ /*bind once*/
mCustomScrollBox.bind("mousewheel",function(event,delta){
event.preventDefault();
var vel=Math.abs(delta*mousewheelVel);
if($this.data("horizontalScroll")){
if($this.data("mouseWheel")==="pixels"){
if(delta<0){
delta=-1;
}else{
delta=1;
}
var scrollTo=Math.abs(Math.round(mCSB_container.position().left))-(delta*$this.data("mouseWheelPixels"));
$this.mCustomScrollbar("scrollTo",scrollTo);
}else{
var posX=mCSB_dragger.position().left-(delta*vel);
mCSB_dragger.css("left",posX);
if(mCSB_dragger.position().left<0){
mCSB_dragger.css("left",0);
}
var mCSB_draggerContainerW=mCSB_draggerContainer.width(),
mCSB_draggerW=mCSB_dragger.width();
if(mCSB_dragger.position().left>mCSB_draggerContainerW-mCSB_draggerW){
mCSB_dragger.css("left",mCSB_draggerContainerW-mCSB_draggerW);
}
$this.mCustomScrollbar("scroll");
}
}else{
if($this.data("mouseWheel")==="pixels"){
if(delta<0){
delta=-1;
}else{
delta=1;
}
var scrollTo=Math.abs(Math.round(mCSB_container.position().top))-(delta*$this.data("mouseWheelPixels"));
$this.mCustomScrollbar("scrollTo",scrollTo);
}else{
var posY=mCSB_dragger.position().top-(delta*vel);
mCSB_dragger.css("top",posY);
if(mCSB_dragger.position().top<0){
mCSB_dragger.css("top",0);
}
var mCSB_draggerContainerH=mCSB_draggerContainer.height(),
mCSB_draggerH=mCSB_dragger.height();
if(mCSB_dragger.position().top>mCSB_draggerContainerH-mCSB_draggerH){
mCSB_dragger.css("top",mCSB_draggerContainerH-mCSB_draggerH);
}
$this.mCustomScrollbar("scroll");
}
}
});
$this.data({"bindEvent_mousewheel":true});
}
}
/*buttons scrolling*/
if($this.data("scrollButtons_enable")){
if($this.data("scrollButtons_scrollType")==="pixels"){ /*scroll by pixels*/
var pixelsScrollTo;
if($.browser.msie && parseInt($.browser.version)<9){ /*stupid ie8*/
$this.data("scrollInertia",0);
}
if($this.data("horizontalScroll")){
mCSB_buttonRight.add(mCSB_buttonLeft).unbind("mousedown touchstart onmsgesturestart mouseup mouseout touchend onmsgestureend",mCSB_buttonRight_stop,mCSB_buttonLeft_stop);
$this.data({"bindEvent_buttonsContinuous_x":false});
if(!$this.data("bindEvent_buttonsPixels_x")){ /*bind once*/
/*scroll right*/
mCSB_buttonRight.bind("click",function(e){
e.preventDefault();
if(!mCSB_container.is(":animated")){
pixelsScrollTo=Math.abs(mCSB_container.position().left)+$this.data("scrollButtons_scrollAmount");
$this.mCustomScrollbar("scrollTo",pixelsScrollTo);
}
});
/*scroll left*/
mCSB_buttonLeft.bind("click",function(e){
e.preventDefault();
if(!mCSB_container.is(":animated")){
pixelsScrollTo=Math.abs(mCSB_container.position().left)-$this.data("scrollButtons_scrollAmount");
if(mCSB_container.position().left>=-$this.data("scrollButtons_scrollAmount")){
pixelsScrollTo="left";
}
$this.mCustomScrollbar("scrollTo",pixelsScrollTo);
}
});
$this.data({"bindEvent_buttonsPixels_x":true});
}
}else{
mCSB_buttonDown.add(mCSB_buttonUp).unbind("mousedown touchstart onmsgesturestart mouseup mouseout touchend onmsgestureend",mCSB_buttonRight_stop,mCSB_buttonLeft_stop);
$this.data({"bindEvent_buttonsContinuous_y":false});
if(!$this.data("bindEvent_buttonsPixels_y")){ /*bind once*/
/*scroll down*/
mCSB_buttonDown.bind("click",function(e){
e.preventDefault();
if(!mCSB_container.is(":animated")){
pixelsScrollTo=Math.abs(mCSB_container.position().top)+$this.data("scrollButtons_scrollAmount");
$this.mCustomScrollbar("scrollTo",pixelsScrollTo);
}
});
/*scroll up*/
mCSB_buttonUp.bind("click",function(e){
e.preventDefault();
if(!mCSB_container.is(":animated")){
pixelsScrollTo=Math.abs(mCSB_container.position().top)-$this.data("scrollButtons_scrollAmount");
if(mCSB_container.position().top>=-$this.data("scrollButtons_scrollAmount")){
pixelsScrollTo="top";
}
$this.mCustomScrollbar("scrollTo",pixelsScrollTo);
}
});
$this.data({"bindEvent_buttonsPixels_y":true});
}
}
}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")){ /*bind once*/
/*scroll right*/
mCSB_buttonRight.bind("mousedown touchstart onmsgesturestart",function(e){
e.preventDefault();
e.stopPropagation();
$this.data({"mCSB_buttonScrollRight":setInterval(function(){
var scrollTo=Math.round((Math.abs(Math.round(mCSB_container.position().left))+$this.data("scrollButtons_scrollSpeed"))/$this.data("scrollAmount"));
$this.mCustomScrollbar("scrollTo",scrollTo,{moveDragger:true});
},30)});
});
var mCSB_buttonRight_stop=function(e){
e.preventDefault();
e.stopPropagation();
clearInterval($this.data("mCSB_buttonScrollRight"));
}
mCSB_buttonRight.bind("mouseup touchend onmsgestureend mouseout",mCSB_buttonRight_stop);
/*scroll left*/
mCSB_buttonLeft.bind("mousedown touchstart onmsgesturestart",function(e){
e.preventDefault();
e.stopPropagation();
$this.data({"mCSB_buttonScrollLeft":setInterval(function(){
var scrollTo=Math.round((Math.abs(Math.round(mCSB_container.position().left))-$this.data("scrollButtons_scrollSpeed"))/$this.data("scrollAmount"));
$this.mCustomScrollbar("scrollTo",scrollTo,{moveDragger:true});
},30)});
});
var mCSB_buttonLeft_stop=function(e){
e.preventDefault();
e.stopPropagation();
clearInterval($this.data("mCSB_buttonScrollLeft"));
}
mCSB_buttonLeft.bind("mouseup touchend onmsgestureend mouseout",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")){ /*bind once*/
/*scroll down*/
mCSB_buttonDown.bind("mousedown touchstart onmsgesturestart",function(e){
e.preventDefault();
e.stopPropagation();
$this.data({"mCSB_buttonScrollDown":setInterval(function(){
var scrollTo=Math.round((Math.abs(Math.round(mCSB_container.position().top))+$this.data("scrollButtons_scrollSpeed"))/$this.data("scrollAmount"));
$this.mCustomScrollbar("scrollTo",scrollTo,{moveDragger:true});
},30)});
});
var mCSB_buttonDown_stop=function(e){
e.preventDefault();
e.stopPropagation();
clearInterval($this.data("mCSB_buttonScrollDown"));
}
mCSB_buttonDown.bind("mouseup touchend onmsgestureend mouseout",mCSB_buttonDown_stop);
/*scroll up*/
mCSB_buttonUp.bind("mousedown touchstart onmsgesturestart",function(e){
e.preventDefault();
e.stopPropagation();
$this.data({"mCSB_buttonScrollUp":setInterval(function(){
var scrollTo=Math.round((Math.abs(Math.round(mCSB_container.position().top))-$this.data("scrollButtons_scrollSpeed"))/$this.data("scrollAmount"));
$this.mCustomScrollbar("scrollTo",scrollTo,{moveDragger:true});
},30)});
});
var mCSB_buttonUp_stop=function(e){
e.preventDefault();
e.stopPropagation();
clearInterval($this.data("mCSB_buttonScrollUp"));
}
mCSB_buttonUp.bind("mouseup touchend onmsgestureend mouseout",mCSB_buttonUp_stop);
$this.data({"bindEvent_buttonsContinuous_y":true});
}
}
}
}
/*scrolling on element focus (e.g. via TAB key)*/
if($this.data("autoScrollOnFocus")){
if(!$this.data("bindEvent_focusin")){ /*bind once*/
mCustomScrollBox.bind("focusin",function(){
mCustomScrollBox.scrollTop(0).scrollLeft(0);
var focusedElem=$(document.activeElement);
if(focusedElem.is("input,textarea,select,button,a[tabindex],area,object")){
if($this.data("horizontalScroll")){
var mCSB_containerX=mCSB_container.position().left,
focusedElemX=focusedElem.position().left,
mCustomScrollBoxW=mCustomScrollBox.width(),
focusedElemW=focusedElem.outerWidth();
if(mCSB_containerX+focusedElemX>=0 && mCSB_containerX+focusedElemX<=mCustomScrollBoxW-focusedElemW){
/*just focus...*/
}else{ /*scroll, then focus*/
var moveDragger=focusedElemX/$this.data("scrollAmount");
if(moveDragger>=mCSB_draggerContainer.width()-mCSB_dragger.width()){ /*max dragger position is bottom*/
moveDragger=mCSB_draggerContainer.width()-mCSB_dragger.width();
}
mCSB_dragger.css("left",moveDragger);
$this.mCustomScrollbar("scroll");
}
}else{
var mCSB_containerY=mCSB_container.position().top,
focusedElemY=focusedElem.position().top,
mCustomScrollBoxH=mCustomScrollBox.height(),
focusedElemH=focusedElem.outerHeight();
if(mCSB_containerY+focusedElemY>=0 && mCSB_containerY+focusedElemY<=mCustomScrollBoxH-focusedElemH){
/*just focus...*/
}else{ /*scroll, then focus*/
var moveDragger=focusedElemY/$this.data("scrollAmount");
if(moveDragger>=mCSB_draggerContainer.height()-mCSB_dragger.height()){ /*max dragger position is bottom*/
moveDragger=mCSB_draggerContainer.height()-mCSB_dragger.height();
}
mCSB_dragger.css("top",moveDragger);
$this.mCustomScrollbar("scroll");
}
}
}
});
$this.data({"bindEvent_focusin":true});
}
}
/*touch events*/
if($(document).data("mCS-is-touch-device")){
/*scrollbar touch-drag*/
if(!$this.data("bindEvent_scrollbar_touch")){ /*bind once*/
var mCSB_draggerTouchY,
mCSB_draggerTouchX;
mCSB_dragger.bind("touchstart onmsgesturestart",function(e){
e.preventDefault();
e.stopPropagation();
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;
if(x<elem.width() && x>0 && y<elem.height() && y>0){
mCSB_draggerTouchY=y;
mCSB_draggerTouchX=x;
}
});
mCSB_dragger.bind("touchmove onmsgesturechange",function(e){
e.preventDefault();
e.stopPropagation();
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;
if($this.data("horizontalScroll")){
$this.mCustomScrollbar("scrollTo",(mCSB_dragger.position().left-(mCSB_draggerTouchX))+x,{moveDragger:true});
}else{
$this.mCustomScrollbar("scrollTo",(mCSB_dragger.position().top-(mCSB_draggerTouchY))+y,{moveDragger:true});
}
});
$this.data({"bindEvent_scrollbar_touch":true});
}
/*content touch-drag*/
if(!$this.data("bindEvent_content_touch")){ /*bind once*/
var touch,
elem,
elemOffset,
x,
y,
mCSB_containerTouchY,
mCSB_containerTouchX;
mCSB_container.bind("touchstart onmsgesturestart",function(e){
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 onmsgesturechange",function(e){
e.preventDefault();
e.stopPropagation();
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);
}else{
$this.mCustomScrollbar("scrollTo",mCSB_containerTouchY-y);
}
});
$this.data({"bindEvent_content_touch":true});
}
}
},
scroll:function(bypassCallbacks){
var $this=$(this),
mCSB_dragger=$this.find(".mCSB_dragger"),
mCSB_container=$this.find(".mCSB_container"),
mCustomScrollBox=$this.find(".mCustomScrollBox");
if($this.data("horizontalScroll")){
var draggerX=mCSB_dragger.position().left,
targX=-draggerX*$this.data("scrollAmount"),
thisX=mCSB_container.position().left,
posX=Math.round(thisX-targX);
}else{
var draggerY=mCSB_dragger.position().top,
targY=-draggerY*$this.data("scrollAmount"),
thisY=mCSB_container.position().top,
posY=Math.round(thisY-targY);
}
if($.browser.webkit){ /*fix webkit zoom and jquery animate*/
var screenCssPixelRatio=(window.outerWidth-8)/window.innerWidth,
isZoomed=(screenCssPixelRatio<.98 || screenCssPixelRatio>1.02);
}
if($this.data("scrollInertia")===0 || isZoomed){
if(!bypassCallbacks){
$this.mCustomScrollbar("callbacks","onScrollStart"); /*user custom callback functions*/
}
if($this.data("horizontalScroll")){
mCSB_container.css("left",targX);
}else{
mCSB_container.css("top",targY);
}
if(!bypassCallbacks){
/*user custom callback functions*/
if($this.data("whileScrolling")){
$this.data("whileScrolling_Callback").call();
}
$this.mCustomScrollbar("callbacks","onScroll");
}
$this.data({"mCS_Init":false});
}else{
if(!bypassCallbacks){
$this.mCustomScrollbar("callbacks","onScrollStart"); /*user custom callback functions*/
}
if($this.data("horizontalScroll")){
mCSB_container.stop().animate({left:"-="+posX},$this.data("scrollInertia"),$this.data("scrollEasing"),function(){
if(!bypassCallbacks){
$this.mCustomScrollbar("callbacks","onScroll"); /*user custom callback functions*/
}
$this.data({"mCS_Init":false});
});
}else{
mCSB_container.stop().animate({top:"-="+posY},$this.data("scrollInertia"),$this.data("scrollEasing"),function(){
if(!bypassCallbacks){
$this.mCustomScrollbar("callbacks","onScroll"); /*user custom callback functions*/
}
$this.data({"mCS_Init":false});
});
}
}
},
scrollTo:function(scrollTo,options){
var defaults={
moveDragger:false,
callback:true
},
options=$.extend(defaults,options),
$this=$(this),
scrollToPos,
mCustomScrollBox=$this.find(".mCustomScrollBox"),
mCSB_container=mCustomScrollBox.children(".mCSB_container"),
mCSB_draggerContainer=$this.find(".mCSB_draggerContainer"),
mCSB_dragger=mCSB_draggerContainer.children(".mCSB_dragger"),
targetPos;
if(scrollTo || scrollTo===0){
if(typeof(scrollTo)==="number"){ /*if integer, scroll by number of pixels*/
if(options.moveDragger){ /*scroll dragger*/
scrollToPos=scrollTo;
}else{ /*scroll content by default*/
targetPos=scrollTo;
scrollToPos=Math.round(targetPos/$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")){
targetPos=target.position().left;
}else{
targetPos=target.position().top;
}
scrollToPos=Math.ceil(targetPos/$this.data("scrollAmount"));
}else{
scrollToPos=target;
}
}
/*scroll to*/
if(scrollToPos<0){
scrollToPos=0;
}
if($this.data("horizontalScroll")){
if(scrollToPos>=mCSB_draggerContainer.width()-mCSB_dragger.width()){ /*max dragger position is bottom*/
scrollToPos=mCSB_draggerContainer.width()-mCSB_dragger.width();
}
mCSB_dragger.css("left",scrollToPos);
}else{
if(scrollToPos>=mCSB_draggerContainer.height()-mCSB_dragger.height()){ /*max dragger position is bottom*/
scrollToPos=mCSB_draggerContainer.height()-mCSB_dragger.height();
}
mCSB_dragger.css("top",scrollToPos);
}
if(options.callback){
$this.mCustomScrollbar("scroll",false);
}else{
$this.mCustomScrollbar("scroll",true);
}
}
},
callbacks:function(callback){
var $this=$(this),
mCustomScrollBox=$this.find(".mCustomScrollBox"),
mCSB_container=$this.find(".mCSB_container");
switch(callback){
/*start scrolling callback*/
case "onScrollStart":
if(!mCSB_container.is(":animated")){
$this.data("onScrollStart_Callback").call();
}
break;
/*end scrolling callback*/
case "onScroll":
if($this.data("horizontalScroll")){
var mCSB_containerX=Math.round(mCSB_container.position().left);
if(mCSB_containerX<0 && mCSB_containerX<=mCustomScrollBox.width()-mCSB_container.outerWidth()+$this.data("onTotalScroll_Offset")){
$this.data("onTotalScroll_Callback").call();
}else if(mCSB_containerX>=-$this.data("onTotalScroll_Offset")){
$this.data("onTotalScrollBack_Callback").call();
}else{
$this.data("onScroll_Callback").call();
}
}else{
var mCSB_containerY=Math.round(mCSB_container.position().top);
if(mCSB_containerY<0 && mCSB_containerY<=mCustomScrollBox.height()-mCSB_container.outerHeight()+$this.data("onTotalScroll_Offset")){
$this.data("onTotalScroll_Callback").call();
}else if(mCSB_containerY>=-$this.data("onTotalScroll_Offset")){
$this.data("onTotalScrollBack_Callback").call();
}else{
$this.data("onScroll_Callback").call();
}
}
break;
/*while scrolling callback*/
case "whileScrolling":
if($this.data("whileScrolling_Callback") && !$this.data("whileScrolling")){
$this.data({"whileScrolling":setInterval(function(){
if(mCSB_container.is(":animated") && !$this.data("mCS_Init")){
$this.data("whileScrolling_Callback").call();
}
},$this.data("whileScrolling_Interval"))});
}
break;
}
},
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.find(".mCSB_dragger");
mCustomScrollBox.unbind("mousewheel focusin");
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}).addClass("mCS_disabled");
},
destroy:function(){
var $this=$(this),
content=$this.find(".mCSB_container").html();
$this.find(".mCustomScrollBox").remove();
$this.html(content).removeClass("mCustomScrollbar _mCS_"+$(document).data("mCustomScrollbar-index")).addClass("mCS_destroyed");
}
}
$.fn.mCustomScrollbar=function(method){
if(methods[method]){
return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
}else if(typeof method==="object" || !method){
return methods.init.apply(this,arguments);
}else{
$.error("Method "+method+" does not exist");
}
};
})(jQuery);
/*iOS 6 bug fix
iOS 6 suffers from a bug that kills timers that are created while a page is scrolling.
The following fixes that problem by recreating timers after scrolling finishes (with interval correction).*/
var iOSVersion=iOSVersion();
if(iOSVersion>=6){
(function(h){var a={};var d={};var e=h.setTimeout;var f=h.setInterval;var i=h.clearTimeout;var c=h.clearInterval;if(!h.addEventListener){return false}function j(q,n,l){var p,k=l[0],m=(q===f);function o(){if(k){k.apply(h,arguments);if(!m){delete n[p];k=null}}}l[0]=o;p=q.apply(h,l);n[p]={args:l,created:Date.now(),cb:k,id:p};return p}function b(q,o,k,r,t){var l=k[r];if(!l){return}var m=(q===f);o(l.id);if(!m){var n=l.args[1];var p=Date.now()-l.created;if(p<0){p=0}n-=p;if(n<0){n=0}l.args[1]=n}function s(){if(l.cb){l.cb.apply(h,arguments);if(!m){delete k[r];l.cb=null}}}l.args[0]=s;l.created=Date.now();l.id=q.apply(h,l.args)}h.setTimeout=function(){return j(e,a,arguments)};h.setInterval=function(){return j(f,d,arguments)};h.clearTimeout=function(l){var k=a[l];if(k){delete a[l];i(k.id)}};h.clearInterval=function(l){var k=d[l];if(k){delete d[l];c(k.id)}};var g=h;while(g.location!=g.parent.location){g=g.parent}g.addEventListener("scroll",function(){var k;for(k in a){b(e,i,a,k)}for(k in d){b(f,c,d,k)}})}(window));
}
function iOSVersion(){
var agent=window.navigator.userAgent,
start=agent.indexOf('OS ');
if((agent.indexOf('iPhone')>-1 || agent.indexOf('iPad')>-1) && start>-1){
return window.Number(agent.substr(start+3,3).replace('_','.'));
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment