(function ($){
$.fn.extend({
slimScroll: function (options){
var defaults={
axis: 'y',
width: 'auto',
height: '250px',
size: '7px',
color: '#000',
positionX: 'bottom',
positionY: 'right',
distance: '1px',
startX: 'left',
startY: 'top',
opacity: 0.4,
alwaysVisible: false,
disableFadeOut: false,
railVisible: false,
railColor: '#333',
railOpacity: 0.2,
railDraggable: true,
railClassX: 'slimScrollRailX',
barClassX: 'slimScrollBarX',
railClassY: 'slimScrollRailY',
barClassY: 'slimScrollBarY',
wrapperClass: 'slimScrollDiv',
animate: false,
allowPageScroll: false,
wheelStep: 20,
touchScrollStep: 200,
borderRadius: '7px',
railBorderRadius: '7px',
ggSlimscrollHandler: false,
};
var o=$.extend(defaults, options);
o.axis=o.axis.toLowerCase();
this.each(function (){
var hasHorizontalScrollbar;
var hasVerticalScrollbar;
var t, pageX, pageY;
var isOverPanel,
isOverBarX,
isOverBarY,
isDragg,
queueHideX,
queueHideY,
touchDifX,
touchDifY,
barHeight,
barWidth,
percentScrollX,
lastScrollX,
percentScrollY,
lastScrollY,
divS='<div></div>',
minBarHeight=30,
minBarWidth=30,
releaseScroll=false;
var me=$(this);
var $doc=$(document);
if(me.parent().hasClass(o.wrapperClass)){
$.extend(o, me.data('slimScrollConfig')||{});
var offset_horizontal=me.scrollLeft();
var offset_vertical=me.scrollTop();
barX=me.siblings('.' + o.barClassX);
railX=me.siblings('.' + o.railClassX);
barY=me.siblings('.' + o.barClassY);
railY=me.siblings('.' + o.railClassY);
hasHorizontalScrollbar=o.axis=='both'||o.axis=='x';
hasVerticalScrollbar=o.axis=='both'||o.axis=='y';
getBarXWidth();
getBarYHeight();
if($.isPlainObject(options)){
if('width' in options&&hasHorizontalScrollbar){
if(options.width=='auto'){
me.parent().css('width', 'auto');
me.css('width', 'auto');
o.width=me.parent().parent().width();
}else{
o.width=options.width;
me.css({ 'white-space': 'nowrap' });
}}
if('height' in options&&hasVerticalScrollbar){
if(options.height=='auto'){
me.parent().css('height', 'auto');
me.css('height', 'auto');
o.height=me.parent().parent().height();
}else{
o.height=options.height;
}}
me.parent().css({
position: 'relative',
overflow: 'hidden',
width: o.width,
height: o.height,
});
me.css({
overflow: 'hidden',
width: o.width,
height: o.height,
});
if('scrollToX' in options){
offset_horizontal=parseInt(o.scrollToX);
}else if('scrollByX' in options){
offset_horizontal +=parseInt(o.scrollByX);
}
if('scrollToY' in options){
offset_vertical=parseInt(o.scrollToY);
}else if('scrollByY' in options){
offset_vertical +=parseInt(o.scrollByY);
}
if('destroy' in options){
barX.remove();
railX.remove();
barY.remove();
railY.remove();
me.unwrap();
return;
}}
scrollContent(offset_horizontal, offset_vertical, false, true);
return;
}else if($.isPlainObject(options)){
if('destroy' in options){
return;
}}
hasHorizontalScrollbar=o.axis=='both'||o.axis=='x';
hasVerticalScrollbar=o.axis=='both'||o.axis=='y';
o.height=o.height=='auto' ? me.parent().height():o.height;
o.width=o.width=='auto' ? me.parent().width():o.width;
me.data('slimScrollConfig', o);
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,
});
me.wrap(wrapper);
if(hasHorizontalScrollbar){
if(o.width!='auto'&&hasHorizontalScrollbar){
me.css({ 'white-space': 'nowrap' });
}
var railX=$(divS)
.addClass(o.railClassX)
.css({
width: '100%',
height: o.size,
position: 'absolute',
left: 0,
display: o.alwaysVisible&&o.railVisible ? 'block':'none',
'border-radius': o.railBorderRadius,
background: o.railColor,
opacity: o.railOpacity,
zIndex: 90,
});
var barX=$(divS)
.addClass(o.barClassX)
.css({
background: o.color,
height: o.size,
position: 'absolute',
left: 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 xPosCss=o.positionX=='top' ? { top: o.distance }:{ bottom: o.distance };
railX.css(xPosCss);
barX.css(xPosCss);
me.parent().append(barX);
me.parent().append(railX);
if(o.railDraggable){
barX
.on('mousedown', function (e){
isDragg=true;
t=parseFloat(barX.css('left'));
pageX=e.pageX;
$doc.on('mousemove.slimscrollX', function (e){
currLeft=t + e.pageX - pageX;
barX.css('left', currLeft);
scrollContent(0, 0, barX.position().left);
});
$doc.on('mouseup.slimscrollX', function (e){
isDragg=false;
hideBarX();
$doc.unbind('.slimscrollX');
});
return false;
})
.on('selectstart.slimscrollX', function (e){
e.stopPropagation();
e.preventDefault();
return false;
});
railX.on('mousedown', function (e){
var deltaX=((e.offsetX - barWidth / 2) * me[0].scrollWidth) / me.outerWidth();
scrollContent(deltaX, 0, false, true);
t=parseFloat(barX.css('left'));
pageX=e.pageX;
$doc.on('mousemove.slimscrollX', function (e){
currLeft=t + e.pageX - pageX;
barX.css('left', currLeft);
scrollContent(0, 0, barX.position().left);
});
$doc.on('mouseup.slimscrollX', function (e){
isDragg=false;
hideBarX();
$doc.unbind('.slimscrollX');
});
return false;
});
}
railX.hover(function (){
showBarX();
},
function (){
hideBarX();
}
);
barX.hover(function (){
isOverBarX=true;
},
function (){
isOverBarX=false;
}
);
getBarXWidth();
if(o.startX==='right'){
barX.css({ left: me.outerWidth() - barX.outerWidth() });
scrollContent(0, 0, true);
}else if(o.startX!=='left'){
scrollContent($(o.startX).position().left, null, null, true);
if(!o.alwaysVisible){
barX.hide();
}}
}
if(hasVerticalScrollbar){
var railY=$(divS)
.addClass(o.railClassY)
.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 barY=$(divS)
.addClass(o.barClassY)
.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 yPosCss=o.positionY=='right' ? { right: o.distance }:{ left: o.distance };
railY.css(yPosCss);
barY.css(yPosCss);
me.parent().append(barY);
me.parent().append(railY);
if(o.railDraggable){
barY
.on('mousedown', function (e){
isDragg=true;
t=parseFloat(barY.css('top'));
pageY=e.pageY;
$doc.on('mousemove.slimscrollY', function (e){
currTop=t + e.pageY - pageY;
barY.css('top', currTop);
scrollContent(0, 0, barY.position().top);
});
$doc.on('mouseup.slimscrollY', function (e){
isDragg=false;
hideBarY();
$doc.unbind('.slimscrollY');
});
return false;
})
.on('selectstart.slimscrollY', function (e){
e.stopPropagation();
e.preventDefault();
return false;
});
railY.on('mousedown', function (e){
var deltaY=((e.offsetY - barHeight / 2) * me[0].scrollHeight) / me.outerHeight();
scrollContent(0, deltaY, false, true);
t=parseFloat(barY.css('top'));
pageY=e.pageY;
$doc.on('mousemove.slimscrollY', function (e){
currTop=t + e.pageY - pageY;
barY.css('top', currTop);
scrollContent(0, 0, barY.position().top);
});
$doc.on('mouseup.slimscrollY', function (e){
isDragg=false;
hideBarY();
$doc.unbind('.slimscrollY');
});
return false;
});
}
railY.hover(function (){
showBarY();
},
function (){
hideBarY();
}
);
barY.hover(function (){
isOverBarY=true;
},
function (){
isOverBarY=false;
}
);
getBarYHeight();
if(o.startY==='bottom'){
barY.css({ top: me.outerHeight() - barY.outerHeight() });
scrollContent(0, 0, true);
}else if(o.startY!=='top'){
scrollContent(null, $(o.startY).position().top, null, true);
if(!o.alwaysVisible){
barY.hide();
}}
}
me.hover(function (){
isOverPanel=true;
showBarX();
showBarY();
hideBarX();
hideBarY();
},
function (){
isOverPanel=false;
hideBarX();
hideBarY();
}
);
var _triggerInit=function (){
if(typeof Hammer_gg=='undefined'){
setTimeout(_triggerInit, 100);
return;
}
if(o.isMobile){
var hammer=new Hammer_gg(this),
scrollWidth=50;
hammer.get('pan').set({
threshold: scrollWidth,
});
hammer.on('panleft', function (e){
scrollContent(0, scrollWidth, false, false, true);
panDistance=e.distance;
});
hammer.on('panend', function (e){
var offset=scrollWidth * (e.velocityX * -1) * 30;
scrollContent(0, offset, false, false, true);
});
hammer.on('panright', function (e){
scrollContent(0, -scrollWidth, false, false, true);
panDistance=e.distance;
});
}};
_triggerInit();
attachWheel(this);
function _getDeltaFromEvent(e){
var deltaX=0;
var deltaY=0;
deltaX=(e.deltaX||-e.wheelDelta||e.detail) >> 10||1;
deltaY=(e.deltaY||-e.wheelDelta||e.detail) >> 10||1;
if('axis' in e&&e.axis===e.HORIZONTAL_AXIS){
deltaX=deltaY * -1;
deltaY=0;
}
if(deltaX!==deltaX&&deltaY!==deltaY ){
deltaX=0;
}
return [deltaX, deltaY];
}
function _onWheel(e){
if(!isOverPanel){
return;
}
e=e||window.event;
var delta=_getDeltaFromEvent(e);
var deltaX=delta[0];
var deltaY=delta[1];
var target=e.target||e.srcTarget||e.srcElement;
if($(target)
.closest('.' + o.wrapperClass)
.is(me.parent())
){
scrollContent(deltaX, deltaY, true);
}
if(e.preventDefault&&!releaseScroll){
e.preventDefault();
e.stopPropagation();
}
if(!releaseScroll){
e.returnValue=false;
}}
function scrollContent(x, y, isWheel, isJump, isPan){
releaseScroll=false;
var needToRunWindowScroll=false,
prevBarXOffset=0;
if(hasHorizontalScrollbar){
var deltaX=x;
var maxLeft=me.outerWidth() - barX.outerWidth(),
totalWidth=me[0].scrollWidth,
scrollOffset=me.scrollLeft(),
barXOffset=parseFloat(barX.css('left'));
if(isWheel){
if(!hasVerticalScrollbar){
x=y;
}
deltaX=parseInt(barX.css('left')) + x * parseInt(o.wheelStep);
deltaX=Math.min(Math.max(deltaX, 0), maxLeft);
deltaX=x > 0 ? Math.ceil(deltaX):Math.floor(deltaX);
barX.css({ left: deltaX + 'px' });
prevBarXOffset=barXOffset;
barXOffset=parseFloat(barX.css('left'));
needToRunWindowScroll=prevBarXOffset==barXOffset;
}
percentScrollX=barXOffset / maxLeft;
deltaX=percentScrollX * (totalWidth - me.outerWidth());
if(isPan){
deltaX=totalWidth - (totalWidth - scrollOffset - y);
var panOffsetPercent=deltaX / (totalWidth - me.outerWidth());
var scrollBarOffset=maxLeft * panOffsetPercent;
scrollBarOffset=Math.min(Math.max(scrollBarOffset, 0), maxLeft);
scrollBarOffset=x > 0 ? Math.ceil(scrollBarOffset):Math.floor(scrollBarOffset);
barX.stop(true, true).animate({ left: scrollBarOffset + 'px' }, 300, 'linear');
}
if(isJump){
if(!hasVerticalScrollbar){
x=y;
}
deltaX=x;
var offsetLeft=(deltaX / me[0].scrollWidth) * me.outerWidth();
offsetLeft=Math.min(Math.max(offsetLeft, 0), maxLeft);
barX.css({ left: offsetLeft + 'px' });
}
if(o.animate){
me.scrollTop(deltaX);
me.stop(true, true).animate({ scrollLeft: deltaX }, 500, 'linear');
}else{
me.scrollLeft(deltaX);
}
me.trigger('slimscrollingX', ~~deltaX);
showBarX(needToRunWindowScroll);
hideBarX();
}
if(hasVerticalScrollbar){
var deltaY=y;
var maxTop=me.outerHeight() - barY.outerHeight();
if(isWheel){
deltaY=parseInt(barY.css('top')) + (y * parseInt(o.wheelStep)) / 100;
deltaY=Math.min(Math.max(deltaY, 0), maxTop);
deltaY=y > 0 ? Math.ceil(deltaY):Math.floor(deltaY);
barY.css({ top: deltaY + 'px' });
}
percentScrollY=parseInt(barY.css('top')) / (me.outerHeight() - barY.outerHeight());
deltaY=percentScrollY * (me[0].scrollHeight - me.outerHeight());
if(isJump){
deltaY=y;
var offsetTop=(deltaY / me[0].scrollHeight) * me.outerHeight();
offsetTop=Math.min(Math.max(offsetTop, 0), maxTop);
barY.css({ top: offsetTop + 'px' });
}
me.scrollTop(deltaY);
me.trigger('slimscrollingY', ~~deltaY);
showBarY();
hideBarY();
}
if(o.ggSlimscrollHandler){
o.ggSlimscrollHandler();
}}
function attachWheel(target){
if(window.addEventListener){
if(typeof window.onwheel!=='undefined'){
target.addEventListener('wheel', _onWheel, false);
}else if(typeof window.onmousewheel!=='undefined'){
target.addEventListener('mousewheel', _onWheel, false);
}
target.addEventListener('DOMMouseScroll', _onWheel, false);
}else{
document.attachEvent('onmousewheel', _onWheel);
}}
function getBarXWidth(){
if(!barX){
return;
}
barWidth=Math.max((me.outerWidth() / me[0].scrollWidth) * me.outerWidth(), minBarWidth);
barX.css({ width: barWidth + 'px' });
var display=hasHorizontalScrollbar&&me[0].scrollWidth > me[0].clientWidth ? 'block':'none';
barX.css({ display: display });
}
function getBarYHeight(){
if(!barY){
return;
}
barHeight=Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);
barY.css({ height: barHeight + 'px' });
var display=hasVerticalScrollbar&&me[0].scrollHeight > me[0].clientHeight ? 'block':'none';
barY.css({ display: display });
}
function showBarX(needToRunWindowScroll){
if(!barX){
return;
}
getBarXWidth();
clearTimeout(queueHideX);
if(percentScrollX==~~percentScrollX&&needToRunWindowScroll){
releaseScroll=o.allowPageScroll;
if(lastScrollX!=percentScrollX){
var msg=~~percentScrollX===0 ? 'left':'right';
me.trigger('slimscrollX', msg);
}}else{
releaseScroll=false;
}
lastScrollX=percentScrollX;
if(barWidth >=me.outerWidth()){
releaseScroll=true;
return;
}
barX.fadeIn('fast');
if(o.railVisible){
railX.stop(true, true).fadeIn('fast');
}}
function hideBarX(){
if(!barX){
return;
}
if(!o.alwaysVisible){
queueHideX=setTimeout(function (){
if(!(o.disableFadeOut&&isOverPanel)&&!isOverBarX&&!isDragg){
barX.fadeOut('slow');
railX.fadeOut('slow');
}}, 1000);
}}
function showBarY(){
if(!barY){
return;
}
getBarYHeight();
clearTimeout(queueHideY);
if(percentScrollY==~~percentScrollY){
releaseScroll=o.allowPageScroll;
if(lastScrollY!=percentScrollY){
var msg=~~percentScrollY===0 ? 'top':'bottom';
me.trigger('slimscrollY', msg);
}}else{
releaseScroll=false;
}
lastScrollY=percentScrollY;
if(barHeight >=me.outerHeight()){
releaseScroll=true;
return;
}
barY.stop(true, true).fadeIn('fast');
if(o.railVisible){
railY.stop(true, true).fadeIn('fast');
}}
function hideBarY(){
if(!barY){
return;
}
if(!o.alwaysVisible){
queueHideY=setTimeout(function (){
if(!(o.disableFadeOut&&isOverPanel)&&!isOverBarY&&!isDragg){
barY.fadeOut('slow');
railY.fadeOut('slow');
}}, 1000);
}}
});
return this;
},
});
$.fn.extend({
slimscroll: $.fn.slimScroll,
});
})(jQuery);