1ae784e_jquery.stickysidebar_9.js 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*jslint browser:true */
  2. /*global jQuery*/
  3. (function ($, window, undefined) {
  4. 'use strict';
  5. var pluginName = 'stickySidebar',
  6. document = window.document,
  7. defaults = {
  8. sidebar: '.sidebar',
  9. content: '.content',
  10. tolerance: -25
  11. },
  12. clearPosition = {
  13. position: '',
  14. top: ''
  15. };
  16. function Plugin(element, options) {
  17. this.options = $.extend({}, defaults, options);
  18. this.defaults = defaults;
  19. this.name = pluginName;
  20. this.root = $(element);
  21. this.init();
  22. }
  23. Plugin.prototype.init = function () {
  24. var self = this;
  25. this.sidebar = this.root.find(this.options.sidebar);
  26. this.content = this.root.find(this.options.content);
  27. this.lastScrollTop = 0;
  28. if (this.canBeSticky() === true) {
  29. $(window).bind('scroll.sticky_sidebar', function () {
  30. self.setScrollDirection()
  31. .setBoundaries()
  32. .positionSidebar();
  33. });
  34. }
  35. };
  36. Plugin.prototype.canBeSticky = function () {
  37. return this.sidebar.height() < this.content.height() &&
  38. this.sidebar.height() > $(window).height();
  39. };
  40. Plugin.prototype.setBoundaries = function () {
  41. var contentTop = this.content.offset().top,
  42. contentHeight = this.content.outerHeight();
  43. this.boundaries = {
  44. contentTop: contentTop,
  45. contentBottom: contentTop + contentHeight,
  46. contentHeight: contentHeight,
  47. sidebarHeight: this.sidebar.outerHeight(),
  48. windowHeight: $(window).height()
  49. };
  50. return this;
  51. };
  52. Plugin.prototype.positionSidebar = function () {
  53. if (this.lastScrollTop > this.boundaries.contentTop &&
  54. this.lastScrollTop < this.boundaries.contentBottom) {
  55. this[this.scrollDirection === 'DOWN' ? 'scrollDown' : 'scrollUp']();
  56. } else if (this.lastScrollTop < this.boundaries.contentTop) {
  57. this.sidebar.css('top', '').removeClass('top-fixed');
  58. }
  59. return this;
  60. };
  61. Plugin.prototype.scrollDown = function () {
  62. var windowScroll = this.lastScrollTop + this.boundaries.windowHeight,
  63. sidebarOffsetTop;
  64. if (this.sidebar.hasClass('scrolling-up')) {
  65. this.sidebar.removeClass('scrolling-up')
  66. .addClass('scrolling-down');
  67. } else if (this.sidebar.hasClass('top-fixed')) {
  68. sidebarOffsetTop = this.sidebar.offset().top - this.boundaries.contentTop;
  69. this.sidebar.removeClass('top-fixed')
  70. .css({
  71. position: 'absolute',
  72. top: sidebarOffsetTop
  73. })
  74. .addClass('scrolling-down');
  75. }
  76. if (this.sidebar.hasClass('scrolling-down')) {
  77. if (windowScroll > this.sidebar.offset().top + this.boundaries.sidebarHeight) {
  78. this.sidebar.css(clearPosition)
  79. .addClass('bottom-fixed')
  80. .removeClass('scrolling-down');
  81. }
  82. } else {
  83. if (windowScroll > this.boundaries.contentBottom) {
  84. this.sidebar.removeClass('bottom-fixed').css({
  85. position: 'absolute',
  86. top: this.boundaries.contentHeight - this.boundaries.sidebarHeight
  87. });
  88. } else if (windowScroll + this.options.tolerance >
  89. this.boundaries.sidebarHeight + this.boundaries.contentTop) {
  90. this.sidebar.css(clearPosition)
  91. .removeClass('top-fixed')
  92. .addClass('bottom-fixed');
  93. }
  94. }
  95. };
  96. Plugin.prototype.scrollUp = function () {
  97. if (this.sidebar.hasClass('scrolling-down')) {
  98. this.sidebar.removeClass('scrolling-down')
  99. .addClass('scrolling-up');
  100. } else if (this.sidebar.hasClass('bottom-fixed')) {
  101. this.sidebar.css({
  102. position: 'absolute',
  103. top: this.sidebar.offset().top - this.boundaries.contentTop
  104. }).removeClass('bottom-fixed').addClass('scrolling-up');
  105. }
  106. if (this.sidebar.hasClass('scrolling-up')) {
  107. if (this.lastScrollTop < this.sidebar.offset().top) {
  108. this.sidebar.css(clearPosition)
  109. .addClass('top-fixed')
  110. .removeClass('scrolling-up');
  111. }
  112. } else {
  113. if (this.lastScrollTop < this.boundaries.contentTop) {
  114. this.sidebar.css('position', '').removeClass('top-fixed');
  115. } else if (this.lastScrollTop - this.options.tolerance <
  116. this.boundaries.contentBottom - this.boundaries.sidebarHeight) {
  117. this.sidebar.css(clearPosition)
  118. .removeClass('bottom-fixed')
  119. .addClass('top-fixed');
  120. }
  121. }
  122. };
  123. Plugin.prototype.setScrollDirection = function () {
  124. var scrollTop = $(window).scrollTop();
  125. this.scrollDirection = (scrollTop > this.lastScrollTop ? 'DOWN' : 'UP');
  126. this.lastScrollTop = scrollTop;
  127. return this;
  128. };
  129. $.fn[pluginName] = function (options) {
  130. return this.each(function () {
  131. if (!$.data(this, 'plugin_' + pluginName)) {
  132. $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
  133. }
  134. });
  135. };
  136. }(jQuery, window));