/jquery.ba-floatingscrollbar.js
Forked from cowboy/jquery.ba-floatingscrollbar.js
Last active Dec 22, 2015
/*! | |
* jQuery Floating Scrollbar - v0.5 - 09/05/2013 | |
* http://benalman.com/ | |
* | |
* Copyright (c) 2011 "Cowboy" Ben Alman | |
* Dual licensed under the MIT and GPL licenses. | |
* http://benalman.com/about/license/ | |
*/ | |
(function($, window){ | |
'use strict'; | |
var // A few reused jQuery objects. | |
win = $(window), | |
// All the elements being monitored. | |
elems = $([]), | |
// The current element. | |
current, | |
// The previous current element. | |
previous, | |
// Create the floating scrollbar. | |
scroller = $('<div id="floating-scrollbar"><div/></div>'), | |
scrollerInner = scroller.children(); | |
// Hide or show the floating scrollbar. | |
function setState( state ) { | |
scroller.toggle(!!state); | |
} | |
// Sync floating scrollbar if element content is scrolled. | |
function scrollCurrent() { | |
if ( current ) { | |
scroller.scrollLeft(current.scrollLeft()); | |
} | |
} | |
// This is called on window scroll or resize, or when elements are added or | |
// removed from the internal elems list. | |
function update() { | |
previous = current; | |
current = null; | |
// Find the first element whose content is visible, but whose bottom is | |
// below the viewport. | |
elems.each(function(){ | |
var elem = $(this), | |
top = elem.offset().top, | |
bottom = top + elem.height(), | |
viewportBottom = win.scrollTop() + win.height(), | |
topOffset = 30; | |
if ( top + topOffset < viewportBottom && bottom > viewportBottom ) { | |
current = elem; | |
return false; | |
} | |
}); | |
// Abort if no elements were found. | |
if ( !current ) { setState(); return; } | |
// Test to see if the current element has a scrollbar. | |
var scroll = current.scrollLeft(), | |
scrollMax = current.scrollLeft(90019001).scrollLeft(), | |
widthOuter = current.innerWidth(), | |
widthInner = widthOuter + scrollMax; | |
current.scrollLeft(scroll); | |
// Abort if the element doesn't have a scrollbar. | |
if ( widthInner <= widthOuter ) { setState(); return; } | |
// Show the floating scrollbar. | |
setState(true); | |
// Sync floating scrollbar if element content is scrolled. | |
if ( !previous || previous[0] !== current[0] ) { | |
if ( previous ) { | |
previous.unbind('scroll', scrollCurrent); | |
} | |
current.scroll(scrollCurrent).after(scroller); | |
} | |
// Adjust the floating scrollbar as-necessary. | |
scroller | |
.css({ | |
left: current.offset().left - win.scrollLeft(), | |
width: widthOuter | |
}) | |
.scrollLeft(scroll); | |
scrollerInner.width(widthInner); | |
} | |
// Initialize the floating scrollbar. | |
scroller | |
.hide() | |
.css({ | |
position: 'fixed', | |
bottom: 0, | |
height: '30px', | |
overflowX: 'auto', | |
overflowY: 'hidden' | |
}) | |
.scroll(function() { | |
// If there's a current element, set its scroll appropriately. | |
if ( current ) { | |
current.scrollLeft(scroller.scrollLeft()); | |
} | |
}); | |
scrollerInner.css({ | |
border: '1px solid #fff', | |
opacity: 0.01 | |
}); | |
// Call on elements to monitor their position and scrollness. Pass `false` to | |
// stop monitoring those elements. | |
$.fn.floatingScrollbar = function( state ) { | |
if ( state === false ) { | |
// Remove these elements from the list. | |
elems = elems.not(this); | |
// Stop monitoring elements for scroll. | |
this.unbind('scroll', scrollCurrent); | |
if ( !elems.length ) { | |
// No elements remain, so detach scroller and unbind events. | |
scroller.detach(); | |
win.unbind('resize scroll', update); | |
} | |
} else if ( this.length ) { | |
// Don't assume the set is non-empty! | |
if ( !elems.length ) { | |
// Adding elements for the first time, so bind events. | |
win.resize(update).scroll(update); | |
} | |
// Add these elements to the list. | |
elems = elems.add(this); | |
} | |
// Update. | |
update(); | |
// Make chainable. | |
return this; | |
}; | |
// Call this to force an update, for instance, if elements were inserted into | |
// the DOM before monitored elements, changing their vertical position. | |
$.floatingScrollbarUpdate = update; | |
})(jQuery, this); |
/* | |
* jQuery Floating Scrollbar - v0.5 - 09/05/2013 | |
* http://benalman.com/ | |
* | |
* Copyright (c) 2011 "Cowboy" Ben Alman | |
* Dual licensed under the MIT and GPL licenses. | |
* http://benalman.com/about/license/ | |
*/ | |
(function(d,j){var h=d(j),a=d([]),i,e,f=d('<div id="floating-scrollbar"><div/></div>'),b=f.children();function g(l){f.toggle(!!l)}function k(){if(i){f.scrollLeft(i.scrollLeft())}}function c(){e=i;i=null;a.each(function(){var s=d(this),t=s.offset().top,p=t+s.height(),r=h.scrollTop()+h.height(),q=30;if(t+q<r&&p>r){i=s;return false}});if(!i){g();return}var m=i.scrollLeft(),l=i.scrollLeft(90019001).scrollLeft(),o=i.innerWidth(),n=o+l;i.scrollLeft(m);if(n<=o){g();return}g(true);if(!e||e[0]!==i[0]){if(e){e.unbind("scroll",k)}i.scroll(k).after(f)}f.css({left:i.offset().left-h.scrollLeft(),width:o}).scrollLeft(m);b.width(n)}f.hide().css({position:"fixed",bottom:0,height:"30px",overflowX:"auto",overflowY:"hidden"}).scroll(function(){if(i){i.scrollLeft(f.scrollLeft())}});b.css({border:"1px solid #fff",opacity:0.01});d.fn.floatingScrollbar=function(l){if(l===false){a=a.not(this);this.unbind("scroll",k);if(!a.length){f.detach();h.unbind("resize scroll",c)}}else{if(this.length){if(!a.length){h.resize(c).scroll(c)}a=a.add(this)}}c();return this};d.floatingScrollbarUpdate=c})(jQuery,this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment