123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /*jslint browser:true */
- /*global jQuery*/
-
- (function ($, window, undefined) {
- 'use strict';
-
- var pluginName = 'stickySidebar',
- document = window.document,
- defaults = {
- sidebar: '.sidebar',
- content: '.content',
- tolerance: -25
- },
- clearPosition = {
- position: '',
- top: ''
- };
-
- function Plugin(element, options) {
- this.options = $.extend({}, defaults, options);
-
- this.defaults = defaults;
- this.name = pluginName;
-
- this.root = $(element);
-
- this.init();
- }
-
- Plugin.prototype.init = function () {
- var self = this;
-
- this.sidebar = this.root.find(this.options.sidebar);
- this.content = this.root.find(this.options.content);
- this.lastScrollTop = 0;
-
- if (this.canBeSticky() === true) {
- $(window).bind('scroll.sticky_sidebar', function () {
- self.setScrollDirection()
- .setBoundaries()
- .positionSidebar();
- });
- }
- };
-
- Plugin.prototype.canBeSticky = function () {
- return this.sidebar.height() < this.content.height() &&
- this.sidebar.height() > $(window).height();
- };
-
- Plugin.prototype.setBoundaries = function () {
- var contentTop = this.content.offset().top,
- contentHeight = this.content.outerHeight();
- this.boundaries = {
- contentTop: contentTop,
- contentBottom: contentTop + contentHeight,
- contentHeight: contentHeight,
- sidebarHeight: this.sidebar.outerHeight(),
- windowHeight: $(window).height()
- };
- return this;
- };
-
- Plugin.prototype.positionSidebar = function () {
- if (this.lastScrollTop > this.boundaries.contentTop &&
- this.lastScrollTop < this.boundaries.contentBottom) {
- this[this.scrollDirection === 'DOWN' ? 'scrollDown' : 'scrollUp']();
- } else if (this.lastScrollTop < this.boundaries.contentTop) {
- this.sidebar.css('top', '').removeClass('top-fixed');
- }
- return this;
- };
-
- Plugin.prototype.scrollDown = function () {
- var windowScroll = this.lastScrollTop + this.boundaries.windowHeight,
- sidebarOffsetTop;
- if (this.sidebar.hasClass('scrolling-up')) {
- this.sidebar.removeClass('scrolling-up')
- .addClass('scrolling-down');
- } else if (this.sidebar.hasClass('top-fixed')) {
- sidebarOffsetTop = this.sidebar.offset().top - this.boundaries.contentTop;
- this.sidebar.removeClass('top-fixed')
- .css({
- position: 'absolute',
- top: sidebarOffsetTop
- })
- .addClass('scrolling-down');
- }
- if (this.sidebar.hasClass('scrolling-down')) {
- if (windowScroll > this.sidebar.offset().top + this.boundaries.sidebarHeight) {
- this.sidebar.css(clearPosition)
- .addClass('bottom-fixed')
- .removeClass('scrolling-down');
- }
- } else {
- if (windowScroll > this.boundaries.contentBottom) {
- this.sidebar.removeClass('bottom-fixed').css({
- position: 'absolute',
- top: this.boundaries.contentHeight - this.boundaries.sidebarHeight
- });
- } else if (windowScroll + this.options.tolerance >
- this.boundaries.sidebarHeight + this.boundaries.contentTop) {
- this.sidebar.css(clearPosition)
- .removeClass('top-fixed')
- .addClass('bottom-fixed');
- }
- }
- };
-
- Plugin.prototype.scrollUp = function () {
- if (this.sidebar.hasClass('scrolling-down')) {
- this.sidebar.removeClass('scrolling-down')
- .addClass('scrolling-up');
- } else if (this.sidebar.hasClass('bottom-fixed')) {
- this.sidebar.css({
- position: 'absolute',
- top: this.sidebar.offset().top - this.boundaries.contentTop
- }).removeClass('bottom-fixed').addClass('scrolling-up');
- }
- if (this.sidebar.hasClass('scrolling-up')) {
- if (this.lastScrollTop < this.sidebar.offset().top) {
- this.sidebar.css(clearPosition)
- .addClass('top-fixed')
- .removeClass('scrolling-up');
- }
- } else {
- if (this.lastScrollTop < this.boundaries.contentTop) {
- this.sidebar.css('position', '').removeClass('top-fixed');
- } else if (this.lastScrollTop - this.options.tolerance <
- this.boundaries.contentBottom - this.boundaries.sidebarHeight) {
- this.sidebar.css(clearPosition)
- .removeClass('bottom-fixed')
- .addClass('top-fixed');
- }
- }
- };
-
- Plugin.prototype.setScrollDirection = function () {
- var scrollTop = $(window).scrollTop();
- this.scrollDirection = (scrollTop > this.lastScrollTop ? 'DOWN' : 'UP');
- this.lastScrollTop = scrollTop;
- return this;
- };
-
- $.fn[pluginName] = function (options) {
- return this.each(function () {
- if (!$.data(this, 'plugin_' + pluginName)) {
- $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
- }
- });
- };
-
- }(jQuery, window));
|