@kwiz/common 1.0.2 → 1.0.3
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/package.json +1 -1
- package/src/_dependencies.ts +0 -2
- package/src/helpers/Guid.ts +0 -182
- package/src/helpers/_dependencies.ts +0 -3
- package/src/helpers/base64.ts +0 -174
- package/src/helpers/browser.test.js +0 -9
- package/src/helpers/browser.ts +0 -1299
- package/src/helpers/browserinfo.ts +0 -293
- package/src/helpers/collections.base.test.js +0 -26
- package/src/helpers/collections.base.ts +0 -439
- package/src/helpers/collections.ts +0 -108
- package/src/helpers/color.ts +0 -55
- package/src/helpers/cookies.ts +0 -55
- package/src/helpers/date.test.js +0 -97
- package/src/helpers/date.ts +0 -163
- package/src/helpers/debug.ts +0 -187
- package/src/helpers/emails.ts +0 -7
- package/src/helpers/eval.ts +0 -5
- package/src/helpers/file.test.js +0 -51
- package/src/helpers/file.ts +0 -59
- package/src/helpers/flatted.ts +0 -150
- package/src/helpers/functions.ts +0 -17
- package/src/helpers/graph/calendar.types.ts +0 -11
- package/src/helpers/http.ts +0 -70
- package/src/helpers/images.ts +0 -23
- package/src/helpers/index.ts +0 -29
- package/src/helpers/json.ts +0 -39
- package/src/helpers/md5.ts +0 -190
- package/src/helpers/objects.test.js +0 -27
- package/src/helpers/objects.ts +0 -256
- package/src/helpers/promises.test.js +0 -18
- package/src/helpers/promises.ts +0 -102
- package/src/helpers/random.ts +0 -27
- package/src/helpers/scheduler/scheduler.test.js +0 -104
- package/src/helpers/scheduler/scheduler.ts +0 -132
- package/src/helpers/sharepoint.ts +0 -681
- package/src/helpers/strings.test.js +0 -43
- package/src/helpers/strings.ts +0 -288
- package/src/helpers/typecheckers.test.js +0 -35
- package/src/helpers/typecheckers.ts +0 -263
- package/src/helpers/url.test.js +0 -18
- package/src/helpers/url.ts +0 -202
- package/src/helpers/urlhelper.ts +0 -104
- package/src/index.ts +0 -24
- package/src/types/common.types.ts +0 -16
- package/src/types/flatted.types.ts +0 -60
- package/src/types/globals.types.ts +0 -7
- package/src/types/graph/calendar.types.ts +0 -81
- package/src/types/graph/index.ts +0 -1
- package/src/types/index.ts +0 -12
- package/src/types/knownscript.types.ts +0 -19
- package/src/types/libs/datajs.types.ts +0 -29
- package/src/types/libs/ics.types.ts +0 -31
- package/src/types/libs/index.ts +0 -4
- package/src/types/libs/msal.types.ts +0 -79
- package/src/types/locales.ts +0 -125
- package/src/types/localstoragecache.types.ts +0 -9
- package/src/types/moment.ts +0 -7
- package/src/types/regex.types.ts +0 -17
- package/src/types/rest.types.ts +0 -94
- package/src/types/sharepoint.types.ts +0 -1413
- package/src/types/sharepoint.utils.types.ts +0 -246
- package/src/utils/_dependencies.ts +0 -4
- package/src/utils/base64.ts +0 -27
- package/src/utils/consolelogger.ts +0 -315
- package/src/utils/date.ts +0 -36
- package/src/utils/emails.ts +0 -25
- package/src/utils/index.ts +0 -13
- package/src/utils/knownscript.ts +0 -280
- package/src/utils/localstoragecache.ts +0 -419
- package/src/utils/rest.ts +0 -465
- package/src/utils/script.ts +0 -168
- package/src/utils/sharepoint.rest/common.ts +0 -149
- package/src/utils/sharepoint.rest/date.ts +0 -61
- package/src/utils/sharepoint.rest/file.folder.ts +0 -368
- package/src/utils/sharepoint.rest/index.ts +0 -11
- package/src/utils/sharepoint.rest/item.ts +0 -456
- package/src/utils/sharepoint.rest/list.ts +0 -1144
- package/src/utils/sharepoint.rest/listutils/GetListItemsByCaml.ts +0 -750
- package/src/utils/sharepoint.rest/listutils/GetListItemsById.ts +0 -265
- package/src/utils/sharepoint.rest/listutils/common.ts +0 -202
- package/src/utils/sharepoint.rest/user-search.ts +0 -254
- package/src/utils/sharepoint.rest/user.ts +0 -447
- package/src/utils/sharepoint.rest/web.ts +0 -1031
- package/src/utils/sod.ts +0 -193
- package/tsconfig.json +0 -21
package/src/helpers/browser.ts
DELETED
|
@@ -1,1299 +0,0 @@
|
|
|
1
|
-
import { IDictionary } from "./_dependencies";
|
|
2
|
-
import { firstIndexOf } from "./collections.base";
|
|
3
|
-
import { LOGO_ANIM } from "./images";
|
|
4
|
-
import { getUniqueId } from "./random";
|
|
5
|
-
import { stripRichTextWhitespace } from "./strings";
|
|
6
|
-
import { isBoolean, isFunction, isNullOrEmptyArray, isNullOrEmptyString, isNullOrUndefined, isNumber, isNumeric, isString, isTypeofFullNameNullOrUndefined, isUndefined } from "./typecheckers";
|
|
7
|
-
|
|
8
|
-
export function triggerNativeEvent(ele: HTMLElement | Element | Document, eventName: string) {
|
|
9
|
-
if (isNullOrUndefined(ele)) {
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
if (!isNullOrUndefined((ele as any).fireEvent)) { // < IE9
|
|
13
|
-
(ele as any).fireEvent('on' + eventName);
|
|
14
|
-
} else {
|
|
15
|
-
// Different events have different event classes.
|
|
16
|
-
// If this switch statement can't map an eventName to an eventClass,
|
|
17
|
-
// the event firing is going to fail.
|
|
18
|
-
let eventClass = "Events";
|
|
19
|
-
switch (eventName) {
|
|
20
|
-
case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead.
|
|
21
|
-
case "mousedown":
|
|
22
|
-
case "mouseup":
|
|
23
|
-
eventClass = "MouseEvents";
|
|
24
|
-
break;
|
|
25
|
-
|
|
26
|
-
case "focus":
|
|
27
|
-
case "change":
|
|
28
|
-
case "blur":
|
|
29
|
-
case "select":
|
|
30
|
-
eventClass = "HTMLEvents";
|
|
31
|
-
break;
|
|
32
|
-
|
|
33
|
-
default:
|
|
34
|
-
eventClass = "CustomEvent";
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
var evt = document.createEvent(eventClass);
|
|
39
|
-
evt.initEvent(eventName, true, true);
|
|
40
|
-
ele.dispatchEvent(evt);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function addEventHandler(elm: HTMLElement | Element | Document | Window, event: string, handler: EventListenerOrEventListenerObject) {
|
|
45
|
-
if (isUndefined(elm.addEventListener))//IE8
|
|
46
|
-
(elm as any).attachEvent("on" + event, handler);
|
|
47
|
-
else
|
|
48
|
-
elm.addEventListener(event, handler, false);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** prompts user to save/download a text file */
|
|
52
|
-
export function saveFile(fileName: string, fileData: string, type: "application/json" | "text/csv") {
|
|
53
|
-
//Issue 6003
|
|
54
|
-
let blobObject = new Blob([fileData], { type: `${type};charset=utf-8;` });
|
|
55
|
-
|
|
56
|
-
if (window.Blob && window.navigator["msSaveOrOpenBlob"]) {
|
|
57
|
-
//edge/IE
|
|
58
|
-
window.navigator["msSaveOrOpenBlob"](blobObject, fileName);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
//Issue 6025
|
|
62
|
-
//var encodedUri = `data:${type};charset=utf-8,` + encodeURIComponent(fileData);
|
|
63
|
-
|
|
64
|
-
let link = document.getElementById('kwizcom_download_link_tmp') as HTMLAnchorElement;
|
|
65
|
-
if (link) {
|
|
66
|
-
link.remove();
|
|
67
|
-
link = null;
|
|
68
|
-
}
|
|
69
|
-
var url = URL.createObjectURL(blobObject);
|
|
70
|
-
if (!link) {
|
|
71
|
-
link = document.createElement("a");
|
|
72
|
-
link.style.position = "fixed";
|
|
73
|
-
link.style.top = "-200px";
|
|
74
|
-
link.download = fileName;
|
|
75
|
-
link.innerHTML = "Click Here to download";
|
|
76
|
-
DisableAnchorIntercept(link);
|
|
77
|
-
link.id = "kwizcom_download_link_tmp";
|
|
78
|
-
document.body.appendChild(link); // Required for FF
|
|
79
|
-
link.href = url;
|
|
80
|
-
}
|
|
81
|
-
window.setTimeout(() => {
|
|
82
|
-
link.click();
|
|
83
|
-
}, 200);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** force browser to download instead of opening a file */
|
|
88
|
-
export function downloadFile(url: string) {
|
|
89
|
-
var link = document.createElement('a');
|
|
90
|
-
link.href = url;
|
|
91
|
-
var parts = link.href.replace(/\\/g, "/").split('/');
|
|
92
|
-
var fileName = parts[parts.length - 1];
|
|
93
|
-
link.download = fileName;
|
|
94
|
-
DisableAnchorIntercept(link);
|
|
95
|
-
document.body.appendChild(link);
|
|
96
|
-
link.click();
|
|
97
|
-
document.body.removeChild(link);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function copyTextToClipboard(text: string): boolean {
|
|
101
|
-
var input = document.createElement("input");
|
|
102
|
-
input.value = text;
|
|
103
|
-
input.style.position = "absolute";
|
|
104
|
-
input.style.top = "-100px";
|
|
105
|
-
input.style.left = "-100px";
|
|
106
|
-
document.body.appendChild(input);
|
|
107
|
-
let copied = copyToClipboard(input);
|
|
108
|
-
input.remove();
|
|
109
|
-
return copied;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/** copies the text of an element to the clipboard. if not supported by browser - will return false so caller must check and show
|
|
113
|
-
* a message to the user asking him to hit ctrl+c
|
|
114
|
-
*/
|
|
115
|
-
export function copyToClipboard(el: HTMLElement): boolean {
|
|
116
|
-
// Copy textarea, pre, div, etc.
|
|
117
|
-
if ((document.body as any).createTextRange) {
|
|
118
|
-
// IE
|
|
119
|
-
var textRange = (document.body as any).createTextRange();
|
|
120
|
-
textRange.moveToElementText(el);
|
|
121
|
-
textRange.select();
|
|
122
|
-
textRange.execCommand("Copy");
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
else if (window.getSelection && document.createRange) {
|
|
126
|
-
// non-IE
|
|
127
|
-
var editable = el.contentEditable; // Record contentEditable status of element
|
|
128
|
-
var readOnly = (el as any).readOnly; // Record readOnly status of element
|
|
129
|
-
(el as any).contentEditable = true; // iOS will only select text on non-form elements if contentEditable = true;
|
|
130
|
-
(el as any).readOnly = false; // iOS will not select in a read only form element
|
|
131
|
-
var range = document.createRange();
|
|
132
|
-
range.selectNodeContents(el);
|
|
133
|
-
var sel = window.getSelection();
|
|
134
|
-
sel.removeAllRanges();
|
|
135
|
-
sel.addRange(range); // Does not work for Firefox if a textarea or input
|
|
136
|
-
if (el.nodeName === "TEXTAREA" || el.nodeName === "INPUT")
|
|
137
|
-
(el as HTMLInputElement).select(); // Firefox will only select a form element with select()
|
|
138
|
-
if ((el as any).setSelectionRange && navigator.userAgent.match(/ipad|ipod|iphone/i))
|
|
139
|
-
(el as any).setSelectionRange(0, 999999); // iOS only selects "form" elements with SelectionRange
|
|
140
|
-
(el as any).contentEditable = editable; // Restore previous contentEditable status
|
|
141
|
-
(el as any).readOnly = readOnly; // Restore previous readOnly status
|
|
142
|
-
if (document.queryCommandSupported("copy")) {
|
|
143
|
-
var successful = document.execCommand('copy');
|
|
144
|
-
if (successful) return true;
|
|
145
|
-
else return false;
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
if (!navigator.userAgent.match(/ipad|ipod|iphone|android|silk/i))
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/** wraps the html in a div element and returns it */
|
|
156
|
-
export function elementFromHtml(html: string) {
|
|
157
|
-
var d = document.createElement("div");
|
|
158
|
-
d.innerHTML = html;
|
|
159
|
-
return <HTMLDivElement>d;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export function HtmlTextContents(htmlElement: string | HTMLElement) {
|
|
163
|
-
let innerText = (isString(htmlElement) ? elementFromHtml(htmlElement) : htmlElement).innerText;
|
|
164
|
-
return stripRichTextWhitespace(innerText.replace(/\n/g, " ").replace(/ {2}/g, " "));
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export function registerDOMContentLoadedListener(doc?: Document) {
|
|
168
|
-
return new Promise<void>((resolve, reject) => {
|
|
169
|
-
doc = doc || document;
|
|
170
|
-
|
|
171
|
-
if (isNullOrUndefined(doc)) {
|
|
172
|
-
reject();
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (!isNullOrUndefined(doc) && doc.readyState === "loading") {
|
|
177
|
-
doc.addEventListener("DOMContentLoaded", () => {
|
|
178
|
-
resolve();
|
|
179
|
-
});
|
|
180
|
-
} else {
|
|
181
|
-
resolve();
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export function registerDocumentLoadComplete(doc?: Document) {
|
|
187
|
-
return new Promise<void>((resolve, reject) => {
|
|
188
|
-
doc = doc || document;
|
|
189
|
-
|
|
190
|
-
if (isNullOrUndefined(doc) || !isFunction(doc.addEventListener)) {
|
|
191
|
-
reject();
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (doc.readyState === "complete") {
|
|
196
|
-
resolve();
|
|
197
|
-
} else {
|
|
198
|
-
doc.addEventListener("readystatechange", () => {
|
|
199
|
-
if (doc.readyState === "complete") {
|
|
200
|
-
resolve();
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/** on modern experience, using navagation does inplace-page update.
|
|
208
|
-
* document ready, and all windows events will not trigger and global objects will remain.
|
|
209
|
-
* our app loader will fire this event when the page does that navigation so we can hook up to be notified.
|
|
210
|
-
*/
|
|
211
|
-
export function registerModernInplaceNavigationOnInit(handler: () => void) {
|
|
212
|
-
addEventHandler(document, "kwOnInit", handler);
|
|
213
|
-
}
|
|
214
|
-
/** Triggers handler when theme changes on a modern page
|
|
215
|
-
* When the user changes the site's theme, or when navigating to a sub-site, or clicking back
|
|
216
|
-
* in the browser navigating back to parent site with different theme
|
|
217
|
-
*/
|
|
218
|
-
export function registerModernThemeChanged(handler: () => void) {
|
|
219
|
-
addEventHandler(document, "kwOnThemeChanged", handler);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
type DOMChangedObserverDef = {
|
|
223
|
-
ele: HTMLElement;
|
|
224
|
-
callbacks: { handler: () => void; key?: string; }[];
|
|
225
|
-
disconnect?: () => void;
|
|
226
|
-
};
|
|
227
|
-
let _DOMChangedObserverDefs: DOMChangedObserverDef[] = [];
|
|
228
|
-
|
|
229
|
-
function _getDOMChangedObserverDef(ele: HTMLElement) {
|
|
230
|
-
if (!isElement(ele)) {
|
|
231
|
-
return null;
|
|
232
|
-
}
|
|
233
|
-
let existingDef = _DOMChangedObserverDefs.filter((observer) => {
|
|
234
|
-
let observerEle = observer.ele;
|
|
235
|
-
return isElement(observerEle) && observerEle.isSameNode(ele);
|
|
236
|
-
})[0];
|
|
237
|
-
return existingDef;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function _getDomObserverCallbackInfo(callbackOrHandler: (() => void) | { key: string; handler?: () => void; }) {
|
|
241
|
-
return {
|
|
242
|
-
handler: isNullOrUndefined(callbackOrHandler) ? null : isFunction(callbackOrHandler) ? callbackOrHandler : callbackOrHandler.handler,
|
|
243
|
-
key: isNullOrUndefined(callbackOrHandler) || isFunction(callbackOrHandler) ? null : callbackOrHandler.key
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export function registerDOMChangedObserver(callbackOrHandler: (() => void) | { key: string; handler: () => void; },
|
|
249
|
-
ele?: HTMLElement) {
|
|
250
|
-
let callbackInfo = _getDomObserverCallbackInfo(callbackOrHandler);
|
|
251
|
-
if (!isFunction(callbackInfo.handler)) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
var win: Window & typeof globalThis;
|
|
256
|
-
var doc: Document;
|
|
257
|
-
|
|
258
|
-
if (ele) {
|
|
259
|
-
try {
|
|
260
|
-
doc = ele.ownerDocument;
|
|
261
|
-
win = doc.defaultView || (doc as any).parentWindow;
|
|
262
|
-
} catch (ex) {
|
|
263
|
-
}
|
|
264
|
-
} else {
|
|
265
|
-
win = window;
|
|
266
|
-
doc = window && window.document;
|
|
267
|
-
ele = doc.body;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (isNullOrUndefined(win) || isNullOrUndefined(doc)) {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
registerDOMContentLoadedListener(win.document).then(() => {
|
|
275
|
-
let existingDef = _getDOMChangedObserverDef(ele);
|
|
276
|
-
|
|
277
|
-
if (!isNullOrUndefined(existingDef)) {
|
|
278
|
-
let existingCallbackIndex = isNullOrEmptyString(callbackInfo.key) ? -1 : firstIndexOf(existingDef.callbacks, cb => cb.key === callbackInfo.key);
|
|
279
|
-
if (existingCallbackIndex >= 0) {
|
|
280
|
-
//replace
|
|
281
|
-
existingDef.callbacks[existingCallbackIndex].handler = callbackInfo.handler;
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
existingDef.callbacks.push(callbackInfo);
|
|
285
|
-
}
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
let newDef: DOMChangedObserverDef = {
|
|
290
|
-
ele: ele,
|
|
291
|
-
callbacks: [callbackInfo]
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
let onDomChanged = debounce(() => {
|
|
295
|
-
if (!isNullOrUndefined(newDef) && !isNullOrEmptyArray(newDef.callbacks)) {
|
|
296
|
-
newDef.callbacks.forEach((c) => {
|
|
297
|
-
try {
|
|
298
|
-
c.handler();
|
|
299
|
-
} catch (e) { }
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
}, 100);
|
|
303
|
-
|
|
304
|
-
if ("MutationObserver" in win) {
|
|
305
|
-
let observer: MutationObserver = new win.MutationObserver((mutations) => {
|
|
306
|
-
let hasUpdates = mutations.some((mutation) => {
|
|
307
|
-
return !!mutation.addedNodes && !!mutation.addedNodes.length
|
|
308
|
-
|| !!mutation.removedNodes && !!mutation.removedNodes.length;
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
if (hasUpdates) {
|
|
312
|
-
onDomChanged();
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
observer.observe(ele, {
|
|
317
|
-
childList: true,
|
|
318
|
-
subtree: true,
|
|
319
|
-
attributes: false,
|
|
320
|
-
characterData: false
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
newDef.disconnect = () => {
|
|
324
|
-
observer.disconnect();
|
|
325
|
-
observer = null;
|
|
326
|
-
};
|
|
327
|
-
} else {
|
|
328
|
-
let domEvents = ["DOMNodeInsertedIntoDocument", "DOMNodeRemovedFromDocument"];
|
|
329
|
-
|
|
330
|
-
domEvents.forEach((eventName) => {
|
|
331
|
-
newDef.ele.addEventListener(eventName, onDomChanged, false);
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
newDef.disconnect = () => {
|
|
335
|
-
domEvents.forEach((eventName) => {
|
|
336
|
-
newDef.ele.removeEventListener(eventName, onDomChanged, false);
|
|
337
|
-
});
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
_DOMChangedObserverDefs.push(newDef);
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
export function removeDOMChangedObserver(callbackOrHandler: (() => void) | { key: string; handler?: () => void; }, ele?: HTMLElement) {
|
|
346
|
-
let callbackInfo = _getDomObserverCallbackInfo(callbackOrHandler);
|
|
347
|
-
if (!isFunction(callbackInfo.handler) && isNullOrEmptyString(callbackInfo.key)) {
|
|
348
|
-
return;//need function or key to remove
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
var win: Window;
|
|
352
|
-
var doc: Document;
|
|
353
|
-
|
|
354
|
-
if (ele) {
|
|
355
|
-
try {
|
|
356
|
-
doc = ele.ownerDocument;
|
|
357
|
-
win = doc.defaultView || (doc as any).parentWindow;
|
|
358
|
-
} catch (ex) {
|
|
359
|
-
}
|
|
360
|
-
} else {
|
|
361
|
-
win = window;
|
|
362
|
-
doc = window && window.document;
|
|
363
|
-
ele = doc.body;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
if (isNullOrUndefined(win) || isNullOrUndefined(doc)) {
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
registerDOMContentLoadedListener(win.document).then(() => {
|
|
371
|
-
let existingDef = _getDOMChangedObserverDef(ele);
|
|
372
|
-
|
|
373
|
-
if (isNullOrUndefined(existingDef) || !isElement(existingDef.ele)) {
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
if (!isNullOrEmptyString(callbackInfo.key))//find by key
|
|
378
|
-
{
|
|
379
|
-
existingDef.callbacks = existingDef.callbacks.filter((cb) => {
|
|
380
|
-
return cb.key !== callbackInfo.key;
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
else//find by handler - probably won't work for functions that are declared inline
|
|
384
|
-
{
|
|
385
|
-
existingDef.callbacks = existingDef.callbacks.filter((cb) => {
|
|
386
|
-
return isNullOrEmptyString(cb.key) && cb.handler !== callbackInfo.handler;
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (existingDef.callbacks.length === 0) {
|
|
391
|
-
existingDef.disconnect();
|
|
392
|
-
_DOMChangedObserverDefs = _DOMChangedObserverDefs.filter((def) => {
|
|
393
|
-
return def !== existingDef;
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
export function isElementVisible(ele: HTMLElement) {
|
|
400
|
-
//must be a valid element
|
|
401
|
-
if (!isElement(ele) || !ele.getAttribute) {
|
|
402
|
-
return false;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
try {
|
|
406
|
-
var doc = ele.ownerDocument;
|
|
407
|
-
var win = doc.defaultView || (doc as any).parentWindow;
|
|
408
|
-
|
|
409
|
-
var computed = win.getComputedStyle(ele);
|
|
410
|
-
|
|
411
|
-
return !!(computed.display.toLowerCase() !== "none"
|
|
412
|
-
&& computed.visibility.toLowerCase() !== "hidden"
|
|
413
|
-
&& (ele.offsetWidth !== 0
|
|
414
|
-
|| ele.offsetHeight !== 0
|
|
415
|
-
|| ele.offsetParent !== null
|
|
416
|
-
|| ele.getClientRects().length));
|
|
417
|
-
|
|
418
|
-
} catch (ex) {
|
|
419
|
-
}
|
|
420
|
-
return false;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
export function querySelectorAllFirstOrNull(selectors: string | string[], maintainOrder = false) {
|
|
424
|
-
if (isNullOrUndefined(selectors)) {
|
|
425
|
-
return null;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (maintainOrder) {
|
|
429
|
-
return (querySelectorAllMaintainOrder(selectors)[0] || null);
|
|
430
|
-
} else {
|
|
431
|
-
var result =
|
|
432
|
-
isString(selectors) && !isNullOrEmptyString(selectors) ? document.querySelectorAll(selectors as string)[0] :
|
|
433
|
-
Array.isArray(selectors) ? document.querySelectorAll((selectors as string[]).join(","))[0] : null;
|
|
434
|
-
|
|
435
|
-
return (result || null);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
export function querySelectorAllMaintainOrder(selectors: string | string[], parent?: HTMLElement | Document | Element) {
|
|
440
|
-
if (isNullOrUndefined(selectors)) {
|
|
441
|
-
return null;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
var query: string[];
|
|
445
|
-
|
|
446
|
-
if (isString(selectors) && !isNullOrEmptyString(selectors)) {
|
|
447
|
-
query = (selectors as string).split(",");
|
|
448
|
-
}
|
|
449
|
-
if (Array.isArray(selectors)) {
|
|
450
|
-
query = selectors as string[];
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
var eles: HTMLElement[] = [];
|
|
454
|
-
|
|
455
|
-
parent = parent || document;
|
|
456
|
-
|
|
457
|
-
query.forEach((selector) => {
|
|
458
|
-
if (isString(selector) && !isNullOrEmptyString(selector)) {
|
|
459
|
-
var result = Array.prototype.slice.call(parent.querySelectorAll(selector)) as HTMLElement[];
|
|
460
|
-
eles = eles.concat(result);
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
return eles;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
export function getScrollParent(node: HTMLElement): HTMLElement {
|
|
468
|
-
if (node === null) {
|
|
469
|
-
return null;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
if (node.scrollHeight > node.clientHeight) {
|
|
473
|
-
return node;
|
|
474
|
-
} else {
|
|
475
|
-
return getScrollParent((node as Node).parentNode as HTMLElement);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
var _scrollbarWidth = -1;
|
|
480
|
-
export function getScrollbarWidth() {
|
|
481
|
-
if (_scrollbarWidth < 0) {
|
|
482
|
-
var outer = document.createElement("div");
|
|
483
|
-
outer.style.visibility = "hidden";
|
|
484
|
-
outer.style.width = "100px";
|
|
485
|
-
outer.style["msOverflowStyle"] = "scrollbar"; // needed for WinJS apps
|
|
486
|
-
|
|
487
|
-
document.body.appendChild(outer);
|
|
488
|
-
|
|
489
|
-
var widthNoScroll = outer.offsetWidth;
|
|
490
|
-
// force scrollbars
|
|
491
|
-
outer.style.overflow = "scroll";
|
|
492
|
-
|
|
493
|
-
// add innerdiv
|
|
494
|
-
var inner = document.createElement("div");
|
|
495
|
-
inner.style.width = "100%";
|
|
496
|
-
outer.appendChild(inner);
|
|
497
|
-
|
|
498
|
-
var widthWithScroll = inner.offsetWidth;
|
|
499
|
-
|
|
500
|
-
// remove divs
|
|
501
|
-
outer.parentNode.removeChild(outer);
|
|
502
|
-
|
|
503
|
-
_scrollbarWidth = widthNoScroll - widthWithScroll;
|
|
504
|
-
}
|
|
505
|
-
return _scrollbarWidth;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
export function cumulativeOffset(element: HTMLElement) {
|
|
509
|
-
var top = 0, left = 0;
|
|
510
|
-
do {
|
|
511
|
-
top += element.offsetTop || 0;
|
|
512
|
-
left += element.offsetLeft || 0;
|
|
513
|
-
element = element.offsetParent as HTMLElement;
|
|
514
|
-
} while (element);
|
|
515
|
-
|
|
516
|
-
return {
|
|
517
|
-
top: top,
|
|
518
|
-
left: left
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
export function computedStyleToInlineStyle(elm: HTMLElement, options: { recursive?: boolean; removeClassNames?: boolean; } = { recursive: true, removeClassNames: true }) {
|
|
523
|
-
if (!elm) {
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
if (options.recursive && elm.children && elm.children.length) {
|
|
528
|
-
var children = <HTMLElement[]>Array.prototype.slice.call(elm.children);
|
|
529
|
-
children.forEach(child => {
|
|
530
|
-
computedStyleToInlineStyle(child, options);
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
var computedStyle = window.getComputedStyle(elm);
|
|
535
|
-
|
|
536
|
-
if (options.removeClassNames) {
|
|
537
|
-
elm.removeAttribute("class");
|
|
538
|
-
}
|
|
539
|
-
elm.setAttribute("style", computedStyle.cssText);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
export function getPageHidden(document: Document = window.document) {
|
|
543
|
-
var hiddenPropName;
|
|
544
|
-
if (typeof document.hidden !== "undefined") {
|
|
545
|
-
// Opera 12.10 and Firefox 18 and later support
|
|
546
|
-
hiddenPropName = "hidden";
|
|
547
|
-
} else if (typeof (document as any).msHidden !== "undefined") {
|
|
548
|
-
hiddenPropName = "msHidden";
|
|
549
|
-
|
|
550
|
-
} else if (typeof (document as any).webkitHidden !== "undefined") {
|
|
551
|
-
hiddenPropName = "webkitHidden";
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
return isString(hiddenPropName) ? document[hiddenPropName] : false;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
export function getAnimationFlags() {
|
|
558
|
-
var isSupported = false,
|
|
559
|
-
animationstring = 'animation',
|
|
560
|
-
keyframeprefix = '',
|
|
561
|
-
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
|
|
562
|
-
pfx = '',
|
|
563
|
-
elem = document.createElement('div');
|
|
564
|
-
|
|
565
|
-
if (elem.style.animationName !== undefined) {
|
|
566
|
-
isSupported = true;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
if (isSupported === false) {
|
|
570
|
-
for (var i = 0; i < domPrefixes.length; i++) {
|
|
571
|
-
if (elem.style[domPrefixes[i] + 'AnimationName'] !== undefined) {
|
|
572
|
-
pfx = domPrefixes[i];
|
|
573
|
-
animationstring = pfx + 'Animation';
|
|
574
|
-
keyframeprefix = '-' + pfx.toLowerCase() + '-';
|
|
575
|
-
isSupported = true;
|
|
576
|
-
break;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
return {
|
|
582
|
-
supported: isSupported,
|
|
583
|
-
animationName: animationstring,
|
|
584
|
-
keyFramePrefix: keyframeprefix,
|
|
585
|
-
prefix: pfx
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
export function getAnimationEndEventName() {
|
|
590
|
-
var animations = {
|
|
591
|
-
"animation": "animationend",
|
|
592
|
-
"OAnimation": "oAnimationEnd",
|
|
593
|
-
"MozAnimation": "animationend",
|
|
594
|
-
"WebkitAnimation": "webkitAnimationEnd"
|
|
595
|
-
};
|
|
596
|
-
|
|
597
|
-
var flags = getAnimationFlags();
|
|
598
|
-
|
|
599
|
-
if (flags.supported) {
|
|
600
|
-
return animations[flags.animationName];
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
export function isElement(ele: any): ele is HTMLElement {
|
|
605
|
-
return !isNullOrUndefined(ele) && (ele.nodeType === 1 || ele instanceof Element);
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
export function isNode(ele: Element | Node) {
|
|
609
|
-
return !isNullOrUndefined(ele) && ((ele.nodeName && ele.nodeType >= 1 && ele.nodeType <= 12) || ele instanceof Node);
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
export type ElementOrElemenctList = Element | HTMLElement | Element[] | HTMLElement[] | NodeListOf<HTMLElement> | NodeListOf<Element>;
|
|
613
|
-
|
|
614
|
-
function _eleOrSelectorToElementArray(eleOrSelector: string | ElementOrElemenctList) {
|
|
615
|
-
if (isNullOrUndefined(eleOrSelector)) {
|
|
616
|
-
return [];
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
var elements: HTMLElement[];
|
|
620
|
-
|
|
621
|
-
if (isString(eleOrSelector)) {
|
|
622
|
-
elements = Array.from(document.querySelectorAll(eleOrSelector) as NodeListOf<HTMLElement>);
|
|
623
|
-
} else if (isElement(eleOrSelector as Element)) {
|
|
624
|
-
elements = [eleOrSelector as HTMLElement];
|
|
625
|
-
} else if (Array.isArray(eleOrSelector)) {
|
|
626
|
-
elements = eleOrSelector as HTMLElement[];
|
|
627
|
-
} else if ((eleOrSelector as NodeListOf<HTMLElement>).length
|
|
628
|
-
|| isFunction((eleOrSelector as NodeListOf<HTMLElement>).forEach)
|
|
629
|
-
|| eleOrSelector instanceof NodeList) {
|
|
630
|
-
elements = Array.from(eleOrSelector as NodeList) as HTMLElement[];
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
return elements || [];
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
export function emptyHTMLElement(eleOrSelector: ElementOrElemenctList) {
|
|
637
|
-
var elements = _eleOrSelectorToElementArray(eleOrSelector);
|
|
638
|
-
|
|
639
|
-
elements.forEach((ele) => {
|
|
640
|
-
if (ele && isElement(ele as Element) && ele.firstChild) {
|
|
641
|
-
while (ele.firstChild) {
|
|
642
|
-
try {
|
|
643
|
-
ele.removeChild(ele.firstChild);
|
|
644
|
-
} catch (ex) {
|
|
645
|
-
break;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
export function removeHTMLElement(eleOrSelector: ElementOrElemenctList) {
|
|
653
|
-
var elements = _eleOrSelectorToElementArray(eleOrSelector);
|
|
654
|
-
|
|
655
|
-
elements.forEach((ele) => {
|
|
656
|
-
try {
|
|
657
|
-
var parent = ele.parentNode || ele.parentElement;
|
|
658
|
-
if (ele && isElement(ele as Element) && parent && parent.removeChild) {
|
|
659
|
-
parent.removeChild(ele);
|
|
660
|
-
}
|
|
661
|
-
} catch (ex) {
|
|
662
|
-
}
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
export function removeAttributeFromHTMLElements(eleOrSelector: ElementOrElemenctList, attributeName: string) {
|
|
667
|
-
var elements = _eleOrSelectorToElementArray(eleOrSelector);
|
|
668
|
-
|
|
669
|
-
elements.forEach((elm) => {
|
|
670
|
-
try {
|
|
671
|
-
elm.removeAttribute(attributeName);
|
|
672
|
-
} catch (ex) {
|
|
673
|
-
}
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
export function getSelectOptionByValue(selectElement: HTMLSelectElement, value: string) {
|
|
678
|
-
if (isNullOrUndefined(selectElement) || isNullOrUndefined(value)) {
|
|
679
|
-
return null;
|
|
680
|
-
}
|
|
681
|
-
var option = Array.from(selectElement.options).filter(o => {
|
|
682
|
-
return o.value === value.toString();
|
|
683
|
-
})[0];
|
|
684
|
-
|
|
685
|
-
return option;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
export function getSelectOptionByIndex(selectElement: HTMLSelectElement, index: number) {
|
|
689
|
-
if (isNullOrUndefined(selectElement) || !isNumeric(index)) {
|
|
690
|
-
return null;
|
|
691
|
-
}
|
|
692
|
-
return selectElement.options[Number(index)];
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
export function getSelectedOption(selectElement: HTMLSelectElement) {
|
|
696
|
-
if (isNullOrUndefined(selectElement)) {
|
|
697
|
-
return null;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
return selectElement.options[selectElement.selectedIndex] || Array.from(selectElement.options).filter((option) => {
|
|
701
|
-
return option.selected;
|
|
702
|
-
})[0];
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
export function setSelectOptionByValue(selectElement: HTMLSelectElement, value: string): HTMLOptionElement {
|
|
706
|
-
var option = getSelectOptionByValue(selectElement, value);
|
|
707
|
-
|
|
708
|
-
if (option) {
|
|
709
|
-
option.selected = true;
|
|
710
|
-
return option;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
return null;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
export function setSelectOptionByIndex(selectElement: HTMLSelectElement, index: number): HTMLOptionElement {
|
|
717
|
-
if (isNullOrUndefined(selectElement) || isNumeric(index)) {
|
|
718
|
-
return null;
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
var option = selectElement.options[Number(index)];
|
|
722
|
-
|
|
723
|
-
if (option) {
|
|
724
|
-
option.selected = true;
|
|
725
|
-
return option;
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
return null;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
export function composePath(evt: Event) {
|
|
732
|
-
var path = (isFunction(evt["composedPath"]) && evt["composedPath"]()) || (evt as any).path as EventTarget[],
|
|
733
|
-
target = evt.target;
|
|
734
|
-
|
|
735
|
-
if (path !== null) {
|
|
736
|
-
// Safari doesn't include Window, and it should.
|
|
737
|
-
path = (path.indexOf(window) < 0) ? path.concat([window]) : path;
|
|
738
|
-
return path;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
if (target === window) {
|
|
742
|
-
return [window];
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
function getParents(node, memo?) {
|
|
746
|
-
memo = memo || [];
|
|
747
|
-
var parentNode = node.parentNode;
|
|
748
|
-
|
|
749
|
-
if (!parentNode) {
|
|
750
|
-
return memo;
|
|
751
|
-
}
|
|
752
|
-
else {
|
|
753
|
-
return getParents(parentNode, memo.concat([parentNode]));
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
return [target].concat(getParents(target)).concat([window]);
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
/** timeouts after 10 seconds by default */
|
|
761
|
-
export function waitForWindowObject(typeFullName: string, windowOrParent?: Window | any, timeout = 10000): Promise<boolean> {
|
|
762
|
-
return waitFor(() => !isTypeofFullNameNullOrUndefined(typeFullName, windowOrParent), timeout);
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
/** timeouts after 10 seconds by default */
|
|
766
|
-
export function waitFor(checker: () => boolean, timeout = 10000, intervalLength = 50): Promise<boolean> {
|
|
767
|
-
return new Promise((resolve, reject) => {
|
|
768
|
-
var timeoutId: number = null;
|
|
769
|
-
|
|
770
|
-
var max = Math.round(timeout / intervalLength);
|
|
771
|
-
var count = 0;
|
|
772
|
-
var exists = false;
|
|
773
|
-
|
|
774
|
-
var _retry = () => {
|
|
775
|
-
if (timeoutId) {
|
|
776
|
-
window.clearTimeout(timeoutId);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
try {
|
|
780
|
-
exists = checker();
|
|
781
|
-
} catch (ex) {
|
|
782
|
-
resolve(false);
|
|
783
|
-
return;
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
if (exists || count > max) {
|
|
787
|
-
resolve(exists);
|
|
788
|
-
} else {
|
|
789
|
-
timeoutId = window.setTimeout(_retry, intervalLength);
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
count++;
|
|
793
|
-
};
|
|
794
|
-
|
|
795
|
-
_retry();
|
|
796
|
-
});
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
/**
|
|
800
|
-
* Waits for an async check to return true or times out.
|
|
801
|
-
* @param checker Async function that returns boolean result.
|
|
802
|
-
* @param timeout The timeout in milliseconds. Defaults to 10000ms.
|
|
803
|
-
* @param intervalLength The interval length in milliseconds to retry the checker function. Defaults to 50ms.
|
|
804
|
-
*/
|
|
805
|
-
export async function waitForAsync(checker: () => Promise<boolean>, timeout = 10000, intervalLength = 50) {
|
|
806
|
-
var max = Math.round(timeout / intervalLength);
|
|
807
|
-
var count = 0;
|
|
808
|
-
var exists = false;
|
|
809
|
-
|
|
810
|
-
for (var count = 0; count < max; count++) {
|
|
811
|
-
exists = await checker();
|
|
812
|
-
if (exists) {
|
|
813
|
-
break;
|
|
814
|
-
}
|
|
815
|
-
await delayAsync(intervalLength);
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
return exists;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
/**
|
|
822
|
-
* An async function that returns after a set delay.
|
|
823
|
-
* @param delay The delay in milliseconds. Defaults to 500ms.
|
|
824
|
-
*/
|
|
825
|
-
export function delayAsync(delay = 500) {
|
|
826
|
-
return new Promise((resolve) => {
|
|
827
|
-
window.setTimeout(() => {
|
|
828
|
-
resolve(null);
|
|
829
|
-
}, delay);
|
|
830
|
-
});
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
export interface IElementCreationOptions<T> {
|
|
834
|
-
attributes?: { [attribName: string]: string; };
|
|
835
|
-
properties?: { [K in keyof T]?: T[K] };
|
|
836
|
-
style?: { [P in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[P] };
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
export function addStyleSheet(options?: IElementCreationOptions<HTMLLinkElement>, doc?: Document) {
|
|
840
|
-
doc = doc || document;
|
|
841
|
-
var head = doc.head || doc.getElementsByTagName("head")[0];
|
|
842
|
-
if (head) {
|
|
843
|
-
var link = createStylesheet(options, doc);
|
|
844
|
-
head.appendChild(link);
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
export function createStylesheet(options?: IElementCreationOptions<HTMLLinkElement>, doc?: Document) {
|
|
849
|
-
doc = doc || document;
|
|
850
|
-
|
|
851
|
-
options = options || {};
|
|
852
|
-
options.properties = {
|
|
853
|
-
...{
|
|
854
|
-
type: "text/css",
|
|
855
|
-
rel: "stylesheet",
|
|
856
|
-
},
|
|
857
|
-
...options.properties
|
|
858
|
-
};
|
|
859
|
-
|
|
860
|
-
return createHtmlElement<HTMLLinkElement>("link", options, doc);
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
export function createHtmlElement<T extends HTMLElement>(tagName: string, options?: IElementCreationOptions<T>, doc?: Document) {
|
|
864
|
-
doc = doc || document;
|
|
865
|
-
var element = doc.createElement(tagName) as HTMLElement;
|
|
866
|
-
|
|
867
|
-
if (options) {
|
|
868
|
-
if (options.attributes) {
|
|
869
|
-
Object.keys(options.attributes).forEach((attribName) => {
|
|
870
|
-
var attribValue = options.attributes[attribName];
|
|
871
|
-
if (!isNullOrUndefined(attribValue)) {
|
|
872
|
-
element.setAttribute(attribName, attribValue);
|
|
873
|
-
}
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
if (options.properties) {
|
|
877
|
-
var mergedProps = {
|
|
878
|
-
...(options.properties as IDictionary<any>),
|
|
879
|
-
...{
|
|
880
|
-
style: options.style
|
|
881
|
-
}
|
|
882
|
-
};
|
|
883
|
-
|
|
884
|
-
Object.keys(mergedProps).forEach((propName) => {
|
|
885
|
-
var obj = mergedProps[propName];
|
|
886
|
-
if (!isNullOrUndefined(obj)) {
|
|
887
|
-
if (isString(obj) || isBoolean(obj) || isNumber(obj)) {
|
|
888
|
-
element[propName] = obj;
|
|
889
|
-
} else {
|
|
890
|
-
if (!element[propName]) {
|
|
891
|
-
element[propName] = obj;
|
|
892
|
-
} else {
|
|
893
|
-
Object.keys(obj).forEach((objName) => {
|
|
894
|
-
element[propName][objName] = obj[objName];
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
});
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
return element as T;
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
export function isInsideIFrame(win?: Window) {
|
|
907
|
-
win = win || window;
|
|
908
|
-
try {
|
|
909
|
-
return win.parent.location !== win.location;
|
|
910
|
-
} catch (ex) {
|
|
911
|
-
return true;
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
export function isIFrameAccessible(iframeEle: HTMLIFrameElement) {
|
|
916
|
-
try {
|
|
917
|
-
var location = (iframeEle.contentWindow || iframeEle.contentDocument).location;
|
|
918
|
-
return location && location.origin ? true : false;
|
|
919
|
-
} catch (ex) {
|
|
920
|
-
return false;
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
export function HTMLEncode(d: string) {
|
|
925
|
-
if (isNullOrEmptyString(d)) {
|
|
926
|
-
return "";
|
|
927
|
-
}
|
|
928
|
-
var tempString = String(d);
|
|
929
|
-
var result: string[] = [];
|
|
930
|
-
|
|
931
|
-
for (var index = 0; index < tempString.length; index++) {
|
|
932
|
-
var char = tempString.charAt(index);
|
|
933
|
-
switch (char) {
|
|
934
|
-
case "<":
|
|
935
|
-
result.push("<");
|
|
936
|
-
break;
|
|
937
|
-
case ">":
|
|
938
|
-
result.push(">");
|
|
939
|
-
break;
|
|
940
|
-
case "&":
|
|
941
|
-
result.push("&");
|
|
942
|
-
break;
|
|
943
|
-
case '"':
|
|
944
|
-
result.push(""");
|
|
945
|
-
break;
|
|
946
|
-
case "'":
|
|
947
|
-
result.push("'");
|
|
948
|
-
break;
|
|
949
|
-
default:
|
|
950
|
-
result.push(char);
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
return result.join("");
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
export function HTMLDecode(a) {
|
|
957
|
-
if (isNullOrEmptyString(a)) {
|
|
958
|
-
return "";
|
|
959
|
-
}
|
|
960
|
-
var e = [/</g, />/g, /"/g, /'/g, /:/g, /{/g, /}/g, /&/g];
|
|
961
|
-
var f = ["<", ">", '"', "'", ":", "{", "}", "&"];
|
|
962
|
-
var d: string[] = [];
|
|
963
|
-
for (var c = 0; c < a.length; c++) {
|
|
964
|
-
var b = a.indexOf("&");
|
|
965
|
-
if (b !== -1) {
|
|
966
|
-
if (b > 0) {
|
|
967
|
-
d.push(a.substr(0, b));
|
|
968
|
-
a = a.substr(b);
|
|
969
|
-
}
|
|
970
|
-
a = a.replace(e[c], f[c]);
|
|
971
|
-
} else {
|
|
972
|
-
break;
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
d.push(a);
|
|
976
|
-
return d.join("");
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
export function ScriptEncode(e) {
|
|
980
|
-
if (null === e || typeof e === "undefined")
|
|
981
|
-
return "";
|
|
982
|
-
for (var d = String(e), a = [], c = 0, g = d.length; c < g; c++) {
|
|
983
|
-
var b = d.charCodeAt(c);
|
|
984
|
-
if (b > 4095)
|
|
985
|
-
a.push("\\u" + b.toString(16).toUpperCase());
|
|
986
|
-
else if (b > 255)
|
|
987
|
-
a.push("\\u0" + b.toString(16).toUpperCase());
|
|
988
|
-
else if (b > 127)
|
|
989
|
-
a.push("\\u00" + b.toString(16).toUpperCase());
|
|
990
|
-
else {
|
|
991
|
-
var f = d.charAt(c);
|
|
992
|
-
switch (f) {
|
|
993
|
-
case "\n":
|
|
994
|
-
a.push("\\n");
|
|
995
|
-
break;
|
|
996
|
-
case "\r":
|
|
997
|
-
a.push("\\r");
|
|
998
|
-
break;
|
|
999
|
-
case '"':
|
|
1000
|
-
a.push("\\u0022");
|
|
1001
|
-
break;
|
|
1002
|
-
case "%":
|
|
1003
|
-
a.push("\\u0025");
|
|
1004
|
-
break;
|
|
1005
|
-
case "&":
|
|
1006
|
-
a.push("\\u0026");
|
|
1007
|
-
break;
|
|
1008
|
-
case "'":
|
|
1009
|
-
a.push("\\u0027");
|
|
1010
|
-
break;
|
|
1011
|
-
case "(":
|
|
1012
|
-
a.push("\\u0028");
|
|
1013
|
-
break;
|
|
1014
|
-
case ")":
|
|
1015
|
-
a.push("\\u0029");
|
|
1016
|
-
break;
|
|
1017
|
-
case "+":
|
|
1018
|
-
a.push("\\u002b");
|
|
1019
|
-
break;
|
|
1020
|
-
case "/":
|
|
1021
|
-
a.push("\\u002f");
|
|
1022
|
-
break;
|
|
1023
|
-
case "<":
|
|
1024
|
-
a.push("\\u003c");
|
|
1025
|
-
break;
|
|
1026
|
-
case ">":
|
|
1027
|
-
a.push("\\u003e");
|
|
1028
|
-
break;
|
|
1029
|
-
case "\\":
|
|
1030
|
-
a.push("\\\\");
|
|
1031
|
-
break;
|
|
1032
|
-
default:
|
|
1033
|
-
a.push(f);
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
return a.join("");
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
export function addEventListeners(eles: ElementOrElemenctList, events: string | string[], listener: (evt: Event) => void, useCapture = false) {
|
|
1041
|
-
if (!isFunction(listener)) {
|
|
1042
|
-
return;
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
var eventNames: string[];
|
|
1046
|
-
if (isString(events)) {
|
|
1047
|
-
eventNames = (events as string).split(" ");
|
|
1048
|
-
} else if (Array.isArray(events)) {
|
|
1049
|
-
eventNames = events;
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
if (isNullOrEmptyArray(eventNames)) {
|
|
1053
|
-
return;
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
var elements = _eleOrSelectorToElementArray(eles);
|
|
1057
|
-
|
|
1058
|
-
if (isNullOrEmptyArray(elements)) {
|
|
1059
|
-
return;
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
elements.forEach((ele) => {
|
|
1063
|
-
if (isElement(ele) && isFunction(ele.addEventListener)) {
|
|
1064
|
-
eventNames.forEach((eventName) => {
|
|
1065
|
-
ele.addEventListener(eventName, listener, useCapture);
|
|
1066
|
-
});
|
|
1067
|
-
}
|
|
1068
|
-
});
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
/** defer calling this function multiple times within X time frame to execute only once after the last call */
|
|
1072
|
-
export function debounce<T extends (...args) => void>(callback: T, ms: number, thisArg: any = null): T {
|
|
1073
|
-
let timeoutId = null;
|
|
1074
|
-
let func = (...args) => {
|
|
1075
|
-
window.clearTimeout(timeoutId);
|
|
1076
|
-
timeoutId = window.setTimeout(() => {
|
|
1077
|
-
callback.apply(thisArg, args);
|
|
1078
|
-
}, ms);
|
|
1079
|
-
};
|
|
1080
|
-
return func as any;
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
/** call a funciton X number of times, on a specific interval. */
|
|
1084
|
-
export function interval<T extends () => void>(callback: T, msBetweenCalls: number, numberOfTimesToCall: number, thisArg: any = null) {
|
|
1085
|
-
for (let index = 1; index <= numberOfTimesToCall; index++)
|
|
1086
|
-
window.setTimeout(() => { callback.apply(thisArg); }, msBetweenCalls * index);
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
/** throttle repeated calls to callback, makes sure it is only called once per *wait* at most, but won't defer it for longer than that.
|
|
1090
|
-
* Unlike debounce, which can end up waiting for 5 minutes if it is being called repeatedly.
|
|
1091
|
-
*/
|
|
1092
|
-
export function throttle<T extends (...args) => any>(callback: T, wait = 250, thisArg: any = null): T {
|
|
1093
|
-
let previous = 0;
|
|
1094
|
-
let timeout: number | null = null;
|
|
1095
|
-
let result: any;
|
|
1096
|
-
let storedContext = thisArg;
|
|
1097
|
-
let storedArgs: any[];
|
|
1098
|
-
|
|
1099
|
-
const later = (): void => {
|
|
1100
|
-
previous = Date.now();
|
|
1101
|
-
timeout = null;
|
|
1102
|
-
result = callback.apply(storedContext, storedArgs);
|
|
1103
|
-
|
|
1104
|
-
if (!timeout) {
|
|
1105
|
-
storedArgs = [];
|
|
1106
|
-
}
|
|
1107
|
-
};
|
|
1108
|
-
|
|
1109
|
-
let wrapper = (...args: any[]) => {
|
|
1110
|
-
const now = Date.now();
|
|
1111
|
-
const remaining = wait - (now - previous);
|
|
1112
|
-
|
|
1113
|
-
storedArgs = args;
|
|
1114
|
-
|
|
1115
|
-
if (remaining <= 0 || remaining > wait) {
|
|
1116
|
-
if (timeout) {
|
|
1117
|
-
clearTimeout(timeout);
|
|
1118
|
-
timeout = null;
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
previous = now;
|
|
1122
|
-
result = callback.apply(storedContext, storedArgs);
|
|
1123
|
-
|
|
1124
|
-
if (!timeout) {
|
|
1125
|
-
storedArgs = [];
|
|
1126
|
-
}
|
|
1127
|
-
} else if (!timeout) {
|
|
1128
|
-
timeout = window.setTimeout(later, remaining);
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
return result;
|
|
1132
|
-
};
|
|
1133
|
-
return wrapper as T;
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
var _resizeHandlers: IDictionary<() => void> = {};
|
|
1137
|
-
var _resizeRegistered = false;
|
|
1138
|
-
function _handleResize() {
|
|
1139
|
-
Object.keys(_resizeHandlers).forEach(key => {
|
|
1140
|
-
try { _resizeHandlers[key](); }
|
|
1141
|
-
catch (e) { }
|
|
1142
|
-
});
|
|
1143
|
-
}
|
|
1144
|
-
/** allows you to register, re-register or remove a resize handler without ending up with multiple registrations. */
|
|
1145
|
-
export function OnWindowResize(handlerID: string, handler: () => void) {
|
|
1146
|
-
if (!isNullOrUndefined(handler))
|
|
1147
|
-
_resizeHandlers[handlerID] = handler;
|
|
1148
|
-
else delete _resizeHandlers[handlerID];
|
|
1149
|
-
|
|
1150
|
-
if (!_resizeRegistered) {
|
|
1151
|
-
_resizeRegistered = true;
|
|
1152
|
-
addEventHandler(window, "resize", debounce(_handleResize, 250));
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
export function dispatchCustomEvent<T>(obj: HTMLElement | Window | Document, eventName: string, params: { bubbles?: boolean; cancelable?: boolean; detail?: T; } = { bubbles: false, cancelable: false, detail: null }) {
|
|
1157
|
-
if (isNullOrUndefined(obj) || !isFunction(obj.dispatchEvent)) {
|
|
1158
|
-
return;
|
|
1159
|
-
}
|
|
1160
|
-
params.bubbles = params.bubbles || false;
|
|
1161
|
-
params.cancelable = params.cancelable || false;
|
|
1162
|
-
params.detail = params.detail || null;
|
|
1163
|
-
|
|
1164
|
-
let event: CustomEvent<T> = null;
|
|
1165
|
-
if (isFunction(window.CustomEvent)) {
|
|
1166
|
-
event = new CustomEvent(eventName, params);
|
|
1167
|
-
} else {
|
|
1168
|
-
event = document.createEvent('CustomEvent');
|
|
1169
|
-
event.initCustomEvent(eventName, params.bubbles, params.cancelable, params.detail);
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
obj.dispatchEvent(event);
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
export function addStyleElement(cssText: string, id?: string) {
|
|
1176
|
-
var parent = document.head || document.getElementsByTagName("head")[0] || document;
|
|
1177
|
-
let cssElm: HTMLStyleElement = !isNullOrEmptyString(id) ? document.getElementById(id) as HTMLStyleElement : null;
|
|
1178
|
-
if (!cssElm) {
|
|
1179
|
-
cssElm = document.createElement("style");
|
|
1180
|
-
if (!isNullOrEmptyString(id))
|
|
1181
|
-
cssElm.id = id;
|
|
1182
|
-
parent.appendChild(cssElm);
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
cssElm.innerHTML = cssText;
|
|
1186
|
-
|
|
1187
|
-
return cssElm;
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
export function getReactInstanceFromElement(node) {
|
|
1191
|
-
if (!isNullOrUndefined(node)) {
|
|
1192
|
-
for (const key in node) {
|
|
1193
|
-
if ((key).startsWith("__reactInternalInstance$") || key.startsWith("__reactFiber$")) {
|
|
1194
|
-
return node[key];
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
return null;
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
/** registers a listener to when the browser url changed */
|
|
1202
|
-
export function registerUrlChanged(callback: () => void) {
|
|
1203
|
-
let url = window.location.href;
|
|
1204
|
-
|
|
1205
|
-
window.setInterval(() => {
|
|
1206
|
-
if (url !== window.location.href) {
|
|
1207
|
-
url = window.location.href;
|
|
1208
|
-
if (isFunction(callback)) {
|
|
1209
|
-
callback();
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
}, 333);
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
export const DisableAnchorInterceptAttribute = "data-interception";
|
|
1216
|
-
export const DisableAnchorInterceptValue = "off";
|
|
1217
|
-
export function DisableAnchorIntercept(link: HTMLAnchorElement) {
|
|
1218
|
-
link.setAttribute(DisableAnchorInterceptAttribute, DisableAnchorInterceptValue);
|
|
1219
|
-
}
|
|
1220
|
-
/** go over HTML and add data-interception="off" to all <a> tags. */
|
|
1221
|
-
export function DisableAnchorInterceptInHtml(html: string) {
|
|
1222
|
-
return html.replace(/<a /g, `<a ${DisableAnchorInterceptAttribute}="${DisableAnchorInterceptValue}" `);
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
export function isChildOf(node: HTMLElement, parent: {
|
|
1226
|
-
class?: string;
|
|
1227
|
-
id?: string;
|
|
1228
|
-
tagName?: string;
|
|
1229
|
-
}) {
|
|
1230
|
-
let _parent = node && node.parentElement;
|
|
1231
|
-
while (_parent) {
|
|
1232
|
-
if ((isNullOrEmptyString(parent.id) || _parent.id === parent.id)
|
|
1233
|
-
&& (isNullOrEmptyString(parent.class) || _parent.classList.contains(parent.class))
|
|
1234
|
-
&& (isNullOrEmptyString(parent.tagName) || _parent.tagName.toUpperCase() === parent.tagName.toUpperCase())
|
|
1235
|
-
)
|
|
1236
|
-
return true;
|
|
1237
|
-
_parent = _parent.parentElement;
|
|
1238
|
-
}
|
|
1239
|
-
return false;
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
export function findAcestor(ele: HTMLElement, predicate: (ele2: HTMLElement) => boolean) {
|
|
1243
|
-
if (!isElement(ele) || !isFunction(predicate)) {
|
|
1244
|
-
return null;
|
|
1245
|
-
}
|
|
1246
|
-
while (ele) {
|
|
1247
|
-
if (predicate(ele)) {
|
|
1248
|
-
return ele;
|
|
1249
|
-
}
|
|
1250
|
-
ele = ele.parentElement;
|
|
1251
|
-
}
|
|
1252
|
-
return null;
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
export function loadModernFormsCSS() {
|
|
1256
|
-
let styleElm = document.getElementById('kw_modernui_css') as HTMLLinkElement;
|
|
1257
|
-
if (!styleElm) {
|
|
1258
|
-
styleElm = document.createElement("link");
|
|
1259
|
-
styleElm.id = "kw_modernui_css";
|
|
1260
|
-
styleElm.rel = "stylesheet";
|
|
1261
|
-
styleElm.href = "https://apps.kwizcom.com/products/modern/css/app.min.css";
|
|
1262
|
-
document.head.appendChild(styleElm);
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
export function showLoadingOverlay(elm: HTMLElement, options?: {
|
|
1266
|
-
bgColor?: string;
|
|
1267
|
-
innerHtml?: string;
|
|
1268
|
-
}) {
|
|
1269
|
-
loadModernFormsCSS();
|
|
1270
|
-
let overlay = elm.querySelector('.kw-loading-overlay') as HTMLDivElement;
|
|
1271
|
-
if (!overlay) {
|
|
1272
|
-
overlay = document.createElement("div");
|
|
1273
|
-
overlay.className = "kw-loading-overlay kw-fixedCenter kw-absoluteFull";
|
|
1274
|
-
elm.appendChild(overlay);
|
|
1275
|
-
}
|
|
1276
|
-
overlay.innerHTML = options && options.innerHtml || `<img src="${LOGO_ANIM}" style="max-width: 30%;max-height: 30%;">`;
|
|
1277
|
-
overlay.style.backgroundColor = options && options.bgColor || "white";
|
|
1278
|
-
}
|
|
1279
|
-
export function hideLoadingOverlay(elm: HTMLElement) {
|
|
1280
|
-
if (isElement(elm)) {
|
|
1281
|
-
let overlays = Array.from(elm.querySelectorAll('.kw-loading-overlay')) as HTMLDivElement[];
|
|
1282
|
-
removeHTMLElement(overlays);
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
export function getLoadingOverlayHtml(options?: {
|
|
1286
|
-
bgColor?: string;
|
|
1287
|
-
innerHtml?: string;
|
|
1288
|
-
}) {
|
|
1289
|
-
loadModernFormsCSS();
|
|
1290
|
-
let overlay = document.createElement("div");
|
|
1291
|
-
overlay.className = "kw-loading-overlay kw-fixedCenter kw-absoluteFull";
|
|
1292
|
-
overlay.innerHTML = options && options.innerHtml || `<img src="${LOGO_ANIM}" style="max-width: 30%;max-height: 30%;">`;
|
|
1293
|
-
overlay.style.backgroundColor = options && options.bgColor || "white";
|
|
1294
|
-
return overlay.outerHTML;
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
export function getUniqueElementId(id: string = "") {
|
|
1298
|
-
return `${id}${getUniqueId()}`;
|
|
1299
|
-
}
|