您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

ControlSidebar.js 10KB

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