diff --git a/static/default.css b/static/default.css index b5ccf70..cb5fd23 100644 --- a/static/default.css +++ b/static/default.css @@ -368,7 +368,7 @@ kbd { opacity: .7; } -.shortcuts-modal { +.shortcuts-help .dialog__content { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-column-gap: 32px; diff --git a/static/shortcuts.js b/static/shortcuts.js index e1214cc..54c7146 100644 --- a/static/shortcuts.js +++ b/static/shortcuts.js @@ -207,45 +207,36 @@ } } - let prevActiveElement = null; - let shortcutsListDialog = null; + class ShortcutsHelpDialog { + constructor() { + let template = $('#dialog-template'); + this.wrap = template.content.firstElementChild.cloneNode(true); + this.wrap.classList.add('shortcuts-help'); + this.wrap.hidden = true; - function openShortcutsReference() { - if (!shortcutsListDialog) { - let wrap = document.createElement('div'); - wrap.className = 'dialog-wrap'; - shortcutsListDialog = wrap; + let handleClose = (event) => { + event.preventDefault(); + event.stopPropagation(); + this.close(); + }; - let dialog = document.createElement('div'); - dialog.className = 'dialog shortcuts-modal'; - dialog.tabIndex = 0; - wrap.appendChild(dialog); + this.shortcuts = new ShortcutHandler(this.wrap, false); + this.shortcuts.add('Escape', handleClose, null, false); - let dialogHeader = document.createElement('div'); - dialogHeader.className = 'dialog__header'; - dialog.appendChild(dialogHeader); + this.wrap.querySelector('.dialog__title').textContent = 'List of shortcuts'; + this.wrap.querySelector('.dialog__close-button').addEventListener('click', handleClose); - let title = document.createElement('h1'); - title.className = 'dialog__title'; - title.textContent = 'List of shortcuts'; - dialogHeader.appendChild(title); - - let closeButton = document.createElement('button'); - closeButton.className = 'dialog__close-button'; - closeButton.setAttribute('aria-label', 'Close this dialog'); - dialogHeader.appendChild(closeButton); + this.wrap.addEventListener('click', handleClose); + this.wrap.querySelector('.dialog').addEventListener('click', event => event.stopPropagation()); + let shortcutsGroup; let shortcutsGroupTemplate = document.createElement('div'); shortcutsGroupTemplate.className = 'shortcuts-group'; - let shortcutsGroup = shortcutsGroupTemplate.cloneNode(); - for (let item of allShortcuts) { if (item.description && !item.shortcut) { - if (shortcutsGroup.children.length > 0) { - dialog.appendChild(shortcutsGroup); - shortcutsGroup = shortcutsGroupTemplate.cloneNode(); - } + shortcutsGroup = shortcutsGroupTemplate.cloneNode(); + this.wrap.querySelector('.dialog__content').appendChild(shortcutsGroup); let heading = document.createElement('h2'); heading.className = 'shortcuts-group-heading'; @@ -278,47 +269,35 @@ } } - if (shortcutsGroup.children.length > 0) { - dialog.appendChild(shortcutsGroup); - shortcutsGroup = shortcutsGroupTemplate.cloneNode(); - } - - let handleClose = (event) => { - event.preventDefault(); - event.stopPropagation(); - closeShortcutsReference(); - }; - - let dialogShortcuts = new ShortcutHandler(dialog, true, notTextField); - - dialogShortcuts.add('Escape', handleClose); - closeButton.addEventListener('click', handleClose); - wrap.addEventListener('click', handleClose); - - dialog.addEventListener('click', event => event.stopPropagation()); - - document.body.appendChild(wrap); + document.body.appendChild(this.wrap); } - document.body.overflow = 'hidden'; - shortcutsListDialog.hidden = false; - prevActiveElement = document.activeElement; - shortcutsListDialog.children[0].focus(); - } + open() { + this.prevActiveElement = document.activeElement; - function closeShortcutsReference() { - if (shortcutsListDialog) { + document.body.overflow = 'hidden'; + this.wrap.hidden = false; + this.wrap.children[0].focus(); + } + + close() { document.body.overflow = ''; - shortcutsListDialog.hidden = true; + this.wrap.hidden = true; - if (prevActiveElement) { - prevActiveElement.focus(); - prevActiveElement = null; + if (this.prevActiveElement) { + this.prevActiveElement.focus(); + this.prevActiveElement = null; } } } window.addEventListener('load', () => { + let helpDialog = null; + let openHelp = () => { + if (!helpDialog) helpDialog = new ShortcutsHelpDialog(); + helpDialog.open(); + }; + // Global shortcuts work everywhere. let globalShortcuts = new ShortcutHandler(document, false); globalShortcuts.add('?, ' + (isMac ? 'Meta+/' : 'Ctrl+/'), openShortcutsReference); diff --git a/views/stuff.qtpl b/views/stuff.qtpl index 0e75d94..7a27a98 100644 --- a/views/stuff.qtpl +++ b/views/stuff.qtpl @@ -28,6 +28,18 @@ {%s= body %} + {%= omnipresentScripts() %} diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go index 5a255bb..054aab3 100644 --- a/views/stuff.qtpl.go +++ b/views/stuff.qtpl.go @@ -93,52 +93,64 @@ func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string, u *user.User, qw422016.N().S(body) //line views/stuff.qtpl:30 qw422016.N().S(` + `) -//line views/stuff.qtpl:31 +//line views/stuff.qtpl:43 streamomnipresentScripts(qw422016) -//line views/stuff.qtpl:31 +//line views/stuff.qtpl:43 qw422016.N().S(` `) -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 } -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 func WriteBaseHTML(qq422016 qtio422016.Writer, title, body string, u *user.User, headElements ...string) { -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 StreamBaseHTML(qw422016, title, body, u, headElements...) -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 } -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 func BaseHTML(title, body string, u *user.User, headElements ...string) string { -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 WriteBaseHTML(qb422016, title, body, u, headElements...) -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 return qs422016 -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:46 } -//line views/stuff.qtpl:36 +//line views/stuff.qtpl:48 func StreamUserListHTML(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:36 +//line views/stuff.qtpl:48 qw422016.N().S(`

List of users

`) -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:53 var ( admins = make([]string, 0) moderators = make([]string, 0) @@ -155,303 +167,303 @@ func StreamUserListHTML(qw422016 *qt422016.Writer) { } } -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:68 qw422016.N().S(`

Admins

    `) -//line views/stuff.qtpl:59 +//line views/stuff.qtpl:71 for _, name := range admins { -//line views/stuff.qtpl:59 +//line views/stuff.qtpl:71 qw422016.N().S(`
  1. `) -//line views/stuff.qtpl:60 +//line views/stuff.qtpl:72 qw422016.E().S(name) -//line views/stuff.qtpl:60 +//line views/stuff.qtpl:72 qw422016.N().S(`
  2. `) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:73 } -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:73 qw422016.N().S(`

Moderators

    `) -//line views/stuff.qtpl:65 +//line views/stuff.qtpl:77 for _, name := range moderators { -//line views/stuff.qtpl:65 +//line views/stuff.qtpl:77 qw422016.N().S(`
  1. `) -//line views/stuff.qtpl:66 +//line views/stuff.qtpl:78 qw422016.E().S(name) -//line views/stuff.qtpl:66 +//line views/stuff.qtpl:78 qw422016.N().S(`
  2. `) -//line views/stuff.qtpl:67 +//line views/stuff.qtpl:79 } -//line views/stuff.qtpl:67 +//line views/stuff.qtpl:79 qw422016.N().S(`

Editors

    `) -//line views/stuff.qtpl:71 +//line views/stuff.qtpl:83 for _, name := range editors { -//line views/stuff.qtpl:71 +//line views/stuff.qtpl:83 qw422016.N().S(`
  1. `) -//line views/stuff.qtpl:72 +//line views/stuff.qtpl:84 qw422016.E().S(name) -//line views/stuff.qtpl:72 +//line views/stuff.qtpl:84 qw422016.N().S(`
  2. `) -//line views/stuff.qtpl:73 +//line views/stuff.qtpl:85 } -//line views/stuff.qtpl:73 +//line views/stuff.qtpl:85 qw422016.N().S(`
`) -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 } -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 func WriteUserListHTML(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 StreamUserListHTML(qw422016) -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 } -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 func UserListHTML() string { -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 WriteUserListHTML(qb422016) -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 return qs422016 -//line views/stuff.qtpl:77 +//line views/stuff.qtpl:89 } -//line views/stuff.qtpl:79 +//line views/stuff.qtpl:91 func StreamHyphaListHTML(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:79 +//line views/stuff.qtpl:91 qw422016.N().S(`

List of hyphae

This wiki has `) -//line views/stuff.qtpl:83 +//line views/stuff.qtpl:95 qw422016.N().D(hyphae.Count()) -//line views/stuff.qtpl:83 +//line views/stuff.qtpl:95 qw422016.N().S(` hyphae.

`) -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 } -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 func WriteHyphaListHTML(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 StreamHyphaListHTML(qw422016) -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 } -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 func HyphaListHTML() string { -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 WriteHyphaListHTML(qb422016) -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 return qs422016 -//line views/stuff.qtpl:96 +//line views/stuff.qtpl:108 } -//line views/stuff.qtpl:98 +//line views/stuff.qtpl:110 func StreamAboutHTML(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:98 +//line views/stuff.qtpl:110 qw422016.N().S(`

About `) -//line views/stuff.qtpl:102 +//line views/stuff.qtpl:114 qw422016.E().S(cfg.WikiName) -//line views/stuff.qtpl:102 +//line views/stuff.qtpl:114 qw422016.N().S(`

See /list for information about hyphae on this wiki.

`) -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 } -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 func WriteAboutHTML(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 StreamAboutHTML(qw422016) -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 } -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 func AboutHTML() string { -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 WriteAboutHTML(qb422016) -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 return qs422016 -//line views/stuff.qtpl:120 +//line views/stuff.qtpl:132 } -//line views/stuff.qtpl:122 +//line views/stuff.qtpl:134 func StreamAdminPanelHTML(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:122 +//line views/stuff.qtpl:134 qw422016.N().S(`
@@ -488,80 +500,80 @@ func StreamAdminPanelHTML(qw422016 *qt422016.Writer) {
`) -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 } -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 func WriteAdminPanelHTML(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 StreamAdminPanelHTML(qw422016) -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 } -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 func AdminPanelHTML() string { -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 WriteAdminPanelHTML(qb422016) -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 return qs422016 -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:169 } -//line views/stuff.qtpl:159 +//line views/stuff.qtpl:171 func streamomnipresentScripts(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:159 +//line views/stuff.qtpl:171 qw422016.N().S(` `) -//line views/stuff.qtpl:160 +//line views/stuff.qtpl:172 for _, scriptPath := range cfg.OmnipresentScripts { -//line views/stuff.qtpl:160 +//line views/stuff.qtpl:172 qw422016.N().S(` `) -//line views/stuff.qtpl:162 +//line views/stuff.qtpl:174 } -//line views/stuff.qtpl:162 +//line views/stuff.qtpl:174 qw422016.N().S(` `) -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 } -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 func writeomnipresentScripts(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 streamomnipresentScripts(qw422016) -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 } -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 func omnipresentScripts() string { -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 writeomnipresentScripts(qb422016) -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 return qs422016 -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:175 }