Skip to content

Instantly share code, notes, and snippets.

@kirbysayshi
Created September 8, 2011 15:51
Show Gist options
  • Save kirbysayshi/1203741 to your computer and use it in GitHub Desktop.
Save kirbysayshi/1203741 to your computer and use it in GitHub Desktop.
jQuery sheepsheep: sticky scroll any element(s). Uses debounce, ported from underscore.
;(function($){
// Underscore.js 1.1.7
// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the MIT license.
// Portions of Underscore are inspired or borrowed from Prototype,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore
// $.throttle, $.debounce, taken from underscore.js
// https://github.com/documentcloud/underscore/blob/master/underscore.js
// Internal function used to implement `$.throttle` and `$.debounce`.
var limit = function(func, wait, debounce) {
var timeout;
return function() {
var context = this, args = arguments;
var throttler = function() {
timeout = null;
func.apply(context, args);
};
if (debounce) clearTimeout(timeout);
if (debounce || !timeout) timeout = setTimeout(throttler, wait);
};
};
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time.
$.throttle = function(func, wait) {
return limit(func, wait, false);
};
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds.
$.debounce = function(func, wait) {
return limit(func, wait, true);
};
})(jQuery)
;(function($){
// Makes all current elements stay in the viewport.
// the elements are like sheep, following you.
$.fn.sheepsheep = function(opts){
var $window = $(window)
,keys = {
wWidth: 'sheepsheep.wWidth'
,oOffset: 'sheepsheep.oOffset'
};
opts = $.extend({
speed: 300
,scrollInterval: 50
,resizeInterval: 333
,activeClass: 'sheep-sheep'
,targetTop: 10
}, opts);
function onResize(e){
var prevPos = this.css('position');
this.css('position', '')
this.each(function(i, el){
var $this = $(this);
$this.data(keys.oOffset, $this.offset())
})
this.css('position', prevPos);
$window.scroll();
}
function onScroll(e){
this.each(function(i, el){
var $this = $(this)
,scroll = $window.scrollTop()
,oOffset = $this.data(keys.oOffset)
|| $this.data(keys.oOffset, $this.offset())
,threshold = oOffset.top - opts.targetTop
,isActive = $this.hasClass(opts.activeClass)
if(isActive){
$this
.animate({
left: oOffset.left
}, {
duration: parseFloat($this.css('left'), 10) === oOffset.left
? 0
: opts.speed
})
}
if(scroll >= threshold && !isActive){
$this
.addClass(opts.activeClass)
.css({
position: 'fixed'
,left: oOffset.left
,top: -(scroll - threshold)
})
.animate({
top: opts.targetTop
}, {
duration: opts.speed
});
} else if(scroll < threshold && isActive) {
$this
.removeClass(opts.activeClass)
.animate({
top: oOffset.top - scroll
}, opts.speed, function(){
$this.css({ position: '', top: '', left: '' });
})
}
});
}
$window
.bind('scroll', $.debounce($.proxy(onScroll, this), opts.scrollInterval))
.bind('resize', $.debounce($.proxy(onResize, this), opts.resizeInterval))
.scroll();
}
})(jQuery)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment