Source: components/spinners/_spinners.js

'use strict';

/**
 * Spinners component.
 * @namespace spinners
 * @memberof UCASDesignFramework
 * @param {object} global - UCASDesignFramework object.
 * @param {object} _u - UCASUtilities object.
 */
(function (global, _u) {
  var defaultId
  var position

  /**
   * Initialise plugin.
   * @function init
   * @memberof! UCASDesignFramework.spinners
   * @public
   */
  function init () {
    global.subscriptions = global.subscriptions || {}
    global.subscriptions.df = global.subscriptions.df || {}

    defaultId = document.body.classList.contains('v5') ? 'content' : 'section--content'

    if (global.bus) {
      global.subscriptions.df.spinnerActivate = global.bus.subscribe('df.spinner.activate', activate)
      global.subscriptions.df.spinnerDeactivate = global.bus.subscribe('df.spinner.deactivate', deactivate)
      global.subscriptions.df.spinnerActivateAfterDelay = global.bus.subscribe('df.spinner.activateAfterDelay', activateAfterDelay)
    }
  }

  /**
   * Activate spinner.
   * @function activate
   * @memberof! UCASDesignFramework.spinners
   * @param {string} [id="section--content"] - the ID of the element to attach a spinner to, defaults to the main content area of the page
   */
  function activate (id) {
    id = id || defaultId
    toggle(id, true) ? global.bus.publish('df.spinner.isActivated', id) : global.bus.publish('df.spinner.error', id)
  }

  /**
   * Activate spinner after delay of 500ms.
   * @function activateAfterDelay
   * @memberof! UCASDesignFramework.spinners
   * @param {string} [id="section--content"] - the ID of the element to attach a spinner to, defaults to the main content area of the page
   */
  function activateAfterDelay (id) {
    id = id || defaultId
    var element = document.getElementById(id)
    if (element) {
      element.setAttribute('data-spinner-delay', '')

      setTimeout(function () {
        if (element.hasAttribute('data-spinner-delay')) {
          toggle(id, true) ? global.bus.publish('df.spinner.isActivated', id) : global.bus.publish('df.spinner.error', id)
        }
      }, 500, element, id)
    } else {
      global.bus.publish('df.spinner.error', id)
    }
  }

  /**
   * Deactivate spinner.
   * @function deactivate
   * @memberof! UCASDesignFramework.spinners
   * @param {string} [id="section--content"] - the ID of the element with spinner attached, defaults to the main content area of the page
   */
  function deactivate (id) {
    id = id || defaultId
    toggle(id, false) ? global.bus.publish('df.spinner.isDeactivated', id) : global.bus.publish('df.spinner.error', id)
  }

  /**
   * Toggle spinner.
   * @function toggle
   * @private
   * @param {string} id - the ID of the element
   * @param {bool} state - true to activate the spinner, false to deactivate
   * @returns {bool} - true if successful
   */
  function toggle (id, state) {
    var success = false
    var element = document.getElementById(id)
    if (element && id === defaultId) { prepareSectionContent(element) }
    if (element && element.classList.contains('spinner')) {
      if (state) { savePosition() }
      element.removeAttribute('data-spinner-delay')
      element.setAttribute('aria-busy', state)
      document.documentElement.setAttribute('data-content-busy', state)
      if (!state) { restorePosition() }
      success = true
    } else {
      _u.log.warn('No element with id ' + id + ' with class spinner.')
    }
    return success
  }

  /**
   * Make sure the main content has the appropriate classes.
   * @function prepareSectionContent
   * @private
   * @param {Node} sectionContent - the element with id section--content.
   */
  function prepareSectionContent (sectionContent) {
    sectionContent.classList.add('spinner')
    sectionContent.classList.add('spinner--full-page')
  }

  /**
   * Save the page position.
   * @function savePosition
   * @private
   */
  function savePosition () {
    position = window.pageYOffset
    document.querySelector('.page-wrapper, #wrapper').style.top = -position + 'px'
    document.querySelector('.page-wrapper, #wrapper').style.height = 'calc(100vh + ' + position + 'px)'
  }

  /**
   * Restore the page position.
   * @function restorePosition
   * @private
   */
  function restorePosition () {
    window.scrollTo(0, position)
    document.querySelector('.page-wrapper, #wrapper').style.top = null
    document.querySelector('.page-wrapper, #wrapper').style.height = null
  }

  // Expose public methods.
  global.spinners = {
    init: init,
    /**
     * @memberof! UCASDesignFramework.spinners
     * @property {Boolean} initOnLoad - run init() on page load
     */
    initOnLoad: true,
    activate: activate,
    deactivate: deactivate,
    activateAfterDelay: activateAfterDelay
  }
})(UCASDesignFramework, UCASUtilities)