mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 05:36:00 +00:00
Ran eslint fix on existing codebase
Had to do some manual fixing of the app.js file due to misplaced comments
This commit is contained in:
parent
752ee664c2
commit
e711290d8b
@ -1,9 +1,16 @@
|
|||||||
|
import events from './services/events';
|
||||||
|
import httpInstance from './services/http';
|
||||||
|
import Translations from './services/translations';
|
||||||
|
|
||||||
|
import * as components from './services/components';
|
||||||
|
import * as componentMap from './components';
|
||||||
|
|
||||||
// Url retrieval function
|
// Url retrieval function
|
||||||
window.baseUrl = function(path) {
|
window.baseUrl = function(path) {
|
||||||
let basePath = document.querySelector('meta[name="base-url"]').getAttribute('content');
|
let basePath = document.querySelector('meta[name="base-url"]').getAttribute('content');
|
||||||
if (basePath[basePath.length-1] === '/') basePath = basePath.slice(0, basePath.length-1);
|
if (basePath[basePath.length - 1] === '/') basePath = basePath.slice(0, basePath.length - 1);
|
||||||
if (path[0] === '/') path = path.slice(1);
|
if (path[0] === '/') path = path.slice(1);
|
||||||
return basePath + '/' + path;
|
return `${basePath}/${path}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
window.importVersioned = function(moduleName) {
|
window.importVersioned = function(moduleName) {
|
||||||
@ -13,22 +20,17 @@ window.importVersioned = function(moduleName) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Set events and http services on window
|
// Set events and http services on window
|
||||||
import events from "./services/events"
|
|
||||||
import httpInstance from "./services/http"
|
|
||||||
window.$http = httpInstance;
|
window.$http = httpInstance;
|
||||||
window.$events = events;
|
window.$events = events;
|
||||||
|
|
||||||
// Translation setup
|
// Translation setup
|
||||||
// Creates a global function with name 'trans' to be used in the same way as Laravel's translation system
|
// Creates a global function with name 'trans' to be used in the same way as the Laravel translation system
|
||||||
import Translations from "./services/translations"
|
|
||||||
const translator = new Translations();
|
const translator = new Translations();
|
||||||
window.trans = translator.get.bind(translator);
|
window.trans = translator.get.bind(translator);
|
||||||
window.trans_choice = translator.getPlural.bind(translator);
|
window.trans_choice = translator.getPlural.bind(translator);
|
||||||
window.trans_plural = translator.parsePlural.bind(translator);
|
window.trans_plural = translator.parsePlural.bind(translator);
|
||||||
|
|
||||||
// Load Components
|
// Load & initialise components
|
||||||
import * as components from "./services/components"
|
|
||||||
import * as componentMap from "./components";
|
|
||||||
components.register(componentMap);
|
components.register(componentMap);
|
||||||
window.$components = components;
|
window.$components = components;
|
||||||
components.init();
|
components.init();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import {EditorView, keymap} from "@codemirror/view";
|
import {EditorView, keymap} from '@codemirror/view';
|
||||||
|
|
||||||
import {copyTextToClipboard} from "../services/clipboard.js"
|
import {copyTextToClipboard} from '../services/clipboard';
|
||||||
import {viewerExtensions, editorExtensions} from "./setups.js";
|
import {viewerExtensions, editorExtensions} from './setups';
|
||||||
import {createView} from "./views.js";
|
import {createView} from './views';
|
||||||
import {SimpleEditorInterface} from "./simple-editor-interface.js";
|
import {SimpleEditorInterface} from './simple-editor-interface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Highlight pre elements on a page
|
* Highlight pre elements on a page
|
||||||
@ -32,7 +32,7 @@ export function highlightWithin(parent) {
|
|||||||
*/
|
*/
|
||||||
function highlightElem(elem) {
|
function highlightElem(elem) {
|
||||||
const innerCodeElem = elem.querySelector('code[class^=language-]');
|
const innerCodeElem = elem.querySelector('code[class^=language-]');
|
||||||
elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi ,'\n');
|
elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi, '\n');
|
||||||
const content = elem.textContent.trimEnd();
|
const content = elem.textContent.trimEnd();
|
||||||
|
|
||||||
let langName = '';
|
let langName = '';
|
||||||
@ -61,10 +61,10 @@ function highlightElem(elem) {
|
|||||||
* @param {EditorView} editorView
|
* @param {EditorView} editorView
|
||||||
*/
|
*/
|
||||||
function addCopyIcon(editorView) {
|
function addCopyIcon(editorView) {
|
||||||
const copyIcon = `<svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>`;
|
const copyIcon = '<svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>';
|
||||||
const checkIcon = `<svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>`;
|
const checkIcon = '<svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>';
|
||||||
const copyButton = document.createElement('button');
|
const copyButton = document.createElement('button');
|
||||||
copyButton.setAttribute('type', 'button')
|
copyButton.setAttribute('type', 'button');
|
||||||
copyButton.classList.add('cm-copy-button');
|
copyButton.classList.add('cm-copy-button');
|
||||||
copyButton.innerHTML = copyIcon;
|
copyButton.innerHTML = copyIcon;
|
||||||
editorView.dom.appendChild(copyButton);
|
editorView.dom.appendChild(copyButton);
|
||||||
@ -112,7 +112,6 @@ export function wysiwygView(cmContainer, shadowRoot, content, language) {
|
|||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a CodeMirror instance to show in the WYSIWYG pop-up editor
|
* Create a CodeMirror instance to show in the WYSIWYG pop-up editor
|
||||||
* @param {HTMLElement} elem
|
* @param {HTMLElement} elem
|
||||||
@ -126,7 +125,7 @@ export function popupEditor(elem, modeSuggestion) {
|
|||||||
doc: content,
|
doc: content,
|
||||||
extensions: [
|
extensions: [
|
||||||
...editorExtensions(elem.parentElement),
|
...editorExtensions(elem.parentElement),
|
||||||
EditorView.updateListener.of((v) => {
|
EditorView.updateListener.of(v => {
|
||||||
if (v.docChanged) {
|
if (v.docChanged) {
|
||||||
// textArea.value = v.state.doc.toString();
|
// textArea.value = v.state.doc.toString();
|
||||||
}
|
}
|
||||||
@ -155,7 +154,7 @@ export function inlineEditor(textArea, mode) {
|
|||||||
doc: content,
|
doc: content,
|
||||||
extensions: [
|
extensions: [
|
||||||
...editorExtensions(textArea.parentElement),
|
...editorExtensions(textArea.parentElement),
|
||||||
EditorView.updateListener.of((v) => {
|
EditorView.updateListener.of(v => {
|
||||||
if (v.docChanged) {
|
if (v.docChanged) {
|
||||||
textArea.value = v.state.doc.toString();
|
textArea.value = v.state.doc.toString();
|
||||||
}
|
}
|
||||||
@ -188,7 +187,7 @@ export function markdownEditor(elem, onChange, domEventHandlers, keyBindings) {
|
|||||||
extensions: [
|
extensions: [
|
||||||
keymap.of(keyBindings),
|
keymap.of(keyBindings),
|
||||||
...editorExtensions(elem.parentElement),
|
...editorExtensions(elem.parentElement),
|
||||||
EditorView.updateListener.of((v) => {
|
EditorView.updateListener.of(v => {
|
||||||
onChange(v);
|
onChange(v);
|
||||||
}),
|
}),
|
||||||
EditorView.domEventHandlers(domEventHandlers),
|
EditorView.domEventHandlers(domEventHandlers),
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
import {StreamLanguage} from "@codemirror/language"
|
import {StreamLanguage} from '@codemirror/language';
|
||||||
|
|
||||||
import {css} from '@codemirror/lang-css';
|
import {css} from '@codemirror/lang-css';
|
||||||
import {json} from '@codemirror/lang-json';
|
import {json} from '@codemirror/lang-json';
|
||||||
import {javascript} from '@codemirror/lang-javascript';
|
import {javascript} from '@codemirror/lang-javascript';
|
||||||
import {html} from "@codemirror/lang-html";
|
import {html} from '@codemirror/lang-html';
|
||||||
import {markdown} from '@codemirror/lang-markdown';
|
import {markdown} from '@codemirror/lang-markdown';
|
||||||
import {php} from '@codemirror/lang-php';
|
import {php} from '@codemirror/lang-php';
|
||||||
import {twig} from "@ssddanbrown/codemirror-lang-twig";
|
import {twig} from '@ssddanbrown/codemirror-lang-twig';
|
||||||
import {xml} from "@codemirror/lang-xml";
|
import {xml} from '@codemirror/lang-xml';
|
||||||
|
|
||||||
const legacyLoad = async (mode) => {
|
const legacyLoad = async mode => {
|
||||||
const modes = await window.importVersioned('legacy-modes');
|
const modes = await window.importVersioned('legacy-modes');
|
||||||
return StreamLanguage.define(modes[mode]);
|
return StreamLanguage.define(modes[mode]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Mapping of possible languages or formats from user input to their codemirror modes.
|
// Mapping of possible languages or formats from user input to their codemirror modes.
|
||||||
// Value can be a mode string or a function that will receive the code content & return the mode string.
|
// Value can be a mode string or a function that will receive the code content & return the mode string.
|
||||||
// The function option is used in the event the exact mode could be dynamic depending on the code.
|
// The function option is used in the event the exact mode could be dynamic depending on the code.
|
||||||
@ -58,7 +57,7 @@ const modeMap = {
|
|||||||
pascal: () => legacyLoad('pascal'),
|
pascal: () => legacyLoad('pascal'),
|
||||||
perl: () => legacyLoad('perl'),
|
perl: () => legacyLoad('perl'),
|
||||||
pgsql: () => legacyLoad('pgSQL'),
|
pgsql: () => legacyLoad('pgSQL'),
|
||||||
php: async (code) => {
|
php: async code => {
|
||||||
const hasTags = code.includes('<?php');
|
const hasTags = code.includes('<?php');
|
||||||
return php({plain: !hasTags});
|
return php({plain: !hasTags});
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export {c, cpp, csharp, java, kotlin, scala, dart} from '@codemirror/legacy-modes/mode/clike';
|
export {
|
||||||
|
c, cpp, csharp, java, kotlin, scala, dart,
|
||||||
|
} from '@codemirror/legacy-modes/mode/clike';
|
||||||
export {diff} from '@codemirror/legacy-modes/mode/diff';
|
export {diff} from '@codemirror/legacy-modes/mode/diff';
|
||||||
export {fortran} from '@codemirror/legacy-modes/mode/fortran';
|
export {fortran} from '@codemirror/legacy-modes/mode/fortran';
|
||||||
export {go} from '@codemirror/legacy-modes/mode/go';
|
export {go} from '@codemirror/legacy-modes/mode/go';
|
||||||
@ -17,11 +19,13 @@ export {ruby} from '@codemirror/legacy-modes/mode/ruby';
|
|||||||
export {rust} from '@codemirror/legacy-modes/mode/rust';
|
export {rust} from '@codemirror/legacy-modes/mode/rust';
|
||||||
export {scheme} from '@codemirror/legacy-modes/mode/scheme';
|
export {scheme} from '@codemirror/legacy-modes/mode/scheme';
|
||||||
export {shell} from '@codemirror/legacy-modes/mode/shell';
|
export {shell} from '@codemirror/legacy-modes/mode/shell';
|
||||||
export {standardSQL, pgSQL, msSQL, mySQL, sqlite, plSQL} from '@codemirror/legacy-modes/mode/sql';
|
export {
|
||||||
|
standardSQL, pgSQL, msSQL, mySQL, sqlite, plSQL,
|
||||||
|
} from '@codemirror/legacy-modes/mode/sql';
|
||||||
export {stex} from '@codemirror/legacy-modes/mode/stex';
|
export {stex} from '@codemirror/legacy-modes/mode/stex';
|
||||||
export {swift} from "@codemirror/legacy-modes/mode/swift";
|
export {swift} from '@codemirror/legacy-modes/mode/swift';
|
||||||
export {toml} from '@codemirror/legacy-modes/mode/toml';
|
export {toml} from '@codemirror/legacy-modes/mode/toml';
|
||||||
export {vb} from '@codemirror/legacy-modes/mode/vb';
|
export {vb} from '@codemirror/legacy-modes/mode/vb';
|
||||||
export {vbScript} from '@codemirror/legacy-modes/mode/vbscript';
|
export {vbScript} from '@codemirror/legacy-modes/mode/vbscript';
|
||||||
export {yaml} from '@codemirror/legacy-modes/mode/yaml';
|
export {yaml} from '@codemirror/legacy-modes/mode/yaml';
|
||||||
export {smarty} from "@ssddanbrown/codemirror-lang-smarty";
|
export {smarty} from '@ssddanbrown/codemirror-lang-smarty';
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import {EditorView, keymap, drawSelection, highlightActiveLine, dropCursor,
|
import {
|
||||||
rectangularSelection, lineNumbers, highlightActiveLineGutter} from "@codemirror/view"
|
EditorView, keymap, drawSelection, highlightActiveLine, dropCursor,
|
||||||
import {bracketMatching} from "@codemirror/language"
|
rectangularSelection, lineNumbers, highlightActiveLineGutter,
|
||||||
import {defaultKeymap, history, historyKeymap, indentWithTab} from "@codemirror/commands"
|
} from '@codemirror/view';
|
||||||
import {EditorState} from "@codemirror/state"
|
import {bracketMatching} from '@codemirror/language';
|
||||||
import {getTheme} from "./themes";
|
import {
|
||||||
|
defaultKeymap, history, historyKeymap, indentWithTab,
|
||||||
|
} from '@codemirror/commands';
|
||||||
|
import {EditorState} from '@codemirror/state';
|
||||||
|
import {getTheme} from './themes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Element} parentEl
|
* @param {Element} parentEl
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {updateViewLanguage} from "./views";
|
import {updateViewLanguage} from './views';
|
||||||
|
|
||||||
|
|
||||||
export class SimpleEditorInterface {
|
export class SimpleEditorInterface {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {EditorView} editorView
|
* @param {EditorView} editorView
|
||||||
*/
|
*/
|
||||||
@ -22,9 +22,9 @@ export class SimpleEditorInterface {
|
|||||||
* @param content
|
* @param content
|
||||||
*/
|
*/
|
||||||
setContent(content) {
|
setContent(content) {
|
||||||
const doc = this.ev.state.doc;
|
const {doc} = this.ev.state;
|
||||||
this.ev.dispatch({
|
this.ev.dispatch({
|
||||||
changes: {from: 0, to: doc.length, insert: content}
|
changes: {from: 0, to: doc.length, insert: content},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,4 +43,5 @@ export class SimpleEditorInterface {
|
|||||||
setMode(mode, content = '') {
|
setMode(mode, content = '') {
|
||||||
updateViewLanguage(this.ev, mode, content);
|
updateViewLanguage(this.ev, mode, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,62 +1,102 @@
|
|||||||
import {tags} from "@lezer/highlight";
|
import {tags} from '@lezer/highlight';
|
||||||
import {HighlightStyle, syntaxHighlighting} from "@codemirror/language";
|
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language';
|
||||||
import {EditorView} from "@codemirror/view";
|
import {EditorView} from '@codemirror/view';
|
||||||
import {oneDarkHighlightStyle, oneDarkTheme} from "@codemirror/theme-one-dark";
|
import {oneDarkHighlightStyle, oneDarkTheme} from '@codemirror/theme-one-dark';
|
||||||
|
|
||||||
const defaultLightHighlightStyle = HighlightStyle.define([
|
const defaultLightHighlightStyle = HighlightStyle.define([
|
||||||
{ tag: tags.meta,
|
{
|
||||||
color: "#388938" },
|
tag: tags.meta,
|
||||||
{ tag: tags.link,
|
color: '#388938',
|
||||||
textDecoration: "underline" },
|
},
|
||||||
{ tag: tags.heading,
|
{
|
||||||
textDecoration: "underline",
|
tag: tags.link,
|
||||||
fontWeight: "bold" },
|
textDecoration: 'underline',
|
||||||
{ tag: tags.emphasis,
|
},
|
||||||
fontStyle: "italic" },
|
{
|
||||||
{ tag: tags.strong,
|
tag: tags.heading,
|
||||||
fontWeight: "bold" },
|
textDecoration: 'underline',
|
||||||
{ tag: tags.strikethrough,
|
fontWeight: 'bold',
|
||||||
textDecoration: "line-through" },
|
},
|
||||||
{ tag: tags.keyword,
|
{
|
||||||
color: "#708" },
|
tag: tags.emphasis,
|
||||||
{ tag: [tags.atom, tags.bool, tags.url, tags.contentSeparator, tags.labelName],
|
fontStyle: 'italic',
|
||||||
color: "#219" },
|
},
|
||||||
{ tag: [tags.literal, tags.inserted],
|
{
|
||||||
color: "#164" },
|
tag: tags.strong,
|
||||||
{ tag: [tags.string, tags.deleted],
|
fontWeight: 'bold',
|
||||||
color: "#a11" },
|
},
|
||||||
{ tag: [tags.regexp, tags.escape, tags.special(tags.string)],
|
{
|
||||||
color: "#e40" },
|
tag: tags.strikethrough,
|
||||||
{ tag: tags.definition(tags.variableName),
|
textDecoration: 'line-through',
|
||||||
color: "#00f" },
|
},
|
||||||
{ tag: tags.local(tags.variableName),
|
{
|
||||||
color: "#30a" },
|
tag: tags.keyword,
|
||||||
{ tag: [tags.typeName, tags.namespace],
|
color: '#708',
|
||||||
color: "#085" },
|
},
|
||||||
{ tag: tags.className,
|
{
|
||||||
color: "#167" },
|
tag: [tags.atom, tags.bool, tags.url, tags.contentSeparator, tags.labelName],
|
||||||
{ tag: [tags.special(tags.variableName), tags.macroName],
|
color: '#219',
|
||||||
color: "#256" },
|
},
|
||||||
{ tag: tags.definition(tags.propertyName),
|
{
|
||||||
color: "#00c" },
|
tag: [tags.literal, tags.inserted],
|
||||||
{ tag: tags.compareOperator,
|
color: '#164',
|
||||||
color: "#708" },
|
},
|
||||||
{ tag: tags.comment,
|
{
|
||||||
color: "#940" },
|
tag: [tags.string, tags.deleted],
|
||||||
{ tag: tags.invalid,
|
color: '#a11',
|
||||||
color: "#f00" }
|
},
|
||||||
|
{
|
||||||
|
tag: [tags.regexp, tags.escape, tags.special(tags.string)],
|
||||||
|
color: '#e40',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: tags.definition(tags.variableName),
|
||||||
|
color: '#00f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: tags.local(tags.variableName),
|
||||||
|
color: '#30a',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [tags.typeName, tags.namespace],
|
||||||
|
color: '#085',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: tags.className,
|
||||||
|
color: '#167',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [tags.special(tags.variableName), tags.macroName],
|
||||||
|
color: '#256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: tags.definition(tags.propertyName),
|
||||||
|
color: '#00c',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: tags.compareOperator,
|
||||||
|
color: '#708',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: tags.comment,
|
||||||
|
color: '#940',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: tags.invalid,
|
||||||
|
color: '#f00',
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const defaultThemeSpec = {
|
const defaultThemeSpec = {
|
||||||
"&": {
|
'&': {
|
||||||
backgroundColor: "#FFF",
|
backgroundColor: '#FFF',
|
||||||
color: "#000",
|
color: '#000',
|
||||||
},
|
},
|
||||||
"&.cm-focused": {
|
'&.cm-focused': {
|
||||||
outline: "none",
|
outline: 'none',
|
||||||
},
|
},
|
||||||
".cm-line": {
|
'.cm-line': {
|
||||||
lineHeight: "1.6",
|
lineHeight: '1.6',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,7 +122,7 @@ export function getTheme(viewParentEl) {
|
|||||||
if (tagStyles.length) {
|
if (tagStyles.length) {
|
||||||
highlightStyle = HighlightStyle.define(tagStyles);
|
highlightStyle = HighlightStyle.define(tagStyles);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
window.$events.emitPublic(viewParentEl, 'library-cm6::configure-theme', eventData);
|
window.$events.emitPublic(viewParentEl, 'library-cm6::configure-theme', eventData);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {Compartment} from "@codemirror/state";
|
import {Compartment} from '@codemirror/state';
|
||||||
import {EditorView} from "@codemirror/view";
|
import {EditorView} from '@codemirror/view';
|
||||||
import {getLanguageExtension} from "./languages";
|
import {getLanguageExtension} from './languages';
|
||||||
|
|
||||||
const viewLangCompartments = new WeakMap();
|
const viewLangCompartments = new WeakMap();
|
||||||
|
|
||||||
@ -33,6 +33,6 @@ export async function updateViewLanguage(ev, modeSuggestion, content) {
|
|||||||
const language = await getLanguageExtension(modeSuggestion, content);
|
const language = await getLanguageExtension(modeSuggestion, content);
|
||||||
|
|
||||||
ev.dispatch({
|
ev.dispatch({
|
||||||
effects: compartment.reconfigure(language ? language : [])
|
effects: compartment.reconfigure(language || []),
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import {onChildEvent} from "../services/dom";
|
import {onChildEvent} from '../services/dom';
|
||||||
import {uniqueId} from "../services/util";
|
import {uniqueId} from '../services/util';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AddRemoveRows
|
* AddRemoveRows
|
||||||
@ -8,6 +8,7 @@ import {Component} from "./component";
|
|||||||
* Needs a model row to use when adding a new row.
|
* Needs a model row to use when adding a new row.
|
||||||
*/
|
*/
|
||||||
export class AddRemoveRows extends Component {
|
export class AddRemoveRows extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.modelRow = this.$refs.model;
|
this.modelRow = this.$refs.model;
|
||||||
this.addButton = this.$refs.add;
|
this.addButton = this.$refs.add;
|
||||||
@ -19,7 +20,7 @@ export class AddRemoveRows extends Component {
|
|||||||
setupListeners() {
|
setupListeners() {
|
||||||
this.addButton.addEventListener('click', this.add.bind(this));
|
this.addButton.addEventListener('click', this.add.bind(this));
|
||||||
|
|
||||||
onChildEvent(this.$el, this.removeSelector, 'click', (e) => {
|
onChildEvent(this.$el, this.removeSelector, 'click', e => {
|
||||||
const row = e.target.closest(this.rowSelector);
|
const row = e.target.closest(this.rowSelector);
|
||||||
row.remove();
|
row.remove();
|
||||||
});
|
});
|
||||||
@ -44,9 +45,10 @@ export class AddRemoveRows extends Component {
|
|||||||
*/
|
*/
|
||||||
setClonedInputNames(clone) {
|
setClonedInputNames(clone) {
|
||||||
const rowId = uniqueId();
|
const rowId = uniqueId();
|
||||||
const randRowIdElems = clone.querySelectorAll(`[name*="randrowid"]`);
|
const randRowIdElems = clone.querySelectorAll('[name*="randrowid"]');
|
||||||
for (const elem of randRowIdElems) {
|
for (const elem of randRowIdElems) {
|
||||||
elem.name = elem.name.split('randrowid').join(rowId);
|
elem.name = elem.name.split('randrowid').join(rowId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,8 @@
|
|||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class AjaxDeleteRow extends Component {
|
export class AjaxDeleteRow extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.row = this.$el;
|
this.row = this.$el;
|
||||||
this.url = this.$opts.url;
|
this.url = this.$opts.url;
|
||||||
@ -24,4 +25,5 @@ export class AjaxDeleteRow extends Component {
|
|||||||
this.row.style.pointerEvents = null;
|
this.row.style.pointerEvents = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import {onEnterPress, onSelect} from "../services/dom";
|
import {onEnterPress, onSelect} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ajax Form
|
* Ajax Form
|
||||||
@ -11,6 +11,7 @@ import {Component} from "./component";
|
|||||||
* otherwise will act as a fake form element.
|
* otherwise will act as a fake form element.
|
||||||
*/
|
*/
|
||||||
export class AjaxForm extends Component {
|
export class AjaxForm extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
this.responseContainer = this.container;
|
this.responseContainer = this.container;
|
||||||
@ -27,7 +28,6 @@ export class AjaxForm extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupListeners() {
|
setupListeners() {
|
||||||
|
|
||||||
if (this.container.tagName === 'FORM') {
|
if (this.container.tagName === 'FORM') {
|
||||||
this.container.addEventListener('submit', this.submitRealForm.bind(this));
|
this.container.addEventListener('submit', this.submitRealForm.bind(this));
|
||||||
return;
|
return;
|
||||||
@ -43,7 +43,7 @@ export class AjaxForm extends Component {
|
|||||||
|
|
||||||
submitFakeForm() {
|
submitFakeForm() {
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
const inputs = this.container.querySelectorAll(`[name]`);
|
const inputs = this.container.querySelectorAll('[name]');
|
||||||
for (const input of inputs) {
|
for (const input of inputs) {
|
||||||
fd.append(input.getAttribute('name'), input.value);
|
fd.append(input.getAttribute('name'), input.value);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attachments List
|
* Attachments List
|
||||||
@ -13,7 +13,7 @@ export class AttachmentsList extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupListeners() {
|
setupListeners() {
|
||||||
const isExpectedKey = (event) => event.key === 'Control' || event.key === 'Meta';
|
const isExpectedKey = event => event.key === 'Control' || event.key === 'Meta';
|
||||||
window.addEventListener('keydown', event => {
|
window.addEventListener('keydown', event => {
|
||||||
if (isExpectedKey(event)) {
|
if (isExpectedKey(event)) {
|
||||||
this.addOpenQueryToLinks();
|
this.addOpenQueryToLinks();
|
||||||
@ -30,7 +30,7 @@ export class AttachmentsList extends Component {
|
|||||||
const links = this.container.querySelectorAll('a.attachment-file');
|
const links = this.container.querySelectorAll('a.attachment-file');
|
||||||
for (const link of links) {
|
for (const link of links) {
|
||||||
if (link.href.split('?')[1] !== 'open=true') {
|
if (link.href.split('?')[1] !== 'open=true') {
|
||||||
link.href = link.href + '?open=true';
|
link.href += '?open=true';
|
||||||
link.setAttribute('target', '_blank');
|
link.setAttribute('target', '_blank');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,4 +43,5 @@ export class AttachmentsList extends Component {
|
|||||||
link.removeAttribute('target');
|
link.removeAttribute('target');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import {showLoading} from "../services/dom";
|
import {showLoading} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class Attachments extends Component {
|
export class Attachments extends Component {
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class AutoSubmit extends Component {
|
export class AutoSubmit extends Component {
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {escapeHtml} from "../services/util";
|
import {escapeHtml} from '../services/util';
|
||||||
import {onChildEvent} from "../services/dom";
|
import {onChildEvent} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
import {KeyboardNavigationHandler} from "../services/keyboard-navigation";
|
import {KeyboardNavigationHandler} from '../services/keyboard-navigation';
|
||||||
|
|
||||||
const ajaxCache = {};
|
const ajaxCache = {};
|
||||||
|
|
||||||
@ -9,6 +9,7 @@ const ajaxCache = {};
|
|||||||
* AutoSuggest
|
* AutoSuggest
|
||||||
*/
|
*/
|
||||||
export class AutoSuggest extends Component {
|
export class AutoSuggest extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.parent = this.$el.parentElement;
|
this.parent = this.$el.parentElement;
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
@ -67,9 +68,7 @@ export class AutoSuggest extends Component {
|
|||||||
const search = this.input.value.toLowerCase();
|
const search = this.input.value.toLowerCase();
|
||||||
const suggestions = await this.loadSuggestions(search, nameFilter);
|
const suggestions = await this.loadSuggestions(search, nameFilter);
|
||||||
|
|
||||||
const toShow = suggestions.filter(val => {
|
const toShow = suggestions.filter(val => search === '' || val.toLowerCase().startsWith(search)).slice(0, 10);
|
||||||
return search === '' || val.toLowerCase().startsWith(search);
|
|
||||||
}).slice(0, 10);
|
|
||||||
|
|
||||||
this.displaySuggestions(toShow);
|
this.displaySuggestions(toShow);
|
||||||
}
|
}
|
||||||
@ -126,4 +125,5 @@ export class AutoSuggest extends Component {
|
|||||||
this.hideSuggestions();
|
this.hideSuggestions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class BackToTop extends Component {
|
export class BackToTop extends Component {
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ export class BackToTop extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onPageScroll() {
|
onPageScroll() {
|
||||||
let scrollTopPos = document.documentElement.scrollTop || document.body.scrollTop || 0;
|
const scrollTopPos = document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||||
if (!this.showing && scrollTopPos > this.breakPoint) {
|
if (!this.showing && scrollTopPos > this.breakPoint) {
|
||||||
this.button.style.display = 'block';
|
this.button.style.display = 'block';
|
||||||
this.showing = true;
|
this.showing = true;
|
||||||
@ -35,15 +35,15 @@ export class BackToTop extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scrollToTop() {
|
scrollToTop() {
|
||||||
let targetTop = this.targetElem.getBoundingClientRect().top;
|
const targetTop = this.targetElem.getBoundingClientRect().top;
|
||||||
let scrollElem = document.documentElement.scrollTop ? document.documentElement : document.body;
|
const scrollElem = document.documentElement.scrollTop ? document.documentElement : document.body;
|
||||||
let duration = 300;
|
const duration = 300;
|
||||||
let start = Date.now();
|
const start = Date.now();
|
||||||
let scrollStart = this.targetElem.getBoundingClientRect().top;
|
const scrollStart = this.targetElem.getBoundingClientRect().top;
|
||||||
|
|
||||||
function setPos() {
|
function setPos() {
|
||||||
let percentComplete = (1-((Date.now() - start) / duration));
|
const percentComplete = (1 - ((Date.now() - start) / duration));
|
||||||
let target = Math.abs(percentComplete * scrollStart);
|
const target = Math.abs(percentComplete * scrollStart);
|
||||||
if (percentComplete > 0) {
|
if (percentComplete > 0) {
|
||||||
scrollElem.scrollTop = target;
|
scrollElem.scrollTop = target;
|
||||||
requestAnimationFrame(setPos.bind(this));
|
requestAnimationFrame(setPos.bind(this));
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
import Sortable, {MultiDrag} from "sortablejs";
|
import Sortable, {MultiDrag} from 'sortablejs';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
import {htmlToDom} from "../services/dom";
|
import {htmlToDom} from '../services/dom';
|
||||||
|
|
||||||
// Auto sort control
|
// Auto sort control
|
||||||
const sortOperations = {
|
const sortOperations = {
|
||||||
name: function(a, b) {
|
name(a, b) {
|
||||||
const aName = a.getAttribute('data-name').trim().toLowerCase();
|
const aName = a.getAttribute('data-name').trim().toLowerCase();
|
||||||
const bName = b.getAttribute('data-name').trim().toLowerCase();
|
const bName = b.getAttribute('data-name').trim().toLowerCase();
|
||||||
return aName.localeCompare(bName);
|
return aName.localeCompare(bName);
|
||||||
},
|
},
|
||||||
created: function(a, b) {
|
created(a, b) {
|
||||||
const aTime = Number(a.getAttribute('data-created'));
|
const aTime = Number(a.getAttribute('data-created'));
|
||||||
const bTime = Number(b.getAttribute('data-created'));
|
const bTime = Number(b.getAttribute('data-created'));
|
||||||
return bTime - aTime;
|
return bTime - aTime;
|
||||||
},
|
},
|
||||||
updated: function(a, b) {
|
updated(a, b) {
|
||||||
const aTime = Number(a.getAttribute('data-updated'));
|
const aTime = Number(a.getAttribute('data-updated'));
|
||||||
const bTime = Number(b.getAttribute('data-updated'));
|
const bTime = Number(b.getAttribute('data-updated'));
|
||||||
return bTime - aTime;
|
return bTime - aTime;
|
||||||
},
|
},
|
||||||
chaptersFirst: function(a, b) {
|
chaptersFirst(a, b) {
|
||||||
const aType = a.getAttribute('data-type');
|
const aType = a.getAttribute('data-type');
|
||||||
const bType = b.getAttribute('data-type');
|
const bType = b.getAttribute('data-type');
|
||||||
if (aType === bType) {
|
if (aType === bType) {
|
||||||
@ -27,7 +27,7 @@ const sortOperations = {
|
|||||||
}
|
}
|
||||||
return (aType === 'chapter' ? -1 : 1);
|
return (aType === 'chapter' ? -1 : 1);
|
||||||
},
|
},
|
||||||
chaptersLast: function(a, b) {
|
chaptersLast(a, b) {
|
||||||
const aType = a.getAttribute('data-type');
|
const aType = a.getAttribute('data-type');
|
||||||
const bType = b.getAttribute('data-type');
|
const bType = b.getAttribute('data-type');
|
||||||
if (aType === bType) {
|
if (aType === bType) {
|
||||||
@ -51,7 +51,7 @@ const moveActions = {
|
|||||||
run(elem, parent, book) {
|
run(elem, parent, book) {
|
||||||
const newSibling = elem.previousElementSibling || parent;
|
const newSibling = elem.previousElementSibling || parent;
|
||||||
newSibling.insertAdjacentElement('beforebegin', elem);
|
newSibling.insertAdjacentElement('beforebegin', elem);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
down: {
|
down: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -60,7 +60,7 @@ const moveActions = {
|
|||||||
run(elem, parent, book) {
|
run(elem, parent, book) {
|
||||||
const newSibling = elem.nextElementSibling || parent;
|
const newSibling = elem.nextElementSibling || parent;
|
||||||
newSibling.insertAdjacentElement('afterend', elem);
|
newSibling.insertAdjacentElement('afterend', elem);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
next_book: {
|
next_book: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -69,7 +69,7 @@ const moveActions = {
|
|||||||
run(elem, parent, book) {
|
run(elem, parent, book) {
|
||||||
const newList = book.nextElementSibling.querySelector('ul');
|
const newList = book.nextElementSibling.querySelector('ul');
|
||||||
newList.prepend(elem);
|
newList.prepend(elem);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
prev_book: {
|
prev_book: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -78,7 +78,7 @@ const moveActions = {
|
|||||||
run(elem, parent, book) {
|
run(elem, parent, book) {
|
||||||
const newList = book.previousElementSibling.querySelector('ul');
|
const newList = book.previousElementSibling.querySelector('ul');
|
||||||
newList.appendChild(elem);
|
newList.appendChild(elem);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
next_chapter: {
|
next_chapter: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -93,7 +93,7 @@ const moveActions = {
|
|||||||
const topItems = Array.from(topLevel.parentElement.children);
|
const topItems = Array.from(topLevel.parentElement.children);
|
||||||
const index = topItems.indexOf(topLevel);
|
const index = topItems.indexOf(topLevel);
|
||||||
return topItems.slice(index + 1).find(elem => elem.dataset.type === 'chapter');
|
return topItems.slice(index + 1).find(elem => elem.dataset.type === 'chapter');
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
prev_chapter: {
|
prev_chapter: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -108,7 +108,7 @@ const moveActions = {
|
|||||||
const topItems = Array.from(topLevel.parentElement.children);
|
const topItems = Array.from(topLevel.parentElement.children);
|
||||||
const index = topItems.indexOf(topLevel);
|
const index = topItems.indexOf(topLevel);
|
||||||
return topItems.slice(0, index).reverse().find(elem => elem.dataset.type === 'chapter');
|
return topItems.slice(0, index).reverse().find(elem => elem.dataset.type === 'chapter');
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
book_end: {
|
book_end: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -116,7 +116,7 @@ const moveActions = {
|
|||||||
},
|
},
|
||||||
run(elem, parent, book) {
|
run(elem, parent, book) {
|
||||||
book.querySelector('ul').append(elem);
|
book.querySelector('ul').append(elem);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
book_start: {
|
book_start: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -124,7 +124,7 @@ const moveActions = {
|
|||||||
},
|
},
|
||||||
run(elem, parent, book) {
|
run(elem, parent, book) {
|
||||||
book.querySelector('ul').prepend(elem);
|
book.querySelector('ul').prepend(elem);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
before_chapter: {
|
before_chapter: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -132,7 +132,7 @@ const moveActions = {
|
|||||||
},
|
},
|
||||||
run(elem, parent, book) {
|
run(elem, parent, book) {
|
||||||
parent.insertAdjacentElement('beforebegin', elem);
|
parent.insertAdjacentElement('beforebegin', elem);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
after_chapter: {
|
after_chapter: {
|
||||||
active(elem, parent, book) {
|
active(elem, parent, book) {
|
||||||
@ -140,7 +140,7 @@ const moveActions = {
|
|||||||
},
|
},
|
||||||
run(elem, parent, book) {
|
run(elem, parent, book) {
|
||||||
parent.insertAdjacentElement('afterend', elem);
|
parent.insertAdjacentElement('afterend', elem);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -197,11 +197,11 @@ export class BookSort extends Component {
|
|||||||
let sortFunction = sortOperations[sort];
|
let sortFunction = sortOperations[sort];
|
||||||
if (reverse && reversibleTypes.includes(sort)) {
|
if (reverse && reversibleTypes.includes(sort)) {
|
||||||
sortFunction = function(a, b) {
|
sortFunction = function(a, b) {
|
||||||
return 0 - sortOperations[sort](a, b)
|
return 0 - sortOperations[sort](a, b);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let list of sortLists) {
|
for (const list of sortLists) {
|
||||||
const directItems = Array.from(list.children).filter(child => child.matches('li'));
|
const directItems = Array.from(list.children).filter(child => child.matches('li'));
|
||||||
directItems.sort(sortFunction).forEach(sortedItem => {
|
directItems.sort(sortFunction).forEach(sortedItem => {
|
||||||
list.appendChild(sortedItem);
|
list.appendChild(sortedItem);
|
||||||
@ -221,7 +221,7 @@ export class BookSort extends Component {
|
|||||||
const alreadyAdded = this.container.querySelector(`[data-type="book"][data-id="${entityInfo.id}"]`) !== null;
|
const alreadyAdded = this.container.querySelector(`[data-type="book"][data-id="${entityInfo.id}"]`) !== null;
|
||||||
if (alreadyAdded) return;
|
if (alreadyAdded) return;
|
||||||
|
|
||||||
const entitySortItemUrl = entityInfo.link + '/sort-item';
|
const entitySortItemUrl = `${entityInfo.link}/sort-item`;
|
||||||
window.$http.get(entitySortItemUrl).then(resp => {
|
window.$http.get(entitySortItemUrl).then(resp => {
|
||||||
const newBookContainer = htmlToDom(resp.data);
|
const newBookContainer = htmlToDom(resp.data);
|
||||||
this.sortContainer.append(newBookContainer);
|
this.sortContainer.append(newBookContainer);
|
||||||
@ -249,9 +249,9 @@ export class BookSort extends Component {
|
|||||||
const chapterGroupConfig = {
|
const chapterGroupConfig = {
|
||||||
name: 'chapter',
|
name: 'chapter',
|
||||||
pull: ['book', 'chapter'],
|
pull: ['book', 'chapter'],
|
||||||
put: function(toList, fromList, draggedElem) {
|
put(toList, fromList, draggedElem) {
|
||||||
return draggedElem.getAttribute('data-type') === 'page';
|
return draggedElem.getAttribute('data-type') === 'page';
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const sortElem of sortElems) {
|
for (const sortElem of sortElems) {
|
||||||
@ -260,8 +260,8 @@ export class BookSort extends Component {
|
|||||||
animation: 150,
|
animation: 150,
|
||||||
fallbackOnBody: true,
|
fallbackOnBody: true,
|
||||||
swapThreshold: 0.65,
|
swapThreshold: 0.65,
|
||||||
onSort: (event) => {
|
onSort: event => {
|
||||||
this.ensureNoNestedChapters()
|
this.ensureNoNestedChapters();
|
||||||
this.updateMapInput();
|
this.updateMapInput();
|
||||||
this.updateMoveActionStateForAll();
|
this.updateMoveActionStateForAll();
|
||||||
},
|
},
|
||||||
@ -304,7 +304,7 @@ export class BookSort extends Component {
|
|||||||
const entityMap = [];
|
const entityMap = [];
|
||||||
const lists = this.container.querySelectorAll('.sort-list');
|
const lists = this.container.querySelectorAll('.sort-list');
|
||||||
|
|
||||||
for (let list of lists) {
|
for (const list of lists) {
|
||||||
const bookId = list.closest('[data-type="book"]').getAttribute('data-id');
|
const bookId = list.closest('[data-type="book"]').getAttribute('data-id');
|
||||||
const directChildren = Array.from(list.children)
|
const directChildren = Array.from(list.children)
|
||||||
.filter(elem => elem.matches('[data-type="page"], [data-type="chapter"]'));
|
.filter(elem => elem.matches('[data-type="page"], [data-type="chapter"]'));
|
||||||
@ -332,9 +332,9 @@ export class BookSort extends Component {
|
|||||||
entityMap.push({
|
entityMap.push({
|
||||||
id: childId,
|
id: childId,
|
||||||
sort: index,
|
sort: index,
|
||||||
parentChapter: parentChapter,
|
parentChapter,
|
||||||
type: type,
|
type,
|
||||||
book: bookId
|
book: bookId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const subPages = childElem.querySelectorAll('[data-type="page"]');
|
const subPages = childElem.querySelectorAll('[data-type="page"]');
|
||||||
@ -344,7 +344,7 @@ export class BookSort extends Component {
|
|||||||
sort: i,
|
sort: i,
|
||||||
parentChapter: childId,
|
parentChapter: childId,
|
||||||
type: 'page',
|
type: 'page',
|
||||||
book: bookId
|
book: bookId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,4 +383,5 @@ export class BookSort extends Component {
|
|||||||
this.updateMoveActionState(item);
|
this.updateMoveActionState(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import {slideUp, slideDown} from "../services/animations";
|
import {slideUp, slideDown} from '../services/animations';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class ChapterContents extends Component {
|
export class ChapterContents extends Component {
|
||||||
|
|
||||||
@ -29,4 +29,5 @@ export class ChapterContents extends Component {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.isOpen ? this.close() : this.open();
|
this.isOpen ? this.close() : this.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import {onChildEvent, onEnterPress, onSelect} from "../services/dom";
|
import {onChildEvent, onEnterPress, onSelect} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
|
|
||||||
export class CodeEditor extends Component {
|
export class CodeEditor extends Component {
|
||||||
|
|
||||||
@ -10,7 +9,9 @@ export class CodeEditor extends Component {
|
|||||||
editor = null;
|
editor = null;
|
||||||
|
|
||||||
callback = null;
|
callback = null;
|
||||||
|
|
||||||
history = {};
|
history = {};
|
||||||
|
|
||||||
historyKey = 'code_history';
|
historyKey = 'code_history';
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
@ -77,13 +78,13 @@ export class CodeEditor extends Component {
|
|||||||
button.setAttribute('data-favourite', isFavorite ? 'true' : 'false');
|
button.setAttribute('data-favourite', isFavorite ? 'true' : 'false');
|
||||||
|
|
||||||
window.$http.patch('/preferences/update-code-language-favourite', {
|
window.$http.patch('/preferences/update-code-language-favourite', {
|
||||||
language: language,
|
language,
|
||||||
active: isFavorite
|
active: isFavorite,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.sortLanguageList();
|
this.sortLanguageList();
|
||||||
if (isFavorite) {
|
if (isFavorite) {
|
||||||
button.scrollIntoView({block: "center", behavior: "smooth"});
|
button.scrollIntoView({block: 'center', behavior: 'smooth'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -95,7 +96,7 @@ export class CodeEditor extends Component {
|
|||||||
|
|
||||||
if (aFav && !bFav) {
|
if (aFav && !bFav) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (bFav && !aFav) {
|
} if (bFav && !aFav) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +134,7 @@ export class CodeEditor extends Component {
|
|||||||
this.getPopup().show(() => {
|
this.getPopup().show(() => {
|
||||||
this.editor.focus();
|
this.editor.focus();
|
||||||
}, () => {
|
}, () => {
|
||||||
this.addHistory()
|
this.addHistory();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +163,7 @@ export class CodeEditor extends Component {
|
|||||||
const isMatch = inputLang === lang;
|
const isMatch = inputLang === lang;
|
||||||
link.classList.toggle('active', isMatch);
|
link.classList.toggle('active', isMatch);
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
link.scrollIntoView({block: "center", behavior: "smooth"});
|
link.scrollIntoView({block: 'center', behavior: 'smooth'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class CodeHighlighter extends Component{
|
export class CodeHighlighter extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const container = this.$el;
|
const container = this.$el;
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
* A simple component to render a code editor within the textarea
|
* A simple component to render a code editor within the textarea
|
||||||
* this exists upon.
|
* this exists upon.
|
||||||
*/
|
*/
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class CodeTextarea extends Component {
|
export class CodeTextarea extends Component {
|
||||||
|
|
||||||
async setup() {
|
async setup() {
|
||||||
const mode = this.$opts.mode;
|
const {mode} = this.$opts;
|
||||||
const Code = await window.importVersioned('code');
|
const Code = await window.importVersioned('code');
|
||||||
Code.inlineEditor(this.$el, mode);
|
Code.inlineEditor(this.$el, mode);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {slideDown, slideUp} from "../services/animations";
|
import {slideDown, slideUp} from '../services/animations';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collapsible
|
* Collapsible
|
||||||
|
@ -51,8 +51,9 @@ export class Component {
|
|||||||
const componentName = this.$name;
|
const componentName = this.$name;
|
||||||
const event = new CustomEvent(`${componentName}-${eventName}`, {
|
const event = new CustomEvent(`${componentName}-${eventName}`, {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
detail: data
|
detail: data,
|
||||||
});
|
});
|
||||||
this.$el.dispatchEvent(event);
|
this.$el.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom equivalent of window.confirm() using our popup component.
|
* Custom equivalent of window.confirm() using our popup component.
|
||||||
@ -42,7 +42,7 @@ export class ConfirmDialog extends Component {
|
|||||||
*/
|
*/
|
||||||
sendResult(result) {
|
sendResult(result) {
|
||||||
if (this.res) {
|
if (this.res) {
|
||||||
this.res(result)
|
this.res(result);
|
||||||
this.res = null;
|
this.res = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class CustomCheckbox extends Component {
|
export class CustomCheckbox extends Component {
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class DetailsHighlighter extends Component {
|
export class DetailsHighlighter extends Component {
|
||||||
|
|
||||||
@ -19,4 +19,5 @@ export class DetailsHighlighter extends Component {
|
|||||||
}
|
}
|
||||||
this.dealtWith = true;
|
this.dealtWith = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import {debounce} from "../services/util";
|
import {debounce} from '../services/util';
|
||||||
import {transitionHeight} from "../services/animations";
|
import {transitionHeight} from '../services/animations';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class DropdownSearch extends Component {
|
export class DropdownSearch extends Component {
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ export class DropdownSearch extends Component {
|
|||||||
|
|
||||||
runLocalSearch(searchTerm) {
|
runLocalSearch(searchTerm) {
|
||||||
const listItems = this.listContainerElem.querySelectorAll(this.localSearchSelector);
|
const listItems = this.listContainerElem.querySelectorAll(this.localSearchSelector);
|
||||||
for (let listItem of listItems) {
|
for (const listItem of listItems) {
|
||||||
const match = !searchTerm || listItem.textContent.toLowerCase().includes(searchTerm);
|
const match = !searchTerm || listItem.textContent.toLowerCase().includes(searchTerm);
|
||||||
listItem.style.display = match ? 'flex' : 'none';
|
listItem.style.display = match ? 'flex' : 'none';
|
||||||
listItem.classList.toggle('hidden', !match);
|
listItem.classList.toggle('hidden', !match);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from '../services/dom';
|
||||||
import {KeyboardNavigationHandler} from "../services/keyboard-navigation";
|
import {KeyboardNavigationHandler} from '../services/keyboard-navigation';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dropdown
|
* Dropdown
|
||||||
@ -76,7 +76,7 @@ export class Dropdown extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hideAll() {
|
hideAll() {
|
||||||
for (let dropdown of window.$components.get('dropdown')) {
|
for (const dropdown of window.$components.get('dropdown')) {
|
||||||
dropdown.hide();
|
dropdown.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,13 +100,13 @@ export class Dropdown extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupListeners() {
|
setupListeners() {
|
||||||
const keyboardNavHandler = new KeyboardNavigationHandler(this.container, (event) => {
|
const keyboardNavHandler = new KeyboardNavigationHandler(this.container, event => {
|
||||||
this.hide();
|
this.hide();
|
||||||
this.toggle.focus();
|
this.toggle.focus();
|
||||||
if (!this.bubbleEscapes) {
|
if (!this.bubbleEscapes) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
}, (event) => {
|
}, event => {
|
||||||
if (event.target.nodeName === 'INPUT') {
|
if (event.target.nodeName === 'INPUT') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import DropZoneLib from "dropzone";
|
import DropZoneLib from 'dropzone';
|
||||||
import {fadeOut} from "../services/animations";
|
import {fadeOut} from '../services/animations';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class Dropzone extends Component {
|
export class Dropzone extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
this.url = this.$opts.url;
|
this.url = this.$opts.url;
|
||||||
@ -25,19 +26,18 @@ export class Dropzone extends Component {
|
|||||||
this.dz.on('sending', _this.onSending.bind(_this));
|
this.dz.on('sending', _this.onSending.bind(_this));
|
||||||
this.dz.on('success', _this.onSuccess.bind(_this));
|
this.dz.on('success', _this.onSuccess.bind(_this));
|
||||||
this.dz.on('error', _this.onError.bind(_this));
|
this.dz.on('error', _this.onError.bind(_this));
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onSending(file, xhr, data) {
|
onSending(file, xhr, data) {
|
||||||
|
|
||||||
const token = window.document.querySelector('meta[name=token]').getAttribute('content');
|
const token = window.document.querySelector('meta[name=token]').getAttribute('content');
|
||||||
data.append('_token', token);
|
data.append('_token', token);
|
||||||
|
|
||||||
xhr.ontimeout = (e) => {
|
xhr.ontimeout = e => {
|
||||||
this.dz.emit('complete', file);
|
this.dz.emit('complete', file);
|
||||||
this.dz.emit('error', file, this.timeoutMessage);
|
this.dz.emit('error', file, this.timeoutMessage);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onSuccess(file, data) {
|
onSuccess(file, data) {
|
||||||
@ -55,10 +55,10 @@ export class Dropzone extends Component {
|
|||||||
onError(file, errorMessage, xhr) {
|
onError(file, errorMessage, xhr) {
|
||||||
this.$emit('error', {file, errorMessage, xhr});
|
this.$emit('error', {file, errorMessage, xhr});
|
||||||
|
|
||||||
const setMessage = (message) => {
|
const setMessage = message => {
|
||||||
const messsageEl = file.previewElement.querySelector('[data-dz-errormessage]');
|
const messsageEl = file.previewElement.querySelector('[data-dz-errormessage]');
|
||||||
messsageEl.textContent = message;
|
messsageEl.textContent = message;
|
||||||
}
|
};
|
||||||
|
|
||||||
if (xhr && xhr.status === 413) {
|
if (xhr && xhr.status === 413) {
|
||||||
setMessage(this.uploadLimitMessage);
|
setMessage(this.uploadLimitMessage);
|
||||||
@ -70,4 +70,5 @@ export class Dropzone extends Component {
|
|||||||
removeAll() {
|
removeAll() {
|
||||||
this.dz.removeAllFiles(true);
|
this.dz.removeAllFiles(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class EditorToolbox extends Component {
|
export class EditorToolbox extends Component {
|
||||||
|
|
||||||
@ -35,7 +35,6 @@ export class EditorToolbox extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setActiveTab(tabName, openToolbox = false) {
|
setActiveTab(tabName, openToolbox = false) {
|
||||||
|
|
||||||
// Set button visibility
|
// Set button visibility
|
||||||
for (const button of this.buttons) {
|
for (const button of this.buttons) {
|
||||||
button.classList.remove('active');
|
button.classList.remove('active');
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {htmlToDom} from "../services/dom";
|
import {htmlToDom} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class EntityPermissions extends Component {
|
export class EntityPermissions extends Component {
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ export class EntityPermissions extends Component {
|
|||||||
this.container.addEventListener('click', event => {
|
this.container.addEventListener('click', event => {
|
||||||
const button = event.target.closest('button');
|
const button = event.target.closest('button');
|
||||||
if (button && button.dataset.roleId) {
|
if (button && button.dataset.roleId) {
|
||||||
this.removeRowOnButtonClick(button)
|
this.removeRowOnButtonClick(button);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -61,8 +61,8 @@ export class EntityPermissions extends Component {
|
|||||||
|
|
||||||
removeRowOnButtonClick(button) {
|
removeRowOnButtonClick(button) {
|
||||||
const row = button.closest('.item-list-row');
|
const row = button.closest('.item-list-row');
|
||||||
const roleId = button.dataset.roleId;
|
const {roleId} = button.dataset;
|
||||||
const roleName = button.dataset.roleName;
|
const {roleName} = button.dataset;
|
||||||
|
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.value = roleId;
|
option.value = roleId;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class EntitySearch extends Component {
|
export class EntitySearch extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.entityId = this.$opts.entityId;
|
this.entityId = this.$opts.entityId;
|
||||||
this.entityType = this.$opts.entityType;
|
this.entityType = this.$opts.entityType;
|
||||||
@ -51,4 +52,5 @@ export class EntitySearch extends Component {
|
|||||||
this.loadingBlock.classList.add('hidden');
|
this.loadingBlock.classList.add('hidden');
|
||||||
this.searchInput.value = '';
|
this.searchInput.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class EntitySelectorPopup extends Component {
|
export class EntitySelectorPopup extends Component {
|
||||||
|
|
||||||
@ -57,4 +57,5 @@ export class EntitySelectorPopup extends Component {
|
|||||||
this.getSelector().reset();
|
this.getSelector().reset();
|
||||||
if (this.callback && entity) this.callback(entity);
|
if (this.callback && entity) this.callback(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import {onChildEvent} from "../services/dom";
|
import {onChildEvent} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity Selector
|
* Entity Selector
|
||||||
@ -65,13 +65,13 @@ export class EntitySelector extends Component {
|
|||||||
if (e.code === 'ArrowDown') {
|
if (e.code === 'ArrowDown') {
|
||||||
this.focusAdjacent(true);
|
this.focusAdjacent(true);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
focusAdjacent(forward = true) {
|
focusAdjacent(forward = true) {
|
||||||
const items = Array.from(this.resultsContainer.querySelectorAll('[data-entity-type]'));
|
const items = Array.from(this.resultsContainer.querySelectorAll('[data-entity-type]'));
|
||||||
const selectedIndex = items.indexOf(document.activeElement);
|
const selectedIndex = items.indexOf(document.activeElement);
|
||||||
const newItem = items[selectedIndex+ (forward ? 1 : -1)] || items[0];
|
const newItem = items[selectedIndex + (forward ? 1 : -1)] || items[0];
|
||||||
if (newItem) {
|
if (newItem) {
|
||||||
newItem.focus();
|
newItem.focus();
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ export class EntitySelector extends Component {
|
|||||||
window.$http.get(this.searchUrl()).then(resp => {
|
window.$http.get(this.searchUrl()).then(resp => {
|
||||||
this.resultsContainer.innerHTML = resp.data;
|
this.resultsContainer.innerHTML = resp.data;
|
||||||
this.hideLoading();
|
this.hideLoading();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
searchUrl() {
|
searchUrl() {
|
||||||
@ -144,13 +144,13 @@ export class EntitySelector extends Component {
|
|||||||
|
|
||||||
const link = item.getAttribute('href');
|
const link = item.getAttribute('href');
|
||||||
const name = item.querySelector('.entity-list-item-name').textContent;
|
const name = item.querySelector('.entity-list-item-name').textContent;
|
||||||
const data = {id: Number(id), name: name, link: link};
|
const data = {id: Number(id), name, link};
|
||||||
|
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
item.classList.add('selected');
|
item.classList.add('selected');
|
||||||
this.selectedItemData = data;
|
this.selectedItemData = data;
|
||||||
} else {
|
} else {
|
||||||
window.$events.emit('entity-select-change', null)
|
window.$events.emit('entity-select-change', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDblClick && !isSelected) return;
|
if (!isDblClick && !isSelected) return;
|
||||||
@ -159,7 +159,7 @@ export class EntitySelector extends Component {
|
|||||||
this.confirmSelection(data);
|
this.confirmSelection(data);
|
||||||
}
|
}
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
window.$events.emit('entity-select-change', data)
|
window.$events.emit('entity-select-change', data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventEmitSelect
|
* EventEmitSelect
|
||||||
@ -12,12 +12,12 @@ import {Component} from "./component";
|
|||||||
* All options will be set as the "detail" of the event with
|
* All options will be set as the "detail" of the event with
|
||||||
* their values included.
|
* their values included.
|
||||||
*/
|
*/
|
||||||
export class EventEmitSelect extends Component{
|
export class EventEmitSelect extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
this.name = this.$opts.name;
|
this.name = this.$opts.name;
|
||||||
|
|
||||||
|
|
||||||
onSelect(this.$el, () => {
|
onSelect(this.$el, () => {
|
||||||
this.$emit(this.name, this.$opts);
|
this.$emit(this.name, this.$opts);
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {slideUp, slideDown} from "../services/animations";
|
import {slideUp, slideDown} from '../services/animations';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class ExpandToggle extends Component {
|
export class ExpandToggle extends Component {
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ export class ExpandToggle extends Component {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const matchingElems = document.querySelectorAll(this.targetSelector);
|
const matchingElems = document.querySelectorAll(this.targetSelector);
|
||||||
for (let match of matchingElems) {
|
for (const match of matchingElems) {
|
||||||
this.isOpen ? this.close(match) : this.open(match);
|
this.isOpen ? this.close(match) : this.open(match);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ export class ExpandToggle extends Component {
|
|||||||
|
|
||||||
updateSystemAjax(isOpen) {
|
updateSystemAjax(isOpen) {
|
||||||
window.$http.patch(this.updateEndpoint, {
|
window.$http.patch(this.updateEndpoint, {
|
||||||
expand: isOpen ? 'true' : 'false'
|
expand: isOpen ? 'true' : 'false',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {htmlToDom} from "../services/dom";
|
import {htmlToDom} from '../services/dom';
|
||||||
import {debounce} from "../services/util";
|
import {debounce} from '../services/util';
|
||||||
import {KeyboardNavigationHandler} from "../services/keyboard-navigation";
|
import {KeyboardNavigationHandler} from '../services/keyboard-navigation';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global (header) search box handling.
|
* Global (header) search box handling.
|
||||||
@ -25,7 +25,7 @@ export class GlobalSearch extends Component {
|
|||||||
|
|
||||||
// Handle search input changes
|
// Handle search input changes
|
||||||
this.input.addEventListener('input', () => {
|
this.input.addEventListener('input', () => {
|
||||||
const value = this.input.value;
|
const {value} = this.input;
|
||||||
if (value.length > 0) {
|
if (value.length > 0) {
|
||||||
this.loadingWrap.style.display = 'block';
|
this.loadingWrap.style.display = 'block';
|
||||||
this.suggestionResultsWrap.style.opacity = '0.5';
|
this.suggestionResultsWrap.style.opacity = '0.5';
|
||||||
@ -71,7 +71,7 @@ export class GlobalSearch extends Component {
|
|||||||
this.container.classList.add('search-active');
|
this.container.classList.add('search-active');
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
this.suggestions.classList.add('search-suggestions-animation');
|
this.suggestions.classList.add('search-suggestions-animation');
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
hideSuggestions() {
|
hideSuggestions() {
|
||||||
@ -79,4 +79,5 @@ export class GlobalSearch extends Component {
|
|||||||
this.suggestions.classList.remove('search-suggestions-animation');
|
this.suggestions.classList.remove('search-suggestions-animation');
|
||||||
this.suggestionResultsWrap.innerHTML = '';
|
this.suggestionResultsWrap.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class HeaderMobileToggle extends Component {
|
export class HeaderMobileToggle extends Component {
|
||||||
|
|
||||||
@ -19,10 +19,10 @@ export class HeaderMobileToggle extends Component {
|
|||||||
this.toggleButton.setAttribute('aria-expanded', this.open ? 'true' : 'false');
|
this.toggleButton.setAttribute('aria-expanded', this.open ? 'true' : 'false');
|
||||||
if (this.open) {
|
if (this.open) {
|
||||||
this.elem.addEventListener('keydown', this.onKeyDown);
|
this.elem.addEventListener('keydown', this.onKeyDown);
|
||||||
window.addEventListener('click', this.onWindowClick)
|
window.addEventListener('click', this.onWindowClick);
|
||||||
} else {
|
} else {
|
||||||
this.elem.removeEventListener('keydown', this.onKeyDown);
|
this.elem.removeEventListener('keydown', this.onKeyDown);
|
||||||
window.removeEventListener('click', this.onWindowClick)
|
window.removeEventListener('click', this.onWindowClick);
|
||||||
}
|
}
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import {onChildEvent, onSelect, removeLoading, showLoading} from "../services/dom";
|
import {
|
||||||
import {Component} from "./component";
|
onChildEvent, onSelect, removeLoading, showLoading,
|
||||||
|
} from '../services/dom';
|
||||||
|
import {Component} from './component';
|
||||||
|
|
||||||
export class ImageManager extends Component {
|
export class ImageManager extends Component {
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class ImagePicker extends Component {
|
export class ImagePicker extends Component {
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ export class ImagePicker extends Component {
|
|||||||
this.removeInput.setAttribute('disabled', 'disabled');
|
this.removeInput.setAttribute('disabled', 'disabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let file of this.imageInput.files) {
|
for (const file of this.imageInput.files) {
|
||||||
this.imageElem.src = window.URL.createObjectURL(file);
|
this.imageElem.src = window.URL.createObjectURL(file);
|
||||||
}
|
}
|
||||||
this.imageElem.classList.remove('none');
|
this.imageElem.classList.remove('none');
|
||||||
|
@ -1,59 +1,59 @@
|
|||||||
export {AddRemoveRows} from "./add-remove-rows.js"
|
export {AddRemoveRows} from './add-remove-rows.js';
|
||||||
export {AjaxDeleteRow} from "./ajax-delete-row.js"
|
export {AjaxDeleteRow} from './ajax-delete-row.js';
|
||||||
export {AjaxForm} from "./ajax-form.js"
|
export {AjaxForm} from './ajax-form.js';
|
||||||
export {Attachments} from "./attachments.js"
|
export {Attachments} from './attachments.js';
|
||||||
export {AttachmentsList} from "./attachments-list.js"
|
export {AttachmentsList} from './attachments-list.js';
|
||||||
export {AutoSuggest} from "./auto-suggest.js"
|
export {AutoSuggest} from './auto-suggest.js';
|
||||||
export {AutoSubmit} from "./auto-submit.js"
|
export {AutoSubmit} from './auto-submit.js';
|
||||||
export {BackToTop} from "./back-to-top.js"
|
export {BackToTop} from './back-to-top.js';
|
||||||
export {BookSort} from "./book-sort.js"
|
export {BookSort} from './book-sort.js';
|
||||||
export {ChapterContents} from "./chapter-contents.js"
|
export {ChapterContents} from './chapter-contents.js';
|
||||||
export {CodeEditor} from "./code-editor.js"
|
export {CodeEditor} from './code-editor.js';
|
||||||
export {CodeHighlighter} from "./code-highlighter.js"
|
export {CodeHighlighter} from './code-highlighter.js';
|
||||||
export {CodeTextarea} from "./code-textarea.js"
|
export {CodeTextarea} from './code-textarea.js';
|
||||||
export {Collapsible} from "./collapsible.js"
|
export {Collapsible} from './collapsible.js';
|
||||||
export {ConfirmDialog} from "./confirm-dialog"
|
export {ConfirmDialog} from './confirm-dialog';
|
||||||
export {CustomCheckbox} from "./custom-checkbox.js"
|
export {CustomCheckbox} from './custom-checkbox.js';
|
||||||
export {DetailsHighlighter} from "./details-highlighter.js"
|
export {DetailsHighlighter} from './details-highlighter.js';
|
||||||
export {Dropdown} from "./dropdown.js"
|
export {Dropdown} from './dropdown.js';
|
||||||
export {DropdownSearch} from "./dropdown-search.js"
|
export {DropdownSearch} from './dropdown-search.js';
|
||||||
export {Dropzone} from "./dropzone.js"
|
export {Dropzone} from './dropzone.js';
|
||||||
export {EditorToolbox} from "./editor-toolbox.js"
|
export {EditorToolbox} from './editor-toolbox.js';
|
||||||
export {EntityPermissions} from "./entity-permissions"
|
export {EntityPermissions} from './entity-permissions';
|
||||||
export {EntitySearch} from "./entity-search.js"
|
export {EntitySearch} from './entity-search.js';
|
||||||
export {EntitySelector} from "./entity-selector.js"
|
export {EntitySelector} from './entity-selector.js';
|
||||||
export {EntitySelectorPopup} from "./entity-selector-popup.js"
|
export {EntitySelectorPopup} from './entity-selector-popup.js';
|
||||||
export {EventEmitSelect} from "./event-emit-select.js"
|
export {EventEmitSelect} from './event-emit-select.js';
|
||||||
export {ExpandToggle} from "./expand-toggle.js"
|
export {ExpandToggle} from './expand-toggle.js';
|
||||||
export {GlobalSearch} from "./global-search.js"
|
export {GlobalSearch} from './global-search.js';
|
||||||
export {HeaderMobileToggle} from "./header-mobile-toggle.js"
|
export {HeaderMobileToggle} from './header-mobile-toggle.js';
|
||||||
export {ImageManager} from "./image-manager.js"
|
export {ImageManager} from './image-manager.js';
|
||||||
export {ImagePicker} from "./image-picker.js"
|
export {ImagePicker} from './image-picker.js';
|
||||||
export {ListSortControl} from "./list-sort-control.js"
|
export {ListSortControl} from './list-sort-control.js';
|
||||||
export {MarkdownEditor} from "./markdown-editor.js"
|
export {MarkdownEditor} from './markdown-editor.js';
|
||||||
export {NewUserPassword} from "./new-user-password.js"
|
export {NewUserPassword} from './new-user-password.js';
|
||||||
export {Notification} from "./notification.js"
|
export {Notification} from './notification.js';
|
||||||
export {OptionalInput} from "./optional-input.js"
|
export {OptionalInput} from './optional-input.js';
|
||||||
export {PageComments} from "./page-comments.js"
|
export {PageComments} from './page-comments.js';
|
||||||
export {PageDisplay} from "./page-display.js"
|
export {PageDisplay} from './page-display.js';
|
||||||
export {PageEditor} from "./page-editor.js"
|
export {PageEditor} from './page-editor.js';
|
||||||
export {PagePicker} from "./page-picker.js"
|
export {PagePicker} from './page-picker.js';
|
||||||
export {PermissionsTable} from "./permissions-table.js"
|
export {PermissionsTable} from './permissions-table.js';
|
||||||
export {Pointer} from "./pointer.js"
|
export {Pointer} from './pointer.js';
|
||||||
export {Popup} from "./popup.js"
|
export {Popup} from './popup.js';
|
||||||
export {SettingAppColorScheme} from "./setting-app-color-scheme.js"
|
export {SettingAppColorScheme} from './setting-app-color-scheme.js';
|
||||||
export {SettingColorPicker} from "./setting-color-picker.js"
|
export {SettingColorPicker} from './setting-color-picker.js';
|
||||||
export {SettingHomepageControl} from "./setting-homepage-control.js"
|
export {SettingHomepageControl} from './setting-homepage-control.js';
|
||||||
export {ShelfSort} from "./shelf-sort.js"
|
export {ShelfSort} from './shelf-sort.js';
|
||||||
export {Shortcuts} from "./shortcuts"
|
export {Shortcuts} from './shortcuts';
|
||||||
export {ShortcutInput} from "./shortcut-input"
|
export {ShortcutInput} from './shortcut-input';
|
||||||
export {SortableList} from "./sortable-list.js"
|
export {SortableList} from './sortable-list.js';
|
||||||
export {SubmitOnChange} from "./submit-on-change.js"
|
export {SubmitOnChange} from './submit-on-change.js';
|
||||||
export {Tabs} from "./tabs.js"
|
export {Tabs} from './tabs.js';
|
||||||
export {TagManager} from "./tag-manager.js"
|
export {TagManager} from './tag-manager.js';
|
||||||
export {TemplateManager} from "./template-manager.js"
|
export {TemplateManager} from './template-manager.js';
|
||||||
export {ToggleSwitch} from "./toggle-switch.js"
|
export {ToggleSwitch} from './toggle-switch.js';
|
||||||
export {TriLayout} from "./tri-layout.js"
|
export {TriLayout} from './tri-layout.js';
|
||||||
export {UserSelect} from "./user-select.js"
|
export {UserSelect} from './user-select.js';
|
||||||
export {WebhookEvents} from "./webhook-events"
|
export {WebhookEvents} from './webhook-events';
|
||||||
export {WysiwygEditor} from "./wysiwyg-editor.js"
|
export {WysiwygEditor} from './wysiwyg-editor.js';
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* ListSortControl
|
* ListSortControl
|
||||||
* Manages the logic for the control which provides list sorting options.
|
* Manages the logic for the control which provides list sorting options.
|
||||||
*/
|
*/
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class ListSortControl extends Component {
|
export class ListSortControl extends Component {
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
import {init as initEditor} from "../markdown/editor";
|
import {init as initEditor} from '../markdown/editor';
|
||||||
|
|
||||||
export class MarkdownEditor extends Component {
|
export class MarkdownEditor extends Component {
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ export class MarkdownEditor extends Component {
|
|||||||
this.divider = this.$refs.divider;
|
this.divider = this.$refs.divider;
|
||||||
this.displayWrap = this.$refs.displayWrap;
|
this.displayWrap = this.$refs.displayWrap;
|
||||||
|
|
||||||
const settingContainer = this.$refs.settingContainer;
|
const {settingContainer} = this.$refs;
|
||||||
const settingInputs = settingContainer.querySelectorAll('input[type="checkbox"]');
|
const settingInputs = settingContainer.querySelectorAll('input[type="checkbox"]');
|
||||||
|
|
||||||
this.editor = null;
|
this.editor = null;
|
||||||
@ -49,10 +49,9 @@ export class MarkdownEditor extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupListeners() {
|
setupListeners() {
|
||||||
|
|
||||||
// Button actions
|
// Button actions
|
||||||
this.elem.addEventListener('click', event => {
|
this.elem.addEventListener('click', event => {
|
||||||
let button = event.target.closest('button[data-action]');
|
const button = event.target.closest('button[data-action]');
|
||||||
if (button === null) return;
|
if (button === null) return;
|
||||||
|
|
||||||
const action = button.getAttribute('data-action');
|
const action = button.getAttribute('data-action');
|
||||||
@ -85,13 +84,13 @@ export class MarkdownEditor extends Component {
|
|||||||
handleDividerDrag() {
|
handleDividerDrag() {
|
||||||
this.divider.addEventListener('pointerdown', event => {
|
this.divider.addEventListener('pointerdown', event => {
|
||||||
const wrapRect = this.elem.getBoundingClientRect();
|
const wrapRect = this.elem.getBoundingClientRect();
|
||||||
const moveListener = (event) => {
|
const moveListener = event => {
|
||||||
const xRel = event.pageX - wrapRect.left;
|
const xRel = event.pageX - wrapRect.left;
|
||||||
const xPct = Math.min(Math.max(20, Math.floor((xRel / wrapRect.width) * 100)), 80);
|
const xPct = Math.min(Math.max(20, Math.floor((xRel / wrapRect.width) * 100)), 80);
|
||||||
this.displayWrap.style.flexBasis = `${100-xPct}%`;
|
this.displayWrap.style.flexBasis = `${100 - xPct}%`;
|
||||||
this.editor.settings.set('editorWidth', xPct);
|
this.editor.settings.set('editorWidth', xPct);
|
||||||
};
|
};
|
||||||
const upListener = (event) => {
|
const upListener = event => {
|
||||||
window.removeEventListener('pointermove', moveListener);
|
window.removeEventListener('pointermove', moveListener);
|
||||||
window.removeEventListener('pointerup', upListener);
|
window.removeEventListener('pointerup', upListener);
|
||||||
this.display.style.pointerEvents = null;
|
this.display.style.pointerEvents = null;
|
||||||
@ -105,7 +104,7 @@ export class MarkdownEditor extends Component {
|
|||||||
});
|
});
|
||||||
const widthSetting = this.editor.settings.get('editorWidth');
|
const widthSetting = this.editor.settings.get('editorWidth');
|
||||||
if (widthSetting) {
|
if (widthSetting) {
|
||||||
this.displayWrap.style.flexBasis = `${100-widthSetting}%`;
|
this.displayWrap.style.flexBasis = `${100 - widthSetting}%`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class NewUserPassword extends Component {
|
export class NewUserPassword extends Component {
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class Notification extends Component {
|
export class Notification extends Component {
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ export class Notification extends Component {
|
|||||||
this.type = this.$opts.type;
|
this.type = this.$opts.type;
|
||||||
this.textElem = this.container.querySelector('span');
|
this.textElem = this.container.querySelector('span');
|
||||||
this.autoHide = this.$opts.autoHide === 'true';
|
this.autoHide = this.$opts.autoHide === 'true';
|
||||||
this.initialShow = this.$opts.show === 'true'
|
this.initialShow = this.$opts.show === 'true';
|
||||||
this.container.style.display = 'grid';
|
this.container.style.display = 'grid';
|
||||||
|
|
||||||
window.$events.listen(this.type, text => {
|
window.$events.listen(this.type, text => {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class OptionalInput extends Component {
|
export class OptionalInput extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.removeButton = this.$refs.remove;
|
this.removeButton = this.$refs.remove;
|
||||||
this.showButton = this.$refs.show;
|
this.showButton = this.$refs.show;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {scrollAndHighlightElement} from "../services/util";
|
import {scrollAndHighlightElement} from '../services/util';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
import {htmlToDom} from "../services/dom";
|
import {htmlToDom} from '../services/dom';
|
||||||
|
|
||||||
export class PageComments extends Component {
|
export class PageComments extends Component {
|
||||||
|
|
||||||
@ -36,11 +36,11 @@ export class PageComments extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleAction(event) {
|
handleAction(event) {
|
||||||
let actionElem = event.target.closest('[action]');
|
const actionElem = event.target.closest('[action]');
|
||||||
|
|
||||||
if (event.target.matches('a[href^="#"]')) {
|
if (event.target.matches('a[href^="#"]')) {
|
||||||
const id = event.target.href.split('#')[1];
|
const id = event.target.href.split('#')[1];
|
||||||
scrollAndHighlightElement(document.querySelector('#' + id));
|
scrollAndHighlightElement(document.querySelector(`#${id}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionElem === null) return;
|
if (actionElem === null) return;
|
||||||
@ -68,24 +68,24 @@ export class PageComments extends Component {
|
|||||||
if (this.editingComment) this.closeUpdateForm();
|
if (this.editingComment) this.closeUpdateForm();
|
||||||
commentElem.querySelector('[comment-content]').style.display = 'none';
|
commentElem.querySelector('[comment-content]').style.display = 'none';
|
||||||
commentElem.querySelector('[comment-edit-container]').style.display = 'block';
|
commentElem.querySelector('[comment-edit-container]').style.display = 'block';
|
||||||
let textArea = commentElem.querySelector('[comment-edit-container] textarea');
|
const textArea = commentElem.querySelector('[comment-edit-container] textarea');
|
||||||
let lineCount = textArea.value.split('\n').length;
|
const lineCount = textArea.value.split('\n').length;
|
||||||
textArea.style.height = ((lineCount * 20) + 40) + 'px';
|
textArea.style.height = `${(lineCount * 20) + 40}px`;
|
||||||
this.editingComment = commentElem;
|
this.editingComment = commentElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateComment(event) {
|
updateComment(event) {
|
||||||
let form = event.target;
|
const form = event.target;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let text = form.querySelector('textarea').value;
|
const text = form.querySelector('textarea').value;
|
||||||
let reqData = {
|
const reqData = {
|
||||||
text: text,
|
text,
|
||||||
parent_id: this.parentId || null,
|
parent_id: this.parentId || null,
|
||||||
};
|
};
|
||||||
this.showLoading(form);
|
this.showLoading(form);
|
||||||
let commentId = this.editingComment.getAttribute('comment');
|
const commentId = this.editingComment.getAttribute('comment');
|
||||||
window.$http.put(`/comment/${commentId}`, reqData).then(resp => {
|
window.$http.put(`/comment/${commentId}`, reqData).then(resp => {
|
||||||
let newComment = document.createElement('div');
|
const newComment = document.createElement('div');
|
||||||
newComment.innerHTML = resp.data;
|
newComment.innerHTML = resp.data;
|
||||||
this.editingComment.innerHTML = newComment.children[0].innerHTML;
|
this.editingComment.innerHTML = newComment.children[0].innerHTML;
|
||||||
window.$events.success(this.updatedText);
|
window.$events.success(this.updatedText);
|
||||||
@ -98,7 +98,7 @@ export class PageComments extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deleteComment(commentElem) {
|
deleteComment(commentElem) {
|
||||||
let id = commentElem.getAttribute('comment');
|
const id = commentElem.getAttribute('comment');
|
||||||
this.showLoading(commentElem.querySelector('[comment-content]'));
|
this.showLoading(commentElem.querySelector('[comment-content]'));
|
||||||
window.$http.delete(`/comment/${id}`).then(resp => {
|
window.$http.delete(`/comment/${id}`).then(resp => {
|
||||||
commentElem.parentNode.removeChild(commentElem);
|
commentElem.parentNode.removeChild(commentElem);
|
||||||
@ -111,9 +111,9 @@ export class PageComments extends Component {
|
|||||||
saveComment(event) {
|
saveComment(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
let text = this.formInput.value;
|
const text = this.formInput.value;
|
||||||
let reqData = {
|
const reqData = {
|
||||||
text: text,
|
text,
|
||||||
parent_id: this.parentId || null,
|
parent_id: this.parentId || null,
|
||||||
};
|
};
|
||||||
this.showLoading(this.form);
|
this.showLoading(this.form);
|
||||||
@ -131,7 +131,7 @@ export class PageComments extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateCount() {
|
updateCount() {
|
||||||
let count = this.container.children.length;
|
const count = this.container.children.length;
|
||||||
this.elem.querySelector('[comments-title]').textContent = window.trans_plural(this.countText, count, {count});
|
this.elem.querySelector('[comments-title]').textContent = window.trans_plural(this.countText, count, {count});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,14 +148,14 @@ export class PageComments extends Component {
|
|||||||
this.formContainer.parentNode.style.display = 'block';
|
this.formContainer.parentNode.style.display = 'block';
|
||||||
this.addButtonContainer.style.display = 'none';
|
this.addButtonContainer.style.display = 'none';
|
||||||
this.formInput.focus();
|
this.formInput.focus();
|
||||||
this.formInput.scrollIntoView({behavior: "smooth"});
|
this.formInput.scrollIntoView({behavior: 'smooth'});
|
||||||
}
|
}
|
||||||
|
|
||||||
hideForm() {
|
hideForm() {
|
||||||
this.formContainer.style.display = 'none';
|
this.formContainer.style.display = 'none';
|
||||||
this.formContainer.parentNode.style.display = 'none';
|
this.formContainer.parentNode.style.display = 'none';
|
||||||
if (this.getCommentCount() > 0) {
|
if (this.getCommentCount() > 0) {
|
||||||
this.elem.appendChild(this.addButtonContainer)
|
this.elem.appendChild(this.addButtonContainer);
|
||||||
} else {
|
} else {
|
||||||
this.commentCountBar.appendChild(this.addButtonContainer);
|
this.commentCountBar.appendChild(this.addButtonContainer);
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ export class PageComments extends Component {
|
|||||||
|
|
||||||
showLoading(formElem) {
|
showLoading(formElem) {
|
||||||
const groups = formElem.querySelectorAll('.form-group');
|
const groups = formElem.querySelectorAll('.form-group');
|
||||||
for (let group of groups) {
|
for (const group of groups) {
|
||||||
group.style.display = 'none';
|
group.style.display = 'none';
|
||||||
}
|
}
|
||||||
formElem.querySelector('.form-group.loading').style.display = 'block';
|
formElem.querySelector('.form-group.loading').style.display = 'block';
|
||||||
@ -190,7 +190,7 @@ export class PageComments extends Component {
|
|||||||
|
|
||||||
hideLoading(formElem) {
|
hideLoading(formElem) {
|
||||||
const groups = formElem.querySelectorAll('.form-group');
|
const groups = formElem.querySelectorAll('.form-group');
|
||||||
for (let group of groups) {
|
for (const group of groups) {
|
||||||
group.style.display = 'block';
|
group.style.display = 'block';
|
||||||
}
|
}
|
||||||
formElem.querySelector('.form-group.loading').style.display = 'none';
|
formElem.querySelector('.form-group.loading').style.display = 'none';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as DOM from "../services/dom";
|
import * as DOM from '../services/dom';
|
||||||
import {scrollAndHighlightElement} from "../services/util";
|
import {scrollAndHighlightElement} from '../services/util';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class PageDisplay extends Component {
|
export class PageDisplay extends Component {
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ export class PageDisplay extends Component {
|
|||||||
window.$components.first('tri-layout').showContent();
|
window.$components.first('tri-layout').showContent();
|
||||||
const contentId = child.getAttribute('href').substr(1);
|
const contentId = child.getAttribute('href').substr(1);
|
||||||
this.goToText(contentId);
|
this.goToText(contentId);
|
||||||
window.history.pushState(null, null, '#' + contentId);
|
window.history.pushState(null, null, `#${contentId}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ export class PageDisplay extends Component {
|
|||||||
// Setup the intersection observer.
|
// Setup the intersection observer.
|
||||||
const intersectOpts = {
|
const intersectOpts = {
|
||||||
rootMargin: '0px 0px 0px 0px',
|
rootMargin: '0px 0px 0px 0px',
|
||||||
threshold: 1.0
|
threshold: 1.0,
|
||||||
};
|
};
|
||||||
const pageNavObserver = new IntersectionObserver(headingVisibilityChange, intersectOpts);
|
const pageNavObserver = new IntersectionObserver(headingVisibilityChange, intersectOpts);
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ export class PageDisplay extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toggleAnchorHighlighting(elementId, shouldHighlight) {
|
function toggleAnchorHighlighting(elementId, shouldHighlight) {
|
||||||
DOM.forEach('a[href="#' + elementId + '"]', anchor => {
|
DOM.forEach(`a[href="#${elementId}"]`, anchor => {
|
||||||
anchor.closest('li').classList.toggle('current-heading', shouldHighlight);
|
anchor.closest('li').classList.toggle('current-heading', shouldHighlight);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -96,4 +96,5 @@ export class PageDisplay extends Component {
|
|||||||
const details = [...this.container.querySelectorAll('details')];
|
const details = [...this.container.querySelectorAll('details')];
|
||||||
details.forEach(detail => detail.addEventListener('toggle', onToggle));
|
details.forEach(detail => detail.addEventListener('toggle', onToggle));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,9 +1,10 @@
|
|||||||
import * as Dates from "../services/dates";
|
import * as Dates from '../services/dates';
|
||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from '../services/dom';
|
||||||
import {debounce} from "../services/util";
|
import {debounce} from '../services/util';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class PageEditor extends Component {
|
export class PageEditor extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
// Options
|
// Options
|
||||||
this.draftsEnabled = this.$opts.draftsEnabled === 'true';
|
this.draftsEnabled = this.$opts.draftsEnabled === 'true';
|
||||||
@ -93,12 +94,12 @@ export class PageEditor extends Component {
|
|||||||
|
|
||||||
runAutoSave() {
|
runAutoSave() {
|
||||||
// Stop if manually saved recently to prevent bombarding the server
|
// Stop if manually saved recently to prevent bombarding the server
|
||||||
const savedRecently = (Date.now() - this.autoSave.last < (this.autoSave.frequency)/2);
|
const savedRecently = (Date.now() - this.autoSave.last < (this.autoSave.frequency) / 2);
|
||||||
if (savedRecently || !this.autoSave.pendingChange) {
|
if (savedRecently || !this.autoSave.pendingChange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.saveDraft()
|
this.saveDraft();
|
||||||
}
|
}
|
||||||
|
|
||||||
savePage() {
|
savePage() {
|
||||||
@ -172,7 +173,6 @@ export class PageEditor extends Component {
|
|||||||
this.startAutoSave();
|
this.startAutoSave();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
window.$events.emit('success', this.draftDiscardedText);
|
window.$events.emit('success', this.draftDiscardedText);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateChangelogDisplay() {
|
updateChangelogDisplay() {
|
||||||
@ -180,7 +180,7 @@ export class PageEditor extends Component {
|
|||||||
if (summary.length === 0) {
|
if (summary.length === 0) {
|
||||||
summary = this.setChangelogText;
|
summary = this.setChangelogText;
|
||||||
} else if (summary.length > 16) {
|
} else if (summary.length > 16) {
|
||||||
summary = summary.slice(0, 16) + '...';
|
summary = `${summary.slice(0, 16)}...`;
|
||||||
}
|
}
|
||||||
this.changelogDisplay.innerText = summary;
|
this.changelogDisplay.innerText = summary;
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ export class PageEditor extends Component {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const link = event.target.closest('a').href;
|
const link = event.target.closest('a').href;
|
||||||
/** @var {ConfirmDialog} **/
|
/** @var {ConfirmDialog} * */
|
||||||
const dialog = window.$components.firstOnElement(this.switchDialogContainer, 'confirm-dialog');
|
const dialog = window.$components.firstOnElement(this.switchDialogContainer, 'confirm-dialog');
|
||||||
const [saved, confirmed] = await Promise.all([this.saveDraft(), dialog.show()]);
|
const [saved, confirmed] = await Promise.all([this.saveDraft(), dialog.show()]);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class PagePicker extends Component {
|
export class PagePicker extends Component {
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ export class PagePicker extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showPopup() {
|
showPopup() {
|
||||||
/** @type {EntitySelectorPopup} **/
|
/** @type {EntitySelectorPopup} * */
|
||||||
const selectorPopup = window.$components.first('entity-selector-popup');
|
const selectorPopup = window.$components.first('entity-selector-popup');
|
||||||
selectorPopup.show(entity => {
|
selectorPopup.show(entity => {
|
||||||
this.setValue(entity.id, entity.name);
|
this.setValue(entity.id, entity.name);
|
||||||
@ -44,7 +44,7 @@ export class PagePicker extends Component {
|
|||||||
toggleElem(this.defaultDisplay, !hasValue);
|
toggleElem(this.defaultDisplay, !hasValue);
|
||||||
toggleElem(this.display, hasValue);
|
toggleElem(this.display, hasValue);
|
||||||
if (hasValue) {
|
if (hasValue) {
|
||||||
let id = this.getAssetIdFromVal();
|
const id = this.getAssetIdFromVal();
|
||||||
this.display.textContent = `#${id}, ${name}`;
|
this.display.textContent = `#${id}, ${name}`;
|
||||||
this.display.href = window.baseUrl(`/link/${id}`);
|
this.display.href = window.baseUrl(`/link/${id}`);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class PermissionsTable extends Component {
|
export class PermissionsTable extends Component {
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ export class PermissionsTable extends Component {
|
|||||||
const tableRows = this.container.querySelectorAll(this.rowSelector);
|
const tableRows = this.container.querySelectorAll(this.rowSelector);
|
||||||
const inputsToToggle = [];
|
const inputsToToggle = [];
|
||||||
|
|
||||||
for (let row of tableRows) {
|
for (const row of tableRows) {
|
||||||
const targetCell = row.children[colIndex];
|
const targetCell = row.children[colIndex];
|
||||||
if (targetCell) {
|
if (targetCell) {
|
||||||
inputsToToggle.push(...targetCell.querySelectorAll('input[type=checkbox]'));
|
inputsToToggle.push(...targetCell.querySelectorAll('input[type=checkbox]'));
|
||||||
@ -57,7 +57,7 @@ export class PermissionsTable extends Component {
|
|||||||
|
|
||||||
toggleAllInputs(inputsToToggle) {
|
toggleAllInputs(inputsToToggle) {
|
||||||
const currentState = inputsToToggle.length > 0 ? inputsToToggle[0].checked : false;
|
const currentState = inputsToToggle.length > 0 ? inputsToToggle[0].checked : false;
|
||||||
for (let checkbox of inputsToToggle) {
|
for (const checkbox of inputsToToggle) {
|
||||||
checkbox.checked = !currentState;
|
checkbox.checked = !currentState;
|
||||||
checkbox.dispatchEvent(new Event('change'));
|
checkbox.dispatchEvent(new Event('change'));
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import * as DOM from "../services/dom";
|
import * as DOM from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
import {copyTextToClipboard} from "../services/clipboard";
|
import {copyTextToClipboard} from '../services/clipboard';
|
||||||
|
|
||||||
|
|
||||||
export class Pointer extends Component {
|
export class Pointer extends Component {
|
||||||
|
|
||||||
@ -113,7 +112,7 @@ export class Pointer extends Component {
|
|||||||
updateForTarget(element) {
|
updateForTarget(element) {
|
||||||
let inputText = this.pointerModeLink ? window.baseUrl(`/link/${this.pageId}#${this.pointerSectionId}`) : `{{@${this.pageId}#${this.pointerSectionId}}}`;
|
let inputText = this.pointerModeLink ? window.baseUrl(`/link/${this.pageId}#${this.pointerSectionId}`) : `{{@${this.pageId}#${this.pointerSectionId}}}`;
|
||||||
if (this.pointerModeLink && !inputText.startsWith('http')) {
|
if (this.pointerModeLink && !inputText.startsWith('http')) {
|
||||||
inputText = window.location.protocol + "//" + window.location.host + inputText;
|
inputText = `${window.location.protocol}//${window.location.host}${inputText}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.input.value = inputText;
|
this.input.value = inputText;
|
||||||
@ -121,7 +120,7 @@ export class Pointer extends Component {
|
|||||||
// Update anchor if present
|
// Update anchor if present
|
||||||
const editAnchor = this.container.querySelector('#pointer-edit');
|
const editAnchor = this.container.querySelector('#pointer-edit');
|
||||||
if (editAnchor && element) {
|
if (editAnchor && element) {
|
||||||
const editHref = editAnchor.dataset.editHref;
|
const {editHref} = editAnchor.dataset;
|
||||||
const elementId = element.id;
|
const elementId = element.id;
|
||||||
|
|
||||||
// get the first 50 characters.
|
// get the first 50 characters.
|
||||||
@ -129,4 +128,5 @@ export class Pointer extends Component {
|
|||||||
editAnchor.href = `${editHref}?content-id=${elementId}&content-text=${encodeURIComponent(queryContent)}`;
|
editAnchor.href = `${editHref}?content-id=${elementId}&content-text=${encodeURIComponent(queryContent)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import {fadeIn, fadeOut} from "../services/animations";
|
import {fadeIn, fadeOut} from '../services/animations';
|
||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Popup window that will contain other content.
|
* Popup window that will contain other content.
|
||||||
@ -47,7 +47,7 @@ export class Popup extends Component {
|
|||||||
show(onComplete = null, onHide = null) {
|
show(onComplete = null, onHide = null) {
|
||||||
fadeIn(this.container, 120, onComplete);
|
fadeIn(this.container, 120, onComplete);
|
||||||
|
|
||||||
this.onkeyup = (event) => {
|
this.onkeyup = event => {
|
||||||
if (event.key === 'Escape') {
|
if (event.key === 'Escape') {
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class SettingAppColorScheme extends Component {
|
export class SettingAppColorScheme extends Component {
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ export class SettingAppColorScheme extends Component {
|
|||||||
this.handleModeChange(newMode);
|
this.handleModeChange(newMode);
|
||||||
});
|
});
|
||||||
|
|
||||||
const onInputChange = (event) => {
|
const onInputChange = event => {
|
||||||
this.updateAppColorsFromInputs();
|
this.updateAppColorsFromInputs();
|
||||||
|
|
||||||
if (event.target.name.startsWith('setting-app-color')) {
|
if (event.target.name.startsWith('setting-app-color')) {
|
||||||
@ -44,7 +44,7 @@ export class SettingAppColorScheme extends Component {
|
|||||||
cssId = 'primary';
|
cssId = 'primary';
|
||||||
}
|
}
|
||||||
|
|
||||||
const varName = '--color-' + cssId;
|
const varName = `--color-${cssId}`;
|
||||||
document.body.style.setProperty(varName, input.value);
|
document.body.style.setProperty(varName, input.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,9 +57,9 @@ export class SettingAppColorScheme extends Component {
|
|||||||
const lightName = input.name.replace('-color', '-color-light');
|
const lightName = input.name.replace('-color', '-color-light');
|
||||||
const hexVal = input.value;
|
const hexVal = input.value;
|
||||||
const rgb = this.hexToRgb(hexVal);
|
const rgb = this.hexToRgb(hexVal);
|
||||||
const rgbLightVal = 'rgba('+ [rgb.r, rgb.g, rgb.b, '0.15'].join(',') +')';
|
const rgbLightVal = `rgba(${[rgb.r, rgb.g, rgb.b, '0.15'].join(',')})`;
|
||||||
|
|
||||||
console.log(input.name, lightName, hexVal, rgbLightVal)
|
console.log(input.name, lightName, hexVal, rgbLightVal);
|
||||||
const lightColorInput = this.container.querySelector(`input[name="${lightName}"][type="hidden"]`);
|
const lightColorInput = this.container.querySelector(`input[name="${lightName}"][type="hidden"]`);
|
||||||
lightColorInput.value = rgbLightVal;
|
lightColorInput.value = rgbLightVal;
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ export class SettingAppColorScheme extends Component {
|
|||||||
return {
|
return {
|
||||||
r: result ? parseInt(result[1], 16) : 0,
|
r: result ? parseInt(result[1], 16) : 0,
|
||||||
g: result ? parseInt(result[2], 16) : 0,
|
g: result ? parseInt(result[2], 16) : 0,
|
||||||
b: result ? parseInt(result[3], 16) : 0
|
b: result ? parseInt(result[3], 16) : 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class SettingColorPicker extends Component {
|
export class SettingColorPicker extends Component {
|
||||||
|
|
||||||
@ -17,4 +17,5 @@ export class SettingColorPicker extends Component {
|
|||||||
this.colorInput.value = value;
|
this.colorInput.value = value;
|
||||||
this.colorInput.dispatchEvent(new Event('change', {bubbles: true}));
|
this.colorInput.dispatchEvent(new Event('change', {bubbles: true}));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class SettingHomepageControl extends Component {
|
export class SettingHomepageControl extends Component {
|
||||||
|
|
||||||
@ -14,4 +14,5 @@ export class SettingHomepageControl extends Component {
|
|||||||
const showPagePicker = this.typeControl.value === 'page';
|
const showPagePicker = this.typeControl.value === 'page';
|
||||||
this.pagePickerContainer.style.display = (showPagePicker ? 'block' : 'none');
|
this.pagePickerContainer.style.display = (showPagePicker ? 'block' : 'none');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import Sortable from "sortablejs";
|
import Sortable from 'sortablejs';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Object<string, function(HTMLElement, HTMLElement, HTMLElement)>}
|
* @type {Object<string, function(HTMLElement, HTMLElement, HTMLElement)>}
|
||||||
@ -66,7 +66,7 @@ export class ShelfSort extends Component {
|
|||||||
this.filterBooksByName(this.bookSearchInput.value);
|
this.filterBooksByName(this.bookSearchInput.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.sortButtonContainer.addEventListener('click' , event => {
|
this.sortButtonContainer.addEventListener('click', event => {
|
||||||
const button = event.target.closest('button[data-sort]');
|
const button = event.target.closest('button[data-sort]');
|
||||||
if (button) {
|
if (button) {
|
||||||
this.sortShelfBooks(button.dataset.sort);
|
this.sortShelfBooks(button.dataset.sort);
|
||||||
@ -78,11 +78,10 @@ export class ShelfSort extends Component {
|
|||||||
* @param {String} filterVal
|
* @param {String} filterVal
|
||||||
*/
|
*/
|
||||||
filterBooksByName(filterVal) {
|
filterBooksByName(filterVal) {
|
||||||
|
|
||||||
// Set height on first search, if not already set, to prevent the distraction
|
// Set height on first search, if not already set, to prevent the distraction
|
||||||
// of the list height jumping around
|
// of the list height jumping around
|
||||||
if (!this.allBookList.style.height) {
|
if (!this.allBookList.style.height) {
|
||||||
this.allBookList.style.height = this.allBookList.getBoundingClientRect().height + 'px';
|
this.allBookList.style.height = `${this.allBookList.getBoundingClientRect().height}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const books = this.allBookList.children;
|
const books = this.allBookList.children;
|
||||||
@ -100,7 +99,7 @@ export class ShelfSort extends Component {
|
|||||||
*/
|
*/
|
||||||
sortItemActionClick(sortItemAction) {
|
sortItemActionClick(sortItemAction) {
|
||||||
const sortItem = sortItemAction.closest('.scroll-box-item');
|
const sortItem = sortItemAction.closest('.scroll-box-item');
|
||||||
const action = sortItemAction.dataset.action;
|
const {action} = sortItemAction.dataset;
|
||||||
|
|
||||||
const actionFunction = itemActions[action];
|
const actionFunction = itemActions[action];
|
||||||
actionFunction(sortItem, this.shelfBookList, this.allBookList);
|
actionFunction(sortItem, this.shelfBookList, this.allBookList);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keys to ignore when recording shortcuts.
|
* Keys to ignore when recording shortcuts.
|
||||||
@ -23,11 +23,11 @@ export class ShortcutInput extends Component {
|
|||||||
|
|
||||||
this.input.addEventListener('blur', () => {
|
this.input.addEventListener('blur', () => {
|
||||||
this.stopListeningForInput();
|
this.stopListeningForInput();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
startListeningForInput() {
|
startListeningForInput() {
|
||||||
this.input.addEventListener('keydown', this.listenerRecordKey)
|
this.input.addEventListener('keydown', this.listenerRecordKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
function reverseMap(map) {
|
function reverseMap(map) {
|
||||||
const reversed = {};
|
const reversed = {};
|
||||||
@ -8,7 +8,6 @@ function reverseMap(map) {
|
|||||||
return reversed;
|
return reversed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class Shortcuts extends Component {
|
export class Shortcuts extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
@ -25,7 +24,6 @@ export class Shortcuts extends Component {
|
|||||||
|
|
||||||
setupListeners() {
|
setupListeners() {
|
||||||
window.addEventListener('keydown', event => {
|
window.addEventListener('keydown', event => {
|
||||||
|
|
||||||
if (event.target.closest('input, select, textarea')) {
|
if (event.target.closest('input, select, textarea')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -44,7 +42,6 @@ export class Shortcuts extends Component {
|
|||||||
* @param {KeyboardEvent} event
|
* @param {KeyboardEvent} event
|
||||||
*/
|
*/
|
||||||
handleShortcutPress(event) {
|
handleShortcutPress(event) {
|
||||||
|
|
||||||
const keys = [
|
const keys = [
|
||||||
event.ctrlKey ? 'Ctrl' : '',
|
event.ctrlKey ? 'Ctrl' : '',
|
||||||
event.metaKey ? 'Cmd' : '',
|
event.metaKey ? 'Cmd' : '',
|
||||||
@ -90,7 +87,7 @@ export class Shortcuts extends Component {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(`Shortcut attempted to be ran for element type that does not have handling setup`, el);
|
console.error('Shortcut attempted to be ran for element type that does not have handling setup', el);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -135,10 +132,10 @@ export class Shortcuts extends Component {
|
|||||||
|
|
||||||
const linkage = document.createElement('div');
|
const linkage = document.createElement('div');
|
||||||
linkage.classList.add('shortcut-linkage');
|
linkage.classList.add('shortcut-linkage');
|
||||||
linkage.style.left = targetBounds.x + 'px';
|
linkage.style.left = `${targetBounds.x}px`;
|
||||||
linkage.style.top = targetBounds.y + 'px';
|
linkage.style.top = `${targetBounds.y}px`;
|
||||||
linkage.style.width = targetBounds.width + 'px';
|
linkage.style.width = `${targetBounds.width}px`;
|
||||||
linkage.style.height = targetBounds.height + 'px';
|
linkage.style.height = `${targetBounds.height}px`;
|
||||||
|
|
||||||
wrapper.append(label, linkage);
|
wrapper.append(label, linkage);
|
||||||
|
|
||||||
@ -159,4 +156,5 @@ export class Shortcuts extends Component {
|
|||||||
|
|
||||||
this.hintsShowing = false;
|
this.hintsShowing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import Sortable from "sortablejs";
|
import Sortable from 'sortablejs';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SortableList
|
* SortableList
|
||||||
@ -9,6 +9,7 @@ import {Component} from "./component";
|
|||||||
* the data to set on the data-transfer.
|
* the data to set on the data-transfer.
|
||||||
*/
|
*/
|
||||||
export class SortableList extends Component {
|
export class SortableList extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
this.handleSelector = this.$opts.handleSelector;
|
this.handleSelector = this.$opts.handleSelector;
|
||||||
@ -33,4 +34,5 @@ export class SortableList extends Component {
|
|||||||
dragoverBubble: false,
|
dragoverBubble: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit on change
|
* Submit on change
|
||||||
@ -9,8 +9,7 @@ export class SubmitOnChange extends Component {
|
|||||||
setup() {
|
setup() {
|
||||||
this.filter = this.$opts.filter;
|
this.filter = this.$opts.filter;
|
||||||
|
|
||||||
this.$el.addEventListener('change', (event) => {
|
this.$el.addEventListener('change', event => {
|
||||||
|
|
||||||
if (this.filter && !event.target.matches(this.filter)) {
|
if (this.filter && !event.target.matches(this.filter)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tabs
|
* Tabs
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class TagManager extends Component {
|
export class TagManager extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.addRemoveComponentEl = this.$refs.addRemove;
|
this.addRemoveComponentEl = this.$refs.addRemove;
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
@ -11,8 +12,7 @@ export class TagManager extends Component {
|
|||||||
|
|
||||||
setupListeners() {
|
setupListeners() {
|
||||||
this.container.addEventListener('input', event => {
|
this.container.addEventListener('input', event => {
|
||||||
|
/** @var {AddRemoveRows} * */
|
||||||
/** @var {AddRemoveRows} **/
|
|
||||||
const addRemoveComponent = window.$components.firstOnElement(this.addRemoveComponentEl, 'add-remove-rows');
|
const addRemoveComponent = window.$components.firstOnElement(this.addRemoveComponentEl, 'add-remove-rows');
|
||||||
if (!this.hasEmptyRows() && event.target.value) {
|
if (!this.hasEmptyRows() && event.target.value) {
|
||||||
addRemoveComponent.add();
|
addRemoveComponent.add();
|
||||||
@ -22,9 +22,8 @@ export class TagManager extends Component {
|
|||||||
|
|
||||||
hasEmptyRows() {
|
hasEmptyRows() {
|
||||||
const rows = this.container.querySelectorAll(this.rowSelector);
|
const rows = this.container.querySelectorAll(this.rowSelector);
|
||||||
const firstEmpty = [...rows].find(row => {
|
const firstEmpty = [...rows].find(row => [...row.querySelectorAll('input')].filter(input => input.value).length === 0);
|
||||||
return [...row.querySelectorAll('input')].filter(input => input.value).length === 0;
|
|
||||||
});
|
|
||||||
return firstEmpty !== undefined;
|
return firstEmpty !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import * as DOM from "../services/dom";
|
import * as DOM from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class TemplateManager extends Component {
|
export class TemplateManager extends Component {
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ export class TemplateManager extends Component {
|
|||||||
|
|
||||||
async insertTemplate(templateId, action = 'replace') {
|
async insertTemplate(templateId, action = 'replace') {
|
||||||
const resp = await window.$http.get(`/templates/${templateId}`);
|
const resp = await window.$http.get(`/templates/${templateId}`);
|
||||||
const eventName = 'editor::' + action;
|
const eventName = `editor::${action}`;
|
||||||
window.$events.emit(eventName, resp.data);
|
window.$events.emit(eventName, resp.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,10 +79,11 @@ export class TemplateManager extends Component {
|
|||||||
|
|
||||||
async performSearch() {
|
async performSearch() {
|
||||||
const searchTerm = this.searchInput.value;
|
const searchTerm = this.searchInput.value;
|
||||||
const resp = await window.$http.get(`/templates`, {
|
const resp = await window.$http.get('/templates', {
|
||||||
search: searchTerm
|
search: searchTerm,
|
||||||
});
|
});
|
||||||
this.searchCancel.style.display = searchTerm ? 'block' : 'none';
|
this.searchCancel.style.display = searchTerm ? 'block' : 'none';
|
||||||
this.list.innerHTML = resp.data;
|
this.list.innerHTML = resp.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class ToggleSwitch extends Component {
|
export class ToggleSwitch extends Component {
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class TriLayout extends Component {
|
export class TriLayout extends Component {
|
||||||
|
|
||||||
@ -9,8 +9,8 @@ export class TriLayout extends Component {
|
|||||||
this.lastLayoutType = 'none';
|
this.lastLayoutType = 'none';
|
||||||
this.onDestroy = null;
|
this.onDestroy = null;
|
||||||
this.scrollCache = {
|
this.scrollCache = {
|
||||||
'content': 0,
|
content: 0,
|
||||||
'info': 0,
|
info: 0,
|
||||||
};
|
};
|
||||||
this.lastTabShown = 'content';
|
this.lastTabShown = 'content';
|
||||||
|
|
||||||
@ -53,20 +53,19 @@ export class TriLayout extends Component {
|
|||||||
for (const tab of this.tabs) {
|
for (const tab of this.tabs) {
|
||||||
tab.removeEventListener('click', this.mobileTabClick);
|
tab.removeEventListener('click', this.mobileTabClick);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
setupDesktop() {
|
setupDesktop() {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action to run when the mobile info toggle bar is clicked/tapped
|
* Action to run when the mobile info toggle bar is clicked/tapped
|
||||||
* @param event
|
* @param event
|
||||||
*/
|
*/
|
||||||
mobileTabClick(event) {
|
mobileTabClick(event) {
|
||||||
const tab = event.target.dataset.tab;
|
const {tab} = event.target.dataset;
|
||||||
this.showTab(tab);
|
this.showTab(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {onChildEvent} from "../services/dom";
|
import {onChildEvent} from '../services/dom';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class UserSelect extends Component {
|
export class UserSelect extends Component {
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ export class UserSelect extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
/** @var {Dropdown} **/
|
/** @var {Dropdown} * */
|
||||||
const dropdown = window.$components.firstOnElement(this.container, 'dropdown');
|
const dropdown = window.$components.firstOnElement(this.container, 'dropdown');
|
||||||
dropdown.hide();
|
dropdown.hide();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* Webhook Events
|
* Webhook Events
|
||||||
* Manages dynamic selection control in the webhook form interface.
|
* Manages dynamic selection control in the webhook form interface.
|
||||||
*/
|
*/
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class WebhookEvents extends Component {
|
export class WebhookEvents extends Component {
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {build as buildEditorConfig} from "../wysiwyg/config";
|
import {build as buildEditorConfig} from '../wysiwyg/config';
|
||||||
import {Component} from "./component";
|
import {Component} from './component';
|
||||||
|
|
||||||
export class WysiwygEditor extends Component {
|
export class WysiwygEditor extends Component {
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ export class WysiwygEditor extends Component {
|
|||||||
*/
|
*/
|
||||||
getContent() {
|
getContent() {
|
||||||
return {
|
return {
|
||||||
html: this.editor.getContent()
|
html: this.editor.getContent(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import DrawIO from "../services/drawio";
|
import DrawIO from '../services/drawio';
|
||||||
|
|
||||||
export class Actions {
|
export class Actions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {MarkdownEditor} editor
|
* @param {MarkdownEditor} editor
|
||||||
*/
|
*/
|
||||||
@ -29,13 +30,13 @@ export class Actions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showImageInsert() {
|
showImageInsert() {
|
||||||
/** @type {ImageManager} **/
|
/** @type {ImageManager} * */
|
||||||
const imageManager = window.$components.first('image-manager');
|
const imageManager = window.$components.first('image-manager');
|
||||||
|
|
||||||
imageManager.show(image => {
|
imageManager.show(image => {
|
||||||
const imageUrl = image.thumbs.display || image.url;
|
const imageUrl = image.thumbs.display || image.url;
|
||||||
const selectedText = this.#getSelectionText();
|
const selectedText = this.#getSelectionText();
|
||||||
const newText = "[![" + (selectedText || image.name) + "](" + imageUrl + ")](" + image.url + ")";
|
const newText = `[![${selectedText || image.name}](${imageUrl})](${image.url})`;
|
||||||
this.#replaceSelection(newText, newText.length);
|
this.#replaceSelection(newText, newText.length);
|
||||||
}, 'gallery');
|
}, 'gallery');
|
||||||
}
|
}
|
||||||
@ -49,12 +50,12 @@ export class Actions {
|
|||||||
const selectedText = this.#getSelectionText();
|
const selectedText = this.#getSelectionText();
|
||||||
const newText = `[${selectedText}]()`;
|
const newText = `[${selectedText}]()`;
|
||||||
const cursorPosDiff = (selectedText === '') ? -3 : -1;
|
const cursorPosDiff = (selectedText === '') ? -3 : -1;
|
||||||
this.#replaceSelection(newText, newText.length+cursorPosDiff);
|
this.#replaceSelection(newText, newText.length + cursorPosDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
showImageManager() {
|
showImageManager() {
|
||||||
const selectionRange = this.#getSelectionRange();
|
const selectionRange = this.#getSelectionRange();
|
||||||
/** @type {ImageManager} **/
|
/** @type {ImageManager} * */
|
||||||
const imageManager = window.$components.first('image-manager');
|
const imageManager = window.$components.first('image-manager');
|
||||||
imageManager.show(image => {
|
imageManager.show(image => {
|
||||||
this.#insertDrawing(image, selectionRange);
|
this.#insertDrawing(image, selectionRange);
|
||||||
@ -65,7 +66,7 @@ export class Actions {
|
|||||||
showLinkSelector() {
|
showLinkSelector() {
|
||||||
const selectionRange = this.#getSelectionRange();
|
const selectionRange = this.#getSelectionRange();
|
||||||
|
|
||||||
/** @type {EntitySelectorPopup} **/
|
/** @type {EntitySelectorPopup} * */
|
||||||
const selector = window.$components.first('entity-selector-popup');
|
const selector = window.$components.first('entity-selector-popup');
|
||||||
selector.show(entity => {
|
selector.show(entity => {
|
||||||
const selectedText = this.#getSelectionText(selectionRange) || entity.name;
|
const selectedText = this.#getSelectionText(selectionRange) || entity.name;
|
||||||
@ -81,16 +82,13 @@ export class Actions {
|
|||||||
|
|
||||||
const selectionRange = this.#getSelectionRange();
|
const selectionRange = this.#getSelectionRange();
|
||||||
|
|
||||||
DrawIO.show(url,() => {
|
DrawIO.show(url, () => Promise.resolve(''), pngData => {
|
||||||
return Promise.resolve('');
|
|
||||||
}, (pngData) => {
|
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
image: pngData,
|
image: pngData,
|
||||||
uploaded_to: Number(this.editor.config.pageId),
|
uploaded_to: Number(this.editor.config.pageId),
|
||||||
};
|
};
|
||||||
|
|
||||||
window.$http.post("/images/drawio", data).then(resp => {
|
window.$http.post('/images/drawio', data).then(resp => {
|
||||||
this.#insertDrawing(resp.data, selectionRange);
|
this.#insertDrawing(resp.data, selectionRange);
|
||||||
DrawIO.close();
|
DrawIO.close();
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
@ -106,7 +104,7 @@ export class Actions {
|
|||||||
|
|
||||||
// Show draw.io if enabled and handle save.
|
// Show draw.io if enabled and handle save.
|
||||||
editDrawing(imgContainer) {
|
editDrawing(imgContainer) {
|
||||||
const drawioUrl = this.editor.config.drawioUrl;
|
const {drawioUrl} = this.editor.config;
|
||||||
if (!drawioUrl) {
|
if (!drawioUrl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -114,16 +112,13 @@ export class Actions {
|
|||||||
const selectionRange = this.#getSelectionRange();
|
const selectionRange = this.#getSelectionRange();
|
||||||
const drawingId = imgContainer.getAttribute('drawio-diagram');
|
const drawingId = imgContainer.getAttribute('drawio-diagram');
|
||||||
|
|
||||||
DrawIO.show(drawioUrl, () => {
|
DrawIO.show(drawioUrl, () => DrawIO.load(drawingId), pngData => {
|
||||||
return DrawIO.load(drawingId);
|
|
||||||
}, (pngData) => {
|
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
image: pngData,
|
image: pngData,
|
||||||
uploaded_to: Number(this.editor.config.pageId),
|
uploaded_to: Number(this.editor.config.pageId),
|
||||||
};
|
};
|
||||||
|
|
||||||
window.$http.post("/images/drawio", data).then(resp => {
|
window.$http.post('/images/drawio', data).then(resp => {
|
||||||
const newText = `<div drawio-diagram="${resp.data.id}"><img src="${resp.data.url}"></div>`;
|
const newText = `<div drawio-diagram="${resp.data.id}"><img src="${resp.data.url}"></div>`;
|
||||||
const newContent = this.#getText().split('\n').map(line => {
|
const newContent = this.#getText().split('\n').map(line => {
|
||||||
if (line.indexOf(`drawio-diagram="${drawingId}"`) !== -1) {
|
if (line.indexOf(`drawio-diagram="${drawingId}"`) !== -1) {
|
||||||
@ -150,7 +145,7 @@ export class Actions {
|
|||||||
|
|
||||||
// Make the editor full screen
|
// Make the editor full screen
|
||||||
fullScreen() {
|
fullScreen() {
|
||||||
const container = this.editor.config.container;
|
const {container} = this.editor.config;
|
||||||
const alreadyFullscreen = container.classList.contains('fullscreen');
|
const alreadyFullscreen = container.classList.contains('fullscreen');
|
||||||
container.classList.toggle('fullscreen', !alreadyFullscreen);
|
container.classList.toggle('fullscreen', !alreadyFullscreen);
|
||||||
document.body.classList.toggle('markdown-fullscreen', !alreadyFullscreen);
|
document.body.classList.toggle('markdown-fullscreen', !alreadyFullscreen);
|
||||||
@ -204,7 +199,7 @@ export class Actions {
|
|||||||
content = this.#cleanTextForEditor(content);
|
content = this.#cleanTextForEditor(content);
|
||||||
const selectionRange = this.#getSelectionRange();
|
const selectionRange = this.#getSelectionRange();
|
||||||
const selectFrom = selectionRange.from + content.length + 1;
|
const selectFrom = selectionRange.from + content.length + 1;
|
||||||
this.#dispatchChange(0, 0, content + '\n', selectFrom);
|
this.#dispatchChange(0, 0, `${content}\n`, selectFrom);
|
||||||
this.focus();
|
this.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +209,7 @@ export class Actions {
|
|||||||
*/
|
*/
|
||||||
appendContent(content) {
|
appendContent(content) {
|
||||||
content = this.#cleanTextForEditor(content);
|
content = this.#cleanTextForEditor(content);
|
||||||
this.#dispatchChange(this.editor.cm.state.doc.length, '\n' + content);
|
this.#dispatchChange(this.editor.cm.state.doc.length, `\n${content}`);
|
||||||
this.focus();
|
this.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +218,7 @@ export class Actions {
|
|||||||
* @param {String} content
|
* @param {String} content
|
||||||
*/
|
*/
|
||||||
replaceContent(content) {
|
replaceContent(content) {
|
||||||
this.#setText(content)
|
this.#setText(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -250,7 +245,7 @@ export class Actions {
|
|||||||
if (alreadySymbol) {
|
if (alreadySymbol) {
|
||||||
newLineContent = lineContent.replace(lineStart, newStart).trim();
|
newLineContent = lineContent.replace(lineStart, newStart).trim();
|
||||||
} else if (newStart !== '') {
|
} else if (newStart !== '') {
|
||||||
newLineContent = newStart + ' ' + lineContent;
|
newLineContent = `${newStart} ${lineContent}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectFrom = selectionRange.from + (newLineContent.length - lineContent.length);
|
const selectFrom = selectionRange.from + (newLineContent.length - lineContent.length);
|
||||||
@ -290,7 +285,7 @@ export class Actions {
|
|||||||
|
|
||||||
const number = (Number(listMatch[2]) || 0) + 1;
|
const number = (Number(listMatch[2]) || 0) + 1;
|
||||||
const whiteSpace = listMatch[1] || '';
|
const whiteSpace = listMatch[1] || '';
|
||||||
const listMark = listMatch[3] || '.'
|
const listMark = listMatch[3] || '.';
|
||||||
|
|
||||||
const prefix = `${whiteSpace}${number}${listMark}`;
|
const prefix = `${whiteSpace}${number}${listMark}`;
|
||||||
return this.replaceLineStart(prefix);
|
return this.replaceLineStart(prefix);
|
||||||
@ -373,7 +368,7 @@ export class Actions {
|
|||||||
* @param {File} file
|
* @param {File} file
|
||||||
* @param {?Number} position
|
* @param {?Number} position
|
||||||
*/
|
*/
|
||||||
async uploadImage(file, position= null) {
|
async uploadImage(file, position = null) {
|
||||||
if (file === null || file.type.indexOf('image') !== 0) return;
|
if (file === null || file.type.indexOf('image') !== 0) return;
|
||||||
let ext = 'png';
|
let ext = 'png';
|
||||||
|
|
||||||
@ -382,17 +377,17 @@ export class Actions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (file.name) {
|
if (file.name) {
|
||||||
let fileNameMatches = file.name.match(/\.(.+)$/);
|
const fileNameMatches = file.name.match(/\.(.+)$/);
|
||||||
if (fileNameMatches.length > 1) ext = fileNameMatches[1];
|
if (fileNameMatches.length > 1) ext = fileNameMatches[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert image into markdown
|
// Insert image into markdown
|
||||||
const id = "image-" + Math.random().toString(16).slice(2);
|
const id = `image-${Math.random().toString(16).slice(2)}`;
|
||||||
const placeholderImage = window.baseUrl(`/loading.gif#upload${id}`);
|
const placeholderImage = window.baseUrl(`/loading.gif#upload${id}`);
|
||||||
const placeHolderText = `![](${placeholderImage})`;
|
const placeHolderText = `![](${placeholderImage})`;
|
||||||
this.#dispatchChange(position, position, placeHolderText, position);
|
this.#dispatchChange(position, position, placeHolderText, position);
|
||||||
|
|
||||||
const remoteFilename = "image-" + Date.now() + "." + ext;
|
const remoteFilename = `image-${Date.now()}.${ext}`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file, remoteFilename);
|
formData.append('file', file, remoteFilename);
|
||||||
formData.append('uploaded_to', this.editor.config.pageId);
|
formData.append('uploaded_to', this.editor.config.pageId);
|
||||||
@ -466,7 +461,7 @@ export class Actions {
|
|||||||
* @return {String}
|
* @return {String}
|
||||||
*/
|
*/
|
||||||
#cleanTextForEditor(text) {
|
#cleanTextForEditor(text) {
|
||||||
return text.replace(/\r\n|\r/g, "\n");
|
return text.replace(/\r\n|\r/g, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -511,7 +506,7 @@ export class Actions {
|
|||||||
* @param {?Number} selectTo
|
* @param {?Number} selectTo
|
||||||
*/
|
*/
|
||||||
#dispatchChange(from, to = null, text = null, selectFrom = null, selectTo = null) {
|
#dispatchChange(from, to = null, text = null, selectFrom = null, selectTo = null) {
|
||||||
const tr = {changes: {from, to: to, insert: text}};
|
const tr = {changes: {from, to, insert: text}};
|
||||||
|
|
||||||
if (selectFrom) {
|
if (selectFrom) {
|
||||||
tr.selection = {anchor: selectFrom};
|
tr.selection = {anchor: selectFrom};
|
||||||
@ -533,4 +528,5 @@ export class Actions {
|
|||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import {provideKeyBindings} from "./shortcuts";
|
import {provideKeyBindings} from './shortcuts';
|
||||||
import {debounce} from "../services/util";
|
import {debounce} from '../services/util';
|
||||||
import Clipboard from "../services/clipboard";
|
import Clipboard from '../services/clipboard';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiate the codemirror instance for the markdown editor.
|
* Initiate the codemirror instance for the markdown editor.
|
||||||
@ -25,9 +25,9 @@ export async function init(editor) {
|
|||||||
|
|
||||||
const domEventHandlers = {
|
const domEventHandlers = {
|
||||||
// Handle scroll to sync display view
|
// Handle scroll to sync display view
|
||||||
scroll: (event) => syncActive && onScrollDebounced(event),
|
scroll: event => syncActive && onScrollDebounced(event),
|
||||||
// Handle image & content drag n drop
|
// Handle image & content drag n drop
|
||||||
drop: (event) => {
|
drop: event => {
|
||||||
const templateId = event.dataTransfer.getData('bookstack/template');
|
const templateId = event.dataTransfer.getData('bookstack/template');
|
||||||
if (templateId) {
|
if (templateId) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -43,7 +43,7 @@ export async function init(editor) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Handle image paste
|
// Handle image paste
|
||||||
paste: (event) => {
|
paste: event => {
|
||||||
const clipboard = new Clipboard(event.clipboardData || event.dataTransfer);
|
const clipboard = new Clipboard(event.clipboardData || event.dataTransfer);
|
||||||
|
|
||||||
// Don't handle the event ourselves if no items exist of contains table-looking data
|
// Don't handle the event ourselves if no items exist of contains table-looking data
|
||||||
@ -55,8 +55,8 @@ export async function init(editor) {
|
|||||||
for (const image of images) {
|
for (const image of images) {
|
||||||
editor.actions.uploadImage(image);
|
editor.actions.uploadImage(image);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
const cm = Code.markdownEditor(
|
const cm = Code.markdownEditor(
|
||||||
editor.config.inputEl,
|
editor.config.inputEl,
|
||||||
|
@ -6,23 +6,22 @@ function getContentToInsert({html, markdown}) {
|
|||||||
* @param {MarkdownEditor} editor
|
* @param {MarkdownEditor} editor
|
||||||
*/
|
*/
|
||||||
export function listen(editor) {
|
export function listen(editor) {
|
||||||
|
window.$events.listen('editor::replace', eventContent => {
|
||||||
window.$events.listen('editor::replace', (eventContent) => {
|
|
||||||
const markdown = getContentToInsert(eventContent);
|
const markdown = getContentToInsert(eventContent);
|
||||||
editor.actions.replaceContent(markdown);
|
editor.actions.replaceContent(markdown);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.$events.listen('editor::append', (eventContent) => {
|
window.$events.listen('editor::append', eventContent => {
|
||||||
const markdown = getContentToInsert(eventContent);
|
const markdown = getContentToInsert(eventContent);
|
||||||
editor.actions.appendContent(markdown);
|
editor.actions.appendContent(markdown);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.$events.listen('editor::prepend', (eventContent) => {
|
window.$events.listen('editor::prepend', eventContent => {
|
||||||
const markdown = getContentToInsert(eventContent);
|
const markdown = getContentToInsert(eventContent);
|
||||||
editor.actions.prependContent(markdown);
|
editor.actions.prependContent(markdown);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.$events.listen('editor::insert', (eventContent) => {
|
window.$events.listen('editor::insert', eventContent => {
|
||||||
const markdown = getContentToInsert(eventContent);
|
const markdown = getContentToInsert(eventContent);
|
||||||
editor.actions.insertContent(markdown);
|
editor.actions.insertContent(markdown);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {patchDomFromHtmlString} from "../services/vdom";
|
import {patchDomFromHtmlString} from '../services/vdom';
|
||||||
|
|
||||||
export class Display {
|
export class Display {
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ export class Display {
|
|||||||
* @param {String} html
|
* @param {String} html
|
||||||
*/
|
*/
|
||||||
patchWithHtml(html) {
|
patchWithHtml(html) {
|
||||||
const body = this.doc.body;
|
const {body} = this.doc;
|
||||||
|
|
||||||
if (body.children.length === 0) {
|
if (body.children.length === 0) {
|
||||||
const wrap = document.createElement('div');
|
const wrap = document.createElement('div');
|
||||||
@ -102,8 +102,8 @@ export class Display {
|
|||||||
const elems = this.doc.body?.children[0]?.children;
|
const elems = this.doc.body?.children[0]?.children;
|
||||||
if (elems && elems.length <= index) return;
|
if (elems && elems.length <= index) return;
|
||||||
|
|
||||||
const topElem = (index === -1) ? elems[elems.length-1] : elems[index];
|
const topElem = (index === -1) ? elems[elems.length - 1] : elems[index];
|
||||||
topElem.scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'smooth'});
|
topElem.scrollIntoView({block: 'start', inline: 'nearest', behavior: 'smooth'});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,9 @@
|
|||||||
import {Markdown} from "./markdown";
|
import {Markdown} from './markdown';
|
||||||
import {Display} from "./display";
|
import {Display} from './display';
|
||||||
import {Actions} from "./actions";
|
import {Actions} from './actions';
|
||||||
import {Settings} from "./settings";
|
import {Settings} from './settings';
|
||||||
import {listen} from "./common-events";
|
import {listen} from './common-events';
|
||||||
import {init as initCodemirror} from "./codemirror";
|
import {init as initCodemirror} from './codemirror';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiate a new markdown editor instance.
|
* Initiate a new markdown editor instance.
|
||||||
@ -12,7 +11,6 @@ import {init as initCodemirror} from "./codemirror";
|
|||||||
* @returns {Promise<MarkdownEditor>}
|
* @returns {Promise<MarkdownEditor>}
|
||||||
*/
|
*/
|
||||||
export async function init(config) {
|
export async function init(config) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {MarkdownEditor}
|
* @type {MarkdownEditor}
|
||||||
*/
|
*/
|
||||||
@ -31,7 +29,6 @@ export async function init(config) {
|
|||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef MarkdownEditorConfig
|
* @typedef MarkdownEditorConfig
|
||||||
* @property {String} pageId
|
* @property {String} pageId
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import MarkdownIt from "markdown-it";
|
import MarkdownIt from 'markdown-it';
|
||||||
import mdTasksLists from 'markdown-it-task-lists';
|
import mdTasksLists from 'markdown-it-task-lists';
|
||||||
|
|
||||||
export class Markdown {
|
export class Markdown {
|
||||||
@ -24,7 +24,5 @@ export class Markdown {
|
|||||||
render(markdown) {
|
render(markdown) {
|
||||||
return this.renderer.render(markdown);
|
return this.renderer.render(markdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,4 +59,5 @@ export class Settings {
|
|||||||
listeners.push(callback);
|
listeners.push(callback);
|
||||||
this.changeListeners[key] = listeners;
|
this.changeListeners[key] = listeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -34,8 +34,8 @@ function provide(editor) {
|
|||||||
shortcuts['Mod-8'] = cm => editor.actions.wrapSelection('`', '`');
|
shortcuts['Mod-8'] = cm => editor.actions.wrapSelection('`', '`');
|
||||||
shortcuts['Shift-Mod-e'] = cm => editor.actions.wrapSelection('`', '`');
|
shortcuts['Shift-Mod-e'] = cm => editor.actions.wrapSelection('`', '`');
|
||||||
shortcuts['Mod-9'] = cm => editor.actions.cycleCalloutTypeAtSelection();
|
shortcuts['Mod-9'] = cm => editor.actions.cycleCalloutTypeAtSelection();
|
||||||
shortcuts['Mod-p'] = cm => editor.actions.replaceLineStart('-')
|
shortcuts['Mod-p'] = cm => editor.actions.replaceLineStart('-');
|
||||||
shortcuts['Mod-o'] = cm => editor.actions.replaceLineStartForOrderedList()
|
shortcuts['Mod-o'] = cm => editor.actions.replaceLineStartForOrderedList();
|
||||||
|
|
||||||
return shortcuts;
|
return shortcuts;
|
||||||
}
|
}
|
||||||
@ -46,15 +46,13 @@ function provide(editor) {
|
|||||||
* @return {{key: String, run: function, preventDefault: boolean}[]}
|
* @return {{key: String, run: function, preventDefault: boolean}[]}
|
||||||
*/
|
*/
|
||||||
export function provideKeyBindings(editor) {
|
export function provideKeyBindings(editor) {
|
||||||
const shortcuts= provide(editor);
|
const shortcuts = provide(editor);
|
||||||
const keyBindings = [];
|
const keyBindings = [];
|
||||||
|
|
||||||
const wrapAction = (action) => {
|
const wrapAction = action => () => {
|
||||||
return () => {
|
|
||||||
action();
|
action();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
for (const [shortcut, action] of Object.entries(shortcuts)) {
|
for (const [shortcut, action] of Object.entries(shortcuts)) {
|
||||||
keyBindings.push({key: shortcut, run: wrapAction(action), preventDefault: true});
|
keyBindings.push({key: shortcut, run: wrapAction(action), preventDefault: true});
|
||||||
|
@ -15,7 +15,7 @@ export function fadeIn(element, animTime = 400, onComplete = null) {
|
|||||||
cleanupExistingElementAnimation(element);
|
cleanupExistingElementAnimation(element);
|
||||||
element.style.display = 'block';
|
element.style.display = 'block';
|
||||||
animateStyles(element, {
|
animateStyles(element, {
|
||||||
opacity: ['0', '1']
|
opacity: ['0', '1'],
|
||||||
}, animTime, () => {
|
}, animTime, () => {
|
||||||
if (onComplete) onComplete();
|
if (onComplete) onComplete();
|
||||||
});
|
});
|
||||||
@ -30,7 +30,7 @@ export function fadeIn(element, animTime = 400, onComplete = null) {
|
|||||||
export function fadeOut(element, animTime = 400, onComplete = null) {
|
export function fadeOut(element, animTime = 400, onComplete = null) {
|
||||||
cleanupExistingElementAnimation(element);
|
cleanupExistingElementAnimation(element);
|
||||||
animateStyles(element, {
|
animateStyles(element, {
|
||||||
opacity: ['1', '0']
|
opacity: ['1', '0'],
|
||||||
}, animTime, () => {
|
}, animTime, () => {
|
||||||
element.style.display = 'none';
|
element.style.display = 'none';
|
||||||
if (onComplete) onComplete();
|
if (onComplete) onComplete();
|
||||||
@ -125,12 +125,12 @@ export function transitionHeight(element, animTime = 400) {
|
|||||||
*/
|
*/
|
||||||
function animateStyles(element, styles, animTime = 400, onComplete = null) {
|
function animateStyles(element, styles, animTime = 400, onComplete = null) {
|
||||||
const styleNames = Object.keys(styles);
|
const styleNames = Object.keys(styles);
|
||||||
for (let style of styleNames) {
|
for (const style of styleNames) {
|
||||||
element.style[style] = styles[style][0];
|
element.style[style] = styles[style][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
for (let style of styleNames) {
|
for (const style of styleNames) {
|
||||||
element.style[style] = null;
|
element.style[style] = null;
|
||||||
}
|
}
|
||||||
element.style.transition = null;
|
element.style.transition = null;
|
||||||
@ -141,7 +141,7 @@ function animateStyles(element, styles, animTime = 400, onComplete = null) {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
element.style.transition = `all ease-in-out ${animTime}ms`;
|
element.style.transition = `all ease-in-out ${animTime}ms`;
|
||||||
for (let style of styleNames) {
|
for (const style of styleNames) {
|
||||||
element.style[style] = styles[style][1];
|
element.style[style] = styles[style][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
export class Clipboard {
|
export class Clipboard {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,7 +20,7 @@ export class Clipboard {
|
|||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
containsTabularData() {
|
containsTabularData() {
|
||||||
const rtfData = this.data.getData( 'text/rtf');
|
const rtfData = this.data.getData('text/rtf');
|
||||||
return rtfData && rtfData.includes('\\trowd');
|
return rtfData && rtfData.includes('\\trowd');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,8 +29,8 @@ export class Clipboard {
|
|||||||
* @return {Array<File>}
|
* @return {Array<File>}
|
||||||
*/
|
*/
|
||||||
getImages() {
|
getImages() {
|
||||||
const types = this.data.types;
|
const {types} = this.data;
|
||||||
const files = this.data.files;
|
const {files} = this.data;
|
||||||
const images = [];
|
const images = [];
|
||||||
|
|
||||||
for (const type of types) {
|
for (const type of types) {
|
||||||
@ -49,6 +48,7 @@ export class Clipboard {
|
|||||||
|
|
||||||
return images;
|
return images;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function copyTextToClipboard(text) {
|
export async function copyTextToClipboard(text) {
|
||||||
@ -58,12 +58,12 @@ export async function copyTextToClipboard(text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Backup option where we can't use the navigator.clipboard API
|
// Backup option where we can't use the navigator.clipboard API
|
||||||
const tempInput = document.createElement("textarea");
|
const tempInput = document.createElement('textarea');
|
||||||
tempInput.style = "position: absolute; left: -1000px; top: -1000px;";
|
tempInput.style = 'position: absolute; left: -1000px; top: -1000px;';
|
||||||
tempInput.value = text;
|
tempInput.value = text;
|
||||||
document.body.appendChild(tempInput);
|
document.body.appendChild(tempInput);
|
||||||
tempInput.select();
|
tempInput.select();
|
||||||
document.execCommand("copy");
|
document.execCommand('copy');
|
||||||
document.body.removeChild(tempInput);
|
document.body.removeChild(tempInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {kebabToCamel, camelToKebab} from "./text";
|
import {kebabToCamel, camelToKebab} from './text';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapping of active components keyed by name, with values being arrays of component
|
* A mapping of active components keyed by name, with values being arrays of component
|
||||||
@ -25,12 +25,12 @@ const elementComponentMap = new WeakMap();
|
|||||||
* @param {Element} element
|
* @param {Element} element
|
||||||
*/
|
*/
|
||||||
function initComponent(name, element) {
|
function initComponent(name, element) {
|
||||||
/** @type {Function<Component>|undefined} **/
|
/** @type {Function<Component>|undefined} * */
|
||||||
const componentModel = componentModelMap[name];
|
const componentModel = componentModelMap[name];
|
||||||
if (componentModel === undefined) return;
|
if (componentModel === undefined) return;
|
||||||
|
|
||||||
// Create our component instance
|
// Create our component instance
|
||||||
/** @type {Component} **/
|
/** @type {Component} * */
|
||||||
let instance;
|
let instance;
|
||||||
try {
|
try {
|
||||||
instance = new componentModel();
|
instance = new componentModel();
|
||||||
@ -46,7 +46,7 @@ function initComponent(name, element) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add to global listing
|
// Add to global listing
|
||||||
if (typeof components[name] === "undefined") {
|
if (typeof components[name] === 'undefined') {
|
||||||
components[name] = [];
|
components[name] = [];
|
||||||
}
|
}
|
||||||
components[name].push(instance);
|
components[name].push(instance);
|
||||||
@ -67,7 +67,7 @@ function parseRefs(name, element) {
|
|||||||
const refs = {};
|
const refs = {};
|
||||||
const manyRefs = {};
|
const manyRefs = {};
|
||||||
|
|
||||||
const prefix = `${name}@`
|
const prefix = `${name}@`;
|
||||||
const selector = `[refs*="${prefix}"]`;
|
const selector = `[refs*="${prefix}"]`;
|
||||||
const refElems = [...element.querySelectorAll(selector)];
|
const refElems = [...element.querySelectorAll(selector)];
|
||||||
if (element.matches(selector)) {
|
if (element.matches(selector)) {
|
||||||
@ -114,7 +114,7 @@ function parseOpts(name, element) {
|
|||||||
* @param {Element|Document} parentElement
|
* @param {Element|Document} parentElement
|
||||||
*/
|
*/
|
||||||
export function init(parentElement = document) {
|
export function init(parentElement = document) {
|
||||||
const componentElems = parentElement.querySelectorAll(`[component],[components]`);
|
const componentElems = parentElement.querySelectorAll('[component],[components]');
|
||||||
|
|
||||||
for (const el of componentElems) {
|
for (const el of componentElems) {
|
||||||
const componentNames = `${el.getAttribute('component') || ''} ${(el.getAttribute('components'))}`.toLowerCase().split(' ').filter(Boolean);
|
const componentNames = `${el.getAttribute('component') || ''} ${(el.getAttribute('components'))}`.toLowerCase().split(' ').filter(Boolean);
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
|
|
||||||
export function getCurrentDay() {
|
export function getCurrentDay() {
|
||||||
let date = new Date();
|
const date = new Date();
|
||||||
let month = date.getMonth() + 1;
|
const month = date.getMonth() + 1;
|
||||||
let day = date.getDate();
|
const day = date.getDate();
|
||||||
|
|
||||||
return `${date.getFullYear()}-${(month>9?'':'0') + month}-${(day>9?'':'0') + day}`;
|
return `${date.getFullYear()}-${(month > 9 ? '' : '0') + month}-${(day > 9 ? '' : '0') + day}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function utcTimeStampToLocalTime(timestamp) {
|
export function utcTimeStampToLocalTime(timestamp) {
|
||||||
let date = new Date(timestamp * 1000);
|
const date = new Date(timestamp * 1000);
|
||||||
let hours = date.getHours();
|
const hours = date.getHours();
|
||||||
let mins = date.getMinutes();
|
const mins = date.getMinutes();
|
||||||
return `${(hours>9?'':'0') + hours}:${(mins>9?'':'0') + mins}`;
|
return `${(hours > 9 ? '' : '0') + hours}:${(mins > 9 ? '' : '0') + mins}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatDateTime(date) {
|
export function formatDateTime(date) {
|
||||||
let month = date.getMonth() + 1;
|
const month = date.getMonth() + 1;
|
||||||
let day = date.getDate();
|
const day = date.getDate();
|
||||||
let hours = date.getHours();
|
const hours = date.getHours();
|
||||||
let mins = date.getMinutes();
|
const mins = date.getMinutes();
|
||||||
|
|
||||||
return `${date.getFullYear()}-${(month>9?'':'0') + month}-${(day>9?'':'0') + day} ${(hours>9?'':'0') + hours}:${(mins>9?'':'0') + mins}`;
|
return `${date.getFullYear()}-${(month > 9 ? '' : '0') + month}-${(day > 9 ? '' : '0') + day} ${(hours > 9 ? '' : '0') + hours}:${(mins > 9 ? '' : '0') + mins}`;
|
||||||
}
|
}
|
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
export function forEach(selector, callback) {
|
export function forEach(selector, callback) {
|
||||||
const elements = document.querySelectorAll(selector);
|
const elements = document.querySelectorAll(selector);
|
||||||
for (let element of elements) {
|
for (const element of elements) {
|
||||||
callback(element);
|
callback(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -17,7 +17,7 @@ export function forEach(selector, callback) {
|
|||||||
* @param {Function<Event>} callback
|
* @param {Function<Event>} callback
|
||||||
*/
|
*/
|
||||||
export function onEvents(listenerElement, events, callback) {
|
export function onEvents(listenerElement, events, callback) {
|
||||||
for (let eventName of events) {
|
for (const eventName of events) {
|
||||||
listenerElement.addEventListener(eventName, callback);
|
listenerElement.addEventListener(eventName, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ export function onSelect(elements, callback) {
|
|||||||
|
|
||||||
for (const listenerElement of elements) {
|
for (const listenerElement of elements) {
|
||||||
listenerElement.addEventListener('click', callback);
|
listenerElement.addEventListener('click', callback);
|
||||||
listenerElement.addEventListener('keydown', (event) => {
|
listenerElement.addEventListener('keydown', event => {
|
||||||
if (event.key === 'Enter' || event.key === ' ') {
|
if (event.key === 'Enter' || event.key === ' ') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
callback(event);
|
callback(event);
|
||||||
@ -58,7 +58,7 @@ export function onEnterPress(elements, callback) {
|
|||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
callback(event);
|
callback(event);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
elements.forEach(e => e.addEventListener('keypress', listener));
|
elements.forEach(e => e.addEventListener('keypress', listener));
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ export function onEnterPress(elements, callback) {
|
|||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
export function onChildEvent(listenerElement, childSelector, eventName, callback) {
|
export function onChildEvent(listenerElement, childSelector, eventName, callback) {
|
||||||
listenerElement.addEventListener(eventName, function(event) {
|
listenerElement.addEventListener(eventName, event => {
|
||||||
const matchingChild = event.target.closest(childSelector);
|
const matchingChild = event.target.closest(childSelector);
|
||||||
if (matchingChild) {
|
if (matchingChild) {
|
||||||
callback.call(matchingChild, event, matchingChild);
|
callback.call(matchingChild, event, matchingChild);
|
||||||
@ -91,7 +91,7 @@ export function onChildEvent(listenerElement, childSelector, eventName, callback
|
|||||||
export function findText(selector, text) {
|
export function findText(selector, text) {
|
||||||
const elements = document.querySelectorAll(selector);
|
const elements = document.querySelectorAll(selector);
|
||||||
text = text.toLowerCase();
|
text = text.toLowerCase();
|
||||||
for (let element of elements) {
|
for (const element of elements) {
|
||||||
if (element.textContent.toLowerCase().includes(text)) {
|
if (element.textContent.toLowerCase().includes(text)) {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ export function findText(selector, text) {
|
|||||||
* @param {Element} element
|
* @param {Element} element
|
||||||
*/
|
*/
|
||||||
export function showLoading(element) {
|
export function showLoading(element) {
|
||||||
element.innerHTML = `<div class="loading-container"><div></div><div></div><div></div></div>`;
|
element.innerHTML = '<div class="loading-container"><div></div><div></div><div></div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
let iFrame = null;
|
let iFrame = null;
|
||||||
let lastApprovedOrigin;
|
let lastApprovedOrigin;
|
||||||
let onInit, onSave;
|
let onInit; let
|
||||||
|
onSave;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the draw.io editor.
|
* Show the draw.io editor.
|
||||||
@ -55,13 +56,15 @@ function drawEventExport(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function drawEventSave(message) {
|
function drawEventSave(message) {
|
||||||
drawPostMessage({action: 'export', format: 'xmlpng', xml: message.xml, spin: 'Updating drawing'});
|
drawPostMessage({
|
||||||
|
action: 'export', format: 'xmlpng', xml: message.xml, spin: 'Updating drawing',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawEventInit() {
|
function drawEventInit() {
|
||||||
if (!onInit) return;
|
if (!onInit) return;
|
||||||
onInit().then(xml => {
|
onInit().then(xml => {
|
||||||
drawPostMessage({action: 'load', autosave: 1, xml: xml});
|
drawPostMessage({action: 'load', autosave: 1, xml});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,11 +84,11 @@ function drawPostMessage(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function upload(imageData, pageUploadedToId) {
|
async function upload(imageData, pageUploadedToId) {
|
||||||
let data = {
|
const data = {
|
||||||
image: imageData,
|
image: imageData,
|
||||||
uploaded_to: pageUploadedToId,
|
uploaded_to: pageUploadedToId,
|
||||||
};
|
};
|
||||||
const resp = await window.$http.post(window.baseUrl(`/images/drawio`), data);
|
const resp = await window.$http.post(window.baseUrl('/images/drawio'), data);
|
||||||
return resp.data;
|
return resp.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,4 +110,6 @@ async function load(drawingId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {show, close, upload, load};
|
export default {
|
||||||
|
show, close, upload, load,
|
||||||
|
};
|
||||||
|
@ -9,9 +9,9 @@ const stack = [];
|
|||||||
function emit(eventName, eventData) {
|
function emit(eventName, eventData) {
|
||||||
stack.push({name: eventName, data: eventData});
|
stack.push({name: eventName, data: eventData});
|
||||||
if (typeof listeners[eventName] === 'undefined') return this;
|
if (typeof listeners[eventName] === 'undefined') return this;
|
||||||
let eventsToStart = listeners[eventName];
|
const eventsToStart = listeners[eventName];
|
||||||
for (let i = 0; i < eventsToStart.length; i++) {
|
for (let i = 0; i < eventsToStart.length; i++) {
|
||||||
let event = eventsToStart[i];
|
const event = eventsToStart[i];
|
||||||
event(eventData);
|
event(eventData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ function listen(eventName, callback) {
|
|||||||
function emitPublic(targetElement, eventName, eventData) {
|
function emitPublic(targetElement, eventName, eventData) {
|
||||||
const event = new CustomEvent(eventName, {
|
const event = new CustomEvent(eventName, {
|
||||||
detail: eventData,
|
detail: eventData,
|
||||||
bubbles: true
|
bubbles: true,
|
||||||
});
|
});
|
||||||
targetElement.dispatchEvent(event);
|
targetElement.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
@ -69,8 +69,8 @@ export default {
|
|||||||
emit,
|
emit,
|
||||||
emitPublic,
|
emitPublic,
|
||||||
listen,
|
listen,
|
||||||
success: (msg) => emit('success', msg),
|
success: msg => emit('success', msg),
|
||||||
error: (msg) => emit('error', msg),
|
error: msg => emit('error', msg),
|
||||||
showValidationErrors,
|
showValidationErrors,
|
||||||
showResponseError,
|
showResponseError,
|
||||||
}
|
};
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a HTTP GET request.
|
* Perform a HTTP GET request.
|
||||||
* Can easily pass query parameters as the second parameter.
|
* Can easily pass query parameters as the second parameter.
|
||||||
@ -63,7 +62,7 @@ async function performDelete(url, data = null) {
|
|||||||
*/
|
*/
|
||||||
async function dataRequest(method, url, data = null) {
|
async function dataRequest(method, url, data = null) {
|
||||||
const options = {
|
const options = {
|
||||||
method: method,
|
method,
|
||||||
body: data,
|
body: data,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,7 +83,7 @@ async function dataRequest(method, url, data = null) {
|
|||||||
options.method = 'post';
|
options.method = 'post';
|
||||||
}
|
}
|
||||||
|
|
||||||
return request(url, options)
|
return request(url, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,7 +100,7 @@ async function request(url, options = {}) {
|
|||||||
|
|
||||||
if (options.params) {
|
if (options.params) {
|
||||||
const urlObj = new URL(url);
|
const urlObj = new URL(url);
|
||||||
for (let paramName of Object.keys(options.params)) {
|
for (const paramName of Object.keys(options.params)) {
|
||||||
const value = options.params[paramName];
|
const value = options.params[paramName];
|
||||||
if (typeof value !== 'undefined' && value !== null) {
|
if (typeof value !== 'undefined' && value !== null) {
|
||||||
urlObj.searchParams.set(paramName, value);
|
urlObj.searchParams.set(paramName, value);
|
||||||
@ -111,13 +110,12 @@ async function request(url, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const csrfToken = document.querySelector('meta[name=token]').getAttribute('content');
|
const csrfToken = document.querySelector('meta[name=token]').getAttribute('content');
|
||||||
options = Object.assign({}, options, {
|
options = {...options, credentials: 'same-origin'};
|
||||||
'credentials': 'same-origin',
|
options.headers = {
|
||||||
});
|
...options.headers || {},
|
||||||
options.headers = Object.assign({}, options.headers || {}, {
|
baseURL: window.baseUrl(''),
|
||||||
'baseURL': window.baseUrl(''),
|
|
||||||
'X-CSRF-TOKEN': csrfToken,
|
'X-CSRF-TOKEN': csrfToken,
|
||||||
});
|
};
|
||||||
|
|
||||||
const response = await fetch(url, options);
|
const response = await fetch(url, options);
|
||||||
const content = await getResponseContent(response);
|
const content = await getResponseContent(response);
|
||||||
@ -160,6 +158,7 @@ async function getResponseContent(response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class HttpError extends Error {
|
class HttpError extends Error {
|
||||||
|
|
||||||
constructor(response, content) {
|
constructor(response, content) {
|
||||||
super(response.statusText);
|
super(response.statusText);
|
||||||
this.data = content;
|
this.data = content;
|
||||||
@ -170,13 +169,14 @@ class HttpError extends Error {
|
|||||||
this.url = response.url;
|
this.url = response.url;
|
||||||
this.original = response;
|
this.original = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
get: get,
|
get,
|
||||||
post: post,
|
post,
|
||||||
put: put,
|
put,
|
||||||
patch: patch,
|
patch,
|
||||||
delete: performDelete,
|
delete: performDelete,
|
||||||
HttpError: HttpError,
|
HttpError,
|
||||||
};
|
};
|
@ -57,7 +57,6 @@ export class KeyboardNavigationHandler {
|
|||||||
* @param {KeyboardEvent} event
|
* @param {KeyboardEvent} event
|
||||||
*/
|
*/
|
||||||
#keydownHandler(event) {
|
#keydownHandler(event) {
|
||||||
|
|
||||||
// Ignore certain key events in inputs to allow text editing.
|
// Ignore certain key events in inputs to allow text editing.
|
||||||
if (event.target.matches('input') && (event.key === 'ArrowRight' || event.key === 'ArrowLeft')) {
|
if (event.target.matches('input') && (event.key === 'ArrowRight' || event.key === 'ArrowLeft')) {
|
||||||
return;
|
return;
|
||||||
@ -88,8 +87,9 @@ export class KeyboardNavigationHandler {
|
|||||||
const focusable = [];
|
const focusable = [];
|
||||||
const selector = '[tabindex]:not([tabindex="-1"]),[href],button:not([tabindex="-1"],[disabled]),input:not([type=hidden])';
|
const selector = '[tabindex]:not([tabindex="-1"]),[href],button:not([tabindex="-1"],[disabled]),input:not([type=hidden])';
|
||||||
for (const container of this.containers) {
|
for (const container of this.containers) {
|
||||||
focusable.push(...container.querySelectorAll(selector))
|
focusable.push(...container.querySelectorAll(selector));
|
||||||
}
|
}
|
||||||
return focusable;
|
return focusable;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,7 +4,7 @@
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function kebabToCamel(kebab) {
|
export function kebabToCamel(kebab) {
|
||||||
const ucFirst = (word) => word.slice(0,1).toUpperCase() + word.slice(1);
|
const ucFirst = word => word.slice(0, 1).toUpperCase() + word.slice(1);
|
||||||
const words = kebab.split('-');
|
const words = kebab.split('-');
|
||||||
return words[0] + words.slice(1).map(ucFirst).join('');
|
return words[0] + words.slice(1).map(ucFirst).join('');
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ class Translator {
|
|||||||
*/
|
*/
|
||||||
parseTranslations() {
|
parseTranslations() {
|
||||||
const translationMetaTags = document.querySelectorAll('meta[name="translation"]');
|
const translationMetaTags = document.querySelectorAll('meta[name="translation"]');
|
||||||
for (let tag of translationMetaTags) {
|
for (const tag of translationMetaTags) {
|
||||||
const key = tag.getAttribute('key');
|
const key = tag.getAttribute('key');
|
||||||
const value = tag.getAttribute('value');
|
const value = tag.getAttribute('value');
|
||||||
this.store.set(key, value);
|
this.store.set(key, value);
|
||||||
@ -64,7 +64,7 @@ class Translator {
|
|||||||
const rangeRegex = /^\[([0-9]+),([0-9*]+)]/;
|
const rangeRegex = /^\[([0-9]+),([0-9*]+)]/;
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
for (let t of splitText) {
|
for (const t of splitText) {
|
||||||
// Parse exact matches
|
// Parse exact matches
|
||||||
const exactMatches = t.match(exactCountRegex);
|
const exactMatches = t.match(exactCountRegex);
|
||||||
if (exactMatches !== null && Number(exactMatches[1]) === count) {
|
if (exactMatches !== null && Number(exactMatches[1]) === count) {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a function, that, as long as it continues to be invoked, will not
|
* Returns a function, that, as long as it continues to be invoked, will not
|
||||||
* be triggered. The function will be called after it stops being called for
|
* be triggered. The function will be called after it stops being called for
|
||||||
@ -14,7 +12,8 @@
|
|||||||
export function debounce(func, wait, immediate) {
|
export function debounce(func, wait, immediate) {
|
||||||
let timeout;
|
let timeout;
|
||||||
return function() {
|
return function() {
|
||||||
const context = this, args = arguments;
|
const context = this; const
|
||||||
|
args = arguments;
|
||||||
const later = function() {
|
const later = function() {
|
||||||
timeout = null;
|
timeout = null;
|
||||||
if (!immediate) func.apply(context, args);
|
if (!immediate) func.apply(context, args);
|
||||||
@ -24,7 +23,7 @@ export function debounce(func, wait, immediate) {
|
|||||||
timeout = setTimeout(later, wait);
|
timeout = setTimeout(later, wait);
|
||||||
if (callNow) func.apply(context, args);
|
if (callNow) func.apply(context, args);
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scroll and highlight an element.
|
* Scroll and highlight an element.
|
||||||
@ -55,11 +54,11 @@ export function scrollAndHighlightElement(element) {
|
|||||||
*/
|
*/
|
||||||
export function escapeHtml(unsafe) {
|
export function escapeHtml(unsafe) {
|
||||||
return unsafe
|
return unsafe
|
||||||
.replace(/&/g, "&")
|
.replace(/&/g, '&')
|
||||||
.replace(/</g, "<")
|
.replace(/</g, '<')
|
||||||
.replace(/>/g, ">")
|
.replace(/>/g, '>')
|
||||||
.replace(/"/g, """)
|
.replace(/"/g, '"')
|
||||||
.replace(/'/g, "'");
|
.replace(/'/g, ''');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,6 +67,6 @@ export function escapeHtml(unsafe) {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function uniqueId() {
|
export function uniqueId() {
|
||||||
const S4 = () => (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
const S4 = () => (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
||||||
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
return (`${S4() + S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`);
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
init,
|
init,
|
||||||
attributesModule,
|
attributesModule,
|
||||||
toVNode
|
toVNode,
|
||||||
} from "snabbdom";
|
} from 'snabbdom';
|
||||||
|
|
||||||
let patcher;
|
let patcher;
|
||||||
|
|
||||||
@ -12,7 +12,6 @@ let patcher;
|
|||||||
function getPatcher() {
|
function getPatcher() {
|
||||||
if (patcher) return patcher;
|
if (patcher) return patcher;
|
||||||
|
|
||||||
|
|
||||||
patcher = init([
|
patcher = init([
|
||||||
attributesModule,
|
attributesModule,
|
||||||
]);
|
]);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
*/
|
*/
|
||||||
export function listen(editor) {
|
export function listen(editor) {
|
||||||
|
|
||||||
// Replace editor content
|
// Replace editor content
|
||||||
window.$events.listen('editor::replace', ({html}) => {
|
window.$events.listen('editor::replace', ({html}) => {
|
||||||
editor.setContent(html);
|
editor.setContent(html);
|
||||||
|
@ -1,32 +1,35 @@
|
|||||||
import {register as registerShortcuts} from "./shortcuts";
|
import {register as registerShortcuts} from './shortcuts';
|
||||||
import {listen as listenForCommonEvents} from "./common-events";
|
import {listen as listenForCommonEvents} from './common-events';
|
||||||
import {scrollToQueryString} from "./scrolling";
|
import {scrollToQueryString} from './scrolling';
|
||||||
import {listenForDragAndPaste} from "./drop-paste-handling";
|
import {listenForDragAndPaste} from './drop-paste-handling';
|
||||||
import {getPrimaryToolbar, registerAdditionalToolbars} from "./toolbars";
|
import {getPrimaryToolbar, registerAdditionalToolbars} from './toolbars';
|
||||||
import {registerCustomIcons} from "./icons";
|
import {registerCustomIcons} from './icons';
|
||||||
|
|
||||||
import {getPlugin as getCodeeditorPlugin} from "./plugin-codeeditor";
|
import {getPlugin as getCodeeditorPlugin} from './plugin-codeeditor';
|
||||||
import {getPlugin as getDrawioPlugin} from "./plugin-drawio";
|
import {getPlugin as getDrawioPlugin} from './plugin-drawio';
|
||||||
import {getPlugin as getCustomhrPlugin} from "./plugins-customhr";
|
import {getPlugin as getCustomhrPlugin} from './plugins-customhr';
|
||||||
import {getPlugin as getImagemanagerPlugin} from "./plugins-imagemanager";
|
import {getPlugin as getImagemanagerPlugin} from './plugins-imagemanager';
|
||||||
import {getPlugin as getAboutPlugin} from "./plugins-about";
|
import {getPlugin as getAboutPlugin} from './plugins-about';
|
||||||
import {getPlugin as getDetailsPlugin} from "./plugins-details";
|
import {getPlugin as getDetailsPlugin} from './plugins-details';
|
||||||
import {getPlugin as getTasklistPlugin} from "./plugins-tasklist";
|
import {getPlugin as getTasklistPlugin} from './plugins-tasklist';
|
||||||
|
|
||||||
const style_formats = [
|
const style_formats = [
|
||||||
{title: "Large Header", format: "h2", preview: 'color: blue;'},
|
{title: 'Large Header', format: 'h2', preview: 'color: blue;'},
|
||||||
{title: "Medium Header", format: "h3"},
|
{title: 'Medium Header', format: 'h3'},
|
||||||
{title: "Small Header", format: "h4"},
|
{title: 'Small Header', format: 'h4'},
|
||||||
{title: "Tiny Header", format: "h5"},
|
{title: 'Tiny Header', format: 'h5'},
|
||||||
{title: "Paragraph", format: "p", exact: true, classes: ''},
|
|
||||||
{title: "Blockquote", format: "blockquote"},
|
|
||||||
{
|
{
|
||||||
title: "Callouts", items: [
|
title: 'Paragraph', format: 'p', exact: true, classes: '',
|
||||||
{title: "Information", format: 'calloutinfo'},
|
},
|
||||||
{title: "Success", format: 'calloutsuccess'},
|
{title: 'Blockquote', format: 'blockquote'},
|
||||||
{title: "Warning", format: 'calloutwarning'},
|
{
|
||||||
{title: "Danger", format: 'calloutdanger'}
|
title: 'Callouts',
|
||||||
]
|
items: [
|
||||||
|
{title: 'Information', format: 'calloutinfo'},
|
||||||
|
{title: 'Success', format: 'calloutsuccess'},
|
||||||
|
{title: 'Warning', format: 'calloutwarning'},
|
||||||
|
{title: 'Danger', format: 'calloutdanger'},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -37,7 +40,7 @@ const formats = {
|
|||||||
calloutsuccess: {block: 'p', exact: true, attributes: {class: 'callout success'}},
|
calloutsuccess: {block: 'p', exact: true, attributes: {class: 'callout success'}},
|
||||||
calloutinfo: {block: 'p', exact: true, attributes: {class: 'callout info'}},
|
calloutinfo: {block: 'p', exact: true, attributes: {class: 'callout info'}},
|
||||||
calloutwarning: {block: 'p', exact: true, attributes: {class: 'callout warning'}},
|
calloutwarning: {block: 'p', exact: true, attributes: {class: 'callout warning'}},
|
||||||
calloutdanger: {block: 'p', exact: true, attributes: {class: 'callout danger'}}
|
calloutdanger: {block: 'p', exact: true, attributes: {class: 'callout danger'}},
|
||||||
};
|
};
|
||||||
|
|
||||||
const color_map = [
|
const color_map = [
|
||||||
@ -66,14 +69,13 @@ const color_map = [
|
|||||||
'#34495E', '',
|
'#34495E', '',
|
||||||
|
|
||||||
'#000000', '',
|
'#000000', '',
|
||||||
'#ffffff', ''
|
'#ffffff', '',
|
||||||
];
|
];
|
||||||
|
|
||||||
function file_picker_callback(callback, value, meta) {
|
function file_picker_callback(callback, value, meta) {
|
||||||
|
|
||||||
// field_name, url, type, win
|
// field_name, url, type, win
|
||||||
if (meta.filetype === 'file') {
|
if (meta.filetype === 'file') {
|
||||||
/** @type {EntitySelectorPopup} **/
|
/** @type {EntitySelectorPopup} * */
|
||||||
const selector = window.$components.first('entity-selector-popup');
|
const selector = window.$components.first('entity-selector-popup');
|
||||||
selector.show(entity => {
|
selector.show(entity => {
|
||||||
callback(entity.link, {
|
callback(entity.link, {
|
||||||
@ -85,13 +87,12 @@ function file_picker_callback(callback, value, meta) {
|
|||||||
|
|
||||||
if (meta.filetype === 'image') {
|
if (meta.filetype === 'image') {
|
||||||
// Show image manager
|
// Show image manager
|
||||||
/** @type {ImageManager} **/
|
/** @type {ImageManager} * */
|
||||||
const imageManager = window.$components.first('image-manager');
|
const imageManager = window.$components.first('image-manager');
|
||||||
imageManager.show(function (image) {
|
imageManager.show(image => {
|
||||||
callback(image.url, {alt: image.name});
|
callback(image.url, {alt: image.name});
|
||||||
}, 'gallery');
|
}, 'gallery');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,21 +101,21 @@ function file_picker_callback(callback, value, meta) {
|
|||||||
*/
|
*/
|
||||||
function gatherPlugins(options) {
|
function gatherPlugins(options) {
|
||||||
const plugins = [
|
const plugins = [
|
||||||
"image",
|
'image',
|
||||||
"table",
|
'table',
|
||||||
"link",
|
'link',
|
||||||
"autolink",
|
'autolink',
|
||||||
"fullscreen",
|
'fullscreen',
|
||||||
"code",
|
'code',
|
||||||
"customhr",
|
'customhr',
|
||||||
"autosave",
|
'autosave',
|
||||||
"lists",
|
'lists',
|
||||||
"codeeditor",
|
'codeeditor',
|
||||||
"media",
|
'media',
|
||||||
"imagemanager",
|
'imagemanager',
|
||||||
"about",
|
'about',
|
||||||
"details",
|
'details',
|
||||||
"tasklist",
|
'tasklist',
|
||||||
options.textDirection === 'rtl' ? 'directionality' : '',
|
options.textDirection === 'rtl' ? 'directionality' : '',
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -137,11 +138,11 @@ function gatherPlugins(options) {
|
|||||||
* Fetch custom HTML head content from the parent page head into the editor.
|
* Fetch custom HTML head content from the parent page head into the editor.
|
||||||
*/
|
*/
|
||||||
function fetchCustomHeadContent() {
|
function fetchCustomHeadContent() {
|
||||||
const headContentLines = document.head.innerHTML.split("\n");
|
const headContentLines = document.head.innerHTML.split('\n');
|
||||||
const startLineIndex = headContentLines.findIndex(line => line.trim() === '<!-- Start: custom user content -->');
|
const startLineIndex = headContentLines.findIndex(line => line.trim() === '<!-- Start: custom user content -->');
|
||||||
const endLineIndex = headContentLines.findIndex(line => line.trim() === '<!-- End: custom user content -->');
|
const endLineIndex = headContentLines.findIndex(line => line.trim() === '<!-- End: custom user content -->');
|
||||||
if (startLineIndex === -1 || endLineIndex === -1) {
|
if (startLineIndex === -1 || endLineIndex === -1) {
|
||||||
return ''
|
return '';
|
||||||
}
|
}
|
||||||
return headContentLines.slice(startLineIndex + 1, endLineIndex).join('\n');
|
return headContentLines.slice(startLineIndex + 1, endLineIndex).join('\n');
|
||||||
}
|
}
|
||||||
@ -152,7 +153,7 @@ function fetchCustomHeadContent() {
|
|||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
*/
|
*/
|
||||||
function setupBrFilter(editor) {
|
function setupBrFilter(editor) {
|
||||||
editor.serializer.addNodeFilter('br', function(nodes) {
|
editor.serializer.addNodeFilter('br', nodes => {
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
if (node.parent && node.parent.name === 'code') {
|
if (node.parent && node.parent.name === 'code') {
|
||||||
const newline = tinymce.html.Node.create('#text');
|
const newline = tinymce.html.Node.create('#text');
|
||||||
@ -200,9 +201,9 @@ function getSetupCallback(options) {
|
|||||||
icon: 'sourcecode',
|
icon: 'sourcecode',
|
||||||
onAction() {
|
onAction() {
|
||||||
editor.execCommand('mceToggleFormat', false, 'code');
|
editor.execCommand('mceToggleFormat', false, 'code');
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -229,7 +230,6 @@ body {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
export function build(options) {
|
export function build(options) {
|
||||||
|
|
||||||
// Set language
|
// Set language
|
||||||
window.tinymce.addI18n(options.language, options.translationMap);
|
window.tinymce.addI18n(options.language, options.translationMap);
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ export function build(options) {
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
selector: '#html-editor',
|
selector: '#html-editor',
|
||||||
cache_suffix: '?version=' + version,
|
cache_suffix: `?version=${version}`,
|
||||||
content_css: [
|
content_css: [
|
||||||
window.baseUrl('/dist/styles.css'),
|
window.baseUrl('/dist/styles.css'),
|
||||||
],
|
],
|
||||||
@ -263,12 +263,12 @@ export function build(options) {
|
|||||||
automatic_uploads: false,
|
automatic_uploads: false,
|
||||||
custom_elements: 'doc-root,code-block',
|
custom_elements: 'doc-root,code-block',
|
||||||
valid_children: [
|
valid_children: [
|
||||||
"-div[p|h1|h2|h3|h4|h5|h6|blockquote|code-block]",
|
'-div[p|h1|h2|h3|h4|h5|h6|blockquote|code-block]',
|
||||||
"+div[pre|img]",
|
'+div[pre|img]',
|
||||||
"-doc-root[doc-root|#text]",
|
'-doc-root[doc-root|#text]',
|
||||||
"-li[details]",
|
'-li[details]',
|
||||||
"+code-block[pre]",
|
'+code-block[pre]',
|
||||||
"+doc-root[p|h1|h2|h3|h4|h5|h6|blockquote|code-block|div]"
|
'+doc-root[p|h1|h2|h3|h4|h5|h6|blockquote|code-block|div]',
|
||||||
].join(','),
|
].join(','),
|
||||||
plugins: gatherPlugins(options),
|
plugins: gatherPlugins(options),
|
||||||
contextmenu: false,
|
contextmenu: false,
|
||||||
@ -285,7 +285,7 @@ export function build(options) {
|
|||||||
color_map,
|
color_map,
|
||||||
file_picker_callback,
|
file_picker_callback,
|
||||||
paste_preprocess(plugin, args) {
|
paste_preprocess(plugin, args) {
|
||||||
const content = args.content;
|
const {content} = args;
|
||||||
if (content.indexOf('<img src="file://') !== -1) {
|
if (content.indexOf('<img src="file://') !== -1) {
|
||||||
args.content = '';
|
args.content = '';
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Clipboard from "../services/clipboard";
|
import Clipboard from '../services/clipboard';
|
||||||
|
|
||||||
let wrap;
|
let wrap;
|
||||||
let draggedContentEditable;
|
let draggedContentEditable;
|
||||||
@ -23,8 +23,7 @@ function paste(editor, options, event) {
|
|||||||
|
|
||||||
const images = clipboard.getImages();
|
const images = clipboard.getImages();
|
||||||
for (const imageFile of images) {
|
for (const imageFile of images) {
|
||||||
|
const id = `image-${Math.random().toString(16).slice(2)}`;
|
||||||
const id = "image-" + Math.random().toString(16).slice(2);
|
|
||||||
const loadingImage = window.baseUrl('/loading.gif');
|
const loadingImage = window.baseUrl('/loading.gif');
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ function paste(editor, options, event) {
|
|||||||
*/
|
*/
|
||||||
async function uploadImageFile(file, pageId) {
|
async function uploadImageFile(file, pageId) {
|
||||||
if (file === null || file.type.indexOf('image') !== 0) {
|
if (file === null || file.type.indexOf('image') !== 0) {
|
||||||
throw new Error(`Not an image file`);
|
throw new Error('Not an image file');
|
||||||
}
|
}
|
||||||
|
|
||||||
const remoteFilename = file.name || `image-${Date.now()}.png`;
|
const remoteFilename = file.name || `image-${Date.now()}.png`;
|
||||||
@ -74,7 +73,7 @@ async function uploadImageFile(file, pageId) {
|
|||||||
* @param {WysiwygConfigOptions} options
|
* @param {WysiwygConfigOptions} options
|
||||||
*/
|
*/
|
||||||
function dragStart(editor, options) {
|
function dragStart(editor, options) {
|
||||||
let node = editor.selection.getNode();
|
const node = editor.selection.getNode();
|
||||||
|
|
||||||
if (node.nodeName === 'IMG') {
|
if (node.nodeName === 'IMG') {
|
||||||
wrap = editor.dom.getParent(node, '.mceTemp');
|
wrap = editor.dom.getParent(node, '.mceTemp');
|
||||||
@ -96,8 +95,8 @@ function dragStart(editor, options) {
|
|||||||
* @param {DragEvent} event
|
* @param {DragEvent} event
|
||||||
*/
|
*/
|
||||||
function drop(editor, options, event) {
|
function drop(editor, options, event) {
|
||||||
let dom = editor.dom,
|
const {dom} = editor;
|
||||||
rng = tinymce.dom.RangeUtils.getCaretRangeFromPoint(event.clientX, event.clientY, editor.getDoc());
|
const rng = tinymce.dom.RangeUtils.getCaretRangeFromPoint(event.clientX, event.clientY, editor.getDoc());
|
||||||
|
|
||||||
// Template insertion
|
// Template insertion
|
||||||
const templateId = event.dataTransfer && event.dataTransfer.getData('bookstack/template');
|
const templateId = event.dataTransfer && event.dataTransfer.getData('bookstack/template');
|
||||||
@ -105,7 +104,7 @@ function drop(editor, options, event) {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
window.$http.get(`/templates/${templateId}`).then(resp => {
|
window.$http.get(`/templates/${templateId}`).then(resp => {
|
||||||
editor.selection.setRng(rng);
|
editor.selection.setRng(rng);
|
||||||
editor.undoManager.transact(function () {
|
editor.undoManager.transact(() => {
|
||||||
editor.execCommand('mceInsertContent', false, resp.data.html);
|
editor.execCommand('mceInsertContent', false, resp.data.html);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -117,7 +116,7 @@ function drop(editor, options, event) {
|
|||||||
} else if (wrap) {
|
} else if (wrap) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
editor.undoManager.transact(function () {
|
editor.undoManager.transact(() => {
|
||||||
editor.selection.setRng(rng);
|
editor.selection.setRng(rng);
|
||||||
editor.selection.setNode(wrap);
|
editor.selection.setNode(wrap);
|
||||||
dom.remove(wrap);
|
dom.remove(wrap);
|
||||||
@ -127,7 +126,7 @@ function drop(editor, options, event) {
|
|||||||
// Handle contenteditable section drop
|
// Handle contenteditable section drop
|
||||||
if (!event.isDefaultPrevented() && draggedContentEditable) {
|
if (!event.isDefaultPrevented() && draggedContentEditable) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
editor.undoManager.transact(function () {
|
editor.undoManager.transact(() => {
|
||||||
const selectedNode = editor.selection.getNode();
|
const selectedNode = editor.selection.getNode();
|
||||||
const range = editor.selection.getRng();
|
const range = editor.selection.getRng();
|
||||||
const selectedNodeRoot = selectedNode.closest('body > *');
|
const selectedNodeRoot = selectedNode.closest('body > *');
|
||||||
|
@ -5,16 +5,14 @@ const icons = {
|
|||||||
'table-insert-column-before': '<svg width="24" height="24"><path d="M8 19h5V5H8C6.764 5 6.766 3 8 3h11a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H8c-1.229 0-1.236-2 0-2zm7-6v6h4v-6zm0-8v6h4V5ZM3.924 11h2V9c0-1.333 2-1.333 2 0v2h2c1.335 0 1.335 2 0 2h-2v2c0 1.333-2 1.333-2 0v-2h-1.9c-1.572 0-1.113-2-.1-2z"/></svg>',
|
'table-insert-column-before': '<svg width="24" height="24"><path d="M8 19h5V5H8C6.764 5 6.766 3 8 3h11a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H8c-1.229 0-1.236-2 0-2zm7-6v6h4v-6zm0-8v6h4V5ZM3.924 11h2V9c0-1.333 2-1.333 2 0v2h2c1.335 0 1.335 2 0 2h-2v2c0 1.333-2 1.333-2 0v-2h-1.9c-1.572 0-1.113-2-.1-2z"/></svg>',
|
||||||
'table-insert-row-above': '<svg width="24" height="24"><path d="M5 8v5h14V8c0-1.235 2-1.234 2 0v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8C3 6.77 5 6.764 5 8zm6 7H5v4h6zm8 0h-6v4h6zM13 3.924v2h2c1.333 0 1.333 2 0 2h-2v2c0 1.335-2 1.335-2 0v-2H9c-1.333 0-1.333-2 0-2h2v-1.9c0-1.572 2-1.113 2-.1z"/></svg>',
|
'table-insert-row-above': '<svg width="24" height="24"><path d="M5 8v5h14V8c0-1.235 2-1.234 2 0v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8C3 6.77 5 6.764 5 8zm6 7H5v4h6zm8 0h-6v4h6zM13 3.924v2h2c1.333 0 1.333 2 0 2h-2v2c0 1.335-2 1.335-2 0v-2H9c-1.333 0-1.333-2 0-2h2v-1.9c0-1.572 2-1.113 2-.1z"/></svg>',
|
||||||
'table-insert-row-after': '<svg width="24" height="24"><path d="M19 16v-5H5v5c0 1.235-2 1.234-2 0V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v11c0 1.229-2 1.236-2 0zm-6-7h6V5h-6zM5 9h6V5H5Zm6 11.076v-2H9c-1.333 0-1.333-2 0-2h2v-2c0-1.335 2-1.335 2 0v2h2c1.333 0 1.333 2 0 2h-2v1.9c0 1.572-2 1.113-2 .1z"/></svg>',
|
'table-insert-row-after': '<svg width="24" height="24"><path d="M19 16v-5H5v5c0 1.235-2 1.234-2 0V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v11c0 1.229-2 1.236-2 0zm-6-7h6V5h-6zM5 9h6V5H5Zm6 11.076v-2H9c-1.333 0-1.333-2 0-2h2v-2c0-1.335 2-1.335 2 0v2h2c1.333 0 1.333 2 0 2h-2v1.9c0 1.572-2 1.113-2 .1z"/></svg>',
|
||||||
'table': '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2ZM5 14v5h6v-5zm14 0h-6v5h6zm0-7h-6v5h6zM5 12h6V7H5Z"/></svg>',
|
table: '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2ZM5 14v5h6v-5zm14 0h-6v5h6zm0-7h-6v5h6zM5 12h6V7H5Z"/></svg>',
|
||||||
'table-delete-table': '<svg width="24" height="24"><path d="M5 21a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14c0 1.1-.9 2-2 2zm0-2h14V5H5v14z"/><path d="m13.711 15.423-1.71-1.712-1.712 1.712c-1.14 1.14-2.852-.57-1.71-1.712l1.71-1.71-1.71-1.712c-1.143-1.142.568-2.853 1.71-1.71L12 10.288l1.711-1.71c1.141-1.142 2.852.57 1.712 1.71L13.71 12l1.626 1.626c1.345 1.345-.76 2.663-1.626 1.797z" style="fill-rule:nonzero;stroke-width:1.20992"/></svg>',
|
'table-delete-table': '<svg width="24" height="24"><path d="M5 21a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14c0 1.1-.9 2-2 2zm0-2h14V5H5v14z"/><path d="m13.711 15.423-1.71-1.712-1.712 1.712c-1.14 1.14-2.852-.57-1.71-1.712l1.71-1.71-1.71-1.712c-1.143-1.142.568-2.853 1.71-1.71L12 10.288l1.711-1.71c1.141-1.142 2.852.57 1.712 1.71L13.71 12l1.626 1.626c1.345 1.345-.76 2.663-1.626 1.797z" style="fill-rule:nonzero;stroke-width:1.20992"/></svg>',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
*/
|
*/
|
||||||
export function registerCustomIcons(editor) {
|
export function registerCustomIcons(editor) {
|
||||||
|
|
||||||
for (const [name, svg] of Object.entries(icons)) {
|
for (const [name, svg] of Object.entries(icons)) {
|
||||||
editor.ui.registry.addIcon(name, svg);
|
editor.ui.registry.addIcon(name, svg);
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,8 @@ function elemIsCodeBlock(elem) {
|
|||||||
*/
|
*/
|
||||||
function showPopup(editor, code, language, callback) {
|
function showPopup(editor, code, language, callback) {
|
||||||
window.$components.first('code-editor').open(code, language, (newCode, newLang) => {
|
window.$components.first('code-editor').open(code, language, (newCode, newLang) => {
|
||||||
callback(newCode, newLang)
|
callback(newCode, newLang);
|
||||||
editor.focus()
|
editor.focus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ function defineCodeBlockCustomElement(editor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getLanguage() {
|
getLanguage() {
|
||||||
const getLanguageFromClassList = (classes) => {
|
const getLanguageFromClassList = classes => {
|
||||||
const langClasses = classes.split(' ').filter(cssClass => cssClass.startsWith('language-'));
|
const langClasses = classes.split(' ').filter(cssClass => cssClass.startsWith('language-'));
|
||||||
return (langClasses[0] || '').replace('language-', '');
|
return (langClasses[0] || '').replace('language-', '');
|
||||||
};
|
};
|
||||||
@ -114,12 +114,12 @@ function defineCodeBlockCustomElement(editor) {
|
|||||||
this.style.height = `${height}px`;
|
this.style.height = `${height}px`;
|
||||||
|
|
||||||
const container = this.shadowRoot.querySelector('.CodeMirrorContainer');
|
const container = this.shadowRoot.querySelector('.CodeMirrorContainer');
|
||||||
const renderEditor = (Code) => {
|
const renderEditor = Code => {
|
||||||
this.editor = Code.wysiwygView(container, this.shadowRoot, content, this.getLanguage());
|
this.editor = Code.wysiwygView(container, this.shadowRoot, content, this.getLanguage());
|
||||||
setTimeout(() => this.style.height = null, 12);
|
setTimeout(() => this.style.height = null, 12);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.importVersioned('code').then((Code) => {
|
window.importVersioned('code').then(Code => {
|
||||||
const timeout = (Date.now() - connectedTime < 20) ? 20 : 0;
|
const timeout = (Date.now() - connectedTime < 20) ? 20 : 0;
|
||||||
setTimeout(() => renderEditor(Code), timeout);
|
setTimeout(() => renderEditor(Code), timeout);
|
||||||
});
|
});
|
||||||
@ -135,26 +135,25 @@ function defineCodeBlockCustomElement(editor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
win.customElements.define('code-block', CodeBlockElement);
|
win.customElements.define('code-block', CodeBlockElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
* @param {String} url
|
* @param {String} url
|
||||||
*/
|
*/
|
||||||
function register(editor, url) {
|
function register(editor, url) {
|
||||||
|
editor.ui.registry.addIcon('codeblock', '<svg width="24" height="24"><path d="M4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1Zm1 2v14h14V5Z"/><path d="M11.103 15.423c.277.277.277.738 0 .922a.692.692 0 0 1-1.106 0l-4.057-3.78a.738.738 0 0 1 0-1.107l4.057-3.872c.276-.277.83-.277 1.106 0a.724.724 0 0 1 0 1.014L7.6 12.012ZM12.897 8.577c-.245-.312-.2-.675.08-.955.28-.281.727-.27 1.027.033l4.057 3.78a.738.738 0 0 1 0 1.107l-4.057 3.872c-.277.277-.83.277-1.107 0a.724.724 0 0 1 0-1.014l3.504-3.412z"/></svg>');
|
||||||
editor.ui.registry.addIcon('codeblock', '<svg width="24" height="24"><path d="M4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1Zm1 2v14h14V5Z"/><path d="M11.103 15.423c.277.277.277.738 0 .922a.692.692 0 0 1-1.106 0l-4.057-3.78a.738.738 0 0 1 0-1.107l4.057-3.872c.276-.277.83-.277 1.106 0a.724.724 0 0 1 0 1.014L7.6 12.012ZM12.897 8.577c-.245-.312-.2-.675.08-.955.28-.281.727-.27 1.027.033l4.057 3.78a.738.738 0 0 1 0 1.107l-4.057 3.872c-.277.277-.83.277-1.107 0a.724.724 0 0 1 0-1.014l3.504-3.412z"/></svg>')
|
|
||||||
|
|
||||||
editor.ui.registry.addButton('codeeditor', {
|
editor.ui.registry.addButton('codeeditor', {
|
||||||
tooltip: 'Insert code block',
|
tooltip: 'Insert code block',
|
||||||
icon: 'codeblock',
|
icon: 'codeblock',
|
||||||
onAction() {
|
onAction() {
|
||||||
editor.execCommand('codeeditor');
|
editor.execCommand('codeeditor');
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.ui.registry.addButton('editcodeeditor', {
|
editor.ui.registry.addButton('editcodeeditor', {
|
||||||
@ -162,7 +161,7 @@ function register(editor, url) {
|
|||||||
icon: 'edit-block',
|
icon: 'edit-block',
|
||||||
onAction() {
|
onAction() {
|
||||||
editor.execCommand('codeeditor');
|
editor.execCommand('codeeditor');
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.addCommand('codeeditor', () => {
|
editor.addCommand('codeeditor', () => {
|
||||||
@ -185,14 +184,14 @@ function register(editor, url) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
editor.on('dblclick', event => {
|
editor.on('dblclick', event => {
|
||||||
let selectedNode = editor.selection.getNode();
|
const selectedNode = editor.selection.getNode();
|
||||||
if (elemIsCodeBlock(selectedNode)) {
|
if (elemIsCodeBlock(selectedNode)) {
|
||||||
showPopupForCodeBlock(editor, selectedNode);
|
showPopupForCodeBlock(editor, selectedNode);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('PreInit', () => {
|
editor.on('PreInit', () => {
|
||||||
editor.parser.addNodeFilter('pre', function(elms) {
|
editor.parser.addNodeFilter('pre', elms => {
|
||||||
for (const el of elms) {
|
for (const el of elms) {
|
||||||
const wrapper = tinymce.html.Node.create('code-block', {
|
const wrapper = tinymce.html.Node.create('code-block', {
|
||||||
contenteditable: 'false',
|
contenteditable: 'false',
|
||||||
@ -207,13 +206,13 @@ function register(editor, url) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.parser.addNodeFilter('code-block', function(elms) {
|
editor.parser.addNodeFilter('code-block', elms => {
|
||||||
for (const el of elms) {
|
for (const el of elms) {
|
||||||
el.attr('contenteditable', 'false');
|
el.attr('contenteditable', 'false');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.serializer.addNodeFilter('code-block', function(elms) {
|
editor.serializer.addNodeFilter('code-block', elms => {
|
||||||
for (const el of elms) {
|
for (const el of elms) {
|
||||||
el.unwrap();
|
el.unwrap();
|
||||||
}
|
}
|
||||||
@ -221,12 +220,12 @@ function register(editor, url) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
editor.ui.registry.addContextToolbar('codeeditor', {
|
editor.ui.registry.addContextToolbar('codeeditor', {
|
||||||
predicate: function (node) {
|
predicate(node) {
|
||||||
return node.nodeName.toLowerCase() === 'code-block';
|
return node.nodeName.toLowerCase() === 'code-block';
|
||||||
},
|
},
|
||||||
items: 'editcodeeditor',
|
items: 'editcodeeditor',
|
||||||
position: 'node',
|
position: 'node',
|
||||||
scope: 'node'
|
scope: 'node',
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('PreInit', () => {
|
editor.on('PreInit', () => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import DrawIO from "../services/drawio";
|
import DrawIO from '../services/drawio';
|
||||||
|
|
||||||
let pageEditor = null;
|
let pageEditor = null;
|
||||||
let currentNode = null;
|
let currentNode = null;
|
||||||
@ -16,12 +16,12 @@ function showDrawingManager(mceEditor, selectedNode = null) {
|
|||||||
pageEditor = mceEditor;
|
pageEditor = mceEditor;
|
||||||
currentNode = selectedNode;
|
currentNode = selectedNode;
|
||||||
|
|
||||||
/** @type {ImageManager} **/
|
/** @type {ImageManager} * */
|
||||||
const imageManager = window.$components.first('image-manager');
|
const imageManager = window.$components.first('image-manager');
|
||||||
imageManager.show(function (image) {
|
imageManager.show(image => {
|
||||||
if (selectedNode) {
|
if (selectedNode) {
|
||||||
const imgElem = selectedNode.querySelector('img');
|
const imgElem = selectedNode.querySelector('img');
|
||||||
pageEditor.undoManager.transact(function () {
|
pageEditor.undoManager.transact(() => {
|
||||||
pageEditor.dom.setAttrib(imgElem, 'src', image.url);
|
pageEditor.dom.setAttrib(imgElem, 'src', image.url);
|
||||||
pageEditor.dom.setAttrib(selectedNode, 'drawio-diagram', image.id);
|
pageEditor.dom.setAttrib(selectedNode, 'drawio-diagram', image.id);
|
||||||
});
|
});
|
||||||
@ -39,10 +39,10 @@ function showDrawingEditor(mceEditor, selectedNode = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function updateContent(pngData) {
|
async function updateContent(pngData) {
|
||||||
const id = "image-" + Math.random().toString(16).slice(2);
|
const id = `image-${Math.random().toString(16).slice(2)}`;
|
||||||
const loadingImage = window.baseUrl('/loading.gif');
|
const loadingImage = window.baseUrl('/loading.gif');
|
||||||
|
|
||||||
const handleUploadError = (error) => {
|
const handleUploadError = error => {
|
||||||
if (error.status === 413) {
|
if (error.status === 413) {
|
||||||
window.$events.emit('error', options.translations.serverUploadLimitText);
|
window.$events.emit('error', options.translations.serverUploadLimitText);
|
||||||
} else {
|
} else {
|
||||||
@ -54,10 +54,10 @@ async function updateContent(pngData) {
|
|||||||
// Handle updating an existing image
|
// Handle updating an existing image
|
||||||
if (currentNode) {
|
if (currentNode) {
|
||||||
DrawIO.close();
|
DrawIO.close();
|
||||||
let imgElem = currentNode.querySelector('img');
|
const imgElem = currentNode.querySelector('img');
|
||||||
try {
|
try {
|
||||||
const img = await DrawIO.upload(pngData, options.pageId);
|
const img = await DrawIO.upload(pngData, options.pageId);
|
||||||
pageEditor.undoManager.transact(function () {
|
pageEditor.undoManager.transact(() => {
|
||||||
pageEditor.dom.setAttrib(imgElem, 'src', img.url);
|
pageEditor.dom.setAttrib(imgElem, 'src', img.url);
|
||||||
pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id);
|
pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id);
|
||||||
});
|
});
|
||||||
@ -72,7 +72,7 @@ async function updateContent(pngData) {
|
|||||||
DrawIO.close();
|
DrawIO.close();
|
||||||
try {
|
try {
|
||||||
const img = await DrawIO.upload(pngData, options.pageId);
|
const img = await DrawIO.upload(pngData, options.pageId);
|
||||||
pageEditor.undoManager.transact(function () {
|
pageEditor.undoManager.transact(() => {
|
||||||
pageEditor.dom.setAttrib(id, 'src', img.url);
|
pageEditor.dom.setAttrib(id, 'src', img.url);
|
||||||
pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id);
|
pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id);
|
||||||
});
|
});
|
||||||
@ -83,7 +83,6 @@ async function updateContent(pngData) {
|
|||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function drawingInit() {
|
function drawingInit() {
|
||||||
if (!currentNode) {
|
if (!currentNode) {
|
||||||
return Promise.resolve('');
|
return Promise.resolve('');
|
||||||
@ -101,13 +100,12 @@ function drawingInit() {
|
|||||||
export function getPlugin(providedOptions) {
|
export function getPlugin(providedOptions) {
|
||||||
options = providedOptions;
|
options = providedOptions;
|
||||||
return function(editor, url) {
|
return function(editor, url) {
|
||||||
|
|
||||||
editor.addCommand('drawio', () => {
|
editor.addCommand('drawio', () => {
|
||||||
const selectedNode = editor.selection.getNode();
|
const selectedNode = editor.selection.getNode();
|
||||||
showDrawingEditor(editor, isDrawing(selectedNode) ? selectedNode : null);
|
showDrawingEditor(editor, isDrawing(selectedNode) ? selectedNode : null);
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.ui.registry.addIcon('diagram', `<svg width="24" height="24" fill="${options.darkMode ? '#BBB' : '#000000'}" xmlns="http://www.w3.org/2000/svg"><path d="M20.716 7.639V2.845h-4.794v1.598h-7.99V2.845H3.138v4.794h1.598v7.99H3.138v4.794h4.794v-1.598h7.99v1.598h4.794v-4.794h-1.598v-7.99zM4.736 4.443h1.598V6.04H4.736zm1.598 14.382H4.736v-1.598h1.598zm9.588-1.598h-7.99v-1.598H6.334v-7.99h1.598V6.04h7.99v1.598h1.598v7.99h-1.598zm3.196 1.598H17.52v-1.598h1.598zM17.52 6.04V4.443h1.598V6.04zm-4.21 7.19h-2.79l-.582 1.599H8.643l2.717-7.191h1.119l2.724 7.19h-1.302zm-2.43-1.006h2.086l-1.039-3.06z"/></svg>`)
|
editor.ui.registry.addIcon('diagram', `<svg width="24" height="24" fill="${options.darkMode ? '#BBB' : '#000000'}" xmlns="http://www.w3.org/2000/svg"><path d="M20.716 7.639V2.845h-4.794v1.598h-7.99V2.845H3.138v4.794h1.598v7.99H3.138v4.794h4.794v-1.598h7.99v1.598h4.794v-4.794h-1.598v-7.99zM4.736 4.443h1.598V6.04H4.736zm1.598 14.382H4.736v-1.598h1.598zm9.588-1.598h-7.99v-1.598H6.334v-7.99h1.598V6.04h7.99v1.598h1.598v7.99h-1.598zm3.196 1.598H17.52v-1.598h1.598zM17.52 6.04V4.443h1.598V6.04zm-4.21 7.19h-2.79l-.582 1.599H8.643l2.717-7.191h1.119l2.724 7.19h-1.302zm-2.43-1.006h2.086l-1.039-3.06z"/></svg>`);
|
||||||
|
|
||||||
editor.ui.registry.addSplitButton('drawio', {
|
editor.ui.registry.addSplitButton('drawio', {
|
||||||
tooltip: 'Insert/edit drawing',
|
tooltip: 'Insert/edit drawing',
|
||||||
@ -123,7 +121,7 @@ export function getPlugin(providedOptions) {
|
|||||||
type: 'choiceitem',
|
type: 'choiceitem',
|
||||||
text: 'Drawing manager',
|
text: 'Drawing manager',
|
||||||
value: 'drawing-manager',
|
value: 'drawing-manager',
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
onItemAction(api, value) {
|
onItemAction(api, value) {
|
||||||
@ -131,25 +129,24 @@ export function getPlugin(providedOptions) {
|
|||||||
const selectedNode = editor.selection.getNode();
|
const selectedNode = editor.selection.getNode();
|
||||||
showDrawingManager(editor, isDrawing(selectedNode) ? selectedNode : null);
|
showDrawingManager(editor, isDrawing(selectedNode) ? selectedNode : null);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('dblclick', event => {
|
editor.on('dblclick', event => {
|
||||||
let selectedNode = editor.selection.getNode();
|
const selectedNode = editor.selection.getNode();
|
||||||
if (!isDrawing(selectedNode)) return;
|
if (!isDrawing(selectedNode)) return;
|
||||||
showDrawingEditor(editor, selectedNode);
|
showDrawingEditor(editor, selectedNode);
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('SetContent', function () {
|
editor.on('SetContent', () => {
|
||||||
const drawings = editor.dom.select('body > div[drawio-diagram]');
|
const drawings = editor.dom.select('body > div[drawio-diagram]');
|
||||||
if (!drawings.length) return;
|
if (!drawings.length) return;
|
||||||
|
|
||||||
editor.undoManager.transact(function () {
|
editor.undoManager.transact(() => {
|
||||||
for (const drawing of drawings) {
|
for (const drawing of drawings) {
|
||||||
drawing.setAttribute('contenteditable', 'false');
|
drawing.setAttribute('contenteditable', 'false');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -3,7 +3,6 @@
|
|||||||
* @param {String} url
|
* @param {String} url
|
||||||
*/
|
*/
|
||||||
function register(editor, url) {
|
function register(editor, url) {
|
||||||
|
|
||||||
const aboutDialog = {
|
const aboutDialog = {
|
||||||
title: 'About the WYSIWYG Editor',
|
title: 'About the WYSIWYG Editor',
|
||||||
url: window.baseUrl('/help/wysiwyg'),
|
url: window.baseUrl('/help/wysiwyg'),
|
||||||
@ -14,12 +13,10 @@ function register(editor, url) {
|
|||||||
tooltip: 'About the editor',
|
tooltip: 'About the editor',
|
||||||
onAction() {
|
onAction() {
|
||||||
tinymce.activeEditor.windowManager.openUrl(aboutDialog);
|
tinymce.activeEditor.windowManager.openUrl(aboutDialog);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {WysiwygConfigOptions} options
|
* @param {WysiwygConfigOptions} options
|
||||||
* @return {register}
|
* @return {register}
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
* @param {String} url
|
* @param {String} url
|
||||||
*/
|
*/
|
||||||
function register(editor, url) {
|
function register(editor, url) {
|
||||||
editor.addCommand('InsertHorizontalRule', function () {
|
editor.addCommand('InsertHorizontalRule', () => {
|
||||||
let hrElem = document.createElement('hr');
|
const hrElem = document.createElement('hr');
|
||||||
let cNode = editor.selection.getNode();
|
const cNode = editor.selection.getNode();
|
||||||
let parentNode = cNode.parentNode;
|
const {parentNode} = cNode;
|
||||||
parentNode.insertBefore(hrElem, cNode);
|
parentNode.insertBefore(hrElem, cNode);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -15,11 +15,10 @@ function register(editor, url) {
|
|||||||
tooltip: 'Insert horizontal line',
|
tooltip: 'Insert horizontal line',
|
||||||
onAction() {
|
onAction() {
|
||||||
editor.execCommand('InsertHorizontalRule');
|
editor.execCommand('InsertHorizontalRule');
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {WysiwygConfigOptions} options
|
* @param {WysiwygConfigOptions} options
|
||||||
* @return {register}
|
* @return {register}
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
* @param {String} url
|
* @param {String} url
|
||||||
*/
|
*/
|
||||||
import {blockElementTypes} from "./util";
|
import {blockElementTypes} from './util';
|
||||||
|
|
||||||
function register(editor, url) {
|
function register(editor, url) {
|
||||||
|
|
||||||
editor.ui.registry.addIcon('details', '<svg width="24" height="24"><path d="M8.2 9a.5.5 0 0 0-.4.8l4 5.6a.5.5 0 0 0 .8 0l4-5.6a.5.5 0 0 0-.4-.8ZM20.122 18.151h-16c-.964 0-.934 2.7 0 2.7h16c1.139 0 1.173-2.7 0-2.7zM20.122 3.042h-16c-.964 0-.934 2.7 0 2.7h16c1.139 0 1.173-2.7 0-2.7z"/></svg>');
|
editor.ui.registry.addIcon('details', '<svg width="24" height="24"><path d="M8.2 9a.5.5 0 0 0-.4.8l4 5.6a.5.5 0 0 0 .8 0l4-5.6a.5.5 0 0 0-.4-.8ZM20.122 18.151h-16c-.964 0-.934 2.7 0 2.7h16c1.139 0 1.173-2.7 0-2.7zM20.122 3.042h-16c-.964 0-.934 2.7 0 2.7h16c1.139 0 1.173-2.7 0-2.7z"/></svg>');
|
||||||
editor.ui.registry.addIcon('togglefold', '<svg height="24" width="24"><path d="M8.12 19.3c.39.39 1.02.39 1.41 0L12 16.83l2.47 2.47c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41l-3.17-3.17c-.39-.39-1.02-.39-1.41 0l-3.17 3.17c-.4.38-.4 1.02-.01 1.41zm7.76-14.6c-.39-.39-1.02-.39-1.41 0L12 7.17 9.53 4.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.03 0 1.42l3.17 3.17c.39.39 1.02.39 1.41 0l3.17-3.17c.4-.39.4-1.03.01-1.42z"/></svg>');
|
editor.ui.registry.addIcon('togglefold', '<svg height="24" width="24"><path d="M8.12 19.3c.39.39 1.02.39 1.41 0L12 16.83l2.47 2.47c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41l-3.17-3.17c-.39-.39-1.02-.39-1.41 0l-3.17 3.17c-.4.38-.4 1.02-.01 1.41zm7.76-14.6c-.39-.39-1.02-.39-1.41 0L12 7.17 9.53 4.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.03 0 1.42l3.17 3.17c.39.39 1.02.39 1.41 0l3.17-3.17c.4-.39.4-1.03.01-1.42z"/></svg>');
|
||||||
editor.ui.registry.addIcon('togglelabel', '<svg height="18" width="18" viewBox="0 0 24 24"><path d="M21.41,11.41l-8.83-8.83C12.21,2.21,11.7,2,11.17,2H4C2.9,2,2,2.9,2,4v7.17c0,0.53,0.21,1.04,0.59,1.41l8.83,8.83 c0.78,0.78,2.05,0.78,2.83,0l7.17-7.17C22.2,13.46,22.2,12.2,21.41,11.41z M6.5,8C5.67,8,5,7.33,5,6.5S5.67,5,6.5,5S8,5.67,8,6.5 S7.33,8,6.5,8z"/></svg>');
|
editor.ui.registry.addIcon('togglelabel', '<svg height="18" width="18" viewBox="0 0 24 24"><path d="M21.41,11.41l-8.83-8.83C12.21,2.21,11.7,2,11.17,2H4C2.9,2,2,2.9,2,4v7.17c0,0.53,0.21,1.04,0.59,1.41l8.83,8.83 c0.78,0.78,2.05,0.78,2.83,0l7.17-7.17C22.2,13.46,22.2,12.2,21.41,11.41z M6.5,8C5.67,8,5,7.33,5,6.5S5.67,5,6.5,5S8,5.67,8,6.5 S7.33,8,6.5,8z"/></svg>');
|
||||||
@ -15,15 +14,15 @@ function register(editor, url) {
|
|||||||
tooltip: 'Insert collapsible block',
|
tooltip: 'Insert collapsible block',
|
||||||
onAction() {
|
onAction() {
|
||||||
editor.execCommand('InsertDetailsBlock');
|
editor.execCommand('InsertDetailsBlock');
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.ui.registry.addButton('removedetails', {
|
editor.ui.registry.addButton('removedetails', {
|
||||||
icon: 'table-delete-table',
|
icon: 'table-delete-table',
|
||||||
tooltip: 'Unwrap',
|
tooltip: 'Unwrap',
|
||||||
onAction() {
|
onAction() {
|
||||||
unwrapDetailsInSelection(editor)
|
unwrapDetailsInSelection(editor);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.ui.registry.addButton('editdetials', {
|
editor.ui.registry.addButton('editdetials', {
|
||||||
@ -31,7 +30,7 @@ function register(editor, url) {
|
|||||||
tooltip: 'Edit label',
|
tooltip: 'Edit label',
|
||||||
onAction() {
|
onAction() {
|
||||||
showDetailLabelEditWindow(editor);
|
showDetailLabelEditWindow(editor);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('dblclick', event => {
|
editor.on('dblclick', event => {
|
||||||
@ -46,15 +45,15 @@ function register(editor, url) {
|
|||||||
const details = getSelectedDetailsBlock(editor);
|
const details = getSelectedDetailsBlock(editor);
|
||||||
details.toggleAttribute('open');
|
details.toggleAttribute('open');
|
||||||
editor.focus();
|
editor.focus();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.addCommand('InsertDetailsBlock', function () {
|
editor.addCommand('InsertDetailsBlock', () => {
|
||||||
let content = editor.selection.getContent({format: 'html'});
|
let content = editor.selection.getContent({format: 'html'});
|
||||||
const details = document.createElement('details');
|
const details = document.createElement('details');
|
||||||
const summary = document.createElement('summary');
|
const summary = document.createElement('summary');
|
||||||
const id = 'details-' + Date.now();
|
const id = `details-${Date.now()}`;
|
||||||
details.setAttribute('data-id', id)
|
details.setAttribute('data-id', id);
|
||||||
details.appendChild(summary);
|
details.appendChild(summary);
|
||||||
|
|
||||||
if (!content) {
|
if (!content) {
|
||||||
@ -76,12 +75,12 @@ function register(editor, url) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
editor.ui.registry.addContextToolbar('details', {
|
editor.ui.registry.addContextToolbar('details', {
|
||||||
predicate: function (node) {
|
predicate(node) {
|
||||||
return node.nodeName.toLowerCase() === 'details';
|
return node.nodeName.toLowerCase() === 'details';
|
||||||
},
|
},
|
||||||
items: 'editdetials toggledetails removedetails',
|
items: 'editdetials toggledetails removedetails',
|
||||||
position: 'node',
|
position: 'node',
|
||||||
scope: 'node'
|
scope: 'node',
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('PreInit', () => {
|
editor.on('PreInit', () => {
|
||||||
@ -135,20 +134,20 @@ function detailsDialog(editor) {
|
|||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
type: 'cancel',
|
type: 'cancel',
|
||||||
text: 'Cancel'
|
text: 'Cancel',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'submit',
|
type: 'submit',
|
||||||
text: 'Save',
|
text: 'Save',
|
||||||
primary: true,
|
primary: true,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
onSubmit(api) {
|
onSubmit(api) {
|
||||||
const {summary} = api.getData();
|
const {summary} = api.getData();
|
||||||
setSummary(editor, summary);
|
setSummary(editor, summary);
|
||||||
api.close();
|
api.close();
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSummary(editor, summaryContent) {
|
function setSummary(editor, summaryContent) {
|
||||||
@ -191,20 +190,20 @@ function unwrapDetailsInSelection(editor) {
|
|||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
*/
|
*/
|
||||||
function setupElementFilters(editor) {
|
function setupElementFilters(editor) {
|
||||||
editor.parser.addNodeFilter('details', function(elms) {
|
editor.parser.addNodeFilter('details', elms => {
|
||||||
for (const el of elms) {
|
for (const el of elms) {
|
||||||
ensureDetailsWrappedInEditable(el);
|
ensureDetailsWrappedInEditable(el);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.serializer.addNodeFilter('details', function(elms) {
|
editor.serializer.addNodeFilter('details', elms => {
|
||||||
for (const el of elms) {
|
for (const el of elms) {
|
||||||
unwrapDetailsEditable(el);
|
unwrapDetailsEditable(el);
|
||||||
el.attr('open', null);
|
el.attr('open', null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.serializer.addNodeFilter('doc-root', function(elms) {
|
editor.serializer.addNodeFilter('doc-root', elms => {
|
||||||
for (const el of elms) {
|
for (const el of elms) {
|
||||||
el.unwrap();
|
el.unwrap();
|
||||||
}
|
}
|
||||||
@ -258,7 +257,6 @@ function unwrapDetailsEditable(detailsEl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {WysiwygConfigOptions} options
|
* @param {WysiwygConfigOptions} options
|
||||||
* @return {register}
|
* @return {register}
|
||||||
|
@ -9,20 +9,19 @@ function register(editor, url) {
|
|||||||
icon: 'image',
|
icon: 'image',
|
||||||
tooltip: 'Insert image',
|
tooltip: 'Insert image',
|
||||||
onAction() {
|
onAction() {
|
||||||
/** @type {ImageManager} **/
|
/** @type {ImageManager} * */
|
||||||
const imageManager = window.$components.first('image-manager');
|
const imageManager = window.$components.first('image-manager');
|
||||||
imageManager.show(function (image) {
|
imageManager.show(image => {
|
||||||
const imageUrl = image.thumbs.display || image.url;
|
const imageUrl = image.thumbs.display || image.url;
|
||||||
let html = `<a href="${image.url}" target="_blank">`;
|
let html = `<a href="${image.url}" target="_blank">`;
|
||||||
html += `<img src="${imageUrl}" alt="${image.name}">`;
|
html += `<img src="${imageUrl}" alt="${image.name}">`;
|
||||||
html += '</a>';
|
html += '</a>';
|
||||||
editor.execCommand('mceInsertContent', false, html);
|
editor.execCommand('mceInsertContent', false, html);
|
||||||
}, 'gallery');
|
}, 'gallery');
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {WysiwygConfigOptions} options
|
* @param {WysiwygConfigOptions} options
|
||||||
* @return {register}
|
* @return {register}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user