/*! * jquery.customscroll 1.0 * * Dual licensed under the MIT or GPL Version 2 licenses. * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl-2.0.html */ ;(function ($) { $.customscrollOptions = { always: false, show: { on: 'mouseenter scrollstart', effect: 'fadeIn', speed: 250, delay: 0 }, hide: { on: 'mouseleave scrollstop', effect: 'fadeOut', speed: 250, delay: 750 }, grow: { size: 3, speed: 100 }, pageUpnDown: { speed: 100 } }; $.fn.customscroll = function (options) { options = $.extend(true, {}, $.customscrollOptions, options || {}); return this.each(function () { var object = $(this); // build template object.addClass('customscroll'); object.html([ '
', '
', object.html(), '
', '
', '
', '
', '
', '
', '
' ].join('')); // get elements var wrapper = object.children('.wrapper'), placeholder = object.children('.placeholder'), track = placeholder.children('.track'), grip = track.children('.grip'); // object hover var showHideTimer, show = function (event) { if (object.height() >= wrapper[0].scrollHeight) { // we dont need scroll return; } if (wrapper[0].scrollHeight < parseInt(object.css('max-height'))) { // this is a fix for IE return; } // show clearInterval(showHideTimer); showHideTimer = setTimeout(function () { track[options.show.effect](options.show.speed); }, options.show.delay); if (!event || event.type !== 'scrollstart') { // used for adjusting sizes wrapper.trigger('scroll'); } }; wrapper.on(options.show.on, show); wrapper.on(options.hide.on, function callback() { // don't hide if always is true if (options.always) { return; } if (wrapper.hasClass('keep')) { // someone says do not hide, try again later return setTimeout(function () { callback(); }, 250); } // hide clearInterval(showHideTimer); showHideTimer = setTimeout(function () { track[options.hide.effect](options.hide.speed); }, options.hide.delay); }); // bind scroll event var scrollingTimer; wrapper.on('scroll', function (event) { var height = object.height(); grip.css({ // grip height is view height / scroll height * 200 (4 is for margins) height: height / this.scrollHeight * height - parseInt(object.css('paddingTop')) - parseInt(object.css('paddingBottom')), // scroll position marginTop: this.scrollTop * 100 / this.scrollHeight * height / 100 + 'px' }); // custom scroll start / end events if (!scrollingTimer) { wrapper.trigger('scrollstart'); } clearInterval(scrollingTimer); scrollingTimer = setTimeout(function () { wrapper.trigger('scrollstop'); scrollingTimer = null; }, 200); }); // placeholder and track hover wrapper.on('mouseover', function () { // do not hide track and show wrapper.addClass('keep'); show(); }); // placeholder and track hover wrapper.on('mouseleave', function () { // do not hide track and show wrapper.removeClass('keep'); }); placeholder.on('mouseover', function () { // do not hide track and show wrapper.addClass('keep'); show(); }); placeholder.on('mouseleave', function () { // hide track wrapper.removeClass('keep'); }); track.on('mouseenter', function () { track.addClass('hover'); if (options.grow) { // stop animation queue and animate track.stop(true, true); track.animate({width: '+=' + options.grow.size + 'px'}, options.grow.speed); } }); track.on('mouseleave', function hover() { track.removeClass('hover'); if (options.grow) { // stop animation queue and animate track.stop(true, true); track.animate({width: '-=' + options.grow.size + 'px'}, options.grow.speed); } }); // page up / down (track click) track.on('click', function (event) { if ($(event.target).hasClass('grip')) { // do not trigger when clicking the egrip return; } if (event.pageY - track.offset().top > parseInt(grip.css('marginTop'))) { // clicked after grip var operation = '+'; } else { // clicked before grip var operation = '-'; } // scroll wrapper.animate({ scrollTop: operation + '=' + object.height() + 'px' }, options.pageUpnDown.speed); }); // show initially if always is true if (options.always) { show(); } // grip drag var dragging = false; grip.on('mousedown', function (event) { // do not hide wrapper.addClass('keep'); // mark as dragging dragging = true; // prevent text selection $('body').addClass('dragging'); }); $(document).on('mousemove', function (event) { if (dragging) { // we have drag, move wrapper.scrollTop(wrapper[0].scrollHeight * (event.pageY - track.offset().top - grip.height() / 2) / object.height()); event.preventDefault(); } }); $(document).on('mouseup', function () { if (dragging) { // we have drag, remove wrapper.removeClass('keep'); dragging = false; $('body').removeClass('dragging'); } }); }); }; })(jQuery);