/** * jQuery Google Wave Scroll Pane * Version 0.1 2010-11-02 * * @requires jQuery v1.3+ * @author Konr Ness http://konrness.com * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html */ (function($) { $.fn.gWaveScrollPane = function(settings) { var config = { 'foo': 'bar' }; if (settings) $.extend(config, settings); return this.each(function() { var $this = $(this); var $scrollableWrapper, $scrollbarContainer, $scrollbarGrabber, $scrollbarIndicator; var waitToMoveGrabber = false; /** * Setup Scrollable Wrapper */ // create gwave-scroll-wrapper $scrollableWrapper = $('
'); // set width/height to be same as this $scrollableWrapper.height($this.height()).width($this.width()); // add scrollable wrapper to DOM just before this $this.before($scrollableWrapper); // put this inside scrollable wrapper $this.appendTo($scrollableWrapper); /** * Create the scrollbar */ $scrollbarContainer = $(' '); $scrollbarGrabber = $(' '); $scrollbarIndicator = $(''); $scrollbarContainer.prepend($scrollbarIndicator); $scrollbarContainer.prepend($scrollbarGrabber); $scrollableWrapper.prepend($scrollbarContainer); /** * Setup initial layout */ // hide indicator $scrollbarIndicator.hide(); // grabber up/down button mouseovers $scrollbarGrabber.children().each(function(){ $(this).mouseover(function(){ $scrollbarGrabber.addClass(this.className + '-over'); }).mouseleave(function(){ $scrollbarGrabber.removeClass(this.className + '-over'); }); }); // reset content's scroll top $this.scrollTop(0); $this.data('goal-scroll-top', $this.scrollTop()); /** * Setup content scrolling events */ // listen to scroll changes from box and update indicator position $this.bind('scroll', function(e){ scrollPercentage = this.scrollTop / (this.scrollHeight - this.offsetHeight); newIndicatorTop = ($scrollbarContainer.height() - $scrollbarIndicator.height()) * scrollPercentage; newIndicatorTop = newIndicatorTop + 'px'; $scrollbarIndicator.css('top', newIndicatorTop); }); // setup mousewheel scrolling for content box $this.bind('mousewheel', function(event, delta) { $this.scrollTop($this.scrollTop() + (-delta*45)); $this.data('goal-scroll-top', $this.scrollTop()); updateGrabberPosition(true); return false; }); /** * Setup grabber events */ // grabber dragging $scrollbarGrabber.draggable({ addClasses : false, axis : 'y', containment : 'parent', distance : 2, cursor : 'pointer', start : function(){ $scrollbarIndicator.show(); }, stop : function(){ $scrollbarIndicator.hide(); }, drag : function(){ scrollPercentage = $scrollbarGrabber.position().top / ($scrollbarContainer.height() - $scrollbarGrabber.height()); scrollToPercentage(scrollPercentage); } }).mouseout(function(){ waitToMoveGrabber = false; updateGrabberPosition(false); }); // grabber arrow clicking $scrollbarGrabber.children('div').click(function(){ direction = $(this).hasClass('up') ? -1 : 1; waitToMoveGrabber = true; $scrollbarIndicator.show(); scrollByDelta(direction * 150); }); /** * Functions */ function updateGrabberPosition(immediate) { if(waitToMoveGrabber == true){ return; } if($scrollbarGrabber.hasClass('ui-draggable-dragging')){ return; } contentScrollPercentage = $this.get(0).scrollTop / ($this.get(0).scrollHeight - $this.get(0).offsetHeight); newGrabberTop = contentScrollPercentage * ($scrollbarContainer.height() - $scrollbarGrabber.height()); if(immediate) { $scrollbarGrabber.css('top', newGrabberTop + 'px'); $scrollbarIndicator.hide(); } else { // animate $scrollbarGrabber.stop().animate( { top : newGrabberTop + 'px' }, 250, 'swing', function(){ $scrollbarIndicator.hide(); } ); } } function scrollToPercentage(percentage) { newContentTop = ($this.get(0).scrollHeight - $this.height()) * percentage; $this.data('goal-scroll-top', newContentTop); $this.stop().animate( { scrollTop: newContentTop + 'px' }, 500, 'swing' ); } function scrollByDelta(delta) { newContentTop = $this.data('goal-scroll-top') + delta; $this.data('goal-scroll-top', newContentTop); $this.stop().animate( { scrollTop: newContentTop + 'px' }, 500, 'swing' ); } }); }; })(jQuery);