]> BookStack Code Mirror - bookstack/blob - resources/js/components/tri-layout.js
f801e52a193715fdea427fa4eac03c2372ca9abf
[bookstack] / resources / js / components / tri-layout.js
1
2 class TriLayout {
3
4     setup() {
5         this.container = this.$refs.container;
6         this.tabs = this.$manyRefs.tab;
7
8         this.lastLayoutType = 'none';
9         this.onDestroy = null;
10         this.scrollCache = {
11             'content': 0,
12             'info': 0,
13         };
14         this.lastTabShown = 'content';
15
16         // Bind any listeners
17         this.mobileTabClick = this.mobileTabClick.bind(this);
18
19         // Watch layout changes
20         this.updateLayout();
21         window.addEventListener('resize', event => {
22             this.updateLayout();
23         }, {passive: true});
24     }
25
26     updateLayout() {
27         let newLayout = 'tablet';
28         if (window.innerWidth <= 1000) newLayout =  'mobile';
29         if (window.innerWidth >= 1400) newLayout =  'desktop';
30         if (newLayout === this.lastLayoutType) return;
31
32         if (this.onDestroy) {
33             this.onDestroy();
34             this.onDestroy = null;
35         }
36
37         if (newLayout === 'desktop') {
38             this.setupDesktop();
39         } else if (newLayout === 'mobile') {
40             this.setupMobile();
41         }
42
43         this.lastLayoutType = newLayout;
44     }
45
46     setupMobile() {
47         for (const tab of this.tabs) {
48             tab.addEventListener('click', this.mobileTabClick);
49         }
50
51         this.onDestroy = () => {
52             for (const tab of this.tabs) {
53                 tab.removeEventListener('click', this.mobileTabClick);
54             }
55         }
56     }
57
58     setupDesktop() {
59         //
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.tab;
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 }
112
113 export default TriLayout;