]> BookStack Code Mirror - bookstack/blob - resources/js/components/tri-layout.js
8ccefb06c482b09da5c7c0d4103f3d8307b8ee12
[bookstack] / resources / js / components / tri-layout.js
1 import {Component} from './component';
2
3 export class TriLayout extends Component {
4
5     setup() {
6         this.container = this.$refs.container;
7         this.tabs = this.$manyRefs.tab;
8
9         this.lastLayoutType = 'none';
10         this.onDestroy = null;
11         this.scrollCache = {
12             content: 0,
13             info: 0,
14         };
15         this.lastTabShown = 'content';
16
17         // Bind any listeners
18         this.mobileTabClick = this.mobileTabClick.bind(this);
19
20         // Watch layout changes
21         this.updateLayout();
22         window.addEventListener('resize', () => {
23             this.updateLayout();
24         }, {passive: true});
25     }
26
27     updateLayout() {
28         let newLayout = 'tablet';
29         if (window.innerWidth <= 1000) newLayout = 'mobile';
30         if (window.innerWidth >= 1400) newLayout = 'desktop';
31         if (newLayout === this.lastLayoutType) return;
32
33         if (this.onDestroy) {
34             this.onDestroy();
35             this.onDestroy = null;
36         }
37
38         if (newLayout === 'desktop') {
39             this.setupDesktop();
40         } else if (newLayout === 'mobile') {
41             this.setupMobile();
42         }
43
44         this.lastLayoutType = newLayout;
45     }
46
47     setupMobile() {
48         for (const tab of this.tabs) {
49             tab.addEventListener('click', this.mobileTabClick);
50         }
51
52         this.onDestroy = () => {
53             for (const tab of this.tabs) {
54                 tab.removeEventListener('click', this.mobileTabClick);
55             }
56         };
57     }
58
59     setupDesktop() {
60         //
61     }
62
63     /**
64      * Action to run when the mobile info toggle bar is clicked/tapped
65      * @param event
66      */
67     mobileTabClick(event) {
68         const {tab} = event.target.dataset;
69         this.showTab(tab);
70     }
71
72     /**
73      * Show the content tab.
74      * Used by the page-display component.
75      */
76     showContent() {
77         this.showTab('content', false);
78     }
79
80     /**
81      * Show the given tab
82      * @param {String} tabName
83      * @param {Boolean }scroll
84      */
85     showTab(tabName, scroll = true) {
86         this.scrollCache[this.lastTabShown] = document.documentElement.scrollTop;
87
88         // Set tab status
89         for (const tab of this.tabs) {
90             const isActive = (tab.dataset.tab === tabName);
91             tab.setAttribute('aria-selected', isActive ? 'true' : 'false');
92         }
93
94         // Toggle section
95         const showInfo = (tabName === 'info');
96         this.container.classList.toggle('show-info', showInfo);
97
98         // Set the scroll position from cache
99         if (scroll) {
100             const pageHeader = document.querySelector('header');
101             const defaultScrollTop = pageHeader.getBoundingClientRect().bottom;
102             document.documentElement.scrollTop = this.scrollCache[tabName] || defaultScrollTop;
103             setTimeout(() => {
104                 document.documentElement.scrollTop = this.scrollCache[tabName] || defaultScrollTop;
105             }, 50);
106         }
107
108         this.lastTabShown = tabName;
109     }
110
111 }