@kwiz/common
Version:
KWIZ common utilities and helpers for M365 platform
171 lines (154 loc) • 7.6 kB
text/typescript
import { isDebug } from "../helpers/debug";
import { noop } from "../helpers/objects";
import { isNotEmptyArray, isNullOrEmptyString, isNullOrUndefined } from "../helpers/typecheckers";
import { IKnownScript, ksGlobal } from "../types/knownscript.types";
import Sod from "./sod";
export interface IScriptUtils {
/** @deprecated - use wrapFunction instead from helpers/functions */
wrapFunction3?: (originalFunction: () => void, instance: any, doBefore: () => void, doAfter: () => void) => void;
loadKnownScript: (script: IKnownScript) => void;
loadKnownScript_Sync: (script: IKnownScript) => void;
ensureScript: (scriptUrl: string, global: ksGlobal, callback: () => void, sodName: string) => void;
ensureScripts: (scripts: { scriptUrl: string; global: ksGlobal; sodName: string; }[], callback: () => void) => void;
}
export default class script implements IScriptUtils {
private static instance: script = null;
public isRtl = false;
public static get Instance() {
if (script.instance === null) {
//share single instance between all imports
if (typeof (window as any).kSingleScripts !== 'undefined')
script.instance = (window as any).kSingleScripts;//a global instance already exists, use it
else {
script.instance = new script();
(window as any).kSingleScripts = script.instance;//place this instance in the global namespace for others to reuse
}
}
return script.instance;
}
public async loadKnownScript(knownScript: IKnownScript) {
var promisesDependencies: Promise<any>[] = [];
(knownScript.dependencies || []).forEach(dep => {
promisesDependencies.push(this.loadKnownScript(dep));
});
if (promisesDependencies.length > 0)
await Promise.all(promisesDependencies);
return new Promise((resolve, reject) => {
this.ensureKnownScriptInternal(knownScript, () => {
resolve(Sod.getGlobal(knownScript.global));
});
});
}
public loadKnownScript_Sync(knownScript: IKnownScript) {
try {
if (isNotEmptyArray(knownScript.dependencies)) {
(knownScript.dependencies || []).forEach(dep => {
this.loadKnownScript_Sync(dep)
});
}
} catch {
}
this.ensureKnownScriptInternal(knownScript, noop, true);
return Sod.getGlobal(knownScript.global);
}
private ensureKnownScriptInternal(knownScript: IKnownScript, callback: () => void, sync = false) {
let url = isDebug() && !knownScript.forceMin ? knownScript.url.replace('.min.js', '.js') : knownScript.url;
if (url[0] === '/') url = "https://apps.kwizcom.com" + url;
if (sync === true)
this.ensureScriptSync(url, knownScript.global, callback, knownScript.sodName);
else
this.ensureScript(url, knownScript.global, callback, knownScript.sodName);
let cssFiles = this.isRtl === true && !isNullOrUndefined(knownScript.rtlCss) ? knownScript.rtlCss : knownScript.css;
if (!isNullOrUndefined(cssFiles))
cssFiles.forEach(css => {
if (!isNullOrEmptyString(css)) {
let cssurl = isDebug() && !knownScript.forceMin ? css.replace('.min.css', '.css') : css;
if (cssurl[0] === '/') cssurl = "https://apps.kwizcom.com" + cssurl;
let knownStyles = document.getElementsByClassName("kwizcom_known_css");
let found = false;
for (let si = 0; si < knownStyles.length; si++) {
let elm: HTMLLinkElement = knownStyles[si] as HTMLLinkElement;
if (elm.href && elm.href.toLowerCase() === cssurl.toLowerCase()) {
found = true;
break;
}
}
if (!found) {
let link = document.createElement("link");
link.rel = "stylesheet";
link.className = "kwizcom_known_css";
link.type = "text/css";
link.href = cssurl;
document.head.appendChild(link);
}
}
});
}
public loadCss(cssUrl: string) {
let knownStyles = document.getElementsByClassName("kwizcom_known_css");
let found = false;
for (let si = 0; si < knownStyles.length; si++) {
let elm: HTMLLinkElement = knownStyles[si] as HTMLLinkElement;
if (elm.href && elm.href.toLowerCase() === cssUrl.toLowerCase()) {
found = true;
break;
}
}
if (!found) {
let link = document.createElement("link");
link.rel = "stylesheet";
link.className = "kwizcom_known_css";
link.type = "text/css";
link.href = cssUrl;
document.head.appendChild(link);
}
}
public ensureScriptSync(scriptUrl: string, global: ksGlobal, callback?: () => void, sodName?: string) {
//in IE there is no promise, we cannot use any async functions
return Sod.ensureScriptNoPromise(scriptUrl, global, callback, sodName, true);
}
public async ensureScript(scriptUrl: string, global: ksGlobal, callback?: () => void, sodName?: string) {
return Sod.ensureScript(scriptUrl, global, callback, sodName, false);
}
/** ensure a collection of scripts and call the callback when they are all done */
public async ensureScripts(scripts: { scriptUrl: string; global: ksGlobal; sodName: string; }[], callback: () => void) {
let promises: Promise<void>[] = [];
let length = scripts.length;
let finished = 0;
let onFinished = typeof (callback) !== "function" ? null : () => {
finished++;
if (finished === length)//all finished
callback();
};
scripts.forEach(scr => {
promises.push(Sod.ensureScript(scr.scriptUrl, scr.global, onFinished, scr.sodName));
});
return Promise.all(promises);
}
private _WrapFunctionArr: any[] = [];
/** @deprecated - use wrapFunction instead from helpers/functions */
public wrapFunction3(originalFunction: () => void, instance: any, doBefore: () => void, doAfter: () => void) {
try {
if (instance !== null) {
originalFunction.bind(instance);
}
var idx = this._WrapFunctionArr.length;
this._WrapFunctionArr[idx] = originalFunction;
originalFunction = function (...args: any[]) {
if (typeof (doBefore) === "function") {
doBefore.apply(instance, args);
}
var returnValue = this._WrapFunctionArr[idx].apply(instance, args);
if (typeof (doAfter) === "function") {
doAfter.apply(instance, args);
}
return returnValue;
};
if (instance !== null) {
originalFunction.bind(instance);
}
} catch (e) {
if (isDebug()) console.log('unhandled error in wrapFunction3');
}
}
}