@syncfusion/ej2-base 24.2.8 → 25.1.35-579988
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/.eslintrc.json +2 -1
- package/CHANGELOG.md +641 -677
- package/{README.md → ReadMe.md} +100 -100
- package/dist/ej2-base.umd.min.js +1 -10
- package/dist/ej2-base.umd.min.js.map +1 -1
- package/dist/es6/ej2-base.es2015.js +178 -1025
- package/dist/es6/ej2-base.es2015.js.map +1 -1
- package/dist/es6/ej2-base.es5.js +226 -934
- package/dist/es6/ej2-base.es5.js.map +1 -1
- package/dist/global/ej2-base.min.js +1 -10
- package/dist/global/ej2-base.min.js.map +1 -1
- package/dist/global/index.d.ts +0 -9
- package/dist/ts/ajax.ts +236 -0
- package/dist/ts/animation.ts +544 -0
- package/dist/ts/base.ts +357 -0
- package/dist/ts/browser.ts +387 -0
- package/dist/ts/child-property.ts +192 -0
- package/dist/ts/component.ts +519 -0
- package/dist/ts/dom.ts +488 -0
- package/dist/ts/draggable.ts +1155 -0
- package/dist/ts/droppable.ts +172 -0
- package/dist/ts/event-handler.ts +169 -0
- package/dist/ts/internationalization.ts +369 -0
- package/dist/ts/intl/date-formatter.ts +317 -0
- package/dist/ts/intl/date-parser.ts +426 -0
- package/dist/ts/intl/intl-base.ts +1104 -0
- package/dist/ts/intl/number-formatter.ts +411 -0
- package/dist/ts/intl/number-parser.ts +158 -0
- package/dist/ts/intl/parser-base.ts +394 -0
- package/dist/ts/keyboard.ts +238 -0
- package/dist/ts/l10n.ts +94 -0
- package/dist/ts/module-loader.ts +149 -0
- package/dist/ts/notify-property-change.ts +726 -0
- package/dist/ts/observer.ts +236 -0
- package/dist/ts/sanitize-helper.ts +224 -0
- package/dist/ts/template-engine.ts +191 -0
- package/dist/ts/template.ts +329 -0
- package/dist/ts/touch.ts +544 -0
- package/dist/ts/util.ts +523 -0
- package/dist/ts/validate-lic.ts +0 -0
- package/e2e/crypto.js +16 -16
- package/e2e/m.protractor.config.js +286 -286
- package/e2e/modified-protractor/protractor.config.js +316 -316
- package/e2e/protractor.config.js +389 -332
- package/helpers/e2e/index.js +3 -3
- package/license +10 -10
- package/package.json +225 -174
- package/src/ajax.d.ts +1 -1
- package/src/ajax.js +3 -8
- package/src/animation-model.d.ts +41 -41
- package/src/animation.d.ts +6 -6
- package/src/animation.js +25 -25
- package/src/base.d.ts +2 -1
- package/src/base.js +9 -7
- package/src/component-model.d.ts +16 -16
- package/src/component.d.ts +9 -3
- package/src/component.js +50 -38
- package/src/draggable-model.d.ts +113 -113
- package/src/draggable.d.ts +2 -0
- package/src/draggable.js +45 -29
- package/src/droppable-model.d.ts +23 -23
- package/src/droppable.js +19 -19
- package/src/event-handler.js +2 -1
- package/src/index.d.ts +0 -3
- package/src/index.js +0 -3
- package/src/intl/date-formatter.js +2 -6
- package/src/intl/date-parser.js +1 -20
- package/src/intl/intl-base.js +1 -164
- package/src/intl/number-formatter.d.ts +3 -0
- package/src/intl/number-formatter.js +7 -7
- package/src/intl/number-parser.js +1 -0
- package/src/keyboard-model.d.ts +16 -16
- package/src/keyboard.js +19 -19
- package/src/module-loader.d.ts +12 -0
- package/src/module-loader.js +11 -0
- package/src/notify-property-change.js +3 -2
- package/src/observer.js +2 -0
- package/src/sanitize-helper.js +5 -0
- package/src/template-engine.js +1 -0
- package/src/template.js +3 -2
- package/src/touch-model.d.ts +39 -39
- package/src/touch.js +19 -19
- package/src/validate-lic.d.ts +0 -11
- package/src/validate-lic.js +1 -259
- package/styles/_all.scss +2 -2
- package/styles/_bds-dark-definition.scss +15 -0
- package/styles/_bds-definition.scss +15 -0
- package/styles/_bootstrap-dark-definition.scss +42 -42
- package/styles/_bootstrap-definition.scss +42 -42
- package/styles/_bootstrap4-definition.scss +11 -11
- package/styles/_bootstrap5-dark-definition.scss +9 -9
- package/styles/_bootstrap5-definition.scss +8 -8
- package/styles/_fabric-dark-definition.scss +42 -42
- package/styles/_fabric-definition.scss +42 -42
- package/styles/_fluent-dark-definition.scss +9 -9
- package/styles/_fluent-definition.scss +9 -9
- package/styles/_fluent2-definition.scss +9 -0
- package/styles/_fusionnew-dark-definition.scss +8 -8
- package/styles/_fusionnew-definition.scss +8 -8
- package/styles/_highcontrast-definition.scss +42 -42
- package/styles/_highcontrast-light-definition.scss +42 -42
- package/styles/_material-dark-definition.scss +48 -48
- package/styles/_material-definition.scss +49 -49
- package/styles/_material3-dark-definition.scss +14 -14
- package/styles/_material3-definition.scss +15 -15
- package/styles/_tailwind-dark-definition.scss +15 -15
- package/styles/_tailwind-definition.scss +15 -15
- package/styles/animation/_all.scss +560 -560
- package/styles/bootstrap-dark.css +10 -1
- package/styles/bootstrap.css +10 -1
- package/styles/bootstrap4.css +10 -1
- package/styles/bootstrap5-dark.css +10 -1
- package/styles/bootstrap5.css +10 -1
- package/styles/common/_all.scss +2 -2
- package/styles/common/_core.scss +117 -117
- package/styles/common/_mixin.scss +9 -9
- package/styles/definition/_bds-dark.scss +1179 -0
- package/styles/definition/_bds.scss +1474 -0
- package/styles/definition/_bootstrap-dark.scss +219 -219
- package/styles/definition/_bootstrap.scss +215 -215
- package/styles/definition/_bootstrap4.scss +167 -167
- package/styles/definition/_bootstrap5-dark.scss +493 -493
- package/styles/definition/_bootstrap5.scss +494 -494
- package/styles/definition/_fabric-dark.scss +200 -200
- package/styles/definition/_fabric.scss +198 -198
- package/styles/definition/_fluent-dark.scss +557 -557
- package/styles/definition/_fluent.scss +558 -558
- package/styles/definition/_fluent2.scss +2198 -0
- package/styles/definition/_fusionnew-dark.scss +362 -362
- package/styles/definition/_fusionnew.scss +363 -363
- package/styles/definition/_highcontrast-light.scss +193 -193
- package/styles/definition/_highcontrast.scss +195 -195
- package/styles/definition/_material-dark.scss +198 -198
- package/styles/definition/_material.scss +192 -192
- package/styles/definition/_material3-dark.scss +710 -710
- package/styles/definition/_material3.scss +792 -792
- package/styles/definition/_tailwind-dark.scss +488 -488
- package/styles/definition/_tailwind.scss +485 -485
- package/styles/fabric-dark.css +10 -1
- package/styles/fabric.css +10 -1
- package/styles/fluent-dark.css +10 -1
- package/styles/fluent.css +10 -1
- package/styles/highcontrast-light.css +10 -1
- package/styles/highcontrast.css +10 -1
- package/styles/material-dark.css +10 -1
- package/styles/material.css +10 -1
- package/styles/material3-dark.css +10 -1
- package/styles/material3.css +10 -1
- package/styles/offline-theme/material-dark.css +10 -1
- package/styles/offline-theme/material.css +10 -1
- package/styles/offline-theme/tailwind-dark.css +10 -1
- package/styles/offline-theme/tailwind.css +10 -1
- package/styles/tailwind-dark.css +10 -1
- package/styles/tailwind.css +10 -1
- package/.github/PULL_REQUEST_TEMPLATE/Bug.md +0 -60
- package/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -42
- package/bin/syncfusion-license.js +0 -2
- package/dist/ej2-base.min.js +0 -10
- package/e2e/index.d.ts +0 -27
- package/src/fetch.d.ts +0 -114
- package/src/fetch.js +0 -116
- package/src/hijri-parser.d.ts +0 -19
- package/src/hijri-parser.js +0 -204
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { isNullOrUndefined, getValue, extend, isBlazor } from './util';
|
|
2
|
+
/**
|
|
3
|
+
* Observer is used to perform event handling based the object.
|
|
4
|
+
* ```
|
|
5
|
+
* //Creating observer instance.
|
|
6
|
+
* let observer:Observer = Observer(this);
|
|
7
|
+
* let handler: Function = (a:number, b: number): number => {return a + b; }
|
|
8
|
+
* //add handler to event.
|
|
9
|
+
* observe.on('eventname', handler);
|
|
10
|
+
* //remove handler from event.
|
|
11
|
+
* observe.off('eventname', handler);
|
|
12
|
+
* //notify the handlers in event.
|
|
13
|
+
* observe.notify('eventname');
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
export interface BoundOptions {
|
|
18
|
+
handler?: Function;
|
|
19
|
+
context?: Object;
|
|
20
|
+
event?: string;
|
|
21
|
+
id?: string;
|
|
22
|
+
}
|
|
23
|
+
export class Observer {
|
|
24
|
+
private context: Object;
|
|
25
|
+
private ranArray: string[] = [];
|
|
26
|
+
private boundedEvents: { [key: string]: [BoundOptions] } = {};
|
|
27
|
+
constructor(context?: Object) {
|
|
28
|
+
if (isNullOrUndefined(context)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.context = context;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* To attach handler for given property in current context.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} property - specifies the name of the event.
|
|
37
|
+
* @param {Function} handler - Specifies the handler function to be called while event notified.
|
|
38
|
+
* @param {Object} context - Specifies the context binded to the handler.
|
|
39
|
+
* @param {string} id - specifies the random generated id.
|
|
40
|
+
* @returns {void}
|
|
41
|
+
*/
|
|
42
|
+
public on(property: string, handler: Function, context?: Object, id?: string): void {
|
|
43
|
+
if (isNullOrUndefined(handler)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const cntxt: Object = context || this.context;
|
|
47
|
+
if (this.notExist(property)) {
|
|
48
|
+
this.boundedEvents[`${property}`] = [{ handler: handler, context: cntxt, id: id }];
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (!isNullOrUndefined(id)) {
|
|
52
|
+
if (this.ranArray.indexOf(id) === -1) {
|
|
53
|
+
this.ranArray.push(id);
|
|
54
|
+
this.boundedEvents[`${property}`].push({ handler: handler, context: cntxt, id: id });
|
|
55
|
+
}
|
|
56
|
+
} else if (!this.isHandlerPresent(this.boundedEvents[`${property}`], handler)) {
|
|
57
|
+
this.boundedEvents[`${property}`].push({ handler: handler, context: cntxt });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* To remove handlers from a event attached using on() function.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} property - specifies the name of the event.
|
|
65
|
+
* @param {Function} handler - Optional argument specifies the handler function to be called while event notified.
|
|
66
|
+
* @param {string} id - specifies the random generated id.
|
|
67
|
+
* @returns {void} ?
|
|
68
|
+
*/
|
|
69
|
+
public off(property: string, handler?: Function, id?: string): void {
|
|
70
|
+
if (this.notExist(property)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const curObject: BoundOptions[] = getValue(property, this.boundedEvents);
|
|
74
|
+
if (handler) {
|
|
75
|
+
for (let i: number = 0; i < curObject.length; i++) {
|
|
76
|
+
if (id) {
|
|
77
|
+
if (curObject[parseInt(i.toString(), 10)].id === id) {
|
|
78
|
+
curObject.splice(i, 1);
|
|
79
|
+
const indexLocation: number = this.ranArray.indexOf(id);
|
|
80
|
+
if (indexLocation !== -1) {
|
|
81
|
+
this.ranArray.splice(indexLocation, 1);
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
} else if (handler === curObject[parseInt(i.toString(), 10)].handler) {
|
|
86
|
+
curObject.splice(i, 1);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
delete this.boundedEvents[`${property}`];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* To notify the handlers in the specified event.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} property - Specifies the event to be notify.
|
|
99
|
+
* @param {Object} argument - Additional parameters to pass while calling the handler.
|
|
100
|
+
* @param {Function} successHandler - this function will invoke after event successfully triggered
|
|
101
|
+
* @param {Function} errorHandler - this function will invoke after event if it was failure to call.
|
|
102
|
+
* @returns {void} ?
|
|
103
|
+
*/
|
|
104
|
+
public notify(property: string, argument?: Object, successHandler?: Function, errorHandler?: Function): void | Object {
|
|
105
|
+
if (this.notExist(property)) {
|
|
106
|
+
if (successHandler) {
|
|
107
|
+
successHandler.call(this, argument);
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (argument) {
|
|
112
|
+
(<{ name: string }>argument).name = property;
|
|
113
|
+
}
|
|
114
|
+
const blazor: string = 'Blazor';
|
|
115
|
+
const curObject: BoundOptions[] = getValue(property, this.boundedEvents).slice(0);
|
|
116
|
+
if (window[`${blazor}`]) {
|
|
117
|
+
return this.blazorCallback(curObject, argument, successHandler, errorHandler, 0);
|
|
118
|
+
} else {
|
|
119
|
+
for (const cur of curObject) {
|
|
120
|
+
cur.handler.call(cur.context, argument);
|
|
121
|
+
}
|
|
122
|
+
if (successHandler) {
|
|
123
|
+
successHandler.call(this, argument);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private blazorCallback(
|
|
129
|
+
objs: BoundOptions[],
|
|
130
|
+
argument: object,
|
|
131
|
+
successHandler: Function,
|
|
132
|
+
errorHandler: Function,
|
|
133
|
+
index: number): void | object {
|
|
134
|
+
const isTrigger: boolean = index === objs.length - 1;
|
|
135
|
+
if (index < objs.length) {
|
|
136
|
+
const obj: BoundOptions = objs[parseInt(index.toString(), 10)];
|
|
137
|
+
const promise: Promise<object> = obj.handler.call(obj.context, argument);
|
|
138
|
+
if (promise && typeof promise.then === 'function') {
|
|
139
|
+
if (!successHandler) {
|
|
140
|
+
return promise;
|
|
141
|
+
}
|
|
142
|
+
promise.then((data: object) => {
|
|
143
|
+
data = typeof data === 'string' && this.isJson(data) ? JSON.parse(data as string, this.dateReviver) : data;
|
|
144
|
+
extend(argument, argument, data, true);
|
|
145
|
+
if (successHandler && isTrigger) {
|
|
146
|
+
successHandler.call(obj.context, argument);
|
|
147
|
+
} else {
|
|
148
|
+
return this.blazorCallback(objs, argument, successHandler, errorHandler, index + 1);
|
|
149
|
+
}
|
|
150
|
+
}).catch((data: object) => {
|
|
151
|
+
if (errorHandler) {
|
|
152
|
+
errorHandler.call(obj.context, typeof data === 'string' &&
|
|
153
|
+
this.isJson(data) ? JSON.parse(data, this.dateReviver) : data);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
} else if (successHandler && isTrigger) {
|
|
157
|
+
successHandler.call(obj.context, argument);
|
|
158
|
+
} else {
|
|
159
|
+
return this.blazorCallback(objs, argument, successHandler, errorHandler, index + 1);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// eslint-disable-next-line
|
|
165
|
+
public dateReviver(key: any, value: any): void | object {
|
|
166
|
+
const dPattern: RegExp = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
|
|
167
|
+
if (isBlazor && typeof value === 'string' && value.match(dPattern) !== null) {
|
|
168
|
+
return (new Date(value));
|
|
169
|
+
}
|
|
170
|
+
return (value);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public isJson(value: string): boolean {
|
|
174
|
+
try {
|
|
175
|
+
JSON.parse(value);
|
|
176
|
+
} catch (e) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* To destroy handlers in the event
|
|
183
|
+
*
|
|
184
|
+
* @returns {void} ?
|
|
185
|
+
*/
|
|
186
|
+
public destroy(): void {
|
|
187
|
+
this.boundedEvents = this.context = undefined;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* To remove internationalization events
|
|
191
|
+
*
|
|
192
|
+
* @returns {void} ?
|
|
193
|
+
*/
|
|
194
|
+
public offIntlEvents(): void {
|
|
195
|
+
// eslint-disable-next-line
|
|
196
|
+
const eventsArr: any = this.boundedEvents['notifyExternalChange'];
|
|
197
|
+
if (eventsArr) {
|
|
198
|
+
for (let i: number = 0; i < eventsArr.length; i++) {
|
|
199
|
+
// eslint-disable-next-line
|
|
200
|
+
const curContext: any = eventsArr[`${i}`].context;
|
|
201
|
+
if (curContext && curContext.detectFunction && curContext.randomId && !curContext.isRendered) {
|
|
202
|
+
this.off('notifyExternalChange', curContext.detectFunction, curContext.randomId);
|
|
203
|
+
i--;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (!this.boundedEvents['notifyExternalChange'].length) {
|
|
207
|
+
delete this.boundedEvents['notifyExternalChange'];
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Returns if the property exists.
|
|
213
|
+
*
|
|
214
|
+
* @param {string} prop ?
|
|
215
|
+
* @returns {boolean} ?
|
|
216
|
+
*/
|
|
217
|
+
private notExist(prop: string): boolean {
|
|
218
|
+
// eslint-disable-next-line
|
|
219
|
+
return this.boundedEvents.hasOwnProperty(prop) === false || this.boundedEvents[prop].length <= 0;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Returns if the handler is present.
|
|
223
|
+
*
|
|
224
|
+
* @param {BoundOptions[]} boundedEvents ?
|
|
225
|
+
* @param {Function} handler ?
|
|
226
|
+
* @returns {boolean} ?
|
|
227
|
+
*/
|
|
228
|
+
private isHandlerPresent(boundedEvents: BoundOptions[], handler: Function): boolean {
|
|
229
|
+
for (const cur of boundedEvents) {
|
|
230
|
+
if (cur.handler === handler) {
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SanitizeHtmlHelper for sanitize the value.
|
|
3
|
+
*/
|
|
4
|
+
import { detach } from './dom';
|
|
5
|
+
import { isNullOrUndefined } from './util';
|
|
6
|
+
|
|
7
|
+
interface BeforeSanitizeHtml {
|
|
8
|
+
/** Illustrates whether the current action needs to be prevented or not. */
|
|
9
|
+
cancel?: boolean;
|
|
10
|
+
/** It is a callback function and executed it before our inbuilt action. It should return HTML as a string.
|
|
11
|
+
*
|
|
12
|
+
* @function
|
|
13
|
+
* @param {string} value - Returns the value.
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
16
|
+
/** Returns the selectors object which carrying both tags and attributes selectors to block list of cross-site scripting attack.
|
|
17
|
+
* Also possible to modify the block list in this event.
|
|
18
|
+
*/
|
|
19
|
+
selectors?: SanitizeSelectors;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface SanitizeSelectors {
|
|
23
|
+
/** Returns the tags. */
|
|
24
|
+
tags?: string[];
|
|
25
|
+
/** Returns the attributes. */
|
|
26
|
+
attributes?: SanitizeRemoveAttrs[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface SanitizeRemoveAttrs {
|
|
30
|
+
/** Defines the attribute name to sanitize */
|
|
31
|
+
attribute?: string;
|
|
32
|
+
/** Defines the selector that sanitize the specified attributes within the selector */
|
|
33
|
+
selector?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const removeTags: string[] = [
|
|
37
|
+
'script',
|
|
38
|
+
'style',
|
|
39
|
+
'iframe[src]',
|
|
40
|
+
'link[href*="javascript:"]',
|
|
41
|
+
'object[type="text/x-scriptlet"]',
|
|
42
|
+
'object[data^="data:text/html;base64"]',
|
|
43
|
+
'img[src^="data:text/html;base64"]',
|
|
44
|
+
'[src^="javascript:"]',
|
|
45
|
+
'[dynsrc^="javascript:"]',
|
|
46
|
+
'[lowsrc^="javascript:"]',
|
|
47
|
+
'[type^="application/x-shockwave-flash"]'
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const removeAttrs: SanitizeRemoveAttrs[] = [
|
|
51
|
+
{ attribute: 'href', selector: '[href*="javascript:"]' },
|
|
52
|
+
{ attribute: 'background', selector: '[background^="javascript:"]' },
|
|
53
|
+
{ attribute: 'style', selector: '[style*="javascript:"]' },
|
|
54
|
+
{ attribute: 'style', selector: '[style*="expression("]' },
|
|
55
|
+
{ attribute: 'href', selector: 'a[href^="data:text/html;base64"]' }];
|
|
56
|
+
|
|
57
|
+
const jsEvents: string[] = ['onchange',
|
|
58
|
+
'onclick',
|
|
59
|
+
'onmouseover',
|
|
60
|
+
'onmouseout',
|
|
61
|
+
'onkeydown',
|
|
62
|
+
'onload',
|
|
63
|
+
'onerror',
|
|
64
|
+
'onblur',
|
|
65
|
+
'onfocus',
|
|
66
|
+
'onbeforeload',
|
|
67
|
+
'onbeforeunload',
|
|
68
|
+
'onkeyup',
|
|
69
|
+
'onsubmit',
|
|
70
|
+
'onafterprint',
|
|
71
|
+
'onbeforeonload',
|
|
72
|
+
'onbeforeprint',
|
|
73
|
+
'oncanplay',
|
|
74
|
+
'oncanplaythrough',
|
|
75
|
+
'oncontextmenu',
|
|
76
|
+
'ondblclick',
|
|
77
|
+
'ondrag',
|
|
78
|
+
'ondragend',
|
|
79
|
+
'ondragenter',
|
|
80
|
+
'ondragleave',
|
|
81
|
+
'ondragover',
|
|
82
|
+
'ondragstart',
|
|
83
|
+
'ondrop',
|
|
84
|
+
'ondurationchange',
|
|
85
|
+
'onemptied',
|
|
86
|
+
'onended',
|
|
87
|
+
'onformchange',
|
|
88
|
+
'onforminput',
|
|
89
|
+
'onhaschange',
|
|
90
|
+
'oninput',
|
|
91
|
+
'oninvalid',
|
|
92
|
+
'onkeypress',
|
|
93
|
+
'onloadeddata',
|
|
94
|
+
'onloadedmetadata',
|
|
95
|
+
'onloadstart',
|
|
96
|
+
'onmessage',
|
|
97
|
+
'onmousedown',
|
|
98
|
+
'onmousemove',
|
|
99
|
+
'onmouseup',
|
|
100
|
+
'onmousewheel',
|
|
101
|
+
'onoffline',
|
|
102
|
+
'onoine',
|
|
103
|
+
'ononline',
|
|
104
|
+
'onpagehide',
|
|
105
|
+
'onpageshow',
|
|
106
|
+
'onpause',
|
|
107
|
+
'onplay',
|
|
108
|
+
'onplaying',
|
|
109
|
+
'onpopstate',
|
|
110
|
+
'onprogress',
|
|
111
|
+
'onratechange',
|
|
112
|
+
'onreadystatechange',
|
|
113
|
+
'onredo',
|
|
114
|
+
'onresize',
|
|
115
|
+
'onscroll',
|
|
116
|
+
'onseeked',
|
|
117
|
+
'onseeking',
|
|
118
|
+
'onselect',
|
|
119
|
+
'onstalled',
|
|
120
|
+
'onstorage',
|
|
121
|
+
'onsuspend',
|
|
122
|
+
'ontimeupdate',
|
|
123
|
+
'onundo',
|
|
124
|
+
'onunload',
|
|
125
|
+
'onvolumechange',
|
|
126
|
+
'onwaiting',
|
|
127
|
+
'onmouseenter',
|
|
128
|
+
'onmouseleave',
|
|
129
|
+
'onstart',
|
|
130
|
+
'onpropertychange',
|
|
131
|
+
'oncopy',
|
|
132
|
+
'ontoggle',
|
|
133
|
+
'onpointerout',
|
|
134
|
+
'onpointermove',
|
|
135
|
+
'onpointerleave',
|
|
136
|
+
'onpointerenter',
|
|
137
|
+
'onpointerrawupdate',
|
|
138
|
+
'onpointerover',
|
|
139
|
+
'onbeforecopy',
|
|
140
|
+
'onbeforecut',
|
|
141
|
+
'onbeforeinput'
|
|
142
|
+
];
|
|
143
|
+
export class SanitizeHtmlHelper {
|
|
144
|
+
public static removeAttrs: SanitizeRemoveAttrs[];
|
|
145
|
+
public static removeTags: string[];
|
|
146
|
+
public static wrapElement: HTMLElement;
|
|
147
|
+
public static beforeSanitize(): BeforeSanitizeHtml {
|
|
148
|
+
return {
|
|
149
|
+
selectors: {
|
|
150
|
+
tags: removeTags,
|
|
151
|
+
attributes: removeAttrs
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
public static sanitize(value: string): string {
|
|
156
|
+
if (isNullOrUndefined(value)) { return value; }
|
|
157
|
+
const item: BeforeSanitizeHtml = this.beforeSanitize();
|
|
158
|
+
const output: string = this.serializeValue(item, value);
|
|
159
|
+
return output;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public static serializeValue(item: BeforeSanitizeHtml, value: string): string {
|
|
163
|
+
this.removeAttrs = item.selectors.attributes;
|
|
164
|
+
this.removeTags = item.selectors.tags;
|
|
165
|
+
this.wrapElement = document.createElement('div');
|
|
166
|
+
this.wrapElement.innerHTML = value;
|
|
167
|
+
this.removeXssTags();
|
|
168
|
+
this.removeJsEvents();
|
|
169
|
+
this.removeXssAttrs();
|
|
170
|
+
const tempEleValue: string = this.wrapElement.innerHTML;
|
|
171
|
+
this.removeElement();
|
|
172
|
+
this.wrapElement = null;
|
|
173
|
+
return tempEleValue.replace(/&/g, '&');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private static removeElement(): void {
|
|
177
|
+
// Removes an element's attibute to avoid html tag validation
|
|
178
|
+
const nodes: HTMLCollection = this.wrapElement.children;
|
|
179
|
+
for (let j: number = 0; j < nodes.length; j++) {
|
|
180
|
+
const attribute: NamedNodeMap = nodes[parseInt(j.toString(), 10)].attributes;
|
|
181
|
+
for (let i: number = 0; i < attribute.length; i++) {
|
|
182
|
+
this.wrapElement.children[parseInt(j.toString(), 10)].removeAttribute(attribute[parseInt(i.toString(), 10)].localName);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private static removeXssTags(): void {
|
|
188
|
+
const elements: NodeListOf<HTMLElement> = this.wrapElement.querySelectorAll(this.removeTags.join(','));
|
|
189
|
+
if (elements.length > 0) {
|
|
190
|
+
elements.forEach((element: Element) => {
|
|
191
|
+
detach(element);
|
|
192
|
+
});
|
|
193
|
+
} else {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private static removeJsEvents(): void {
|
|
199
|
+
const elements: NodeListOf<HTMLElement> = this.wrapElement.querySelectorAll('[' + jsEvents.join('],[') + ']');
|
|
200
|
+
if (elements.length > 0) {
|
|
201
|
+
elements.forEach((element: Element) => {
|
|
202
|
+
jsEvents.forEach((attr: string) => {
|
|
203
|
+
if (element.hasAttribute(attr)) {
|
|
204
|
+
element.removeAttribute(attr);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
} else {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private static removeXssAttrs(): void {
|
|
214
|
+
// eslint-disable-next-line
|
|
215
|
+
this.removeAttrs.forEach((item: { [key: string]: string }, index: number) => {
|
|
216
|
+
const elements: NodeListOf<HTMLElement> = this.wrapElement.querySelectorAll(item.selector);
|
|
217
|
+
if (elements.length > 0) {
|
|
218
|
+
elements.forEach((element: Element) => {
|
|
219
|
+
element.removeAttribute(item.attribute);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Engine Bridge
|
|
3
|
+
*/
|
|
4
|
+
import { compile as render } from './template';
|
|
5
|
+
import { createElement } from './dom';
|
|
6
|
+
import { isNullOrUndefined, isBlazor } from './util';
|
|
7
|
+
|
|
8
|
+
const HAS_ROW: RegExp = /^[\n\r.]+<tr|^<tr/;
|
|
9
|
+
const HAS_SVG: RegExp = /^[\n\r.]+<svg|^<path|^<g/;
|
|
10
|
+
export const blazorTemplates: object = {};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @returns {string} ?
|
|
15
|
+
*/
|
|
16
|
+
export function getRandomId(): string {
|
|
17
|
+
|
|
18
|
+
return '-' + Math.random().toString(36).substr(2, 5);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Interface for Template Engine.
|
|
23
|
+
*/
|
|
24
|
+
export interface ITemplateEngine {
|
|
25
|
+
compile: (templateString: string | Function, helper?: Object, ignorePrefix?: boolean) => (data: Object | JSON) => string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Compile the template string into template function.
|
|
30
|
+
*
|
|
31
|
+
* @param {string | Function} templateString - The template string which is going to convert.
|
|
32
|
+
* @param {Object} helper - Helper functions as an object.
|
|
33
|
+
* @param {boolean} ignorePrefix ?
|
|
34
|
+
* @returns {NodeList} ?
|
|
35
|
+
* @private
|
|
36
|
+
*/
|
|
37
|
+
// eslint-disable-next-line
|
|
38
|
+
export function compile(templateString: string | Function, helper?: Object, ignorePrefix?:boolean): (data: Object | JSON, component?: any, propName?: any) => NodeList {
|
|
39
|
+
const compiler: Function = engineObj.compile(templateString, helper, ignorePrefix);
|
|
40
|
+
// eslint-disable-next-line
|
|
41
|
+
return (data: Object, component?: any, propName?: any, templateId?: any, isStringTemplate?: boolean, index?: number, element?: any, root?: any): NodeList => {
|
|
42
|
+
const result: object = compiler(data, component, propName, element, root);
|
|
43
|
+
const blazorTemplateId: string = 'BlazorTemplateId';
|
|
44
|
+
if (isBlazor() && !isStringTemplate) {
|
|
45
|
+
const randomId: string = getRandomId();
|
|
46
|
+
let blazorId: string = templateId + randomId;
|
|
47
|
+
if (!blazorTemplates[`${templateId}`]) {
|
|
48
|
+
blazorTemplates[`${templateId}`] = [];
|
|
49
|
+
}
|
|
50
|
+
if (!isNullOrUndefined(index)) {
|
|
51
|
+
const keys: string[] = Object.keys(blazorTemplates[`${templateId}`][parseInt(index.toString(), 10)]);
|
|
52
|
+
for (const key of keys) {
|
|
53
|
+
if (key !== blazorTemplateId && data[`${key}`]) {
|
|
54
|
+
blazorTemplates[`${templateId}`][parseInt(index.toString(), 10)][`${key}`] = data[`${key}`];
|
|
55
|
+
}
|
|
56
|
+
if (key === blazorTemplateId) {
|
|
57
|
+
blazorId = blazorTemplates[`${templateId}`][parseInt(index.toString(), 10)][`${key}`];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
data[`${blazorTemplateId}`] = blazorId;
|
|
62
|
+
blazorTemplates[`${templateId}`].push(data);
|
|
63
|
+
}
|
|
64
|
+
// eslint-disable-next-line
|
|
65
|
+
return propName === 'rowTemplate' ? [createElement('tr', { id: blazorId, className: 'e-blazor-template' })] as any :
|
|
66
|
+
// eslint-disable-next-line
|
|
67
|
+
[createElement('div', { id: blazorId, className: 'e-blazor-template' })] as any;
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
if (typeof result === 'string') {
|
|
71
|
+
if (HAS_SVG.test(result)) {
|
|
72
|
+
const ele: HTMLElement = createElement('svg', { innerHTML: result });
|
|
73
|
+
return <NodeList>ele.childNodes;
|
|
74
|
+
} else {
|
|
75
|
+
const ele: HTMLElement = createElement((HAS_ROW.test(result) ? 'table' : 'div'), { innerHTML: result });
|
|
76
|
+
return <NodeList>ele.childNodes;
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
return <NodeList>result;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
*
|
|
86
|
+
* @param {string} templateId ?
|
|
87
|
+
* @param {string} templateName ?
|
|
88
|
+
* @param {string} comp ?
|
|
89
|
+
* @param {boolean} isEmpty ?
|
|
90
|
+
* @param {Function} callBack ?
|
|
91
|
+
* @returns {void} ?
|
|
92
|
+
*/
|
|
93
|
+
export function updateBlazorTemplate(
|
|
94
|
+
templateId?: string, templateName?: string, comp?: object,
|
|
95
|
+
isEmpty?: boolean, callBack?: Function): void {
|
|
96
|
+
if (isBlazor()) {
|
|
97
|
+
const ejsIntrop: string = 'sfBlazor';
|
|
98
|
+
window[`${ejsIntrop}`].updateTemplate(templateName, blazorTemplates[`${templateId}`], templateId, comp, callBack);
|
|
99
|
+
if (isEmpty !== false) {
|
|
100
|
+
blazorTemplates[`${templateId}`] = [];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
* @param {string} templateId ?
|
|
108
|
+
* @param {string} templateName ?
|
|
109
|
+
* @param {number} index ?
|
|
110
|
+
* @returns {void} ?
|
|
111
|
+
*/
|
|
112
|
+
export function resetBlazorTemplate(templateId?: string, templateName?: string, index?: number): void {
|
|
113
|
+
const templateDiv: HTMLElement = document.getElementById(templateId);
|
|
114
|
+
if (templateDiv) {
|
|
115
|
+
// eslint-disable-next-line
|
|
116
|
+
const innerTemplates: HTMLElement[] = templateDiv.getElementsByClassName('blazor-inner-template') as any;
|
|
117
|
+
for (let i: number = 0; i < innerTemplates.length; i++) {
|
|
118
|
+
let tempId: string = ' ';
|
|
119
|
+
if (!isNullOrUndefined(index)) {
|
|
120
|
+
tempId = innerTemplates[parseInt(index.toString(), 10)].getAttribute('data-templateId');
|
|
121
|
+
} else {
|
|
122
|
+
tempId = innerTemplates[parseInt(i.toString(), 10)].getAttribute('data-templateId');
|
|
123
|
+
}
|
|
124
|
+
const tempElement: HTMLElement = document.getElementById(tempId);
|
|
125
|
+
if (tempElement) {
|
|
126
|
+
const length: number = tempElement.childNodes.length;
|
|
127
|
+
for (let j: number = 0; j < length; j++) {
|
|
128
|
+
if (!isNullOrUndefined(index)) {
|
|
129
|
+
innerTemplates[parseInt(index.toString(), 10)].appendChild(tempElement.childNodes[0]);
|
|
130
|
+
i = innerTemplates.length;
|
|
131
|
+
} else {
|
|
132
|
+
innerTemplates[parseInt(i.toString(), 10)].appendChild(tempElement.childNodes[0]);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Set your custom template engine for template rendering.
|
|
143
|
+
*
|
|
144
|
+
* @param {ITemplateEngine} classObj - Class object for custom template.
|
|
145
|
+
* @returns {void} ?
|
|
146
|
+
* @private
|
|
147
|
+
*/
|
|
148
|
+
export function setTemplateEngine(classObj: ITemplateEngine): void {
|
|
149
|
+
engineObj.compile = classObj.compile;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get current template engine for template rendering
|
|
154
|
+
*
|
|
155
|
+
* @returns {string} ?
|
|
156
|
+
* @private
|
|
157
|
+
*/
|
|
158
|
+
export function getTemplateEngine(): (template: string, helper?: Object) => (data: Object | JSON) => string {
|
|
159
|
+
return engineObj.compile;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Set the current template function to support Content Security Policy.
|
|
164
|
+
*
|
|
165
|
+
* @param {Function} template - The template function that is going to render.
|
|
166
|
+
* @param {any} helper - The data utilized by the template from the helper.
|
|
167
|
+
* @returns {Function} ?
|
|
168
|
+
* @private
|
|
169
|
+
*/
|
|
170
|
+
// eslint-disable-next-line
|
|
171
|
+
export function initializeCSPTemplate (template : Function, helper?: any): Function {
|
|
172
|
+
let boundFunc : Function;
|
|
173
|
+
template.prototype.CSPTemplate = true;
|
|
174
|
+
if (!isNullOrUndefined(helper)) {
|
|
175
|
+
boundFunc = template.bind(helper);
|
|
176
|
+
boundFunc.prototype = Object.create(template.prototype);
|
|
177
|
+
} else {
|
|
178
|
+
boundFunc = template;
|
|
179
|
+
}
|
|
180
|
+
return boundFunc;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
//Default Engine Class
|
|
184
|
+
class Engine implements ITemplateEngine {
|
|
185
|
+
// eslint-disable-next-line
|
|
186
|
+
public compile(templateString: string, helper: Object = {}, ignorePrefix?:boolean): (data: Object | JSON) => string {
|
|
187
|
+
return render(templateString, helper);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const engineObj: ITemplateEngine = { compile: new Engine().compile };
|