X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/3286f29a61833327b5701b28db626d0a480b07f9..refs/pull/1561/head:/resources/assets/js/components/tri-layout.js diff --git a/resources/assets/js/components/tri-layout.js b/resources/assets/js/components/tri-layout.js index d18d37d60..905ca03b1 100644 --- a/resources/assets/js/components/tri-layout.js +++ b/resources/assets/js/components/tri-layout.js @@ -3,18 +3,23 @@ class TriLayout { constructor(elem) { this.elem = elem; - this.middle = elem.querySelector('.tri-layout-middle'); - this.right = elem.querySelector('.tri-layout-right'); - this.left = elem.querySelector('.tri-layout-left'); this.lastLayoutType = 'none'; this.onDestroy = null; + this.scrollCache = { + 'content': 0, + 'info': 0, + }; + this.lastTabShown = 'content'; + // Bind any listeners + this.mobileTabClick = this.mobileTabClick.bind(this); + // Watch layout changes this.updateLayout(); window.addEventListener('resize', event => { this.updateLayout(); - }); + }, {passive: true}); } updateLayout() { @@ -38,16 +43,15 @@ class TriLayout { } setupMobile() { - const mobileSidebarClickBound = this.mobileSidebarClick.bind(this); - const mobileContentClickBound = this.mobileContentClick.bind(this); - this.left.addEventListener('click', mobileSidebarClickBound); - this.right.addEventListener('click', mobileSidebarClickBound); - this.middle.addEventListener('click', mobileContentClickBound); + const layoutTabs = document.querySelectorAll('[tri-layout-mobile-tab]'); + for (let tab of layoutTabs) { + tab.addEventListener('click', this.mobileTabClick); + } this.onDestroy = () => { - this.left.removeEventListener('click', mobileSidebarClickBound); - this.right.removeEventListener('click', mobileSidebarClickBound); - this.middle.removeEventListener('click', mobileContentClickBound); + for (let tab of layoutTabs) { + tab.removeEventListener('click', this.mobileTabClick); + } } } @@ -55,27 +59,53 @@ class TriLayout { // } + /** - * Slide the main content back into view if clicked and - * currently slid out of view. + * Action to run when the mobile info toggle bar is clicked/tapped * @param event */ - mobileContentClick(event) { - this.elem.classList.remove('mobile-open'); + mobileTabClick(event) { + const tab = event.target.getAttribute('tri-layout-mobile-tab'); + this.showTab(tab); } /** - * On sidebar click, Show the content by sliding the main content out. - * @param event + * Show the content tab. + * Used by the page-display component. + */ + showContent() { + this.showTab('content', false); + } + + /** + * Show the given tab + * @param tabName */ - mobileSidebarClick(event) { - if (this.elem.classList.contains('mobile-open')) { - this.elem.classList.remove('mobile-open'); - } else { - event.preventDefault(); - event.stopPropagation(); - this.elem.classList.add('mobile-open'); + showTab(tabName, scroll = true) { + this.scrollCache[this.lastTabShown] = document.documentElement.scrollTop; + + // Set tab status + const tabs = document.querySelectorAll('.tri-layout-mobile-tab'); + for (let tab of tabs) { + const isActive = (tab.getAttribute('tri-layout-mobile-tab') === tabName); + tab.classList.toggle('active', isActive); } + + // Toggle section + const showInfo = (tabName === 'info'); + this.elem.classList.toggle('show-info', showInfo); + + // Set the scroll position from cache + if (scroll) { + const pageHeader = document.querySelector('header'); + const defaultScrollTop = pageHeader.getBoundingClientRect().bottom; + document.documentElement.scrollTop = this.scrollCache[tabName] || defaultScrollTop; + setTimeout(() => { + document.documentElement.scrollTop = this.scrollCache[tabName] || defaultScrollTop; + }, 50); + } + + this.lastTabShown = tabName; } }