Skip to content

Instantly share code, notes, and snippets.

@DutchKevv
Last active December 30, 2015 08:39
Show Gist options
  • Save DutchKevv/7803702 to your computer and use it in GitHub Desktop.
Save DutchKevv/7803702 to your computer and use it in GitHub Desktop.
A javascript sticky bar (floating sidebar) plugin. Requires jQuery and lodash/underscore
(function (window, document, App, $, _) {
'use strict';
App.prototype.Components || (App.prototype.Components = {});
var supports3d = false,
prefixes = ['Webkit', 'Moz', 'ms', 'O'],
div = document.createElement('div');
if (typeof div.style.perspective !== 'undefined') {
supports3d = true; // Browser supports CSS transform 3d without prefix
} else {
for ( var i = 0; i < prefixes.length; ++i ) {
if ((prefixes[i] + "Perspective") in div.style) {
supports3d = true;
break;
}
}
}
var StickyBar = function (obj) {
this.$el = obj.$el;
this.el = obj.$el[0];
this.headerH = $('header').height() || 0;
this.footerH = $('footer').height() || 0;
this.isDefault = true;
this.isAtBottom = false;
this.isAtTop = false;
this.timeout = false;
this.offsetBottom = obj.offsetBottom || 100;
// Set transitions.
if (supports3d) {
this.el.style.WebkitTransition = '-webkit-transform 200ms linear';
this.el.style.MozTransition = '-moz-transform 200ms linear';
this.el.style.MsTransition = '-ms-transform 200ms linear';
this.el.style.transition = 'transform 200ms linear';
}
document.addEventListener('scroll', this.onScroll.bind(this), false);
};
StickyBar.prototype.toDefault = function () {
this.isAtBottom = this.isAtTop = false;
this.isDefault = true;
this.animate(0);
};
StickyBar.prototype.holdOnTop = function (pos) {
this.isAtTop = true;
this.isDefault = this.isAtBottom = false;
this.animate(pos);
};
StickyBar.prototype.holdSteady = function () {
this.isDefault = this.isAtBottom = this.isAtTop = false;
};
StickyBar.prototype.holdOnBottom = function (pos) {
this.isAtBottom = true;
this.isDefault = this.isAtTop = false;
this.animate(pos);
};
StickyBar.prototype.animate = function (pos) {
if (supports3d) {
var t = 'translate3d(0,' + pos + 'px,0)';
this.el.style.WebkitTransform = t;
this.el.style.MozTransform = t;
this.el.style.MsTransform = t;
this.el.style.transform = t;
} else {
// TODO: Set right animation.
}
};
StickyBar.prototype.onScroll = _.debounce(function () {
var $el = this.$el,
windowH = _SF.prototype.windowH,
scrollPos = _SF.prototype.scrollTop,
barOffset = $el.offset().top,
barH = $el.height(),
dir = _SF.prototype.scrollDir;
// Parent is just as long as sidebar, so do nothing at all.
if (barH >= $el.parent().height()) {
if (!this.isDefault) {
this.toDefault();
}
}
// Scroll bar is @ top of page OR bar fits in screen completely
else if (!this.isDefault && scrollPos <= this.headerH || barH < (windowH - this.headerH - this.footerH)) {
this.toDefault();
}
// Bar is hanging @ bottom/top and user is scrolling up/down
else if ((dir === 'up' && this.isAtBottom) || (dir === 'down' && this.isAtTop)) {
this.holdSteady();
}
// User is scrolling THROUGH the content and the BOTTOM of the bar is reached
else if (dir === 'down' && (scrollPos + windowH) > (barOffset + barH)) {
this.holdOnBottom(scrollPos + windowH - barH - 340);
}
// User is scrolling THROUGH the content and the TOP of the bar is reached
else if (dir === 'up' && (scrollPos + this.headerH) <= barOffset) {
this.holdOnTop(scrollPos);
}
// memory cleanup.
$el = windowH = scrollPos = barOffset = barH = dir = null;
return false;
}, 100);
App.prototype.Components.StickyBar = StickyBar;
})(window, document, _SF, $, _);
@DutchKevv
Copy link
Author

Use like this:

var floatingBar = new App.Compontents.StickyBar ($('#sidebarContainer'));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment