Layout.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /**
  2. * --------------------------------------------
  3. * AdminLTE Layout.js
  4. * License MIT
  5. * --------------------------------------------
  6. */
  7. const Layout = (($) => {
  8. /**
  9. * Constants
  10. * ====================================================
  11. */
  12. const NAME = 'Layout'
  13. const DATA_KEY = 'lte.layout'
  14. const EVENT_KEY = `.${DATA_KEY}`
  15. const JQUERY_NO_CONFLICT = $.fn[NAME]
  16. const Event = {
  17. SIDEBAR: 'sidebar'
  18. }
  19. const Selector = {
  20. HEADER : '.main-header',
  21. MAIN_SIDEBAR : '.main-sidebar',
  22. SIDEBAR : '.main-sidebar .sidebar',
  23. CONTENT : '.content-wrapper',
  24. BRAND : '.brand-link',
  25. CONTENT_HEADER : '.content-header',
  26. WRAPPER : '.wrapper',
  27. CONTROL_SIDEBAR: '.control-sidebar',
  28. CONTROL_SIDEBAR_CONTENT: '.control-sidebar-content',
  29. CONTROL_SIDEBAR_BTN: '[data-widget="control-sidebar"]',
  30. LAYOUT_FIXED : '.layout-fixed',
  31. FOOTER : '.main-footer',
  32. PUSHMENU_BTN : '[data-widget="pushmenu"]',
  33. LOGIN_BOX : '.login-box',
  34. REGISTER_BOX : '.register-box'
  35. }
  36. const ClassName = {
  37. HOLD : 'hold-transition',
  38. SIDEBAR : 'main-sidebar',
  39. CONTENT_FIXED : 'content-fixed',
  40. SIDEBAR_FOCUSED: 'sidebar-focused',
  41. LAYOUT_FIXED : 'layout-fixed',
  42. NAVBAR_FIXED : 'layout-navbar-fixed',
  43. FOOTER_FIXED : 'layout-footer-fixed',
  44. LOGIN_PAGE : 'login-page',
  45. REGISTER_PAGE : 'register-page',
  46. CONTROL_SIDEBAR_SLIDE_OPEN: 'control-sidebar-slide-open',
  47. CONTROL_SIDEBAR_OPEN: 'control-sidebar-open',
  48. }
  49. const Default = {
  50. scrollbarTheme : 'os-theme-light',
  51. scrollbarAutoHide: 'l',
  52. panelAutoHeight: true,
  53. loginRegisterAutoHeight: true,
  54. }
  55. /**
  56. * Class Definition
  57. * ====================================================
  58. */
  59. class Layout {
  60. constructor(element, config) {
  61. this._config = config
  62. this._element = element
  63. this._init()
  64. }
  65. // Public
  66. fixLayoutHeight(extra = null) {
  67. let control_sidebar = 0
  68. if ($('body').hasClass(ClassName.CONTROL_SIDEBAR_SLIDE_OPEN) || $('body').hasClass(ClassName.CONTROL_SIDEBAR_OPEN) || extra == 'control_sidebar') {
  69. control_sidebar = $(Selector.CONTROL_SIDEBAR_CONTENT).height()
  70. }
  71. const heights = {
  72. window: $(window).height(),
  73. header: $(Selector.HEADER).length !== 0 ? $(Selector.HEADER).outerHeight() : 0,
  74. footer: $(Selector.FOOTER).length !== 0 ? $(Selector.FOOTER).outerHeight() : 0,
  75. sidebar: $(Selector.SIDEBAR).length !== 0 ? $(Selector.SIDEBAR).height() : 0,
  76. control_sidebar: control_sidebar,
  77. }
  78. const max = this._max(heights)
  79. let offset = this._config.panelAutoHeight
  80. if (offset === true) {
  81. offset = 0;
  82. }
  83. if (offset !== false) {
  84. if (max == heights.control_sidebar) {
  85. $(Selector.CONTENT).css('min-height', (max + offset))
  86. } else if (max == heights.window) {
  87. $(Selector.CONTENT).css('min-height', (max + offset) - heights.header - heights.footer)
  88. } else {
  89. $(Selector.CONTENT).css('min-height', (max + offset) - heights.header)
  90. }
  91. if (this._isFooterFixed()) {
  92. $(Selector.CONTENT).css('min-height', parseFloat($(Selector.CONTENT).css('min-height')) + heights.footer);
  93. }
  94. }
  95. if ($('body').hasClass(ClassName.LAYOUT_FIXED)) {
  96. if (offset !== false) {
  97. $(Selector.CONTENT).css('min-height', (max + offset) - heights.header - heights.footer)
  98. }
  99. if (typeof $.fn.overlayScrollbars !== 'undefined') {
  100. $(Selector.SIDEBAR).overlayScrollbars({
  101. className : this._config.scrollbarTheme,
  102. sizeAutoCapable : true,
  103. scrollbars : {
  104. autoHide: this._config.scrollbarAutoHide,
  105. clickScrolling : true
  106. }
  107. })
  108. }
  109. }
  110. }
  111. fixLoginRegisterHeight() {
  112. if ($(Selector.LOGIN_BOX + ', ' + Selector.REGISTER_BOX).length === 0) {
  113. $('body, html').css('height', 'auto')
  114. } else if ($(Selector.LOGIN_BOX + ', ' + Selector.REGISTER_BOX).length !== 0) {
  115. let box_height = $(Selector.LOGIN_BOX + ', ' + Selector.REGISTER_BOX).height()
  116. if ($('body').css('min-height') !== box_height) {
  117. $('body').css('min-height', box_height)
  118. }
  119. }
  120. }
  121. // Private
  122. _init() {
  123. // Activate layout height watcher
  124. this.fixLayoutHeight()
  125. if (this._config.loginRegisterAutoHeight === true) {
  126. this.fixLoginRegisterHeight()
  127. } else if (Number.isInteger(this._config.loginRegisterAutoHeight)) {
  128. setInterval(this.fixLoginRegisterHeight, this._config.loginRegisterAutoHeight);
  129. }
  130. $(Selector.SIDEBAR)
  131. .on('collapsed.lte.treeview expanded.lte.treeview', () => {
  132. this.fixLayoutHeight()
  133. })
  134. $(Selector.PUSHMENU_BTN)
  135. .on('collapsed.lte.pushmenu shown.lte.pushmenu', () => {
  136. this.fixLayoutHeight()
  137. })
  138. $(Selector.CONTROL_SIDEBAR_BTN)
  139. .on('collapsed.lte.controlsidebar', () => {
  140. this.fixLayoutHeight()
  141. })
  142. .on('expanded.lte.controlsidebar', () => {
  143. this.fixLayoutHeight('control_sidebar')
  144. })
  145. $(window).resize(() => {
  146. this.fixLayoutHeight()
  147. })
  148. setTimeout(() => {
  149. $('body.hold-transition').removeClass('hold-transition')
  150. }, 50);
  151. }
  152. _max(numbers) {
  153. // Calculate the maximum number in a list
  154. let max = 0
  155. Object.keys(numbers).forEach((key) => {
  156. if (numbers[key] > max) {
  157. max = numbers[key]
  158. }
  159. })
  160. return max
  161. }
  162. _isFooterFixed() {
  163. return $('.main-footer').css('position') === 'fixed';
  164. }
  165. // Static
  166. static _jQueryInterface(config = '') {
  167. return this.each(function () {
  168. let data = $(this).data(DATA_KEY)
  169. const _options = $.extend({}, Default, $(this).data())
  170. if (!data) {
  171. data = new Layout($(this), _options)
  172. $(this).data(DATA_KEY, data)
  173. }
  174. if (config === 'init' || config === '') {
  175. data['_init']()
  176. } else if (config === 'fixLayoutHeight' || config === 'fixLoginRegisterHeight') {
  177. data[config]()
  178. }
  179. })
  180. }
  181. }
  182. /**
  183. * Data API
  184. * ====================================================
  185. */
  186. $(window).on('load', () => {
  187. Layout._jQueryInterface.call($('body'))
  188. })
  189. $(Selector.SIDEBAR + ' a').on('focusin', () => {
  190. $(Selector.MAIN_SIDEBAR).addClass(ClassName.SIDEBAR_FOCUSED);
  191. })
  192. $(Selector.SIDEBAR + ' a').on('focusout', () => {
  193. $(Selector.MAIN_SIDEBAR).removeClass(ClassName.SIDEBAR_FOCUSED);
  194. })
  195. /**
  196. * jQuery API
  197. * ====================================================
  198. */
  199. $.fn[NAME] = Layout._jQueryInterface
  200. $.fn[NAME].Constructor = Layout
  201. $.fn[NAME].noConflict = function () {
  202. $.fn[NAME] = JQUERY_NO_CONFLICT
  203. return Layout._jQueryInterface
  204. }
  205. return Layout
  206. })(jQuery)
  207. export default Layout