1/*  DokuWiki MoaiEditor Layout_desktop.js file
2    Author  : MoaiTools <info@moaitools.org>
3    License : GPL 3 (http://www.gnu.org/licenses/gpl.html) */
4
5/*  Desktop layout class
6    ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
7    This class handles the desktop layout.
8
9    Layout
10    ‾‾‾‾‾‾
11    body                            --
12      #moaied__wrapper              -- Semitransparent overlay
13        #moaied__tplsidebar         -- Container for editor (and optionally the template sidebar as well)
14        #moaied__editor             -- Container for the editor itself
15
16       ┌─ #moaied__wrapper           ┌─ #moaied__editor
17       │                             │
18    ┌──┴──┏━━━━━━┓─┏━━━━━━━━━━━━━━━━━━┴━━━━━━┓─────┐
19    │/ / /┃      ┃/┃                         ┃/ / /│
20    │/ / /┃      ┃/┃                         ┃/ / /│
21    │/ / /┃      ┃/┃                         ┃/ / /│
22    │/ / /┃      ┃/┃                         ┃/ / /│
23    │/ / /┃      ┃/┃                         ┃/ / /│
24    │/ / /┃      ┃/┃                         ┃/ / /│
25    │/ / /┃      ┃/┃                         ┃/ / /│
26    │/ / /┃      ┃/┃                         ┃/ / /│
27    │/ / /┃      ┃/┃                         ┃/ / /│
28    │/ / /┃      ┃/┃                         ┃/ / /│
29    └─────┗━━━┬━━┛─┗━━━━━━━━━━━━━━━━━━━━━━━━━┛─────┘
3031              └─ #moaied__tplsidebar (the template's sidebar)
32*/
33MoaiEditor.LayoutDesktop = class {
34
35    constructor(layout) {
36
37        // Arguments
38        this.layout = layout;
39
40        // Settings
41        this.settings = {
42            default: { show_edit_summary:false, show_optional_buttons:false}
43        };
44        // Variables
45        this.show_edit_summary = this.settings.default.show_edit_summary;
46        this.show_optional_buttons = this.settings.default.show_optional_buttons;
47
48    }
49
50    deactivate () {
51        // Remove the right sidebar from the panes container
52        this.sidebar.remove();
53        // Unhide all buttons
54        const buttons = document.querySelectorAll(".moaied-button");
55        for (let button of buttons)
56            button.classList.remove('moaied-display-none');
57        // Remove editor padding
58        this.layout.editor.style.paddingLeft = '';
59        this.layout.editor.style.paddingRight = '';
60        // Unhide edit summary
61        this.show_edit_summary = true;
62        this.setEditSummaryVisibility();
63    }
64
65    activate () {
66
67        // Handles
68        const editor = this.layout.editor;
69        const elements = this.layout.elements;
70
71        // Editor layout
72        this.row1         = moaiEditor.createHTML('<div id="moaied__row1"></div>');             // Page location, MoaiEditor buttons
73        this.row2         = moaiEditor.createHTML('<div id="moaied__row2"></div>');             // Toolbar buttons, edit-summary input fields
74        this.paneswrapper = moaiEditor.createHTML('<div id="moaied__panes_wrapper"></div>');    // This div allows us to scroll the panes horizontally in single pane view
75        this.footer       = moaiEditor.createHTML('<div id="moaied__footer"></div>');           // Footer row
76        editor.appendChild(this.row1);
77        editor.appendChild(this.layout.msgarea);
78        editor.appendChild(this.row2);
79        editor.appendChild(this.paneswrapper);
80        editor.appendChild(this.footer);
81        editor.appendChild(this.layout.indicatorScrolling);
82        this.paneswrapper.appendChild(this.layout.panes);
83
84        // Setup Dokuwiki page-tools (currently we are not showing it but someone might want it back in the future)
85        //this.setupPageTools();
86
87        // ──────────────── Row 1 ────────────────────
88
89        // Left, center and right
90        this.topleft = moaiEditor.createHTML('<div id="moaied__topleft"></div>');           // Back button and document id
91        this.toc = moaiEditor.toc.container;                                                // Table of contents
92        this.toc.classList.remove('phone');
93        this.buttons = moaiEditor.createHTML('<div id="moaied__buttons"></div>');           // Editor buttons
94        this.row1.appendChild(this.topleft);
95        this.row1.appendChild(this.toc);
96        this.row1.appendChild(this.buttons);
97
98        // Back button
99        this.topleft.appendChild(moaiEditor.buttons.back.handle);
100
101        // Page id
102        this.topleft.appendChild(this.layout.pageid);
103
104        // Editor buttons
105        var names = [
106            'preview',
107            'livepreview',
108            'partialpreview',
109            'autoscroll',
110            'sep',
111            'divider_moveleft',
112            'divider_moveright',
113            'panes',
114            'sep',
115            'settings',
116            'fullwidth',
117            'enabled',
118            'sep',
119            'save',
120            'cancel',
121        ];
122        this.layout.addButtons (this.buttons, names);
123
124        // ──────────────── Row 2 ────────────────────
125
126        // Left and right
127        this.row2left = moaiEditor.createHTML('<div id="moaied__row2_left" class="moaied-second-to-shrink"></div>');
128        this.row2right = moaiEditor.createHTML('<div id="moaied__row2_right" class="moaied-first-to-shrink"></div>');
129        this.row2.appendChild(this.row2left);
130        this.row2.appendChild(this.row2right);
131
132        // Default Dokuwiki toolbar
133        this.toolbar = elements.toolbar;
134        this.row2left.appendChild(this.toolbar);
135
136
137        // Edit summary
138        this.row2right.appendChild(this.layout.summary);
139
140        // ──────────────── Side ────────────────────
141
142        // Sidebar buttons
143        this.btn_options = this.layout.createSidebarButton ('options', 'More options', this.toggleButtonsVisibility.bind(this) );
144        this.btn_scrollhrz = this.layout.createSidebarButton ('arrowhrz', 'Toggle preview', this.toggleHorizontalScroll.bind(this) );
145        this.btn_editsummary = this.layout.createSidebarButton ('summary', 'Edit summary', this.toggleEditSummaryVisibility.bind(this) );
146
147        // Sidebar
148        this.sidebar = moaiEditor.createHTML('<div id="moaied__sidebar"></div>');    // Sidebar with buttons (on the right)
149        this.row2.appendChild(this.sidebar);
150        this.sidebar.appendChild(this.btn_options);
151        this.sidebar.appendChild(this.btn_scrollhrz);
152        this.sidebar.appendChild(this.btn_editsummary);
153        this.sidebar.appendChild(this.layout.btn_editor);
154        this.sidebar.appendChild(this.layout.btn_linewrap);
155        this.sidebar.appendChild(this.layout.btn_fullscreen);
156        this.sidebar.appendChild(this.layout.btn_scrolltop);
157        this.sidebar.appendChild(this.layout.btn_scrollbottom);
158
159        // Bottom right container (for logo, codemirror menu, etc)
160        this.footer.appendChild(this.layout.bottomRight);
161
162        // ──────────────── Footer ────────────────────
163
164        // Footer
165        this.footerLeft = moaiEditor.createHTML('<div id="moaied__footer_left"></div>');
166        this.docinfo = moaiEditor.createHTML('<div id="moaied__docinfo">&nbsp;</div>');
167        this.footer.appendChild(this.footerLeft);
168        this.footer.appendChild(this.docinfo);
169
170        // Docinfo (will not exist when creating a document)
171        const data = JSINFO.plugin_moaieditor.docinfo;
172        if (data !== null) {
173            const path = '<span>'+data.labelPath+':&nbsp;&nbsp;'+data.path+'</span>';
174            const mod  = '<span>'+data.labelMod+'&nbsp;&nbsp;'+data.time+'&nbsp;&nbsp;'+data.by+'</span>';
175            this.docinfo.innerHTML = path + '&nbsp;&nbsp;·&nbsp;&nbsp;' + mod;
176        }
177        // ────────────────── Hints ─────────────────────
178
179        this.hint_scrollhrz_btn = new MoaiEditor.Hint('arrow-right', 'Click me', this.btn_scrollhrz, 40, 2);
180        this.hint_scrollhrz_bar = new MoaiEditor.Hint('arrow-corner-left-down', 'Drag the scroll bar', this.footer, 200, 52);
181
182        // ────────────── Other things ──────────────────
183
184        this.updatePanesLayout();               // Update the panes layout (side-by-side, top-bottom, single-pane)
185        this.setButtonsVisibility();            // Hide or show the optional buttons at the top
186        this.setEditSummaryVisibility();        // Hide or show the edit summary input fields
187        moaiEditor.buttons.updateDivider();     // Update the panel divider position
188    }
189
190    onClickPanesBtn() {
191        const mode = moaiEditor.buttons.panes.mode;
192        // Show or hide hints
193        this.hint_scrollhrz_btn.disable();
194        this.hint_scrollhrz_bar.disable();
195        if (mode == 'single') {
196            this.hint_scrollhrz_btn.start();
197            this.hint_scrollhrz_bar.start();
198        }
199        // Update the layout
200        this.updatePanesLayout();
201    }
202
203    updatePanesLayout() {
204
205        // Handles
206        const mode = moaiEditor.buttons.panes.mode;
207        const wrapper = document.body.querySelector('#moaied__panes_wrapper');
208        const panes = document.body.querySelector('#moaied__panes');
209        const btn_moveleft = moaiEditor.buttons.divider_moveleft;
210        const btn_moveright = moaiEditor.buttons.divider_moveright;
211
212        // Set single or dual pane layout
213        if (wrapper) {
214            wrapper.classList.remove('moaied-single-pane');
215            if (mode == 'single')
216                wrapper.classList.add('moaied-single-pane');
217        }
218        // In dual pane layout, adjust the orientation of the panes (side-by-side, top-bottom) by controlling 'flex-direction'
219        if (panes) {
220            panes.classList.remove('column');
221            if (mode == 'column')
222                panes.classList.add('column');
223        }
224        // Update the icons of the divider adjustment buttons (to show the correct layout)
225        if (mode != 'single') {
226            btn_moveleft.mode = mode;
227            btn_moveright.mode = mode;
228        }
229        // In single pane layout
230        btn_moveleft.handle.classList.remove('moaied-display-none-secondary');
231        btn_moveright.handle.classList.remove('moaied-display-none-secondary');
232        this.btn_scrollhrz.classList.add('moaied-display-none');
233        if (mode == 'single') {
234            // Hide the divider adjustment buttons (as they are not needed)
235            btn_moveleft.handle.classList.add('moaied-display-none-secondary');
236            btn_moveright.handle.classList.add('moaied-display-none-secondary');
237            // Show the horizontal scroll toggle button (to toggle between editor and preview panes)
238            this.btn_scrollhrz.classList.remove('moaied-display-none');
239        }
240        // Set the maximum width depending on user settings and full-width button
241        const userSettings = JSINFO.plugin_moaieditor;
242        var maxwidth;
243        if (mode == 'row')
244            maxwidth = userSettings.editor_width_side_by_side;
245        if (mode == 'column')
246            maxwidth = userSettings.editor_width_top_bottom;
247        if (mode == 'single')
248            maxwidth = userSettings.editor_width_single_pane;
249        if (moaiEditor.buttons.fullwidth.mode == 'on')
250            maxwidth = 'none';
251        this.layout.editor.style.maxWidth = maxwidth;
252        //console.warn(JSINFO.plugin_moaieditor);
253    }
254
255    toggleHorizontalScroll() {
256        // Toggle between editor and preview pane in single pane layout mode (horizontal scroll)
257        const scroll = this.paneswrapper.scrollLeft;
258        const maxScroll = moaiEditor.scroll.tools.getMaxScrollX (this.paneswrapper);
259        const threshold = maxScroll / 2;
260        if (scroll > threshold)
261            this.paneswrapper.scrollLeft = 0;
262        else
263            this.paneswrapper.scrollLeft = maxScroll+10;
264    }
265
266    toggleButtonsVisibility() {
267        // Show or hide additional buttons at the top of the editor (blue and green buttons)
268        this.show_optional_buttons = !this.show_optional_buttons;
269        this.setButtonsVisibility();
270    }
271    setButtonsVisibility() {
272        // Hide or show the optional buttons at the top of the editor
273        const show = this.show_optional_buttons;
274        var element;
275        var names = [
276            'livepreview',
277            'partialpreview',
278            'autoscroll',
279            'settings',
280            /*'enabled',
281            3*/
282        ];
283        for (let name of names) {
284            if (typeof name === 'string')
285                element = moaiEditor.buttons[name].handle;
286             else
287                element = document.getElementById('moaied__sep_'+name);
288            if (show)
289                element.classList.remove('moaied-display-none');
290            else
291                element.classList.add('moaied-display-none');
292        }
293    }
294
295    toggleEditSummaryVisibility() {
296        // Show or hide the edit-summary input fields (because many users don't use this feature)
297        this.show_edit_summary = !this.show_edit_summary;
298        this.setEditSummaryVisibility();
299    }
300    setEditSummaryVisibility() {
301        const summary = this.layout.summary;
302        if (this.show_edit_summary)
303            summary.classList.remove('moaied-display-none');
304        else
305            summary.classList.add('moaied-display-none');
306    }
307
308    onWindowResize() {
309        this.adjustPaddings();
310    }
311
312    adjustPaddings() {
313        //
314        var w = window.innerWidth;
315        var h = window.innerHeight;
316        // Horizontal padding
317        var left = 10;
318        var right = 40;
319        if (w > 1200) {
320            let extra = (w-1200)/40;
321            left += extra;
322            right += extra*.65;
323        }
324        this.layout.editor.style.paddingLeft = left + 'px';
325        this.layout.editor.style.paddingRight = right + 'px';
326
327    }
328}; // End Class
329
330
331