jodit 3.8.8 → 3.9.2
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/.github/workflows/tests.yml +23 -0
- package/.idea/dictionaries/v_chupurnov.xml +1 -0
- package/.idea/workspace.xml +295 -286
- package/CHANGELOG.MD +110 -24
- package/README.md +3 -3
- package/build/jodit.css +2 -2
- package/build/jodit.es2018.css +1 -1
- package/build/jodit.es2018.en.css +1 -1
- package/build/jodit.es2018.en.js +329 -210
- package/build/jodit.es2018.en.min.js +1 -1
- package/build/jodit.es2018.js +329 -210
- package/build/jodit.es2018.min.js +1 -1
- package/build/jodit.js +1066 -881
- package/build/jodit.min.css +1 -1
- package/build/jodit.min.js +1 -1
- package/package.json +1 -1
- package/src/core/async.ts +1 -1
- package/src/core/constants.ts +2 -0
- package/src/core/dom.ts +113 -99
- package/src/core/events/{events-native.ts → event-emitter.ts} +14 -9
- package/src/core/events/index.ts +1 -1
- package/src/core/global.ts +2 -2
- package/src/core/helpers/array/to-array.ts +1 -0
- package/src/core/helpers/data-bind.ts +2 -2
- package/src/core/helpers/utils/utils.ts +20 -4
- package/src/core/request/ajax.ts +212 -0
- package/src/core/request/config.ts +37 -0
- package/{build-system/minimizer/index.js → src/core/request/index.ts} +2 -1
- package/src/core/request/response.ts +39 -0
- package/src/core/selection/select.ts +59 -27
- package/src/core/selection/style/api/element-has-same-style.ts +13 -0
- package/src/core/selection/style/api/get-suit-parent.ts +1 -1
- package/src/core/selection/style/api/is-suit-element.ts +24 -4
- package/src/core/selection/style/api/unwrap-children.ts +45 -16
- package/src/core/selection/style/api/wrap-unwrapped-text.ts +28 -23
- package/src/core/selection/style/apply-style.ts +14 -8
- package/src/core/traits/elms.ts +1 -0
- package/src/core/ui/helpers/get-control-type.ts +3 -1
- package/src/core/view/view.ts +3 -3
- package/src/modules/context-menu/context-menu.ts +1 -1
- package/src/modules/file-browser/README.MD +1 -1
- package/src/modules/file-browser/data-provider.ts +22 -42
- package/src/modules/file-browser/file-browser.ts +3 -0
- package/src/modules/index.ts +1 -1
- package/src/modules/table.ts +106 -101
- package/src/modules/uploader/uploader.ts +4 -3
- package/src/plugins/fix/clean-html.ts +37 -16
- package/src/plugins/indent.ts +25 -18
- package/src/plugins/size/resize-handler.ts +1 -1
- package/src/plugins/size/size.ts +1 -3
- package/src/plugins/source/source.ts +1 -1
- package/src/plugins/table/select-cells.ts +23 -5
- package/src/types/ajax.d.ts +15 -6
- package/src/types/async.d.ts +1 -1
- package/src/types/events.d.ts +12 -12
- package/src/types/view.d.ts +2 -2
- package/types/core/async.d.ts +1 -1
- package/types/core/constants.d.ts +1 -0
- package/types/core/dom.d.ts +25 -19
- package/types/core/events/{events-native.d.ts → event-emitter.d.ts} +8 -3
- package/types/core/events/index.d.ts +1 -1
- package/types/core/global.d.ts +2 -2
- package/types/core/helpers/utils/utils.d.ts +12 -4
- package/types/core/{ajax.d.ts → request/ajax.d.ts} +4 -14
- package/types/core/request/config.d.ts +14 -0
- package/{build-system/rules/css.js → types/core/request/index.d.ts} +2 -7
- package/types/core/request/response.d.ts +16 -0
- package/types/core/selection/style/api/element-has-same-style.d.ts +4 -0
- package/types/core/selection/style/api/is-suit-element.d.ts +1 -0
- package/types/core/selection/style/api/wrap-unwrapped-text.d.ts +2 -2
- package/types/core/view/view.d.ts +2 -2
- package/types/modules/file-browser/data-provider.d.ts +1 -1
- package/types/modules/index.d.ts +1 -1
- package/types/plugins/fix/clean-html.d.ts +4 -0
- package/types/plugins/size/resize-handler.d.ts +1 -1
- package/types/plugins/source/source.d.ts +1 -1
- package/types/types/ajax.d.ts +15 -6
- package/types/types/async.d.ts +1 -1
- package/types/types/events.d.ts +12 -12
- package/types/types/view.d.ts +2 -2
- package/.editorconfig +0 -15
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -109
- package/.prettierrc.json +0 -9
- package/.stylelintrc +0 -17
- package/app.css +0 -112
- package/build-system/index.js +0 -78
- package/build-system/loaders/css-variables-prefixes.js +0 -12
- package/build-system/loaders/lang-loader.js +0 -57
- package/build-system/loaders/style.js +0 -31
- package/build-system/loaders/svg-loader.js +0 -21
- package/build-system/minimizer/css.js +0 -20
- package/build-system/minimizer/js.js +0 -41
- package/build-system/plugins/banner.js +0 -15
- package/build-system/plugins/define.js +0 -22
- package/build-system/plugins/extract-css.js +0 -14
- package/build-system/plugins/index.js +0 -31
- package/build-system/plugins/post-build.js +0 -52
- package/build-system/rules/extra-typescript.js +0 -22
- package/build-system/rules/index.js +0 -17
- package/build-system/rules/internal-typescript.js +0 -23
- package/build-system/rules/langs.js +0 -20
- package/build-system/rules/svg.js +0 -19
- package/build-system/utils/filename.js +0 -17
- package/build-system/utils/post-build.js +0 -28
- package/build-system/variables.js +0 -53
- package/composer.json +0 -12
- package/src/core/ajax.ts +0 -266
- package/src/types/core.d.ts +0 -7
- package/src/types/core.js +0 -8
- package/src/types/core.js.map +0 -1
- package/src/types/storage.d.ts +0 -13
- package/src/types/storage.js +0 -8
- package/src/types/storage.js.map +0 -1
- package/types/types/core.js +0 -8
- package/types/types/core.js.map +0 -1
- package/types/types/storage.js +0 -8
- package/types/types/storage.js.map +0 -1
package/package.json
CHANGED
package/src/core/async.ts
CHANGED
|
@@ -201,7 +201,7 @@ export class Async implements IAsync {
|
|
|
201
201
|
promise<T>(
|
|
202
202
|
executor: (
|
|
203
203
|
resolve: (value: T | PromiseLike<T>) => void,
|
|
204
|
-
reject
|
|
204
|
+
reject: (reason?: any) => void
|
|
205
205
|
) => void
|
|
206
206
|
): RejectablePromise<T> {
|
|
207
207
|
let rejectCallback: RejectablePromise<T>['rejectCallback'] = () => {};
|
package/src/core/constants.ts
CHANGED
package/src/core/dom.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
trim
|
|
31
31
|
} from './helpers';
|
|
32
32
|
import { Select } from './selection';
|
|
33
|
+
import { TEMP_ATTR } from './constants';
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Module for working with DOM
|
|
@@ -146,47 +147,6 @@ export class Dom {
|
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
/**
|
|
150
|
-
* It goes through all the internal elements of the node, causing a callback function
|
|
151
|
-
*
|
|
152
|
-
* @param elm - the element whose children and descendants you want to iterate over
|
|
153
|
-
* @param callback - It called for each item found
|
|
154
|
-
* @example
|
|
155
|
-
* ```javascript
|
|
156
|
-
* Jodit.modules.Dom.each(parent.s.current(), function (node) {
|
|
157
|
-
* if (node.nodeType === Node.TEXT_NODE) {
|
|
158
|
-
* node.nodeValue = node.nodeValue.replace(Jodit.INVISIBLE_SPACE_REG_EX, '') // remove all of
|
|
159
|
-
* the text element codes invisible character
|
|
160
|
-
* }
|
|
161
|
-
* });
|
|
162
|
-
* ```
|
|
163
|
-
*/
|
|
164
|
-
static each(
|
|
165
|
-
elm: Node | HTMLElement,
|
|
166
|
-
callback: (node: Node) => void | boolean
|
|
167
|
-
): boolean {
|
|
168
|
-
let node: Node | null | false = elm.firstChild;
|
|
169
|
-
|
|
170
|
-
if (node) {
|
|
171
|
-
while (node) {
|
|
172
|
-
const next = Dom.next(node, Boolean, elm);
|
|
173
|
-
|
|
174
|
-
if (callback(node) === false) {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// inside callback - node could be removed
|
|
179
|
-
if (node.parentNode && !Dom.each(node, callback)) {
|
|
180
|
-
return false;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
node = next;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return true;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
150
|
/**
|
|
191
151
|
* Call function for all nodes between `start` and `end`
|
|
192
152
|
*/
|
|
@@ -461,39 +421,25 @@ export class Dom {
|
|
|
461
421
|
/**
|
|
462
422
|
* Find previous node
|
|
463
423
|
*/
|
|
464
|
-
static prev(
|
|
424
|
+
static prev<T extends Node = Node>(
|
|
465
425
|
node: Node,
|
|
466
426
|
condition: NodeCondition,
|
|
467
|
-
root:
|
|
427
|
+
root: HTMLElement,
|
|
468
428
|
withChild: boolean = true
|
|
469
|
-
): Nullable<
|
|
470
|
-
return Dom.find(
|
|
471
|
-
node,
|
|
472
|
-
condition,
|
|
473
|
-
root,
|
|
474
|
-
false,
|
|
475
|
-
'previousSibling',
|
|
476
|
-
withChild ? 'lastChild' : false
|
|
477
|
-
);
|
|
429
|
+
): Nullable<T> {
|
|
430
|
+
return Dom.find<T>(node, condition, root, false, withChild);
|
|
478
431
|
}
|
|
479
432
|
|
|
480
433
|
/**
|
|
481
434
|
* Find next node what `condition(next) === true`
|
|
482
435
|
*/
|
|
483
|
-
static next(
|
|
436
|
+
static next<T extends Node = Node>(
|
|
484
437
|
node: Node,
|
|
485
438
|
condition: NodeCondition,
|
|
486
|
-
root:
|
|
439
|
+
root: HTMLElement,
|
|
487
440
|
withChild: boolean = true
|
|
488
|
-
): Nullable<
|
|
489
|
-
return Dom.find(
|
|
490
|
-
node,
|
|
491
|
-
condition,
|
|
492
|
-
root,
|
|
493
|
-
undefined,
|
|
494
|
-
undefined,
|
|
495
|
-
withChild ? 'firstChild' : false
|
|
496
|
-
);
|
|
441
|
+
): Nullable<T> {
|
|
442
|
+
return Dom.find<T>(node, condition, root, true, withChild);
|
|
497
443
|
}
|
|
498
444
|
|
|
499
445
|
static prevWithClass(
|
|
@@ -525,51 +471,122 @@ export class Dom {
|
|
|
525
471
|
/**
|
|
526
472
|
* Find next/prev node what `condition(next) === true`
|
|
527
473
|
*/
|
|
528
|
-
static find(
|
|
474
|
+
static find<T extends Node = Node>(
|
|
529
475
|
node: Node,
|
|
530
476
|
condition: NodeCondition,
|
|
531
|
-
root:
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
477
|
+
root: HTMLElement,
|
|
478
|
+
leftToRight: boolean = true,
|
|
479
|
+
withChild: boolean = true
|
|
480
|
+
): Nullable<T> {
|
|
481
|
+
const gen = this.nextGen(node, root, leftToRight, withChild);
|
|
482
|
+
|
|
483
|
+
let item = gen.next();
|
|
484
|
+
|
|
485
|
+
while (!item.done) {
|
|
486
|
+
if (condition(item.value)) {
|
|
487
|
+
return <T>item.value;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
item = gen.next();
|
|
538
491
|
}
|
|
539
492
|
|
|
540
|
-
|
|
541
|
-
|
|
493
|
+
return null;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Find next/prev node what `condition(next) === true`
|
|
498
|
+
*/
|
|
499
|
+
static *nextGen(
|
|
500
|
+
start: Node,
|
|
501
|
+
root: HTMLElement,
|
|
502
|
+
leftToRight: boolean = true,
|
|
503
|
+
withChild: boolean = true
|
|
504
|
+
): Generator<Node> {
|
|
505
|
+
const stack: Node[] = [];
|
|
506
|
+
|
|
507
|
+
let currentNode = start;
|
|
542
508
|
|
|
543
509
|
do {
|
|
544
|
-
next =
|
|
510
|
+
let next = leftToRight
|
|
511
|
+
? currentNode.nextSibling
|
|
512
|
+
: currentNode.previousSibling;
|
|
545
513
|
|
|
546
|
-
|
|
547
|
-
|
|
514
|
+
while (next) {
|
|
515
|
+
stack.unshift(next);
|
|
516
|
+
next = leftToRight ? next.nextSibling : next.previousSibling;
|
|
548
517
|
}
|
|
549
518
|
|
|
550
|
-
|
|
551
|
-
const nextOne = Dom.find(
|
|
552
|
-
next[child] as Node,
|
|
553
|
-
condition,
|
|
554
|
-
next,
|
|
555
|
-
true,
|
|
556
|
-
sibling,
|
|
557
|
-
child
|
|
558
|
-
);
|
|
519
|
+
yield* this.runInStack(start, stack, leftToRight, withChild);
|
|
559
520
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
521
|
+
currentNode = <Node>currentNode.parentNode;
|
|
522
|
+
} while (currentNode !== root);
|
|
523
|
+
|
|
524
|
+
return null;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* It goes through all the internal elements of the node, causing a callback function
|
|
529
|
+
*
|
|
530
|
+
* @param elm - the element whose children and descendants you want to iterate over
|
|
531
|
+
* @param callback - It called for each item found
|
|
532
|
+
* @example
|
|
533
|
+
* ```javascript
|
|
534
|
+
* Jodit.modules.Dom.each(parent.s.current(), function (node) {
|
|
535
|
+
* if (node.nodeType === Node.TEXT_NODE) {
|
|
536
|
+
* node.nodeValue = node.nodeValue.replace(Jodit.INVISIBLE_SPACE_REG_EX, '') // remove all of
|
|
537
|
+
* the text element codes invisible character
|
|
538
|
+
* }
|
|
539
|
+
* });
|
|
540
|
+
* ```
|
|
541
|
+
*/
|
|
542
|
+
static each(
|
|
543
|
+
elm: Node,
|
|
544
|
+
callback: (node: Node) => void | boolean,
|
|
545
|
+
leftToRight: boolean = true
|
|
546
|
+
): boolean {
|
|
547
|
+
const gen = this.eachGen(elm, leftToRight);
|
|
548
|
+
|
|
549
|
+
let item = gen.next();
|
|
550
|
+
|
|
551
|
+
while (!item.done) {
|
|
552
|
+
if (callback(item.value) === false) {
|
|
553
|
+
return false;
|
|
563
554
|
}
|
|
564
555
|
|
|
565
|
-
|
|
566
|
-
|
|
556
|
+
item = gen.next();
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
static eachGen(root: Node, leftToRight: boolean = true): Generator<Node> {
|
|
563
|
+
return this.runInStack(root, [root], leftToRight);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
private static *runInStack(
|
|
567
|
+
start: Node,
|
|
568
|
+
stack: Node[],
|
|
569
|
+
leftToRight: boolean,
|
|
570
|
+
withChild: boolean = true
|
|
571
|
+
): Generator<Node> {
|
|
572
|
+
while (stack.length) {
|
|
573
|
+
const item = <Node>stack.pop();
|
|
574
|
+
|
|
575
|
+
if (start !== item) {
|
|
576
|
+
yield item;
|
|
567
577
|
}
|
|
568
578
|
|
|
569
|
-
|
|
570
|
-
|
|
579
|
+
if (withChild) {
|
|
580
|
+
let child = leftToRight ? item.lastChild : item.firstChild;
|
|
571
581
|
|
|
572
|
-
|
|
582
|
+
while (child) {
|
|
583
|
+
stack.push(child);
|
|
584
|
+
child = leftToRight
|
|
585
|
+
? child.previousSibling
|
|
586
|
+
: child.nextSibling;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
573
590
|
}
|
|
574
591
|
|
|
575
592
|
/**
|
|
@@ -948,7 +965,7 @@ export class Dom {
|
|
|
948
965
|
attributes?: IDictionary
|
|
949
966
|
): K {
|
|
950
967
|
attributes && attr(element, attributes);
|
|
951
|
-
attr(element,
|
|
968
|
+
attr(element, TEMP_ATTR, true);
|
|
952
969
|
return element;
|
|
953
970
|
}
|
|
954
971
|
|
|
@@ -960,10 +977,7 @@ export class Dom {
|
|
|
960
977
|
return false;
|
|
961
978
|
}
|
|
962
979
|
|
|
963
|
-
return (
|
|
964
|
-
Select.isMarker(element) ||
|
|
965
|
-
attr(element, 'data-jodit-temp') === 'true'
|
|
966
|
-
);
|
|
980
|
+
return Select.isMarker(element) || attr(element, TEMP_ATTR) === 'true';
|
|
967
981
|
}
|
|
968
982
|
|
|
969
983
|
/**
|
|
@@ -980,6 +994,6 @@ export class Dom {
|
|
|
980
994
|
* Get temporary list
|
|
981
995
|
*/
|
|
982
996
|
static temporaryList(root: HTMLElement): HTMLElement[] {
|
|
983
|
-
return $$(
|
|
997
|
+
return $$(`[${TEMP_ATTR}]`, root);
|
|
984
998
|
}
|
|
985
999
|
}
|
|
@@ -4,14 +4,11 @@
|
|
|
4
4
|
* Copyright (c) 2013-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
* The module editor's event manager
|
|
9
|
-
*/
|
|
10
|
-
|
|
7
|
+
// eslint-disable-next-line max-classes-per-file
|
|
11
8
|
import type {
|
|
12
9
|
CallbackFunction,
|
|
13
10
|
EventHandlerBlock,
|
|
14
|
-
|
|
11
|
+
IEventEmitter
|
|
15
12
|
} from '../../types';
|
|
16
13
|
import { defaultNameSpace, EventHandlersStore } from './store';
|
|
17
14
|
import { isString } from '../helpers/checker/is-string';
|
|
@@ -19,7 +16,10 @@ import { isFunction } from '../helpers/checker/is-function';
|
|
|
19
16
|
import { isArray } from '../helpers/checker/is-array';
|
|
20
17
|
import { error } from '../helpers/type';
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The module editor's event manager
|
|
21
|
+
*/
|
|
22
|
+
export class EventEmitter implements IEventEmitter {
|
|
23
23
|
private mutedEvents: Set<string> = new Set();
|
|
24
24
|
|
|
25
25
|
mute(event?: string): this {
|
|
@@ -40,7 +40,7 @@ export class EventsNative implements IEventsNative {
|
|
|
40
40
|
return this;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
readonly __key: string = '
|
|
43
|
+
readonly __key: string = '__JoditEventEmitterNamespaces';
|
|
44
44
|
|
|
45
45
|
private doc: Document = document;
|
|
46
46
|
|
|
@@ -265,7 +265,7 @@ export class EventsNative implements IEventsNative {
|
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
const isDOMElement = isFunction((subject as any).addEventListener),
|
|
268
|
-
self:
|
|
268
|
+
self: EventEmitter = this;
|
|
269
269
|
|
|
270
270
|
let syntheticCallback: CallbackFunction = function (
|
|
271
271
|
this: any,
|
|
@@ -564,7 +564,7 @@ export class EventsNative implements IEventsNative {
|
|
|
564
564
|
* ```
|
|
565
565
|
* or you can trigger native browser listener
|
|
566
566
|
* ```javascript
|
|
567
|
-
* var events = new Jodit.modules.
|
|
567
|
+
* var events = new Jodit.modules.EventEmitter();
|
|
568
568
|
* events.on(document.body, 'click',function (event) {
|
|
569
569
|
* alert('click on ' + event.target.id );
|
|
570
570
|
* });
|
|
@@ -697,3 +697,8 @@ export class EventsNative implements IEventsNative {
|
|
|
697
697
|
delete (this as any)[this.__key];
|
|
698
698
|
}
|
|
699
699
|
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* @deprecated Use `EventEmitter` instead
|
|
703
|
+
*/
|
|
704
|
+
export class EventsNative extends EventEmitter implements IEventEmitter {}
|
package/src/core/events/index.ts
CHANGED
package/src/core/global.ts
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
kebabCase
|
|
25
25
|
} from './helpers/';
|
|
26
26
|
|
|
27
|
-
import {
|
|
27
|
+
import { EventEmitter } from './events';
|
|
28
28
|
|
|
29
29
|
export const instances: IDictionary<IJodit> = {};
|
|
30
30
|
|
|
@@ -124,4 +124,4 @@ export function getContainer<T extends HTMLTagNames = HTMLTagNames>(
|
|
|
124
124
|
/**
|
|
125
125
|
* Global event emitter
|
|
126
126
|
*/
|
|
127
|
-
export const eventEmitter = new
|
|
127
|
+
export const eventEmitter = new EventEmitter();
|
|
@@ -17,5 +17,6 @@ export const toArray = function toArray<T extends typeof Array.from>(
|
|
|
17
17
|
const func = isNativeFunction(Array.from)
|
|
18
18
|
? Array.from
|
|
19
19
|
: reset<typeof Array.from>('Array.from') ?? Array.from;
|
|
20
|
+
|
|
20
21
|
return func.apply(Array, args) as ReturnType<T>;
|
|
21
22
|
} as typeof Array.from;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Copyright (c) 2013-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {
|
|
7
|
+
import type { IEventEmitter, IViewComponent, Nullable } from '../../types';
|
|
8
8
|
import { ViewComponent } from '../component';
|
|
9
9
|
import { isViewObject } from './checker';
|
|
10
10
|
|
|
@@ -21,7 +21,7 @@ export const dataBind = <T = any>(
|
|
|
21
21
|
itemStore = {};
|
|
22
22
|
store.set(elm, itemStore);
|
|
23
23
|
|
|
24
|
-
let e: Nullable<
|
|
24
|
+
let e: Nullable<IEventEmitter> = null;
|
|
25
25
|
|
|
26
26
|
if (elm instanceof ViewComponent) {
|
|
27
27
|
e = (elm as IViewComponent).j.e;
|
|
@@ -40,21 +40,37 @@ export function call<T extends any[], R>(
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
44
|
-
* it will also check `data-{key}` attribute
|
|
45
|
-
* if set `value` it is alias for setAttribute with same logic
|
|
43
|
+
* Get attribute
|
|
46
44
|
*/
|
|
47
45
|
export function attr(elm: Element, key: string): null | string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Remove attribute
|
|
49
|
+
*/
|
|
50
|
+
export function attr(elm: Element, key: string, value: null): null | string;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Set attribute
|
|
54
|
+
*/
|
|
48
55
|
export function attr(
|
|
49
56
|
elm: Element,
|
|
50
57
|
key: string,
|
|
51
|
-
value: string | number | boolean |
|
|
58
|
+
value: string | number | boolean | undefined | null
|
|
52
59
|
): null;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Set or remove several attributes
|
|
63
|
+
*/
|
|
53
64
|
export function attr(
|
|
54
65
|
elm: Element,
|
|
55
66
|
attributes: IDictionary<string | number | boolean | null>
|
|
56
67
|
): null;
|
|
57
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Alias for `elm.getAttribute` but if set second argument `-{key}`
|
|
71
|
+
* it will also check `data-{key}` attribute
|
|
72
|
+
* if set `value` it is alias for setAttribute with same logic
|
|
73
|
+
*/
|
|
58
74
|
export function attr(
|
|
59
75
|
elm: Element,
|
|
60
76
|
keyOrAttributes: string | IDictionary<string | number | boolean | null>,
|
|
@@ -0,0 +1,212 @@
|
|
|
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
IDictionary,
|
|
9
|
+
IRequest,
|
|
10
|
+
IViewBased,
|
|
11
|
+
AjaxOptions,
|
|
12
|
+
IAjax,
|
|
13
|
+
RejectablePromise,
|
|
14
|
+
IResponse
|
|
15
|
+
} from '../../types';
|
|
16
|
+
|
|
17
|
+
import { Config } from '../../config';
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
error,
|
|
21
|
+
isPlainObject,
|
|
22
|
+
parseQuery,
|
|
23
|
+
buildQuery,
|
|
24
|
+
isString,
|
|
25
|
+
isFunction,
|
|
26
|
+
ConfigProto
|
|
27
|
+
} from '../helpers';
|
|
28
|
+
import { Response } from './response';
|
|
29
|
+
|
|
30
|
+
import './config';
|
|
31
|
+
|
|
32
|
+
export class Ajax<T extends object = any> implements IAjax<T> {
|
|
33
|
+
static log: IRequest[] = [];
|
|
34
|
+
|
|
35
|
+
private readonly xhr!: XMLHttpRequest;
|
|
36
|
+
|
|
37
|
+
private __buildParams(
|
|
38
|
+
obj: string | IDictionary<string | object> | FormData,
|
|
39
|
+
prefix?: string
|
|
40
|
+
): string | FormData {
|
|
41
|
+
if (isFunction(this.o.queryBuild)) {
|
|
42
|
+
return this.o.queryBuild.call(this, obj, prefix);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
isString(obj) ||
|
|
47
|
+
((this.j.ow as any).FormData &&
|
|
48
|
+
obj instanceof (this.j.ow as any).FormData)
|
|
49
|
+
) {
|
|
50
|
+
return obj as string | FormData;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return buildQuery(obj);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
options: AjaxOptions;
|
|
57
|
+
get o(): this['options'] {
|
|
58
|
+
return this.options;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Alias for this.jodit
|
|
63
|
+
*/
|
|
64
|
+
get j(): this['jodit'] {
|
|
65
|
+
return this.jodit;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
abort(): Ajax {
|
|
69
|
+
try {
|
|
70
|
+
this.xhr.abort();
|
|
71
|
+
} catch {}
|
|
72
|
+
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private resolved = false;
|
|
77
|
+
|
|
78
|
+
private activated = false;
|
|
79
|
+
|
|
80
|
+
send(): RejectablePromise<IResponse<T>> {
|
|
81
|
+
this.activated = true;
|
|
82
|
+
|
|
83
|
+
const { xhr, o } = this;
|
|
84
|
+
|
|
85
|
+
const request = this.prepareRequest();
|
|
86
|
+
|
|
87
|
+
return this.j.async.promise((resolve, reject) => {
|
|
88
|
+
const onReject = () => {
|
|
89
|
+
reject(error('Connection error'));
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const onResolve = () => {
|
|
93
|
+
this.resolved = true;
|
|
94
|
+
|
|
95
|
+
resolve(
|
|
96
|
+
new Response<T>(
|
|
97
|
+
request,
|
|
98
|
+
xhr.status,
|
|
99
|
+
xhr.statusText,
|
|
100
|
+
xhr.responseText
|
|
101
|
+
)
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
xhr.onabort = onReject;
|
|
106
|
+
xhr.onerror = onReject;
|
|
107
|
+
xhr.ontimeout = onReject;
|
|
108
|
+
|
|
109
|
+
xhr.onload = onResolve;
|
|
110
|
+
|
|
111
|
+
xhr.onprogress = (e): void => {
|
|
112
|
+
let percentComplete = 0;
|
|
113
|
+
|
|
114
|
+
if (e.lengthComputable) {
|
|
115
|
+
percentComplete = (e.loaded / e.total) * 100;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.options.onProgress?.(percentComplete);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
xhr.onreadystatechange = () => {
|
|
122
|
+
this.options.onProgress?.(10);
|
|
123
|
+
|
|
124
|
+
if (xhr.readyState === XMLHttpRequest.DONE) {
|
|
125
|
+
if (o.successStatuses.includes(xhr.status)) {
|
|
126
|
+
onResolve();
|
|
127
|
+
} else {
|
|
128
|
+
reject(error(xhr.statusText || 'Connection error'));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
xhr.withCredentials = o.withCredentials ?? false;
|
|
134
|
+
|
|
135
|
+
const { url, data, method } = request;
|
|
136
|
+
|
|
137
|
+
xhr.open(method, url, true);
|
|
138
|
+
|
|
139
|
+
if (o.contentType && xhr.setRequestHeader) {
|
|
140
|
+
xhr.setRequestHeader('Content-type', o.contentType);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const { headers } = o;
|
|
144
|
+
|
|
145
|
+
if (headers && xhr.setRequestHeader) {
|
|
146
|
+
Object.keys(headers).forEach(key => {
|
|
147
|
+
xhr.setRequestHeader(key, headers[key]);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// IE
|
|
152
|
+
this.j.async.setTimeout(() => {
|
|
153
|
+
xhr.send(data ? this.__buildParams(data) : undefined);
|
|
154
|
+
}, 0);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
prepareRequest(): IRequest {
|
|
159
|
+
if (!this.o.url) {
|
|
160
|
+
throw error('Need URL for AJAX request');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
let url: string = this.o.url;
|
|
164
|
+
|
|
165
|
+
const data = this.o.data;
|
|
166
|
+
const method = (this.o.method || 'get').toLowerCase();
|
|
167
|
+
|
|
168
|
+
if (method === 'get' && data && isPlainObject(data)) {
|
|
169
|
+
const qIndex = url.indexOf('?');
|
|
170
|
+
|
|
171
|
+
if (qIndex !== -1) {
|
|
172
|
+
const urlData = parseQuery(url);
|
|
173
|
+
|
|
174
|
+
url =
|
|
175
|
+
url.substr(0, qIndex) +
|
|
176
|
+
'?' +
|
|
177
|
+
buildQuery({ ...urlData, ...(data as IDictionary) });
|
|
178
|
+
} else {
|
|
179
|
+
url += '?' + buildQuery(this.o.data as IDictionary);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const request = {
|
|
184
|
+
url,
|
|
185
|
+
method,
|
|
186
|
+
data
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
Ajax.log.splice(100);
|
|
190
|
+
Ajax.log.push(request);
|
|
191
|
+
|
|
192
|
+
return request;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
constructor(readonly jodit: IViewBased, options: Partial<AjaxOptions>) {
|
|
196
|
+
this.options = ConfigProto(
|
|
197
|
+
options || {},
|
|
198
|
+
Config.prototype.defaultAjaxOptions
|
|
199
|
+
) as AjaxOptions;
|
|
200
|
+
|
|
201
|
+
this.xhr = this.o.xhr ? this.o.xhr() : new XMLHttpRequest();
|
|
202
|
+
|
|
203
|
+
jodit && jodit.e && jodit.e.on('beforeDestruct', () => this.destruct());
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
destruct(): void {
|
|
207
|
+
if (this.activated && !this.resolved) {
|
|
208
|
+
this.abort();
|
|
209
|
+
this.resolved = true;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|