diff options
author | Mike Greiling <mike@pixelcog.com> | 2016-09-02 01:33:43 -0500 |
---|---|---|
committer | Mike Greiling <mike@pixelcog.com> | 2016-09-07 14:02:21 -0500 |
commit | b2f8ebbb4295e5f070187050e094db87ff9d6ad0 (patch) | |
tree | b743850b7043d4585bcca6a5e126c5519ecc4f19 /app/assets/javascripts/sidebar.js.es6 | |
parent | 6690fc70478b4d82c49689e9e13e414bc77bb271 (diff) | |
download | gitlab-ce-b2f8ebbb4295e5f070187050e094db87ff9d6ad0.tar.gz |
refactor sidebar logic into singleton class
Diffstat (limited to 'app/assets/javascripts/sidebar.js.es6')
-rw-r--r-- | app/assets/javascripts/sidebar.js.es6 | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/app/assets/javascripts/sidebar.js.es6 b/app/assets/javascripts/sidebar.js.es6 new file mode 100644 index 00000000000..737f343ed0d --- /dev/null +++ b/app/assets/javascripts/sidebar.js.es6 @@ -0,0 +1,98 @@ +((global) => { + let singleton; + + const pinnedStateCookie = 'pin_nav'; + const sidebarBreakpoint = 1024; + + const pageSelector = '.page-with-sidebar'; + const navbarSelector = '.navbar-fixed-top'; + const sidebarWrapperSelector = '.sidebar-wrapper'; + const sidebarContentSelector = '.nav-sidebar'; + + const pinnedToggleSelector = '.js-nav-pin'; + const sidebarToggleSelector = '.toggle-nav-collapse, .side-nav-toggle'; + + const pinnedPageClass = 'page-sidebar-pinned'; + const expandedPageClass = 'page-sidebar-expanded'; + const collapsedPageClass = 'page-sidebar-collapsed'; + + const pinnedNavbarClass = 'header-pinned-nav'; + const expandedNavbarClass = 'header-expanded'; + const collapsedNavbarClass = 'header-collapsed'; + + class Sidebar { + constructor() { + if (!singleton) { + singleton = this; + singleton.init(); + } else { + singleton.renderState(); + } + return singleton; + } + + init() { + this.isPinned = $.cookie(pinnedStateCookie) === 'true'; + this.isExpanded = ( + window.innerWidth >= sidebarBreakpoint && + $(pageSelector).hasClass(expandedPageClass) + ); + $(document) + .on('click', sidebarToggleSelector, () => this.toggleSidebar()) + .on('click', pinnedToggleSelector, () => this.togglePinnedState()) + .on('click', 'html, body', (e) => this.handleClickEvent(e)); + this.renderState(); + } + + handleClickEvent(e) { + if (this.isExpanded && (!this.isPinned || window.innerWidth < sidebarBreakpoint)) { + const $target = $(e.target); + const targetIsToggle = $target.closest(sidebarToggleSelector).length > 0; + const targetIsSidebar = $target.closest(sidebarWrapperSelector).length > 0; + if (!targetIsToggle && (!targetIsSidebar || $target.closest('a'))) { + this.toggleSidebar(); + } + } + } + + toggleSidebar() { + this.isExpanded = !this.isExpanded; + this.renderState(); + } + + togglePinnedState() { + this.isPinned = !this.isPinned; + if (!this.isPinned) { + this.isExpanded = false; + } + $.cookie(pinnedStateCookie, this.isPinned ? 'true' : 'false', { + path: gon.relative_url_root || '/', + expires: 3650 + }); + this.renderState(); + } + + renderState() { + $(pageSelector) + .toggleClass(pinnedPageClass, this.isPinned && this.isExpanded) + .toggleClass(expandedPageClass, this.isExpanded) + .toggleClass(collapsedPageClass, !this.isExpanded); + $(navbarSelector) + .toggleClass(pinnedNavbarClass, this.isPinned && this.isExpanded) + .toggleClass(expandedNavbarClass, this.isExpanded) + .toggleClass(collapsedNavbarClass, !this.isExpanded); + + const $pinnedToggle = $(pinnedToggleSelector); + const tooltipText = this.isPinned ? 'Unpin navigation' : 'Pin navigation'; + const tooltipState = $pinnedToggle.attr('aria-describedby') && this.isExpanded ? 'show' : 'hide'; + $pinnedToggle.attr('title', tooltipText).tooltip('fixTitle').tooltip(tooltipState); + + if (this.isExpanded) { + setTimeout(() => $(sidebarContentSelector).niceScroll().updateScrollBar(), 200); + } + } + } + + global.Sidebar = Sidebar; + +})(window.gl || (window.gl = {})); |