ControlSidebar.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /**
  2. * --------------------------------------------
  3. * AdminLTE ControlSidebar.js
  4. * License MIT
  5. * --------------------------------------------
  6. */
  7. const ControlSidebar = ($ => {
  8. /**
  9. * Constants
  10. * ====================================================
  11. */
  12. const NAME = 'ControlSidebar'
  13. const DATA_KEY = 'lte.controlsidebar'
  14. const EVENT_KEY = `.${DATA_KEY}`
  15. const JQUERY_NO_CONFLICT = $.fn[NAME]
  16. const Event = {
  17. COLLAPSED: `collapsed${EVENT_KEY}`,
  18. EXPANDED: `expanded${EVENT_KEY}`
  19. }
  20. const Selector = {
  21. CONTROL_SIDEBAR: '.control-sidebar',
  22. CONTROL_SIDEBAR_CONTENT: '.control-sidebar-content',
  23. DATA_TOGGLE: '[data-widget="control-sidebar"]',
  24. HEADER: '.main-header',
  25. FOOTER: '.main-footer'
  26. }
  27. const ClassName = {
  28. CONTROL_SIDEBAR_ANIMATE: 'control-sidebar-animate',
  29. CONTROL_SIDEBAR_OPEN: 'control-sidebar-open',
  30. CONTROL_SIDEBAR_SLIDE: 'control-sidebar-slide-open',
  31. LAYOUT_FIXED: 'layout-fixed',
  32. NAVBAR_FIXED: 'layout-navbar-fixed',
  33. NAVBAR_SM_FIXED: 'layout-sm-navbar-fixed',
  34. NAVBAR_MD_FIXED: 'layout-md-navbar-fixed',
  35. NAVBAR_LG_FIXED: 'layout-lg-navbar-fixed',
  36. NAVBAR_XL_FIXED: 'layout-xl-navbar-fixed',
  37. FOOTER_FIXED: 'layout-footer-fixed',
  38. FOOTER_SM_FIXED: 'layout-sm-footer-fixed',
  39. FOOTER_MD_FIXED: 'layout-md-footer-fixed',
  40. FOOTER_LG_FIXED: 'layout-lg-footer-fixed',
  41. FOOTER_XL_FIXED: 'layout-xl-footer-fixed'
  42. }
  43. const Default = {
  44. controlsidebarSlide: true,
  45. scrollbarTheme: 'os-theme-light',
  46. scrollbarAutoHide: 'l'
  47. }
  48. /**
  49. * Class Definition
  50. * ====================================================
  51. */
  52. class ControlSidebar {
  53. constructor(element, config) {
  54. this._element = element
  55. this._config = config
  56. this._init()
  57. }
  58. // Public
  59. collapse() {
  60. // Show the control sidebar
  61. if (this._config.controlsidebarSlide) {
  62. $('html').addClass(ClassName.CONTROL_SIDEBAR_ANIMATE)
  63. $('body').removeClass(ClassName.CONTROL_SIDEBAR_SLIDE).delay(300).queue(function () {
  64. $(Selector.CONTROL_SIDEBAR).hide()
  65. $('html').removeClass(ClassName.CONTROL_SIDEBAR_ANIMATE)
  66. $(this).dequeue()
  67. })
  68. } else {
  69. $('body').removeClass(ClassName.CONTROL_SIDEBAR_OPEN)
  70. }
  71. const collapsedEvent = $.Event(Event.COLLAPSED)
  72. $(this._element).trigger(collapsedEvent)
  73. }
  74. show() {
  75. // Collapse the control sidebar
  76. if (this._config.controlsidebarSlide) {
  77. $('html').addClass(ClassName.CONTROL_SIDEBAR_ANIMATE)
  78. $(Selector.CONTROL_SIDEBAR).show().delay(10).queue(function () {
  79. $('body').addClass(ClassName.CONTROL_SIDEBAR_SLIDE).delay(300).queue(function () {
  80. $('html').removeClass(ClassName.CONTROL_SIDEBAR_ANIMATE)
  81. $(this).dequeue()
  82. })
  83. $(this).dequeue()
  84. })
  85. } else {
  86. $('body').addClass(ClassName.CONTROL_SIDEBAR_OPEN)
  87. }
  88. const expandedEvent = $.Event(Event.EXPANDED)
  89. $(this._element).trigger(expandedEvent)
  90. }
  91. toggle() {
  92. const shouldClose = $('body').hasClass(ClassName.CONTROL_SIDEBAR_OPEN) || $('body')
  93. .hasClass(ClassName.CONTROL_SIDEBAR_SLIDE)
  94. if (shouldClose) {
  95. // Close the control sidebar
  96. this.collapse()
  97. } else {
  98. // Open the control sidebar
  99. this.show()
  100. }
  101. }
  102. // Private
  103. _init() {
  104. this._fixHeight()
  105. this._fixScrollHeight()
  106. $(window).resize(() => {
  107. this._fixHeight()
  108. this._fixScrollHeight()
  109. })
  110. $(window).scroll(() => {
  111. if ($('body').hasClass(ClassName.CONTROL_SIDEBAR_OPEN) || $('body').hasClass(ClassName.CONTROL_SIDEBAR_SLIDE)) {
  112. this._fixScrollHeight()
  113. }
  114. })
  115. }
  116. _fixScrollHeight() {
  117. if (!$('body').hasClass(ClassName.LAYOUT_FIXED)) {
  118. return
  119. }
  120. const heights = {
  121. scroll: $(document).height(),
  122. window: $(window).height(),
  123. header: $(Selector.HEADER).outerHeight(),
  124. footer: $(Selector.FOOTER).outerHeight()
  125. }
  126. const positions = {
  127. bottom: Math.abs((heights.window + $(window).scrollTop()) - heights.scroll),
  128. top: $(window).scrollTop()
  129. }
  130. let navbarFixed = false
  131. let footerFixed = false
  132. if (
  133. $('body').hasClass(ClassName.NAVBAR_FIXED) ||
  134. $('body').hasClass(ClassName.NAVBAR_SM_FIXED) ||
  135. $('body').hasClass(ClassName.NAVBAR_MD_FIXED) ||
  136. $('body').hasClass(ClassName.NAVBAR_LG_FIXED) ||
  137. $('body').hasClass(ClassName.NAVBAR_XL_FIXED)
  138. ) {
  139. if ($(Selector.HEADER).css('position') === 'fixed') {
  140. navbarFixed = true
  141. }
  142. }
  143. if (
  144. $('body').hasClass(ClassName.FOOTER_FIXED) ||
  145. $('body').hasClass(ClassName.FOOTER_SM_FIXED) ||
  146. $('body').hasClass(ClassName.FOOTER_MD_FIXED) ||
  147. $('body').hasClass(ClassName.FOOTER_LG_FIXED) ||
  148. $('body').hasClass(ClassName.FOOTER_XL_FIXED)
  149. ) {
  150. if ($(Selector.FOOTER).css('position') === 'fixed') {
  151. footerFixed = true
  152. }
  153. }
  154. if (positions.top === 0 && positions.bottom === 0) {
  155. $(Selector.CONTROL_SIDEBAR).css('bottom', heights.footer)
  156. $(Selector.CONTROL_SIDEBAR).css('top', heights.header)
  157. $(Selector.CONTROL_SIDEBAR + ', ' + Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', heights.window - (heights.header + heights.footer))
  158. } else if (positions.bottom <= heights.footer) {
  159. if (footerFixed === false) {
  160. $(Selector.CONTROL_SIDEBAR).css('bottom', heights.footer - positions.bottom)
  161. $(Selector.CONTROL_SIDEBAR + ', ' + Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', heights.window - (heights.footer - positions.bottom))
  162. } else {
  163. $(Selector.CONTROL_SIDEBAR).css('bottom', heights.footer)
  164. }
  165. } else if (positions.top <= heights.header) {
  166. if (navbarFixed === false) {
  167. $(Selector.CONTROL_SIDEBAR).css('top', heights.header - positions.top)
  168. $(Selector.CONTROL_SIDEBAR + ', ' + Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', heights.window - (heights.header - positions.top))
  169. } else {
  170. $(Selector.CONTROL_SIDEBAR).css('top', heights.header)
  171. }
  172. } else if (navbarFixed === false) {
  173. $(Selector.CONTROL_SIDEBAR).css('top', 0)
  174. $(Selector.CONTROL_SIDEBAR + ', ' + Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', heights.window)
  175. } else {
  176. $(Selector.CONTROL_SIDEBAR).css('top', heights.header)
  177. }
  178. }
  179. _fixHeight() {
  180. if (!$('body').hasClass(ClassName.LAYOUT_FIXED)) {
  181. return
  182. }
  183. const heights = {
  184. window: $(window).height(),
  185. header: $(Selector.HEADER).outerHeight(),
  186. footer: $(Selector.FOOTER).outerHeight()
  187. }
  188. let sidebarHeight = heights.window - heights.header
  189. if (
  190. $('body').hasClass(ClassName.FOOTER_FIXED) ||
  191. $('body').hasClass(ClassName.FOOTER_SM_FIXED) ||
  192. $('body').hasClass(ClassName.FOOTER_MD_FIXED) ||
  193. $('body').hasClass(ClassName.FOOTER_LG_FIXED) ||
  194. $('body').hasClass(ClassName.FOOTER_XL_FIXED)
  195. ) {
  196. if ($(Selector.FOOTER).css('position') === 'fixed') {
  197. sidebarHeight = heights.window - heights.header - heights.footer
  198. }
  199. }
  200. $(Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', sidebarHeight)
  201. if (typeof $.fn.overlayScrollbars !== 'undefined') {
  202. $(Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).overlayScrollbars({
  203. className: this._config.scrollbarTheme,
  204. sizeAutoCapable: true,
  205. scrollbars: {
  206. autoHide: this._config.scrollbarAutoHide,
  207. clickScrolling: true
  208. }
  209. })
  210. }
  211. }
  212. // Static
  213. static _jQueryInterface(operation) {
  214. return this.each(function () {
  215. let data = $(this).data(DATA_KEY)
  216. const _options = $.extend({}, Default, $(this).data())
  217. if (!data) {
  218. data = new ControlSidebar(this, _options)
  219. $(this).data(DATA_KEY, data)
  220. }
  221. if (data[operation] === 'undefined') {
  222. throw new Error(`${operation} is not a function`)
  223. }
  224. data[operation]()
  225. })
  226. }
  227. }
  228. /**
  229. *
  230. * Data Api implementation
  231. * ====================================================
  232. */
  233. $(document).on('click', Selector.DATA_TOGGLE, function (event) {
  234. event.preventDefault()
  235. ControlSidebar._jQueryInterface.call($(this), 'toggle')
  236. })
  237. /**
  238. * jQuery API
  239. * ====================================================
  240. */
  241. $.fn[NAME] = ControlSidebar._jQueryInterface
  242. $.fn[NAME].Constructor = ControlSidebar
  243. $.fn[NAME].noConflict = function () {
  244. $.fn[NAME] = JQUERY_NO_CONFLICT
  245. return ControlSidebar._jQueryInterface
  246. }
  247. return ControlSidebar
  248. })(jQuery)
  249. export default ControlSidebar