jodit 4.18.3 → 4.18.6
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 +52 -0
- package/es2015/jodit.css +72 -34
- package/es2015/jodit.fat.min.css +1 -1
- package/es2015/jodit.fat.min.js +35 -10
- package/es2015/jodit.js +1967 -327
- package/es2015/jodit.min.css +1 -1
- package/es2015/jodit.min.js +41 -16
- 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 +35 -10
- package/es2018/jodit.min.css +1 -1
- package/es2018/jodit.min.js +35 -10
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021/jodit.css +72 -34
- package/es2021/jodit.fat.min.css +1 -1
- package/es2021/jodit.fat.min.js +42 -17
- package/es2021/jodit.js +1949 -323
- package/es2021/jodit.min.css +1 -1
- package/es2021/jodit.min.js +42 -17
- 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 +72 -34
- package/es2021.en/jodit.fat.min.css +1 -1
- package/es2021.en/jodit.fat.min.js +42 -17
- package/es2021.en/jodit.js +1923 -297
- package/es2021.en/jodit.min.css +1 -1
- package/es2021.en/jodit.min.js +51 -26
- 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 +85 -38
- package/es5/jodit.fat.min.css +1 -1
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +2225 -379
- 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 +28 -26
- package/esm/config.js +19 -21
- package/esm/core/constants.js +1 -1
- 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/helpers/utils/align.d.ts +1 -1
- package/esm/core/helpers/utils/align.js +2 -3
- 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/jodit.js +14 -4
- package/esm/langs/ar.d.ts +10 -0
- package/esm/langs/ar.js +11 -1
- package/esm/langs/az.d.ts +10 -0
- package/esm/langs/az.js +11 -1
- package/esm/langs/cs_cz.d.ts +10 -0
- package/esm/langs/cs_cz.js +12 -1
- package/esm/langs/de.d.ts +10 -0
- package/esm/langs/de.js +11 -1
- package/esm/langs/es.d.ts +10 -0
- package/esm/langs/es.js +11 -1
- package/esm/langs/fa.d.ts +10 -0
- package/esm/langs/fa.js +11 -1
- package/esm/langs/fi.d.ts +10 -0
- package/esm/langs/fi.js +11 -1
- package/esm/langs/fr.d.ts +10 -0
- package/esm/langs/fr.js +11 -1
- package/esm/langs/he.d.ts +10 -0
- package/esm/langs/he.js +11 -1
- package/esm/langs/hu.d.ts +10 -0
- package/esm/langs/hu.js +11 -1
- package/esm/langs/id.d.ts +10 -0
- package/esm/langs/id.js +11 -1
- package/esm/langs/it.d.ts +10 -0
- package/esm/langs/it.js +11 -1
- package/esm/langs/ja.d.ts +10 -0
- package/esm/langs/ja.js +11 -1
- package/esm/langs/ko.d.ts +10 -0
- package/esm/langs/ko.js +11 -1
- package/esm/langs/mn.d.ts +10 -0
- package/esm/langs/mn.js +11 -1
- package/esm/langs/nl.d.ts +10 -0
- package/esm/langs/nl.js +11 -1
- package/esm/langs/no.d.ts +10 -0
- package/esm/langs/no.js +11 -1
- package/esm/langs/pl.d.ts +10 -0
- package/esm/langs/pl.js +11 -1
- package/esm/langs/pt_br.d.ts +10 -0
- package/esm/langs/pt_br.js +11 -1
- package/esm/langs/ru.d.ts +10 -0
- package/esm/langs/ru.js +11 -1
- package/esm/langs/sk.d.ts +10 -0
- package/esm/langs/sk.js +11 -1
- package/esm/langs/sv.d.ts +10 -0
- package/esm/langs/sv.js +11 -1
- package/esm/langs/tr.d.ts +10 -0
- package/esm/langs/tr.js +11 -1
- package/esm/langs/ua.d.ts +10 -0
- package/esm/langs/ua.js +11 -1
- package/esm/langs/zh_cn.d.ts +10 -0
- package/esm/langs/zh_cn.js +11 -1
- package/esm/langs/zh_tw.d.ts +10 -0
- package/esm/langs/zh_tw.js +11 -1
- package/esm/modules/dialog/dialog.d.ts +7 -0
- package/esm/modules/dialog/dialog.js +24 -6
- package/esm/modules/table/table.d.ts +6 -0
- package/esm/modules/table/table.js +18 -26
- package/esm/plugins/all.d.ts +1 -0
- package/esm/plugins/all.js +1 -0
- package/esm/plugins/backspace/cases/check-join-neighbors.js +90 -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.d.ts +4 -1
- package/esm/plugins/image-processor/image-processor.js +15 -4
- package/esm/plugins/image-properties/readers/align.d.ts +2 -2
- package/esm/plugins/index.d.ts +1 -0
- package/esm/plugins/inline-popup/config/items/iframe.d.ts +9 -1
- package/esm/plugins/inline-popup/config/items/iframe.js +15 -0
- package/esm/plugins/inline-popup/inline-popup.d.ts +19 -0
- package/esm/plugins/inline-popup/inline-popup.js +70 -1
- package/esm/plugins/media/media.js +16 -7
- 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/config.d.ts +5 -3
- package/esm/plugins/resizer/config.js +8 -2
- package/esm/plugins/resizer/resizer.d.ts +20 -0
- package/esm/plugins/resizer/resizer.js +140 -17
- 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/esm/plugins/video/config.d.ts +6 -0
- package/esm/plugins/video/config.js +77 -65
- package/esm/plugins/video-properties/interface.d.ts +31 -0
- package/esm/plugins/video-properties/interface.js +6 -0
- package/esm/plugins/video-properties/readers.d.ts +26 -0
- package/esm/plugins/video-properties/readers.js +65 -0
- package/esm/plugins/video-properties/replace.d.ts +15 -0
- package/esm/plugins/video-properties/replace.js +97 -0
- package/esm/plugins/video-properties/ui/ui-video-form.d.ts +41 -0
- package/esm/plugins/video-properties/ui/ui-video-form.js +228 -0
- package/esm/plugins/video-properties/video-properties.d.ts +37 -0
- package/esm/plugins/video-properties/video-properties.js +175 -0
- package/esm/plugins/video-properties/writers.d.ts +15 -0
- package/esm/plugins/video-properties/writers.js +73 -0
- package/esm/types/types.d.ts +1 -1
- package/package.json +1 -1
- package/types/config.d.ts +28 -26
- package/types/core/helpers/html/word-lists.d.ts +29 -0
- package/types/core/helpers/utils/align.d.ts +1 -1
- 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 +10 -0
- package/types/langs/az.d.ts +10 -0
- package/types/langs/cs_cz.d.ts +10 -0
- package/types/langs/de.d.ts +10 -0
- package/types/langs/es.d.ts +10 -0
- package/types/langs/fa.d.ts +10 -0
- package/types/langs/fi.d.ts +10 -0
- package/types/langs/fr.d.ts +10 -0
- package/types/langs/he.d.ts +10 -0
- package/types/langs/hu.d.ts +10 -0
- package/types/langs/id.d.ts +10 -0
- package/types/langs/it.d.ts +10 -0
- package/types/langs/ja.d.ts +10 -0
- package/types/langs/ko.d.ts +10 -0
- package/types/langs/mn.d.ts +10 -0
- package/types/langs/nl.d.ts +10 -0
- package/types/langs/no.d.ts +10 -0
- package/types/langs/pl.d.ts +10 -0
- package/types/langs/pt_br.d.ts +10 -0
- package/types/langs/ru.d.ts +10 -0
- package/types/langs/sk.d.ts +10 -0
- package/types/langs/sv.d.ts +10 -0
- package/types/langs/tr.d.ts +10 -0
- package/types/langs/ua.d.ts +10 -0
- package/types/langs/zh_cn.d.ts +10 -0
- package/types/langs/zh_tw.d.ts +10 -0
- package/types/modules/dialog/dialog.d.ts +7 -0
- package/types/modules/table/table.d.ts +6 -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-processor/image-processor.d.ts +4 -1
- package/types/plugins/image-properties/readers/align.d.ts +2 -2
- package/types/plugins/index.d.ts +1 -0
- package/types/plugins/inline-popup/config/items/iframe.d.ts +9 -1
- 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/config.d.ts +5 -3
- package/types/plugins/resizer/resizer.d.ts +20 -0
- package/types/plugins/select-cells/select-cells.d.ts +23 -0
- package/types/plugins/video/config.d.ts +6 -0
- package/types/plugins/video-properties/interface.d.ts +31 -0
- package/types/plugins/video-properties/readers.d.ts +26 -0
- package/types/plugins/video-properties/replace.d.ts +15 -0
- package/types/plugins/video-properties/ui/ui-video-form.d.ts +41 -0
- package/types/plugins/video-properties/video-properties.d.ts +37 -0
- package/types/plugins/video-properties/writers.d.ts +15 -0
- package/types/types/types.d.ts +1 -1
|
@@ -17,10 +17,13 @@ import * as consts from "../../core/constants.js";
|
|
|
17
17
|
import { IS_ES_NEXT, IS_IE, KEY_ALT } from "../../core/constants.js";
|
|
18
18
|
import { autobind, watch } from "../../core/decorators/index.js";
|
|
19
19
|
import { Dom } from "../../core/dom/dom.js";
|
|
20
|
-
import { eventEmitter, pluginSystem } from "../../core/global.js";
|
|
21
|
-
import { $$, attr, css, dataBind, innerWidth, markOwner, offset } from "../../core/helpers/index.js";
|
|
20
|
+
import { eventEmitter, getContainer, pluginSystem } from "../../core/global.js";
|
|
21
|
+
import { $$, attr, css, dataBind, getWrappedMedia, innerWidth, markOwner, offset } from "../../core/helpers/index.js";
|
|
22
22
|
import { cssInline } from "../../core/helpers/utils/css.js";
|
|
23
23
|
import { Plugin } from "../../core/plugin/plugin.js";
|
|
24
|
+
import { isMoved } from "../../core/selection/helpers/index.js";
|
|
25
|
+
import { UIElement } from "../../core/ui/index.js";
|
|
26
|
+
import { Popup } from "../../core/ui/popup/index.js";
|
|
24
27
|
import "./config.js";
|
|
25
28
|
const keyBInd = '__jodit-resizer_binded';
|
|
26
29
|
/**
|
|
@@ -36,6 +39,26 @@ function attrPixelSize(element, key) {
|
|
|
36
39
|
}
|
|
37
40
|
return parseFloat(value);
|
|
38
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* A video with no height of its own takes it from its width and its ratio,
|
|
44
|
+
* so resizing it keeps the ratio without setting a height.
|
|
45
|
+
*/
|
|
46
|
+
function heightFollowsWidth(element) {
|
|
47
|
+
return (Dom.isTag(element, 'video') &&
|
|
48
|
+
!attr(element, 'height') &&
|
|
49
|
+
!cssInline(element, 'height'));
|
|
50
|
+
}
|
|
51
|
+
const IFRAME_WRAPPER = '[data-jodit_iframe_wrapper]';
|
|
52
|
+
/**
|
|
53
|
+
* A click on an embed lands on its wrapper, so it selects the embed, until the
|
|
54
|
+
* wrapper is active. While the editor is locked, as during resizing, the
|
|
55
|
+
* wrapper takes the mouse again.
|
|
56
|
+
*/
|
|
57
|
+
const EMBED_WRAPPER_STYLE = `${IFRAME_WRAPPER}{position:relative;display:block;user-select:none}` +
|
|
58
|
+
`${IFRAME_WRAPPER} iframe{position:relative}` +
|
|
59
|
+
`${IFRAME_WRAPPER}::after{position:absolute;z-index:1;display:block;background:transparent;content:'';cursor:pointer;inset:0}` +
|
|
60
|
+
`${IFRAME_WRAPPER}[data-jodit-wrapper_active=true] iframe{z-index:2}` +
|
|
61
|
+
`.jodit_lock ${IFRAME_WRAPPER}[data-jodit-wrapper_active=true] iframe{z-index:1}`;
|
|
39
62
|
/**
|
|
40
63
|
* The module creates a supporting frame for resizing of the elements img and table
|
|
41
64
|
*/
|
|
@@ -58,9 +81,13 @@ export class resizer extends Plugin {
|
|
|
58
81
|
<div class="jodit-resizer__bottom-left"></div>
|
|
59
82
|
<span>100x100</span>
|
|
60
83
|
</div>`);
|
|
84
|
+
// Clips the frame to the workplace, without the frame making it scroll
|
|
85
|
+
this.layer = this.j.c.div('jodit-resizer-layer');
|
|
61
86
|
this.sizeViewer = this.rect.getElementsByTagName('span')[0];
|
|
62
87
|
this.pointerX = 0;
|
|
63
88
|
this.pointerY = 0;
|
|
89
|
+
this.__keyDownRange = null;
|
|
90
|
+
this.__keyDownTable = null;
|
|
64
91
|
this.isAltMode = false;
|
|
65
92
|
this.onClickElement = (element) => {
|
|
66
93
|
if (this.isResizeMode) {
|
|
@@ -72,6 +99,10 @@ export class resizer extends Plugin {
|
|
|
72
99
|
if (Dom.isTag(this.element, 'img') && !this.element.complete) {
|
|
73
100
|
this.j.e.one(this.element, 'load', this.updateSize);
|
|
74
101
|
}
|
|
102
|
+
if (Dom.isTag(this.element, 'video') &&
|
|
103
|
+
this.element.readyState < HTMLMediaElement.HAVE_METADATA) {
|
|
104
|
+
this.j.e.one(this.element, 'loadedmetadata', this.updateSize);
|
|
105
|
+
}
|
|
75
106
|
}
|
|
76
107
|
};
|
|
77
108
|
this.updateSize = () => {
|
|
@@ -108,6 +139,9 @@ export class resizer extends Plugin {
|
|
|
108
139
|
}
|
|
109
140
|
/** @override */
|
|
110
141
|
afterInit(editor) {
|
|
142
|
+
// It goes in the editing document, so iframe mode has it whatever `iframeStyle` holds
|
|
143
|
+
getContainer(editor, 'resizer', 'style', true).textContent =
|
|
144
|
+
EMBED_WRAPPER_STYLE;
|
|
111
145
|
$$('div', this.rect).forEach((resizeHandle) => {
|
|
112
146
|
editor.e.on(resizeHandle, 'mousedown.resizer touchstart.resizer', this.onStartResizing.bind(this, resizeHandle));
|
|
113
147
|
});
|
|
@@ -119,6 +153,9 @@ export class resizer extends Plugin {
|
|
|
119
153
|
}
|
|
120
154
|
})
|
|
121
155
|
.on('afterInit changePlace', this.addEventListeners.bind(this))
|
|
156
|
+
// Handlers without a namespace run first, ahead of those that
|
|
157
|
+
// move the caret, as table-keyboard-navigation's do
|
|
158
|
+
.on('keydown', this.onEditorKeyDown, { top: true })
|
|
122
159
|
.on('afterGetValueFromEditor.resizer', (data) => {
|
|
123
160
|
const rgx = /<jodit[^>]+data-jodit_iframe_wrapper[^>]+>(.*?<iframe[^>]*>.*?<\/iframe>.*?)<\/jodit>/gi;
|
|
124
161
|
if (rgx.test(data.value)) {
|
|
@@ -135,14 +172,33 @@ export class resizer extends Plugin {
|
|
|
135
172
|
let node = e.target;
|
|
136
173
|
const { editor, options: { allowResizeTags } } = this.j;
|
|
137
174
|
while (node && node !== editor) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
this.
|
|
175
|
+
const element = this.__resizable(node);
|
|
176
|
+
if (Dom.isTag(element, allowResizeTags)) {
|
|
177
|
+
this.__bind(element);
|
|
178
|
+
this.onClickElement(element);
|
|
141
179
|
return;
|
|
142
180
|
}
|
|
143
181
|
node = node.parentNode;
|
|
144
182
|
}
|
|
145
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* What a click on `node` resizes: the media in it when it's a media
|
|
186
|
+
* wrapper (`jodit-media`, or one from `mediaWrappers`), or `node` itself
|
|
187
|
+
*/
|
|
188
|
+
__resizable(node) {
|
|
189
|
+
var _a;
|
|
190
|
+
const media = (_a = getWrappedMedia(this.j, node)) !== null && _a !== void 0 ? _a : (Dom.isHTMLElement(node) && attr(node, 'data-jodit_fake_wrapper')
|
|
191
|
+
? node.firstElementChild
|
|
192
|
+
: null);
|
|
193
|
+
if (!media) {
|
|
194
|
+
return node;
|
|
195
|
+
}
|
|
196
|
+
// An embed is resized through its own wrapper
|
|
197
|
+
return Dom.isHTMLElement(media.parentNode) &&
|
|
198
|
+
attr(media.parentNode, 'data-jodit_iframe_wrapper')
|
|
199
|
+
? media.parentNode
|
|
200
|
+
: media;
|
|
201
|
+
}
|
|
146
202
|
__afterInsertImage(image) {
|
|
147
203
|
if (this.j.o.resizer.forImageChangeAttributes) {
|
|
148
204
|
return;
|
|
@@ -169,17 +225,15 @@ export class resizer extends Plugin {
|
|
|
169
225
|
})
|
|
170
226
|
.on(editor.ow, 'resize.resizer', this.updateSize)
|
|
171
227
|
.on('resize.resizer', this.updateSize)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
})
|
|
228
|
+
// The frame is outside the content, so it's moved to follow the
|
|
229
|
+
// element as the content scrolls
|
|
230
|
+
.on([editor.ow, editor.editor], 'scroll.resizer', this.updateSize)
|
|
177
231
|
.on(editor.ow, 'keydown.resizer', this.onKeyDown)
|
|
178
232
|
.on(editor.ow, 'keyup.resizer', this.onKeyUp)
|
|
179
233
|
.on(editor.ow, 'mouseup.resizer touchend.resizer', this.onClickOutside);
|
|
180
234
|
}
|
|
181
235
|
onStartResizing(resizeHandle, e) {
|
|
182
|
-
if (!this.element || !this.
|
|
236
|
+
if (!this.element || !this.isElementInEditor) {
|
|
183
237
|
this.hide();
|
|
184
238
|
return false;
|
|
185
239
|
}
|
|
@@ -233,8 +287,9 @@ export class resizer extends Plugin {
|
|
|
233
287
|
const className = this.handle.className;
|
|
234
288
|
let new_w, new_h;
|
|
235
289
|
const uar = this.j.o.resizer.useAspectRatio;
|
|
236
|
-
|
|
237
|
-
(uar === true || (uar && Dom.isTag(this.element, uar)))
|
|
290
|
+
const keepRatio = !this.isAltMode &&
|
|
291
|
+
(uar === true || Boolean(uar && Dom.isTag(this.element, uar)));
|
|
292
|
+
if (keepRatio) {
|
|
238
293
|
if (diff_x) {
|
|
239
294
|
new_w =
|
|
240
295
|
this.width +
|
|
@@ -266,7 +321,8 @@ export class resizer extends Plugin {
|
|
|
266
321
|
this.applySize(this.element, 'width', '100%');
|
|
267
322
|
}
|
|
268
323
|
}
|
|
269
|
-
if (new_h > this.j.o.resizer.min_height
|
|
324
|
+
if (new_h > this.j.o.resizer.min_height &&
|
|
325
|
+
!(keepRatio && heightFollowsWidth(this.element))) {
|
|
270
326
|
this.applySize(this.element, 'height', new_h);
|
|
271
327
|
}
|
|
272
328
|
this.updateSize();
|
|
@@ -274,6 +330,43 @@ export class resizer extends Plugin {
|
|
|
274
330
|
e.stopImmediatePropagation();
|
|
275
331
|
}
|
|
276
332
|
}
|
|
333
|
+
onEditorKeyDown(event) {
|
|
334
|
+
// A key held down moves the caret on every repeat, with one keyup
|
|
335
|
+
if (event === null || event === void 0 ? void 0 : event.repeat) {
|
|
336
|
+
this.__followCaret();
|
|
337
|
+
}
|
|
338
|
+
this.__keyDownRange = this.j.s.range.cloneRange();
|
|
339
|
+
this.__keyDownTable = this.__caretTable();
|
|
340
|
+
}
|
|
341
|
+
__caretTable() {
|
|
342
|
+
return Dom.closest(this.j.s.range.startContainer, 'table', this.j.editor);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Hide the frame once a key has moved the caret off its element, and
|
|
346
|
+
* frame a table the caret has moved into, as clicks do
|
|
347
|
+
*/
|
|
348
|
+
onEditorKeyUp() {
|
|
349
|
+
this.__followCaret();
|
|
350
|
+
}
|
|
351
|
+
__followCaret() {
|
|
352
|
+
const before = this.__keyDownRange;
|
|
353
|
+
this.__keyDownRange = null;
|
|
354
|
+
if (!isMoved(this.j, before)) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (this.isShown &&
|
|
358
|
+
this.element &&
|
|
359
|
+
!this.j.s.range.intersectsNode(this.element)) {
|
|
360
|
+
this.hide();
|
|
361
|
+
}
|
|
362
|
+
const table = this.__caretTable();
|
|
363
|
+
if (table &&
|
|
364
|
+
table !== this.__keyDownTable &&
|
|
365
|
+
this.j.o.allowResizeTags.has('table')) {
|
|
366
|
+
this.__bind(table);
|
|
367
|
+
this.onClickElement(table);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
277
370
|
onKeyDown(e) {
|
|
278
371
|
this.isAltMode = e.key === KEY_ALT;
|
|
279
372
|
if (!this.isAltMode && this.isResizeMode) {
|
|
@@ -295,6 +388,12 @@ export class resizer extends Plugin {
|
|
|
295
388
|
return;
|
|
296
389
|
}
|
|
297
390
|
if (!this.isResizeMode) {
|
|
391
|
+
// A click in the element's popup, or in a list it opens, works on
|
|
392
|
+
// the element, so it keeps its frame
|
|
393
|
+
if ((e === null || e === void 0 ? void 0 : e.target) &&
|
|
394
|
+
UIElement.closestElement(e.target, Popup)) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
298
397
|
return this.hide();
|
|
299
398
|
}
|
|
300
399
|
e.stopImmediatePropagation();
|
|
@@ -312,10 +411,20 @@ export class resizer extends Plugin {
|
|
|
312
411
|
css(element, key, value);
|
|
313
412
|
}
|
|
314
413
|
}
|
|
414
|
+
/**
|
|
415
|
+
* The framed element can go with a wrapper round it, keeping its parent
|
|
416
|
+
*/
|
|
417
|
+
get isElementInEditor() {
|
|
418
|
+
return Boolean(this.element && this.j.editor.contains(this.element));
|
|
419
|
+
}
|
|
315
420
|
onDelete(e) {
|
|
316
421
|
if (!this.element) {
|
|
317
422
|
return;
|
|
318
423
|
}
|
|
424
|
+
if (!this.isElementInEditor) {
|
|
425
|
+
this.hide();
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
319
428
|
if (this.element.tagName !== 'JODIT') {
|
|
320
429
|
this.j.s.select(this.element);
|
|
321
430
|
}
|
|
@@ -327,7 +436,7 @@ export class resizer extends Plugin {
|
|
|
327
436
|
}
|
|
328
437
|
__onChangeEditor() {
|
|
329
438
|
if (this.isShown) {
|
|
330
|
-
if (!this.
|
|
439
|
+
if (!this.isElementInEditor) {
|
|
331
440
|
this.hide();
|
|
332
441
|
}
|
|
333
442
|
else {
|
|
@@ -439,9 +548,13 @@ export class resizer extends Plugin {
|
|
|
439
548
|
return;
|
|
440
549
|
}
|
|
441
550
|
this.isShown = true;
|
|
551
|
+
if (this.layer.parentNode !== this.j.workplace) {
|
|
552
|
+
markOwner(this.j, this.layer);
|
|
553
|
+
Dom.append(this.j.workplace, this.layer);
|
|
554
|
+
}
|
|
442
555
|
if (!this.rect.parentNode) {
|
|
443
556
|
markOwner(this.j, this.rect);
|
|
444
|
-
Dom.append(this.
|
|
557
|
+
Dom.append(this.layer, this.rect);
|
|
445
558
|
}
|
|
446
559
|
if (this.j.isFullSize) {
|
|
447
560
|
css(this.rect, 'zIndex', css(this.j.container, 'zIndex').toString());
|
|
@@ -462,8 +575,12 @@ export class resizer extends Plugin {
|
|
|
462
575
|
}
|
|
463
576
|
beforeDestruct(jodit) {
|
|
464
577
|
this.hide();
|
|
578
|
+
Dom.safeRemove(this.layer);
|
|
465
579
|
eventEmitter.off('hideHelpers', this.hide);
|
|
466
|
-
jodit.e
|
|
580
|
+
jodit.e
|
|
581
|
+
.off(this.j.ow, '.resizer')
|
|
582
|
+
.off('.resizer')
|
|
583
|
+
.off('keydown', this.onEditorKeyDown);
|
|
467
584
|
}
|
|
468
585
|
}
|
|
469
586
|
__decorate([
|
|
@@ -481,6 +598,12 @@ __decorate([
|
|
|
481
598
|
__decorate([
|
|
482
599
|
autobind
|
|
483
600
|
], resizer.prototype, "onResize", null);
|
|
601
|
+
__decorate([
|
|
602
|
+
autobind
|
|
603
|
+
], resizer.prototype, "onEditorKeyDown", null);
|
|
604
|
+
__decorate([
|
|
605
|
+
watch(':keyup')
|
|
606
|
+
], resizer.prototype, "onEditorKeyUp", null);
|
|
484
607
|
__decorate([
|
|
485
608
|
autobind
|
|
486
609
|
], resizer.prototype, "onKeyDown", null);
|
|
@@ -18,6 +18,29 @@ export declare class selectCells extends Plugin {
|
|
|
18
18
|
*/
|
|
19
19
|
private get __tableModule();
|
|
20
20
|
protected afterInit(jodit: IJodit): void;
|
|
21
|
+
/**
|
|
22
|
+
* The cell with the caret, and the selection, when a key went down
|
|
23
|
+
*/
|
|
24
|
+
private __keyDownCell;
|
|
25
|
+
private __keyDownRange;
|
|
26
|
+
private __onKeyDown;
|
|
27
|
+
/**
|
|
28
|
+
* A link's popup replaces the cell's while the caret is in the link
|
|
29
|
+
*/
|
|
30
|
+
private __keyDownInLink;
|
|
31
|
+
private __isInLink;
|
|
32
|
+
/**
|
|
33
|
+
* Where the selection starts rather than `s.current()`, which finds the
|
|
34
|
+
* first cell when the caret is just before the table
|
|
35
|
+
*/
|
|
36
|
+
private __caretCell;
|
|
37
|
+
/**
|
|
38
|
+
* A key that moves the caret into a cell, from another cell or from
|
|
39
|
+
* outside the table, marks that cell and opens its popup, as a click on
|
|
40
|
+
* it does. One that moves the caret out of the table unmarks the cells
|
|
41
|
+
*/
|
|
42
|
+
protected onKeyUp(): void;
|
|
43
|
+
private __followCaret;
|
|
21
44
|
/**
|
|
22
45
|
* First selected cell
|
|
23
46
|
*/
|
|
@@ -19,6 +19,7 @@ import { Dom } from "../../core/dom/dom.js";
|
|
|
19
19
|
import { pluginSystem } from "../../core/global.js";
|
|
20
20
|
import { $$, alignElement, position, toArray } from "../../core/helpers/index.js";
|
|
21
21
|
import { Plugin } from "../../core/plugin/index.js";
|
|
22
|
+
import { isMoved } from "../../core/selection/helpers/index.js";
|
|
22
23
|
import { Table } from "../../modules/table/table.js";
|
|
23
24
|
import "./config.js";
|
|
24
25
|
const key = 'table_processor_observer';
|
|
@@ -26,6 +27,15 @@ const MOUSE_MOVE_LABEL = 'onMoveTableSelectCell';
|
|
|
26
27
|
export class selectCells extends Plugin {
|
|
27
28
|
constructor() {
|
|
28
29
|
super(...arguments);
|
|
30
|
+
/**
|
|
31
|
+
* The cell with the caret, and the selection, when a key went down
|
|
32
|
+
*/
|
|
33
|
+
this.__keyDownCell = null;
|
|
34
|
+
this.__keyDownRange = null;
|
|
35
|
+
/**
|
|
36
|
+
* A link's popup replaces the cell's while the caret is in the link
|
|
37
|
+
*/
|
|
38
|
+
this.__keyDownInLink = false;
|
|
29
39
|
/**
|
|
30
40
|
* First selected cell
|
|
31
41
|
*/
|
|
@@ -46,6 +56,9 @@ export class selectCells extends Plugin {
|
|
|
46
56
|
return;
|
|
47
57
|
}
|
|
48
58
|
jodit.e
|
|
59
|
+
// Handlers without a namespace run first, ahead of those that
|
|
60
|
+
// move the caret, as table-keyboard-navigation's do
|
|
61
|
+
.on('keydown', this.__onKeyDown, { top: true })
|
|
49
62
|
.on('keydown.select-cells', (event) => {
|
|
50
63
|
if (event.key === KEY_TAB) {
|
|
51
64
|
this.unselectCells();
|
|
@@ -76,6 +89,61 @@ export class selectCells extends Plugin {
|
|
|
76
89
|
}
|
|
77
90
|
});
|
|
78
91
|
}
|
|
92
|
+
__onKeyDown(event) {
|
|
93
|
+
// A key held down moves the caret on every repeat, with one keyup
|
|
94
|
+
if (event === null || event === void 0 ? void 0 : event.repeat) {
|
|
95
|
+
this.__followCaret();
|
|
96
|
+
}
|
|
97
|
+
this.__keyDownCell = this.__caretCell();
|
|
98
|
+
this.__keyDownRange = this.j.s.range.cloneRange();
|
|
99
|
+
this.__keyDownInLink = this.__isInLink();
|
|
100
|
+
}
|
|
101
|
+
__isInLink() {
|
|
102
|
+
return Boolean(Dom.closest(this.j.s.range.startContainer, 'a', this.j.editor));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Where the selection starts rather than `s.current()`, which finds the
|
|
106
|
+
* first cell when the caret is just before the table
|
|
107
|
+
*/
|
|
108
|
+
__caretCell() {
|
|
109
|
+
return Dom.closest(this.j.s.range.startContainer, Dom.isCell, this.j.editor);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* A key that moves the caret into a cell, from another cell or from
|
|
113
|
+
* outside the table, marks that cell and opens its popup, as a click on
|
|
114
|
+
* it does. One that moves the caret out of the table unmarks the cells
|
|
115
|
+
*/
|
|
116
|
+
onKeyUp() {
|
|
117
|
+
this.__followCaret();
|
|
118
|
+
}
|
|
119
|
+
__followCaret() {
|
|
120
|
+
const before = this.__keyDownRange;
|
|
121
|
+
this.__keyDownRange = null;
|
|
122
|
+
if (this.j.o.readonly || !isMoved(this.j, before)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const cell = this.__caretCell();
|
|
126
|
+
const hasLeftLink = this.__keyDownInLink && !this.__isInLink();
|
|
127
|
+
if (cell === this.__keyDownCell && !(cell && hasLeftLink)) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const hadMarked = this.__tableModule.getAllSelectedCells().length > 0;
|
|
131
|
+
this.unselectCells();
|
|
132
|
+
if (!cell) {
|
|
133
|
+
if (hadMarked) {
|
|
134
|
+
this.j.e.fire('hidePopup', 'cells');
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const table = Dom.closest(cell, 'table', this.j.editor);
|
|
139
|
+
if (!table) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// As after a click, the first change to the cell keeps the mark
|
|
143
|
+
this.__selectedCell = cell;
|
|
144
|
+
this.__tableModule.addSelection(cell);
|
|
145
|
+
this.j.e.fire('showPopup', table, () => position(cell, this.j), 'cells');
|
|
146
|
+
}
|
|
79
147
|
/**
|
|
80
148
|
* Mouse click inside the table
|
|
81
149
|
*/
|
|
@@ -418,10 +486,16 @@ export class selectCells extends Plugin {
|
|
|
418
486
|
/** @override */
|
|
419
487
|
beforeDestruct(jodit) {
|
|
420
488
|
this.__onRemoveSelection();
|
|
421
|
-
jodit.e.off('.select-cells');
|
|
489
|
+
jodit.e.off('.select-cells').off('keydown', this.__onKeyDown);
|
|
422
490
|
}
|
|
423
491
|
}
|
|
424
492
|
selectCells.requires = ['select'];
|
|
493
|
+
__decorate([
|
|
494
|
+
autobind
|
|
495
|
+
], selectCells.prototype, "__onKeyDown", null);
|
|
496
|
+
__decorate([
|
|
497
|
+
watch(':keyup')
|
|
498
|
+
], selectCells.prototype, "onKeyUp", null);
|
|
425
499
|
__decorate([
|
|
426
500
|
autobind
|
|
427
501
|
], selectCells.prototype, "onStartSelection", null);
|
|
@@ -36,7 +36,9 @@ export function tableKeyboardNavigation(editor) {
|
|
|
36
36
|
case consts.KEY_TAB:
|
|
37
37
|
case consts.KEY_LEFT: {
|
|
38
38
|
next = getNextCell();
|
|
39
|
-
|
|
39
|
+
// Left in the first cell leaves the table, as Up in the
|
|
40
|
+
// top row does
|
|
41
|
+
if (!next && key === consts.KEY_TAB) {
|
|
40
42
|
tableModule.appendRow(table, !isPrev
|
|
41
43
|
? false
|
|
42
44
|
: Dom.first(table, node => Dom.isTag(node, 'tr')), !isPrev);
|
|
@@ -65,7 +67,6 @@ export function tableKeyboardNavigation(editor) {
|
|
|
65
67
|
if (!next) {
|
|
66
68
|
return;
|
|
67
69
|
}
|
|
68
|
-
editor.e.fire('hidePopup hideResizer');
|
|
69
70
|
if (!next.firstChild) {
|
|
70
71
|
const first = editor.createInside.element('br');
|
|
71
72
|
Dom.append(next, first);
|
|
@@ -53,3 +53,9 @@ declare module 'jodit/config' {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* The video popup's tabs: Upload, when the uploader is configured, then Link
|
|
58
|
+
* and Code. `insert` runs what a tab inserts, which by default goes in at the
|
|
59
|
+
* selection the popup was opened with.
|
|
60
|
+
*/
|
|
61
|
+
export declare function videoTabs(jodit: IJodit, close: () => void, insert?: (run: () => void) => void): HTMLElement;
|
|
@@ -26,73 +26,85 @@ Config.prototype.video = {
|
|
|
26
26
|
defaultHandlerSuccess: insertVideos
|
|
27
27
|
};
|
|
28
28
|
Icon.set('video', videoIcon);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
new
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
29
|
+
/**
|
|
30
|
+
* The video popup's tabs: Upload, when the uploader is configured, then Link
|
|
31
|
+
* and Code. `insert` runs what a tab inserts, which by default goes in at the
|
|
32
|
+
* selection the popup was opened with.
|
|
33
|
+
*/
|
|
34
|
+
export function videoTabs(jodit, close, insert) {
|
|
35
|
+
const run = insert !== null && insert !== void 0 ? insert : ((fn) => {
|
|
36
|
+
jodit.s.restore();
|
|
37
|
+
fn();
|
|
38
|
+
});
|
|
39
|
+
const formLink = new UIForm(jodit, [
|
|
40
|
+
new UIBlock(jodit, [
|
|
41
|
+
new UIInput(jodit, {
|
|
42
|
+
name: 'url',
|
|
43
|
+
required: true,
|
|
44
|
+
label: 'URL',
|
|
45
|
+
placeholder: 'https://',
|
|
46
|
+
validators: ['url']
|
|
47
|
+
})
|
|
48
|
+
]),
|
|
49
|
+
new UIBlock(jodit, [
|
|
50
|
+
Button(jodit, '', 'Insert', 'primary').onAction(() => formLink.submit())
|
|
51
|
+
])
|
|
52
|
+
]), formCode = new UIForm(jodit, [
|
|
53
|
+
new UIBlock(jodit, [
|
|
54
|
+
new UITextArea(jodit, {
|
|
55
|
+
name: 'code',
|
|
56
|
+
required: true,
|
|
57
|
+
label: 'Embed code'
|
|
58
|
+
})
|
|
59
|
+
]),
|
|
60
|
+
new UIBlock(jodit, [
|
|
61
|
+
Button(jodit, '', 'Insert', 'primary').onAction(() => formCode.submit())
|
|
62
|
+
])
|
|
63
|
+
]), tabs = [], insertCode = (code) => {
|
|
64
|
+
run(() => jodit.s.insertHTML(prepareEmbedCode(jodit, code)));
|
|
65
|
+
close();
|
|
66
|
+
};
|
|
67
|
+
if (!insert) {
|
|
60
68
|
jodit.s.save();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
}
|
|
70
|
+
const { uploader } = jodit.o;
|
|
71
|
+
// Base64 alone would put whole video files into the content
|
|
72
|
+
if (uploader.showTabInFileSelector !== false &&
|
|
73
|
+
(uploader.url || uploader.customUploadFunction)) {
|
|
74
|
+
tabs.push(UploadTab(jodit, data => {
|
|
75
|
+
run(() => {
|
|
66
76
|
var _a, _b;
|
|
67
|
-
jodit.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
77
|
+
return ((_b = (_a = jodit.o.video) === null || _a === void 0 ? void 0 : _a.defaultHandlerSuccess) !== null && _b !== void 0 ? _b : insertVideos).call(jodit, data);
|
|
78
|
+
});
|
|
79
|
+
}, { label: 'Drop file', accept: 'video/*' }));
|
|
80
|
+
}
|
|
81
|
+
tabs.push({
|
|
82
|
+
icon: 'link',
|
|
83
|
+
name: 'Link',
|
|
84
|
+
content: formLink.container
|
|
85
|
+
}, {
|
|
86
|
+
icon: 'source',
|
|
87
|
+
name: 'Code',
|
|
88
|
+
content: formCode.container
|
|
89
|
+
});
|
|
90
|
+
formLink.onSubmit(data => {
|
|
91
|
+
var _a, _b, _c, _d;
|
|
92
|
+
insertCode(call((_b = (_a = jodit.o.video) === null || _a === void 0 ? void 0 : _a.parseUrlToVideoEmbed) !== null && _b !== void 0 ? _b : convertMediaUrlToVideoEmbed, data.url, {
|
|
93
|
+
width: (_c = jodit.o.video) === null || _c === void 0 ? void 0 : _c.defaultWidth,
|
|
94
|
+
height: (_d = jodit.o.video) === null || _d === void 0 ? void 0 : _d.defaultHeight
|
|
95
|
+
}));
|
|
96
|
+
});
|
|
97
|
+
formCode.onSubmit(data => {
|
|
98
|
+
insertCode(data.code);
|
|
99
|
+
});
|
|
100
|
+
const box = TabsWidget(jodit, tabs);
|
|
101
|
+
// Its tabs are sized to their labels, as the file selector's are, since
|
|
102
|
+
// "Upload" doesn't fit a third of the popup
|
|
103
|
+
box.classList.add('jodit-file-selector');
|
|
104
|
+
return box;
|
|
105
|
+
}
|
|
106
|
+
Config.prototype.controls.video = {
|
|
107
|
+
popup: (jodit, current, close) => videoTabs(jodit, close),
|
|
96
108
|
tags: ['iframe'],
|
|
97
109
|
tooltip: 'Insert youtube/vimeo video'
|
|
98
110
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
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/video-properties
|
|
8
|
+
*/
|
|
9
|
+
export type EditedMedia = HTMLVideoElement | HTMLAudioElement | HTMLIFrameElement;
|
|
10
|
+
export interface VideoPropertiesValues {
|
|
11
|
+
width: number | string;
|
|
12
|
+
height: number | string;
|
|
13
|
+
poster: string;
|
|
14
|
+
autoplay: boolean;
|
|
15
|
+
loop: boolean;
|
|
16
|
+
muted: boolean;
|
|
17
|
+
controls: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface VideoPropertiesState {
|
|
20
|
+
/**
|
|
21
|
+
* What the dialog was opened for: the media, or a wrapper round it
|
|
22
|
+
*/
|
|
23
|
+
target: HTMLElement;
|
|
24
|
+
media: EditedMedia;
|
|
25
|
+
ratio: number;
|
|
26
|
+
sizeIsLocked: boolean;
|
|
27
|
+
values: VideoPropertiesValues;
|
|
28
|
+
}
|
|
29
|
+
export interface VideoPropertiesAPI {
|
|
30
|
+
openPosterPopup: (target: HTMLElement) => void;
|
|
31
|
+
}
|