jodit 4.18.4 → 4.18.7
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/CHANGELOG.md +45 -0
- package/es2015/jodit.css +13 -34
- package/es2015/jodit.fat.min.css +1 -1
- package/es2015/jodit.fat.min.js +12 -12
- package/es2015/jodit.js +1130 -225
- package/es2015/jodit.min.css +1 -1
- package/es2015/jodit.min.js +12 -12
- package/es2015/plugins/debug/debug.css +1 -1
- package/es2015/plugins/debug/debug.js +1 -1
- package/es2015/plugins/debug/debug.min.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2018/jodit.fat.min.css +1 -1
- package/es2018/jodit.fat.min.js +12 -12
- package/es2018/jodit.min.css +1 -1
- package/es2018/jodit.min.js +12 -12
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021/jodit.css +13 -34
- package/es2021/jodit.fat.min.css +1 -1
- package/es2021/jodit.fat.min.js +16 -16
- package/es2021/jodit.js +1121 -223
- package/es2021/jodit.min.css +1 -1
- package/es2021/jodit.min.js +16 -16
- package/es2021/plugins/debug/debug.css +1 -1
- package/es2021/plugins/debug/debug.js +1 -1
- package/es2021/plugins/debug/debug.min.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021.en/jodit.css +13 -34
- package/es2021.en/jodit.fat.min.css +1 -1
- package/es2021.en/jodit.fat.min.js +16 -16
- package/es2021.en/jodit.js +1095 -197
- package/es2021.en/jodit.min.css +1 -1
- package/es2021.en/jodit.min.js +16 -16
- package/es2021.en/plugins/debug/debug.css +1 -1
- package/es2021.en/plugins/debug/debug.js +1 -1
- package/es2021.en/plugins/debug/debug.min.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/jodit.css +14 -41
- package/es5/jodit.fat.min.css +1 -1
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +1260 -273
- package/es5/jodit.min.css +3 -3
- package/es5/jodit.min.js +2 -2
- package/es5/plugins/debug/debug.css +1 -1
- package/es5/plugins/debug/debug.js +1 -1
- package/es5/plugins/debug/debug.min.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/polyfills.fat.min.js +1 -1
- package/es5/polyfills.js +1 -1
- package/es5/polyfills.min.js +1 -1
- package/esm/config.d.ts +5 -0
- package/esm/core/constants.js +1 -1
- package/esm/core/decorators/component/component.js +12 -0
- package/esm/core/helpers/html/apply-styles.js +3 -0
- package/esm/core/helpers/html/clean-from-word.js +3 -0
- package/esm/core/helpers/html/strip-tags.js +24 -6
- package/esm/core/helpers/html/word-lists.d.ts +29 -0
- package/esm/core/helpers/html/word-lists.js +158 -0
- package/esm/core/selection/helpers/index.d.ts +1 -0
- package/esm/core/selection/helpers/index.js +1 -0
- package/esm/core/selection/helpers/is-moved.d.ts +15 -0
- package/esm/core/selection/helpers/is-moved.js +22 -0
- package/esm/core/selection/style/api/list/toggle-ordered-list.js +40 -3
- package/esm/core/selection/style/transactions.js +5 -2
- package/esm/core/ui/popup/popup.js +14 -9
- package/esm/jodit.js +5 -1
- package/esm/langs/ar.d.ts +3 -0
- package/esm/langs/ar.js +4 -1
- package/esm/langs/az.d.ts +3 -0
- package/esm/langs/az.js +4 -1
- package/esm/langs/cs_cz.d.ts +3 -0
- package/esm/langs/cs_cz.js +4 -1
- package/esm/langs/de.d.ts +3 -0
- package/esm/langs/de.js +4 -1
- package/esm/langs/es.d.ts +3 -0
- package/esm/langs/es.js +4 -1
- package/esm/langs/fa.d.ts +3 -0
- package/esm/langs/fa.js +4 -1
- package/esm/langs/fi.d.ts +3 -0
- package/esm/langs/fi.js +4 -1
- package/esm/langs/fr.d.ts +3 -0
- package/esm/langs/fr.js +4 -1
- package/esm/langs/he.d.ts +3 -0
- package/esm/langs/he.js +4 -1
- package/esm/langs/hu.d.ts +3 -0
- package/esm/langs/hu.js +4 -1
- package/esm/langs/id.d.ts +3 -0
- package/esm/langs/id.js +4 -1
- package/esm/langs/it.d.ts +3 -0
- package/esm/langs/it.js +4 -1
- package/esm/langs/ja.d.ts +3 -0
- package/esm/langs/ja.js +4 -1
- package/esm/langs/ko.d.ts +3 -0
- package/esm/langs/ko.js +4 -1
- package/esm/langs/mn.d.ts +3 -0
- package/esm/langs/mn.js +4 -1
- package/esm/langs/nl.d.ts +3 -0
- package/esm/langs/nl.js +4 -1
- package/esm/langs/no.d.ts +3 -0
- package/esm/langs/no.js +4 -1
- package/esm/langs/pl.d.ts +3 -0
- package/esm/langs/pl.js +4 -1
- package/esm/langs/pt_br.d.ts +3 -0
- package/esm/langs/pt_br.js +4 -1
- package/esm/langs/ru.d.ts +3 -0
- package/esm/langs/ru.js +4 -1
- package/esm/langs/sk.d.ts +3 -0
- package/esm/langs/sk.js +4 -1
- package/esm/langs/sv.d.ts +3 -0
- package/esm/langs/sv.js +4 -1
- package/esm/langs/tr.d.ts +3 -0
- package/esm/langs/tr.js +4 -1
- package/esm/langs/ua.d.ts +3 -0
- package/esm/langs/ua.js +4 -1
- package/esm/langs/zh_cn.d.ts +3 -0
- package/esm/langs/zh_cn.js +4 -1
- package/esm/langs/zh_tw.d.ts +3 -0
- package/esm/langs/zh_tw.js +4 -1
- package/esm/modules/dialog/dialog.d.ts +7 -0
- package/esm/modules/dialog/dialog.js +24 -6
- package/esm/modules/file-browser/ui/files/files.js +17 -2
- package/esm/modules/file-browser/ui/tree/tree.js +17 -2
- package/esm/modules/table/table.d.ts +6 -0
- package/esm/modules/table/table.js +18 -26
- package/esm/plugins/backspace/cases/check-join-neighbors.js +90 -3
- package/esm/plugins/backspace/cases/check-remove-char.d.ts +2 -1
- package/esm/plugins/backspace/cases/check-remove-char.js +25 -4
- package/esm/plugins/backspace/config.d.ts +2 -0
- package/esm/plugins/backspace/config.js +6 -3
- package/esm/plugins/clean-html/clean-html.d.ts +8 -0
- package/esm/plugins/clean-html/clean-html.js +21 -1
- package/esm/plugins/clean-html/helpers/index.d.ts +1 -0
- package/esm/plugins/clean-html/helpers/index.js +1 -0
- package/esm/plugins/clean-html/helpers/remove-placeholder-br.d.ts +16 -0
- package/esm/plugins/clean-html/helpers/remove-placeholder-br.js +51 -0
- package/esm/plugins/delete/delete.d.ts +11 -1
- package/esm/plugins/delete/delete.js +92 -16
- package/esm/plugins/focus/focus.js +12 -1
- package/esm/plugins/iframe/config.d.ts +3 -0
- package/esm/plugins/iframe/config.js +0 -27
- package/esm/plugins/iframe/iframe.js +8 -1
- package/esm/plugins/image-processor/image-processor.js +6 -1
- package/esm/plugins/image-properties/image-properties.d.ts +5 -0
- package/esm/plugins/image-properties/image-properties.js +30 -5
- package/esm/plugins/inline-popup/inline-popup.d.ts +19 -0
- package/esm/plugins/inline-popup/inline-popup.js +70 -1
- package/esm/plugins/mobile/mobile.js +7 -4
- package/esm/plugins/ordered-list/config.js +13 -2
- package/esm/plugins/ordered-list/start-dialog.d.ts +19 -0
- package/esm/plugins/ordered-list/start-dialog.js +58 -0
- package/esm/plugins/placeholder/placeholder.js +7 -1
- package/esm/plugins/resizer/resizer.d.ts +10 -0
- package/esm/plugins/resizer/resizer.js +76 -2
- package/esm/plugins/select-cells/select-cells.d.ts +23 -0
- package/esm/plugins/select-cells/select-cells.js +75 -1
- package/esm/plugins/table-keyboard-navigation/table-keyboard-navigation.js +3 -2
- package/package.json +1 -1
- package/types/config.d.ts +5 -0
- package/types/core/helpers/html/word-lists.d.ts +29 -0
- package/types/core/selection/helpers/index.d.ts +1 -0
- package/types/core/selection/helpers/is-moved.d.ts +15 -0
- package/types/langs/ar.d.ts +3 -0
- package/types/langs/az.d.ts +3 -0
- package/types/langs/cs_cz.d.ts +3 -0
- package/types/langs/de.d.ts +3 -0
- package/types/langs/es.d.ts +3 -0
- package/types/langs/fa.d.ts +3 -0
- package/types/langs/fi.d.ts +3 -0
- package/types/langs/fr.d.ts +3 -0
- package/types/langs/he.d.ts +3 -0
- package/types/langs/hu.d.ts +3 -0
- package/types/langs/id.d.ts +3 -0
- package/types/langs/it.d.ts +3 -0
- package/types/langs/ja.d.ts +3 -0
- package/types/langs/ko.d.ts +3 -0
- package/types/langs/mn.d.ts +3 -0
- package/types/langs/nl.d.ts +3 -0
- package/types/langs/no.d.ts +3 -0
- package/types/langs/pl.d.ts +3 -0
- package/types/langs/pt_br.d.ts +3 -0
- package/types/langs/ru.d.ts +3 -0
- package/types/langs/sk.d.ts +3 -0
- package/types/langs/sv.d.ts +3 -0
- package/types/langs/tr.d.ts +3 -0
- package/types/langs/ua.d.ts +3 -0
- package/types/langs/zh_cn.d.ts +3 -0
- package/types/langs/zh_tw.d.ts +3 -0
- package/types/modules/dialog/dialog.d.ts +7 -0
- package/types/modules/table/table.d.ts +6 -0
- package/types/plugins/backspace/cases/check-remove-char.d.ts +2 -1
- package/types/plugins/backspace/config.d.ts +2 -0
- package/types/plugins/clean-html/clean-html.d.ts +8 -0
- package/types/plugins/clean-html/helpers/index.d.ts +1 -0
- package/types/plugins/clean-html/helpers/remove-placeholder-br.d.ts +16 -0
- package/types/plugins/delete/delete.d.ts +11 -1
- package/types/plugins/iframe/config.d.ts +3 -0
- package/types/plugins/image-properties/image-properties.d.ts +5 -0
- package/types/plugins/inline-popup/inline-popup.d.ts +19 -0
- package/types/plugins/ordered-list/start-dialog.d.ts +19 -0
- package/types/plugins/resizer/resizer.d.ts +10 -0
- package/types/plugins/select-cells/select-cells.d.ts +23 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Dom } from "../../core/dom/index.js";
|
|
7
7
|
import { pluginSystem } from "../../core/global.js";
|
|
8
|
-
import {
|
|
8
|
+
import { toArray } from "../../core/helpers/index.js";
|
|
9
9
|
import { trim } from "../../core/helpers/string/trim.js";
|
|
10
10
|
import { Plugin } from "../../core/plugin/index.js";
|
|
11
11
|
import "./interface.js";
|
|
@@ -56,6 +56,11 @@ export class deleteCommand extends Plugin {
|
|
|
56
56
|
}
|
|
57
57
|
jodit.s.expandSelection();
|
|
58
58
|
const range = jodit.s.range;
|
|
59
|
+
const caret = this.__clearSelectedCells(range);
|
|
60
|
+
if (caret && range.collapsed) {
|
|
61
|
+
jodit.s.selectRange(caret);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
59
64
|
range.deleteContents();
|
|
60
65
|
const fake = jodit.createInside.fake();
|
|
61
66
|
range.insertNode(fake);
|
|
@@ -65,13 +70,78 @@ export class deleteCommand extends Plugin {
|
|
|
65
70
|
range.setStartBefore(fake);
|
|
66
71
|
range.collapse(true);
|
|
67
72
|
this.__moveCursorInEditableSibling(jodit, leftSibling, fake, range);
|
|
68
|
-
this.__addBrInEmptyBlock(fake,
|
|
73
|
+
this.__addBrInEmptyBlock(fake, range);
|
|
69
74
|
Dom.safeRemove(fake);
|
|
70
|
-
jodit.s.selectRange(range);
|
|
75
|
+
jodit.s.selectRange(caret !== null && caret !== void 0 ? caret : range);
|
|
71
76
|
return false;
|
|
72
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* A selection that starts or ends in a table cell clears the selected part
|
|
80
|
+
* of each cell it covers and keeps the cells, as the browsers do.
|
|
81
|
+
* `deleteContents` would remove the cells it fully covers, and the cells
|
|
82
|
+
* it cuts would then be merged as blocks. The range is moved out of those
|
|
83
|
+
* tables, so only the content between them is left to delete.
|
|
84
|
+
*
|
|
85
|
+
* Returns where the caret goes, or null when no table is involved
|
|
86
|
+
*/
|
|
87
|
+
__clearSelectedCells(range) {
|
|
88
|
+
const { editor, createInside } = this.j;
|
|
89
|
+
const startCell = Dom.closest(range.startContainer, Dom.isCell, editor);
|
|
90
|
+
const endCell = Dom.closest(range.endContainer, Dom.isCell, editor);
|
|
91
|
+
if (startCell === endCell) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const startTable = Dom.closest(startCell, 'table', editor);
|
|
95
|
+
const endTable = Dom.closest(endCell, 'table', editor);
|
|
96
|
+
const caret = range.cloneRange();
|
|
97
|
+
caret.collapse(true);
|
|
98
|
+
const parts = [];
|
|
99
|
+
const addParts = (table) => {
|
|
100
|
+
toArray(table.rows)
|
|
101
|
+
.flatMap(row => toArray(row.cells))
|
|
102
|
+
.filter(cell => range.intersectsNode(cell))
|
|
103
|
+
.forEach(cell => {
|
|
104
|
+
const part = range.cloneRange();
|
|
105
|
+
if (!Dom.isOrContains(cell, range.startContainer)) {
|
|
106
|
+
part.setStart(cell, 0);
|
|
107
|
+
}
|
|
108
|
+
if (!Dom.isOrContains(cell, range.endContainer)) {
|
|
109
|
+
part.setEnd(cell, cell.childNodes.length);
|
|
110
|
+
}
|
|
111
|
+
parts.push([cell, part]);
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
if (startTable) {
|
|
115
|
+
addParts(startTable);
|
|
116
|
+
if (startTable === endTable) {
|
|
117
|
+
range.collapse(true);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
range.setStartAfter(startTable);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (endTable && endTable !== startTable) {
|
|
124
|
+
addParts(endTable);
|
|
125
|
+
range.setEndBefore(endTable);
|
|
126
|
+
}
|
|
127
|
+
parts.forEach(([cell, part]) => {
|
|
128
|
+
part.deleteContents();
|
|
129
|
+
if (Dom.isEmpty(cell)) {
|
|
130
|
+
Dom.detach(cell);
|
|
131
|
+
Dom.append(cell, createInside.element('br'));
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
return startTable ? caret : null;
|
|
135
|
+
}
|
|
73
136
|
__moveContentInLeftSibling(fake, leftSibling, rightSibling) {
|
|
74
137
|
leftSibling = this.__defineRightLeftBox(leftSibling);
|
|
138
|
+
// Nothing is moved into a table, and a block left empty after it goes
|
|
139
|
+
if (Dom.isTag(leftSibling, 'table')) {
|
|
140
|
+
if (Dom.isBlock(rightSibling) && Dom.isEmpty(rightSibling)) {
|
|
141
|
+
Dom.safeRemove(rightSibling);
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
75
145
|
if (!Dom.isList(rightSibling) &&
|
|
76
146
|
!Dom.isTag(rightSibling, 'table') &&
|
|
77
147
|
Dom.isBlock(rightSibling) &&
|
|
@@ -80,11 +150,24 @@ export class deleteCommand extends Plugin {
|
|
|
80
150
|
Dom.moveContent(rightSibling, leftSibling);
|
|
81
151
|
Dom.safeRemove(rightSibling);
|
|
82
152
|
}
|
|
83
|
-
// Remove empty right LI
|
|
84
153
|
if (Dom.isList(rightSibling) &&
|
|
85
|
-
Dom.isLeaf(rightSibling.firstElementChild)
|
|
86
|
-
|
|
87
|
-
|
|
154
|
+
Dom.isLeaf(rightSibling.firstElementChild)) {
|
|
155
|
+
const item = rightSibling.firstElementChild;
|
|
156
|
+
// What's left of the right list's first item joins the left block,
|
|
157
|
+
// up to a list nested in the item
|
|
158
|
+
if (!Dom.isEmpty(item) && Dom.isBlock(leftSibling)) {
|
|
159
|
+
Dom.append(leftSibling, fake);
|
|
160
|
+
while (item.firstChild && !Dom.isBlock(item.firstChild)) {
|
|
161
|
+
Dom.append(leftSibling, item.firstChild);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Remove empty right LI
|
|
165
|
+
if (Dom.isEmpty(item)) {
|
|
166
|
+
Dom.safeRemove(item);
|
|
167
|
+
}
|
|
168
|
+
if (Dom.isEmpty(rightSibling)) {
|
|
169
|
+
Dom.safeRemove(rightSibling);
|
|
170
|
+
}
|
|
88
171
|
}
|
|
89
172
|
}
|
|
90
173
|
/**
|
|
@@ -102,9 +185,9 @@ export class deleteCommand extends Plugin {
|
|
|
102
185
|
return lastLeaf;
|
|
103
186
|
}
|
|
104
187
|
/**
|
|
105
|
-
* Add BR in empty
|
|
188
|
+
* Add BR in the empty block left at the caret
|
|
106
189
|
*/
|
|
107
|
-
__addBrInEmptyBlock(fake,
|
|
190
|
+
__addBrInEmptyBlock(fake, range) {
|
|
108
191
|
const jodit = this.j;
|
|
109
192
|
if (fake.isConnected &&
|
|
110
193
|
Dom.isBlock(fake.parentNode) &&
|
|
@@ -115,13 +198,6 @@ export class deleteCommand extends Plugin {
|
|
|
115
198
|
range.setStartBefore(br);
|
|
116
199
|
range.collapse(true);
|
|
117
200
|
}
|
|
118
|
-
// Add BR in the right empty table cell
|
|
119
|
-
if (Dom.isTag(rightSibling, 'table')) {
|
|
120
|
-
const firstCell = $$('td,th', rightSibling).shift();
|
|
121
|
-
if (Dom.isCell(firstCell) && Dom.isEmpty(firstCell)) {
|
|
122
|
-
Dom.append(firstCell, jodit.createInside.element('br'));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
201
|
}
|
|
126
202
|
__moveCursorInEditableSibling(jodit, leftSibling, fake, range) {
|
|
127
203
|
var _a;
|
|
@@ -67,7 +67,18 @@ export function focus(editor) {
|
|
|
67
67
|
editor.e.on('afterInit', () => {
|
|
68
68
|
if (editor.o.autofocus) {
|
|
69
69
|
if (editor.defaultTimeout) {
|
|
70
|
-
editor
|
|
70
|
+
// A click or key in the editor during the delay has put the
|
|
71
|
+
// caret where the user wants it, so autofocus leaves it there
|
|
72
|
+
const userInput = 'mousedown touchstart keydown';
|
|
73
|
+
const cancel = () => {
|
|
74
|
+
editor.async.clearTimeout(timeout);
|
|
75
|
+
editor.e.off(userInput, cancel);
|
|
76
|
+
};
|
|
77
|
+
const timeout = editor.async.setTimeout(() => {
|
|
78
|
+
editor.e.off(userInput, cancel);
|
|
79
|
+
focus();
|
|
80
|
+
}, 300);
|
|
81
|
+
editor.e.on(userInput, cancel);
|
|
71
82
|
}
|
|
72
83
|
else {
|
|
73
84
|
focus();
|
|
@@ -37,6 +37,9 @@ declare module 'jodit/config' {
|
|
|
37
37
|
iframeDoctype: string;
|
|
38
38
|
/**
|
|
39
39
|
* Custom style to be used inside the iframe to display content.
|
|
40
|
+
* It goes in after `iframeCSSLinks`. The rules Jodit's own plugins need
|
|
41
|
+
* in the editing document are added apart from it, so a value of your
|
|
42
|
+
* own doesn't have to repeat them.
|
|
40
43
|
*
|
|
41
44
|
* ```javascript
|
|
42
45
|
* Jodit.make('#editor', {
|
|
@@ -51,33 +51,6 @@ Config.prototype.iframeStyle =
|
|
|
51
51
|
'p{' +
|
|
52
52
|
'margin-top:0;' +
|
|
53
53
|
'}' +
|
|
54
|
-
'[data-jodit_iframe_wrapper]{' +
|
|
55
|
-
'display: block;' +
|
|
56
|
-
'user-select: none;' +
|
|
57
|
-
'position: relative;' +
|
|
58
|
-
'}' +
|
|
59
|
-
'[data-jodit_iframe_wrapper] iframe{' +
|
|
60
|
-
'position: relative;' +
|
|
61
|
-
'}' +
|
|
62
|
-
'[data-jodit_iframe_wrapper]:after {' +
|
|
63
|
-
'position:absolute;' +
|
|
64
|
-
'content:"";' +
|
|
65
|
-
'z-index:1;' +
|
|
66
|
-
'top:0;' +
|
|
67
|
-
'left:0;' +
|
|
68
|
-
'right: 0;' +
|
|
69
|
-
'bottom: 0;' +
|
|
70
|
-
'cursor: pointer;' +
|
|
71
|
-
'display: block;' +
|
|
72
|
-
'background: rgba(0, 0, 0, 0);' +
|
|
73
|
-
'} ' +
|
|
74
|
-
'[data-jodit_iframe_wrapper][data-jodit-wrapper_active=true] iframe{' +
|
|
75
|
-
'z-index: 2;' +
|
|
76
|
-
'}' +
|
|
77
|
-
'.jodit-wysiwyg_image-selected::selection,' +
|
|
78
|
-
'.jodit-wysiwyg_image-selected *:not(img)::selection{' +
|
|
79
|
-
'background:transparent' +
|
|
80
|
-
'}' +
|
|
81
54
|
'.jodit_disabled{' +
|
|
82
55
|
'user-select: none;' +
|
|
83
56
|
'-o-user-select: none;' +
|
|
@@ -7,7 +7,7 @@ import { MODE_SOURCE } from "../../core/constants.js";
|
|
|
7
7
|
import { Dom } from "../../core/dom/dom.js";
|
|
8
8
|
import { pluginSystem } from "../../core/global.js";
|
|
9
9
|
import { error } from "../../core/helpers/index.js";
|
|
10
|
-
import { attr, callPromise, css, defaultLanguage } from "../../core/helpers/index.js";
|
|
10
|
+
import { $$, attr, callPromise, css, defaultLanguage } from "../../core/helpers/index.js";
|
|
11
11
|
import "./config.js";
|
|
12
12
|
/**
|
|
13
13
|
* Iframe plugin - use `iframe` instead of DIV in editor. It can be need when you want to attach custom styles in editor
|
|
@@ -43,6 +43,8 @@ export function iframe(editor) {
|
|
|
43
43
|
attr(link, 'rel', 'stylesheet');
|
|
44
44
|
attr(link, 'href', href);
|
|
45
45
|
doc.head && Dom.append(doc.head, link);
|
|
46
|
+
// What plugins measured in the editing document changes once it's styled
|
|
47
|
+
jodit.e.on(link, 'load', () => jodit.e.fire('resize'));
|
|
46
48
|
});
|
|
47
49
|
}
|
|
48
50
|
if (opt.iframeStyle) {
|
|
@@ -83,6 +85,8 @@ export function iframe(editor) {
|
|
|
83
85
|
null);
|
|
84
86
|
};
|
|
85
87
|
const clearMarkers = (html) => {
|
|
88
|
+
// The plugins' own styles, from `getContainer`, aren't part of the value
|
|
89
|
+
html = html.replace(/<style[^>]+jodit-box[^>]*>[\s\S]*?<\/style>/gi, '');
|
|
86
90
|
const bodyReg = /<body.*<\/body>/im, bodyMarker = '{%%BODY%%}', body = bodyReg.exec(html);
|
|
87
91
|
if (body) {
|
|
88
92
|
// remove markers
|
|
@@ -119,7 +123,10 @@ export function iframe(editor) {
|
|
|
119
123
|
const replaceDocument = (html) => {
|
|
120
124
|
const inert = new DOMParser().parseFromString(html, 'text/html');
|
|
121
125
|
editor.e.fire('safeHTML', inert.documentElement);
|
|
126
|
+
// The plugins' own styles stay, as the value leaves them out
|
|
127
|
+
const styles = $$('style.jodit-box', doc.head);
|
|
122
128
|
doc.replaceChild(doc.adoptNode(inert.documentElement), doc.documentElement);
|
|
129
|
+
styles.forEach(style => Dom.append(doc.head, style));
|
|
123
130
|
};
|
|
124
131
|
if (docMode) {
|
|
125
132
|
const tag = editor.element.tagName;
|
|
@@ -16,7 +16,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
16
16
|
import { INVISIBLE_SPACE_REG_EXP, SOURCE_CONSUMER } from "../../core/constants.js";
|
|
17
17
|
import { autobind, cached, debounce, watch } from "../../core/decorators/index.js";
|
|
18
18
|
import { Dom } from "../../core/dom/dom.js";
|
|
19
|
-
import { pluginSystem } from "../../core/global.js";
|
|
19
|
+
import { getContainer, pluginSystem } from "../../core/global.js";
|
|
20
20
|
import { $$, dataBind, getWrappedMedia } from "../../core/helpers/index.js";
|
|
21
21
|
import { Plugin } from "../../core/plugin/index.js";
|
|
22
22
|
import { dataURItoBlob } from "../../modules/uploader/helpers/data-uri-to-blob.js";
|
|
@@ -31,6 +31,11 @@ const SELECTED_TAGS = new Set(['img', 'jodit', 'jodit-media']);
|
|
|
31
31
|
export class imageProcessor extends Plugin {
|
|
32
32
|
afterInit(jodit) {
|
|
33
33
|
jodit.e.on(jodit.ed, 'selectionchange', this.onSelectionChange);
|
|
34
|
+
// Over the highlight in `styles/reset.less`; the image keeps its own. It goes
|
|
35
|
+
// in the editing document, so iframe mode has it whatever `iframeStyle` holds
|
|
36
|
+
getContainer(jodit, 'image-processor', 'style', true).textContent =
|
|
37
|
+
`.jodit-wysiwyg.${IMAGE_SELECTED}::selection,` +
|
|
38
|
+
`.jodit-wysiwyg.${IMAGE_SELECTED} *:not(img)::selection{background:transparent}`;
|
|
34
39
|
}
|
|
35
40
|
beforeDestruct(jodit) {
|
|
36
41
|
jodit.e.off(jodit.ed, 'selectionchange', this.onSelectionChange);
|
|
@@ -52,6 +52,11 @@ export declare class imageProperties extends Plugin {
|
|
|
52
52
|
* ```
|
|
53
53
|
*/
|
|
54
54
|
protected open(): void | false;
|
|
55
|
+
/**
|
|
56
|
+
* Keys typed while the dialog is open must not reach the editor behind it,
|
|
57
|
+
* so focus the active tab's first field, or else the first field shown
|
|
58
|
+
*/
|
|
59
|
+
private __focusFirstField;
|
|
55
60
|
private __lock;
|
|
56
61
|
private __unlock;
|
|
57
62
|
/** @override **/
|
|
@@ -16,7 +16,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
16
16
|
import { cache, cached, watch } from "../../core/decorators/index.js";
|
|
17
17
|
import { Dom } from "../../core/dom/dom.js";
|
|
18
18
|
import { pluginSystem } from "../../core/global.js";
|
|
19
|
-
import { isAbortError, isNumeric, markOwner } from "../../core/helpers/index.js";
|
|
19
|
+
import { isAbortError, isNumeric, markOwner, toArray } from "../../core/helpers/index.js";
|
|
20
20
|
import { Plugin } from "../../core/plugin/plugin.js";
|
|
21
21
|
import { Button } from "../../core/ui/button/index.js";
|
|
22
22
|
import "./config.js";
|
|
@@ -99,8 +99,12 @@ export class imageProperties extends Plugin {
|
|
|
99
99
|
dialog.close();
|
|
100
100
|
});
|
|
101
101
|
buttons.remove.onAction(() => {
|
|
102
|
+
const caret = j.s.createRange();
|
|
103
|
+
caret.setStartBefore(this.state.sourceImage);
|
|
104
|
+
caret.collapse(true);
|
|
102
105
|
j.s.removeNode(this.state.sourceImage);
|
|
103
106
|
dialog.close();
|
|
107
|
+
j.s.selectRange(caret);
|
|
104
108
|
});
|
|
105
109
|
buttons.cancel.onAction(() => {
|
|
106
110
|
dialog.close();
|
|
@@ -108,11 +112,20 @@ export class imageProperties extends Plugin {
|
|
|
108
112
|
dialog.setHeader(j.i18n('Image properties'));
|
|
109
113
|
dialog.setContent(this.form);
|
|
110
114
|
dialog.setFooter([[buttons.cancel, buttons.remove], buttons.check]);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
// The dialog fires `afterClose` on its own emitter, not the editor's
|
|
116
|
+
dialog.e.on(dialog, 'afterClose', () => {
|
|
117
|
+
const { sourceImage } = this.state;
|
|
118
|
+
if (j.isInDestruct || !Dom.isOrContains(j.editor, sourceImage)) {
|
|
119
|
+
return;
|
|
115
120
|
}
|
|
121
|
+
if (j.o.image.selectImageAfterClose) {
|
|
122
|
+
j.s.select(sourceImage);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const caret = j.s.createRange();
|
|
126
|
+
caret.setStartAfter(sourceImage);
|
|
127
|
+
caret.collapse(true);
|
|
128
|
+
j.s.selectRange(caret);
|
|
116
129
|
});
|
|
117
130
|
dialog.setSize(j.o.image.dialogWidth);
|
|
118
131
|
markOwner(j, dialog.container);
|
|
@@ -144,6 +157,7 @@ export class imageProperties extends Plugin {
|
|
|
144
157
|
this.activeTabState.activeTab = 'Image';
|
|
145
158
|
this.__lock();
|
|
146
159
|
this.dialog.open().setModal(true).setPosition();
|
|
160
|
+
this.__focusFirstField();
|
|
147
161
|
this.async
|
|
148
162
|
.promise((resolve, reject) => readValuesFromImage(this.j, this.state).then(resolve, reject))
|
|
149
163
|
.catch((e) => {
|
|
@@ -154,6 +168,17 @@ export class imageProperties extends Plugin {
|
|
|
154
168
|
.finally(() => this.__unlock());
|
|
155
169
|
return false;
|
|
156
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Keys typed while the dialog is open must not reach the editor behind it,
|
|
173
|
+
* so focus the active tab's first field, or else the first field shown
|
|
174
|
+
*/
|
|
175
|
+
__focusFirstField() {
|
|
176
|
+
var _a;
|
|
177
|
+
const fields = (box) => toArray(box.querySelectorAll('input, select, textarea'));
|
|
178
|
+
(_a = fields(this.form.getElm('tabsBox'))
|
|
179
|
+
.concat(fields(this.form.container))
|
|
180
|
+
.find(field => field.offsetParent != null)) === null || _a === void 0 ? void 0 : _a.focus();
|
|
181
|
+
}
|
|
157
182
|
__lock() {
|
|
158
183
|
this.dialog.lock();
|
|
159
184
|
this.form.setMod('lock', true);
|
|
@@ -37,6 +37,17 @@ export declare class inlinePopup extends Plugin {
|
|
|
37
37
|
*/
|
|
38
38
|
private hidePopup;
|
|
39
39
|
protected onOutsideClick(): void;
|
|
40
|
+
/**
|
|
41
|
+
* A key that moves the caret off an element closes its popup, and one
|
|
42
|
+
* that moves the caret into an element with a popup (a link) opens it,
|
|
43
|
+
* as clicks do
|
|
44
|
+
*/
|
|
45
|
+
protected onKeyUp(): void;
|
|
46
|
+
private __followCaret;
|
|
47
|
+
/**
|
|
48
|
+
* The element with a popup that holds `node`
|
|
49
|
+
*/
|
|
50
|
+
private __elementAt;
|
|
40
51
|
/**
|
|
41
52
|
* Can show popup for this type
|
|
42
53
|
*/
|
|
@@ -53,6 +64,13 @@ export declare class inlinePopup extends Plugin {
|
|
|
53
64
|
* while the selection is still there. See #1238
|
|
54
65
|
*/
|
|
55
66
|
private __reopenSelectionPopup;
|
|
67
|
+
/**
|
|
68
|
+
* The alignment controls fire `recalcPositionPopup` once they have moved
|
|
69
|
+
* the element, and their button then fires `closeAllPopups`. The popup
|
|
70
|
+
* opens again beside the element, as the selection toolbar does
|
|
71
|
+
*/
|
|
72
|
+
private __reopenFor;
|
|
73
|
+
protected onRecalcPositionPopup(): void;
|
|
56
74
|
private __onDocumentMouseDown;
|
|
57
75
|
private __onCloseAllPopups;
|
|
58
76
|
/**
|
|
@@ -64,6 +82,7 @@ export declare class inlinePopup extends Plugin {
|
|
|
64
82
|
private __selectionBound;
|
|
65
83
|
private snapRange;
|
|
66
84
|
private onSelectionStart;
|
|
85
|
+
private __keyDownElement;
|
|
67
86
|
private onSelectionEnd;
|
|
68
87
|
/**
|
|
69
88
|
* Selection change handler
|
|
@@ -18,6 +18,7 @@ import { Dom } from "../../core/dom/index.js";
|
|
|
18
18
|
import { pluginSystem } from "../../core/global.js";
|
|
19
19
|
import { camelCase, getMediaWrapper, getWrappedMedia, isArray, isFunction, isString, keys, position, splitArray, toArray } from "../../core/helpers/index.js";
|
|
20
20
|
import { Plugin } from "../../core/plugin/index.js";
|
|
21
|
+
import { isMoved } from "../../core/selection/helpers/index.js";
|
|
21
22
|
import { UIElement } from "../../core/ui/index.js";
|
|
22
23
|
import { Popup } from "../../core/ui/popup/index.js";
|
|
23
24
|
import { makeCollection } from "../../modules/toolbar/factory.js";
|
|
@@ -35,7 +36,14 @@ export class inlinePopup extends Plugin {
|
|
|
35
36
|
* while the selection is still there. See #1238
|
|
36
37
|
*/
|
|
37
38
|
this.__reopenSelectionPopup = false;
|
|
39
|
+
/**
|
|
40
|
+
* The alignment controls fire `recalcPositionPopup` once they have moved
|
|
41
|
+
* the element, and their button then fires `closeAllPopups`. The popup
|
|
42
|
+
* opens again beside the element, as the selection toolbar does
|
|
43
|
+
*/
|
|
44
|
+
this.__reopenFor = null;
|
|
38
45
|
this.snapRange = null;
|
|
46
|
+
this.__keyDownElement = null;
|
|
39
47
|
this.elmsList = keys(this.j.o.popup, false).filter(s => !this.isExcludedTarget(s));
|
|
40
48
|
}
|
|
41
49
|
get popup() {
|
|
@@ -129,6 +137,38 @@ export class inlinePopup extends Plugin {
|
|
|
129
137
|
onOutsideClick() {
|
|
130
138
|
this.popup.close();
|
|
131
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* A key that moves the caret off an element closes its popup, and one
|
|
142
|
+
* that moves the caret into an element with a popup (a link) opens it,
|
|
143
|
+
* as clicks do
|
|
144
|
+
*/
|
|
145
|
+
onKeyUp() {
|
|
146
|
+
this.__followCaret();
|
|
147
|
+
}
|
|
148
|
+
__followCaret() {
|
|
149
|
+
if (!isMoved(this.j, this.snapRange)) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const { range } = this.j.s;
|
|
153
|
+
const target = this.previousTarget;
|
|
154
|
+
if (this.popup.isOpened &&
|
|
155
|
+
this.type !== 'selection' &&
|
|
156
|
+
target &&
|
|
157
|
+
!range.intersectsNode(target)) {
|
|
158
|
+
this.popup.close();
|
|
159
|
+
}
|
|
160
|
+
const node = range.startContainer;
|
|
161
|
+
const element = this.__elementAt(node);
|
|
162
|
+
if (range.collapsed && element && element !== this.__keyDownElement) {
|
|
163
|
+
this.onClick(node);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* The element with a popup that holds `node`
|
|
168
|
+
*/
|
|
169
|
+
__elementAt(node) {
|
|
170
|
+
return Dom.closest(node, this.elmsList, this.j.editor);
|
|
171
|
+
}
|
|
132
172
|
/**
|
|
133
173
|
* Can show popup for this type
|
|
134
174
|
*/
|
|
@@ -183,7 +223,15 @@ export class inlinePopup extends Plugin {
|
|
|
183
223
|
.on('closeAllPopups', this.__onCloseAllPopups);
|
|
184
224
|
this.addListenersForElements();
|
|
185
225
|
}
|
|
226
|
+
onRecalcPositionPopup() {
|
|
227
|
+
if (this.popup.isOpened &&
|
|
228
|
+
this.type !== 'selection' &&
|
|
229
|
+
this.previousTarget) {
|
|
230
|
+
this.__reopenFor = this.previousTarget;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
186
233
|
__onDocumentMouseDown(e) {
|
|
234
|
+
this.__reopenFor = null;
|
|
187
235
|
if (this.popup.isOpened &&
|
|
188
236
|
this.type === 'selection' &&
|
|
189
237
|
e.target &&
|
|
@@ -192,6 +240,16 @@ export class inlinePopup extends Plugin {
|
|
|
192
240
|
}
|
|
193
241
|
}
|
|
194
242
|
__onCloseAllPopups() {
|
|
243
|
+
const target = this.__reopenFor;
|
|
244
|
+
if (target) {
|
|
245
|
+
this.__reopenFor = null;
|
|
246
|
+
// After the popup's own `closeAllPopups` handler, as below
|
|
247
|
+
this.j.async.setTimeout(() => {
|
|
248
|
+
if (this.j.editor.contains(target)) {
|
|
249
|
+
this.onClick(target);
|
|
250
|
+
}
|
|
251
|
+
}, 1);
|
|
252
|
+
}
|
|
195
253
|
if (!this.__reopenSelectionPopup) {
|
|
196
254
|
return;
|
|
197
255
|
}
|
|
@@ -224,8 +282,13 @@ export class inlinePopup extends Plugin {
|
|
|
224
282
|
}
|
|
225
283
|
return { left, top, width: rect.width, height: rect.height };
|
|
226
284
|
}
|
|
227
|
-
onSelectionStart() {
|
|
285
|
+
onSelectionStart(event) {
|
|
286
|
+
// A key held down moves the caret on every repeat, with one keyup
|
|
287
|
+
if (event === null || event === void 0 ? void 0 : event.repeat) {
|
|
288
|
+
this.__followCaret();
|
|
289
|
+
}
|
|
228
290
|
this.snapRange = this.j.s.range.cloneRange();
|
|
291
|
+
this.__keyDownElement = this.__elementAt(this.snapRange.startContainer);
|
|
229
292
|
}
|
|
230
293
|
onSelectionEnd(e) {
|
|
231
294
|
if (e &&
|
|
@@ -339,6 +402,12 @@ __decorate([
|
|
|
339
402
|
__decorate([
|
|
340
403
|
watch(':outsideClick')
|
|
341
404
|
], inlinePopup.prototype, "onOutsideClick", null);
|
|
405
|
+
__decorate([
|
|
406
|
+
watch(':keyup')
|
|
407
|
+
], inlinePopup.prototype, "onKeyUp", null);
|
|
408
|
+
__decorate([
|
|
409
|
+
watch(':recalcPositionPopup')
|
|
410
|
+
], inlinePopup.prototype, "onRecalcPositionPopup", null);
|
|
342
411
|
__decorate([
|
|
343
412
|
autobind
|
|
344
413
|
], inlinePopup.prototype, "__onDocumentMouseDown", null);
|
|
@@ -78,9 +78,11 @@ function fitToButtons(list, editor) {
|
|
|
78
78
|
return cleaned;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
* The width that decides which breakpoint set the toolbar uses
|
|
82
|
-
*
|
|
83
|
-
*
|
|
81
|
+
* The width that decides which breakpoint set the toolbar uses: the editor's
|
|
82
|
+
* own width, or its parent's while the editor has none yet (for example
|
|
83
|
+
* while hidden at init). A toolbar rendered into an external container
|
|
84
|
+
* (`toolbar` set to an element or a selector) lays out in that container, so
|
|
85
|
+
* its width is what matters there.
|
|
84
86
|
*/
|
|
85
87
|
function adaptiveWidth(editor) {
|
|
86
88
|
var _a;
|
|
@@ -91,7 +93,8 @@ function adaptiveWidth(editor) {
|
|
|
91
93
|
return width;
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
|
-
return (
|
|
96
|
+
return (editor.container.offsetWidth ||
|
|
97
|
+
((_a = editor.container.parentElement) !== null && _a !== void 0 ? _a : editor.container).offsetWidth);
|
|
95
98
|
}
|
|
96
99
|
/**
|
|
97
100
|
* Rebuild toolbar in depends on editor's width
|
|
@@ -8,10 +8,19 @@ import { Icon } from "../../core/ui/icon.js";
|
|
|
8
8
|
import { Config } from "../../config.js";
|
|
9
9
|
import olIcon from "./icons/ol.svg.js";
|
|
10
10
|
import ulIcon from "./icons/ul.svg.js";
|
|
11
|
+
import { closestOrderedList, openStartDialog } from "./start-dialog.js";
|
|
12
|
+
/**
|
|
13
|
+
* The `ol` dropdown item that asks for the list's start number
|
|
14
|
+
*/
|
|
15
|
+
const START = 'start';
|
|
11
16
|
const memoExec = (jodit, _, { control }) => {
|
|
12
17
|
var _a;
|
|
13
18
|
const key = `button${control.command}`;
|
|
14
19
|
const value = (_a = (control.args && control.args[0])) !== null && _a !== void 0 ? _a : dataBind(jodit, key);
|
|
20
|
+
if (value === START) {
|
|
21
|
+
openStartDialog(jodit);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
15
24
|
dataBind(jodit, key, value);
|
|
16
25
|
jodit.execCommand(control.command, false, value === 'default' ? null : value);
|
|
17
26
|
};
|
|
@@ -38,7 +47,9 @@ Config.prototype.controls.ol = {
|
|
|
38
47
|
'lower-greek': 'Lower Greek',
|
|
39
48
|
'lower-roman': 'Lower Roman',
|
|
40
49
|
'upper-alpha': 'Upper Alpha',
|
|
41
|
-
'upper-roman': 'Upper Roman'
|
|
50
|
+
'upper-roman': 'Upper Roman',
|
|
51
|
+
[START]: 'Start at...'
|
|
42
52
|
},
|
|
43
|
-
exec: memoExec
|
|
53
|
+
exec: memoExec,
|
|
54
|
+
isChildDisabled: (jodit, button) => { var _a; return ((_a = button.control.args) === null || _a === void 0 ? void 0 : _a[0]) === START && !closestOrderedList(jodit); }
|
|
44
55
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @module plugins/ordered-list
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit, Nullable } from "../../types/index";
|
|
10
|
+
/**
|
|
11
|
+
* The numbered list the selection is in
|
|
12
|
+
*/
|
|
13
|
+
export declare function closestOrderedList(jodit: IJodit): Nullable<HTMLOListElement>;
|
|
14
|
+
/**
|
|
15
|
+
* Asks for the number of the first item of the list the selection is in,
|
|
16
|
+
* and sets the list's `start`. The selection is put back when the dialog
|
|
17
|
+
* closes, however it closes.
|
|
18
|
+
*/
|
|
19
|
+
export declare function openStartDialog(jodit: IJodit): void;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
import { Dom } from "../../core/dom/dom.js";
|
|
7
|
+
import { attr } from "../../core/helpers/utils/attr.js";
|
|
8
|
+
import { Button } from "../../core/ui/button/index.js";
|
|
9
|
+
import { UIBlock, UIForm, UIInput } from "../../core/ui/form/index.js";
|
|
10
|
+
/**
|
|
11
|
+
* The numbered list the selection is in
|
|
12
|
+
*/
|
|
13
|
+
export function closestOrderedList(jodit) {
|
|
14
|
+
const current = jodit.s.current();
|
|
15
|
+
return current ? Dom.closest(current, 'ol', jodit.editor) : null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Asks for the number of the first item of the list the selection is in,
|
|
19
|
+
* and sets the list's `start`. The selection is put back when the dialog
|
|
20
|
+
* closes, however it closes.
|
|
21
|
+
*/
|
|
22
|
+
export function openStartDialog(jodit) {
|
|
23
|
+
const list = closestOrderedList(jodit);
|
|
24
|
+
if (!list) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const dialog = jodit.dlg({ resizable: false, closeOnClickOverlay: true });
|
|
28
|
+
const input = new UIInput(jodit, {
|
|
29
|
+
name: 'start',
|
|
30
|
+
type: 'number',
|
|
31
|
+
label: 'Number for the first item',
|
|
32
|
+
value: list.start
|
|
33
|
+
});
|
|
34
|
+
const form = new UIForm(jodit, [new UIBlock(jodit, [input])]);
|
|
35
|
+
form.container.classList.add('jodit-dialog_alert');
|
|
36
|
+
form.onSubmit(({ start }) => {
|
|
37
|
+
const value = start === '' ? 1 : parseInt(start, 10);
|
|
38
|
+
if (isNaN(value)) {
|
|
39
|
+
input.focus();
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
dialog.close();
|
|
43
|
+
attr(list, 'start', value === 1 ? null : value);
|
|
44
|
+
jodit.synchronizeValues();
|
|
45
|
+
});
|
|
46
|
+
jodit.s.save();
|
|
47
|
+
dialog.e.on(dialog, 'afterClose', () => {
|
|
48
|
+
jodit.s.focus();
|
|
49
|
+
jodit.s.restore();
|
|
50
|
+
});
|
|
51
|
+
dialog.setFooter([
|
|
52
|
+
Button(jodit, 'cancel', 'Cancel').onAction(() => dialog.close()),
|
|
53
|
+
Button(jodit, 'ok', 'Apply', 'primary').onAction(() => form.submit())
|
|
54
|
+
]);
|
|
55
|
+
dialog.open(form, jodit.i18n('Start numbering at'), true, true);
|
|
56
|
+
input.focus();
|
|
57
|
+
input.nativeInput.select();
|
|
58
|
+
}
|