diff --git a/static/editor.js b/static/editor.js index 79f8973..ca0e70e 100644 --- a/static/editor.js +++ b/static/editor.js @@ -1,21 +1,19 @@ -(function () { - window.hyphaChanged = false; - let textarea = document.querySelector('.edit-form__textarea'); - let form = document.querySelector('.edit-form'); +window.hyphaChanged = false; +let textarea = document.querySelector('.edit-form__textarea'); +let form = document.querySelector('.edit-form'); - let warnBeforeClosing = function (ev) { - if (!window.hyphaChanged) return; - ev.preventDefault(); - return ev.returnValue = 'Are you sure you want to exit? You have unsaved changes.'; - }; +let warnBeforeClosing = function (ev) { + if (!window.hyphaChanged) return; + ev.preventDefault(); + return ev.returnValue = 'Are you sure you want to exit? You have unsaved changes.'; +}; - textarea.addEventListener('input', function () { - window.hyphaChanged = true; - }); +textarea.addEventListener('input', function () { + window.hyphaChanged = true; +}); - form.addEventListener('submit', function () { - window.hyphaChanged = false; - }); +form.addEventListener('submit', function () { + window.hyphaChanged = false; +}); - window.addEventListener('beforeunload', warnBeforeClosing); -})(); +window.addEventListener('beforeunload', warnBeforeClosing); diff --git a/static/shortcuts.js b/static/shortcuts.js index 6b18ff4..8b4a385 100644 --- a/static/shortcuts.js +++ b/static/shortcuts.js @@ -1,367 +1,367 @@ -(() => { - const $ = document.querySelector.bind(document); - const $$ = (...args) => Array.prototype.slice.call(document.querySelectorAll(...args)); +const $ = document.querySelector.bind(document); +const $$ = (...args) => Array.prototype.slice.call(document.querySelectorAll(...args)); - const isMac = /Macintosh/.test(window.navigator.userAgent); +const isMac = /Macintosh/.test(window.navigator.userAgent); - function keyEventToShortcut(event) { - let elideShift = event.key.toUpperCase() === event.key && event.shiftKey; - return (event.ctrlKey ? 'Ctrl+' : '') + - (event.altKey ? 'Alt+' : '') + - (event.metaKey ? 'Meta+' : '') + - (!elideShift && event.shiftKey ? 'Shift+' : '') + - (event.key === ',' ? 'Comma' : event.key === ' ' ? 'Space' : event.key); +function keyEventToShortcut(event) { + let elideShift = event.key.toUpperCase() === event.key && event.shiftKey; + return (event.ctrlKey ? 'Ctrl+' : '') + + (event.altKey ? 'Alt+' : '') + + (event.metaKey ? 'Meta+' : '') + + (!elideShift && event.shiftKey ? 'Shift+' : '') + + (event.key === ',' ? 'Comma' : event.key === ' ' ? 'Space' : event.key); +} + +function prettifyShortcut(shortcut) { + let keys = shortcut.split('+'); + + if (isMac) { + let cmdIdx = keys.indexOf('Meta'); + if (cmdIdx !== -1 && keys.length - cmdIdx > 2) { + let tmp = keys[cmdIdx + 1]; + keys[cmdIdx + 1] = 'Meta'; + keys[cmdIdx] = tmp; + } } - function prettifyShortcut(shortcut) { - let keys = shortcut.split('+'); + let lastKey = keys[keys.length - 1]; + if (!keys.includes('Shift') && lastKey.toUpperCase() === lastKey && lastKey.toLowerCase() !== lastKey) { + keys.splice(keys.length - 1, 0, 'Shift'); + } + for (let i = 0; i < keys.length; i++) { if (isMac) { - let cmdIdx = keys.indexOf('Meta'); - if (cmdIdx !== -1 && keys.length - cmdIdx > 2) { - let tmp = keys[cmdIdx + 1]; - keys[cmdIdx + 1] = 'Meta'; - keys[cmdIdx] = tmp; - } - } - - let lastKey = keys[keys.length - 1]; - if (!keys.includes('Shift') && lastKey.toUpperCase() === lastKey && lastKey.toLowerCase() !== lastKey) { - keys.splice(keys.length - 1, 0, 'Shift'); - } - - for (let i = 0; i < keys.length; i++) { - if (isMac) { - switch (keys[i]) { - case 'Ctrl': keys[i] = '⌃'; break; - case 'Alt': keys[i] = '⌥'; break; - case 'Shift': keys[i] = '⇧'; break; - case 'Meta': keys[i] = '⌘'; break; - } - } - - if (i === keys.length - 1 && i > 0 && keys[i].length === 1) { - keys[i] = keys[i].toUpperCase(); - } - switch (keys[i]) { - case 'ArrowLeft': keys[i] = '←'; break; - case 'ArrowRight': keys[i] = '→'; break; - case 'ArrowUp': keys[i] = '↑'; break; - case 'ArrowDown': keys[i] = '↓'; break; - case 'Comma': keys[i] = ','; break; - case 'Enter': keys[i] = '↩'; break; - case ' ': keys[i] = 'Space'; break; + case 'Ctrl': keys[i] = '⌃'; break; + case 'Alt': keys[i] = '⌥'; break; + case 'Shift': keys[i] = '⇧'; break; + case 'Meta': keys[i] = '⌘'; break; } - - keys[i] = `${keys[i]}`; } - return keys.join(isMac ? '' : ' + '); + if (i === keys.length - 1 && i > 0 && keys[i].length === 1) { + keys[i] = keys[i].toUpperCase(); + } + + switch (keys[i]) { + case 'ArrowLeft': keys[i] = '←'; break; + case 'ArrowRight': keys[i] = '→'; break; + case 'ArrowUp': keys[i] = '↑'; break; + case 'ArrowDown': keys[i] = '↓'; break; + case 'Comma': keys[i] = ','; break; + case 'Enter': keys[i] = '↩'; break; + case ' ': keys[i] = 'Space'; break; + } + + keys[i] = `${keys[i]}`; } - function isTextField(element) { - let name = element.nodeName.toLowerCase(); - return name === 'textarea' || - name === 'select' || - (name === 'input' && !['submit', 'reset', 'checkbox', 'radio'].includes(element.type)) || - element.isContentEditable; + return keys.join(isMac ? '' : ' + '); +} + +function isTextField(element) { + let name = element.nodeName.toLowerCase(); + return name === 'textarea' || + name === 'select' || + (name === 'input' && !['submit', 'reset', 'checkbox', 'radio'].includes(element.type)) || + element.isContentEditable; +} + +let notTextField = event => !(event.target instanceof Node && isTextField(event.target)); + +let allShortcuts = []; +let shortcutsGroup = null; + +class ShortcutHandler { + constructor(element, override, filter = () => true) { + this.element = element; + this.map = {}; + this.active = this.map; + this.override = override; + this.filter = filter; + this.timeout = null; + + this.handleKeyDown = this.handleKeyDown.bind(this); + this.resetActive = this.resetActive.bind(this); + this.addEventListeners(); } - let notTextField = event => !(event.target instanceof Node && isTextField(event.target)); + addEventListeners() { + this.element.addEventListener('keydown', this.handleKeyDown); + } - let allShortcuts = []; - let shortcutsGroup = null; + add(text, action, description = null, shownInHelp = true) { + let shortcuts = text.trim().split(',').map(shortcut => shortcut.trim().split(' ')); - class ShortcutHandler { - constructor(element, override, filter = () => true) { - this.element = element; - this.map = {}; - this.active = this.map; - this.override = override; - this.filter = filter; + if (shortcutsGroup && shownInHelp) { + shortcutsGroup.push({ + action, + shortcut: text, + description, + }) + } + + for (let shortcut of shortcuts) { + let node = this.map; + for (let key of shortcut) { + if (!node[key]) { + node[key] = {}; + } + node = node[key]; + if (node.action) { + delete node.action; + delete node.shortcut; + delete node.description; + } + } + + node.action = action; + node.shortcut = shortcut; + node.description = description; + } + } + + group(...args) { + if (typeof args[0] === 'string') this.fakeItem(args.shift()); + shortcutsGroup = []; + + args[0].bind(this)(); + + if (shortcutsGroup && shortcutsGroup.length) allShortcuts.push(shortcutsGroup); + shortcutsGroup = null; + } + + bindElement(shortcut, element, ...other) { + element = typeof element === 'string' ? $(element) : element; + if (!element) return; + this.add(shortcut, () => { + if (isTextField(element)) { + element.focus(); + } else { + element.click(); + } + }, ...other); + } + + bindLink(shortcut, link, ...other) { + this.add(shortcut, () => window.location.href = link, ...other); + } + + bindCollection(prefix, elements, collectionDescription, itemDescription) { + this.fakeItem(prefix + ' 1 – 9', collectionDescription); + + if (typeof elements === 'string') { + elements = $$(elements); + } else if (Array.isArray(elements)) { + elements = elements.map(el => typeof el === 'string' ? $(el) : el); + } + + for (let i = 1; i <= elements.length && i < 10; i++) { + this.bindElement(`${prefix} ${i}`, elements[i - 1], `${itemDescription} #${i}`, false); + } + } + + fakeItem(shortcut, description = null) { + let list = shortcutsGroup || allShortcuts; + list.push({ + shortcut: description ? shortcut : null, + description: description || shortcut, + }); + } + + handleKeyDown(event) { + if (event.defaultPrevented) return; + if (['Control', 'Alt', 'Shift', 'Meta'].includes(event.key)) return; + if (!this.filter(event)) return; + + let shortcut = keyEventToShortcut(event); + + if (!this.active[shortcut]) { + this.resetActive(); + return; + } + + this.active = this.active[shortcut]; + if (this.active.action) { + event.stopPropagation(); + this.active.action(event); + if (this.override) event.preventDefault(); + this.resetActive(); + return; + } + + if (this.timeout) clearTimeout(this.timeout); + this.timeout = window.setTimeout(this.resetActive, 1500); + } + + resetActive() { + this.active = this.map; + if (this.timeout) { + clearTimeout(this.timeout) this.timeout = null; - - this.handleKeyDown = this.handleKeyDown.bind(this); - this.resetActive = this.resetActive.bind(this); - this.addEventListeners(); - } - - addEventListeners() { - this.element.addEventListener('keydown', this.handleKeyDown); - } - - add(text, action, description = null, shownInHelp = true) { - let shortcuts = text.trim().split(',').map(shortcut => shortcut.trim().split(' ')); - - if (shortcutsGroup && shownInHelp) { - shortcutsGroup.push({ - action, - shortcut: text, - description, - }) - } - - for (let shortcut of shortcuts) { - let node = this.map; - for (let key of shortcut) { - if (!node[key]) { - node[key] = {}; - } - node = node[key]; - if (node.action) { - delete node.action; - delete node.shortcut; - delete node.description; - } - } - - node.action = action; - node.shortcut = shortcut; - node.description = description; - } - } - - group(...args) { - if (typeof args[0] === 'string') this.fakeItem(args.shift()); - shortcutsGroup = []; - - args[0].bind(this)(); - - if (shortcutsGroup && shortcutsGroup.length) allShortcuts.push(shortcutsGroup); - shortcutsGroup = null; - } - - bindElement(shortcut, element, ...other) { - element = typeof element === 'string' ? $(element) : element; - if (!element) return; - this.add(shortcut, () => { - if (isTextField(element)) { - element.focus(); - } else { - element.click(); - } - }, ...other); - } - - bindLink(shortcut, link, ...other) { - this.add(shortcut, () => window.location.href = link, ...other); - } - - bindCollection(prefix, elements, collectionDescription, itemDescription) { - this.fakeItem(prefix + ' 1 – 9', collectionDescription); - - if (typeof elements === 'string') { - elements = $$(elements); - } else if (Array.isArray(elements)) { - elements = elements.map(el => typeof el === 'string' ? $(el) : el); - } - - for (let i = 1; i <= elements.length && i < 10; i++) { - this.bindElement(`${prefix} ${i}`, elements[i-1], `${itemDescription} #${i}`, false); - } - } - - fakeItem(shortcut, description = null) { - let list = shortcutsGroup || allShortcuts; - list.push({ - shortcut: description ? shortcut : null, - description: description || shortcut, - }); - } - - handleKeyDown(event) { - if (event.defaultPrevented) return; - if (['Control', 'Alt', 'Shift', 'Meta'].includes(event.key)) return; - if (!this.filter(event)) return; - - let shortcut = keyEventToShortcut(event); - - if (!this.active[shortcut]) { - this.resetActive(); - return; - } - - this.active = this.active[shortcut]; - if (this.active.action) { - event.stopPropagation(); - this.active.action(event); - if (this.override) event.preventDefault(); - this.resetActive(); - return; - } - - if (this.timeout) clearTimeout(this.timeout); - this.timeout = window.setTimeout(this.resetActive, 1500); - } - - resetActive() { - this.active = this.map; - if (this.timeout) { - clearTimeout(this.timeout) - this.timeout = null; - } } } +} - class ShortcutsHelpDialog { - constructor() { - let template = $('#dialog-template'); - let clonedTemplate = template.content.cloneNode(true); - this.backdrop = clonedTemplate.children[0]; - this.dialog = clonedTemplate.children[1]; +class ShortcutsHelpDialog { + constructor() { + let template = $('#dialog-template'); + let clonedTemplate = template.content.cloneNode(true); + this.backdrop = clonedTemplate.children[0]; + this.dialog = clonedTemplate.children[1]; - this.dialog.classList.add('shortcuts-help'); - this.dialog.hidden = true; - this.backdrop.hidden = true; + this.dialog.classList.add('shortcuts-help'); + this.dialog.hidden = true; + this.backdrop.hidden = true; - document.body.appendChild(this.backdrop); - document.body.appendChild(this.dialog); + document.body.appendChild(this.backdrop); + document.body.appendChild(this.dialog); - this.close = this.close.bind(this); + this.close = this.close.bind(this); - this.dialog.querySelector('.dialog__title').textContent = 'List of shortcuts'; - this.dialog.querySelector('.dialog__close-button').addEventListener('click', this.close); - this.backdrop.addEventListener('click', this.close); + this.dialog.querySelector('.dialog__title').textContent = 'List of shortcuts'; + this.dialog.querySelector('.dialog__close-button').addEventListener('click', this.close); + this.backdrop.addEventListener('click', this.close); - this.shortcuts = new ShortcutHandler(this.dialog, false); - this.shortcuts.add('Escape', this.close, null, false); + this.shortcuts = new ShortcutHandler(this.dialog, false); + this.shortcuts.add('Escape', this.close, null, false); - let shortcutsGroup; - let shortcutsGroupTemplate = document.createElement('div'); - shortcutsGroupTemplate.className = 'shortcuts-group'; + let shortcutsGroup; + let shortcutsGroupTemplate = document.createElement('div'); + shortcutsGroupTemplate.className = 'shortcuts-group'; - for (let item of allShortcuts) { - if (item.description && !item.shortcut) { - shortcutsGroup = shortcutsGroupTemplate.cloneNode(); - this.dialog.querySelector('.dialog__content').appendChild(shortcutsGroup); + for (let item of allShortcuts) { + if (item.description && !item.shortcut) { + shortcutsGroup = shortcutsGroupTemplate.cloneNode(); + this.dialog.querySelector('.dialog__content').appendChild(shortcutsGroup); - let heading = document.createElement('h2'); - heading.className = 'shortcuts-group-heading'; - heading.textContent = item.description; - shortcutsGroup.appendChild(heading); + let heading = document.createElement('h2'); + heading.className = 'shortcuts-group-heading'; + heading.textContent = item.description; + shortcutsGroup.appendChild(heading); - } else { - let list = document.createElement('ul'); - list.className = 'shortcuts-list'; + } else { + let list = document.createElement('ul'); + list.className = 'shortcuts-list'; - for (let shortcut of item) { - let listItem = document.createElement('li'); - listItem.className = 'shortcut-row'; - list.appendChild(listItem); + for (let shortcut of item) { + let listItem = document.createElement('li'); + listItem.className = 'shortcut-row'; + list.appendChild(listItem); - let descriptionColumn = document.createElement('div') - descriptionColumn.className = 'shortcut-row__description'; - descriptionColumn.textContent = shortcut.description; - listItem.appendChild(descriptionColumn); + let descriptionColumn = document.createElement('div') + descriptionColumn.className = 'shortcut-row__description'; + descriptionColumn.textContent = shortcut.description; + listItem.appendChild(descriptionColumn); - let shortcutColumn = document.createElement('div'); - shortcutColumn.className = 'shortcut-row__keys'; - shortcutColumn.innerHTML = shortcut.shortcut.split(',') - .map(shortcuts => shortcuts.trim().split(' ').map(prettifyShortcut).join(' ')) - .join(' or '); - listItem.appendChild(shortcutColumn); - } + let shortcutColumn = document.createElement('div'); + shortcutColumn.className = 'shortcut-row__keys'; + shortcutColumn.innerHTML = shortcut.shortcut.split(',') + .map(shortcuts => shortcuts.trim().split(' ').map(prettifyShortcut).join(' ')) + .join(' or '); + listItem.appendChild(shortcutColumn); + } + if (shortcutsGroup) { shortcutsGroup.appendChild(list); } } } - - open() { - this.prevActiveElement = document.activeElement; - - document.body.overflow = 'hidden'; - this.backdrop.hidden = false; - this.dialog.hidden = false; - this.dialog.focus(); - } - - close() { - document.body.overflow = ''; - this.backdrop.hidden = true; - this.dialog.hidden = true; - - if (this.prevActiveElement) { - this.prevActiveElement.focus(); - this.prevActiveElement = null; - } - } } - window.addEventListener('load', () => { - let helpDialog = null; - let openHelp = () => { - if (!helpDialog) helpDialog = new ShortcutsHelpDialog(); - helpDialog.open(); - }; + open() { + this.prevActiveElement = document.activeElement; - let onEditPage = typeof editTextarea !== 'undefined'; + document.body.overflow = 'hidden'; + this.backdrop.hidden = false; + this.dialog.hidden = false; + this.dialog.focus(); + } - // Global shortcuts work everywhere. - let globalShortcuts = new ShortcutHandler(document, false); - globalShortcuts.add(isMac ? 'Meta+/' : 'Ctrl+/', openHelp); + close() { + document.body.overflow = ''; + this.backdrop.hidden = true; + this.dialog.hidden = true; - // Page shortcuts work everywhere except on text fields. - let pageShortcuts = new ShortcutHandler(document, false, notTextField); - pageShortcuts.add('?', openHelp, null, false); + if (this.prevActiveElement) { + this.prevActiveElement.focus(); + this.prevActiveElement = null; + } + } +} - // Common shortcuts - pageShortcuts.group('Common', function () { - this.bindCollection('g', '.top-bar__highlight-link', 'First 9 header links', 'Header link'); - this.bindLink('g h', '/', 'Home'); - this.bindLink('g l', '/list/', 'List of hyphae'); - this.bindLink('g r', '/recent-changes/', 'Recent changes'); - this.bindElement('g u', '.auth-links__user-link', 'Your profile′s hypha'); +window.addEventListener('load', () => { + let helpDialog = null; + let openHelp = () => { + if (!helpDialog) helpDialog = new ShortcutsHelpDialog(); + helpDialog.open(); + }; + + let onEditPage = typeof editTextarea !== 'undefined'; + + // Global shortcuts work everywhere. + let globalShortcuts = new ShortcutHandler(document, false); + globalShortcuts.add(isMac ? 'Meta+/' : 'Ctrl+/', openHelp); + + // Page shortcuts work everywhere except on text fields. + let pageShortcuts = new ShortcutHandler(document, false, notTextField); + pageShortcuts.add('?', openHelp, null, false); + + // Common shortcuts + pageShortcuts.group('Common', function () { + this.bindCollection('g', '.top-bar__highlight-link', 'First 9 header links', 'Header link'); + this.bindLink('g h', '/', 'Home'); + this.bindLink('g l', '/list/', 'List of hyphae'); + this.bindLink('g r', '/recent-changes/', 'Recent changes'); + this.bindElement('g u', '.auth-links__user-link', 'Your profile′s hypha'); + }); + + if (!onEditPage) { + // Hypha shortcuts + pageShortcuts.group('Hypha', function () { + this.bindCollection('', 'article .wikilink', 'First 9 hypha′s links', 'Hypha link'); + this.bindElement('p, Alt+ArrowLeft, Ctrl+Alt+ArrowLeft', '.prevnext__prev', 'Next hypha'); + this.bindElement('n, Alt+ArrowRight, Ctrl+Alt+ArrowRight', '.prevnext__next', 'Previous hypha'); + this.bindElement('s, Alt+ArrowUp, Ctrl+Alt+ArrowUp', $$('.navi-title a').slice(1, -1).slice(-1)[0], 'Parent hypha'); + this.bindElement('c, Alt+ArrowDown, Ctrl+Alt+ArrowDown', '.subhyphae__link', 'First child hypha'); + + this.bindElement('v', '.hypha-info__link[href^="/hypha/"]', 'Go to hypha′s page'); + this.bindElement('e, ' + (isMac ? "Meta+Enter" : "Ctrl+Enter"), '.edit-btn__link[href^="/edit/"]', 'Edit this hypha'); + this.bindElement('a', '.hypha-info__link[href^="/attachment/"]', 'Go to attachment'); + this.bindElement('h', '.hypha-info__link[href^="/history/"]', 'Go to history'); + this.bindElement('r', '.hypha-info__link[href^="/rename-ask/"]', 'Rename this hypha'); }); - if (!onEditPage) { - // Hypha shortcuts - pageShortcuts.group('Hypha', function () { - this.bindCollection('', 'article .wikilink', 'First 9 hypha′s links', 'Hypha link'); - this.bindElement('p, Alt+ArrowLeft, Ctrl+Alt+ArrowLeft', '.prevnext__prev', 'Next hypha'); - this.bindElement('n, Alt+ArrowRight, Ctrl+Alt+ArrowRight', '.prevnext__next', 'Previous hypha'); - this.bindElement('s, Alt+ArrowUp, Ctrl+Alt+ArrowUp', $$('.navi-title a').slice(1, -1).slice(-1)[0], 'Parent hypha'); - this.bindElement('c, Alt+ArrowDown, Ctrl+Alt+ArrowDown', '.subhyphae__link', 'First child hypha'); + } else { + // Hypha editor shortcuts. These work only on editor's text area. + let editorShortcuts = new ShortcutHandler(editTextarea, true); - this.bindElement('v', '.hypha-info__link[href^="/hypha/"]', 'Go to hypha′s page'); - this.bindElement('e, ' + (isMac ? "Meta+Enter" : "Ctrl+Enter"), '.edit-btn__link[href^="/edit/"]', 'Edit this hypha'); - this.bindElement('a', '.hypha-info__link[href^="/attachment/"]', 'Go to attachment'); - this.bindElement('h', '.hypha-info__link[href^="/history/"]', 'Go to history'); - this.bindElement('r', '.hypha-info__link[href^="/rename-ask/"]', 'Rename this hypha'); - }); + let shortcuts = [ + // Win+Linux Mac Action Description + ['Ctrl+b', 'Meta+b', wrapBold, 'Format: Bold'], + ['Ctrl+i', 'Meta+i', wrapItalic, 'Format: Italic'], + ['Ctrl+M', 'Meta+Shift+m', wrapMonospace, 'Format: Monospaced'], + ['Ctrl+I', 'Meta+Shift+i', wrapHighlighted, 'Format: Highlight'], + ['Ctrl+.', 'Meta+.', wrapLifted, 'Format: Superscript'], + ['Ctrl+Comma', 'Meta+Comma', wrapLowered, 'Format: Subscript'], + ['Ctrl+X', 'Meta+Shift+x', wrapStrikethrough, 'Format: Strikethrough'], + ['Ctrl+k', 'Meta+k', wrapLink, 'Format: Inline link'], + // Apparently, ⌘; conflicts with a Safari's hotkey. Whatever. + ['Ctrl+;', 'Meta+;', insertDate, 'Insert date UTC'], + ]; - } else { - // Hypha editor shortcuts. These work only on editor's text area. - let editorShortcuts = new ShortcutHandler(editTextarea, true); - - let shortcuts = [ - // Win+Linux Mac Action Description - ['Ctrl+b', 'Meta+b', wrapBold, 'Format: Bold'], - ['Ctrl+i', 'Meta+i', wrapItalic, 'Format: Italic'], - ['Ctrl+M', 'Meta+Shift+m', wrapMonospace, 'Format: Monospaced'], - ['Ctrl+I', 'Meta+Shift+i', wrapHighlighted, 'Format: Highlight'], - ['Ctrl+.', 'Meta+.', wrapLifted, 'Format: Superscript'], - ['Ctrl+Comma', 'Meta+Comma', wrapLowered, 'Format: Subscript'], - ['Ctrl+X', 'Meta+Shift+x', wrapStrikethrough, 'Format: Strikethrough'], - ['Ctrl+k', 'Meta+k', wrapLink, 'Format: Inline link'], - // Apparently, ⌘; conflicts with a Safari's hotkey. Whatever. - ['Ctrl+;', 'Meta+;', insertDate, 'Insert date UTC'], - ]; - - editorShortcuts.group('Editor', function () { - for (let shortcut of shortcuts) { - if (isMac) { - this.add(shortcut[1], ...shortcut.slice(2)) - } else { - this.add(shortcut[0], ...shortcut.slice(2)) - } + editorShortcuts.group('Editor', function () { + for (let shortcut of shortcuts) { + if (isMac) { + this.add(shortcut[1], ...shortcut.slice(2)) + } else { + this.add(shortcut[0], ...shortcut.slice(2)) } - }); + } + }); - editorShortcuts.group(function () { - this.bindElement(isMac ? 'Meta+Enter' : 'Ctrl+Enter', $('.edit-form__save'), 'Save changes'); - }); - } - }); -})(); + editorShortcuts.group(function () { + this.bindElement(isMac ? 'Meta+Enter' : 'Ctrl+Enter', $('.edit-form__save'), 'Save changes'); + }); + } +}); diff --git a/static/toolbar.js b/static/toolbar.js index 5984a10..6f2f9b7 100644 --- a/static/toolbar.js +++ b/static/toolbar.js @@ -44,8 +44,8 @@ function selectionWrapper(cursorPosition, prefix, postfix = null, el = editTexta // selection is decorated, so we just cut it removing = true result = text.substring(cursorPosition, text.length - cursorPosition) - } else if ( (prefix == el.value.slice(start-cursorPosition, start)) && - (postfix == el.value.slice(end, end+cursorPosition)) ) { + } else if ( (prefix === el.value.slice(start-cursorPosition, start)) && + (postfix === el.value.slice(end, end+cursorPosition)) ) { // selection is surrounded by decorations removing = true result = text