jsf.js_next_gen
Version:
A next generation typescript reimplementation of jsf.js
1,358 lines (1,345 loc) • 378 kB
JavaScript
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/mona-dish/src/main/typescript/AssocArray.ts":
/*!******************************************************************!*\
!*** ./node_modules/mona-dish/src/main/typescript/AssocArray.ts ***!
\******************************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/*!
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.deepEqual = exports.shallowMerge = exports.simpleShallowMerge = exports.deepCopy = exports.buildPath = exports.resolve = exports.appendIf = exports.assignIf = exports.append = exports.assign = void 0;
const Es2019Array_1 = __webpack_require__(/*! ./Es2019Array */ "./node_modules/mona-dish/src/main/typescript/Es2019Array.ts");
/**
* A nop as assign functionality (aka ignore assign)
*/
class IgnoreAssign {
constructor(parent) {
this.parent = parent;
}
set value(value) {
}
get value() {
return this.parent;
}
}
;
/**
* uses the known pattern from config
* assign(target, key1, key2, key3).value = value;
* @param target
* @param keys
*/
function assign(target, ...accessPath) {
if (accessPath.length < 1) {
return new IgnoreAssign(target);
}
const lastPathItem = buildPath(target, ...accessPath);
let assigner = new (class {
set value(value) {
lastPathItem.target[lastPathItem.key] = value;
}
get value() {
return lastPathItem.target[lastPathItem.key];
}
})();
return assigner;
}
exports.assign = assign;
function append(target, ...accessPath) {
if (accessPath.length < 1) {
return new IgnoreAssign(target);
}
const lastPathItem = buildPath(target, ...accessPath);
let appender = new (class {
set value(value) {
if (!Array.isArray(value)) {
value = [value];
}
if (!lastPathItem.target[lastPathItem.key]) {
lastPathItem.target[lastPathItem.key] = value;
}
else {
if (!Array.isArray(lastPathItem.target[lastPathItem.key])) {
lastPathItem.target[lastPathItem.key] = [lastPathItem.target[lastPathItem.key]];
}
lastPathItem.target[lastPathItem.key].push(...value);
}
}
})();
return appender;
}
exports.append = append;
/**
* uses the known pattern from config
* assign(target, key1, key2, key3).value = value;
* @param target
* @param keys
*/
function assignIf(condition, target, ...accessPath) {
if ((!condition) || accessPath.length < 1) {
return new IgnoreAssign(target);
}
return assign(target, ...accessPath);
}
exports.assignIf = assignIf;
/**
* uses the known pattern from config
* assign(target, key1, key2, key3).value = value;
* @param target
* @param keys
*/
function appendIf(condition, target, ...accessPath) {
if ((!condition) || accessPath.length < 1) {
return new IgnoreAssign(target);
}
return append(target, ...accessPath);
}
exports.appendIf = appendIf;
function resolve(target, ...accessPath) {
let ret = null;
accessPath = flattenAccessPath(accessPath);
let currPtr = target;
for (let cnt = 0; cnt < accessPath.length; cnt++) {
let accessKeyIndex = accessPath[cnt];
accessKeyIndex = arrayIndex(accessKeyIndex) != -1 ? arrayIndex(accessKeyIndex) : accessKeyIndex;
currPtr = currPtr === null || currPtr === void 0 ? void 0 : currPtr[accessKeyIndex];
if ('undefined' == typeof currPtr) {
return null;
}
ret = currPtr;
}
return currPtr;
}
exports.resolve = resolve;
function keyVal(key) {
let start = key.indexOf("[");
if (start >= 0) {
return key.substring(0, start);
}
else {
return key;
}
}
function arrayIndex(key) {
let start = key.indexOf("[");
let end = key.indexOf("]");
if (start >= 0 && end > 0 && start < end) {
return parseInt(key.substring(start + 1, end));
}
else {
return -1;
}
}
function isArrayPos(currKey, arrPos) {
return currKey === "" && arrPos >= 0;
}
function isNoArray(arrPos) {
return arrPos == -1;
}
function alloc(arr, length, defaultVal = {}) {
let toAdd = [];
toAdd.length = length;
toAdd[length - 1] = defaultVal;
arr.push(...toAdd);
}
function flattenAccessPath(accessPath) {
return new Es2019Array_1.Es2019Array(...accessPath).flatMap(path => path.split("["))
.map(path => path.indexOf("]") != -1 ? "[" + path : path)
.filter(path => path != "");
}
/**
* builds up a path, only done if no data is present!
* @param target
* @param accessPath
* @returns the last assignable entry
*/
function buildPath(target, ...accessPath) {
accessPath = flattenAccessPath(accessPath);
//we now have a pattern of having the array accessors always in separate items
let parentPtr = target;
let parKeyArrPos = null;
let currKey = null;
let arrPos = -1;
for (let cnt = 0; cnt < accessPath.length; cnt++) {
currKey = keyVal(accessPath[cnt]);
arrPos = arrayIndex(accessPath[cnt]);
//it now is either key or arrPos
if (arrPos != -1) {
//case root(array)[5] -> root must be array and allocate 5 elements
//case root.item[5] root.item must be array and of 5 elements
if (!Array.isArray(parentPtr)) {
throw Error("Associative array referenced as index array in path reference");
}
//we need to look ahead for proper allocation
//not end reached
let nextArrPos = -1;
if (cnt < accessPath.length - 1) {
nextArrPos = arrayIndex(accessPath[cnt + 1]);
}
let dataPresent = 'undefined' != typeof (parentPtr === null || parentPtr === void 0 ? void 0 : parentPtr[arrPos]);
//no data present check here is needed, because alloc only reserves if not present
alloc(parentPtr, arrPos + 1, nextArrPos != -1 ? [] : {});
parKeyArrPos = arrPos;
//we now go to the reserved element
if (cnt == accessPath.length - 1) {
parentPtr[arrPos] = (dataPresent) ? parentPtr[arrPos] : null;
}
else {
parentPtr = parentPtr[arrPos];
}
}
else {
if (Array.isArray(parentPtr)) {
throw Error("Index array referenced as associative array in path reference");
}
//again look ahead whether the next value is an array or assoc array
let nextArrPos = -1;
if (cnt < accessPath.length - 1) {
nextArrPos = arrayIndex(accessPath[cnt + 1]);
}
parKeyArrPos = currKey;
let dataPresent = 'undefined' != typeof (parentPtr === null || parentPtr === void 0 ? void 0 : parentPtr[currKey]);
if (cnt == accessPath.length - 1) {
if (!dataPresent) {
parentPtr[currKey] = null;
}
}
else {
if (!dataPresent) {
parentPtr[currKey] = nextArrPos == -1 ? {} : [];
}
parentPtr = parentPtr[currKey];
}
}
}
return { target: parentPtr, key: parKeyArrPos };
}
exports.buildPath = buildPath;
function deepCopy(fromAssoc) {
return JSON.parse(JSON.stringify(fromAssoc));
}
exports.deepCopy = deepCopy;
/**
* simple left to right merge
*
* @param assocArrays
*/
function simpleShallowMerge(...assocArrays) {
return shallowMerge(true, false, ...assocArrays);
}
exports.simpleShallowMerge = simpleShallowMerge;
function _appendWithOverwrite(withAppend, target, key, arr, toAssign) {
if (!withAppend) {
target[key] = arr[key];
}
else {
//overwrite means in this case, no double entries!
//we do not a deep compare for now a single value compare suffices
if ('undefined' == typeof (target === null || target === void 0 ? void 0 : target[key])) {
target[key] = toAssign;
}
else if (!Array.isArray(target[key])) {
let oldVal = target[key];
let newVals = [];
//TODO maybe deep deep compare here, but on the other hand it is
//shallow
toAssign.forEach(item => {
if (oldVal != item) {
newVals.push(item);
}
});
target[key] = new Es2019Array_1.Es2019Array(...[]);
target[key].push(oldVal);
target[key].push(...newVals);
}
else {
let oldVal = target[key];
let newVals = [];
//TODO deep compare here
toAssign.forEach(item => {
if (oldVal.indexOf(item) == -1) {
newVals.push(item);
}
});
target[key].push(...newVals);
}
}
}
function _appendWithoutOverwrite(withAppend, target, key, arr, toAssign) {
if (!withAppend) {
return;
}
else {
//overwrite means in this case, no double entries!
//we do not a deep compare for now a single value compare suffices
if ('undefined' == typeof (target === null || target === void 0 ? void 0 : target[key])) {
target[key] = toAssign;
}
else if (!Array.isArray(target[key])) {
let oldVal = target[key];
target[key] = new Es2019Array_1.Es2019Array(...[]);
target[key].push(oldVal);
target[key].push(...toAssign);
}
else {
target[key].push(...toAssign);
}
}
}
/**
* Shallow merge as in config, but on raw associative arrays
*
* @param overwrite overwrite existing keys, if they exist with their subtrees
* @param withAppend if a key exist append the values or drop them
* Combination overwrite withappend filters doubles out of merged arrays
* @param assocArrays array of assoc arres reduced right to left
*/
function shallowMerge(overwrite = true, withAppend = false, ...assocArrays) {
let target = {};
new Es2019Array_1.Es2019Array(...assocArrays).map(arr => {
return { arr, keys: Object.keys(arr) };
}).forEach(({ arr, keys }) => {
keys.forEach(key => {
let toAssign = arr[key];
if (!Array.isArray(toAssign) && withAppend) {
toAssign = new Es2019Array_1.Es2019Array(...[toAssign]);
}
if (overwrite || !(target === null || target === void 0 ? void 0 : target[key])) {
_appendWithOverwrite(withAppend, target, key, arr, toAssign);
}
else if (!overwrite && (target === null || target === void 0 ? void 0 : target[key])) {
_appendWithoutOverwrite(withAppend, target, key, arr, toAssign);
}
});
});
return target;
}
exports.shallowMerge = shallowMerge;
//TODO test this, slightly altered from https://medium.com/@pancemarko/deep-equality-in-javascript-determining-if-two-objects-are-equal-bf98cf47e934
//he overlooked some optimizations and a shortcut at typeof!
function deepEqual(obj1, obj2) {
if (obj1 == obj2) {
return false;
}
if (typeof obj1 != typeof obj2) {
return false;
}
if (Array.isArray(obj1) && Array.isArray(obj2)) {
if (obj1.length != obj2.length) {
return;
}
//arrays must be equal, order as well, there is no way around it
//this is the major limitation we have
return obj1.every((item, cnt) => deepEqual(item, obj2[cnt]));
}
//string number and other primitives are filtered out here
if ("object" == typeof obj1 && "object" == typeof obj2) {
let keys1 = Object.keys(obj1);
let keys2 = Object.keys(obj2);
if (keys1.length != keys2.length) {
return false;
}
return keys1.every(key => keys2.indexOf(key) != -1) &&
keys1.every(key => deepEqual(obj1[key], obj2[key]));
}
return false;
//done here no match found
}
exports.deepEqual = deepEqual;
/***/ }),
/***/ "./node_modules/mona-dish/src/main/typescript/Config.ts":
/*!**************************************************************!*\
!*** ./node_modules/mona-dish/src/main/typescript/Config.ts ***!
\**************************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Config = exports.CONFIG_ANY = exports.CONFIG_VALUE = void 0;
const Es2019Array_1 = __webpack_require__(/*! ./Es2019Array */ "./node_modules/mona-dish/src/main/typescript/Es2019Array.ts");
const Monad_1 = __webpack_require__(/*! ./Monad */ "./node_modules/mona-dish/src/main/typescript/Monad.ts");
const Lang_1 = __webpack_require__(/*! ./Lang */ "./node_modules/mona-dish/src/main/typescript/Lang.ts");
var objAssign = Lang_1.Lang.objAssign;
const AssocArray_1 = __webpack_require__(/*! ./AssocArray */ "./node_modules/mona-dish/src/main/typescript/AssocArray.ts");
/**
* specialized value embedder
* for our Configuration
*/
class ConfigEntry extends Monad_1.ValueEmbedder {
constructor(rootElem, key, arrPos) {
super(rootElem, key);
this.arrPos = arrPos !== null && arrPos !== void 0 ? arrPos : -1;
}
get value() {
if (this.key == "" && this.arrPos >= 0) {
return this._value[this.arrPos];
}
else if (this.key && this.arrPos >= 0) {
return this._value[this.key][this.arrPos];
}
return this._value[this.key];
}
set value(val) {
if (this.key == "" && this.arrPos >= 0) {
this._value[this.arrPos] = val;
return;
}
else if (this.key && this.arrPos >= 0) {
this._value[this.key][this.arrPos] = val;
return;
}
this._value[this.key] = val;
}
}
/*default value for absent*/
ConfigEntry.absent = ConfigEntry.fromNullable(null);
exports.CONFIG_VALUE = "__END_POINT__";
exports.CONFIG_ANY = "__ANY_POINT__";
/**
* Config, basically an optional wrapper for a json structure
* (not Side - effect free, since we can alter the internal config state
* without generating a new config), not sure if we should make it side - effect free
* since this would swallow a lot of performance and ram
*/
class Config extends Monad_1.Optional {
constructor(root, configDef) {
super(root);
this.configDef = configDef;
}
/**
* shallow copy getter, copies only the first level, references the deeper nodes
* in a shared manner
*/
get shallowCopy() {
return this.shallowCopy$();
}
shallowCopy$() {
let ret = new Config({});
ret.shallowMerge(this.value);
return ret;
}
/**
* deep copy, copies all config nodes
*/
get deepCopy() {
return this.deepCopy$();
}
deepCopy$() {
return new Config(objAssign({}, this.value));
}
/**
* creates a config from an initial value or null
* @param value
*/
static fromNullable(value) {
return new Config(value);
}
/**
* simple merge for the root configs
*/
shallowMerge(other, overwrite = true, withAppend = false) {
//shallow merge must be mutable so we have to remap
let newThis = (0, AssocArray_1.shallowMerge)(overwrite, withAppend, this.value, other.value);
if (Array.isArray(this._value)) {
this._value.length = 0;
this._value.push(...newThis);
}
else {
Object.getOwnPropertyNames(this._value).forEach(key => delete this._value[key]);
Object.getOwnPropertyNames(newThis).forEach(key => this._value[key] = newThis[key]);
}
}
/**
* assigns a single value as array, or appends it
* to an existing value mapping a single value to array
*
*
* usage myConfig.append("foobaz").value = "newValue"
* myConfig.append("foobaz").value = "newValue2"
*
* resulting in myConfig.foobaz == ["newValue, newValue2"]
*
* @param {string[]} accessPath
*/
append(...accessPath) {
return (0, AssocArray_1.append)(this._value, ...accessPath);
}
/**
* appends to an existing entry (or extends into an array and appends)
* if the condition is met
* @param {boolean} condition
* @param {string[]} accessPath
*/
appendIf(condition, ...accessPath) {
return (0, AssocArray_1.appendIf)(condition, this._value, ...accessPath);
}
/**
* assigns a new value on the given access path
* @param accessPath
*/
assign(...accessPath) {
return (0, AssocArray_1.assign)(this.value, ...accessPath);
}
/**
* assign a value if the condition is set to true, otherwise skip it
*
* @param condition the condition, the access accessPath into the config
* @param accessPath
*/
assignIf(condition, ...accessPath) {
return (0, AssocArray_1.assignIf)(condition, this._value, ...accessPath);
}
/**
* get if the access path is present (get is reserved as getter with a default, on the current path)
* TODO will be renamed to something more meaningful and deprecated, the name is ambiguous
* @param accessPath the access path
*/
getIf(...accessPath) {
this.assertAccessPath(...accessPath);
return this.getClass().fromNullable((0, AssocArray_1.resolve)(this.value, ...accessPath));
}
/**
* gets the current node and if none is present returns a config with a default value
* @param defaultVal
*/
get(defaultVal) {
return this.getClass().fromNullable(super.get(defaultVal).value);
}
//empties the current config entry
delete(key) {
if (key in this.value) {
delete this.value[key];
}
return this;
}
/**
* converts the entire config into a json object
*/
toJson() {
return JSON.stringify(this.value);
}
getClass() {
return Config;
}
setVal(val) {
this._value = val;
}
/**
* asserts the access path for a semi typed access
* @param accessPath
* @private
*/
assertAccessPath(...accessPath) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
accessPath = this.preprocessKeys(...accessPath);
if (!this.configDef) {
//untyped
return;
}
const ERR_ACCESS_PATH = "Access Path to config invalid";
let currAccessPos = Monad_1.Optional.fromNullable(Object.keys(this.configDef).map(key => {
let ret = {};
ret[key] = this.configDef[key];
return ret;
}));
for (let cnt = 0; cnt < accessPath.length; cnt++) {
let currKey = this.keyVal(accessPath[cnt]);
let arrPos = this.arrayIndex(accessPath[cnt]);
//key index
if (this.isArray(arrPos)) {
if (currKey != "") {
currAccessPos = Array.isArray(currAccessPos.value) ?
Monad_1.Optional.fromNullable((_b = (_a = new Es2019Array_1.Es2019Array(...currAccessPos.value)
.find(item => {
var _a;
return !!((_a = item === null || item === void 0 ? void 0 : item[currKey]) !== null && _a !== void 0 ? _a : false);
})) === null || _a === void 0 ? void 0 : _a[currKey]) === null || _b === void 0 ? void 0 : _b[arrPos]) :
Monad_1.Optional.fromNullable((_e = (_d = (_c = currAccessPos.value) === null || _c === void 0 ? void 0 : _c[currKey]) === null || _d === void 0 ? void 0 : _d[arrPos]) !== null && _e !== void 0 ? _e : null);
}
else {
currAccessPos = (Array.isArray(currAccessPos.value)) ?
Monad_1.Optional.fromNullable((_f = currAccessPos.value) === null || _f === void 0 ? void 0 : _f[arrPos]) : Monad_1.Optional.absent;
}
//we noe store either the current array or the filtered look ahead to go further
}
else {
//we now have an array and go further with a singular key
currAccessPos = (Array.isArray(currAccessPos.value)) ? Monad_1.Optional.fromNullable((_g = new Es2019Array_1.Es2019Array(...currAccessPos.value)
.find(item => {
var _a;
return !!((_a = item === null || item === void 0 ? void 0 : item[currKey]) !== null && _a !== void 0 ? _a : false);
})) === null || _g === void 0 ? void 0 : _g[currKey]) :
Monad_1.Optional.fromNullable((_j = (_h = currAccessPos.value) === null || _h === void 0 ? void 0 : _h[currKey]) !== null && _j !== void 0 ? _j : null);
}
if (!currAccessPos.isPresent()) {
throw Error(ERR_ACCESS_PATH);
}
if (currAccessPos.value == exports.CONFIG_ANY) {
return;
}
}
}
isNoArray(arrPos) {
return arrPos == -1;
}
isArray(arrPos) {
return !this.isNoArray(arrPos);
}
}
exports.Config = Config;
/***/ }),
/***/ "./node_modules/mona-dish/src/main/typescript/DomQuery.ts":
/*!****************************************************************!*\
!*** ./node_modules/mona-dish/src/main/typescript/DomQuery.ts ***!
\****************************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
/*!
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http:// www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DQ$ = exports.DQ = exports.DomQueryCollector = exports.DomQuery = exports.Style = exports.ElementAttribute = void 0;
const Monad_1 = __webpack_require__(/*! ./Monad */ "./node_modules/mona-dish/src/main/typescript/Monad.ts");
const SourcesCollectors_1 = __webpack_require__(/*! ./SourcesCollectors */ "./node_modules/mona-dish/src/main/typescript/SourcesCollectors.ts");
const Lang_1 = __webpack_require__(/*! ./Lang */ "./node_modules/mona-dish/src/main/typescript/Lang.ts");
const Global_1 = __webpack_require__(/*! ./Global */ "./node_modules/mona-dish/src/main/typescript/Global.ts");
const Es2019Array_1 = __webpack_require__(/*! ./Es2019Array */ "./node_modules/mona-dish/src/main/typescript/Es2019Array.ts");
var trim = Lang_1.Lang.trim;
var isString = Lang_1.Lang.isString;
var eqi = Lang_1.Lang.equalsIgnoreCase;
var objToArray = Lang_1.Lang.objToArray;
const AssocArray_1 = __webpack_require__(/*! ./AssocArray */ "./node_modules/mona-dish/src/main/typescript/AssocArray.ts");
class NonceValueEmbedder extends Monad_1.ValueEmbedder {
constructor(rootElems) {
super(rootElems === null || rootElems === void 0 ? void 0 : rootElems[0], "nonce");
this.rootElems = rootElems;
}
isAbsent() {
const value = this.value;
return 'undefined' == typeof value || '' == value;
}
get value() {
var _a, _b, _c, _d, _e;
return (_c = (_b = (_a = this === null || this === void 0 ? void 0 : this.rootElems) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.nonce) !== null && _c !== void 0 ? _c : (_e = (_d = this === null || this === void 0 ? void 0 : this.rootElems) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.getAttribute("nonce");
}
set value(newVal) {
var _a;
if (!((_a = this === null || this === void 0 ? void 0 : this.rootElems) === null || _a === void 0 ? void 0 : _a.length)) {
return;
}
this.rootElems.forEach((rootElem) => {
if ("undefined" != typeof (rootElem === null || rootElem === void 0 ? void 0 : rootElem.nonce)) {
rootElem.nonce = newVal;
}
else {
rootElem.setAttribute("nonce", newVal);
}
});
}
}
/**
*
* // - submit checkboxes and radio inputs only if checked
if ((tagName != "select" && elemType != "button"
&& elemType != "reset" && elemType != "submit" && elemType != "image")
&& ((elemType != "checkbox" && elemType != "radio"
*/
var ALLOWED_SUBMITTABLE_ELEMENTS;
(function (ALLOWED_SUBMITTABLE_ELEMENTS) {
ALLOWED_SUBMITTABLE_ELEMENTS["SELECT"] = "select";
ALLOWED_SUBMITTABLE_ELEMENTS["BUTTON"] = "button";
ALLOWED_SUBMITTABLE_ELEMENTS["SUBMIT"] = "submit";
ALLOWED_SUBMITTABLE_ELEMENTS["RESET"] = "reset";
ALLOWED_SUBMITTABLE_ELEMENTS["IMAGE"] = "image";
ALLOWED_SUBMITTABLE_ELEMENTS["RADIO"] = "radio";
ALLOWED_SUBMITTABLE_ELEMENTS["CHECKBOX"] = "checkbox";
})(ALLOWED_SUBMITTABLE_ELEMENTS || (ALLOWED_SUBMITTABLE_ELEMENTS = {}));
/**
* helper to fix a common problem that a system has to wait, until a certain condition is reached.
* Depending on the browser this uses either the Mutation Observer or a semi compatible interval as fallback.
* @param root the root DomQuery element to start from
* @param condition the condition lambda to be fulfilled
* @param options options for the search
*/
function waitUntilDom(root, condition, options = {
attributes: true,
childList: true,
subtree: true,
timeout: 500,
interval: 100
}) {
return new Promise((success, error) => {
let observer = null;
const MUT_ERROR = new Error("Mutation observer timeout");
// we do the same but for now ignore the options on the dom query
// we cannot use absent here, because the condition might search for an absent element
function findElement(root, condition) {
let found = null;
if (!!condition(root)) {
return root;
}
if (options.childList) {
found = (condition(root)) ? root : root.childNodes.filter(item => condition(item)).first().value.value;
}
else if (options.subtree) {
found = (condition(root)) ? root : root.querySelectorAll(" * ").filter(item => condition(item)).first().value.value;
}
else {
found = (condition(root)) ? root : null;
}
return found;
}
let foundElement = root;
if (!!(foundElement = findElement(foundElement, condition))) {
success(new DomQuery(foundElement));
return;
}
if ('undefined' != typeof MutationObserver) {
const mutTimeout = setTimeout(() => {
observer.disconnect();
return error(MUT_ERROR);
}, options.timeout);
const callback = (mutationList) => {
const found = new DomQuery(mutationList.map((mut) => mut.target)).filter(item => condition(item)).first();
if (found.isPresent()) {
clearTimeout(mutTimeout);
observer.disconnect();
success(new DomQuery(found || root));
}
};
observer = new MutationObserver(callback);
// browsers might ignore it, but we cannot break the api in the case
// hence no timeout is passed
let observableOpts = Object.assign({}, options);
delete observableOpts.timeout;
root.eachElem(item => {
observer.observe(item, observableOpts);
});
}
else { // fallback for legacy browsers without mutation observer
let interval = setInterval(() => {
let found = findElement(root, condition);
if (!!found) {
if (timeout) {
clearTimeout(timeout);
clearInterval(interval);
interval = null;
}
success(new DomQuery(found || root));
}
}, options.interval);
let timeout = setTimeout(() => {
if (interval) {
clearInterval(interval);
error(MUT_ERROR);
}
}, options.timeout);
}
});
}
class ElementAttribute extends Monad_1.ValueEmbedder {
constructor(element, name, defaultVal = null) {
super(element, name);
this.element = element;
this.name = name;
this.defaultVal = defaultVal;
}
get value() {
let val = this.element.get(0).orElse(...[]).values;
if (!val.length) {
return this.defaultVal;
}
return val[0].getAttribute(this.name);
}
set value(value) {
let val = this.element.get(0).orElse(...[]).values;
for (let cnt = 0; cnt < val.length; cnt++) {
val[cnt].setAttribute(this.name, value);
}
val[0].setAttribute(this.name, value);
}
getClass() {
return ElementAttribute;
}
static fromNullable(value, valueKey = "value") {
return new ElementAttribute(value, valueKey);
}
}
exports.ElementAttribute = ElementAttribute;
class Style extends Monad_1.ValueEmbedder {
constructor(element, name, defaultVal = null) {
super(element, name);
this.element = element;
this.name = name;
this.defaultVal = defaultVal;
}
get value() {
let val = this.element.values;
if (!val.length) {
return this.defaultVal;
}
return val[0].style[this.name];
}
set value(value) {
let val = this.element.values;
for (let cnt = 0; cnt < val.length; cnt++) {
val[cnt].style[this.name] = value;
}
}
getClass() {
return ElementAttribute;
}
static fromNullable(value, valueKey = "value") {
return new ElementAttribute(value, valueKey);
}
}
exports.Style = Style;
/**
* small helper for the specialized jsf case
* @constructor
*/
const DEFAULT_WHITELIST = () => {
return true;
};
/**
* Monadic DomNode representation, ala jquery
* This is a thin wrapper over querySelectorAll
* to get slim monadic support
* to reduce implementation code on the users side.
* This is vital for frameworks which want to rely on
* plain dom but still do not want to lose
* the reduced code footprint of querying dom trees and traversing
* by using functional patterns.
*
* Also, a few convenience methods are added to reduce
* the code footprint of standard dom processing
* operations like eval
*
* in most older systems
* Note parts of this code still stem from the Dom.js I have written 10 years
* ago, those parts look a bit ancient and will be replaced over time.
*
*/
class DomQuery {
constructor(...rootNode) {
this.rootNode = [];
this.pos = -1;
// because we can stream from an array stream directly into the dom query
this._limits = -1;
if (Monad_1.Optional.fromNullable(rootNode).isAbsent() || !rootNode.length) {
return;
}
else {
// we need to flatten out the arrays
for (let cnt = 0; cnt < rootNode.length; cnt++) {
if (!rootNode[cnt]) {
// we skip possible null entries which can happen in
// certain corner conditions due to the constructor re-wrapping single elements into arrays.
}
else if (isString(rootNode[cnt])) {
let foundElement = DomQuery.querySelectorAll(rootNode[cnt]);
if (!foundElement.isAbsent()) {
rootNode.push(...foundElement.values);
}
}
else if (rootNode[cnt] instanceof DomQuery) {
this.rootNode.push(...rootNode[cnt].values);
}
else {
this.rootNode.push(rootNode[cnt]);
}
}
}
}
/**
* returns the first element
*/
get value() {
return this.getAsElem(0);
}
get values() {
return this.allElems();
}
get global() {
return Global_1._global$;
}
get stream() {
throw Error("Not implemented, include Stream.ts for this to work");
}
get lazyStream() {
throw Error("Not implemented, include Stream.ts for this to work");
}
/**
* returns the id of the first element
*/
get id() {
return new ElementAttribute(this.get(0), "id");
}
/**
* length of the entire query set
*/
get length() {
return this.rootNode.length;
}
/**
* convenience method for tagName
*/
get tagName() {
return this.getAsElem(0).getIf("tagName");
}
/**
* convenience method for nodeName
*/
get nodeName() {
return this.getAsElem(0).getIf("nodeName");
}
isTag(tagName) {
return !this.isAbsent()
&& (this.nodeName.orElse("__none___")
.value.toLowerCase() == tagName.toLowerCase()
|| this.tagName.orElse("__none___")
.value.toLowerCase() == tagName.toLowerCase());
}
/**
* convenience property for type
*
* returns null in case of no type existing otherwise
* the type of the first element
*/
get type() {
return this.getAsElem(0).getIf("type");
}
/**
* convenience property for name
*
* returns null in case of no type existing otherwise
* the name of the first element
*/
get name() {
return new Monad_1.ValueEmbedder(this.getAsElem(0).value, "name");
}
/**
* convenience property for value
*
* returns null in case of no type existing otherwise
* the value of the first element
*/
get inputValue() {
if (this.getAsElem(0).getIf("value").isPresent()) {
return new Monad_1.ValueEmbedder(this.getAsElem(0).value);
}
else {
return Monad_1.ValueEmbedder.absent;
}
}
get val() {
return this.inputValue.value;
}
set val(value) {
this.inputValue.value = value;
}
get nodeId() {
return this.id.value;
}
set nodeId(value) {
this.id.value = value;
}
get checked() {
return new Es2019Array_1.Es2019Array(...this.values).every(el => !!el.checked);
}
set checked(newChecked) {
this.eachElem(el => el.checked = newChecked);
}
get elements() {
// a simple querySelectorAll should suffice
return this.querySelectorAll("input, checkbox, select, textarea, fieldset");
}
get deepElements() {
let elemStr = "input, select, textarea, checkbox, fieldset";
return this.querySelectorAllDeep(elemStr);
}
/**
* a deep search which treats the single isolated shadow dom areas
* separately and runs the query on each shadow dom
* @param queryStr
*/
querySelectorAllDeep(queryStr) {
let found = [];
let queryRes = this.querySelectorAll(queryStr);
if (queryRes.length) {
found.push(queryRes);
}
let shadowRoots = this.querySelectorAll("*").shadowRoot;
if (shadowRoots.length) {
let shadowRes = shadowRoots.querySelectorAllDeep(queryStr);
if (shadowRes.length) {
found.push(shadowRes);
}
}
return new DomQuery(...found);
}
/**
* disabled flag
*/
get disabled() {
return this.attr("disabled").isPresent();
}
set disabled(disabled) {
// this.attr("disabled").value = disabled + "";
if (!disabled) {
this.removeAttribute("disabled");
}
else {
this.attr("disabled").value = "disabled";
}
}
removeAttribute(name) {
this.eachElem(item => item.removeAttribute(name));
}
get childNodes() {
let childNodeArr = [];
this.eachElem((item) => {
childNodeArr = childNodeArr.concat(objToArray(item.childNodes));
});
return new DomQuery(...childNodeArr);
}
get asArray() {
// filter not supported by IE11
let items = new Es2019Array_1.Es2019Array(...this.rootNode).filter(item => {
return item != null;
}).map(item => {
return DomQuery.byId(item);
});
return items;
}
get offsetWidth() {
return new Es2019Array_1.Es2019Array(...this.rootNode)
.filter(item => item != null)
.map(elem => elem.offsetWidth)
.reduce((accumulate, incoming) => accumulate + incoming, 0);
}
get offsetHeight() {
return new Es2019Array_1.Es2019Array(...this.rootNode)
.filter(item => item != null)
.map(elem => elem.offsetHeight)
.reduce((accumulate, incoming) => accumulate + incoming, 0);
}
get offsetLeft() {
return new Es2019Array_1.Es2019Array(...this.rootNode)
.filter(item => item != null)
.map(elem => elem.offsetLeft)
.reduce((accumulate, incoming) => accumulate + incoming, 0);
}
get offsetTop() {
return new Es2019Array_1.Es2019Array(this.rootNode)
.filter(item => item != null)
.map(elem => elem.offsetTop)
.reduce((accumulate, incoming) => accumulate + incoming, 0);
}
get asNodeArray() {
return new Es2019Array_1.Es2019Array(...this.rootNode.filter(item => item != null));
}
get nonce() {
return new NonceValueEmbedder(this.rootNode);
}
static querySelectorAllDeep(selector) {
return new DomQuery(document).querySelectorAllDeep(selector);
}
/**
* easy query selector all producer
*
* @param selector the selector
* @returns a results dom query object
*/
static querySelectorAll(selector) {
if (selector.indexOf("/shadow/") != -1) {
return new DomQuery(document)._querySelectorAllDeep(selector);
}
else {
return new DomQuery(document)._querySelectorAll(selector);
}
}
/**
* byId producer
*
* @param selector id
* @param deep true if you want to go into shadow areas
* @return a DomQuery containing the found elements
*/
static byId(selector, deep = false) {
if (isString(selector)) {
return (!deep) ? new DomQuery(document).byId(selector) : new DomQuery(document).byIdDeep(selector);
}
else {
return new DomQuery(selector);
}
}
/**
* byTagName producer
*
* @param selector name
* @return a DomQuery containing the found elements
*/
static byTagName(selector) {
if (isString(selector)) {
return new DomQuery(document).byTagName(selector);
}
else {
return new DomQuery(selector);
}
}
static globalEval(code, nonce) {
return new DomQuery(document).globalEval(code, nonce);
}
static globalEvalSticky(code, nonce) {
return new DomQuery(document).globalEvalSticky(code, nonce);
}
/**
* builds the ie nodes properly in a placeholder
* and bypasses a non script insert bug that way
* @param markup the markup code to be executed from
*/
static fromMarkup(markup) {
// https:// developer.mozilla.org/de/docs/Web/API/DOMParser license creative commons
const doc = document.implementation.createHTMLDocument("");
markup = trim(markup);
let lowerMarkup = markup.toLowerCase();
if (lowerMarkup.search(/<!doctype[^\w\-]+/gi) != -1 ||
lowerMarkup.search(/<html[^\w\-]+/gi) != -1 ||
lowerMarkup.search(/<head[^\w\-]+/gi) != -1 ||
lowerMarkup.search(/<body[^\w\-]+/gi) != -1) {
doc.documentElement.innerHTML = markup;
return new DomQuery(doc.documentElement);
}
else {
let startsWithTag = function (str, tagName) {
let tag1 = ["<", tagName, ">"].join("");
let tag2 = ["<", tagName, " "].join("");
return (str.indexOf(tag1) == 0) || (str.indexOf(tag2) == 0);
};
let dummyPlaceHolder = new DomQuery(document.createElement("div"));
// table needs special treatment due to the browsers auto creation
if (startsWithTag(lowerMarkup, "thead") || startsWithTag(lowerMarkup, "tbody")) {
dummyPlaceHolder.html(`<table>${markup}</table>`);
return dummyPlaceHolder.querySelectorAll("table").get(0).childNodes.detach();
}
else if (startsWithTag(lowerMarkup, "tfoot")) {
dummyPlaceHolder.html(`<table><thead></thead><tbody><tbody${markup}</table>`);
return dummyPlaceHolder.querySelectorAll("table").get(2).childNodes.detach();
}
else if (startsWithTag(lowerMarkup, "tr")) {
dummyPlaceHolder.html(`<table><tbody>${markup}</tbody></table>`);
return dummyPlaceHolder.querySelectorAll("tbody").get(0).childNodes.detach();
}
else if (startsWithTag(lowerMarkup, "td")) {
dummyPlaceHolder.html(`<table><tbody><tr>${markup}</tr></tbody></table>`);
return dummyPlaceHolder.querySelectorAll("tr").get(0).childNodes.detach();
}
dummyPlaceHolder.html(markup);
return dummyPlaceHolder.childNodes.detach();
}
}
/**
* returns the nth element as DomQuery
* from the internal elements
* note if you try to reach a non-existing element position
* you will get back an absent entry
*
* @param index the nth index
*/
get(index) {
return (index < this.rootNode.length) ? new DomQuery(this.rootNode[index]) : DomQuery.absent;
}
/**
* returns the nth element as optional of an Element object
* @param index the number from the index
* @param defaults the default value if the index is overrun default Optional\.absent
*/
getAsElem(index, defaults = Monad_1.Optional.absent) {
return (index < this.rootNode.length) ? Monad_1.Optional.fromNullable(this.rootNode[index]) : defaults;
}
/**
* returns the files from a given element
* @param index
*/
filesFromElem(index) {
var _a;
return (index < this.rootNode.length) ? ((_a = this.rootNode[index]) === null || _a === void 0 ? void 0 : _a.files) ? this.rootNode[index].files : [] : [];
}
/**
* returns the value array< of all elements
*/
allElems() {
return this.rootNode;
}
/**
* absent no values reached?
*/
isAbsent() {
return this.length == 0;
}
/**
* should make the code clearer
* note if you pass a function
* this refers to the active DomQuery object
*/
isPresent(presentRunnable) {
let absent = this.isAbsent();
if (!absent && presentRunnable) {
presentRunnable.call(this, this);
}
return !absent;
}
/**
* should make the code clearer
* note if you pass a function
* this refers to the active DomQuery object
*
*
* @param presentRunnable
*/
ifPresentLazy(presentRunnable = function () {
}) {
this.isPresent.call(this, presentRunnable);
return this;
}
/**
* remove all affected nodes from this query object from the dom tree
*/
delete() {
this.eachElem((node) => {
if (node.parentNode) {
node.parentNode.removeChild(node);
}
});
}
querySelectorAll(selector) {
// We could merge both methods, but for now this is more readable
if (selector.indexOf("/shadow/") != -1) {
return this._querySelectorAllDeep(selector);
}
else {
return this._querySelectorAll(selector);
}
}
closest(selector) {
// We could merge both methods, but for now this is more readable
if (selector.indexOf("/shadow/") != -1) {
return this._closestDeep(selector);
}
else {
return this._closest(selector);
}
}
/**
* core byId method
* @param id the id to search for
* @param includeRoot also match the root element?
*/
byId(id, includeRoot) {
let res = [];
if (includeRoot) {
res = res.concat(...new Es2019Array_1.Es2019Array(...((this === null || this === void 0 ? void 0 : this.rootNode) || []))
.filter(((item) => id == item.id))
.map(item => new DomQuery(item)));
}
// for some strange kind of reason the # selector fails
// on hidden elements we use the attributes match selector
// that works
res = res.concat(this.querySelectorAll(`[id="${id}"]`));
return new DomQuery(...res);
}
byIdDeep(id, includeRoot) {
let res = [];
if (includeRoot) {
res = res.concat(new Es2019Array_1.Es2019Array(...((this === null || this === void 0 ? void 0 : this.rootNode) || []))
.filter(item => id == item.id)
.map(item => new DomQuery(item)));
}
let subItems = this.querySelectorAllDeep(`[id="${id}"]`);
if (subItems.length) {
res.push(subItems);
}
return new DomQuery(...res);
}
/**
* same as byId just for the tag name
* @param tagName the tag-name to search for
* @param includeRoot shall the root element be part of this search
* @param deep do we also want to go into shadow dom areas
*/
byTagName(tagName, includeRoot, deep) {
var _a;
let res = [];
if (includeRoot) {
res = new Es2019Array_1.Es2019Array(...((_a = this === null || this === void 0 ? void 0 : this.rootNode) !== null && _a !== void 0 ? _a : []))
.filter(element => (element === null || element === void 0 ? void 0 : element.tagName) == tagName)
.reduce((reduction, item) => reduction.concat([item]), res);
}
(deep) ? res.push(this.querySelectorAllDeep(tagName)) : res.push(this.querySelectorAll(tagName));
return new DomQuery(...res);
}
/**
* attr accessor, usage myQuery.attr("class").value = "bla"
* or let value myQuery.attr("class").value
* @param attr the attribute to set
* @param defaultValue the default value in case nothing is presented (defaults to null)
*/
attr(attr, defaultValue = null) {
return new ElementAttribute(this, attr, defaultValue);
}
style(cssProperty, defaultValue = null) {
return new Style(this, cssProperty, defaultValue);
}
/**
* Checks for an existing class in the class attributes
*
* @param clazz the class to search for
*/
hasClass(clazz) {
let hasIt = false;
this.eachElem(node => {
hasIt = node.classList.contains(clazz);
if (hasIt) {
return false;
}
});
return hasIt;
}
/**
* append