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 └─────┗━━━┬━━┛─┗━━━━━━━━━━━━━━━━━━━━━━━━━┛─────┘ 30 │ 31 └─ #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"> </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+': '+data.path+'</span>'; 174 const mod = '<span>'+data.labelMod+' '+data.time+' '+data.by+'</span>'; 175 this.docinfo.innerHTML = path + ' · ' + 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