;(function (factory)
{
if (typeof define === 'function' && define.amd)
{
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object')
{
// Node/CommonJS
factory(require('jquery'));
} else
{
// Browser globals
factory(jQuery);
}
}(function ($)
{
$.tiny = $.tiny || { };
$.tiny.scrollbar = {
options: {
axis : 'y' // vertical or horizontal scrollbar? ( x || y ).
, wheel : true // enable or disable the mousewheel;
, wheelSpeed : 40 // how many pixels must the mouswheel scroll at a time.
, wheelLock : true // return mouswheel to browser if there is no more content.
, scrollInvert : false // Enable invert style scrolling
, trackSize : false // set the size of the scrollbar to auto or a fixed number.
, thumbSize : false // set the size of the thumb to auto or a fixed number.
}
};
$.fn.tinyscrollbar = function(params)
{
var options = $.extend( {}, $.tiny.scrollbar.options, params );
this.each(function()
{
$(this).data('tsb', new Scrollbar( $( this ), options ) );
});
return this;
};
$.fn.tinyscrollbar_update = function(sScroll)
{
return $( this ).data( 'tsb' ).update( sScroll );
};
function Scrollbar($container, options)
{
var self = this
, $viewport = $container.find(".viewport")
, $overview = $container.find(".overview")
, $scrollbar = $container.find(".scrollbar")
, $track = $scrollbar.find(".track")
, $thumb = $scrollbar.find(".thumb")
, viewportSize = 0
, contentSize = 0
, contentPosition = 0
, contentRatio = 0
, trackSize = 0
, trackRatio = 0
, thumbSize = 0
, thumbPosition = 0
, mousePosition = 0
, isHorizontal = options.axis === 'x'
, hasTouchEvents = "ontouchstart" in document.documentElement
, sizeLabel = isHorizontal ? "width" : "height"
, posiLabel = isHorizontal ? "left" : "top"
;
function initialize()
{
self.update();
setEvents();
return self;
}
this.update = function(scrollTo)
{
sizeLabelCap = sizeLabel.charAt(0).toUpperCase() + sizeLabel.slice(1).toLowerCase();
viewportSize = $viewport[0]['offset'+ sizeLabelCap];
contentSize = $overview[0]['scroll'+ sizeLabelCap];
contentRatio = viewportSize / contentSize;
trackSize = options.trackSize || viewportSize;
thumbSize = Math.min(trackSize, Math.max(0, (options.thumbSize || (trackSize * contentRatio))));
trackRatio = options.thumbSize ? (contentSize - viewportSize) / (trackSize - thumbSize) : (contentSize / trackSize);
$scrollbar.toggleClass("disable", contentRatio >= 1);
switch (scrollTo)
{
case "bottom":
contentPosition = contentSize - viewportSize;
break;
case "relative":
contentPosition = Math.min(contentSize - viewportSize, Math.max(0, contentPosition));
break;
default:
contentPosition = parseInt(scrollTo, 10) || 0;
}
setSize();
};
function setSize()
{
$thumb.css(posiLabel, contentPosition / trackRatio);
$overview.css(posiLabel, -contentPosition);
mousePosition = $thumb.offset()[posiLabel];
$scrollbar.css(sizeLabel, trackSize);
$track.css(sizeLabel, trackSize);
$thumb.css(sizeLabel, thumbSize);
}
function setEvents()
{
if(hasTouchEvents)
{
$viewport[0].ontouchstart = function(event)
{
if(1 === event.touches.length)
{
start(event.touches[0]);
event.stopPropagation();
}
};
}
else
{
$thumb.bind("mousedown", start);
$track.bind("mouseup", drag);
}
if(options.wheel && window.addEventListener)
{
$container[0].addEventListener("DOMMouseScroll", wheel, false );
$container[0].addEventListener("mousewheel", wheel, false );
}
else if(options.wheel)
{
$container[0].onmousewheel = wheel;
}
}
function start(event)
{
$("body").addClass("noSelect");
mousePosition = isHorizontal ? event.pageX : event.pageY;
thumbPosition = parseInt($thumb.css(posiLabel), 10) || 0;
if(hasTouchEvents)
{
document.ontouchmove = function(event)
{
event.preventDefault();
drag(event.touches[0]);
};
document.ontouchend = end;
}
else
{
$(document).bind("mousemove", drag);
$(document).bind("mouseup", end);
$thumb.bind("mouseup", end);
}
}
function wheel(event)
{
if(contentRatio < 1)
{
var eventObject = event || window.event
, wheelSpeedDelta = eventObject.wheelDelta ? eventObject.wheelDelta / 120 : -eventObject.detail / 3
;
contentPosition -= wheelSpeedDelta * options.wheelSpeed;
contentPosition = Math.min((contentSize - viewportSize), Math.max(0, contentPosition));
$thumb.css(posiLabel, contentPosition / trackRatio);
$overview.css(posiLabel, -contentPosition);
if(options.wheelLock || (contentPosition !== (contentSize - viewportSize) && contentPosition !== 0))
{
eventObject = $.event.fix(eventObject);
eventObject.preventDefault();
}
}
}
function drag( event )
{
if(contentRatio < 1)
{
mousePositionNew = isHorizontal ? event.pageX : event.pageY;
thumbPositionDelta = mousePositionNew - mousePosition;
if(options.scrollInvert)
{
thumbPositionDelta = mousePosition - mousePositionNew;
}
thumbPositionNew = Math.min((trackSize - thumbSize), Math.max(0, thumbPosition + thumbPositionDelta));
contentPosition = thumbPositionNew * trackRatio;
$thumb.css(posiLabel, thumbPositionNew);
$overview.css(posiLabel, -contentPosition);
}
}
function end()
{
$("body").removeClass("noSelect");
$(document).unbind("mousemove", drag);
$(document).unbind("mouseup", end);
$thumb.unbind("mouseup", end);
document.ontouchmove = document.ontouchend = null;
}
return initialize();
}
}));