sticky.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * Copyright © Magento, Inc. All rights reserved.
  3. * See COPYING.txt for license details.
  4. */
  5. define([
  6. 'jquery',
  7. 'jquery/ui'
  8. ], function ($) {
  9. 'use strict';
  10. $.widget('mage.sticky', {
  11. options: {
  12. /**
  13. * Element selector, who's height will be used to restrict the
  14. * maximum offsetTop position of the stuck element.
  15. * Default uses document body.
  16. * @type {String}
  17. */
  18. container: '',
  19. /**
  20. * Spacing in pixels above the stuck element
  21. * @type {Number|Function} Number or Function that will return a Number
  22. */
  23. spacingTop: 0,
  24. /**
  25. * Allows postponing sticking, until element will go out of the
  26. * screen for the number of pixels.
  27. * @type {Number|Function} Number or Function that will return a Number
  28. */
  29. stickAfter: 0,
  30. /**
  31. * CSS class for active sticky state
  32. * @type {String}
  33. */
  34. stickyClass: '_sticky'
  35. },
  36. /**
  37. * Retrieve option value
  38. * @param {String} option
  39. * @return {*}
  40. * @private
  41. */
  42. _getOptionValue: function (option) {
  43. var value = this.options[option] || 0;
  44. if (typeof value === 'function') {
  45. value = this.options[option]();
  46. }
  47. return value;
  48. },
  49. /**
  50. * Bind handlers to scroll event
  51. * @private
  52. */
  53. _create: function () {
  54. $(window).on({
  55. 'scroll': $.proxy(this._stick, this),
  56. 'resize': $.proxy(this.reset, this)
  57. });
  58. this.element.on('dimensionsChanged', $.proxy(this.reset, this));
  59. this.reset();
  60. },
  61. /**
  62. * float Block on windowScroll
  63. * @private
  64. */
  65. _stick: function () {
  66. var offset,
  67. isStatic,
  68. stuck,
  69. stickAfter;
  70. isStatic = this.element.css('position') === 'static';
  71. if (!isStatic && this.element.is(':visible')) {
  72. offset = $(document).scrollTop() -
  73. this.parentOffset +
  74. this._getOptionValue('spacingTop');
  75. offset = Math.max(0, Math.min(offset, this.maxOffset));
  76. stuck = this.element.hasClass(this.options.stickyClass);
  77. stickAfter = this._getOptionValue('stickAfter');
  78. if (offset && !stuck && offset < stickAfter) {
  79. offset = 0;
  80. }
  81. this.element
  82. .toggleClass(this.options.stickyClass, offset > 0)
  83. .css('top', offset);
  84. }
  85. },
  86. /**
  87. * Defines maximum offset value of the element.
  88. * @private
  89. */
  90. _calculateDimens: function () {
  91. var $parent = this.element.parent(),
  92. topMargin = parseInt(this.element.css('margin-top'), 10),
  93. parentHeight = $parent.height() - topMargin,
  94. height = this.element.innerHeight(),
  95. maxScroll = document.body.offsetHeight - window.innerHeight;
  96. if (this.options.container.length > 0) {
  97. maxScroll = $(this.options.container).height();
  98. }
  99. this.parentOffset = $parent.offset().top + topMargin;
  100. this.maxOffset = maxScroll - this.parentOffset;
  101. if (this.maxOffset + height >= parentHeight) {
  102. this.maxOffset = parentHeight - height;
  103. }
  104. return this;
  105. },
  106. /**
  107. * Facade method that palces sticky element where it should be.
  108. */
  109. reset: function () {
  110. this._calculateDimens()
  111. ._stick();
  112. }
  113. });
  114. return $.mage.sticky;
  115. });