Source: components/sticky-container/_sticky-container.js

'use strict';

/**
 * Sticky Containers component.
 * @namespace StickyContainers
 * @memberof UCASDesignFramework
 * @param {object} global - UCASDesignFramework object.
 * @param {object} _u - UCASUtilities object.
 */
(function (global, _u) {
  var clientWidth
  var stickyContainers
  var resizeTimeout
  var screenSize

  /**
   * @function init
   * @memberof! UCASDesignFramework.stickyContainers
   * @returns {Boolean} - true for success
   * @example
   * UCASDesignFramework.stickyContainers.init()
   */
  function init () {
    if (document.documentMode) { return false }
    stickyContainers = document.querySelectorAll('[data-sticky-clear]')
    screenSize = calculateScreenSize()
    if (stickyContainers.length === 0) {
      return false
    }
    renderStickyContainers(stickyContainers)
    window.addEventListener('dfScroll', renderOnScroll)
    window.addEventListener('resize', resizeThrottler, false)
    return true
  }

  /**
   * @function renderOnScroll
   * @memberof! UCASDesignFramework.stickyContainers
   * @private
   * Renders the StickyContainers every time dfScroll is called to ensure they maintain their spacing.
   */
  function renderOnScroll () {
    renderStickyContainers(stickyContainers)
  }

  /**
   * Slow down the resize handler so we don't repaint too much.
   * @TODO This can be generalised and put into _size.js
   */
  function resizeThrottler () {
    if (!resizeTimeout) {
      resizeTimeout = setTimeout(function () {
        resizeTimeout = null

        // Check width as triggering the keyboard on Android changes page size.
        // We're only interested if the width changes.
        if (clientWidth !== document.body.clientWidth) {
          clientWidth = document.body.clientWidth
          screenSize = calculateScreenSize()
          renderStickyContainers(stickyContainers)
        }
      }, 200)
    }
  }

  /**
   * Decide how to display the stickyContainers.
   * @return {string} - mobile|desktop
   */
  function calculateScreenSize () {
    return global.size.cssBreakpoint === 'xsmall' || global.size.cssBreakpoint === 'small' ? 'mobile' : 'desktop'
  }

  /**
   * @function renderStickyContainers
   * @memberof! UCASDesignFramework.stickyContainers
   * @param {Node} elements - data-sticky-clear node(s)
   * @private
   */
  function renderStickyContainers (elements) {
    elements.forEach(function (el) {
      var elementToClear = document.getElementById(el.getAttribute('data-sticky-clear'))
      if (elementToClear !== null) {
        el.style.top = Number(Number(elementToClear.offsetHeight) + Number(el.style.paddingTop) + 25) + 'px'
      }
    })

    Array.from(elements).reverse().forEach(function (el, index) {
      if (screenSize !== 'mobile') {
        el.style.zIndex = index
      }
    })
  }

  /**
   * Assumes the elements have been removed from the DOM.
   * @function destroy
   * @memberof! UCASDesignFramework.stickyContainers
   * @example
   * UCASDesignFramework.stickyContainers.destroy()
   */
  function destroy () {
    if (stickyContainers !== null) {
      stickyContainers = resizeTimeout = null
      window.removeEventListener('resize', resizeThrottler, false)
      window.removeEventListener('dfScroll', renderOnScroll)
    }
  }

  // Expose public methods and properties.
  global.stickyContainers = {
    addSubscriptions: true,
    init: init,
    destroy: destroy
  }
})(UCASDesignFramework, UCASUtilities)