// Stop scrolling at footer. // // This can be added to elements with `position: fixed` to stop them from // overflowing on the footer. // // Usage: // // GOVUK.stopScrollingAtFooter.addEl($(node), $(node).height()); // // Height is passed in separatly incase the scrolling element has no height // itself.

;(function (global) {

'use strict'

var $ = global.jQuery
var GOVUK = global.GOVUK || {}

var stopScrollingAtFooter = {
  _pollingId: null,
  _isPolling: false,
  _hasScrollEvt: false,
  _els: [],

  addEl: function ($fixedEl, height) {
    var fixedOffset

    if (!$fixedEl.length) { return }

    fixedOffset = parseInt($fixedEl.css('top'), 10)
    fixedOffset = isNaN(fixedOffset) ? 0 : fixedOffset

    stopScrollingAtFooter.updateFooterTop()
    $(global).on('govuk.pageSizeChanged', stopScrollingAtFooter.updateFooterTop)

    var $siblingEl = $('<div></div>')
    $siblingEl.insertBefore($fixedEl)
    var fixedTop = $siblingEl.offset().top - $siblingEl.position().top
    $siblingEl.remove()

    var el = {
      $fixedEl: $fixedEl,
      height: height + fixedOffset,
      fixedTop: height + fixedTop,
      state: 'fixed'
    }
    stopScrollingAtFooter._els.push(el)

    stopScrollingAtFooter.initTimeout()
  },
  updateFooterTop: function () {
    var footer = $('.js-footer:eq(0)')
    if (footer.length === 0) {
      return 0
    }
    stopScrollingAtFooter.footerTop = footer.offset().top - 10
  },
  initTimeout: function () {
    if (stopScrollingAtFooter._hasScrollEvt === false) {
      $(window).scroll(stopScrollingAtFooter.onScroll)
      stopScrollingAtFooter._hasScrollEvt = true
    }
  },
  onScroll: function () {
    if (stopScrollingAtFooter._isPolling === false) {
      stopScrollingAtFooter.startPolling()
    }
  },
  startPolling: (function () {
    if (window.requestAnimationFrame) {
      return function () {
        var callback = function () {
          stopScrollingAtFooter.checkScroll()
          if (stopScrollingAtFooter._isPolling === true) {
            stopScrollingAtFooter.startPolling()
          }
        }
        stopScrollingAtFooter._pollingId = window.requestAnimationFrame(callback)
        stopScrollingAtFooter._isPolling = true
      }
    } else {
      return function () {
        stopScrollingAtFooter._pollingId = window.setInterval(stopScrollingAtFooter.checkScroll, 16)
        stopScrollingAtFooter._isPolling = true
      }
    }
  }()),
  stopPolling: (function () {
    if (window.requestAnimationFrame) {
      return function () {
        window.cancelAnimationFrame(stopScrollingAtFooter._pollingId)
        stopScrollingAtFooter._isPolling = false
      }
    } else {
      return function () {
        window.clearInterval(stopScrollingAtFooter._pollingId)
        stopScrollingAtFooter._isPolling = false
      }
    }
  }()),
  checkScroll: function () {
    var cachedScrollTop = $(window).scrollTop()
    if ((cachedScrollTop < (stopScrollingAtFooter.cachedScrollTop + 2)) && (cachedScrollTop > (stopScrollingAtFooter.cachedScrollTop - 2))) {
      stopScrollingAtFooter.stopPolling()
      return
    } else {
      stopScrollingAtFooter.cachedScrollTop = cachedScrollTop
    }

    $.each(stopScrollingAtFooter._els, function (i, el) {
      var bottomOfEl = cachedScrollTop + el.height

      if (bottomOfEl > stopScrollingAtFooter.footerTop) {
        stopScrollingAtFooter.stick(el)
      } else {
        stopScrollingAtFooter.unstick(el)
      }
    })
  },
  stick: function (el) {
    if (el.state === 'fixed' && el.$fixedEl.css('position') === 'fixed') {
      el.$fixedEl.css({ 'position': 'absolute', 'top': stopScrollingAtFooter.footerTop - el.fixedTop })
      el.state = 'absolute'
    }
  },
  unstick: function (el) {
    if (el.state === 'absolute') {
      el.$fixedEl.css({ 'position': '', 'top': '' })
      el.state = 'fixed'
    }
  }
}

GOVUK.stopScrollingAtFooter = stopScrollingAtFooter

$(global).load(function () { $(global).trigger('govuk.pageSizeChanged') })

global.GOVUK = GOVUK

})(window)