push-menu.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /**
  2. * --------------------------------------------
  3. * @file AdminLTE push-menu.ts
  4. * @description Push menu for AdminLTE.
  5. * @license MIT
  6. * --------------------------------------------
  7. */
  8. import {
  9. onDOMContentLoaded
  10. } from './util/index'
  11. /**
  12. * ------------------------------------------------------------------------
  13. * Constants
  14. * ------------------------------------------------------------------------
  15. */
  16. const DATA_KEY = 'lte.push-menu'
  17. const EVENT_KEY = `.${DATA_KEY}`
  18. const EVENT_OPEN = `open${EVENT_KEY}`
  19. const EVENT_COLLAPSE = `collapse${EVENT_KEY}`
  20. const CLASS_NAME_SIDEBAR_MINI = 'sidebar-mini'
  21. const CLASS_NAME_SIDEBAR_COLLAPSE = 'sidebar-collapse'
  22. const CLASS_NAME_SIDEBAR_OPEN = 'sidebar-open'
  23. const CLASS_NAME_SIDEBAR_EXPAND = 'sidebar-expand'
  24. const CLASS_NAME_SIDEBAR_OVERLAY = 'sidebar-overlay'
  25. const CLASS_NAME_MENU_OPEN = 'menu-open'
  26. const SELECTOR_APP_SIDEBAR = '.app-sidebar'
  27. const SELECTOR_SIDEBAR_MENU = '.sidebar-menu'
  28. const SELECTOR_NAV_ITEM = '.nav-item'
  29. const SELECTOR_NAV_TREEVIEW = '.nav-treeview'
  30. const SELECTOR_APP_WRAPPER = '.app-wrapper'
  31. const SELECTOR_SIDEBAR_EXPAND = `[class*="${CLASS_NAME_SIDEBAR_EXPAND}"]`
  32. const SELECTOR_SIDEBAR_TOGGLE = '[data-lte-toggle="sidebar"]'
  33. type Config = {
  34. sidebarBreakpoint: number;
  35. }
  36. const Defaults = {
  37. sidebarBreakpoint: 992
  38. }
  39. /**
  40. * Class Definition
  41. * ====================================================
  42. */
  43. class PushMenu {
  44. _element: HTMLElement
  45. _config: Config
  46. constructor(element: HTMLElement, config: Config) {
  47. this._element = element
  48. this._config = { ...Defaults, ...config }
  49. }
  50. // TODO
  51. menusClose() {
  52. const navTreeview = document.querySelectorAll<HTMLElement>(SELECTOR_NAV_TREEVIEW)
  53. navTreeview.forEach(navTree => {
  54. navTree.style.removeProperty('display')
  55. navTree.style.removeProperty('height')
  56. })
  57. const navSidebar = document.querySelector(SELECTOR_SIDEBAR_MENU)
  58. const navItem = navSidebar?.querySelectorAll(SELECTOR_NAV_ITEM)
  59. if (navItem) {
  60. navItem.forEach(navI => {
  61. navI.classList.remove(CLASS_NAME_MENU_OPEN)
  62. })
  63. }
  64. }
  65. expand() {
  66. const event = new Event(EVENT_OPEN)
  67. document.body.classList.remove(CLASS_NAME_SIDEBAR_COLLAPSE)
  68. document.body.classList.add(CLASS_NAME_SIDEBAR_OPEN)
  69. this._element.dispatchEvent(event)
  70. }
  71. collapse() {
  72. const event = new Event(EVENT_COLLAPSE)
  73. document.body.classList.remove(CLASS_NAME_SIDEBAR_OPEN)
  74. document.body.classList.add(CLASS_NAME_SIDEBAR_COLLAPSE)
  75. this._element.dispatchEvent(event)
  76. }
  77. addSidebarBreakPoint() {
  78. const sidebarExpandList = document.querySelector(SELECTOR_SIDEBAR_EXPAND)?.classList ?? []
  79. const sidebarExpand = Array.from(sidebarExpandList).find(className => className.startsWith(CLASS_NAME_SIDEBAR_EXPAND)) ?? ''
  80. const sidebar = document.getElementsByClassName(sidebarExpand)[0]
  81. const sidebarContent = window.getComputedStyle(sidebar, '::before').getPropertyValue('content')
  82. this._config = { ...this._config, sidebarBreakpoint: Number(sidebarContent.replace(/[^\d.-]/g, '')) }
  83. if (window.innerWidth <= this._config.sidebarBreakpoint) {
  84. this.collapse()
  85. } else {
  86. if (!document.body.classList.contains(CLASS_NAME_SIDEBAR_MINI)) {
  87. this.expand()
  88. }
  89. if (document.body.classList.contains(CLASS_NAME_SIDEBAR_MINI) && document.body.classList.contains(CLASS_NAME_SIDEBAR_COLLAPSE)) {
  90. this.collapse()
  91. }
  92. }
  93. }
  94. toggle() {
  95. if (document.body.classList.contains(CLASS_NAME_SIDEBAR_COLLAPSE)) {
  96. this.expand()
  97. } else {
  98. this.collapse()
  99. }
  100. }
  101. init() {
  102. this.addSidebarBreakPoint()
  103. }
  104. }
  105. /**
  106. * ------------------------------------------------------------------------
  107. * Data Api implementation
  108. * ------------------------------------------------------------------------
  109. */
  110. onDOMContentLoaded(() => {
  111. const sidebar = document?.querySelector(SELECTOR_APP_SIDEBAR) as HTMLElement | undefined
  112. if (sidebar) {
  113. const data = new PushMenu(sidebar, Defaults)
  114. data.init()
  115. window.addEventListener('resize', () => {
  116. data.init()
  117. })
  118. }
  119. const sidebarOverlay = document.createElement('div')
  120. sidebarOverlay.className = CLASS_NAME_SIDEBAR_OVERLAY
  121. document.querySelector(SELECTOR_APP_WRAPPER)?.append(sidebarOverlay)
  122. sidebarOverlay.addEventListener('touchstart', event => {
  123. event.preventDefault()
  124. const target = event.currentTarget as HTMLElement
  125. const data = new PushMenu(target, Defaults)
  126. data.collapse()
  127. }, { passive: true })
  128. sidebarOverlay.addEventListener('click', event => {
  129. event.preventDefault()
  130. const target = event.currentTarget as HTMLElement
  131. const data = new PushMenu(target, Defaults)
  132. data.collapse()
  133. })
  134. const fullBtn = document.querySelectorAll(SELECTOR_SIDEBAR_TOGGLE)
  135. fullBtn.forEach(btn => {
  136. btn.addEventListener('click', event => {
  137. event.preventDefault()
  138. let button = event.currentTarget as HTMLElement | undefined
  139. if (button?.dataset.lteToggle !== 'sidebar') {
  140. button = button?.closest(SELECTOR_SIDEBAR_TOGGLE) as HTMLElement | undefined
  141. }
  142. if (button) {
  143. event?.preventDefault()
  144. const data = new PushMenu(button, Defaults)
  145. data.toggle()
  146. }
  147. })
  148. })
  149. })
  150. export default PushMenu