jquery-stickem
Version:
Packaging the great jquery-stickem code into an NPM module so people can find it with Yarn
180 lines (144 loc) • 4.56 kB
JavaScript
/**
* @name jQuery Stick 'em
* @author Trevor Davis
* @version 1.4.1
*
* $('.container').stickem({
* item: '.stickem',
* container: '.stickem-container',
* stickClass: 'stickit',
* endStickClass: 'stickit-end',
* offset: 0,
* onStick: null,
* onUnstick: null
* });
*/
;(function($, window, document, undefined) {
var Stickem = function(elem, options) {
this.elem = elem;
this.$elem = $(elem);
this.options = options;
this.metadata = this.$elem.data("stickem-options");
this.$win = $(window);
};
Stickem.prototype = {
defaults: {
item: '.stickem',
container: '.stickem-container',
stickClass: 'stickit',
endStickClass: 'stickit-end',
offset: 0,
start: 0,
onStick: null,
onUnstick: null
},
init: function() {
var _self = this;
//Merge options
_self.config = $.extend({}, _self.defaults, _self.options, _self.metadata);
_self.setWindowHeight();
_self.getItems();
_self.bindEvents();
return _self;
},
bindEvents: function() {
var _self = this;
_self.$win.on('scroll.stickem', $.proxy(_self.handleScroll, _self));
_self.$win.on('resize.stickem', $.proxy(_self.handleResize, _self));
},
destroy: function() {
var _self = this;
_self.$win.off('scroll.stickem');
_self.$win.off('resize.stickem');
},
getItem: function(index, element) {
var _self = this;
var $this = $(element);
var item = {
$elem: $this,
elemHeight: $this.height(),
$container: $this.parents(_self.config.container),
isStuck: false
};
//If the element is smaller than the window
if(_self.windowHeight > item.elemHeight) {
item.containerHeight = item.$container.outerHeight();
item.containerInner = {
border: {
bottom: parseInt(item.$container.css('border-bottom'), 10) || 0,
top: parseInt(item.$container.css('border-top'), 10) || 0
},
padding: {
bottom: parseInt(item.$container.css('padding-bottom'), 10) || 0,
top: parseInt(item.$container.css('padding-top'), 10) || 0
}
};
item.containerInnerHeight = item.$container.height();
item.containerStart = item.$container.offset().top - _self.config.offset + _self.config.start + item.containerInner.padding.top + item.containerInner.border.top;
item.scrollFinish = item.containerStart - _self.config.start + (item.containerInnerHeight - item.elemHeight);
//If the element is smaller than the container
if(item.containerInnerHeight > item.elemHeight) {
_self.items.push(item);
}
} else {
item.$elem.removeClass(_self.config.stickClass + ' ' + _self.config.endStickClass);
}
},
getItems: function() {
var _self = this;
_self.items = [];
_self.$elem.find(_self.config.item).each($.proxy(_self.getItem, _self));
},
handleResize: function() {
var _self = this;
_self.getItems();
_self.setWindowHeight();
},
handleScroll: function() {
var _self = this;
if(_self.items.length > 0) {
var pos = _self.$win.scrollTop();
for(var i = 0, len = _self.items.length; i < len; i++) {
var item = _self.items[i];
//If it's stuck, and we need to unstick it, or if the page loads below it
if((item.isStuck && (pos < item.containerStart || pos > item.scrollFinish)) || pos > item.scrollFinish) {
item.$elem.removeClass(_self.config.stickClass);
//only at the bottom
if(pos > item.scrollFinish) {
item.$elem.addClass(_self.config.endStickClass);
}
item.isStuck = false;
//if supplied fire the onUnstick callback
if(_self.config.onUnstick) {
_self.config.onUnstick(item);
}
//If we need to stick it
} else if(item.isStuck === false && pos > item.containerStart && pos < item.scrollFinish) {
item.$elem.removeClass(_self.config.endStickClass).addClass(_self.config.stickClass);
item.isStuck = true;
//if supplied fire the onStick callback
if(_self.config.onStick) {
_self.config.onStick(item);
}
}
}
}
},
setWindowHeight: function() {
var _self = this;
_self.windowHeight = _self.$win.height() - _self.config.offset;
}
};
Stickem.defaults = Stickem.prototype.defaults;
$.fn.stickem = function(options) {
//Create a destroy method so that you can kill it and call it again.
this.destroy = function() {
this.each(function() {
new Stickem(this, options).destroy();
});
};
return this.each(function() {
new Stickem(this, options).init();
});
};
})(jQuery, window , document);