@coreui/coreui-pro
Version:
UI Kit built on top of Bootstrap 4
305 lines (256 loc) • 9.01 kB
JavaScript
import $ from 'jquery'
import PerfectScrollbar from 'perfect-scrollbar'
import getStyle from './utilities/get-style'
import toggleClasses from './toggle-classes'
/**
* --------------------------------------------------------------------------
* CoreUI (v2.1.14): sidebar.js
* Licensed under MIT (https://coreui.io/license)
* --------------------------------------------------------------------------
*/
const Sidebar = (($) => {
/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/
const NAME = 'sidebar'
const VERSION = '2.1.14'
const DATA_KEY = 'coreui.sidebar'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const JQUERY_NO_CONFLICT = $.fn[NAME]
const Default = {
transition : 400
}
const ClassName = {
ACTIVE : 'active',
BRAND_MINIMIZED : 'brand-minimized',
NAV_DROPDOWN_TOGGLE : 'nav-dropdown-toggle',
OPEN : 'open',
SIDEBAR_FIXED : 'sidebar-fixed',
SIDEBAR_MINIMIZED : 'sidebar-minimized',
SIDEBAR_OFF_CANVAS : 'sidebar-off-canvas'
}
const Event = {
CLICK : 'click',
DESTROY : 'destroy',
INIT : 'init',
LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,
TOGGLE : 'toggle',
UPDATE : 'update'
}
const Selector = {
BODY : 'body',
BRAND_MINIMIZER : '.brand-minimizer',
NAV_DROPDOWN_TOGGLE : '.nav-dropdown-toggle',
NAV_DROPDOWN_ITEMS : '.nav-dropdown-items',
NAV_ITEM : '.nav-item',
NAV_LINK : '.nav-link',
NAV_LINK_QUERIED : '.nav-link-queried',
NAVIGATION_CONTAINER : '.sidebar-nav',
NAVIGATION : '.sidebar-nav > .nav',
SIDEBAR : '.sidebar',
SIDEBAR_MINIMIZER : '.sidebar-minimizer',
SIDEBAR_TOGGLER : '.sidebar-toggler',
SIDEBAR_SCROLL : '.sidebar-scroll'
}
const ShowClassNames = [
'sidebar-show',
'sidebar-sm-show',
'sidebar-md-show',
'sidebar-lg-show',
'sidebar-xl-show'
]
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
class Sidebar {
constructor(element) {
this._element = element
this.mobile = false
this.ps = null
this.perfectScrollbar(Event.INIT)
this.setActiveLink()
this._breakpointTest = this._breakpointTest.bind(this)
this._clickOutListener = this._clickOutListener.bind(this)
this._addEventListeners()
this._addMediaQuery()
}
// Getters
static get VERSION() {
return VERSION
}
// Public
perfectScrollbar(event) {
if (typeof PerfectScrollbar !== 'undefined') {
const classList = document.body.classList
if (event === Event.INIT && !classList.contains(ClassName.SIDEBAR_MINIMIZED)) {
this.ps = this.makeScrollbar()
}
if (event === Event.DESTROY) {
this.destroyScrollbar()
}
if (event === Event.TOGGLE) {
if (classList.contains(ClassName.SIDEBAR_MINIMIZED)) {
this.destroyScrollbar()
} else {
this.destroyScrollbar()
this.ps = this.makeScrollbar()
}
}
if (event === Event.UPDATE && !classList.contains(ClassName.SIDEBAR_MINIMIZED)) {
// ToDo: Add smooth transition
setTimeout(() => {
this.destroyScrollbar()
this.ps = this.makeScrollbar()
}, Default.transition)
}
}
}
makeScrollbar() {
let container = Selector.SIDEBAR_SCROLL
if (document.querySelector(container) === null) {
container = Selector.NAVIGATION_CONTAINER
if (document.querySelector(container) === null) {
return null
}
}
const ps = new PerfectScrollbar(document.querySelector(container), {
suppressScrollX: true
})
// ToDo: find real fix for ps rtl
ps.isRtl = false
return ps
}
destroyScrollbar() {
if (this.ps) {
this.ps.destroy()
this.ps = null
}
}
setActiveLink() {
$(Selector.NAVIGATION).find(Selector.NAV_LINK).each((key, value) => {
let link = value
let cUrl
if (link.classList.contains(Selector.NAV_LINK_QUERIED)) {
cUrl = String(window.location)
} else {
cUrl = String(window.location).split('?')[0]
}
if (cUrl.substr(cUrl.length - 1) === '#') {
cUrl = cUrl.slice(0, -1)
}
if ($($(link))[0].href === cUrl) {
$(link).addClass(ClassName.ACTIVE).parents(Selector.NAV_DROPDOWN_ITEMS).add(link).each((key, value) => {
link = value
$(link).parent().addClass(ClassName.OPEN)
})
}
})
}
// Private
_addMediaQuery() {
const sm = getStyle('--breakpoint-sm')
if (!sm) {
return
}
const smVal = parseInt(sm, 10) - 1
const mediaQueryList = window.matchMedia(`(max-width: ${smVal}px)`)
this._breakpointTest(mediaQueryList)
mediaQueryList.addListener(this._breakpointTest)
}
_breakpointTest(e) {
this.mobile = Boolean(e.matches)
this._toggleClickOut()
}
_clickOutListener(event) {
if (!this._element.contains(event.target)) { // or use: event.target.closest(Selector.SIDEBAR) === null
event.preventDefault()
event.stopPropagation()
this._removeClickOut()
document.body.classList.remove('sidebar-show')
}
}
_addClickOut() {
document.addEventListener(Event.CLICK, this._clickOutListener, true)
}
_removeClickOut() {
document.removeEventListener(Event.CLICK, this._clickOutListener, true)
}
_toggleClickOut() {
if (this.mobile && document.body.classList.contains('sidebar-show')) {
document.body.classList.remove('aside-menu-show')
this._addClickOut()
} else {
this._removeClickOut()
}
}
_addEventListeners() {
$(document).on(Event.CLICK, Selector.BRAND_MINIMIZER, (event) => {
event.preventDefault()
event.stopPropagation()
$(Selector.BODY).toggleClass(ClassName.BRAND_MINIMIZED)
})
$(document).on(Event.CLICK, Selector.NAV_DROPDOWN_TOGGLE, (event) => {
event.preventDefault()
event.stopPropagation()
const dropdown = event.target
$(dropdown).parent().toggleClass(ClassName.OPEN)
this.perfectScrollbar(Event.UPDATE)
})
$(document).on(Event.CLICK, Selector.SIDEBAR_MINIMIZER, (event) => {
event.preventDefault()
event.stopPropagation()
$(Selector.BODY).toggleClass(ClassName.SIDEBAR_MINIMIZED)
this.perfectScrollbar(Event.TOGGLE)
})
$(document).on(Event.CLICK, Selector.SIDEBAR_TOGGLER, (event) => {
event.preventDefault()
event.stopPropagation()
const toggle = event.currentTarget.dataset ? event.currentTarget.dataset.toggle : $(event.currentTarget).data('toggle')
toggleClasses(toggle, ShowClassNames)
this._toggleClickOut()
})
$(`${Selector.NAVIGATION} > ${Selector.NAV_ITEM} ${Selector.NAV_LINK}:not(${Selector.NAV_DROPDOWN_TOGGLE})`).on(Event.CLICK, () => {
this._removeClickOut()
document.body.classList.remove('sidebar-show')
})
}
// Static
static _jQueryInterface() {
return this.each(function () {
const $element = $(this)
let data = $element.data(DATA_KEY)
if (!data) {
data = new Sidebar(this)
$element.data(DATA_KEY, data)
}
})
}
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(window).on(Event.LOAD_DATA_API, () => {
const sidebar = $(Selector.SIDEBAR)
Sidebar._jQueryInterface.call(sidebar)
})
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/
$.fn[NAME] = Sidebar._jQueryInterface
$.fn[NAME].Constructor = Sidebar
$.fn[NAME].noConflict = () => {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Sidebar._jQueryInterface
}
return Sidebar
})($)
export default Sidebar