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
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
import type { Nullable } from "../../types/index";
|
|
10
|
+
import type { EditedMedia, VideoPropertiesState } from "./interface";
|
|
11
|
+
/**
|
|
12
|
+
* The media `target` is, or holds as its wrapper (`jodit-media`, the resizer's
|
|
13
|
+
* `jodit` for an embed, or one from `mediaWrappers`)
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
export declare function editedMedia(target: HTMLElement): Nullable<EditedMedia>;
|
|
17
|
+
/**
|
|
18
|
+
* The size `media` is given, inline or by its attribute
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
21
|
+
export declare function ownSize(media: EditedMedia, key: 'width' | 'height'): string;
|
|
22
|
+
/**
|
|
23
|
+
* Read the media's values into the state
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
export declare function readValues(state: VideoPropertiesState): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
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 { isNumeric } from "../../core/helpers/checker/is-numeric.js";
|
|
8
|
+
import { attr } from "../../core/helpers/utils/attr.js";
|
|
9
|
+
import { cssInline } from "../../core/helpers/utils/css.js";
|
|
10
|
+
import { normalSizeFromString } from "../image-properties/utils/utils.js";
|
|
11
|
+
const mediaSelector = 'video, audio, iframe';
|
|
12
|
+
/**
|
|
13
|
+
* The media `target` is, or holds as its wrapper (`jodit-media`, the resizer's
|
|
14
|
+
* `jodit` for an embed, or one from `mediaWrappers`)
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
17
|
+
export function editedMedia(target) {
|
|
18
|
+
return (target.matches(mediaSelector)
|
|
19
|
+
? target
|
|
20
|
+
: target.querySelector(mediaSelector));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The size `media` is given, inline or by its attribute
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
export function ownSize(media, key) {
|
|
27
|
+
return cssInline(media, key) || attr(media, key) || '';
|
|
28
|
+
}
|
|
29
|
+
const toNumber = (value) => parseFloat(value.toString());
|
|
30
|
+
/**
|
|
31
|
+
* Read the media's values into the state
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
export function readValues(state) {
|
|
35
|
+
const { media, values } = state;
|
|
36
|
+
const width = ownSize(media, 'width');
|
|
37
|
+
const height = ownSize(media, 'height');
|
|
38
|
+
values.width = width ? normalSizeFromString(width) : media.offsetWidth;
|
|
39
|
+
values.height = height ? normalSizeFromString(height) : '';
|
|
40
|
+
if (Dom.isTag(media, 'video') && media.videoWidth) {
|
|
41
|
+
state.ratio = media.videoWidth / media.videoHeight;
|
|
42
|
+
}
|
|
43
|
+
else if (isNumeric(values.width) && isNumeric(values.height)) {
|
|
44
|
+
state.ratio = toNumber(values.width) / toNumber(values.height);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
state.ratio = media.offsetWidth / media.offsetHeight || 1;
|
|
48
|
+
}
|
|
49
|
+
// One with no height takes it from its width
|
|
50
|
+
if (!height && isNumeric(values.width)) {
|
|
51
|
+
values.height = Math.round(toNumber(values.width) / state.ratio);
|
|
52
|
+
}
|
|
53
|
+
state.sizeIsLocked =
|
|
54
|
+
isNumeric(values.width) &&
|
|
55
|
+
isNumeric(values.height) &&
|
|
56
|
+
(!height ||
|
|
57
|
+
Math.abs(toNumber(values.width) - toNumber(values.height) * state.ratio) < 1);
|
|
58
|
+
values.poster = attr(media, 'poster') || '';
|
|
59
|
+
values.autoplay = media.hasAttribute('autoplay');
|
|
60
|
+
values.loop = media.hasAttribute('loop');
|
|
61
|
+
// Autoplay's own: turning it off gives the sound back
|
|
62
|
+
values.muted = media.hasAttribute('muted') && !values.autoplay;
|
|
63
|
+
// Without Autoplay it keeps its controls, or it could never be played
|
|
64
|
+
values.controls = media.hasAttribute('controls') || !values.autoplay;
|
|
65
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
import type { IJodit } from "../../types/index";
|
|
10
|
+
/**
|
|
11
|
+
* Run `insert`, which inserts media at the cursor, with the cursor after
|
|
12
|
+
* `replaced`, and put what it inserts in place of `replaced`
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
export declare function replaceMedia(j: IJodit, replaced: HTMLElement, insert: () => void): void;
|
|
@@ -0,0 +1,97 @@
|
|
|
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 { css } from "../../core/helpers/utils/css.js";
|
|
9
|
+
import { editedMedia, ownSize, readValues } from "./readers.js";
|
|
10
|
+
import { applyValues } from "./writers.js";
|
|
11
|
+
/**
|
|
12
|
+
* Give `media`, in `outer`, the classes, inline styles, size and playback
|
|
13
|
+
* settings of `old`, in `oldOuter`. It keeps its own source and poster.
|
|
14
|
+
*/
|
|
15
|
+
function takeOver(j, oldOuter, old, outer, media) {
|
|
16
|
+
var _a;
|
|
17
|
+
const state = {
|
|
18
|
+
target: oldOuter,
|
|
19
|
+
media: old,
|
|
20
|
+
ratio: 1,
|
|
21
|
+
sizeIsLocked: true,
|
|
22
|
+
values: {
|
|
23
|
+
width: '',
|
|
24
|
+
height: '',
|
|
25
|
+
poster: '',
|
|
26
|
+
autoplay: false,
|
|
27
|
+
loop: false,
|
|
28
|
+
muted: false,
|
|
29
|
+
controls: true
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
readValues(state);
|
|
33
|
+
const pairs = [[old, media]];
|
|
34
|
+
// A wrapper kept in the content, which holds the alignment
|
|
35
|
+
if (oldOuter !== old &&
|
|
36
|
+
outer !== media &&
|
|
37
|
+
oldOuter.nodeName === outer.nodeName) {
|
|
38
|
+
pairs.push([oldOuter, outer]);
|
|
39
|
+
}
|
|
40
|
+
pairs.forEach(([from, to]) => {
|
|
41
|
+
['class', 'style'].forEach(name => attr(to, name, attr(from, name)));
|
|
42
|
+
});
|
|
43
|
+
// A video's size is CSS and an embed's its attributes, so the writer sizes
|
|
44
|
+
// one that's a different element
|
|
45
|
+
if (old.nodeName !== media.nodeName) {
|
|
46
|
+
css(media, { width: null, height: null });
|
|
47
|
+
if (!((_a = attr(media, 'style')) === null || _a === void 0 ? void 0 : _a.trim())) {
|
|
48
|
+
attr(media, 'style', null);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
state.media = media;
|
|
52
|
+
state.values.poster = attr(media, 'poster') || '';
|
|
53
|
+
applyValues(j, state, Boolean(ownSize(old, 'width') || ownSize(old, 'height')));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run `insert`, which inserts media at the cursor, with the cursor after
|
|
57
|
+
* `replaced`, and put what it inserts in place of `replaced`
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
export function replaceMedia(j, replaced, insert) {
|
|
61
|
+
const inserted = [];
|
|
62
|
+
const collect = (node) => {
|
|
63
|
+
inserted.push(node);
|
|
64
|
+
};
|
|
65
|
+
j.history.snapshot.transaction(() => {
|
|
66
|
+
j.s.focus();
|
|
67
|
+
j.s.setCursorAfter(replaced);
|
|
68
|
+
j.e.on('afterInsertNode', collect);
|
|
69
|
+
try {
|
|
70
|
+
insert();
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
j.e.off('afterInsertNode', collect);
|
|
74
|
+
}
|
|
75
|
+
const [outer] = inserted;
|
|
76
|
+
if (!Dom.isHTMLElement(outer)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const old = editedMedia(replaced);
|
|
80
|
+
const media = editedMedia(outer);
|
|
81
|
+
if (old && media) {
|
|
82
|
+
takeOver(j, replaced, old, outer, media);
|
|
83
|
+
}
|
|
84
|
+
// The resizer can have put an embed in its own wrapper already
|
|
85
|
+
const placed = Dom.isHTMLElement(outer.parentElement) &&
|
|
86
|
+
attr(outer.parentElement, 'data-jodit-temp')
|
|
87
|
+
? outer.parentElement
|
|
88
|
+
: outer;
|
|
89
|
+
// Where the old one was, since media Jodit counts as blocks can be put
|
|
90
|
+
// after the paragraph
|
|
91
|
+
Dom.before(replaced, placed);
|
|
92
|
+
Dom.safeRemove(replaced);
|
|
93
|
+
j.s.setCursorAfter(placed);
|
|
94
|
+
});
|
|
95
|
+
j.synchronizeValues();
|
|
96
|
+
j.e.fire('closeAllPopups');
|
|
97
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
import type { IJodit } from "../../../types/index";
|
|
10
|
+
import { UIElement } from "../../../core/ui/element";
|
|
11
|
+
import type { VideoPropertiesAPI, VideoPropertiesState } from "../interface";
|
|
12
|
+
/** @private */
|
|
13
|
+
export declare class UIVideoPropertiesForm extends UIElement<IJodit> {
|
|
14
|
+
private state;
|
|
15
|
+
private handlers;
|
|
16
|
+
className(): string;
|
|
17
|
+
constructor(jodit: IJodit, state: VideoPropertiesState, handlers: VideoPropertiesAPI);
|
|
18
|
+
protected render(): string;
|
|
19
|
+
private input;
|
|
20
|
+
private show;
|
|
21
|
+
/**
|
|
22
|
+
* A video has every field, an embed only its size, and audio only its
|
|
23
|
+
* playback settings
|
|
24
|
+
*/
|
|
25
|
+
protected onStateMediaChange(): void;
|
|
26
|
+
private showPreview;
|
|
27
|
+
protected hideChangePoster(): void;
|
|
28
|
+
protected onStatePosterChange(): void;
|
|
29
|
+
protected onPosterChange(): void;
|
|
30
|
+
protected onChangePosterClick(e: MouseEvent): void;
|
|
31
|
+
protected onRemovePosterClick(): void;
|
|
32
|
+
protected onStateSizeIsLockedChange(): void;
|
|
33
|
+
protected onLockSizeClick(): void;
|
|
34
|
+
protected onStateSizeChange(): void;
|
|
35
|
+
protected onSizeInput(e: Event): void;
|
|
36
|
+
/**
|
|
37
|
+
* Autoplay mutes it, and it keeps its controls unless it autoplays
|
|
38
|
+
*/
|
|
39
|
+
protected onStateFlagsChange(): void;
|
|
40
|
+
protected onFlagChange(e: Event): void;
|
|
41
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
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
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
9
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else
|
|
11
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
12
|
+
if (d = decorators[i])
|
|
13
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
+
};
|
|
16
|
+
import { component } from "../../../core/decorators/component/component.js";
|
|
17
|
+
import { hook } from "../../../core/decorators/hook/hook.js";
|
|
18
|
+
import { watch } from "../../../core/decorators/watch/watch.js";
|
|
19
|
+
import { Dom } from "../../../core/dom/dom.js";
|
|
20
|
+
import { isNumeric } from "../../../core/helpers/checker/is-numeric.js";
|
|
21
|
+
import { attr } from "../../../core/helpers/utils/attr.js";
|
|
22
|
+
import { css } from "../../../core/helpers/utils/css.js";
|
|
23
|
+
import { UIElement } from "../../../core/ui/element.js";
|
|
24
|
+
import { Icon } from "../../../core/ui/icon.js";
|
|
25
|
+
const flags = {
|
|
26
|
+
autoplay: 'Autoplay',
|
|
27
|
+
loop: 'Loop',
|
|
28
|
+
muted: 'Muted',
|
|
29
|
+
controls: 'Controls'
|
|
30
|
+
};
|
|
31
|
+
const checkbox = ([flag, label]) => `<label class="jodit_vertical_middle">
|
|
32
|
+
<input type="checkbox" class="jodit-checkbox &__${flag}"/>
|
|
33
|
+
<span>~${label}~</span>
|
|
34
|
+
</label>`;
|
|
35
|
+
/** @private */
|
|
36
|
+
let UIVideoPropertiesForm = class UIVideoPropertiesForm extends UIElement {
|
|
37
|
+
className() {
|
|
38
|
+
return 'UIVideoPropertiesForm';
|
|
39
|
+
}
|
|
40
|
+
constructor(jodit, state, handlers) {
|
|
41
|
+
super(jodit);
|
|
42
|
+
this.state = state;
|
|
43
|
+
this.handlers = handlers;
|
|
44
|
+
}
|
|
45
|
+
render() {
|
|
46
|
+
return `<form>
|
|
47
|
+
<div class="jodit-form__group &__previewBox">
|
|
48
|
+
<img class="&__preview" alt=""/>
|
|
49
|
+
</div>
|
|
50
|
+
<div class="jodit-form__group &__sizes">
|
|
51
|
+
<input type="text" class="jodit-input &__width" placeholder="~Width~" aria-label="~Width~"/>
|
|
52
|
+
<a class="&__lockSize">*lock*</a>
|
|
53
|
+
<input type="text" class="jodit-input &__height" placeholder="~Height~" aria-label="~Height~"/>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="jodit-form__group &__editPoster">
|
|
56
|
+
<label>~Poster~</label>
|
|
57
|
+
<div class="jodit-input_group">
|
|
58
|
+
<input type="text" class="jodit-input &__poster" placeholder="https://"/>
|
|
59
|
+
<div class="jodit-input_group-buttons">
|
|
60
|
+
<a class="jodit-button &__changePoster" title="~Upload~">*image*</a>
|
|
61
|
+
<a class="jodit-button &__removePoster" title="~Remove~">*bin*</a>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<div class="jodit-form__group &__playback">
|
|
66
|
+
${Object.entries(flags).map(checkbox).join('')}
|
|
67
|
+
</div>
|
|
68
|
+
</form>`;
|
|
69
|
+
}
|
|
70
|
+
input(name) {
|
|
71
|
+
return this.getElm(name);
|
|
72
|
+
}
|
|
73
|
+
show(name, shown) {
|
|
74
|
+
css(this.getElm(name), 'display', shown ? null : 'none');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A video has every field, an embed only its size, and audio only its
|
|
78
|
+
* playback settings
|
|
79
|
+
*/
|
|
80
|
+
onStateMediaChange() {
|
|
81
|
+
const { media } = this.state;
|
|
82
|
+
this.show('editPoster', Dom.isTag(media, 'video'));
|
|
83
|
+
this.show('sizes', !Dom.isTag(media, 'audio'));
|
|
84
|
+
this.show('playback', !Dom.isTag(media, 'iframe'));
|
|
85
|
+
this.showPreview();
|
|
86
|
+
}
|
|
87
|
+
// A video's poster, when it has one
|
|
88
|
+
showPreview() {
|
|
89
|
+
const { media, values } = this.state;
|
|
90
|
+
const shown = Dom.isTag(media, 'video') && Boolean(values.poster);
|
|
91
|
+
this.show('previewBox', shown);
|
|
92
|
+
attr(this.getElm('preview'), 'src', shown ? values.poster : null);
|
|
93
|
+
}
|
|
94
|
+
hideChangePoster() {
|
|
95
|
+
const { uploader, filebrowser } = this.j.o;
|
|
96
|
+
// What FileSelectorWidget offers
|
|
97
|
+
const canUpload = uploader.showTabInFileSelector !== false &&
|
|
98
|
+
Boolean(uploader.url ||
|
|
99
|
+
uploader.insertImageAsBase64URI ||
|
|
100
|
+
uploader.customUploadFunction);
|
|
101
|
+
const canBrowse = Boolean(filebrowser.ajax.url || filebrowser.items.url);
|
|
102
|
+
this.show('changePoster', canUpload || canBrowse);
|
|
103
|
+
}
|
|
104
|
+
onStatePosterChange() {
|
|
105
|
+
const { poster } = this.state.values;
|
|
106
|
+
this.input('poster').value = poster;
|
|
107
|
+
this.show('removePoster', Boolean(poster));
|
|
108
|
+
this.showPreview();
|
|
109
|
+
}
|
|
110
|
+
onPosterChange() {
|
|
111
|
+
this.state.values.poster = this.input('poster').value;
|
|
112
|
+
}
|
|
113
|
+
onChangePosterClick(e) {
|
|
114
|
+
this.handlers.openPosterPopup(this.getElm('changePoster'));
|
|
115
|
+
e.stopPropagation();
|
|
116
|
+
}
|
|
117
|
+
onRemovePosterClick() {
|
|
118
|
+
this.state.values.poster = '';
|
|
119
|
+
}
|
|
120
|
+
onStateSizeIsLockedChange() {
|
|
121
|
+
this.getElm('lockSize').innerHTML = Icon.get(this.state.sizeIsLocked ? 'lock' : 'unlock');
|
|
122
|
+
}
|
|
123
|
+
onLockSizeClick() {
|
|
124
|
+
const { state } = this;
|
|
125
|
+
const { values } = state;
|
|
126
|
+
state.sizeIsLocked = !state.sizeIsLocked;
|
|
127
|
+
if (state.sizeIsLocked && isNumeric(values.width)) {
|
|
128
|
+
values.height = Math.round(parseFloat(values.width.toString()) / state.ratio);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
onStateSizeChange() {
|
|
132
|
+
const { values } = this.state;
|
|
133
|
+
// Not the field being typed in
|
|
134
|
+
['width', 'height'].forEach(key => {
|
|
135
|
+
const input = this.input(key);
|
|
136
|
+
if (input !== this.j.od.activeElement) {
|
|
137
|
+
input.value = values[key].toString();
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
onSizeInput(e) {
|
|
142
|
+
const { state } = this;
|
|
143
|
+
const { values } = state;
|
|
144
|
+
// Both read first, since setting one rewrites the other's field
|
|
145
|
+
const width = this.input('width').value;
|
|
146
|
+
const height = this.input('height').value;
|
|
147
|
+
if (!state.sizeIsLocked || !isNumeric(width) || !isNumeric(height)) {
|
|
148
|
+
values.width = width;
|
|
149
|
+
values.height = height;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const w = parseFloat(width);
|
|
153
|
+
const h = parseFloat(height);
|
|
154
|
+
if (e.target === this.input('width')) {
|
|
155
|
+
values.width = w;
|
|
156
|
+
values.height = Math.round(w / state.ratio);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
values.width = Math.round(h * state.ratio);
|
|
160
|
+
values.height = h;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Autoplay mutes it, and it keeps its controls unless it autoplays
|
|
165
|
+
*/
|
|
166
|
+
onStateFlagsChange() {
|
|
167
|
+
const { values } = this.state;
|
|
168
|
+
this.input('autoplay').checked = values.autoplay;
|
|
169
|
+
this.input('loop').checked = values.loop;
|
|
170
|
+
this.input('muted').checked = values.muted || values.autoplay;
|
|
171
|
+
this.input('muted').disabled = values.autoplay;
|
|
172
|
+
this.input('controls').checked = values.controls || !values.autoplay;
|
|
173
|
+
this.input('controls').disabled = !values.autoplay;
|
|
174
|
+
}
|
|
175
|
+
onFlagChange(e) {
|
|
176
|
+
Object.keys(flags).forEach(flag => {
|
|
177
|
+
const input = this.input(flag);
|
|
178
|
+
if (e.target === input) {
|
|
179
|
+
this.state.values[flag] = input.checked;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
__decorate([
|
|
185
|
+
hook('ready'),
|
|
186
|
+
watch('state.media')
|
|
187
|
+
], UIVideoPropertiesForm.prototype, "onStateMediaChange", null);
|
|
188
|
+
__decorate([
|
|
189
|
+
hook('ready')
|
|
190
|
+
], UIVideoPropertiesForm.prototype, "hideChangePoster", null);
|
|
191
|
+
__decorate([
|
|
192
|
+
hook('ready'),
|
|
193
|
+
watch('state.values.poster')
|
|
194
|
+
], UIVideoPropertiesForm.prototype, "onStatePosterChange", null);
|
|
195
|
+
__decorate([
|
|
196
|
+
watch('poster:change')
|
|
197
|
+
], UIVideoPropertiesForm.prototype, "onPosterChange", null);
|
|
198
|
+
__decorate([
|
|
199
|
+
watch('changePoster:click')
|
|
200
|
+
], UIVideoPropertiesForm.prototype, "onChangePosterClick", null);
|
|
201
|
+
__decorate([
|
|
202
|
+
watch('removePoster:click')
|
|
203
|
+
], UIVideoPropertiesForm.prototype, "onRemovePosterClick", null);
|
|
204
|
+
__decorate([
|
|
205
|
+
hook('ready'),
|
|
206
|
+
watch('state.sizeIsLocked')
|
|
207
|
+
], UIVideoPropertiesForm.prototype, "onStateSizeIsLockedChange", null);
|
|
208
|
+
__decorate([
|
|
209
|
+
watch('lockSize:click')
|
|
210
|
+
], UIVideoPropertiesForm.prototype, "onLockSizeClick", null);
|
|
211
|
+
__decorate([
|
|
212
|
+
hook('ready'),
|
|
213
|
+
watch(['state.values.width', 'state.values.height'])
|
|
214
|
+
], UIVideoPropertiesForm.prototype, "onStateSizeChange", null);
|
|
215
|
+
__decorate([
|
|
216
|
+
watch(['width:input', 'height:input', 'width:change', 'height:change'])
|
|
217
|
+
], UIVideoPropertiesForm.prototype, "onSizeInput", null);
|
|
218
|
+
__decorate([
|
|
219
|
+
hook('ready'),
|
|
220
|
+
watch(Object.keys(flags).map(flag => `state.values.${flag}`))
|
|
221
|
+
], UIVideoPropertiesForm.prototype, "onStateFlagsChange", null);
|
|
222
|
+
__decorate([
|
|
223
|
+
watch(Object.keys(flags).map(flag => `${flag}:change`))
|
|
224
|
+
], UIVideoPropertiesForm.prototype, "onFlagChange", null);
|
|
225
|
+
UIVideoPropertiesForm = __decorate([
|
|
226
|
+
component
|
|
227
|
+
], UIVideoPropertiesForm);
|
|
228
|
+
export { UIVideoPropertiesForm };
|
|
@@ -0,0 +1,37 @@
|
|
|
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 { Plugin } from "../../core/plugin/plugin";
|
|
7
|
+
import type { VideoPropertiesState } from "./interface";
|
|
8
|
+
/**
|
|
9
|
+
* Show a dialog with the size, poster and playback settings of a video, an
|
|
10
|
+
* embed or audio. The media popup's Edit button opens it:
|
|
11
|
+
*
|
|
12
|
+
* ```javascript
|
|
13
|
+
* editor.events.fire('openVideoProperties', video);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare class videoProperties extends Plugin {
|
|
17
|
+
protected state: VideoPropertiesState;
|
|
18
|
+
private __readSize;
|
|
19
|
+
private get __size();
|
|
20
|
+
private get form();
|
|
21
|
+
private get dialog();
|
|
22
|
+
private get __buttons();
|
|
23
|
+
/**
|
|
24
|
+
* Open the dialog for the media `target` is, or is the wrapper of
|
|
25
|
+
*/
|
|
26
|
+
protected open(target: HTMLElement): void;
|
|
27
|
+
/**
|
|
28
|
+
* The video popup's tabs for the media popup's Replace: what they insert
|
|
29
|
+
* takes the place of the media `target` is, or is the wrapper of
|
|
30
|
+
*/
|
|
31
|
+
protected onGenerateReplaceVideoTabs(target: HTMLElement, close: () => void): HTMLElement;
|
|
32
|
+
private __openPosterPopup;
|
|
33
|
+
/** @override */
|
|
34
|
+
protected afterInit(): void;
|
|
35
|
+
/** @override */
|
|
36
|
+
protected beforeDestruct(): void;
|
|
37
|
+
}
|