foundation.smoothScroll.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import $ from 'jquery';
  2. import { GetYoDigits } from './foundation.core.utils';
  3. import { Plugin } from './foundation.core.plugin';
  4. /**
  5. * SmoothScroll module.
  6. * @module foundation.smooth-scroll
  7. */
  8. class SmoothScroll extends Plugin {
  9. /**
  10. * Creates a new instance of SmoothScroll.
  11. * @class
  12. * @name SmoothScroll
  13. * @fires SmoothScroll#init
  14. * @param {Object} element - jQuery object to add the trigger to.
  15. * @param {Object} options - Overrides to the default plugin settings.
  16. */
  17. _setup(element, options) {
  18. this.$element = element;
  19. this.options = $.extend({}, SmoothScroll.defaults, this.$element.data(), options);
  20. this.className = 'SmoothScroll'; // ie9 back compat
  21. this._init();
  22. }
  23. /**
  24. * Initialize the SmoothScroll plugin
  25. * @private
  26. */
  27. _init() {
  28. const id = this.$element[0].id || GetYoDigits(6, 'smooth-scroll');
  29. this.$element.attr({ id });
  30. this._events();
  31. }
  32. /**
  33. * Initializes events for SmoothScroll.
  34. * @private
  35. */
  36. _events() {
  37. this._linkClickListener = this._handleLinkClick.bind(this);
  38. this.$element.on('click.zf.smoothScroll', this._linkClickListener);
  39. this.$element.on('click.zf.smoothScroll', 'a[href^="#"]', this._linkClickListener);
  40. }
  41. /**
  42. * Handle the given event to smoothly scroll to the anchor pointed by the event target.
  43. * @param {*} e - event
  44. * @function
  45. * @private
  46. */
  47. _handleLinkClick(e) {
  48. // Follow the link if it does not point to an anchor.
  49. if (!$(e.currentTarget).is('a[href^="#"]')) return;
  50. const arrival = e.currentTarget.getAttribute('href');
  51. this._inTransition = true;
  52. SmoothScroll.scrollToLoc(arrival, this.options, () => {
  53. this._inTransition = false;
  54. });
  55. e.preventDefault();
  56. };
  57. /**
  58. * Function to scroll to a given location on the page.
  59. * @param {String} loc - A properly formatted jQuery id selector. Example: '#foo'
  60. * @param {Object} options - The options to use.
  61. * @param {Function} callback - The callback function.
  62. * @static
  63. * @function
  64. */
  65. static scrollToLoc(loc, options = SmoothScroll.defaults, callback) {
  66. const $loc = $(loc);
  67. // Do nothing if target does not exist to prevent errors
  68. if (!$loc.length) return false;
  69. var scrollPos = Math.round($loc.offset().top - options.threshold / 2 - options.offset);
  70. $('html, body').stop(true).animate(
  71. { scrollTop: scrollPos },
  72. options.animationDuration,
  73. options.animationEasing,
  74. () => {
  75. if (typeof callback === 'function'){
  76. callback();
  77. }
  78. }
  79. );
  80. }
  81. /**
  82. * Destroys the SmoothScroll instance.
  83. * @function
  84. */
  85. _destroy() {
  86. this.$element.off('click.zf.smoothScroll', this._linkClickListener)
  87. this.$element.off('click.zf.smoothScroll', 'a[href^="#"]', this._linkClickListener);
  88. }
  89. }
  90. /**
  91. * Default settings for plugin.
  92. */
  93. SmoothScroll.defaults = {
  94. /**
  95. * Amount of time, in ms, the animated scrolling should take between locations.
  96. * @option
  97. * @type {number}
  98. * @default 500
  99. */
  100. animationDuration: 500,
  101. /**
  102. * Animation style to use when scrolling between locations. Can be `'swing'` or `'linear'`.
  103. * @option
  104. * @type {string}
  105. * @default 'linear'
  106. * @see {@link https://api.jquery.com/animate|Jquery animate}
  107. */
  108. animationEasing: 'linear',
  109. /**
  110. * Number of pixels to use as a marker for location changes.
  111. * @option
  112. * @type {number}
  113. * @default 50
  114. */
  115. threshold: 50,
  116. /**
  117. * Number of pixels to offset the scroll of the page on item click if using a sticky nav bar.
  118. * @option
  119. * @type {number}
  120. * @default 0
  121. */
  122. offset: 0
  123. }
  124. export {SmoothScroll}