Last active
August 29, 2015 14:01
-
-
Save chriskoelle/a7498526b5255d11d714 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;(function($) { | |
$.fn.extend({ | |
stickyWidget: function(options) { | |
// Exit if there are no elements to avoid errors: | |
if (this.length === 0) { | |
return this; | |
} | |
var settings = $.extend({ | |
footer: '', // The page footer or any element that the sticky module should stop when it hits | |
minWidth: 980, // The minimum width to enable sticky - usually the width of the content area | |
threshold: 60, // An extra buffer added to the height when determining whether or not to enable | |
bufferTop: 0, // Distance from top of page element should stick (added to element bottom margin) | |
bufferBottom: 0 // Distance from footer to stop (added to element bottom margin) | |
}, options); | |
var sticky = { | |
el: $(this), | |
stickyLeft: 0, | |
stickyTop: 0, | |
stickyHeight: 0, | |
win: $(window), | |
footer: false, | |
threshold: settings.bufferTop + settings.threshold + settings.bufferBottom | |
}; | |
// Orginal positioning | |
var orig = { | |
mar: $(this).css('margin-left'), | |
left: $(this).css('left'), | |
top: $(this).css('top'), | |
pos: $(this).css('position') | |
} | |
var timer; | |
var stickyEnabled = true; | |
cacheElements(); | |
return this.each(function() { | |
buildSticky(); | |
}); | |
function buildSticky() { | |
sticky.win.bind({ | |
load: setupSticky, | |
sticky: setupSticky, | |
scroll: stick, | |
resize: function() { | |
clearTimeout(timer); | |
timer = window.setTimeout(enableSticky, 200); | |
} | |
}); | |
} | |
function setupSticky() { | |
var mid = sticky.win.width() / 2; | |
var widgetLeft = sticky.el.offset().left; | |
sticky.stickyLeft = widgetLeft - parseInt(mid, 10); | |
sticky.stickyTop = sticky.el.offset().top; | |
sticky.stickyHeight = sticky.el.outerHeight(true); | |
enableSticky(); | |
} | |
// Caches elements into jquery objects | |
function cacheElements() { | |
if(settings.footer !== '' && $(settings.footer).length !== 0){ | |
sticky.footer = $(settings.footer); | |
} | |
} | |
// Only enable the sticky module if it's not going to break anything | |
function enableSticky() { | |
var ft = sticky.footer ? sticky.footer.offset().top : $(document).height(); | |
var track = (ft - sticky.threshold) >= (sticky.stickyHeight + sticky.stickyTop) && | |
sticky.stickyHeight < sticky.win.height() && | |
sticky.win.width() >= settings.minWidth && | |
'ontouchstart' in window === false; | |
if( track ) { | |
stickyEnabled = true; | |
} else { | |
stickyEnabled = false; | |
} | |
calculateLimits(); | |
stick(); | |
} | |
// Calcualtes the limits top and bottom limits for the sidebar | |
function calculateLimits() { | |
sticky.stickyStart = sticky.stickyTop - settings.bufferTop; | |
if(sticky.footer) { | |
sticky.stickyStop = sticky.footer.offset().top - sticky.stickyHeight - settings.bufferTop - settings.bufferBottom; | |
} | |
} | |
// Sets widget to fixed position | |
function setFixedWidget() { | |
sticky.el.css({ | |
position: 'fixed', | |
top: settings.bufferTop, | |
left: '50%', | |
marginLeft: sticky.stickyLeft | |
}); | |
} | |
// sets widget to a static positioned element | |
function setStaticWidget() { | |
sticky.el.css({ | |
position: orig.pos, | |
marginLeft: orig.mar, | |
left: orig.left, | |
top: orig.top | |
}); | |
} | |
// initiated to stop the widget from intersecting the footer | |
function setLockedWidget(diff) { | |
sticky.el.css({ | |
top: diff | |
}); | |
} | |
//determines whether sidebar should stick and applies appropriate settings to make it stick | |
function stick() { | |
var windowTop = sticky.win.scrollTop(); | |
var hitBreakPoint = stickyEnabled && sticky.stickyStart < windowTop; | |
if (hitBreakPoint) { | |
setFixedWidget(); | |
} else { | |
setStaticWidget(); | |
} | |
if (sticky.footer && sticky.stickyStop < windowTop) { | |
var diff = sticky.stickyStop - windowTop + settings.bufferTop; | |
setLockedWidget(diff); | |
} | |
} | |
} | |
}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment