Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 1.31
  • master
  • 1.10.0
  • 1.30.1
  • 1.31.0
  • 1.8.0
  • 1.9.0
  • 3.100.0
  • 3.100.1
  • 3.100.10
  • 3.100.11
  • 3.100.12
  • 3.100.13
  • 3.100.14
  • 3.100.15
  • 3.100.16
  • 3.100.17
  • 3.100.18
  • 3.100.19
  • 3.100.2
  • 3.100.20
  • 3.100.3
  • 3.100.4
  • 3.100.5
  • 3.100.6
  • 3.100.7
  • 3.100.8
  • 3.100.9
  • 3.101.0
  • 3.101.1
  • 3.101.2
  • 3.101.3
  • 3.102.0
  • 3.102.1
  • 3.102.2
  • 3.102.3
  • 3.102.4
  • 3.102.5
  • 3.102.6
  • 3.103.0
  • 3.103.1
  • 3.104.0
  • 3.104.1
  • 3.105.0
  • 3.105.1
  • 3.105.2
  • 3.106.0
  • 3.106.1
  • 3.107.0
  • 3.108.0
  • 3.108.1
  • 3.108.2
  • 3.108.3
  • 3.108.4
  • 3.108.5
  • 3.109.0
  • 3.110.0
  • 3.110.1
  • 3.110.2
  • 3.110.3
  • 3.110.4
  • 3.111.0
  • 3.112.0
  • 3.112.1
  • 3.112.2
  • 3.112.3
  • 3.112.4
  • 3.113.0
  • 3.114.0
  • 3.114.1
  • 3.114.2
  • 3.114.3
  • 3.114.4
  • 3.114.5
  • 3.114.6
  • 3.114.7
  • 3.115.0
  • 3.115.1
  • 3.115.2
  • 3.115.3
  • 3.115.4
  • 3.116.0
  • 3.116.1
  • 3.117.0
  • 3.117.1
  • 3.117.2
  • 3.117.3
  • 3.118.0
  • 3.118.1
  • 3.119.0
  • 3.120.0
  • 3.121.0
  • 3.51.5
  • 3.52.0
  • 3.52.1
  • 3.53.0
  • 3.54.0
  • 3.55.0
  • 3.55.1
  • 3.55.2
  • 3.55.3
  • 3.55.4
102 results

Target

Select target project
  • oss/libraries/javascript/monster
1 result
Select Git revision
  • 1.31
  • master
  • 1.10.0
  • 1.30.1
  • 1.31.0
  • 1.8.0
  • 1.9.0
  • 3.100.0
  • 3.100.1
  • 3.100.10
  • 3.100.11
  • 3.100.12
  • 3.100.13
  • 3.100.14
  • 3.100.15
  • 3.100.16
  • 3.100.17
  • 3.100.18
  • 3.100.19
  • 3.100.2
  • 3.100.20
  • 3.100.3
  • 3.100.4
  • 3.100.5
  • 3.100.6
  • 3.100.7
  • 3.100.8
  • 3.100.9
  • 3.101.0
  • 3.101.1
  • 3.101.2
  • 3.101.3
  • 3.102.0
  • 3.102.1
  • 3.102.2
  • 3.102.3
  • 3.102.4
  • 3.102.5
  • 3.102.6
  • 3.103.0
  • 3.103.1
  • 3.104.0
  • 3.104.1
  • 3.105.0
  • 3.105.1
  • 3.105.2
  • 3.106.0
  • 3.106.1
  • 3.107.0
  • 3.108.0
  • 3.108.1
  • 3.108.2
  • 3.108.3
  • 3.108.4
  • 3.108.5
  • 3.109.0
  • 3.110.0
  • 3.110.1
  • 3.110.2
  • 3.110.3
  • 3.110.4
  • 3.111.0
  • 3.112.0
  • 3.112.1
  • 3.112.2
  • 3.112.3
  • 3.112.4
  • 3.113.0
  • 3.114.0
  • 3.114.1
  • 3.114.2
  • 3.114.3
  • 3.114.4
  • 3.114.5
  • 3.114.6
  • 3.114.7
  • 3.115.0
  • 3.115.1
  • 3.115.2
  • 3.115.3
  • 3.115.4
  • 3.116.0
  • 3.116.1
  • 3.117.0
  • 3.117.1
  • 3.117.2
  • 3.117.3
  • 3.118.0
  • 3.118.1
  • 3.119.0
  • 3.120.0
  • 3.121.0
  • 3.51.5
  • 3.52.0
  • 3.52.1
  • 3.53.0
  • 3.54.0
  • 3.55.0
  • 3.55.1
  • 3.55.2
  • 3.55.3
  • 3.55.4
102 results
Show changes

Commits on Source 5

Showing
with 384 additions and 247 deletions
<a name="v3.35.0"></a>
## [v3.35.0] - 2023-03-27
### Changes
- tidy and doc
### Documentation
- update
<a name="v3.34.0"></a> <a name="v3.34.0"></a>
## [v3.34.0] - 2023-03-27 ## [v3.34.0] - 2023-03-27
### Add Features ### Add Features
...@@ -488,6 +497,7 @@ ...@@ -488,6 +497,7 @@
<a name="1.8.0"></a> <a name="1.8.0"></a>
## 1.8.0 - 2021-08-15 ## 1.8.0 - 2021-08-15
[v3.35.0]: https://gitlab.schukai.com/oss/libraries/javascript/monster/compare/v3.34.0...v3.35.0
[v3.34.0]: https://gitlab.schukai.com/oss/libraries/javascript/monster/compare/v3.33.0...v3.34.0 [v3.34.0]: https://gitlab.schukai.com/oss/libraries/javascript/monster/compare/v3.33.0...v3.34.0
[v3.33.0]: https://gitlab.schukai.com/oss/libraries/javascript/monster/compare/v3.32.0...v3.33.0 [v3.33.0]: https://gitlab.schukai.com/oss/libraries/javascript/monster/compare/v3.32.0...v3.33.0
[v3.32.0]: https://gitlab.schukai.com/oss/libraries/javascript/monster/compare/v3.31.1...v3.32.0 [v3.32.0]: https://gitlab.schukai.com/oss/libraries/javascript/monster/compare/v3.31.1...v3.32.0
......
{ {
"name": "@schukai/monster", "name": "@schukai/monster",
"version": "3.33.0", "version": "3.34.0",
"description": "Monster is a simple library for creating fast, robust and lightweight websites.", "description": "Monster is a simple library for creating fast, robust and lightweight websites.",
"keywords": [ "keywords": [
"framework", "framework",
......
...@@ -19,27 +19,26 @@ export { buildMap, PARENT, assembleParts }; ...@@ -19,27 +19,26 @@ export { buildMap, PARENT, assembleParts };
const PARENT = "^"; const PARENT = "^";
/** /**
* With the help of the function `buildMap()`, maps can be easily created from data objects. * Maps can be easily created from data objects with the help of the function `buildMap()`.
* *
* Either a simple definition `a.b.c` or a template `${a.b.c}` can be specified as the path. * The path can be specified as either a simple definition a.b.c or a template ${a.b.c}.
* Key and value can be either a definition or a template. The key does not have to be defined. * Key and value can be either a definition or a template. The key does not have to be defined.
*
* The templates determine the appearance of the keys and the value of the map. Either a single value * The templates determine the appearance of the keys and the value of the map. Either a single value
* `id` can be taken or a composite key `${id} ${name}` can be used. * id can be taken or a composite key ${id} ${name} can be used.
* *
* If you want to access values of the parent data set, you have to use the `^` character `${id} ${^.name}`. * If you want to access values of the parent data set, you have to use the ^ character, for example ${id} ${^.name}.
* *
* @externalExample ../../example/data/buildmap.mjs * @externalExample ../../example/data/buildmap.mjs
* @param {*} subject * @param {*} subject - The data object from which the map will be created
* @param {string|Monster.Data~exampleSelectorCallback} selector * @param {string|Monster.Data~exampleSelectorCallback} selector - The path to the data object, or a callback that returns a map.
* @param {string} [valueTemplate] * @param {string} [valueTemplate] - A template for the value of the map.
* @param {string} [keyTemplate] * @param {string} [keyTemplate] - A template for the key of the map.
* @param {Monster.Data~exampleFilterCallback} [filter] * @param {Monster.Data~exampleFilterCallback} [filter] - A callback function to filter out values.
* @return {*} * @return {*} - The created map.
* @memberOf Monster.Data * @memberOf Monster.Data
* @throws {TypeError} value is neither a string nor a function * @throws {TypeError} - If the value is neither a string nor a function.
* @throws {TypeError} the selector callback must return a map * @throws {TypeError} - If the selector callback does not return a map.
*/ **/
function buildMap(subject, selector, valueTemplate, keyTemplate, filter) { function buildMap(subject, selector, valueTemplate, keyTemplate, filter) {
return assembleParts(subject, selector, filter, function (v, k, m) { return assembleParts(subject, selector, filter, function (v, k, m) {
k = build(v, keyTemplate, k); k = build(v, keyTemplate, k);
...@@ -49,13 +48,66 @@ function buildMap(subject, selector, valueTemplate, keyTemplate, filter) { ...@@ -49,13 +48,66 @@ function buildMap(subject, selector, valueTemplate, keyTemplate, filter) {
} }
/** /**
* The assembleParts function is a private function that helps in building a map from a subject object based on a provided
* selector. The selector can either be a string or a callback function. This function is meant to be used as a
* helper function by other functions in the module.
*
* The function takes four parameters:
*
* subject: The subject object from which the map is to be built
* selector: The selector to determine the structure of the map. It can be a string or a callback function.
* filter (optional): A callback function that can be used to filter values based on some criteria.
* callback: A function to be called for each element in the map.
* If the selector parameter is a callback function, it is executed passing the subject as its argument,
* and the resulting value must be an instance of Map. Otherwise, if the selector parameter is a string,
* buildFlatMap is called to build a flat map with keys and values extracted from the subject object based on the selector.
*
* If the filter parameter is provided, it will be used to filter out certain elements from the map, based on some
* criteria. The callback will be passed the value, key, and map object, and if it returns false, the element will be skipped.
*
* For each element in the map, the callback function is called with the following parameters:
*
* v: The value of the element
* k: The key of the element
* m: The map object
* The function returns a new map with the processed values. If map is not an instance of Map, an empty map will be returned.
*
* Example Usage:
*
* ```javascript
* const obj = {
* name: "John",
* age: 30,
* address: {
* city: "New York",
* state: "NY",
* country: "USA",
* },
* };
*
* const selector = "address";
*
* const map = assembleParts(obj, selector, null, function (v, k, m) {
* this.set(k, v);
* });
*
* console.log(map);
* // Output: Map(3) {
* // "address.city" => "New York",
* // "address.state" => "NY",
* // "address.country" => "USA"
* // }
* ```
*
*
* @private * @private
* @param {*} subject * @param {*} subject - The subject object from which the map is to be built.
* @param {string|Monster.Data~exampleSelectorCallback} selector * @param {string|Monster.Data~exampleSelectorCallback} selector - The selector to determine the structure of the map. It can be a string or a callback function.
* @param {Monster.Data~exampleFilterCallback} [filter] * @param {Monster.Data~exampleFilterCallback} [filter] - A callback function that can be used to filter values based on some criteria.
* @param {function} callback * @param {function} callback - A function to be called for each element in the map.
* @return {Map} * @return {Map} - A new map with the processed values.
* @throws {TypeError} selector is neither a string nor a function * @throws {TypeError} - When selector is neither a string nor a function.
* @memberOf Monster.Data
*/ */
function assembleParts(subject, selector, filter, callback) { function assembleParts(subject, selector, filter, callback) {
const result = new Map(); const result = new Map();
......
...@@ -33,19 +33,102 @@ const rootSymbol = Symbol("root"); ...@@ -33,19 +33,102 @@ const rootSymbol = Symbol("root");
*/ */
/** /**
* With the help of the function `buildTree()`, nodes can be easily created from data objects. * Creates a tree structure from a given subject using a selector and specified ID and parent ID keys.
* *
* @param {*} subject * The buildTree function is a powerful tool for creating tree-like data structures from plain JavaScript
* @param {string|Monster.Data~exampleSelectorCallback} selector * objects. It takes in four required parameters: the subject object that you want to turn into a tree, a
* @param {string} idKey * selector that identifies which parts of the subject to use when building the tree, and two keys
* @param {string} parentIDKey * (idKey and parentIDKey) that specify which properties in the subject represent the unique identifiers
* @param {buildTreeOptions} [options] * and parent-child relationships between nodes in the tree.
* @return {*} *
* @memberOf Monster.Data * Optionally, you can also pass in an options object to further configure the behavior of the function,
* @throws {TypeError} value is neither a string nor a function * such as specifying which values should be treated as roots of the tree, or providing a custom filter
* @throws {TypeError} the selector callback must return a map * function to only include certain nodes in the final output.
* @throws {Error} the object has no value for the specified id *
* The buildTree function works by first using the assembleParts helper function to extract the relevant
* parts of the subject based on the selector, and then iterates over the resulting map to create Node
* objects and organize them into parent-child relationships based on the values of the idKey and parentIDKey properties.
*
* The resulting NodeList represents the tree structure, with each Node object containing the original
* object data as well as additional metadata about its position in the tree. You can then use the childNodes
* property of each Node to access its children, or the parent property to access its parent.
*
* Overall, the buildTree function is a flexible and powerful way to transform flat data into hierarchical
* structures, and can be especially useful in scenarios such as displaying folder structures or
* visualizing complex data relationships.
*
* Let's say you have an array of data objects representing a file system directory structure, and you want
* to turn it into a tree-like structure where each node represents a folder or file, and child nodes
* represent the contents of the folder:
*
* ```javascript
* const fileSystem = [
* { id: 'folder1', name: 'Folder 1', type: 'folder', parent: null },
* { id: 'file1', name: 'File 1', type: 'file', parent: 'folder1' },
* { id: 'file2', name: 'File 2', type: 'file', parent: 'folder1' },
* { id: 'subfolder1', name: 'Subfolder 1', type: 'folder', parent: 'folder1' },
* { id: 'file3', name: 'File 3', type: 'file', parent: 'subfolder1' },
* { id: 'file4', name: 'File 4', type: 'file', parent: 'subfolder1' },
* { id: 'subfolder2', name: 'Subfolder 2', type: 'folder', parent: 'folder1' },
* { id: 'file5', name: 'File 5', type: 'file', parent: 'subfolder2' },
* { id: 'file6', name: 'File 6', type: 'file', parent: 'subfolder2' },
* { id: 'folder2', name: 'Folder 2', type: 'folder', parent: null },
* { id: 'file7', name: 'File 7', type: 'file', parent: 'folder2' },
* { id: 'file8', name: 'File 8', type: 'file', parent: 'folder2' },
* { id: 'subfolder3', name: 'Subfolder 3', type: 'folder', parent: 'folder2' },
* { id: 'file9', name: 'File 9', type: 'file', parent: 'subfolder3' },
* { id: 'file10', name: 'File 10', type: 'file', parent: 'subfolder3' },
* ];
*
* const tree = buildTree(fileSystem, 'id', 'id', 'parent', { rootReferences: [null] });
*
* console.log(tree.toString());
* ```
*
* The buildTree function takes in the array of data objects, as well as some configuration options specifying
* the keys to use for identifying nodes and their parent-child relationships. In this example, we use the id
* key to identify nodes, and the parent key to specify the parent of each node.
*
* The resulting tree object is a nested tree structure, where each node is an object representing a file or
* folder, and has child nodes representing its contents. The toString method of the tree object
* can be used to print out the tree in a readable format:
*
* ```markdown
* - Folder 1
* - File 1
* - File 2
* - Subfolder 1
* - File 3
* - File 4
* - Subfolder 2
* - File 5
* - File 6
* - Folder 2
* - File 7
* - File 8
* - Subfolder 3
* - File 9
* - File 10
* ```
*
* @memberof Monster.Data
*
* @param {*} subject - The object or array to build the tree from.
* @param {string|Monster.Data~exampleSelectorCallback} selector - Either a string to specify a property of each object to use as a selector, or a selector function to generate a map of objects.
* @param {string} idKey - The property key to use as the unique ID of each node.
* @param {string} parentIDKey - The property key to use as the parent ID of each node.
* @param {object} [options] - Additional options to modify the function behavior.
* @param {Array<*>} [options.rootReferences=[null, undefined]] - An array of values to treat as root references when creating the tree.
* @param {function} [options.filter] - A filter function to apply to each node.
*
* @return {*} The resulting tree structure as a NodeList.
*
* @throws {TypeError} selector is neither a string nor a function.
* @throws {TypeError} the selector callback must return a map.
* @throws {Error} the object has no value for the specified id.
*
* @license AGPLv3 * @license AGPLv3
*
* @since 1.26.0 * @since 1.26.0
*/ */
function buildTree(subject, selector, idKey, parentIDKey, options) { function buildTree(subject, selector, idKey, parentIDKey, options) {
......
...@@ -11,7 +11,6 @@ import { Datasource } from "../datasource.mjs"; ...@@ -11,7 +11,6 @@ import { Datasource } from "../datasource.mjs";
export { DomStorage }; export { DomStorage };
/** /**
* The DomStorage is a class that stores data in memory. * The DomStorage is a class that stores data in memory.
* *
...@@ -53,7 +52,7 @@ class DomStorage extends Datasource { ...@@ -53,7 +52,7 @@ class DomStorage extends Datasource {
}, },
write: { write: {
selector: undefined, selector: undefined,
} },
}); });
} }
...@@ -78,13 +77,12 @@ class DomStorage extends Datasource { ...@@ -78,13 +77,12 @@ class DomStorage extends Datasource {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
let data = JSON.parse(storage.innerHTML); let data = JSON.parse(storage.innerHTML);
self.set(data) self.set(data);
resolve(data); resolve(data);
} catch (e) { } catch (e) {
reject(e); reject(e);
} }
; });
})
} }
/** /**
...@@ -93,7 +91,6 @@ class DomStorage extends Datasource { ...@@ -93,7 +91,6 @@ class DomStorage extends Datasource {
* @throws {Error} There are no storage element * @throws {Error} There are no storage element
*/ */
write() { write() {
const self = this; const self = this;
let selector = self.getOption("write.selector"); let selector = self.getOption("write.selector");
...@@ -113,10 +110,6 @@ class DomStorage extends Datasource { ...@@ -113,10 +110,6 @@ class DomStorage extends Datasource {
} catch (e) { } catch (e) {
reject(e); reject(e);
} }
}) });
} }
} }
...@@ -127,7 +127,8 @@ class RestAPI extends Server { ...@@ -127,7 +127,8 @@ class RestAPI extends Server {
if (!init["method"]) init["method"] = "GET"; if (!init["method"]) init["method"] = "GET";
let callback = self.getOption("read.responseCallback"); let callback = self.getOption("read.responseCallback");
if(!callback) callback = (obj) => { if (!callback)
callback = (obj) => {
self.set(self.transformServerPayload.call(self, obj)); self.set(self.transformServerPayload.call(self, obj));
}; };
...@@ -199,7 +200,6 @@ function fetchData(init, key, callback) { ...@@ -199,7 +200,6 @@ function fetchData(init, key, callback) {
obj = JSON.parse(body); obj = JSON.parse(body);
response[rawDataSymbol] = obj; response[rawDataSymbol] = obj;
} catch (e) { } catch (e) {
if (body.length > 100) { if (body.length > 100) {
body = `${body.substring(0, 97)}...`; body = `${body.substring(0, 97)}...`;
......
...@@ -576,7 +576,6 @@ function transform(value) { ...@@ -576,7 +576,6 @@ function transform(value) {
throw new Error("type not supported"); throw new Error("type not supported");
case "map": case "map":
map = new Map(); map = new Map();
while (args.length > 0) { while (args.length > 0) {
...@@ -592,7 +591,6 @@ function transform(value) { ...@@ -592,7 +591,6 @@ function transform(value) {
return map.get(value); return map.get(value);
case "equals": case "equals":
if (args.length === 0) { if (args.length === 0) {
throw new Error("missing value parameter"); throw new Error("missing value parameter");
} }
...@@ -631,11 +629,10 @@ function transform(value) { ...@@ -631,11 +629,10 @@ function transform(value) {
case "money": case "money":
case "currency": case "currency":
try { try {
locale = getLocaleOfDocument(); locale = getLocaleOfDocument();
} catch (e) { } catch (e) {
throw new Error("unsupported locale or missing format (" + e.message + ")"); throw new Error(`unsupported locale or missing format (${e.message})`);
} }
const currency = value.substring(0, 3); const currency = value.substring(0, 3);
...@@ -672,9 +669,8 @@ function transform(value) { ...@@ -672,9 +669,8 @@ function transform(value) {
try { try {
locale = getLocaleOfDocument(); locale = getLocaleOfDocument();
return date.toLocaleTimeString(locale); return date.toLocaleTimeString(locale);
} catch (e) { } catch (e) {
throw new Error("unsupported locale or missing format (" + e.message + ")"); throw new Error(`unsupported locale or missing format (${e.message})`);
} }
case "datetime": case "datetime":
...@@ -686,9 +682,8 @@ function transform(value) { ...@@ -686,9 +682,8 @@ function transform(value) {
try { try {
locale = getLocaleOfDocument(); locale = getLocaleOfDocument();
return date.toLocaleString(locale); return date.toLocaleString(locale);
} catch (e) { } catch (e) {
throw new Error("unsupported locale or missing format (" + e.message + ")"); throw new Error(`unsupported locale or missing format (${e.message})`);
} }
case "date": case "date":
...@@ -700,12 +695,10 @@ function transform(value) { ...@@ -700,12 +695,10 @@ function transform(value) {
try { try {
locale = getLocaleOfDocument(); locale = getLocaleOfDocument();
return date.toLocaleDateString(locale); return date.toLocaleDateString(locale);
} catch (e) { } catch (e) {
throw new Error("unsupported locale or missing format (" + e.message + ")"); throw new Error(`unsupported locale or missing format (${e.message})`);
} }
case "year": case "year":
date = new Date(value); date = new Date(value);
if (isNaN(date.getTime())) { if (isNaN(date.getTime())) {
......
...@@ -286,7 +286,6 @@ class CustomElement extends HTMLElement { ...@@ -286,7 +286,6 @@ class CustomElement extends HTMLElement {
}; };
} }
/** /**
* This method updates the labels of the element. * This method updates the labels of the element.
* The labels are defined in the options object. * The labels are defined in the options object.
...@@ -315,7 +314,7 @@ class CustomElement extends HTMLElement { ...@@ -315,7 +314,7 @@ class CustomElement extends HTMLElement {
if (isString(def)) { if (isString(def)) {
const text = translations.getText(key, def); const text = translations.getText(key, def);
if (text !== def) { if (text !== def) {
this.setOption("labels." + key, text); this.setOption(`labels.${key}`, text);
} }
continue; continue;
} else if (isObject(def)) { } else if (isObject(def)) {
...@@ -327,14 +326,13 @@ class CustomElement extends HTMLElement { ...@@ -327,14 +326,13 @@ class CustomElement extends HTMLElement {
throw new Error("Invalid labels definition"); throw new Error("Invalid labels definition");
} }
if (text !== d) { if (text !== d) {
this.setOption("labels." + key + "." + k, text); this.setOption(`labels.${key}.${k}`, text);
} }
} }
continue; continue;
} }
throw new Error("Invalid labels definition"); throw new Error("Invalid labels definition");
} }
return this; return this;
} }
...@@ -352,7 +350,6 @@ class CustomElement extends HTMLElement { ...@@ -352,7 +350,6 @@ class CustomElement extends HTMLElement {
throw new Error("the method getTag must be overwritten by the derived class."); throw new Error("the method getTag must be overwritten by the derived class.");
} }
/** /**
* At this point a `CSSStyleSheet` object can be returned. If the environment does not * At this point a `CSSStyleSheet` object can be returned. If the environment does not
* support a constructor, then an object can also be built using the following detour. * support a constructor, then an object can also be built using the following detour.
...@@ -422,8 +419,7 @@ class CustomElement extends HTMLElement { ...@@ -422,8 +419,7 @@ class CustomElement extends HTMLElement {
try { try {
value = new Pathfinder(this[internalSymbol].getRealSubject()["options"]).getVia(path); value = new Pathfinder(this[internalSymbol].getRealSubject()["options"]).getVia(path);
} catch (e) { } catch (e) {}
}
if (value === undefined) return defaultValue; if (value === undefined) return defaultValue;
return value; return value;
...@@ -493,8 +489,7 @@ class CustomElement extends HTMLElement { ...@@ -493,8 +489,7 @@ class CustomElement extends HTMLElement {
try { try {
initShadowRoot.call(self); initShadowRoot.call(self);
elements = self.shadowRoot.childNodes; elements = self.shadowRoot.childNodes;
} catch (e) { } catch (e) {}
}
try { try {
initCSSStylesheet.call(this); initCSSStylesheet.call(this);
...@@ -545,8 +540,7 @@ class CustomElement extends HTMLElement { ...@@ -545,8 +540,7 @@ class CustomElement extends HTMLElement {
* @return {void} * @return {void}
* @since 1.7.0 * @since 1.7.0
*/ */
disconnectedCallback() { disconnectedCallback() {}
}
/** /**
* The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)). * The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)).
...@@ -554,8 +548,7 @@ class CustomElement extends HTMLElement { ...@@ -554,8 +548,7 @@ class CustomElement extends HTMLElement {
* @return {void} * @return {void}
* @since 1.7.0 * @since 1.7.0
*/ */
adoptedCallback() { adoptedCallback() {}
}
/** /**
* Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
...@@ -792,8 +785,7 @@ function parseOptionsJSON(data) { ...@@ -792,8 +785,7 @@ function parseOptionsJSON(data) {
try { try {
let dataUrl = parseDataURL(data); let dataUrl = parseDataURL(data);
data = dataUrl.content; data = dataUrl.content;
} catch (e) { } catch (e) {}
}
try { try {
obj = JSON.parse(data); obj = JSON.parse(data);
...@@ -815,7 +807,6 @@ function initHtmlContent() { ...@@ -815,7 +807,6 @@ function initHtmlContent() {
} catch (e) { } catch (e) {
let html = this.getOption("templates.main", ""); let html = this.getOption("templates.main", "");
if (isString(html) && html.length > 0) { if (isString(html) && html.length > 0) {
const mapping = this.getOption("templateMapping", {}); const mapping = this.getOption("templateMapping", {});
if (isObject(mapping)) { if (isObject(mapping)) {
html = new Formatter(mapping).format(html); html = new Formatter(mapping).format(html);
...@@ -938,7 +929,7 @@ function initShadowRoot() { ...@@ -938,7 +929,7 @@ function initShadowRoot() {
*/ */
function registerCustomElement(element) { function registerCustomElement(element) {
validateFunction(element); validateFunction(element);
const customElements = getGlobalObject("customElements") const customElements = getGlobalObject("customElements");
if (customElements === undefined) { if (customElements === undefined) {
throw new Error("customElements is not supported."); throw new Error("customElements is not supported.");
} }
......
...@@ -5,21 +5,22 @@ ...@@ -5,21 +5,22 @@
* License text available at https://www.gnu.org/licenses/agpl-3.0.en.html * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
*/ */
import {getWindow} from './util.mjs'; import { getWindow } from "./util.mjs";
export {convertToPixels, getDeviceDPI}
export { convertToPixels, getDeviceDPI };
/** /**
* Stores the DPI of the device. * Stores the DPI of the device.
* *
* @private
* @returns {number} * @returns {number}
* @type {number} * @since 3.34.0
* @type {number|function}
*/ */
let CURRENT_DEVICE_DPI = function () { let CURRENT_DEVICE_DPI = function () {
let i = 0; let i = 0;
for (i = 56; i < 2000; i++) { for (i = 56; i < 2000; i++) {
if (getWindow().matchMedia("(max-resolution: " + i + "dpi)").matches === true) { if (getWindow().matchMedia(`(max-resolution: ${i}dpi)`).matches === true) {
return i; return i;
} }
} }
...@@ -29,18 +30,19 @@ let CURRENT_DEVICE_DPI = function () { ...@@ -29,18 +30,19 @@ let CURRENT_DEVICE_DPI = function () {
/** /**
* Returns the DPI of the device. * Returns the DPI of the device.
* *
* @since 3.34.0
* @memberOf Monster.DOM
* @returns {number} * @returns {number}
*/ */
function getDeviceDPI() { function getDeviceDPI() {
// only call the function once // only call the function once
if (typeof CURRENT_DEVICE_DPI === 'function') { if (typeof CURRENT_DEVICE_DPI === "function") {
CURRENT_DEVICE_DPI = CURRENT_DEVICE_DPI(); CURRENT_DEVICE_DPI = CURRENT_DEVICE_DPI();
} }
return getWindow().devicePixelRatio * CURRENT_DEVICE_DPI; return getWindow().devicePixelRatio * CURRENT_DEVICE_DPI;
} }
/** /**
* Converts a CSS value to pixels. * Converts a CSS value to pixels.
* *
...@@ -59,15 +61,15 @@ function getDeviceDPI() { ...@@ -59,15 +61,15 @@ function getDeviceDPI() {
* - rem * - rem
* - % * - %
* *
* @param value * @param {string} value
* @param parentElement * @param {HTMLElement} [parentElement=document.documentElement]
* @param fontSizeElement * @param {HTMLElement} [fontSizeElement=document.documentElement]
* @returns {number} * @returns {number}
* @license AGPLv3 * @license AGPLv3
* @since 1.6.0 * @since 3.34.0
* @copyright schukai GmbH * @copyright schukai GmbH
* @memberOf Monster.DOM
* @throws {Error} Unsupported unit * @throws {Error} Unsupported unit
* @memberOf Monster.DOM
*/ */
function convertToPixels(value, parentElement = document.documentElement, fontSizeElement = document.documentElement) { function convertToPixels(value, parentElement = document.documentElement, fontSizeElement = document.documentElement) {
...@@ -76,30 +78,28 @@ function convertToPixels(value, parentElement = document.documentElement, fontSi ...@@ -76,30 +78,28 @@ function convertToPixels(value, parentElement = document.documentElement, fontSi
const number = parseFloat(num); const number = parseFloat(num);
const dpi = getDeviceDPI(); const dpi = getDeviceDPI();
if (unit === 'px') { if (unit === "px") {
return number; return number;
} else if (unit === 'em') { } else if (unit === "em") {
const fontSize = parseFloat(window.getComputedStyle(fontSizeElement).fontSize); const fontSize = parseFloat(window.getComputedStyle(fontSizeElement).fontSize);
return number * fontSize; return number * fontSize;
} else if (unit === 'rem') { } else if (unit === "rem") {
const rootFontSize = parseFloat(window.getComputedStyle(parentElement).fontSize); const rootFontSize = parseFloat(window.getComputedStyle(parentElement).fontSize);
return number * rootFontSize; return number * rootFontSize;
} else if (unit === '%') { } else if (unit === "%") {
const parentWidth = parseFloat(window.getComputedStyle(parentElement).width); const parentWidth = parseFloat(window.getComputedStyle(parentElement).width);
return (number * parentWidth) / 100; return (number * parentWidth) / 100;
} else if (unit === 'in') { } else if (unit === "in") {
return number * dpi; return number * dpi;
} else if (unit === 'cm') { } else if (unit === "cm") {
return (number * dpi) / 2.54; return (number * dpi) / 2.54;
} else if (unit === 'mm') { } else if (unit === "mm") {
return (number * dpi) / 25.4; return (number * dpi) / 25.4;
} else if (unit === 'pt') { } else if (unit === "pt") {
return (number * dpi) / 72; return (number * dpi) / 72;
} else if (unit === 'pc') { } else if (unit === "pc") {
return (number * dpi) / 6; return (number * dpi) / 6;
} else { } else {
throw new Error(`Unsupported unit: ${unit}`); throw new Error(`Unsupported unit: ${unit}`);
} }
} }
...@@ -74,14 +74,17 @@ class ResourceManager extends Base { ...@@ -74,14 +74,17 @@ class ResourceManager extends Base {
* @property {Array} resources.data=[] array with {@link Monster.DOM.Resource.Data} objects * @property {Array} resources.data=[] array with {@link Monster.DOM.Resource.Data} objects
*/ */
get internalDefaults() { get internalDefaults() {
return Object.assign({}, { return Object.assign(
{},
{
document: getGlobalObject("document"), document: getGlobalObject("document"),
resources: { resources: {
scripts: [], scripts: [],
stylesheets: [], stylesheets: [],
data: [], data: [],
}, },
}); },
);
} }
/** /**
......
...@@ -57,7 +57,6 @@ function getSlottedNodes(query, name) { ...@@ -57,7 +57,6 @@ function getSlottedNodes(query, name) {
return result; return result;
} }
/** /**
* @private * @private
* @param {String|undefined} query * @param {String|undefined} query
......
...@@ -17,7 +17,7 @@ import { ...@@ -17,7 +17,7 @@ import {
ATTRIBUTE_UPDATER_INSERT_REFERENCE, ATTRIBUTE_UPDATER_INSERT_REFERENCE,
ATTRIBUTE_UPDATER_REMOVE, ATTRIBUTE_UPDATER_REMOVE,
ATTRIBUTE_UPDATER_REPLACE, ATTRIBUTE_UPDATER_REPLACE,
ATTRIBUTE_UPDATER_SELECT_THIS ATTRIBUTE_UPDATER_SELECT_THIS,
} from "../dom/constants.mjs"; } from "../dom/constants.mjs";
import { Base } from "../types/base.mjs"; import { Base } from "../types/base.mjs";
......
...@@ -152,7 +152,6 @@ function getDocumentFragmentFromString(html) { ...@@ -152,7 +152,6 @@ function getDocumentFragmentFromString(html) {
return template.content; return template.content;
} }
/** /**
* Recursively searches upwards from a given element to find an ancestor element * Recursively searches upwards from a given element to find an ancestor element
* with a specified ID, considering both normal DOM and shadow DOM. * with a specified ID, considering both normal DOM and shadow DOM.
......
...@@ -33,7 +33,6 @@ const translationsLinkSymbol = Symbol.for("@schukai/monster/i18n/translations@@l ...@@ -33,7 +33,6 @@ const translationsLinkSymbol = Symbol.for("@schukai/monster/i18n/translations@@l
* @see {@link https://datatracker.ietf.org/doc/html/rfc3066} * @see {@link https://datatracker.ietf.org/doc/html/rfc3066}
*/ */
class Provider extends BaseWithOptions { class Provider extends BaseWithOptions {
/** /**
* This method is called by the `instanceof` operator. * This method is called by the `instanceof` operator.
* @returns {symbol} * @returns {symbol}
...@@ -48,7 +47,6 @@ class Provider extends BaseWithOptions { ...@@ -48,7 +47,6 @@ class Provider extends BaseWithOptions {
* @return {Promise} * @return {Promise}
*/ */
getTranslations(locale) { getTranslations(locale) {
if (locale === undefined) { if (locale === undefined) {
locale = getLocaleOfDocument(); locale = getLocaleOfDocument();
} }
...@@ -68,7 +66,6 @@ class Provider extends BaseWithOptions { ...@@ -68,7 +66,6 @@ class Provider extends BaseWithOptions {
* @return {Provider} * @return {Provider}
*/ */
assignToElement(locale, element) { assignToElement(locale, element) {
if (locale === undefined) { if (locale === undefined) {
locale = getLocaleOfDocument(); locale = getLocaleOfDocument();
} }
...@@ -86,7 +83,6 @@ class Provider extends BaseWithOptions { ...@@ -86,7 +83,6 @@ class Provider extends BaseWithOptions {
} }
return this.getTranslations(locale).then((obj) => { return this.getTranslations(locale).then((obj) => {
let translations = null; let translations = null;
if (hasObjectLink(element, translationsLinkSymbol)) { if (hasObjectLink(element, translationsLinkSymbol)) {
const objects = getLinkedObjects(element, translationsLinkSymbol); const objects = getLinkedObjects(element, translationsLinkSymbol);
...@@ -102,15 +98,11 @@ class Provider extends BaseWithOptions { ...@@ -102,15 +98,11 @@ class Provider extends BaseWithOptions {
} }
translations.assignTranslations(obj); translations.assignTranslations(obj);
} else { } else {
addToObjectLink(element, translationsLinkSymbol, obj); addToObjectLink(element, translationsLinkSymbol, obj);
} }
return obj; return obj;
}); });
} }
} }
...@@ -91,7 +91,6 @@ class Embed extends Provider { ...@@ -91,7 +91,6 @@ class Embed extends Provider {
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (this.translateElement === null) { if (this.translateElement === null) {
reject(new Error("Text not found")); reject(new Error("Text not found"));
return; return;
...@@ -127,7 +126,6 @@ class Embed extends Provider { ...@@ -127,7 +126,6 @@ class Embed extends Provider {
}); });
} }
/** /**
* Initializes the translations for the current document. * Initializes the translations for the current document.
* *
...@@ -137,7 +135,7 @@ class Embed extends Provider { ...@@ -137,7 +135,7 @@ class Embed extends Provider {
* @returns {Promise<unknown[]>} * @returns {Promise<unknown[]>}
*/ */
static assignTranslationsToElement(element) { static assignTranslationsToElement(element) {
const d = getDocument() const d = getDocument();
if (!(element instanceof HTMLElement)) { if (!(element instanceof HTMLElement)) {
element = d.querySelector("body"); element = d.querySelector("body");
...@@ -157,5 +155,4 @@ class Embed extends Provider { ...@@ -157,5 +155,4 @@ class Embed extends Provider {
return Promise.all(promises); return Promise.all(promises);
} }
} }
...@@ -15,7 +15,6 @@ import {validateInteger, validateObject, validateString} from "../types/validate ...@@ -15,7 +15,6 @@ import {validateInteger, validateObject, validateString} from "../types/validate
import { Locale, parseLocale } from "./locale.mjs"; import { Locale, parseLocale } from "./locale.mjs";
import { translationsLinkSymbol } from "./provider.mjs"; import { translationsLinkSymbol } from "./provider.mjs";
export { Translations, getDocumentTranslations }; export { Translations, getDocumentTranslations };
/** /**
...@@ -208,13 +207,13 @@ class Translations extends Base { ...@@ -208,13 +207,13 @@ class Translations extends Base {
* @throws {Error} Cannot find element with translations. Add a translations object to the document. * @throws {Error} Cannot find element with translations. Add a translations object to the document.
* @throws {Error} This element has no translations. * @throws {Error} This element has no translations.
* @throws {Error} Missing translations. * @throws {Error} Missing translations.
* @memberOf Monster.I18n
*/ */
function getDocumentTranslations(element) { function getDocumentTranslations(element) {
const d = getDocument();
const d = getDocument()
if (!(element instanceof HTMLElement)) { if (!(element instanceof HTMLElement)) {
element = d.querySelector('[' + ATTRIBUTE_OBJECTLINK + '~="' + translationsLinkSymbol.toString() + '"]'); element = d.querySelector(`[${ATTRIBUTE_OBJECTLINK}~="${translationsLinkSymbol.toString()}"]`);
if (element === null) { if (element === null) {
throw new Error("Cannot find element with translations. Add a translations object to the document."); throw new Error("Cannot find element with translations. Add a translations object to the document.");
} }
...@@ -237,7 +236,4 @@ function getDocumentTranslations(element) { ...@@ -237,7 +236,4 @@ function getDocumentTranslations(element) {
} }
throw new Error("Missing translations."); throw new Error("Missing translations.");
} }
export {generateRangeComparisonExpression} export { generateRangeComparisonExpression };
/** /**
* Generates a comparison expression for a comma-separated string of ranges and single values. * The `generateRangeComparisonExpression()` function is function that generates a string representation
* of a comparison expression based on a range of values. It takes three arguments:
*
* - expression (required): a string representation of a range of values in the format of start1-end1,start2-end2,value3....
* - valueName (required): a string representing the name of the value that is being compared to the range of values.
* - options (optional): an object containing additional options to customize the comparison expression.
*
* The generateRangeComparisonExpression() function returns a string representation of the comparison expression.
*
* ## Options
* The options parameter is an object that can have the following properties:
*
* urlEncode (boolean, default: false): if set to true, URL encodes the comparison operators.
* andOp (string, default: '&&'): the logical AND operator to use in the expression.
* orOp (string, default: '||'): the logical OR operator to use in the expression.
* eqOp (string, default: '=='): the equality operator to use in the expression.
* geOp (string, default: '>='): the greater than or equal to operator to use in the expression.
* leOp (string, default: '<='): the less than or equal to operator to use in the expression.
*
* Examples
*
* ```javascript
* const expression = '0-10,20-30';
* const valueName = 'age';
* const options = { urlEncode: true, andOp: 'and', orOp: 'or', eqOp: '=', geOp: '>=', leOp: '<=' };
* const comparisonExpression = generateRangeComparisonExpression(expression, valueName, options);
*
* console.log(comparisonExpression); // age%3E%3D0%20and%20age%3C%3D10%20or%20age%3E%3D20%20and%20age%3C%3D30
* ```
*
* In this example, the generateRangeComparisonExpression() function generates a string representation of the comparison
* expression for the expression and valueName parameters with the specified options. The resulting comparison
* expression is 'age>=0 and age<=10 or age>=20 and age<=30', URL encoded according to the urlEncode option.
*
* @param {string} expression - The string expression to generate the comparison for. * @param {string} expression - The string expression to generate the comparison for.
* @param {string} valueName - The name of the value to compare against. * @param {string} valueName - The name of the value to compare against.
* @param {Object} [options] - The optional parameters. * @param {Object} [options] - The optional parameters.
...@@ -13,33 +46,29 @@ export {generateRangeComparisonExpression} ...@@ -13,33 +46,29 @@ export {generateRangeComparisonExpression}
* @param {string} [options.leOp='<='] - The comparison operator for less than or equal to to use. * @param {string} [options.leOp='<='] - The comparison operator for less than or equal to to use.
* @returns {string} The generated comparison expression. * @returns {string} The generated comparison expression.
* @throws {Error} If the input is invalid. * @throws {Error} If the input is invalid.
* @memberOf Monster.Text
* @summary Generates a comparison expression based on a range of values.
*/ */
function generateRangeComparisonExpression(expression, valueName, options = {}) { function generateRangeComparisonExpression(expression, valueName, options = {}) {
const { const { urlEncode = false, andOp = "&&", orOp = "||", eqOp = "==", geOp = ">=", leOp = "<=" } = options;
urlEncode = false, const ranges = expression.split(",");
andOp = '&&', let comparison = "";
orOp = '||',
eqOp = '==',
geOp = '>=',
leOp = '<=',
} = options;
const ranges = expression.split(',');
let comparison = '';
for (let i = 0; i < ranges.length; i++) { for (let i = 0; i < ranges.length; i++) {
const range = ranges[i].trim(); const range = ranges[i].trim();
if (range === '') { if (range === "") {
throw new Error(`Invalid range '${range}'`); throw new Error(`Invalid range '${range}'`);
} else if (range.includes('-')) { } else if (range.includes("-")) {
const [start, end] = range.split('-').map(s => (s === '' ? null : parseFloat(s))); const [start, end] = range.split("-").map((s) => (s === "" ? null : parseFloat(s)));
if ((start !== null && isNaN(start)) || (end !== null && isNaN(end))) { if ((start !== null && isNaN(start)) || (end !== null && isNaN(end))) {
throw new Error(`Invalid value in range '${range}'`); throw new Error(`Invalid value in range '${range}'`);
} }
if (start !== null && end !== null && start > end) { if (start !== null && end !== null && start > end) {
throw new Error(`Invalid range '${range}'`); throw new Error(`Invalid range '${range}'`);
} }
const compStart = start !== null ? `${valueName}${urlEncode ? encodeURIComponent(geOp) : geOp}${start}` : ''; const compStart =
const compEnd = end !== null ? `${valueName}${urlEncode ? encodeURIComponent(leOp) : leOp}${end}` : ''; start !== null ? `${valueName}${urlEncode ? encodeURIComponent(geOp) : geOp}${start}` : "";
const compRange = `${compStart}${compStart && compEnd ? ` ${andOp} ` : ''}${compEnd}`; const compEnd = end !== null ? `${valueName}${urlEncode ? encodeURIComponent(leOp) : leOp}${end}` : "";
const compRange = `${compStart}${compStart && compEnd ? ` ${andOp} ` : ""}${compEnd}`;
comparison += ranges.length > 1 ? `(${compRange})` : compRange; comparison += ranges.length > 1 ? `(${compRange})` : compRange;
} else { } else {
const value = parseFloat(range); const value = parseFloat(range);
......