@akilli/editor-src 5.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abbreviation/Abbreviation.js +32 -0
- package/abbreviation/AbbreviationDialog.js +21 -0
- package/audio/Audio.js +47 -0
- package/audio/AudioDialog.js +18 -0
- package/audio/AudioListener.js +50 -0
- package/base/AlignCommand.js +34 -0
- package/base/AlignableListener.js +45 -0
- package/base/Alignment.js +36 -0
- package/base/BarListener.js +95 -0
- package/base/Base.js +127 -0
- package/base/Command.js +139 -0
- package/base/CommandManager.js +60 -0
- package/base/ContentFilter.js +109 -0
- package/base/DeletableListener.js +36 -0
- package/base/DeleteCommand.js +18 -0
- package/base/Dialog.js +153 -0
- package/base/DialogManager.js +44 -0
- package/base/Dispatcher.js +88 -0
- package/base/Dom.js +790 -0
- package/base/EditableListener.js +82 -0
- package/base/Editor.js +448 -0
- package/base/Filter.js +35 -0
- package/base/FilterManager.js +44 -0
- package/base/FocusableListener.js +22 -0
- package/base/FocusbarListener.js +99 -0
- package/base/FormCreator.js +162 -0
- package/base/FormatbarListener.js +32 -0
- package/base/Key.js +258 -0
- package/base/Listener.js +51 -0
- package/base/NavigableListener.js +81 -0
- package/base/Plugin.js +176 -0
- package/base/PluginManager.js +51 -0
- package/base/SlotableListener.js +40 -0
- package/base/SortCommand.js +30 -0
- package/base/SortableListener.js +135 -0
- package/base/Sorting.js +36 -0
- package/base/Tag.js +113 -0
- package/base/TagGroup.js +183 -0
- package/base/TagListener.js +34 -0
- package/base/TagManager.js +61 -0
- package/base/TagName.js +470 -0
- package/base/ToolbarListener.js +11 -0
- package/base/util.js +59 -0
- package/block/Block.js +51 -0
- package/block/BlockDialog.js +11 -0
- package/block/BlockElement.js +21 -0
- package/block/BlockListener.js +60 -0
- package/blockquote/Blockquote.js +43 -0
- package/blockquote/BlockquoteFilter.js +22 -0
- package/blockquote/BlockquoteListener.js +34 -0
- package/bold/Bold.js +30 -0
- package/break/Break.js +33 -0
- package/break/BreakFilter.js +24 -0
- package/build/BuildEditor.js +97 -0
- package/build/editor.css +548 -0
- package/build/editor.woff2 +0 -0
- package/cite/Cite.js +30 -0
- package/code/Code.js +30 -0
- package/data/Data.js +32 -0
- package/data/DataDialog.js +13 -0
- package/definition/Definition.js +32 -0
- package/definition/DefinitionDialog.js +13 -0
- package/deletion/Deletion.js +30 -0
- package/details/Details.js +63 -0
- package/details/DetailsFilter.js +17 -0
- package/details/DetailsListener.js +102 -0
- package/division/Division.js +53 -0
- package/division/DivisionDialog.js +13 -0
- package/emphasis/Emphasis.js +30 -0
- package/figure/Figure.js +58 -0
- package/figure/FigureFilter.js +14 -0
- package/figure/FigureListener.js +23 -0
- package/heading/Heading.js +38 -0
- package/horizontalrule/HorizontalRule.js +37 -0
- package/i18n/I18n.js +26 -0
- package/i18n/de.js +167 -0
- package/iframe/Iframe.js +49 -0
- package/iframe/IframeDialog.js +20 -0
- package/iframe/IframeListener.js +48 -0
- package/image/Image.js +47 -0
- package/image/ImageDialog.js +23 -0
- package/image/ImageListener.js +47 -0
- package/insertion/Insertion.js +30 -0
- package/italic/Italic.js +30 -0
- package/keyboard/Keyboard.js +30 -0
- package/link/Link.js +34 -0
- package/link/LinkDialog.js +14 -0
- package/link/LinkListener.js +45 -0
- package/list/List.js +40 -0
- package/list/ListListener.js +91 -0
- package/mark/Mark.js +30 -0
- package/orderedlist/OrderedList.js +39 -0
- package/package.json +24 -0
- package/paragraph/Paragraph.js +42 -0
- package/paragraph/ParagraphListener.js +40 -0
- package/preformat/Preformat.js +43 -0
- package/preformat/PreformatFilter.js +22 -0
- package/preformat/PreformatListener.js +34 -0
- package/quote/Quote.js +30 -0
- package/sample/Sample.js +30 -0
- package/section/Section.js +55 -0
- package/section/SectionDialog.js +13 -0
- package/small/Small.js +30 -0
- package/strikethrough/Strikethrough.js +30 -0
- package/strong/Strong.js +30 -0
- package/subheading/Subheading.js +38 -0
- package/subscript/Subscript.js +30 -0
- package/superscript/Superscript.js +30 -0
- package/table/Table.js +113 -0
- package/table/TableCellListener.js +125 -0
- package/table/TableColumnAddCommand.js +19 -0
- package/table/TableColumnListener.js +34 -0
- package/table/TableCommand.js +23 -0
- package/table/TableDialog.js +14 -0
- package/table/TableFilter.js +35 -0
- package/table/TableListener.js +39 -0
- package/table/TableRowAddCommand.js +18 -0
- package/table/TableRowListener.js +34 -0
- package/time/Time.js +32 -0
- package/time/TimeDialog.js +13 -0
- package/underline/Underline.js +30 -0
- package/unorderedlist/UnorderedList.js +39 -0
- package/variable/Variable.js +30 -0
- package/video/Video.js +47 -0
- package/video/VideoDialog.js +20 -0
- package/video/VideoListener.js +48 -0
package/base/Plugin.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import Command from './Command.js';
|
|
2
|
+
import Editor from './Editor.js';
|
|
3
|
+
import Tag from './Tag.js';
|
|
4
|
+
import TagName from './TagName.js';
|
|
5
|
+
import { isOptString, isString } from './util.js';
|
|
6
|
+
|
|
7
|
+
export default class Plugin {
|
|
8
|
+
/**
|
|
9
|
+
* @type {Editor}
|
|
10
|
+
*/
|
|
11
|
+
#editor;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @return {Editor}
|
|
15
|
+
*/
|
|
16
|
+
get editor() {
|
|
17
|
+
return this.#editor;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @type {string}
|
|
22
|
+
*/
|
|
23
|
+
static get name() {
|
|
24
|
+
throw new Error('Missing name');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @type {Plugin[]}
|
|
29
|
+
*/
|
|
30
|
+
static get dependencies() {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Default configuration
|
|
36
|
+
*
|
|
37
|
+
* @type {Object.<string, any>}
|
|
38
|
+
*/
|
|
39
|
+
static get config() {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {Editor} editor
|
|
45
|
+
*/
|
|
46
|
+
constructor(editor) {
|
|
47
|
+
if (!(editor instanceof Editor)) {
|
|
48
|
+
throw new TypeError('Invalid argument');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.#editor = editor;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @abstract
|
|
56
|
+
* @return {void}
|
|
57
|
+
*/
|
|
58
|
+
init() {
|
|
59
|
+
throw new Error('Not implemented');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Translates given string
|
|
64
|
+
*
|
|
65
|
+
* @protected
|
|
66
|
+
* @param {string} key
|
|
67
|
+
* @return {string}
|
|
68
|
+
*/
|
|
69
|
+
_(key) {
|
|
70
|
+
return this.editor.translate(key);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Registers i18n data for this plugin
|
|
75
|
+
*
|
|
76
|
+
* @protected
|
|
77
|
+
* @param {Object.<string, Object.<string, string>>} i18n
|
|
78
|
+
* @return {void}
|
|
79
|
+
*/
|
|
80
|
+
_i18n(i18n) {
|
|
81
|
+
if (i18n[this.editor.config.base.lang]) {
|
|
82
|
+
this.editor.i18n = i18n[this.editor.config.base.lang];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Creates and registers a tag with given options
|
|
88
|
+
*
|
|
89
|
+
* @protected
|
|
90
|
+
* @param {Object} opts
|
|
91
|
+
* @return {void}
|
|
92
|
+
*/
|
|
93
|
+
_tag(opts) {
|
|
94
|
+
this.editor.tags.set(new Tag(opts));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Registers a command with given parameters
|
|
99
|
+
*
|
|
100
|
+
* @protected
|
|
101
|
+
* @param {string} tagName
|
|
102
|
+
* @return {void}
|
|
103
|
+
*/
|
|
104
|
+
_command(tagName) {
|
|
105
|
+
this.editor.commands.set(new Command(this.editor, this.constructor.name, tagName));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Adds a toolbar button
|
|
110
|
+
*
|
|
111
|
+
* @protected
|
|
112
|
+
* @param {string} label
|
|
113
|
+
* @param {string|undefined} [command = undefined]
|
|
114
|
+
* @return {void}
|
|
115
|
+
*/
|
|
116
|
+
_toolbar(label, command = undefined) {
|
|
117
|
+
const l = this._(label);
|
|
118
|
+
this.editor.dom.insertLastChild(this.#button(l, l, undefined, command), this.editor.toolbar);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Adds a formatbar button
|
|
123
|
+
*
|
|
124
|
+
* @protected
|
|
125
|
+
* @param {string} label
|
|
126
|
+
* @param {string|undefined} [key = undefined]
|
|
127
|
+
* @param {string|undefined} [command = undefined]
|
|
128
|
+
* @return {void}
|
|
129
|
+
*/
|
|
130
|
+
_formatbar(label, key = undefined, command = undefined) {
|
|
131
|
+
const l = this._(label);
|
|
132
|
+
const alt = this._('Alt');
|
|
133
|
+
const shift = this._('Shift');
|
|
134
|
+
const title = l + (key ? ` [${alt} + ${shift} + ${key}]` : '');
|
|
135
|
+
|
|
136
|
+
this.editor.dom.insertLastChild(this.#button(l, title, key, command), this.editor.formatbar);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Adds a focusbar button
|
|
141
|
+
*
|
|
142
|
+
* @protected
|
|
143
|
+
* @param {string} label
|
|
144
|
+
* @param {string|undefined} [command = undefined]
|
|
145
|
+
* @return {void}
|
|
146
|
+
*/
|
|
147
|
+
_focusbar(label, command = undefined) {
|
|
148
|
+
const l = this._(label);
|
|
149
|
+
this.editor.dom.insertLastChild(this.#button(l, l, undefined, command), this.editor.focusbar);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Creates a button
|
|
154
|
+
*
|
|
155
|
+
* @param {string} html
|
|
156
|
+
* @param {string} title
|
|
157
|
+
* @param {string|undefined} [key = undefined]
|
|
158
|
+
* @param {string|undefined} [command = undefined]
|
|
159
|
+
* @return {HTMLButtonElement}
|
|
160
|
+
*/
|
|
161
|
+
#button(html, title, key = undefined, command = undefined) {
|
|
162
|
+
if (!isString(html) || !isString(title) || !isOptString(key)) {
|
|
163
|
+
throw new TypeError('Invalid argument');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return this.editor.dom.createElement(TagName.BUTTON, {
|
|
167
|
+
attributes: {
|
|
168
|
+
type: 'button',
|
|
169
|
+
title,
|
|
170
|
+
'data-command': command || this.constructor.name,
|
|
171
|
+
'data-key': key,
|
|
172
|
+
},
|
|
173
|
+
html,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import Plugin from './Plugin.js';
|
|
2
|
+
|
|
3
|
+
export default class PluginManager {
|
|
4
|
+
/**
|
|
5
|
+
* @type {Map<string, Plugin>}
|
|
6
|
+
*/
|
|
7
|
+
#items = new Map();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {Plugin[]} [plugins = []]
|
|
11
|
+
*/
|
|
12
|
+
constructor(plugins = []) {
|
|
13
|
+
plugins.forEach((plugin) => this.set(plugin));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {string} name
|
|
18
|
+
* @return {Plugin|undefined}
|
|
19
|
+
*/
|
|
20
|
+
get(name) {
|
|
21
|
+
return this.#items.get(name);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Plugin} plugin
|
|
26
|
+
* @return {void}
|
|
27
|
+
*/
|
|
28
|
+
set(plugin) {
|
|
29
|
+
if (!(plugin instanceof Plugin)) {
|
|
30
|
+
throw new TypeError('Invalid argument');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this.#items.set(plugin.constructor.name, plugin);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @return {void}
|
|
38
|
+
*/
|
|
39
|
+
init() {
|
|
40
|
+
this.#items.forEach((plugin) => plugin.init());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @return {void}
|
|
45
|
+
*/
|
|
46
|
+
freeze() {
|
|
47
|
+
this.#items.forEach((plugin) => Object.freeze(plugin));
|
|
48
|
+
Object.freeze(this.#items);
|
|
49
|
+
Object.freeze(this);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Key from './Key.js';
|
|
2
|
+
import Listener from './Listener.js';
|
|
3
|
+
import TagName from './TagName.js';
|
|
4
|
+
|
|
5
|
+
export default class SlotableListener extends Listener {
|
|
6
|
+
/**
|
|
7
|
+
* @param {Editor} editor
|
|
8
|
+
*/
|
|
9
|
+
constructor(editor) {
|
|
10
|
+
super(editor);
|
|
11
|
+
this.editor.root.addEventListener('insert', this);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {CustomEvent} event
|
|
16
|
+
* @param {HTMLElement} event.detail.element
|
|
17
|
+
* @return {void}
|
|
18
|
+
*/
|
|
19
|
+
insert({ detail: { element } }) {
|
|
20
|
+
if (element instanceof HTMLSlotElement) {
|
|
21
|
+
element.addEventListener('keydown', this);
|
|
22
|
+
} else if (element.hasAttribute('data-slotable') && !element.querySelector(':scope > ' + TagName.SLOT)) {
|
|
23
|
+
this.editor.dom.insertLastChild(this.editor.dom.createElement(TagName.SLOT), element);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {KeyboardEvent} event
|
|
29
|
+
* @param {HTMLSlotElement} event.target
|
|
30
|
+
* @return {void}
|
|
31
|
+
*/
|
|
32
|
+
keydown(event) {
|
|
33
|
+
if (Key.isEventFor(event, Key.BACKSPACE) && event.target.matches(':only-child')) {
|
|
34
|
+
this.editor.dom.delete(event.target.parentElement);
|
|
35
|
+
} else if (!Key.isEventFor(event, Key.TAB) && !Key.isEventFor(event, Key.TAB, { shift: true })) {
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
event.stopPropagation();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Command from './Command.js';
|
|
2
|
+
import Sorting from './Sorting.js';
|
|
3
|
+
|
|
4
|
+
export default class SortCommand extends Command {
|
|
5
|
+
/**
|
|
6
|
+
* @type {string}
|
|
7
|
+
*/
|
|
8
|
+
#sorting;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {Editor} editor
|
|
12
|
+
* @param {string} sorting
|
|
13
|
+
*/
|
|
14
|
+
constructor(editor, sorting) {
|
|
15
|
+
if (!Sorting.values().includes(sorting)) {
|
|
16
|
+
throw new TypeError('Invalid argument');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
super(editor, 'sort-' + sorting);
|
|
20
|
+
this.#sorting = sorting;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @return {void}
|
|
25
|
+
*/
|
|
26
|
+
execute() {
|
|
27
|
+
const element = this.editor.dom.getActiveElement();
|
|
28
|
+
element?.hasAttribute('data-sortable') && this.editor.dom.sort(element, this.#sorting);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import Key from './Key.js';
|
|
2
|
+
import Listener from './Listener.js';
|
|
3
|
+
import Sorting from './Sorting.js';
|
|
4
|
+
import TagName from './TagName.js';
|
|
5
|
+
|
|
6
|
+
export default class SortableListener extends Listener {
|
|
7
|
+
/**
|
|
8
|
+
* @param {Editor} editor
|
|
9
|
+
*/
|
|
10
|
+
constructor(editor) {
|
|
11
|
+
super(editor);
|
|
12
|
+
this.editor.root.addEventListener('insert', this);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {CustomEvent} event
|
|
17
|
+
* @param {HTMLElement} event.detail.element
|
|
18
|
+
* @return {void}
|
|
19
|
+
*/
|
|
20
|
+
insert({ detail: { element } }) {
|
|
21
|
+
if (element.hasAttribute('data-sortable')) {
|
|
22
|
+
element.addEventListener('keydown', this);
|
|
23
|
+
element.addEventListener('pointerdown', this);
|
|
24
|
+
element.addEventListener('pointermove', this);
|
|
25
|
+
element.addEventListener('pointerup', this);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {KeyboardEvent} event
|
|
31
|
+
* @param {HTMLElement} event.target
|
|
32
|
+
* @return {void}
|
|
33
|
+
*/
|
|
34
|
+
keydown(event) {
|
|
35
|
+
const map = {
|
|
36
|
+
[Key.HOME]: Sorting.FIRST,
|
|
37
|
+
[Key.ARROWUP]: Sorting.PREV,
|
|
38
|
+
[Key.ARROWDOWN]: Sorting.NEXT,
|
|
39
|
+
[Key.END]: Sorting.LAST,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
if (event.target === event.currentTarget && Key.isEventFor(event, Object.keys(map), { ctrl: true })) {
|
|
43
|
+
this.editor.dom.sort(event.target, map[event.key]);
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
event.stopPropagation();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {PointerEvent} event
|
|
51
|
+
* @param {HTMLElement} event.target
|
|
52
|
+
* @return {void}
|
|
53
|
+
*/
|
|
54
|
+
pointerdown(event) {
|
|
55
|
+
const target = event.target.closest('[data-sortable]');
|
|
56
|
+
|
|
57
|
+
if (target && this.editor.dom.contains(target)) {
|
|
58
|
+
target.setAttribute('data-sort', '');
|
|
59
|
+
target.setPointerCapture(event.pointerId);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {PointerEvent} event
|
|
65
|
+
* @param {HTMLElement} event.target
|
|
66
|
+
* @return {void}
|
|
67
|
+
*/
|
|
68
|
+
pointermove(event) {
|
|
69
|
+
const target = event.target.closest('[data-sortable][data-sort]');
|
|
70
|
+
const element = this.editor.dom.document.elementFromPoint(event.x, event.y);
|
|
71
|
+
this.#sortover();
|
|
72
|
+
|
|
73
|
+
if (target && this.editor.dom.contains(target) && this.#droppable(target, element)) {
|
|
74
|
+
element.setAttribute('data-sortover', '');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {PointerEvent} event
|
|
80
|
+
* @param {HTMLElement} event.target
|
|
81
|
+
* @return {void}
|
|
82
|
+
*/
|
|
83
|
+
pointerup(event) {
|
|
84
|
+
const target = event.target.closest('[data-sortable][data-sort]');
|
|
85
|
+
|
|
86
|
+
if (target && this.editor.dom.contains(target)) {
|
|
87
|
+
const element = this.editor.dom.document.elementFromPoint(event.x, event.y);
|
|
88
|
+
const parent = element.parentElement;
|
|
89
|
+
this.#sortover();
|
|
90
|
+
target.removeAttribute('data-sort');
|
|
91
|
+
target.releasePointerCapture(event.pointerId);
|
|
92
|
+
|
|
93
|
+
if (this.#droppable(target, element)) {
|
|
94
|
+
if (target.localName === TagName.COL && parent === target.parentElement) {
|
|
95
|
+
const t = Array.from(parent.children).indexOf(target);
|
|
96
|
+
const e = Array.from(parent.children).indexOf(element);
|
|
97
|
+
const table = parent.parentElement;
|
|
98
|
+
Array.from(table.rows).forEach((row) => this.editor.dom.insertBefore(row.cells[t], row.cells[e]));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.editor.dom.insertBefore(target, element);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Removes editor sortover attribute
|
|
108
|
+
*
|
|
109
|
+
* @return {void}
|
|
110
|
+
*/
|
|
111
|
+
#sortover() {
|
|
112
|
+
this.editor.root.querySelectorAll('[data-sortover]').forEach((item) => item.removeAttribute('data-sortover'));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Indicates if target element is a potential drop target for given element
|
|
117
|
+
*
|
|
118
|
+
* @param {HTMLElement} element
|
|
119
|
+
* @param {HTMLElement} target
|
|
120
|
+
* @return {boolean}
|
|
121
|
+
*/
|
|
122
|
+
#droppable(element, target) {
|
|
123
|
+
return (
|
|
124
|
+
element instanceof HTMLElement &&
|
|
125
|
+
target instanceof HTMLElement &&
|
|
126
|
+
this.editor.dom.contains(target) &&
|
|
127
|
+
![this.editor.root, element].includes(target) &&
|
|
128
|
+
target.hasAttribute('data-sortable') &&
|
|
129
|
+
(element.parentElement === target.parentElement ||
|
|
130
|
+
(this.editor.dom.arbitrary(element.parentElement) &&
|
|
131
|
+
this.editor.dom.arbitrary(target.parentElement))) &&
|
|
132
|
+
this.editor.tags.allowed(target.parentElement, element)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
package/base/Sorting.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export default class Sorting {
|
|
2
|
+
/**
|
|
3
|
+
* @return {string}
|
|
4
|
+
*/
|
|
5
|
+
static get FIRST() {
|
|
6
|
+
return 'first';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @return {string}
|
|
11
|
+
*/
|
|
12
|
+
static get PREV() {
|
|
13
|
+
return 'prev';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @return {string}
|
|
18
|
+
*/
|
|
19
|
+
static get NEXT() {
|
|
20
|
+
return 'next';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @return {string}
|
|
25
|
+
*/
|
|
26
|
+
static get LAST() {
|
|
27
|
+
return 'last';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @return {string[]}
|
|
32
|
+
*/
|
|
33
|
+
static values() {
|
|
34
|
+
return [this.FIRST, this.PREV, this.NEXT, this.LAST];
|
|
35
|
+
}
|
|
36
|
+
}
|
package/base/Tag.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { isOptArray, isOptString, isString } from './util.js';
|
|
2
|
+
|
|
3
|
+
export default class Tag {
|
|
4
|
+
/**
|
|
5
|
+
* @type {string}
|
|
6
|
+
*/
|
|
7
|
+
name;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @type {string}
|
|
11
|
+
*/
|
|
12
|
+
group;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @type {string[]}
|
|
16
|
+
*/
|
|
17
|
+
children;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @type {string[]}
|
|
21
|
+
*/
|
|
22
|
+
attributes;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @type {boolean}
|
|
26
|
+
*/
|
|
27
|
+
alignable;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Does element allow arbitrary amount of child elements
|
|
31
|
+
*
|
|
32
|
+
* @type {boolean}
|
|
33
|
+
*/
|
|
34
|
+
arbitrary;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @type {boolean}
|
|
38
|
+
*/
|
|
39
|
+
deletable;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @type {boolean}
|
|
43
|
+
*/
|
|
44
|
+
editable;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Is element empty or allowed to be empty
|
|
48
|
+
*
|
|
49
|
+
* @type {boolean}
|
|
50
|
+
*/
|
|
51
|
+
empty;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @type {boolean}
|
|
55
|
+
*/
|
|
56
|
+
focusable;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @type {boolean}
|
|
60
|
+
*/
|
|
61
|
+
navigable;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Does element define a slot
|
|
65
|
+
*
|
|
66
|
+
* @type {boolean}
|
|
67
|
+
*/
|
|
68
|
+
slotable;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @type {boolean}
|
|
72
|
+
*/
|
|
73
|
+
sortable;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Element to insert when ENTER-key is pressed
|
|
77
|
+
*
|
|
78
|
+
* @type {string|undefined}
|
|
79
|
+
*/
|
|
80
|
+
enter;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @param {string} name
|
|
84
|
+
* @param {string} group
|
|
85
|
+
* @param {Object.<string, any>} [opts = {}]
|
|
86
|
+
*/
|
|
87
|
+
constructor({ name, group, ...opts } = {}) {
|
|
88
|
+
if (
|
|
89
|
+
!isString(name) ||
|
|
90
|
+
!isString(group) ||
|
|
91
|
+
!isOptArray(opts.children) ||
|
|
92
|
+
!isOptArray(opts.attributes) ||
|
|
93
|
+
!isOptString(opts.enter)
|
|
94
|
+
) {
|
|
95
|
+
throw new TypeError('Invalid argument');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.name = name;
|
|
99
|
+
this.group = group;
|
|
100
|
+
this.children = opts.children || [];
|
|
101
|
+
this.attributes = opts.attributes || [];
|
|
102
|
+
this.arbitrary = opts.arbitrary === true;
|
|
103
|
+
this.alignable = opts.alignable === true;
|
|
104
|
+
this.deletable = opts.deletable === true;
|
|
105
|
+
this.editable = opts.editable === true;
|
|
106
|
+
this.empty = opts.empty === true;
|
|
107
|
+
this.focusable = opts.focusable === true;
|
|
108
|
+
this.navigable = opts.navigable === true;
|
|
109
|
+
this.slotable = opts.slotable === true;
|
|
110
|
+
this.sortable = opts.sortable === true;
|
|
111
|
+
this.enter = opts.enter;
|
|
112
|
+
}
|
|
113
|
+
}
|