jodit 3.6.2 → 3.6.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 +21 -0
- package/README.md +1 -3
- package/build/jodit.css +6 -6
- package/build/jodit.es2018.css +3 -3
- package/build/jodit.es2018.en.css +3 -3
- package/build/jodit.es2018.en.js +194 -73
- package/build/jodit.es2018.en.min.css +1 -1
- package/build/jodit.es2018.en.min.js +2 -2
- package/build/jodit.es2018.js +194 -73
- package/build/jodit.es2018.min.css +1 -1
- package/build/jodit.es2018.min.js +2 -2
- package/build/jodit.js +443 -308
- package/build/jodit.min.css +2 -2
- package/build/jodit.min.js +2 -2
- package/package.json +2 -2
- package/src/config.ts +2 -0
- package/src/core/decorators/persistent.ts +1 -1
- package/src/core/decorators/watch.ts +6 -0
- package/src/core/helpers/checker/is-url.ts +3 -3
- package/src/core/plugin-system.ts +1 -0
- package/src/core/ui/helpers/get-control-type.ts +2 -1
- package/src/core/ui/list/group.ts +3 -2
- package/src/core/ui/popup/popup.ts +17 -8
- package/src/core/view/view-with-toolbar.ts +1 -1
- package/src/core/view/view.ts +9 -4
- package/src/jodit.ts +7 -2
- package/src/modules/dialog/dialog.ts +2 -1
- package/src/modules/file-browser/config.ts +2 -0
- package/src/plugins/clipboard/drag-and-drop-element.ts +1 -0
- package/src/plugins/index.ts +1 -0
- package/src/plugins/inline-popup/config/items/cells.ts +1 -0
- package/src/plugins/inline-popup/inline-popup.ts +39 -9
- package/src/plugins/justify.ts +3 -0
- package/src/plugins/link/link.ts +8 -2
- package/src/plugins/resizer/resizer.ts +52 -55
- package/src/plugins/select.ts +88 -0
- package/src/plugins/table/select-cells.ts +43 -43
- package/src/styles/jodit.less +1 -1
- package/src/styles/variables.less +1 -1
- package/src/types/view.d.ts +2 -0
- package/test/bootstrap.js +7 -0
- package/test/tests/acceptance/commandsTest.js +1 -2
- package/test/tests/acceptance/imageTest.js +1 -1
- package/test/tests/acceptance/inlineModeTest.js +21 -16
- package/test/tests/acceptance/plugins/inline-popup.js +1 -2
- package/test/tests/acceptance/plugins/link.js +145 -17
- package/test/tests/acceptance/tableTest.js +184 -197
- package/test/tests/acceptance/toolbarTest.js +34 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jodit",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.6",
|
|
4
4
|
"description": "Jodit is awesome and usefully wysiwyg editor with filebrowser",
|
|
5
5
|
"main": "build/jodit.min.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"test": "npm run build-no-uglify-es5 && karma start --browsers FirefoxHeadless karma.conf.js",
|
|
21
21
|
"test-debug": "karma start --browsers Chrome karma.conf.js --single-run false",
|
|
22
22
|
"test-chrome": "karma start --browsers Chrome karma.conf.js",
|
|
23
|
-
"jodit": "cd ../jodit-pro &&
|
|
23
|
+
"jodit": "cd ../jodit-pro && npm run newversion && cd ../jodit-react/ && npm update && npm run newversion && cd ../jodit-joomla && npm run newversion && cd ../jodit-master && npm run newversion",
|
|
24
24
|
"types": "rm -rf types/* && tsc --project . --declaration --outDir types --emitDeclarationOnly",
|
|
25
25
|
"pretty": "npx prettier --write ./src/*.{ts,less} ./src/**/*.{ts,less} ./src/**/**/*.{ts,less} ./src/**/**/**/*.{ts,less} ./src/**/**/**/**/*.{ts,less}",
|
|
26
26
|
"fix": "npx eslint ./src/* ./test/ --fix && npm run pretty",
|
package/src/config.ts
CHANGED
|
@@ -22,6 +22,8 @@ import * as consts from './core/constants';
|
|
|
22
22
|
* Default Editor's Configuration
|
|
23
23
|
*/
|
|
24
24
|
export class Config implements IViewOptions {
|
|
25
|
+
namespace: string = '';
|
|
26
|
+
|
|
25
27
|
/**
|
|
26
28
|
* When this option is enabled, the editor's content will be placed in an iframe and isolated from the rest of the page.
|
|
27
29
|
*
|
|
@@ -19,7 +19,7 @@ export function persistent<T extends IComponent>(target: T, propertyKey: string)
|
|
|
19
19
|
const jodit = isViewObject(component)
|
|
20
20
|
? component
|
|
21
21
|
: ((component as unknown) as IViewComponent).jodit,
|
|
22
|
-
storageKey = `${component.componentName}_prop_${propertyKey}`,
|
|
22
|
+
storageKey = `${jodit.options.namespace}${component.componentName}_prop_${propertyKey}`,
|
|
23
23
|
initialValue = (component as IDictionary)[propertyKey];
|
|
24
24
|
|
|
25
25
|
Object.defineProperty(component, propertyKey, {
|
|
@@ -63,6 +63,12 @@ export function watch(observeFields: string[] | string, context?: object | ((c:
|
|
|
63
63
|
.on(context || component, eventName, callback)
|
|
64
64
|
.on(eventName, callback);
|
|
65
65
|
|
|
66
|
+
view.hookStatus('beforeDestruct', () => {
|
|
67
|
+
view.events
|
|
68
|
+
.off(context || component, eventName, callback)
|
|
69
|
+
.off(eventName, callback);
|
|
70
|
+
});
|
|
71
|
+
|
|
66
72
|
return;
|
|
67
73
|
}
|
|
68
74
|
|
|
@@ -16,9 +16,9 @@ export function isURL(str: string): boolean {
|
|
|
16
16
|
'^(https?:\\/\\/)' + // protocol
|
|
17
17
|
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' + // domain name
|
|
18
18
|
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
|
19
|
-
'(\\:\\d+)?(\\/[-a-z
|
|
20
|
-
'(\\?[;&a-z
|
|
21
|
-
'(\\#[-a-z
|
|
19
|
+
'(\\:\\d+)?(\\/[-a-zа-яё\\d%_.~+]*)*' + // port and path
|
|
20
|
+
'(\\?[;&a-zа-яё\\d%_.~+=-]*)?' + // query string
|
|
21
|
+
'(\\#[-a-zа-яё\\d_]*)?$',
|
|
22
22
|
'i'
|
|
23
23
|
); // fragment locator
|
|
24
24
|
|
|
@@ -25,7 +25,8 @@ export function getControlType(
|
|
|
25
25
|
): IControlTypeStrong {
|
|
26
26
|
let buttonControl: IControlTypeStrong;
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
if (!controls)
|
|
29
|
+
controls = Config.defaultOptions.controls;
|
|
29
30
|
|
|
30
31
|
if (!isString(button)) {
|
|
31
32
|
buttonControl = { name: 'empty', ...ConfigFlatten(button) };
|
|
@@ -39,17 +39,18 @@ export class UIGroup<T extends IViewBased = IViewBased>
|
|
|
39
39
|
*/
|
|
40
40
|
get allChildren(): IUIElement[] {
|
|
41
41
|
const result: IUIElement[] = [];
|
|
42
|
+
|
|
42
43
|
const stack: Array<IUIElement | IUIElement[] | IUIGroup> = [
|
|
43
44
|
...this.elements
|
|
44
45
|
];
|
|
45
46
|
|
|
46
47
|
while (stack.length) {
|
|
47
|
-
const elm = stack.
|
|
48
|
+
const elm = stack.shift();
|
|
48
49
|
|
|
49
50
|
if (isArray(elm)) {
|
|
50
51
|
stack.push(...elm);
|
|
51
52
|
} else if (elm instanceof UIGroup) {
|
|
52
|
-
stack.push(...elm.elements
|
|
53
|
+
stack.push(...elm.elements);
|
|
53
54
|
} else {
|
|
54
55
|
elm && result.push(elm);
|
|
55
56
|
}
|
|
@@ -303,7 +303,7 @@ export class Popup extends UIElement implements IPopup {
|
|
|
303
303
|
this.childrenPopups.forEach(popup => popup.close());
|
|
304
304
|
|
|
305
305
|
this.j.e.fire(this, 'beforeClose');
|
|
306
|
-
this.j.e.fire(
|
|
306
|
+
this.j.e.fire('beforePopupClose', this);
|
|
307
307
|
|
|
308
308
|
this.removeGlobalListeners();
|
|
309
309
|
|
|
@@ -342,13 +342,17 @@ export class Popup extends UIElement implements IPopup {
|
|
|
342
342
|
|
|
343
343
|
eventEmitter.on('closeAllPopups', this.close);
|
|
344
344
|
|
|
345
|
+
if (this.smart) {
|
|
346
|
+
this.j.e
|
|
347
|
+
.on('escape', this.close)
|
|
348
|
+
.on('mousedown touchstart', this.closeOnOutsideClick)
|
|
349
|
+
.on(ow, 'mousedown touchstart', this.closeOnOutsideClick);
|
|
350
|
+
}
|
|
351
|
+
|
|
345
352
|
this.j.e
|
|
346
353
|
.on('closeAllPopups', this.close)
|
|
347
|
-
.on('escape', this.close)
|
|
348
354
|
.on('resize', up)
|
|
349
355
|
.on(this.container, 'scroll mousewheel', up)
|
|
350
|
-
.on('mousedown touchstart', this.closeOnOutsideClick)
|
|
351
|
-
.on(ow, 'mousedown touchstart', this.closeOnOutsideClick)
|
|
352
356
|
.on(ow, 'scroll', up)
|
|
353
357
|
.on(ow, 'resize', up);
|
|
354
358
|
}
|
|
@@ -359,13 +363,18 @@ export class Popup extends UIElement implements IPopup {
|
|
|
359
363
|
|
|
360
364
|
eventEmitter.off('closeAllPopups', this.close);
|
|
361
365
|
|
|
366
|
+
if (this.smart) {
|
|
367
|
+
this.j.e
|
|
368
|
+
.off('escape', this.close)
|
|
369
|
+
.off('mousedown touchstart', this.closeOnOutsideClick)
|
|
370
|
+
.off(ow, 'mousedown touchstart', this.closeOnOutsideClick);
|
|
371
|
+
}
|
|
372
|
+
|
|
362
373
|
this.j.e
|
|
363
374
|
.off('closeAllPopups', this.close)
|
|
364
|
-
|
|
375
|
+
|
|
365
376
|
.off('resize', up)
|
|
366
377
|
.off(this.container, 'scroll mousewheel', up)
|
|
367
|
-
.off('mousedown touchstart', this.closeOnOutsideClick)
|
|
368
|
-
.off(ow, 'mousedown touchstart', this.closeOnOutsideClick)
|
|
369
378
|
.off(ow, 'scroll', up)
|
|
370
379
|
.off(ow, 'resize', up);
|
|
371
380
|
}
|
|
@@ -378,7 +387,7 @@ export class Popup extends UIElement implements IPopup {
|
|
|
378
387
|
this.container.style.zIndex = index.toString();
|
|
379
388
|
}
|
|
380
389
|
|
|
381
|
-
constructor(jodit: IViewBased) {
|
|
390
|
+
constructor(jodit: IViewBased, readonly smart: boolean = true) {
|
|
382
391
|
super(jodit);
|
|
383
392
|
attr(this.container, 'role', 'popup');
|
|
384
393
|
}
|
|
@@ -154,7 +154,7 @@ export abstract class ViewWithToolbar extends View implements IViewWithToolbar {
|
|
|
154
154
|
|
|
155
155
|
/** @override **/
|
|
156
156
|
protected constructor(
|
|
157
|
-
options?: IViewOptions
|
|
157
|
+
options?: Partial<IViewOptions>,
|
|
158
158
|
readonly isJodit: boolean = false
|
|
159
159
|
) {
|
|
160
160
|
super(options, isJodit);
|
package/src/core/view/view.ts
CHANGED
|
@@ -235,15 +235,19 @@ export abstract class View extends Component implements IViewBased, Mods, Elms {
|
|
|
235
235
|
* Return current version
|
|
236
236
|
*/
|
|
237
237
|
getVersion(): string {
|
|
238
|
-
return
|
|
238
|
+
return appVersion;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static getVersion(): string {
|
|
242
|
+
return appVersion;
|
|
239
243
|
}
|
|
240
244
|
|
|
241
245
|
/** @override */
|
|
242
|
-
protected initOptions(options?: IViewOptions): void {
|
|
246
|
+
protected initOptions(options?: Partial<IViewOptions>): void {
|
|
243
247
|
this.options = ConfigProto(
|
|
244
248
|
options || {},
|
|
245
249
|
ConfigProto(this.options || {}, View.defaultOptions)
|
|
246
|
-
);
|
|
250
|
+
) as IViewOptions;
|
|
247
251
|
}
|
|
248
252
|
|
|
249
253
|
/**
|
|
@@ -252,7 +256,7 @@ export abstract class View extends Component implements IViewBased, Mods, Elms {
|
|
|
252
256
|
protected initOwners(): void {}
|
|
253
257
|
|
|
254
258
|
protected constructor(
|
|
255
|
-
options?: IViewOptions
|
|
259
|
+
options?: Partial<IViewOptions>,
|
|
256
260
|
readonly isJodit: boolean = false
|
|
257
261
|
) {
|
|
258
262
|
super();
|
|
@@ -360,6 +364,7 @@ export abstract class View extends Component implements IViewBased, Mods, Elms {
|
|
|
360
364
|
View.defaultOptions = {
|
|
361
365
|
extraButtons: [],
|
|
362
366
|
textIcons: false,
|
|
367
|
+
namespace: '',
|
|
363
368
|
removeButtons: [],
|
|
364
369
|
zIndex: 100002,
|
|
365
370
|
defaultTimeout: 100,
|
package/src/jodit.ts
CHANGED
|
@@ -136,6 +136,8 @@ export class Jodit extends ViewWithToolbar implements IJodit {
|
|
|
136
136
|
return Config.defaultOptions;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
static fatMode: boolean = false;
|
|
140
|
+
|
|
139
141
|
static plugins: IPluginSystem = pluginSystem;
|
|
140
142
|
|
|
141
143
|
static modules: IDictionary<Function> = modules;
|
|
@@ -1221,14 +1223,17 @@ export class Jodit extends ViewWithToolbar implements IJodit {
|
|
|
1221
1223
|
|
|
1222
1224
|
workplace.appendChild(editor);
|
|
1223
1225
|
|
|
1224
|
-
const currentPlace = {
|
|
1226
|
+
const currentPlace: IWorkPlace = {
|
|
1225
1227
|
editor,
|
|
1226
1228
|
element,
|
|
1227
1229
|
container,
|
|
1228
1230
|
workplace,
|
|
1229
1231
|
statusbar,
|
|
1230
1232
|
options: this.isReady
|
|
1231
|
-
? ConfigProto(
|
|
1233
|
+
? (ConfigProto(
|
|
1234
|
+
options || {},
|
|
1235
|
+
Config.defaultOptions
|
|
1236
|
+
) as IWorkPlace['options'])
|
|
1232
1237
|
: this.options,
|
|
1233
1238
|
observer: new Observer(this),
|
|
1234
1239
|
editorWindow: this.ow
|
|
@@ -56,6 +56,7 @@ declare module '../../config' {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
Config.prototype.dialog = {
|
|
59
|
+
namespace: '',
|
|
59
60
|
extraButtons: [],
|
|
60
61
|
resizable: true,
|
|
61
62
|
draggable: true,
|
|
@@ -728,7 +729,7 @@ export class Dialog extends ViewWithToolbar implements IDialog {
|
|
|
728
729
|
return this;
|
|
729
730
|
}
|
|
730
731
|
|
|
731
|
-
constructor(options?: IDialogOptions) {
|
|
732
|
+
constructor(options?: Partial<IDialogOptions>) {
|
|
732
733
|
super(options);
|
|
733
734
|
|
|
734
735
|
const self: Dialog = this;
|
package/src/plugins/index.ts
CHANGED
|
@@ -37,6 +37,7 @@ export { placeholder } from './placeholder/placeholder';
|
|
|
37
37
|
export { redoUndo } from './redo-undo';
|
|
38
38
|
export { resizer } from './resizer/resizer';
|
|
39
39
|
export { search } from './search/search';
|
|
40
|
+
export { select } from './select';
|
|
40
41
|
export { size, resizeHandler } from './size';
|
|
41
42
|
export { source } from './source';
|
|
42
43
|
export { stat } from './stat';
|
|
@@ -27,18 +27,21 @@ import {
|
|
|
27
27
|
isArray,
|
|
28
28
|
isFunction,
|
|
29
29
|
toArray,
|
|
30
|
-
keys
|
|
30
|
+
keys,
|
|
31
|
+
camelCase
|
|
31
32
|
} from '../../core/helpers';
|
|
32
33
|
import { Dom, Table, ToolbarCollection, UIElement } from '../../modules';
|
|
33
|
-
import { debounce, wait, autobind } from '../../core/decorators';
|
|
34
|
+
import { debounce, wait, autobind, watch } from '../../core/decorators';
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Plugin for show inline popup dialog
|
|
37
38
|
*/
|
|
38
39
|
export class inlinePopup extends Plugin {
|
|
40
|
+
requires = ['select'];
|
|
41
|
+
|
|
39
42
|
private type: Nullable<string> = null;
|
|
40
43
|
|
|
41
|
-
private popup: IPopup = new Popup(this.jodit);
|
|
44
|
+
private popup: IPopup = new Popup(this.jodit, false);
|
|
42
45
|
|
|
43
46
|
private toolbar: IToolbarCollection = makeCollection(
|
|
44
47
|
this.jodit,
|
|
@@ -46,9 +49,8 @@ export class inlinePopup extends Plugin {
|
|
|
46
49
|
);
|
|
47
50
|
|
|
48
51
|
@autobind
|
|
49
|
-
private onClick(
|
|
50
|
-
const
|
|
51
|
-
elements = keys(this.j.o.popup, false) as HTMLTagNames[],
|
|
52
|
+
private onClick(node: Node): void | false {
|
|
53
|
+
const elements = this.elmsList as HTMLTagNames[],
|
|
52
54
|
target = Dom.isTag(node, 'img')
|
|
53
55
|
? node
|
|
54
56
|
: Dom.closest(node, elements, this.j.editor);
|
|
@@ -59,6 +61,8 @@ export class inlinePopup extends Plugin {
|
|
|
59
61
|
target.nodeName.toLowerCase(),
|
|
60
62
|
target
|
|
61
63
|
);
|
|
64
|
+
|
|
65
|
+
return false;
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -114,13 +118,19 @@ export class inlinePopup extends Plugin {
|
|
|
114
118
|
/**
|
|
115
119
|
* Hide opened popup
|
|
116
120
|
*/
|
|
121
|
+
@watch(':clickEditor')
|
|
117
122
|
@autobind
|
|
118
123
|
private hidePopup(type?: string): void {
|
|
119
|
-
if (!type || type === this.type) {
|
|
124
|
+
if (!isString(type) || type === this.type) {
|
|
120
125
|
this.popup.close();
|
|
121
126
|
}
|
|
122
127
|
}
|
|
123
128
|
|
|
129
|
+
@watch(':outsideClick')
|
|
130
|
+
protected onOutsideClick(e: MouseEvent): void {
|
|
131
|
+
this.popup.close();
|
|
132
|
+
}
|
|
133
|
+
|
|
124
134
|
/**
|
|
125
135
|
* Can show popup for this type
|
|
126
136
|
* @param type
|
|
@@ -189,9 +199,10 @@ export class inlinePopup extends Plugin {
|
|
|
189
199
|
);
|
|
190
200
|
}
|
|
191
201
|
)
|
|
192
|
-
.on('click', this.onClick)
|
|
193
202
|
.on('mousedown keydown', this.onSelectionStart)
|
|
194
203
|
.on([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd);
|
|
204
|
+
|
|
205
|
+
this.addListenersForElements();
|
|
195
206
|
}
|
|
196
207
|
|
|
197
208
|
private snapRange: Nullable<Range> = null;
|
|
@@ -289,7 +300,26 @@ export class inlinePopup extends Plugin {
|
|
|
289
300
|
protected beforeDestruct(jodit: IJodit): void {
|
|
290
301
|
jodit.e
|
|
291
302
|
.off('showPopup')
|
|
292
|
-
.off('click', this.onClick)
|
|
293
303
|
.off([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd);
|
|
304
|
+
|
|
305
|
+
this.removeListenersForElements();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
private elmsList: string[] = keys(this.j.o.popup, false).filter(
|
|
309
|
+
s => !this.isExcludedTarget(s)
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
private addListenersForElements() {
|
|
313
|
+
this.j.e.on(
|
|
314
|
+
this.elmsList.map(e => camelCase(`click_${e}`)).join(' '),
|
|
315
|
+
this.onClick
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
private removeListenersForElements() {
|
|
320
|
+
this.j.e.off(
|
|
321
|
+
this.elmsList.map(e => camelCase(`click_${e}`)).join(' '),
|
|
322
|
+
this.onClick
|
|
323
|
+
);
|
|
294
324
|
}
|
|
295
325
|
}
|
package/src/plugins/justify.ts
CHANGED
|
@@ -152,12 +152,15 @@ export const alignElement = (
|
|
|
152
152
|
case 'justifyfull':
|
|
153
153
|
box.style.textAlign = 'justify';
|
|
154
154
|
break;
|
|
155
|
+
|
|
155
156
|
case 'justifyright':
|
|
156
157
|
box.style.textAlign = 'right';
|
|
157
158
|
break;
|
|
159
|
+
|
|
158
160
|
case 'justifyleft':
|
|
159
161
|
box.style.textAlign = 'left';
|
|
160
162
|
break;
|
|
163
|
+
|
|
161
164
|
case 'justifycenter':
|
|
162
165
|
box.style.textAlign = 'center';
|
|
163
166
|
break;
|
package/src/plugins/link/link.ts
CHANGED
|
@@ -202,7 +202,6 @@ export class link extends Plugin {
|
|
|
202
202
|
html: string
|
|
203
203
|
): HTMLAnchorElement | void {
|
|
204
204
|
const { jodit } = this;
|
|
205
|
-
|
|
206
205
|
if (isURL(html)) {
|
|
207
206
|
if (jodit.o.link.processVideoLink) {
|
|
208
207
|
const embed = convertMediaUrlToVideoEmbed(html);
|
|
@@ -307,6 +306,7 @@ export class link extends Plugin {
|
|
|
307
306
|
className_input.value = attr(link, 'class') || '';
|
|
308
307
|
}
|
|
309
308
|
break;
|
|
309
|
+
|
|
310
310
|
case 'select':
|
|
311
311
|
if (className_select) {
|
|
312
312
|
for (
|
|
@@ -394,7 +394,13 @@ export class link extends Plugin {
|
|
|
394
394
|
|
|
395
395
|
if (!link) {
|
|
396
396
|
if (!jodit.s.isCollapsed()) {
|
|
397
|
-
|
|
397
|
+
const node = jodit.s.current();
|
|
398
|
+
|
|
399
|
+
if (Dom.isTag(node, ['img'])) {
|
|
400
|
+
links = [Dom.wrap(node, 'a', jodit) as HTMLAnchorElement];
|
|
401
|
+
} else {
|
|
402
|
+
links = jodit.s.wrapInTag('a') as HTMLAnchorElement[];
|
|
403
|
+
}
|
|
398
404
|
} else {
|
|
399
405
|
const a = jodit.createInside.element('a');
|
|
400
406
|
jodit.s.insertNode(a);
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import './resizer.less';
|
|
8
8
|
|
|
9
|
-
import type { IBound } from '../../types';
|
|
9
|
+
import type { HTMLTagNames, IBound, Nullable } from '../../types';
|
|
10
10
|
import type { IJodit } from '../../types';
|
|
11
11
|
import { Config } from '../../config';
|
|
12
12
|
import * as consts from '../../core/constants';
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from '../../core/helpers';
|
|
23
23
|
import { Plugin } from '../../core/plugin';
|
|
24
24
|
import { eventEmitter } from '../../core/global';
|
|
25
|
-
import { autobind } from '../../core/decorators';
|
|
25
|
+
import { autobind, debounce, watch } from '../../core/decorators';
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* The module creates a supporting frame for resizing of the elements img and table
|
|
@@ -34,9 +34,7 @@ import { autobind } from '../../core/decorators';
|
|
|
34
34
|
*/
|
|
35
35
|
declare module '../../config' {
|
|
36
36
|
interface Config {
|
|
37
|
-
|
|
38
|
-
useTableResizer: boolean;
|
|
39
|
-
useImageResizer: boolean;
|
|
37
|
+
allowResizeTags: HTMLTagNames[];
|
|
40
38
|
|
|
41
39
|
resizer: {
|
|
42
40
|
showSize: boolean;
|
|
@@ -46,17 +44,8 @@ declare module '../../config' {
|
|
|
46
44
|
};
|
|
47
45
|
}
|
|
48
46
|
}
|
|
49
|
-
Config.prototype.useIframeResizer = true;
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
* @property{boolean} useTableResizer=true Use true frame for editing table size
|
|
53
|
-
*/
|
|
54
|
-
Config.prototype.useTableResizer = true;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @property{boolean} useImageResizer=true Use true image editing frame size
|
|
58
|
-
*/
|
|
59
|
-
Config.prototype.useImageResizer = true;
|
|
48
|
+
Config.prototype.allowResizeTags = ['img', 'iframe', 'table', 'jodit'];
|
|
60
49
|
|
|
61
50
|
/**
|
|
62
51
|
* @property {object} resizer
|
|
@@ -105,6 +94,7 @@ export class resizer extends Plugin {
|
|
|
105
94
|
'span'
|
|
106
95
|
)[0];
|
|
107
96
|
|
|
97
|
+
/** @override */
|
|
108
98
|
protected afterInit(editor: IJodit): void {
|
|
109
99
|
$$('i', this.rect).forEach((resizeHandle: HTMLElement) => {
|
|
110
100
|
editor.e.on(
|
|
@@ -134,18 +124,37 @@ export class resizer extends Plugin {
|
|
|
134
124
|
}
|
|
135
125
|
)
|
|
136
126
|
.on('hideResizer', this.hide)
|
|
137
|
-
.on(
|
|
138
|
-
'change afterInit afterSetMode',
|
|
139
|
-
editor.async.debounce(
|
|
140
|
-
this.onChangeEditor.bind(this),
|
|
141
|
-
editor.defaultTimeout
|
|
142
|
-
)
|
|
143
|
-
);
|
|
127
|
+
.on('change afterInit afterSetMode', this.onChangeEditor);
|
|
144
128
|
|
|
145
129
|
this.addEventListeners();
|
|
146
130
|
this.onChangeEditor();
|
|
147
131
|
}
|
|
148
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Click in the editor area
|
|
135
|
+
* @param e
|
|
136
|
+
* @protected
|
|
137
|
+
*/
|
|
138
|
+
@watch(':click')
|
|
139
|
+
protected onEditorClick(e: MouseEvent): void {
|
|
140
|
+
let node = e.target as Nullable<Node>;
|
|
141
|
+
|
|
142
|
+
const {
|
|
143
|
+
editor,
|
|
144
|
+
options: { allowResizeTags }
|
|
145
|
+
} = this.j;
|
|
146
|
+
|
|
147
|
+
while (node && node !== editor) {
|
|
148
|
+
if (Dom.isTag(node, allowResizeTags)) {
|
|
149
|
+
this.bind(node);
|
|
150
|
+
this.onClickElement(node, e);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
node = node.parentNode;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
149
158
|
private addEventListeners() {
|
|
150
159
|
const editor = this.j;
|
|
151
160
|
|
|
@@ -303,9 +312,8 @@ export class resizer extends Plugin {
|
|
|
303
312
|
}
|
|
304
313
|
}
|
|
305
314
|
|
|
315
|
+
@debounce()
|
|
306
316
|
private onChangeEditor() {
|
|
307
|
-
const editor = this.j;
|
|
308
|
-
|
|
309
317
|
if (this.isShown) {
|
|
310
318
|
if (!this.element || !this.element.parentNode) {
|
|
311
319
|
this.hide();
|
|
@@ -314,35 +322,20 @@ export class resizer extends Plugin {
|
|
|
314
322
|
}
|
|
315
323
|
}
|
|
316
324
|
|
|
317
|
-
|
|
318
|
-
$$('img, table, iframe', editor.editor).forEach(
|
|
319
|
-
(elm: HTMLElement) => {
|
|
320
|
-
if (editor.getMode() === consts.MODE_SOURCE) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
if (
|
|
325
|
-
!(elm as any)[keyBInd] &&
|
|
326
|
-
((Dom.isTag(elm, 'iframe') &&
|
|
327
|
-
editor.o.useIframeResizer) ||
|
|
328
|
-
(Dom.isTag(elm, 'img') &&
|
|
329
|
-
editor.o.useImageResizer) ||
|
|
330
|
-
(Dom.isTag(elm, 'table') &&
|
|
331
|
-
editor.o.useTableResizer))
|
|
332
|
-
) {
|
|
333
|
-
(elm as any)[keyBInd] = true;
|
|
334
|
-
this.bind(elm);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
);
|
|
338
|
-
}
|
|
325
|
+
$$('iframe', this.j.editor).forEach(this.bind)
|
|
339
326
|
}
|
|
340
327
|
|
|
341
328
|
/**
|
|
342
329
|
* Bind an edit element toWYSIWYG element
|
|
343
330
|
* @param {HTMLElement} element The element that you want toWYSIWYG add a function toWYSIWYG resize
|
|
344
331
|
*/
|
|
345
|
-
|
|
332
|
+
@autobind
|
|
333
|
+
private bind(element: HTMLElement): void {
|
|
334
|
+
if ((element as any)[keyBInd]) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
(element as any)[keyBInd] = true;
|
|
346
339
|
let wrapper: HTMLElement;
|
|
347
340
|
|
|
348
341
|
if (Dom.isTag(element, 'iframe')) {
|
|
@@ -399,11 +392,14 @@ export class resizer extends Plugin {
|
|
|
399
392
|
if (IS_IE && Dom.isTag(element, 'img')) {
|
|
400
393
|
event.preventDefault();
|
|
401
394
|
}
|
|
402
|
-
})
|
|
403
|
-
.on(element, 'click', () => this.onClickElement(element));
|
|
395
|
+
});
|
|
404
396
|
}
|
|
405
397
|
|
|
406
|
-
private onClickElement = (element: HTMLElement) => {
|
|
398
|
+
private onClickElement = (element: HTMLElement, e: MouseEvent) => {
|
|
399
|
+
if (this.isResized) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
|
|
407
403
|
if (this.element !== element || !this.isShown) {
|
|
408
404
|
this.element = element;
|
|
409
405
|
|
|
@@ -514,11 +510,12 @@ export class resizer extends Plugin {
|
|
|
514
510
|
*/
|
|
515
511
|
@autobind
|
|
516
512
|
private hide(): void {
|
|
517
|
-
this.isResized
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
513
|
+
if (!this.isResized) {
|
|
514
|
+
this.isResized = false;
|
|
515
|
+
this.isShown = false;
|
|
516
|
+
this.element = null;
|
|
517
|
+
Dom.safeRemove(this.rect);
|
|
518
|
+
}
|
|
522
519
|
}
|
|
523
520
|
|
|
524
521
|
private hideSizeViewer = () => {
|