jsf.js_next_gen
Version:
A next generation typescript reimplementation of jsf.js
1,273 lines (1,251 loc) • 461 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, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ append: () => (/* binding */ append),
/* harmony export */ appendIf: () => (/* binding */ appendIf),
/* harmony export */ assign: () => (/* binding */ assign),
/* harmony export */ assignIf: () => (/* binding */ assignIf),
/* harmony export */ buildPath: () => (/* binding */ buildPath),
/* harmony export */ deepCopy: () => (/* binding */ deepCopy),
/* harmony export */ deepEqual: () => (/* binding */ deepEqual),
/* harmony export */ resolve: () => (/* binding */ resolve),
/* harmony export */ shallowMerge: () => (/* binding */ shallowMerge),
/* harmony export */ simpleShallowMerge: () => (/* binding */ simpleShallowMerge)
/* harmony export */ });
/* harmony import */ var _Es2019Array__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Es2019Array */ "./node_modules/mona-dish/src/main/typescript/Es2019Array.ts");
/*!
* 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.
*/
/**
* 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;
}
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]];
}
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.pushChunked)(lastPathItem.target[lastPathItem.key], value);
}
}
})();
return appender;
}
/**
* 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);
}
/**
* 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);
}
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;
}
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;
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.pushChunked)(arr, toAdd);
}
function flattenAccessPath(accessPath) {
return new _Es2019Array__WEBPACK_IMPORTED_MODULE_0__.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 };
}
function deepCopy(fromAssoc) {
return JSON.parse(JSON.stringify(fromAssoc));
}
/**
* simple left to right merge
*
* @param assocArrays
*/
function simpleShallowMerge(...assocArrays) {
return shallowMerge(true, false, ...assocArrays);
}
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__WEBPACK_IMPORTED_MODULE_0__.Es2019Array(...[]);
target[key].push(oldVal);
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.pushChunked)(target[key], newVals);
}
else {
let oldVal = target[key];
let newVals = [];
//TODO deep compare here
toAssign.forEach((item) => {
if (oldVal.indexOf(item) == -1) {
newVals.push(item);
}
});
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.pushChunked)(target[key], 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__WEBPACK_IMPORTED_MODULE_0__.Es2019Array(...[]);
target[key].push(oldVal);
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.pushChunked)(target[key], toAssign);
}
else {
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.pushChunked)(target[key], 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__WEBPACK_IMPORTED_MODULE_0__.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__WEBPACK_IMPORTED_MODULE_0__.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;
}
//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
}
/***/ },
/***/ "./node_modules/mona-dish/src/main/typescript/Config.ts"
/*!**************************************************************!*\
!*** ./node_modules/mona-dish/src/main/typescript/Config.ts ***!
\**************************************************************/
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ CONFIG_ANY: () => (/* binding */ CONFIG_ANY),
/* harmony export */ CONFIG_VALUE: () => (/* binding */ CONFIG_VALUE),
/* harmony export */ Config: () => (/* binding */ Config)
/* harmony export */ });
/* harmony import */ var _Es2019Array__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Es2019Array */ "./node_modules/mona-dish/src/main/typescript/Es2019Array.ts");
/* harmony import */ var _Monad__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Monad */ "./node_modules/mona-dish/src/main/typescript/Monad.ts");
/* harmony import */ var _Lang__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Lang */ "./node_modules/mona-dish/src/main/typescript/Lang.ts");
/* harmony import */ var _AssocArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./AssocArray */ "./node_modules/mona-dish/src/main/typescript/AssocArray.ts");
const objAssign = _Lang__WEBPACK_IMPORTED_MODULE_2__.Lang.objAssign;
/**
* specialized value embedder
* for our Configuration
*/
class ConfigEntry extends _Monad__WEBPACK_IMPORTED_MODULE_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);
const CONFIG_VALUE = "__END_POINT__";
const 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__WEBPACK_IMPORTED_MODULE_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__WEBPACK_IMPORTED_MODULE_3__.shallowMerge)(overwrite, withAppend, this.value, other.value);
if (Array.isArray(this._value)) {
this._value.length = 0;
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.pushChunked)(this._value, 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__WEBPACK_IMPORTED_MODULE_3__.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__WEBPACK_IMPORTED_MODULE_3__.appendIf)(condition, this._value, ...accessPath);
}
/**
* assigns a new value on the given access path
* @param accessPath
*/
assign(...accessPath) {
return (0,_AssocArray__WEBPACK_IMPORTED_MODULE_3__.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__WEBPACK_IMPORTED_MODULE_3__.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__WEBPACK_IMPORTED_MODULE_3__.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__WEBPACK_IMPORTED_MODULE_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__WEBPACK_IMPORTED_MODULE_1__.Optional.fromNullable((_b = (_a = (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.Es2019ArrayFrom)(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__WEBPACK_IMPORTED_MODULE_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__WEBPACK_IMPORTED_MODULE_1__.Optional.fromNullable((_f = currAccessPos.value) === null || _f === void 0 ? void 0 : _f[arrPos]) : _Monad__WEBPACK_IMPORTED_MODULE_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__WEBPACK_IMPORTED_MODULE_1__.Optional.fromNullable((_g = (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_0__.Es2019ArrayFrom)(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__WEBPACK_IMPORTED_MODULE_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 == CONFIG_ANY) {
return;
}
}
}
isNoArray(arrPos) {
return arrPos == -1;
}
isArray(arrPos) {
return !this.isNoArray(arrPos);
}
}
/***/ },
/***/ "./node_modules/mona-dish/src/main/typescript/DomQuery.ts"
/*!****************************************************************!*\
!*** ./node_modules/mona-dish/src/main/typescript/DomQuery.ts ***!
\****************************************************************/
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ DQ: () => (/* binding */ DQ),
/* harmony export */ DQ$: () => (/* binding */ DQ$),
/* harmony export */ DomQuery: () => (/* binding */ DomQuery),
/* harmony export */ DomQueryCollector: () => (/* binding */ DomQueryCollector),
/* harmony export */ ElementAttribute: () => (/* binding */ ElementAttribute),
/* harmony export */ Style: () => (/* binding */ Style)
/* harmony export */ });
/* harmony import */ var _Monad__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Monad */ "./node_modules/mona-dish/src/main/typescript/Monad.ts");
/* harmony import */ var _SourcesCollectors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./SourcesCollectors */ "./node_modules/mona-dish/src/main/typescript/SourcesCollectors.ts");
/* harmony import */ var _Lang__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Lang */ "./node_modules/mona-dish/src/main/typescript/Lang.ts");
/* harmony import */ var _Global__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Global */ "./node_modules/mona-dish/src/main/typescript/Global.ts");
/* harmony import */ var _Es2019Array__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Es2019Array */ "./node_modules/mona-dish/src/main/typescript/Es2019Array.ts");
/* harmony import */ var _AssocArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./AssocArray */ "./node_modules/mona-dish/src/main/typescript/AssocArray.ts");
/*!
* 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 = (undefined && undefined.__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());
});
};
const trim = _Lang__WEBPACK_IMPORTED_MODULE_2__.Lang.trim;
const isString = _Lang__WEBPACK_IMPORTED_MODULE_2__.Lang.isString;
const eqi = _Lang__WEBPACK_IMPORTED_MODULE_2__.Lang.equalsIgnoreCase;
const objToArray = _Lang__WEBPACK_IMPORTED_MODULE_2__.Lang.objToArray;
/**
* chunk-safe version of target.prepend(...elements)
* (spreading a large element list overflows the argument stack)
*
* the chunks are prepended in reverse order, so the resulting
* element order is the same as a single prepend call would produce,
* for less than MAX_ARG_LENGTH elements this boils down to exactly
* one native prepend call
*/
function prependChunked(target, elements) {
for (let end = elements.length; end > 0; end -= _Es2019Array__WEBPACK_IMPORTED_MODULE_4__.MAX_ARG_LENGTH) {
const start = Math.max(0, end - _Es2019Array__WEBPACK_IMPORTED_MODULE_4__.MAX_ARG_LENGTH);
target.prepend(...elements.slice(start, end));
}
}
class NonceValueEmbedder extends _Monad__WEBPACK_IMPORTED_MODULE_0__.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;
let timeout;
interval = setInterval(() => {
let found = findElement(root, condition);
if (!!found) {
if (timeout) {
clearTimeout(timeout);
clearInterval(interval);
interval = null;
}
success(new DomQuery(found || root));
}
}, options.interval);
timeout = setTimeout(() => {
if (interval) {
clearInterval(interval);
error(MUT_ERROR);
}
}, options.timeout);
}
});
}
class ElementAttribute extends _Monad__WEBPACK_IMPORTED_MODULE_0__.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);
}
}
getClass() {
return ElementAttribute;
}
static fromNullable(value, valueKey = "value") {
return new ElementAttribute(value, valueKey);
}
}
class Style extends _Monad__WEBPACK_IMPORTED_MODULE_0__.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 Style;
}
static fromNullable(value, valueKey = "value") {
return new Style(value, valueKey);
}
}
/**
* 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__WEBPACK_IMPORTED_MODULE_0__.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()) {
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.pushChunked)(rootNode, foundElement.values);
}
}
else if (rootNode[cnt] instanceof DomQuery) {
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.pushChunked)(this.rootNode, rootNode[cnt].values);
}
else if (Array.isArray(rootNode[cnt])) {
// flatten array arguments into the work list, so large element
// arrays can be passed without spreading them into the call
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.pushChunked)(rootNode, rootNode[cnt]);
}
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__WEBPACK_IMPORTED_MODULE_3__._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__WEBPACK_IMPORTED_MODULE_0__.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__WEBPACK_IMPORTED_MODULE_0__.ValueEmbedder(this.getAsElem(0).value);
}
else {
return _Monad__WEBPACK_IMPORTED_MODULE_0__.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 (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.Es2019ArrayFrom)(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, select, textarea, fieldset");
}
get deepElements() {
let elemStr = "input, select, textarea, 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._collectShadowRoots();
if (shadowRoots.length) {
let shadowRes = new DomQuery(shadowRoots).querySelectorAllDeep(queryStr);
if (shadowRes.length) {
found.push(shadowRes);
}
}
return new DomQuery(found);
}
/**
* Collects the shadow roots hosted by the light-DOM descendants of each root
* node in a single pass.
*
* This replaces the prior `querySelectorAll("*").shadowRoot`, which
* materialized a DomQuery wrapping every element on the page and then walked
* that throwaway collection a second time through the shadowRoot getter. We
* still have to inspect every element - there is no CSS selector for "has a
* shadow root", so the cost stays O(number of elements) - but we drop the
* intermediate all-elements DomQuery and the redundant second traversal.
*
* @private
*/
_collectShadowRoots() {
var _a, _b;
let shadowRoots = [];
for (let cnt = 0; cnt < ((_b = (_a = this === null || this === void 0 ? void 0 : this.rootNode) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0); cnt++) {
let root = this.rootNode[cnt];
if (!(root === null || root === void 0 ? void 0 : root.querySelectorAll)) {
continue;
}
let all = root.querySelectorAll("*");
for (let i = 0, len = all.length; i < len; i++) {
let shadowRoot = all[i].shadowRoot;
if (shadowRoot) {
shadowRoots.push(shadowRoot);
}
}
}
return shadowRoots;
}
/**
* 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) => {
// push the live childNodes list straight into the single target in
// chunks instead of concat(objToArray(...)) per root, which both
// copied each child list and reallocated the growing accumulator
// (O(roots * total children))
(0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.pushChunked)(childNodeArr, item.childNodes);
});
return new DomQuery(childNodeArr);
}
get asArray() {
// filter not supported by IE11
let items = (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.Es2019ArrayFrom)(this.rootNode).filter(item => {
return item != null;
}).map(item => {
return DomQuery.byId(item);
});
return items;
}
get offsetWidth() {
return (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.Es2019ArrayFrom)(this.rootNode)
.filter(item => item != null)
.map(elem => elem.offsetWidth)
.reduce((accumulate, incoming) => accumulate + incoming, 0);
}
get offsetHeight() {
return (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.Es2019ArrayFrom)(this.rootNode)
.filter(item => item != null)
.map(elem => elem.offsetHeight)
.reduce((accumulate, incoming) => accumulate + incoming, 0);
}
get offsetLeft() {
return (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.Es2019ArrayFrom)(this.rootNode)
.filter(item => item != null)
.map(elem => elem.offsetLeft)
.reduce((accumulate, incoming) => accumulate + incoming, 0);
}
get offsetTop() {
return (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.Es2019ArrayFrom)(this.rootNode)
.filter(item => item != null)
.map(elem => elem.offsetTop)
.reduce((accumulate, incoming) => accumulate + incoming, 0);
}
get asNodeArray() {
return (0,_Es2019Array__WEBPACK_IMPORTED_MODULE_4__.Es2019ArrayFrom)(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) {
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")
|| startsWithTag(lowerMarkup, "tfoot")) {
dummyPlaceHolder.html(`<table>${markup}</table>`);
return dummyPlaceHolder.querySelectorAll("table").get(0).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") || startsWithTag(lowerMarkup, "th")) {
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