aboutsummaryrefslogtreecommitdiff
path: root/src/directives/body_scroll_lock.js
blob: d7f114b59073626f3312a67ca78b92515bc9e09e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import * as bodyScrollLock from 'body-scroll-lock'

let previousNavPaddingRight
let previousAppBgWrapperRight
let lockerEls = []

const disableBodyScroll = (el) => {
  const scrollBarGap = window.innerWidth - document.documentElement.clientWidth
  bodyScrollLock.disableBodyScroll(el, {
    reserveScrollBarGap: true
  })
  if (!lockerEls.includes(el)) {
    lockerEls.push(el)
  }
  setTimeout(() => {
    if (lockerEls.length <= 1) {
      // If previousNavPaddingRight is already set, don't set it again.
      if (previousNavPaddingRight === undefined) {
        const navEl = document.getElementById('nav')
        previousNavPaddingRight = window.getComputedStyle(navEl).getPropertyValue('padding-right')
        navEl.style.paddingRight = previousNavPaddingRight ? `calc(${previousNavPaddingRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
      }
      // If previousAppBgWrapeprRight is already set, don't set it again.
      if (previousAppBgWrapperRight === undefined) {
        const appBgWrapperEl = document.getElementById('app_bg_wrapper')
        previousAppBgWrapperRight = window.getComputedStyle(appBgWrapperEl).getPropertyValue('right')
        appBgWrapperEl.style.right = previousAppBgWrapperRight ? `calc(${previousAppBgWrapperRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
      }
      document.body.classList.add('scroll-locked')
    }
  })
}

const enableBodyScroll = (el) => {
  if (lockerEls.includes(el)) {
    lockerEls = lockerEls.filter(e => e !== el)
  }
  setTimeout(() => {
    if (lockerEls.length === 0) {
      if (previousNavPaddingRight !== undefined) {
        document.getElementById('nav').style.paddingRight = previousNavPaddingRight
        // Restore previousNavPaddingRight to undefined so disableBodyScroll knows it can be set again.
        previousNavPaddingRight = undefined
      }
      if (previousAppBgWrapperRight !== undefined) {
        document.getElementById('app_bg_wrapper').style.right = previousAppBgWrapperRight
        // Restore previousAppBgWrapperRight to undefined so disableBodyScroll knows it can be set again.
        previousAppBgWrapperRight = undefined
      }
      document.body.classList.remove('scroll-locked')
    }
  })
  bodyScrollLock.enableBodyScroll(el)
}

const directive = {
  inserted: (el, binding) => {
    if (binding.value) {
      disableBodyScroll(el)
    }
  },
  componentUpdated: (el, binding) => {
    if (binding.oldValue === binding.value) {
      return
    }

    if (binding.value) {
      disableBodyScroll(el)
    } else {
      enableBodyScroll(el)
    }
  },
  unbind: (el) => {
    enableBodyScroll(el)
  }
}

export default (Vue) => {
  Vue.directive('body-scroll-lock', directive)
}