Compare commits

...

63 Commits

Author SHA1 Message Date
chris c0171aa8d8 IMPRO,FEAT: added modifyChildren 1 month ago
chris 6933a89111 IMPRO,REFA,FEAT: extended distributeSpacingEvengly 1 month ago
chris 7a40c27712 REFA,IMPRO: select elements are InputComponents as well 1 month ago
chris 6de0aca195 REFA,FIX,IMPRO: changed default behaviour of text() 1 month ago
chris 02203a5dd0 CHORE: updated package version corresponding with git 2 months ago
chris a36190bde9 CHORE: updated package-lock.json 2 months ago
chris 41d71f1523 CHORE: fix dupplication of devdependencies introduced by git 2 months ago
chris 1a51451e82 DOC,REFA,LINT: implemented first couple of lint issues 2 months ago
chris 9fb347421d CHORE,REFA: introduced linter 2 months ago
chris 362d9f870c CHORE,REFA: introduced linter 2 months ago
chris cf6438d623 CHORE: updated version reference in package.json 2 months ago
chris c0b43e38d1 CHORE: adjusted licence to include exclusion of waranty 2 months ago
chris d361a1bbee FEAT,REFA: externalized extension base class 2 months ago
chris c25f9bb93e FEAT: added noselect modifier 2 months ago
chris aa65dc1e54 FIX,IMPRO,REFA: overriding all function for border 2 months ago
chris 5dab23dc14 FEAT,FIX,IMPRO,REFA: reworked overflow behaviour 2 months ago
chris 46f12f517d FIX,REFA: handling parameter given as string or function 2 months ago
chris ab4d39d55d IMPRO,MINOR,FIX: changed replacement order of empty string characters 2 months ago
chris 0496bb0295 FIX,IMPRO,REFA: removed shape invokation on border constructor 2 months ago
chris d578a56269 MINOR,FIX: lookup for existing key in object 2 months ago
chris 61a32a7bfe MINOR,IMPRO,FIX,REFA: changed to map approach 2 months ago
chris 27cc2d930d FIX: entries is a function of a map 2 months ago
chris 73c85f4d2e FIX: wrongfully created a dependend call loop 2 months ago
chris 025573a16c FIX: default values for parameters were wrongfully provided 2 months ago
chris 467fca6adf CHORE: extend npm module with exports attemt to include module variant 2 months ago
chris 819ad6bee0 CHORE: update npm run generate call 2 months ago
chris e65c2f96cd REFA,IMPRO: local custom bundler generates vainlla and module 2 months ago
chris 3608ae5cf0 FIX,FEAT-BUNDLING: ChainableModifier was missing 2 months ago
chris 2b50ed88d1 FIX: generator used this (legacy from component) 2 months ago
chris 60776d6fc3 DOC,REFA: unified used "imports", updated usage of deprecated methods 2 months ago
chris b9a92a4df2 MAJOR,REFA,IMPL: updated files for current bundling process 2 months ago
chris 74974f6c80 REFA: preparations for jpclw-bundler 2 months ago
chris 92a86aa880 CHORE: Removing name form disclaimer 2 months ago
chris fc1dfd7e21 REFA: renamed files to represent classes directly 2 months ago
chris 9f374eeaa4 IMPRO: default generator 2 months ago
chris 20710fc461 MAJOR,IMPL,FEAT,REFA: generator 2 months ago
chris db5750ca16 REFA: changed extStore setup 2 months ago
chris 0110253876 REFA: moved executeStoreTypeCollectedTriple function 2 months ago
chris e495aa72ad FIX: setFunctionsExtStorage setting property 2 months ago
chris 439a98eb33 REFA,DOC: Added Doc removed empty lines 2 months ago
chris 70e5d0d66f REFA: renamed properties of WebTrinity 2 months ago
chris 60faa1a062 MAJOR,REFA: extracted TwoDimPoint class in own file 2 months ago
chris e539ace5a0 DRAFT,IMPL,DOC: changed loop approaches 2 months ago
chris 23e30b8ffb MINOR,FEAT,REFA,DOC: first implementation of generator class 2 months ago
chris 8d6eb00ae4 MAJOR,REFA: moved context.js into corresponding module 2 months ago
chris c2a34dd540 MAJOR,REFA: moved base types into sepperate module 2 months ago
chris 12f52feca8 MAJOR,REFA: moved event/behaviour modifiers to handlers module 2 months ago
chris 89bc8106c9 MAJOR,REFA: seperated and moved baseCompontent 2 months ago
chris c34114c176 MAJOR,REFA: Moved style-modifiers into decorators dir 2 months ago
chris 6ff45892cb REFA: removing empty lines at begin of files (and doc if redundant) 2 months ago
chris 6f186b64d8 MAJOR,REFA: moved component and ancestry into module 2 months ago
chris dd3d986485 MAJOR,REFA: moved modifiers to decorators 2 months ago
chris d9cef5210d MAJOR,REFA: moved helpers into module out of context 2 months ago
chris 26becc9431 MAJOR,REFA: moved twoDimPoint to helpers instead 2 months ago
chris 3afeb8a5e6 MAJOR,REFA: Moved/Renamed modifier extensions into "module" dir 2 months ago
chris 0209c1012f MAJOR,REFA: externalized modifier extension classes 2 months ago
chris 1b81c4df0e REFA,CHORE: add module type generated bundle to gitignore 2 months ago
chris e4e4c60f27 REFA,CHORE: introducing module bundling 2 months ago
chris b53ffc3571 REFA, IMPRO: removing the property "_wenity" 2 months ago
chris eca487c2fe CHORE,REFA: removed copyright disclaimer from 'every' file 2 months ago
chris e0fbe8bd96 CHORE,DOC: some doc added, removed unused dependencies 2 months ago
chris c228b251b2 MINOR,FEAT: return parent if child is undefined to allow empty method stubs 2 months ago
chris 208481a867 FIX,DOC: adjusted return types and fixed integer identification 2 months ago
  1. 1
      .gitignore
  2. 26
      LICENCE.md
  3. 2
      README.md
  4. 15
      eslint.config.mjs
  5. 194
      fileOrder.json
  6. 183
      generate_single_file.js
  7. 695
      jpclw-bundle.json
  8. 2156
      package-lock.json
  9. 22
      package.json
  10. 79
      src/base/extStore.js
  11. 49
      src/base/webTrinity.js
  12. 236
      src/baseComponents.js
  13. 47
      src/builder.js
  14. 14
      src/component/ChildbearerComponent.js
  15. 19
      src/component/Column.js
  16. 292
      src/component/Component.js
  17. 173
      src/component/FlexContainerComponent.js
  18. 69
      src/component/InputComponent.js
  19. 46
      src/component/Row.js
  20. 30
      src/component/StyleAndScriptStoringComponent.js
  21. 7
      src/component/modifiableComponent.js
  22. 8
      src/context/context.js
  23. 19
      src/context/framework-controls.js
  24. 11
      src/context/scriptAndStyleContext.js
  25. 31
      src/context/webTrinity.js
  26. 6
      src/decorators/alignment.js
  27. 6
      src/decorators/arrangement.js
  28. 83
      src/decorators/border.js
  29. 8
      src/decorators/color.js
  30. 19
      src/decorators/dimensions.js
  31. 2
      src/decorators/margin.js
  32. 0
      src/decorators/padding.js
  33. 30
      src/decorators/shapes.js
  34. 24
      src/decorators/siding.js
  35. 84
      src/extensions/extension.js
  36. 1
      src/generators/defaultGenerators.js
  37. 313
      src/generators/generator.js
  38. 6
      src/handlers/commonEvents.js
  39. 14
      src/handlers/contextMenu.js
  40. 6
      src/handlers/dragAndDrop.js
  41. 55
      src/helper/ObjectAccessObject.js
  42. 70
      src/helper/general.js
  43. 84
      src/helper/indices.js
  44. 86
      src/helper/twoDimPoint.js
  45. 187
      src/modifier/ChainableModifier.js
  46. 87
      src/modifier/ModificationSubChain.js
  47. 150
      src/modifier/Modifier.js
  48. 82
      src/modifier/mixinModSubChain.js

1
.gitignore

@ -1,4 +1,5 @@
node_modules/
samples/*/
jpc-like-websites.js
jpc-like-websites.mjs
extensions/

26
LICENCE.md

@ -1,5 +1,21 @@
Copyright (C) Christian Martin - All Rights Reserved
Unauthorized copying of this file,
via any medium is strictly prohibited
Proprietary and confidential
Written by Christian Martin, September 2024
Copyright (c) 2024-2025 Christian Martin
All rights reserved.
This software
and associated documentation files (the "Software")
are the exclusive property of Christian Martin.
You may not use, copy, modify, merge, publish,
distribute, sublicense, or sell copies of the Software,
in whole or in part,
without the express prior written permission of the copyright holder.
For inquiries regarding licensing, please contact:
christian.martin3(at)gmx.net.
THE SOFTWARE IS PROVIDED "AS IS",
WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

2
README.md

@ -45,3 +45,5 @@ you have been warned.
```sh
sh join_js_files.sh
```
https://eslint.org/docs/latest/use/getting-started

15
eslint.config.mjs

@ -0,0 +1,15 @@
import js from "@eslint/js";
import globals from "globals";
import json from "@eslint/json";
import css from "@eslint/css";
import { defineConfig } from "eslint/config";
export default defineConfig([
{ files: ["**/*.{js,mjs,cjs}"], plugins: { js }, extends: ["js/recommended"] },
{ files: ["**/*.js"], languageOptions: { sourceType: "script" } },
{ files: ["**/*.{js,mjs,cjs}"], languageOptions: { globals: globals.browser } },
{ files: ["**/*.json"], plugins: { json }, language: "json/json", extends: ["json/recommended"] },
{ files: ["**/*.jsonc"], plugins: { json }, language: "json/jsonc", extends: ["json/recommended"] },
{ files: ["**/*.css"], plugins: { css }, language: "css/css", extends: ["css/recommended"] },
]);

194
fileOrder.json

@ -1,194 +0,0 @@
{
"orderedGroups": {
"pure_stylings": [
"color.js",
"alignment.js",
"arrangement.js"
],
"size_sidings": [
"modificationSubChainMixins.js",
"siding.js",
"padding.js",
"margin.js",
"shapes.js",
"border.js",
"twoDimPoint.js",
"dimensions.js"
],
"behaviour_modifications": [
"commonEvents.js",
"contextMenu.js",
"dragAndDrop.js"
],
"pre_context": [
"webTrinity.js",
"extStore.js",
"generalHelpers.js"
],
"modifier": [
"modifier.js"
],
"component": [
"wrapperComponent.js",
"modifiableComponent.js",
"addStyleAndFunctions.js",
"component.js"
],
"builder": [
"baseComponents.js",
"builder.js"
],
"extensions": [
"extension.js"
],
"app_context": [
"scriptAndStyleContext.js",
"framework-controls.js",
"context.js"
]
},
"keys": [
"color.js",
"alignment.js",
"arrangement.js",
"siding.js",
"shapes.js",
"border.js",
"dimensions.js",
"commonEvents.js",
"contextMenu.js",
"dragAndDrop.js",
"webTrinity.js",
"extStore.js",
"generalHelpers.js",
"modifier.js",
"wrapperComponent.js",
"modifiableComponent.js",
"addStyleAndFunctions.js",
"component.js",
"baseComponents.js",
"builder.js",
"extension.js",
"scriptAndStyleContext.js",
"framework-controls.js",
"context.js",
"modificationSubChainMixins.js",
"padding.js",
"margin.js",
"twoDimPoint.js"
],
"objects": {
"color.js": {
"name": "color.js",
"folder": "src"
},
"alignment.js": {
"name": "alignment.js",
"folder": "src"
},
"arrangement.js": {
"name": "arrangement.js",
"folder": "src"
},
"siding.js": {
"name": "siding.js",
"folder": "src/sizeSide"
},
"shapes.js": {
"name": "shapes.js",
"folder": "src/sizeSide"
},
"border.js": {
"name": "border.js",
"folder": "src/sizeSide"
},
"dimensions.js": {
"name": "dimensions.js",
"folder": "src/sizeSide"
},
"commonEvents.js": {
"name": "commonEvents.js",
"folder": "src"
},
"contextMenu.js": {
"name": "contextMenu.js",
"folder": "src/modifications"
},
"dragAndDrop.js": {
"name": "dragAndDrop.js",
"folder": "src/modifications"
},
"webTrinity.js": {
"name": "webTrinity.js",
"folder": "src/context"
},
"extStore.js": {
"name": "extStore.js",
"folder": "src/context"
},
"generalHelpers.js": {
"name": "generalHelpers.js",
"folder": "src/context"
},
"modifier.js": {
"name": "modifier.js",
"folder": "src"
},
"wrapperComponent.js": {
"name": "wrapperComponent.js",
"folder": "src/componentAncestry"
},
"modifiableComponent.js": {
"name": "modifiableComponent.js",
"folder": "src/componentAncestry"
},
"addStyleAndFunctions.js": {
"name": "addStyleAndFunctions.js",
"folder": "src/componentAncestry"
},
"component.js": {
"name": "component.js",
"folder": "src"
},
"baseComponents.js": {
"name": "baseComponents.js",
"folder": "src"
},
"builder.js": {
"name": "builder.js",
"folder": "src"
},
"extension.js": {
"name": "extension.js",
"folder": "src/extensions"
},
"scriptAndStyleContext.js": {
"name": "scriptAndStyleContext.js",
"folder": "src/context"
},
"framework-controls.js": {
"name": "framework-controls.js",
"folder": "src/context"
},
"context.js": {
"name": "context.js",
"folder": "src"
},
"modificationSubChainMixins.js":{
"name": "modificationSubChainMixins.js",
"folder": "src/modifiers"
},
"padding.js":{
"name": "padding.js",
"folder": "src/modifiers"
},
"margin.js":{
"name": "margin.js",
"folder": "src/modifiers"
},
"twoDimPoint.js":{
"name": "twoDimPoint.js",
"folder": "src/modifiers"
}
}
}

183
generate_single_file.js

@ -1,49 +1,14 @@
const fs = require('fs/promises');
const path = require('path');
const copyright_disclaimer = `
/**
* purely convienience
*/
class FileDependecy {
name;
folder;
path() {
return this.folder + '/' + this.name;
}
}
/**
* Object Access Object
* purely convienience
*/
class OAO {
constructor() {
/**
* @type {boolean|Map<string,FileDependecy>}
*/
this.orderedGroups
/**
* @type {Array<string>}
*/
this.keys = [];
/**
* @type {map<string, FileDependecy>}
*/
this.objects = {};
/**
* @type {boolean}
*/
this.isOrdered = false;
}
}
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator
*/
let fileOrder = Object.assign(new OAO(), require('./fileOrder.json'));
fileOrder.objects = fileOrder.keys
.reduce((a, fileName) => Object.assign(
a,
{ [fileName]: Object.assign(new FileDependecy(), fileOrder.objects[fileName]) }
), {});
`;
/**
* Kept for future reference, might be that we will return to the dependency resolvement approach.
@ -111,46 +76,118 @@ function resolveDependencyOrder(oao) {
}
function appendContent(srcFile, targetFile) {
return fs.readFile(srcFile, 'utf8')
.then(content => {
console.log(`Processing '${srcFile}'`);
console.log(` READ: successfully!`)
console.log(` Attepting to append`);
return fs.appendFile(targetFile, content);
})
.then(() => {
console.log(` Append/Write: successfully!`);
})
.catch(error => {
console.error(`Error reading/writing files: ${error.message}`);
})
/**
*
* @param {string} srcFile path to src file
* @param {string} targetFile path of target file that will contain all scripts
*/
async function appendContent(srcFile, targetFile, contentModifications = [], lineModifications = []) {
try {
let content = await fs.readFile(srcFile, 'utf8');
console.log(`Processing '${srcFile}'`);
console.log(` READ: successfully!`, `Attepting to append file`);
/* Apply modifications */
content = contentModifications
.reduce((a, c) => c(a), content.split('\r\n'))
.map(line => lineModifications.reduce((a, c) => c(a), line))
.join('\r\n');
await fs.appendFile(targetFile, content);
console.log(` Append/Write: successfully!`);
} catch (error) {
console.error(`Error reading/writing files: ${error.message}`);
}
}
/**
*
* @param {string} srcFile path to src file
* @param {string} targetFile path of target file that will contain all scripts
*/
async function bundleWithSpecifiedMode(targetFile, fileList, modulize = true) {
let contentModifications = [
function (content) {
return [
...copyright_disclaimer.split('\r\n'),
...content
];
}
];
let lineModifications = [
function (line) {
let starters = ["function", "const", "let", "class"];
if (starters.some(s => line.startsWith(s))) {
return "export " + line;
}
return line;
}
];
fileList
.reduce((prevPromise, filePath) => prevPromise
.then(
() => appendContent(filePath, targetFile, contentModifications)
), Promise.resolve()
)
if (modulize) {
let targetModule = path.basename(targetFile).split('.', 1)[0] + '.mjs';
fileList
.reduce((prevPromise, filePath) => prevPromise
.then(
() => appendContent(filePath, targetModule, contentModifications, lineModifications)
), Promise.resolve()
)
}
}
let orderedJoinList = Object.keys(fileOrder.orderedGroups)
.flatMap(groupName => fileOrder.orderedGroups[groupName])
.map(fileName => fileOrder.objects[fileName].path());
/*
// Kept for future reference, might be that we will return to the dependency resolvement approach.
fileOrder = resolveDependencyOrder(fileOrder);
/**
* @deprecated Currently this function takles the task of successfully bundling the jpc-framework.
* A custom bundler will replace this function/file.
* Some logic might be copied/used from here.
*
* Takes the given order from the jpclw-bundle.json and bundles the scripts accordingly.
*
* @param {string|path} targetFile path to the targetfile (without file extension)
* @param {boolean} modulize flag to decide to generate a mjs module as well
* @param {string|path} bundleFile path to the bundleFile if there is some
* - preparation for jpclw-bundler
*/
function bundle(modulize = false, targetFile = "./jpc-like-websites.js", bundleFile = './jpclw-bundle.json') {
let fileOrder = require(bundleFile);
let orderedJoinList = fileOrder.keys
.map(fileName => fileOrder.objects[k].path());
*/
console.log("(Re-) Creating target file: '" + targetFile + "'");
/* EMPTY (create?) TARGET FILE */
fs.writeFile(targetFile, "", err => { });
if (modulize) {
let targetModule = path.basename(targetFile).split('.', 1)[0] + '.mjs';
fs.writeFile(targetModule, "", err => { });
}
let fileList = Object.keys(fileOrder.orderedGroups)
.flatMap(groupName => fileOrder.orderedGroups[groupName])
.map(fileName => {
let f = fileOrder.objects[fileName];
/* The Path build by name and folder */
return `${f.folder}/${f.name}`;
});
const targetFile = "./jpc-like-websites.js";
console.log("(Re-) Creating target file: '" + targetFile + "'");
bundleWithSpecifiedMode(targetFile, fileList, modulize);
}
/* EMPTY (create?) TARGET FILE */
fs.writeFile(targetFile, "", err => { })
let args = process.argv.slice(2);
bundle(Boolean(args[0]), args[1], args[2]);
orderedJoinList
.reduce((prevPromise, filePath) => prevPromise
.then(
()=>appendContent(filePath, targetFile)
), Promise.resolve())

695
jpclw-bundle.json

@ -0,0 +1,695 @@
{
"orderedGroups": {
"base": [
"webTrinity.js",
"extStore.js"
],
"helper": [
"ObjectAccessObject.js",
"TwoDimPoint.js",
"general.js",
"indices.js"
],
"chain_mixins": [
"mixinModSubChain.js",
"ModificationSubChain.js"
],
"decorators": [
"color.js",
"alignment.js",
"arrangement.js",
"siding.js",
"padding.js",
"margin.js",
"shapes.js",
"border.js",
"dimensions.js"
],
"handlers": [
"commonEvents.js",
"contextMenu.js",
"dragAndDrop.js"
],
"modifier": [
"Modifier.js",
"ChainableModifier.js"
],
"generators":[
"generator.js",
"defaultGenerators.js"
],
"component": [
"ChildbearerComponent.js",
"ModifiableComponent.js",
"StyleAndScriptStoringComponent.js",
"Component.js",
"FlexContainerComponent.js",
"Column.js",
"Row.js",
"InputComponent.js"
],
"extensions": [
"extension.js"
],
"context": [
"scriptAndStyleContext.js",
"framework-controls.js",
"context.js"
],
"builder": [
"builder.js"
]
},
"keys": [
"extStore.js",
"webTrinity.js",
"builder.js",
"ChildbearerComponent.js",
"Column.js",
"Component.js",
"FlexContainerComponent.js",
"InputComponent.js",
"ModifiableComponent.js",
"Row.js",
"StyleAndScriptStoringComponent.js",
"context.js",
"framework-controls.js",
"scriptAndStyleContext.js",
"alignment.js",
"arrangement.js",
"border.js",
"color.js",
"dimensions.js",
"margin.js",
"padding.js",
"shapes.js",
"siding.js",
"extension.js",
"simplePagingAndNavigation.js",
"defaultGenerators.js",
"generator.js",
"commonEvents.js",
"contextMenu.js",
"dragAndDrop.js",
"general.js",
"indices.js",
"ObjectAccessObject.js",
"TwoDimPoint.js",
"ChainableModifier.js",
"mixinModSubChain.js",
"ModificationSubChain.js",
"Modifier.js"
],
"objects": {
"extStore.js": {
"folder": "src/base",
"name": "extStore.js",
"exports": [
"ESAggregation",
"ExtStorePosition",
"OverwriteBehaviour",
"clearFunctionDeclarationText",
"getScriptTagInjectionText",
"FunctionStoreBuffer",
"ExtStorage",
"ExtStoreType",
"SStoreDefinition",
"resolveOverwrite",
"identifyAndResolveOverwrite",
"generateAndFillScriptTag",
"getStylingInjectionText",
"generateAndFillStyleTag",
"executeOnExtStoreTypeCollectedTriple"
],
"imports": {
"../Component": [
"Component"
],
"../context": [
"Page"
]
}
},
"webTrinity.js": {
"folder": "src/base",
"name": "webTrinity.js",
"exports": [
"WebTrinity"
]
},
"builder.js": {
"folder": "src",
"name": "builder.js",
"exports": [
"builder"
],
"imports": {
"./Component": [
"Component",
"FlexContainerComponent",
"Row",
"Column",
"InputComponent"
],
"./modifier": [
"Modifier"
],
"./context": [
"Page"
]
}
},
"ChildbearerComponent.js": {
"folder": "src/component",
"name": "ChildbearerComponent.js",
"exports": [
"ChildbearerComponent"
],
"imports": {
"../decorators": [
"Alignment",
"Arrangement"
],
"../helper": [
"helperFun"
],
"./Component": [
"Component"
],
"../builder": [
"builder"
]
}
},
"Column.js": {
"folder": "src/component",
"name": "Column.js",
"exports": [
"Column"
],
"imports": {
"./FlexContainerComponent": [
"FlexContainerComponent"
]
}
},
"Component.js": {
"folder": "src/component",
"name": "Component.js",
"exports": [
"Component"
],
"imports": {
"../base": [
"ExtStorage"
],
"../modifier": [
"Modifier"
],
"../context": [
"Page",
"CommonCompelGroups"
],
"../handlers": [
"DefaultContextMenu",
"DragAndDropImplementation"
],
"../generators": [
"CompelGenerator"
]
}
},
"FlexContainerComponent.js": {
"folder": "src/component",
"name": "FlexContainerComponent.js",
"exports": [
"FlexContainerComponent"
],
"imports": {
"./Component": [
"Component"
],
"../modifier": [
"Modifier"
]
}
},
"InputComponent.js": {
"folder": "src/component",
"name": "InputComponent.js",
"exports": [
"InputComponent"
],
"imports": {
"./Component": [
"Component"
]
}
},
"ModifiableComponent.js": {
"folder": "src/component",
"name": "ModifiableComponent.js",
"exports": [
"ModifiableComponent"
],
"imports": {
"./ChildbearerComponent": [
"ChildbearerComponent"
],
"../base": [
"SStoreDefinition"
],
"../modifier": [
"ChainableModifier"
]
}
},
"Row.js": {
"folder": "src/component",
"name": "Row.js",
"exports": [
"Row"
],
"imports": {
"./FlexContainerComponent": [
"FlexContainerComponent"
],
"../helper": [
"onSingleOrArray"
]
}
},
"StyleAndScriptStoringComponent.js": {
"folder": "src/component",
"name": "StyleAndScriptStoringComponent.js",
"exports": [
"StyleAndScriptStoringComponent"
],
"imports": {
"./ModifiableComponent": [
"ModifiableComponent"
],
"../decorators": [
"Alignment",
"Arrangement"
],
"../base": [
"ExtStorage",
"ExtStoreType",
"SStoreDefinition"
]
}
},
"context.js": {
"folder": "src/context",
"name": "context.js",
"exports": [
"PageBuilder",
"CommonCompelGroups",
"Page"
],
"imports": {
"./scriptAndStyleContext": [
"ScriptAndStyleContext"
],
"../extensions": [
"CompelExtension"
]
}
},
"framework-controls.js": {
"folder": "src/context",
"name": "framework-controls.js",
"exports": [
"frameworkControlPanel"
],
"imports": {
"../builder": [
"builder"
],
"../modifier": [
"Modifier"
],
"../decorators": [
"Alignment",
"Arrangement",
"Colors",
"Border",
"MaterialFiveHundredlColors"
],
"../base": [
"ExtStoreType"
],
"../Component": [
"Component"
]
}
},
"scriptAndStyleContext.js": {
"folder": "src/context",
"name": "scriptAndStyleContext.js",
"exports": [
"ScriptAndStyleContext"
],
"imports": {
"../base": [
"OverwriteBehaviour",
"FunctionStoreBuffer"
]
}
},
"alignment.js": {
"folder": "src/decorators",
"name": "alignment.js",
"exports": [
"Alignment"
]
},
"arrangement.js": {
"folder": "src/decorators",
"name": "arrangement.js",
"exports": [
"Arrangement"
]
},
"border.js": {
"folder": "src/decorators",
"name": "border.js",
"exports": [
"LineStyles",
"BorderDefinition",
"Define",
"Border",
"BorderChain",
"BorderChainedModifier"
],
"imports": {
"./siding": [
"SizeUnits",
"Sides"
],
"./color": [
"Color",
"Colors"
],
"./shapes": [
"Shapes"
],
"../modifier": [
"mixinModSubChainEndings",
"mixinModSubChainComponentMethods"
]
}
},
"color.js": {
"folder": "src/decorators",
"name": "color.js",
"exports": [
"Color",
"Colors",
"MaterialFiveHundredlColors"
]
},
"dimensions.js": {
"folder": "src/decorators",
"name": "dimensions.js",
"exports": [
"Dimensions",
"DimensionsChain",
"DimensionsChainedModifier"
],
"imports": {
"./siding": [
"DirectionUnitDependentAttribute",
"SizeUnits"
],
"../helper": [
"TwoDimPoint"
],
"../modifier": [
"mixinModSubChainEndings",
"mixinModSubChainComponentMethods"
]
}
},
"margin.js": {
"folder": "src/decorators",
"name": "margin.js",
"exports": [
"Margin",
"MarginChain",
"MarginChainedModifier"
],
"imports": {
"./siding": [
"Sides",
"SizeUnits"
],
"../modifier": [
"mixinModSubChainEndings",
"mixinModSubChainComponentMethods"
]
}
},
"padding.js": {
"folder": "src/decorators",
"name": "padding.js",
"exports": [
"Padding",
"PaddingChain",
"PaddingChainedModifier"
],
"imports": {
"./siding": [
"Sides",
"SizeUnits"
],
"../modifier": [
"mixinModSubChainEndings",
"mixinModSubChainComponentMethods"
]
}
},
"shapes.js": {
"folder": "src/decorators",
"name": "shapes.js",
"exports": [
"Shape",
"ShapeChain",
"ShapeChainedModifier",
"Shapes"
],
"imports": {
"./siding": [
"DirectionUnitDependentAttribute",
"SizeUnits",
"SidingRefCorners"
],
"../modifier": [
"mixinModSubChainEndings",
"mixinModSubChainComponentMethods"
]
}
},
"siding.js": {
"folder": "src/decorators",
"name": "siding.js",
"exports": [
"SizeUnits",
"DirectionUnitDependentAttribute",
"SideDirections",
"SideTransitionDirection",
"Corners",
"CornerTransitionDirection",
"Sides"
]
},
"extension.js": {
"folder": "src/extensions",
"name": "extension.js"
},
"simplePagingAndNavigation.js": {
"folder": "src/extensions",
"name": "simplePagingAndNavigation.js"
},
"defaultGenerators.js": {
"folder": "src/generators",
"name": "defaultGenerators.js",
"exports": [
"singlepage"
],
"imports": {
"./generator": [
"CompelGenerator"
]
}
},
"generator.js": {
"folder": "src/generators",
"name": "generator.js",
"exports": [
"CompelGenerator"
],
"imports": {
"../base": [
"WebTrinity",
"ExtStoreType"
],
"../Component": [
"Component"
],
"../modifier": [
"Modifier"
]
}
},
"commonEvents.js": {
"folder": "src/handlers",
"name": "commonEvents.js",
"exports": [
"CommonEvents"
]
},
"contextMenu.js": {
"folder": "src/handlers",
"name": "contextMenu.js",
"exports": [
"DefaultContextMenu"
],
"imports": {
"../decorators": [
"Sides"
],
"../helper": [
"helperFun",
"getEnclosingBounds"
]
}
},
"dragAndDrop.js": {
"folder": "src/handlers",
"name": "dragAndDrop.js",
"exports": [
"EventDrag",
"DragAndDropImplementation",
"DADInPlace"
],
"imports": {
"../helper": [
"TwoDimPoint"
],
"../decorators": [
"Dimensions"
]
}
},
"general.js": {
"folder": "src/helper",
"name": "general.js",
"exports": [
"onSingleOrArray",
"helperFun"
]
},
"indices.js": {
"folder": "src/helper",
"name": "indices.js",
"exports": [
"isValueInBounds",
"areXYInArea",
"isPointInArea",
"getEnclosingBounds"
],
"imports": {
"../decorators": [
"SideDirections"
],
"./TwoDimPoint": [
"TwoDimPoint"
]
}
},
"ObjectAccessObject.js": {
"folder": "src/helper",
"name": "ObjectAccessObject.js",
"exports": [
"ObjectAccessObject"
]
},
"TwoDimPoint.js": {
"folder": "src/helper",
"name": "TwoDimPoint.js",
"exports": [
"TwoDimPoint"
]
},
"ChainableModifier.js": {
"folder": "src/modifier",
"name": "ChainableModifier.js",
"exports": [
"ChainableModifier"
],
"imports": {
"./modifier": [
"Modifier"
],
"../Component": [
"Component"
],
"../decorators": [
"PaddingChainedModifier",
"MarginChainedModifier",
"ShapeChainedModifier",
"BorderChainedModifier"
]
}
},
"mixinModSubChain.js": {
"folder": "src/modifier",
"name": "mixinModSubChain.js",
"exports": [
"mixinModSubChainEndings",
"mixinModSubChainComponentMethods"
],
"imports": {
"./modifier": [
"Modifier"
],
"./ChainableModifier": [
"ChainableModifier"
]
}
},
"ModificationSubChain.js": {
"folder": "src/modifier",
"name": "ModificationSubChain.js",
"exports": [
"ModificationSubChain",
"ModificationSubChainReComp"
]
},
"Modifier.js": {
"folder": "src/modifier",
"name": "Modifier.js",
"exports": [
"Modifier"
],
"imports": {
"../decorators": [
"Sides",
"Border",
"BorderChain",
"Color",
"Dimensions",
"DimensionsChain",
"Margin",
"MarginChain",
"Padding",
"PaddingChain",
"Shape",
"ShapeChain"
]
}
}
}
}

2156
package-lock.json

File diff suppressed because it is too large

22
package.json

@ -1,17 +1,31 @@
{
"name": "jpc-like-websites",
"version": "1.0.0",
"version": "1.9.13.34",
"description": "Framework to build websites in a Jetpack Compose like manner, as well as an extensive use of method-chaingin.",
"main": "jpc-like-websites.js",
"exports": {
"vanilla": "./jpc-like-websites.js",
"module": "./jpc-like-websites.mjs"
},
"files": [
"/src"
],
"scripts": {
"prepare": "npm run build",
"generate": "node generate_single_file.js",
"generate": "node generate_single_file.js true",
"build": "npm run generate",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "cm",
"license": "ISC"
}
"license": "SEE LICENCE.md",
"dependencies": {
"jpclw-extension": "git+https://git.labos.goip.de/chris/jpclw-extension.git"
},
"devDependencies": {
"@eslint/css": "^0.7.0",
"@eslint/js": "^9.26.0",
"@eslint/json": "^0.12.0",
"eslint": "^9.26.0",
"globals": "^16.1.0"
}
}

79
src/context/extStore.js → src/base/extStore.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* ESAggregation := Extensions Storage Aggregation (method)
*/
@ -60,30 +54,38 @@ function clearFunctionDeclarationText(func) {
}
return shrinkEmptyStrings(
func.toString()
.replaceAll('\n', ' ')
.replaceAll('\r\n', ' ')
.replaceAll('\n\r', ' ')
.replaceAll('\n', ' ')
.replaceAll('\r', ' ')
);
}
/**
* @todo when ExtStorage-feature/logic is reevaluated
* the resolvement of functions (as basically major or main target)
* needs to be overlooked improved and simplified.
*
* @param {Function} func
* @param {string} registrationName
* @returns {string}
*/
function getScriptTagInjectionText(func, registrationName) {
let funcHasName = func.name && func.name.trim() !== '';
if (func.startWith('function')) {
let label = `function ${registrationName}`;
let isNameInFuncText = func.startWith(label);
if (funcHasName && isNameInFuncText) {
let funcHasName;
if (typeof func === 'function') {
funcHasName = ((func.name) && func.name.trim() !== '');
}
if (func.startsWith('function')) {
let label = ` function ${registrationName}`;
let isNameInFuncText = func.startsWith(label);
if (isNameInFuncText) {
return func;
} else {
return [label, '(', func.split('(', 1)[1]].join('')
return [label, '(', func.split('(').slice(1).join('(')].join('')
}
} else {
return `const ${registrationName} = ${func}; `;
return ` const ${registrationName} = ${func}; `;
}
}
@ -164,7 +166,7 @@ class ExtStorage {
/**
*
* @param {OverwriteBehaviour} behave
* @returns {EXPosConfer}
* @returns {ExtStorage}
*/
setOverwriteBehaviour(behave) {
this._overwriteBehaviour = behave;
@ -365,7 +367,7 @@ class ExtStorage {
}
if (element instanceof Component) {
ensuredElement = element.generate().html;
ensuredElement = element.generate().compext;
}
switch (this._position) {
@ -391,7 +393,7 @@ class ExtStorage {
}
/**
*
* Returns a function that will setup the distribution of a given styling.
* @returns {function(SStoreDefinition,HTMLElement,number): boolean}
*/
getStylingDistribution() {
@ -528,18 +530,21 @@ class SStoreDefinition {
*/
function resolveOverwrite(key, container, overwriteBehaviour) {
let dealAsMap = container instanceof Map;
let occurances = (dealAsMap
? container.keys
: Object.keys(container)
let occurances = [...(
dealAsMap
? container.keys()
: Object.keys(container)
)
.filter(e => e.includes(key))
.length;
.filter(e => e.includes(key)
)].length;
switch (overwriteBehaviour) {
case OverwriteBehaviour.REPLACE:
case OverwriteBehaviour.REPLACE: {
break;
case OverwriteBehaviour.RENAME_OLD:
nameForOld = `${key}${occurances}`;
}
case OverwriteBehaviour.RENAME_OLD: {
let nameForOld = `${key}${occurances}`;
if (dealAsMap) {
container.set(nameForOld, container.get(key));
container.delete(key);
@ -548,8 +553,10 @@ function resolveOverwrite(key, container, overwriteBehaviour) {
delete container[key];
}
break;
case OverwriteBehaviour.RENAME:
default:
}
case OverwriteBehaviour.RENAME:
default:
key = `${key}${occurances}`;
break;
}
@ -582,7 +589,8 @@ function identifyAndResolveOverwrite(targetContainer, compareKey, newValue, over
}
/**
*
* Creates a new Script Tag
* and then fills the given css rules into it.
* @param {Array<SStoreDefinition>} ssdArray
* @returns {HTMLScriptElement}
*/
@ -601,6 +609,7 @@ function generateAndFillScriptTag(ssdArray) {
return tag;
}
/**
*
* @param {string} selector
@ -635,3 +644,17 @@ function generateAndFillStyleTag(ssdArray) {
return tag;
}
/**
* Executes the given function upon the delegating ExtStoreTypes
* @param {Function} func
* @returns {Map<ExtStoreType, *}
*/
function executeOnExtStoreTypeCollectedTriple(func) {
return new Map([
{ [ExtStoreType.COLLECTED_SEGMENT_BEGIN]: func(ExtStoreType.COLLECTED_SEGMENT_BEGIN) },
{ [ExtStoreType.COLLECTED_DOC_HEAD]: func(ExtStoreType.COLLECTED_DOC_HEAD) },
{ [ExtStoreType.COLLECTED_DOC_FOOTER]: func(ExtStoreType.COLLECTED_DOC_FOOTER) }
]);
}

49
src/base/webTrinity.js

@ -0,0 +1,49 @@
/**
* Wenity := Web Trinity
*/
class WebTrinity {
/**
* @deprecated renamed - use copext instead
* @type {HTMLElement|Component|string} = compext, for a migration period
*/
html;
/**
* @deprecated renamed - use scripts instead
* @type {HTMLStyleElement|Map<ExtStorageType, Array<SStoreDefinition>} = scripts, for a migration period
*/
js;
/**
* @deprecated renamed - use stylings instead
* @type {HTMLScriptElement|Array<SStoreDefinition>} = stylings, for a migration period
*/
css;
/**
*
* @param {HTMLElement|Component|string} compext := Component Text
* @param {HTMLStyleElement|Map<ExtStorageType, Array<SStoreDefinition>} scripts
* @param {HTMLScriptElement|Array<SStoreDefinition>} stylings
*/
constructor(compext = null, scripts = null, stylings = null) {
this.compext = compext;
this.html = compext;
this.scripts = scripts;
this.js = scripts;
this.stylings = stylings;
this.css = stylings;
}
/**
*
* @returns {boolean}
*/
isSSEmpty() {
return (this.scripts === null || this.scripts.length === 0)
&& (this.stylings === null || this.stylings.size === 0)
/* LEGACY CHECK */
&& (this.js === null || this.js.length === 0)
&& (this.css === null || this.css.size === 0);
}
}

236
src/baseComponents.js

@ -1,236 +0,0 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Represents a Component (of an HTMLElement) that is capable of receiving input.
* @extends Component
* @inheritdoc
*/
class InputComponent extends Component {
/**
*
* @param {string} element
* @param {Attr} attr
* @param {Modifier} modifier
*/
constructor(element, attr = {}, modifier = null) {
super(element, attr);
this.addStyleClass("el-input-comp");
if (modifier) {
this.modifier(modifier);
}
}
/**
* The parameter makes it optional to trigger the state by a variable
* @param {boolean} readonly
* @returns {Component}
*/
readonly(readonly = true) {
if (readonly) {
this._element.setAttribute("readonly", readonly);
}
return this;
}
/**
* Sets the value of the InputComponent
* @param {string} Value
* @returns {InputComponent|Component}
*/
value(value) {
this._element.value = value;
return this;
}
/**
*
* @param {string} name
* @returns {InputComponent|Component}
*/
name(name) {
return this.setAttribute("name", name);
}
}
/**
* Represents container Components.
* Some predefined modifications are applied on the child components.
* @extends Component
* @inheritdoc
*/
class FlexContainerComponent extends Component {
/**
* @type {boolean}
*/
_distributeEvenglyAfterGenerate;
/**
* @type {string}
*/
_flexDirection;
/**
*
* @param {Attr} attr
* @param {Modifier} modifier
*/
constructor(attr = {}, modifier = null, baseElement = "div") {
super(document.createElement(baseElement), attr);
this._flexDirection = "";
this._distributeEvenglyAfterGenerate = false;
this.addStyleClass("flex-container-component");
if (modifier) {
this.modifier(modifier);
}
}
/**
*
* @param {boolean} [vertical=true]
* @returns {FlexContainerComponent}
*/
setFlexDirection(vertical = true) {
return this.modifier(
new Modifier()
.setStyleRule(
"flex-direction",
(vertical ? "column" : "row")
)
)
}
/**
*
* @param {Component|Array<Component>} innerComponent
* @returns {FlexContainerComponent} this component object
*/
childContext(innerComponent) {
if (innerComponent instanceof Array) {
innerComponent
.map(cl => {
if (cl instanceof Component) {
return cl
} else {
return cl.ensureModifier().toComponent()
}
})
.forEach(icomp => {
icomp._modifier = new Modifier()
.setStyleRule("flex", "none")
.join(icomp._modifier)
})
}
return super.childContext(innerComponent);
}
/**
*
* @returns {FlexContainerComponent}
*/
distibuteSpacingEvenly() {
this._distributeEvenglyAfterGenerate = true;
return this;
}
/**
* @override
* @inheritdoc
* @extends Component.generate()
*/
generate(modifier = null, styleStore = null, functionStore = null) {
if (this._children && this._children.length > 0) {
if (this._distributeEvenglyAfterGenerate) {
let childDistributionFraction = Math.floor(
((100 - this._children.length) / this._children.length) * 100
) / 100;
let direction = (this._flexDirection === 'column' ? 'height' : "width");
for (const icomp of this._children) {
/* sets the width for all elements,
to avoid overlapping or line break because of lacking width,
a percent is subtracted for every child element */
/* To enable "override" a new Modifier is generated and joined
with the modifier of the component */
icomp._modifier._modifications[direction] = childDistributionFraction + "%";
icomp._modifier._modifications["max-"+direction] = childDistributionFraction + "%";
}
}
}
return super.generate(modifier, styleStore, functionStore);
}
}
/**
* A FlexContainerComponent, which organizes the children in a column like manner.
* @extends FlexContainerComponent
* @inheritdoc
*/
class Column extends FlexContainerComponent {
/**
*
* @param {Attr} attr
* @param {Modifier} modifier
*/
constructor(attr = {}, modifier = null) {
super(attr, modifier);
this.addStyleClass("column-component");
this._flexDirection = "column";
this.setFlexDirection();
}
}
/**
* A FlexContainerComponent, which organizes the children in a row like manner.
*
* @extends FlexContainerComponent
* @inheritdoc
*/
class Row extends FlexContainerComponent {
/**
*
* @param {Attr} attr
* @param {Modifier} modifier
*/
constructor(attr = {}, modifier = null) {
super(attr, modifier);
this.addStyleClass("row-component")
this._flexDirection = "row";
//this.modifier(new Modifier().fillMaxWidth());
this.setFlexDirection(false);
}
/**
*
* @param {Component|Array<Component>} innerComponent
* @returns {Row}
*/
childContext(innerComponent) {
function setFloat(comp, side = "right") {
comp._modifier = new Modifier()
.setStyleRule("float", side)
.join(comp._modifier);
}
super.childContext(innerComponent);
for (const child of this._children) {
onSingleOrArray(
child,
(e, i) => setFloat(e, (i === 0 ? "left" : "right"))
);
}
return this;
}
}

47
src/builder.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Method Collection with predefined HTMLElements
*/
@ -187,7 +181,7 @@ const builder = {
input: function (type, attr = {}, modifier = null) {
let comp = new InputComponent(
document.createElement("input"),
Object.assign({ "type": type }, attr),
Object.assign({ "type": (type || "text") }, attr),
modifier
)
.addStyleClass(`el-input`);
@ -278,7 +272,21 @@ const builder = {
* @param {Modifier} modifier
* @returns {Component}
*/
select: function (attr = {}, modifier = null) { return builder.genTag("select", attr, modifier); },
select: function (attr = {}, modifier = null) {
let comp = new InputComponent(
document.createElement("select"),
attr,
modifier
)
.addStyleClass(`el-input`);
if (this.components.previous) {
comp._parentComponent = this.components.previous;
this.components.previous = null;
}
return comp;
},
/**
*
@ -342,9 +350,7 @@ const builder = {
*/
table: function (attr = {}, modifier = null) {
return builder.genTag("table", attr, modifier)
.chainModifier()
.removeStyleRule("display")
.toComponent();
.modifier(new Modifier().removeStyleRule("display"))
},
/**
@ -387,9 +393,7 @@ const builder = {
*/
tableBody: function (attr = {}, modifier = null) {
return builder.genTag("tbody", attr, modifier)
.chainModifier()
.removeStyleRule("display")
.toComponent();
.modifier(new Modifier().removeStyleRule("display"))
},
/**
@ -400,9 +404,7 @@ const builder = {
*/
tableHead: function (attr = {}, modifier = null) {
return builder.genTag("thead", attr, modifier)
.chainModifier()
.removeStyleRule("display")
.toComponent();
.modifier(new Modifier().removeStyleRule("display"))
},
/**
@ -413,9 +415,7 @@ const builder = {
*/
tableFooter: function (attr = {}, modifier = null) {
return builder.genTag("tfoot", attr, modifier)
.chainModifier()
.removeStyleRule("display")
.toComponent();
.modifier(new Modifier().removeStyleRule("display"))
},
/**
@ -435,10 +435,7 @@ const builder = {
form: function (attr = {}, modifier = null) {
return builder.genTag("form", attr, modifier)
.addStyleClass("flex-container-component")
.chainModifier()
.setStyleRule("flex-direction", "column")
.ensureModifier()
.toComponent()
.modifier(new Modifier().setStyleRule("flex-direction", "column"))
},
/**
@ -506,7 +503,7 @@ const builder = {
.arrangement(Arrangement.CENTER)
.childContext(innerComponents)
.generate()
.html
.compext
);
Page.generate();
main.remove();

14
src/componentAncestry/wrapperComponent.js → src/component/ChildbearerComponent.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Represents the most basic and simple form of a Component.
* It is mainly a collection of wrapper methods
@ -67,11 +61,7 @@ class ElementWrapper {
* @returns {Component} this component object
*/
text(text) {
if (this._element instanceof HTMLInputElement && this._element.type === "text") {
this._element.value = text;
} else {
this._element.innerText = text;
}
this._element.innerText = text;
return this;
}
@ -189,6 +179,8 @@ class ChildbearerComponent extends ElementWrapper {
* @returns {Component} this component object
*/
childContext(component) {
if (!component) return this;
if (arguments.length > 1) {
for (let i = 0; i < arguments.length; i++) {
this.childContext(arguments[i]);

19
src/component/Column.js

@ -0,0 +1,19 @@
/**
* A FlexContainerComponent, which organizes the children in a column like manner.
* @extends FlexContainerComponent
* @inheritdoc
*/
class Column extends FlexContainerComponent {
/**
*
* @param {Attr} attr
* @param {Modifier} modifier
*/
constructor(attr = {}, modifier = null) {
super(attr, modifier);
this.addStyleClass("column-component");
this._flexDirection = "column";
this.setFlexDirection();
}
}

292
src/component.js → src/component/Component.js

@ -1,10 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Represents the most basic and simple form of a Component.
* It is mainly a collection of wrapper methods
@ -19,10 +12,6 @@ class Component extends StyleAndScriptStoringComponent {
* @type {boolean}
*/
_isCompel;
/**
* @type {WebTrinity}
*/
_wenity;
/**
* @type {Array<any>}
*/
@ -93,14 +82,21 @@ class Component extends StyleAndScriptStoringComponent {
* @param {boolean} horizontal Defines if the Component should overflow horizontally (default: false)
* @returns {Component}
*/
overflow(vertical = true, horizontal = false) {
if (vertical) {
overflow(vertical = true, horizontal = false ) {
if (vertical || horizontal) {
this._modifier.join(
new Modifier()
.removeStyleRule("flex")
.setStyleRule("overflow", "hidden auto")
);
this.subscribeOnGenerate(CommonCompelGroups.OVERFLOWING);
this._modifier._modifications["overflow-y"] = "auto";
}
if (vertical) {
this._modifier._modifications["overflow-y"] = "hidden auto";
}
if (horizontal) {
this.subscribeOnGenerate(CommonCompelGroups.OVERFLOWING);
this._modifier._modifications["overflow-x"] = "auto";
this._modifier._modifications["overflow-x"] = "hidden auto";
}
return this;
}
@ -296,270 +292,38 @@ class Component extends StyleAndScriptStoringComponent {
}
/**
* Defines how a child Component is to be appended.
* @param {Component} component the child component to add it.
* @returns {HTMLElement}
*/
_appendChildComponent(component) {
let child = new WebTrinity();
if (component instanceof Component) {
child = component.generate();
}
if (component instanceof WebTrinity) {
child = component;
}
if (component instanceof HTMLElement) {
console.log("No wenity set - htmlEl was given");
child.html = component;
}
this._element.append(child.html);
return child;
}
/**
*
* @param {ExtStorage} extStore
* @returns {Array<SStoreDefinition>}
*/
_processStyles(extStore = null) {
extStore = (extStore
? extStore
: this._stylesExtStore
)
.setupForGeneralStyling();
let forCollection = [];
let counter = 0;
for (const ssd of this._styles) {
/* Make sure that the type is unified for later processing */
if (ssd._definition instanceof Modifier) {
ssd._definition = ssd._definition._modifications;
}
/* Check/Ensure proper ExtStorageType for following comparison */
/**
* @type {ExtStorage}
*/
let curExtStore = extStore;
if (Object.hasOwn(ssd, "_extStore") && ssd._extStore) {
curExtStore = ssd._extStore.setupForGeneralStyling();
}
if (curExtStore.getStylingDistribution()(ssd, this._element, counter)) {
forCollection.push(ssd);
}
}
return forCollection;
}
/**
*
* @param {ExtStorage} extStore
* @returns {Array<SStoreDefinition>}
*/
_processFunctions(extStore = null) {
extStore = (extStore
? extStore
: this._functionsExtStore
)
.setupForFunctions();
const forCollection = new Map();
const collectForBefore = [];
let counter = 0;
for (const ssd of this._functions) {
/* Make sure that the type is unified for later processing */
let curExtStore = extStore;
if (Object.hasOwn(ssd, "_extStore") && ssd._extStore) {
curExtStore = ssd._extStore.setupForFunctions();
}
if (curExtStore.getFunctionDistribution()(ssd, counter)) {
if (curExtStore._position.BEFORE) {
collectForBefore.push(ssd);
} else {
if (!forCollection.has(curExtStore)) {
forCollection.set(curExtStore, []);
}
forCollection.get(curExtStore).push(ssd);
}
}
}
return forCollection;
}
/**
* Ends chain.
* Applies all modifications on the element.
* Processes alls stored additions.
* Processes all stored additions.
* Returns the constructed HTMLElement of this Component.
*
*
* @param {CompelGenerator} generator
* @param {Modifier | undefined} [modifier=null]
* @param {ExtStorage | undefined} [styleStore=null]
* @param {ExtStorage | undefined} [functionStore=null]
* @param {ExtStorage}
* @returns {WebTrinity} the constructed HTMLElement of this Component.
*/
generate(modifier = null, styleStore = null, functionStore = null) {
generate(generator = singlepage, styleStore = null, functionStore = null) {
/**
* In the case that this component is a chainChild created one.
* The generation chain needs to be setup in the proper order
* so that the resulting element tree equals the expected/desired result.
*
* Therefore if this is a chainChild,
* it will be added to the parent via the regular childContext
* and the generation of the parent will be returned.
*
* The parent will generate this component on its generate().
*/
if (this._parentComponent) {
let parent = this._parentComponent;
this._parentComponent = null;
return parent.childContext(this)
.generate(modifier, styleStore, functionStore);
}
if (modifier) {
this._modifier = modifier
.join(this._modifier);
}
this._wenity = new WebTrinity();
if (!styleStore) {
styleStore = this._stylesExtStore;
.generate(generator, styleStore, functionStore);
}
/* DEAL WITH COMPONENT MODIFICATION FIRST */
// @todo pay attention to the "overwrite" behaviour - the local modifier styles are the "closest"
// it might be appropriate to use this._styles.unshift(...) instead.
this._styles.push(new SStoreDefinition(
(styleStore._aggregation !== ESAggregation.INTERNALIZED ? "." : "") + this._compName,
this._modifier,
this._stylesExtStore
));
/* DEAL WITH CHILDREN */
let collectedWenities = [];
for (let i = 0; i < this._children.length; i++) {
/**
* @type {Component}
*/
let child = this._children[i];
if (child instanceof ChainableModifier) {
child = child.toComponent();
}
if (Page._useCssCalc) {
child._modifier._updateDimensionsBy(this._modifier._paddingValues);
}
child = child.generate(modifier, styleStore, functionStore);
let wenity = this._appendChildComponent(child);
if (!wenity.isSSEmpty()) {
collectedWenities.push(wenity);
}
}
/* DEAL WITH STYLING AND PROCESSING */
/**
* @type {Array<SStoreDefinition>}
*/
let styleCollection = this._processStyles(styleStore);
/**
* @type {Map<ExtStoreType, Array<SStoreDefinition>>}
*/
const funcCollections = this._processFunctions(functionStore);
/**
*
* @param {Map<ExtStoreType, Array<SStoreDefinition>>} source
* @param {Map<ExtStoreType, Array<SStoreDefinition>>} target
* @param {ExtStoreType} extStoreType
* @returns
*/
function transferCollectedFunctions(source, target, extStoreType) {
if (source) {
if (source.has(extStoreType)) {
if (funcCollections.has(extStoreType)) {
target.get(extStoreType)
.push(source.get(extStoreType))
} else {
target.set(
extStoreType,
source.get(extStoreType)
);
}
}
}
return target;
}
function executeOnExtStoreTypeCollectedTriple(func) {
return new Map([
{ [ExtStoreType.COLLECTED_SEGMENT_BEGIN]: func(ExtStoreType.COLLECTED_SEGMENT_BEGIN) },
{ [ExtStoreType.COLLECTED_DOC_HEAD]: func(ExtStoreType.COLLECTED_DOC_HEAD) },
{ [ExtStoreType.COLLECTED_DOC_FOOTER]: func(ExtStoreType.COLLECTED_DOC_FOOTER) }
]);
}
for (let i = 0; i < collectedWenities.length; i++) {
const child = collectedWenities[i];
if (child.js) {
executeOnExtStoreTypeCollectedTriple(
(extstoretype) => transferCollectedFunctions(child.js, funcCollections, extstoretype)
);
}
}
if (this._isCompel) {
/**
*
* @param {Map<ExtStoreType, *>} map
* @param {ExtStorageType} extStoreType
*/
function dealCollected(map, extStoreType) {
if (map.has(extStoreType)) {
let collectionScriptTag = generateAndFillScriptTag(map.get(extStoreType));
if (extStoreType === ExtStoreType.COLLECTED_SEGMENT_BEGIN) {
this._element.insertAdjacentElement(
"afterbegin",
generateAndFillScriptTag(segment)
);
} else {
Page.addElementToPage(
collectionScriptTag,
extStoreType
);
}
}
}
executeOnExtStoreTypeCollectedTriple((est) => dealCollected(funcCollections, est));
} else {
this._wenity.js = funcCollections;
this._wenity.css = styleCollection;
}
this._wenity.html = this._element;
for (let i = 0; i < this._toRegister.length; i++) {
const group = this._toRegister[i];
Page.subscribeComponentToGroup(group, this._compName)
}
return this._wenity;
return generator.generate(this, styleStore, functionStore);
}
}

173
src/component/FlexContainerComponent.js

@ -0,0 +1,173 @@
/**
* Represents container Components.
* Some predefined modifications are applied on the child components.
* @extends Component
* @inheritdoc
*/
class FlexContainerComponent extends Component {
/**
* @type {boolean}
*/
_distributeEvenglyAfterGenerate;
/**
* @type {number} the amount that should be left out of the total space before the children
* space is set.
*/
#distributionRecess;
/**
* @type {number} the additional gap that should be left for children before their space is set
*/
#distributionGapPerChild;
/**
* @type {string}
*/
_flexDirection;
/**
*
* @param {Attr} attr
* @param {Modifier} modifier
*/
constructor(attr = {}, modifier = null, baseElement = "div") {
super(document.createElement(baseElement), attr);
this._flexDirection = "";
this._distributeEvenglyAfterGenerate = false;
this.addStyleClass("flex-container-component");
if (modifier) {
this.modifier(modifier);
}
}
/**
*
* @param {boolean} [vertical=true]
* @returns {FlexContainerComponent}
*/
setFlexDirection(vertical = true) {
return this.modifier(
new Modifier()
.setStyleRule(
"flex-direction",
(vertical ? "column" : "row")
)
);
}
/**
*
* @param {Component|Array<Component>} innerComponent
* @returns {FlexContainerComponent} this component object
*/
childContext(innerComponent) {
if (innerComponent instanceof Array) {
innerComponent
.map(cl => {
if (cl instanceof Component) {
return cl;
} else {
return cl.ensureModifier().toComponent();
}
})
.forEach(icomp => {
icomp._modifier = new Modifier()
.removeStyleRule("flex")
.join(icomp._modifier);
});
}
return super.childContext(innerComponent);
}
/**
*
* @param {number} [recessFraction=0.0] recessFraction a fraction/percentage of the recess
* that should be left out before distributing the remaining space.
* @param {number} [gapPerChild=1] gapPerChild the gap per child, therefore inbetween children
* that shouldn't be distributed to the children
*/
_distributingSpacing(recessFraction = 0.0, gapPerChild = 1) {
if (this._children && this._children.length > 1) {
let distributableSpace = 100 - 100 * recessFraction - (this._children.length - 1) * gapPerChild;
let childDistributionFraction = Math.floor(
(distributableSpace / this._children.length) * 100
) / 100;
let direction = (this._flexDirection === 'column' ? 'height' : "width");
for (const icomp of this._children) {
/* sets the width for all elements,
to avoid overlapping or line break because of lacking width,
a percent is subtracted for every child element */
/* To enable "override" a new Modifier is generated and joined
with the modifier of the component */
icomp._modifier._modifications[direction] = childDistributionFraction + "%";
icomp._modifier._modifications["max-" + direction] = childDistributionFraction + "%";
}
}
}
/**
* Distributes the spacing of the childrens evengly,
* according to the flexdirection of this component.
* By default this will be executed imediately when called.
*
* @param {boolean} [rightNow=true] if set to false it will set properties accordingly
* so that the distribution will be executed on generate
* @param {number} [recessFraction=0.0] recessFraction a fraction/percentage of the recess
* that should be left out before distributing the remaining space.
* @param {number} [gapPerChild=1] gapPerChild the gap per child, therefore inbetween children
* that shouldn't be distributed to the children
* @returns {FlexContainerComponent}
*/
distibuteSpacingEvenly(rightNow = true, recessFraction = 0.0, gapPerChild = 1) {
if (rightNow) {
this._distributingSpacing(recessFraction, gapPerChild);
} else {
this.#distributionRecess = recessFraction;
this.#distributionGapPerChild = gapPerChild;
this._distributeEvenglyAfterGenerate = true;
}
return this;
}
/**
* Adds, sets, updates or overwrites the Modification of/for the children of this component.
* Just calls .modifier(modifier) on each child.
*
* @param {Modifier} modifier
* @param {boolean|ExtStorage|ExtStoreType|OverwriteBehaviour} [extStore=null]
* @returns {FlexContainerComponent} this component object
*/
modifyChildren(modifier, underTheName = "", extStore = false) {
if (underTheName === "") {
underTheName = `.${this._compName}-style-children`;
}
if (!extStore) {
for (const child of this._children) {
child.modifier(modifier)
}
} else {
this.addStyleClass(underTheName);
this._styles.push(
new SStoreDefinition(
underTheName,
modifier.ensureModifier()
)
);
}
return this;
}
/**
* @override
* @inheritdoc
* @extends Component.generate()
*/
generate(generator = singlepage, styleStore = null, functionStore = null) {
if (this._distributeEvenglyAfterGenerate) {
this._distributingSpacing(this.#distributionRecess, this.#distributionGapPerChild);
}
return super.generate(generator, styleStore, functionStore);
}
}

69
src/component/InputComponent.js

@ -0,0 +1,69 @@
/**
* Represents a Component (of an HTMLElement) that is capable of receiving input.
* @extends Component
* @inheritdoc
*/
class InputComponent extends Component {
/**
*
* @param {string} element
* @param {Attr} attr
* @param {Modifier} modifier
*/
constructor(element, attr = {}, modifier = null) {
super(element, attr);
this.addStyleClass("el-input-comp");
if (modifier) {
this.modifier(modifier);
}
}
/**
* This overrides the text() method in such a way,
* that it sets the value attribute for input elements instead.
*
* @override
* @inheritdoc
* @param {string} text
* @returns {InputComponent}
*/
text(text){
if (this._element instanceof HTMLInputElement) {
this._element.value = text;
} else {
super.text(text);
}
return this;
}
/**
* The parameter makes it optional to trigger the state by a variable
* @param {boolean} readonly
* @returns {Component}
*/
readonly(readonly = true) {
if (readonly) {
this._element.setAttribute("readonly", readonly);
}
return this;
}
/**
* Sets the value of the InputComponent
* @param {string} Value
* @returns {InputComponent|Component}
*/
value(value) {
this._element.value = value;
return this;
}
/**
*
* @param {string} name
* @returns {InputComponent|Component}
*/
name(name) {
return this.setAttribute("name", name);
}
}

46
src/component/Row.js

@ -0,0 +1,46 @@
/**
* A FlexContainerComponent, which organizes the children in a row like manner.
*
* @extends FlexContainerComponent
* @inheritdoc
*/
class Row extends FlexContainerComponent {
/**
*
* @param {Attr} attr
* @param {Modifier} modifier
*/
constructor(attr = {}, modifier = null) {
super(attr, modifier);
this.addStyleClass("row-component")
this._flexDirection = "row";
//this.modifier(new Modifier().fillMaxWidth());
this.setFlexDirection(false);
}
/**
*
* @param {Component|Array<Component>} innerComponent
* @returns {Row}
*/
childContext(innerComponent) {
function setFloat(comp, side = "right") {
comp._modifier = new Modifier()
.setStyleRule("float", side)
.join(comp._modifier);
}
super.childContext(innerComponent);
for (const child of this._children) {
onSingleOrArray(
child,
(e, i) => setFloat(e, (i === 0 ? "left" : "right"))
);
}
return this;
}
}

30
src/componentAncestry/addStyleAndFunctions.js → src/component/StyleAndScriptStoringComponent.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* @inheritdoc
* @abstract
@ -51,24 +45,18 @@ class StyleAndScriptStoringComponent extends ModifiableComponent {
constructor(element, attr = {}) {
super(element, attr);
this._styleClassesExtStore = ExtStoreType.CENTRALIZED_DOC_HEAD
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE);
this._isClassESDefault = true;
this._stylesExtStore = ExtStoreType.INTERNALIZED_WITHIN
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE);
this._isStyleESDefault = true;
this._styles = [];
this._isFunESDefault = true;
this._functions = [];
this._styleClassesExtStore = ExtStoreType.CENTRALIZED_DOC_HEAD
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE);
this._stylesExtStore = ExtStoreType.INTERNALIZED_WITHIN
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE);
this._functionsExtStore = ExtStoreType.CENTRALIZED_DOC_HEAD
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE);
this._isFunESDefault = true;
this._functions = [];
}
@ -152,11 +140,11 @@ class StyleAndScriptStoringComponent extends ModifiableComponent {
setFunctionsStorage(extStore) {
if (extStore) {
if (extStore instanceof ExtStorage) {
this._stylesExtStore = extStore;
this._functionsExtStore = extStore;
} else if (extStore instanceof ExtStoreType) {
this._stylesExtStore.setExtStoreType(extStore);
this._functionsExtStore.setExtStoreType(extStore);
} else {
this._stylesExtStore.OverwriteBehaviour(extStore);
this._functionsExtStore.OverwriteBehaviour(extStore);
}
this._isFunESDefault = false;
} else {

7
src/componentAncestry/modifiableComponent.js → src/component/modifiableComponent.js

@ -1,10 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* @inheritdoc
* @extends ChildbearerComponent

8
src/context.js → src/context/context.js

@ -1,10 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* @todo Potentially class implementation could be removed entirely.
* Since it (at the time being) is only working as a singleton anyway.
@ -199,4 +192,5 @@ const CommonCompelGroups = Object.freeze({
DROP_TARGET: "droptarget",
});
const Page = new PageBuilder();

19
src/context/framework-controls.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
*
* @param {Array<CompelExtension>} extensions
@ -21,15 +15,12 @@ function frameworkControlPanel(
new Modifier()
.fillMaxWidth()
.background(MaterialFiveHundredlColors.ORANGE)
.dimensions(
new Dimensions()
.height(200)
)
.padding(4)
.border(
new Border(3)
.color(Colors.goldenrod_3)
.color(Colors.goldenrod_3)
)
.linkPadding(4)
.dimensions().height(200)
)
.childContext([
builder.column()
@ -41,8 +32,8 @@ function frameworkControlPanel(
.overflow()
.modifier(
new Modifier()
.linkPadding(4).ensureModifier()
.linkBorder(1)
.padding(4)
.border(1)
)
.childContext(
extensions.map(

11
src/context/scriptAndStyleContext.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* @abstract
* Class adds function and style storing properties to the context (PageBuilder).
@ -56,8 +50,7 @@ class ScriptAndStyleContext {
].find(e => e !== '');
/* deal with name already present */
let functionNames = this.#functions.keys;
if (functionNames.includes(registrationName)) {
if (this.#functions.has(registrationName)) {
registrationName = resolveOverwrite(registrationName, this.#functions, overwriteBehaviour);
}
@ -180,7 +173,7 @@ class ScriptAndStyleContext {
if (this.#functions.size > 0) {
let funcTag = document.createElement('script');
for (const tuple of this.#functions.entries) {
for (const tuple of this.#functions.entries()) {
let regName = tuple[0];
let fsb = tuple[1];
funcTag.innerText += getScriptTagInjectionText(fsb.func, regName);

31
src/context/webTrinity.js

@ -1,31 +0,0 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Wenity := Web Trinity
*/
class WebTrinity {
/**
*
* @param {HTMLElement|Component} html
* @param {HTMLStyleElement|Map<ExtStorageType, Array<SStoreDefinition>} js
* @param {HTMLScriptElement|Array<SStoreDefinition>} css
*/
constructor(html = null, js = null, css = null) {
this.html = html;
this.js = js;
this.css = css;
}
/**
*
* @returns {boolean}
*/
isSSEmpty() {
return (this.js === null || this.js.length === 0)
&& (this.css === null || this.css.size === 0);
}
}

6
src/alignment.js → src/decorators/alignment.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Enum providing common alignment rules
*/

6
src/arrangement.js → src/decorators/arrangement.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Enum providing common alignment rules
*/

83
src/sizeSide/border.js → src/decorators/border.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
*
*/
@ -21,24 +15,50 @@ const LineStyles = Object.freeze({
})
class BorderDefinition {
/**
*
* @param {number} width
* @param {Color} color
* @param {LineStyles} style
*/
constructor(width = 0, color = Colors.black, style = LineStyles.solid) {
this._width = width;
this._color = color;
this._style = style;
}
/**
*
* @param {number} width
* @returns {BorderDefinition}
*/
width(width) {
this._width = width;
return this;
}
/**
*
* @param {Color} color
* @returns {BorderDefinition}
*/
color(color) {
this._color = color;
return this;
}
/**
*
* @param {LineStyles} style
* @returns {BorderDefinition}
*/
style(style) {
this._style = style;
return this;
}
/**
*
* @param {BorderDefinition} def
* @returns {BorderDefinition}
*/
join(def) {
Object.keys(def)
.forEach(key => this[key] = def[key]);
@ -57,20 +77,25 @@ const Define = Object.freeze({
* @extends Sides
*/
class Border extends Sides {
constructor(width = 0, color = Colors.black, style = LineStyles.solid, defaultUnit = SizeUnits.PIXEL, shape = Shapes.Rectangle) {
constructor(width = 0, color = Colors.black, style = LineStyles.solid, defaultUnit = SizeUnits.PIXEL) {
super('border', 0, defaultUnit);
this._fFirst = new BorderDefinition(width, color, style);
this._fSecond = new BorderDefinition(width, color, style);
this._fThird = new BorderDefinition(width, color, style);
this._fForth = new BorderDefinition(width, color, style);
this._shape = shape;
}
/**
* @override
* @param {number} index
* @param {number} value
* @returns {Border}
*/
setByIndex(index, value) {
if (value instanceof BorderDefinition) {
this.getByIndex(index).join(value)
this.getByIndex(index).join(value);
} else {
this.getByIndex(index)._width = value
this.getByIndex(index)._width = value;
}
return this;
}
@ -79,7 +104,7 @@ class Border extends Sides {
*
* @param {string} key
* @param {*} value
* @returns {this}
* @returns {typeof Border}
*/
setOnDirections(key, value) {
let orderedAttributes = this.getOrderedAttributes()
@ -92,7 +117,7 @@ class Border extends Sides {
/**
*
* @param {number} width
* @returns {this}
* @returns {typeof Border}
*/
width(width) {
this._fFirst._width = width;
@ -105,7 +130,7 @@ class Border extends Sides {
/**
*
* @param {*} color
* @returns {this}
* @returns {typeof Border}
*/
color(color) {
this._fFirst._color = color;
@ -118,7 +143,7 @@ class Border extends Sides {
/**
*
* @param {Shape} shape
* @returns {this}
* @returns {typeof Border}
*/
shape(shape) {
this._shape = shape;
@ -128,7 +153,7 @@ class Border extends Sides {
/**
* Sets the border-style of all sides to the given.
* @param {LineStyles} lineStyle style of the border
* @returns {this}
* @returns {typeof Border}
*/
setStyleAll(lineStyle) {
this._fFirst._style = lineStyle;
@ -142,7 +167,7 @@ class Border extends Sides {
*
* @param {LineStyles} lineStyle
* @param {*} sidingRefSide
* @returns {this}
* @returns {typeof Border}
*/
setLineStyle(lineStyle, sidingRefSide) {
this._sidingStyles.setBySidingRef(sidingRefSide, lineStyle)
@ -152,7 +177,7 @@ class Border extends Sides {
/**
*
* @param {Map<SidingRefSides, LineStyles} refSideStyleMap
* @returns {this}
* @returns {typeof Border}
*/
setLineStyles(refSideStyleMap) {
let rkeys = Object.keys(refSideStyleMap);
@ -181,6 +206,30 @@ class Border extends Sides {
]
});
}
/**
* If the given amount is a number this method calls width(amount).
* If amount is instanceof BorderDefinition it will set the BorderDefinition
* to all sides.
* If neither it will do nothing and return this Border object.
*
* @inheritdoc
* @override
* @param {number|BorderDefinition} amount value to set for all directions
* @returns {typeof Sides} this
*/
all(amount) {
if(amount instanceof Number){
return this.width(amount);
}
if(amount instanceof BorderDefinition){
return super.all(amount);
}
return this;
}
}
/**

8
src/color.js → src/decorators/color.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* A simple Color class for rgb set color values.
*
@ -507,7 +501,6 @@ const Colors = Object.freeze({
gray_99: new Color(252, 252, 252).hex('#FCFCFC'),
gray_98: new Color(250, 250, 250).hex('#FAFAFA'),
gray_97: new Color(247, 247, 247).hex('#F7F7F7'),
white_smoke: new Color(245, 245, 245).hex('#F5F5F5'), // (gray 96)
gray_95: new Color(242, 242, 242).hex('#F2F2F2'),
gray_94: new Color(240, 240, 240).hex('#F0F0F0'),
gray_93: new Color(237, 237, 237).hex('#EDEDED'),
@ -562,7 +555,6 @@ const Colors = Object.freeze({
gray_44: new Color(112, 112, 112).hex('#707070'),
gray_43: new Color(110, 110, 110).hex('#6E6E6E'),
gray_42: new Color(107, 107, 107).hex('#6B6B6B'),
dimgray: new Color(105, 105, 105).hex('#696969'), // (gray 42)
gray_40: new Color(102, 102, 102).hex('#666666'),
gray_39: new Color(99, 99, 99).hex('#636363'),
gray_38: new Color(97, 97, 97).hex('#616161'),

19
src/sizeSide/dimensions.js → src/decorators/dimensions.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Simple Dimensions container for the height and width in pixels.
*
@ -26,7 +20,7 @@ class Dimensions extends DirectionUnitDependentAttribute {
/**
* Sets width (x) value of amount
* @param {number} amount
* @returns {this} this Dimensions Modifier
* @returns {typeof Dimensions} this Dimensions Modifier
*/
width(amount) {
this._fFirst = amount;
@ -36,7 +30,7 @@ class Dimensions extends DirectionUnitDependentAttribute {
/**
* Sets height (y) value of amount
* @param {number} amount
* @returns {this} this Dimensions Modifier
* @returns {typeof Dimensions} this Dimensions Modifier
*/
height(amount) {
this._fSecond = amount;
@ -46,15 +40,18 @@ class Dimensions extends DirectionUnitDependentAttribute {
/**
*
* @param {number} size
* @returns {this}
* @returns {typeof Dimensions}
*/
all(size) {
return this.width(size).height(size);
}
/**
*
* @returns
*/
getOrderedValues() {
return this.getOrderedValues().slice(2)
return super.getOrderedValues().slice(2)
}
/**

2
src/modifiers/margin.js → src/decorators/margin.js

@ -9,7 +9,7 @@ class Margin extends Sides {
* @param {SizeUnits} defaultUnit
*/
constructor(defaultValue = 0, defaultUnit = SizeUnits.PIXEL) {
super("margin",defaultValue, defaultUnit);
super("margin", defaultValue, defaultUnit);
}
}

0
src/modifiers/padding.js → src/decorators/padding.js

30
src/sizeSide/shapes.js → src/decorators/shapes.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* @extends DirectionUnitDependentAttribute
* @inheritdoc
@ -15,7 +9,7 @@ class Shape extends DirectionUnitDependentAttribute {
/**
*
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
topLeft(amount) {
this._fFirst = amount;
@ -24,7 +18,7 @@ class Shape extends DirectionUnitDependentAttribute {
/**
*
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
topRight(amount) {
this._fSecond = amount;
@ -33,7 +27,7 @@ class Shape extends DirectionUnitDependentAttribute {
/**
*
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
bottomLeft(amount) {
this._fForth = amount;
@ -42,7 +36,7 @@ class Shape extends DirectionUnitDependentAttribute {
/**
*
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
bottomRight(amount) {
this._fThird = amount;
@ -51,7 +45,7 @@ class Shape extends DirectionUnitDependentAttribute {
/**
* Sets the BottomLeft and TopRight corners
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
diagonalPositive(amount) {
return this.bottomLeft(amount).topRight(amount);
@ -59,7 +53,7 @@ class Shape extends DirectionUnitDependentAttribute {
/**
* Sets the TopLeft and BottomRight corners
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
diagonalNegative(amount) {
return this.topLeft(amount).bottomRight(amount);
@ -67,7 +61,7 @@ class Shape extends DirectionUnitDependentAttribute {
/**
* Sets both corners on the left side
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
left(amount) {
return this.topLeft(amount).bottomLeft(amount);
@ -75,7 +69,7 @@ class Shape extends DirectionUnitDependentAttribute {
/**
* Sets both corners on the right side
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
right(amount) {
return this.topRight(amount).bottomRight(amount);
@ -83,17 +77,17 @@ class Shape extends DirectionUnitDependentAttribute {
/**
* Sets both top corners
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
top(amount){
top(amount) {
return this.topLeft(amount).topRight(amount);
}
/**
* Sets both bottom corners
* @param {number} amount
* @returns {this}
* @returns {typeof Shape}
*/
bottom(amount){
bottom(amount) {
return this.bottomLeft(amount).bottomRight(amount);
}

24
src/sizeSide/siding.js → src/decorators/siding.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Enum providing predefined set of Size-Units
*/
@ -43,7 +37,7 @@ class DirectionUnitDependentAttribute {
/**
*
* @param {Units} unit The unit of the amount or style
* @returns {this} this - Object
* @returns {typeof Sides} this - Object
*/
setUnit(unit) {
this._unit = unit;
@ -72,7 +66,7 @@ class DirectionUnitDependentAttribute {
* Mainly used by the setup of directions of subclasses.
* @param {number} index [1,4]
* @param {number} value
* @returns {this} this
* @returns {typeof Sides} this
*/
setByIndex(index, value) {
switch (index) {
@ -132,7 +126,7 @@ class DirectionUnitDependentAttribute {
/**
* sets the amount-value for all directions.
* @param {number} amount value to set for all directions
* @returns {this} this
* @returns {typeof Sides} this
*/
all(amount) {
this._fFirst = amount;
@ -188,7 +182,7 @@ class Sides extends DirectionUnitDependentAttribute {
/**
* sets the amount-value for the left side.
* @param {number} amount Sides for left
* @returns {this} this Sides Object
* @returns {typeof Sides} this Sides Object
*/
left(amount) {
return this.setByIndex(1, amount);
@ -197,7 +191,7 @@ class Sides extends DirectionUnitDependentAttribute {
/**
* sets the amount-value for the right side.
* @param {number} amount Sides for right
* @returns {this} this Sides Object
* @returns {typeof Sides} this Sides Object
*/
right(amount) {
return this.setByIndex(3, amount);
@ -206,7 +200,7 @@ class Sides extends DirectionUnitDependentAttribute {
/**
* sets the amount-value for the top side.
* @param {number} amount Sides for top
* @returns {this} this Sides Object
* @returns {typeof Sides} this Sides Object
*/
top(amount) {
return this.setByIndex(2, amount);
@ -215,7 +209,7 @@ class Sides extends DirectionUnitDependentAttribute {
/**
* sets the amount-value for the bottom side.
* @param {number} amount Sides for bottom
* @returns {this} this Sides Object
* @returns {typeof Sides} this Sides Object
*/
bottom(amount) {
return this.setByIndex(4, amount);
@ -225,7 +219,7 @@ class Sides extends DirectionUnitDependentAttribute {
/**
* sets the amount-value for the horizontal sides (left and right).
* @param {number} amount Sides for left and right.
* @returns {this} this Sides Object
* @returns {typeof Sides} this Sides Object
*/
horizontal(amount) {
return this.left(amount).right(amount);
@ -234,7 +228,7 @@ class Sides extends DirectionUnitDependentAttribute {
/**
* sets the amount-value for the vertical sides (left and right).
* @param {number} amount Sides for top and bottom.
* @returns {this} this Sides Object
* @returns {typeof Sides} this Sides Object
*/
vertical(amount) {
return this.top(amount).bottom(amount);

84
src/extensions/extension.js

@ -1,84 +0,0 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Defines an extension that can be added to the jpclw-framework
*/
class CompelExtension {
/**
* @type {string}
*/
name;
/**
* @type {string}
*/
diplayTitle;
/**
* @type {Array<SStoreDefinition>}
*/
stylings;
/**
* @type {Array<SStoreDefinition>}
*/
functions;
/**
* Predefined components. Usually of a higher (constructed) kind.
* @type {Object}
*/
components;
/**
* Extensions for/to the Page or the framework in general.
* @type {Object}
*/
frameworkControls;
/**
* Additional elements for the builder (likely referencing components)
* @type {Object}
*/
builderElements;
/**
* Additional helper functions
* @type {{*:Function}}
*/
helperFun;
/**
* functions that are supposed to be executed after install,
* to extend it that way.
* @type {Array<Function>}
*/
funAfterInstall
/**
* defines how jpc-like-websites is to be extended and executes that extension
*/
install() {
if (this.helperFun) {
helperFun.extensions = Object.assign(helperFun.extensions, this.helperFun);
}
if (this.builderElements) {
builder.extensions = Object.assign(builder.extensions, this.builderElements);
}
if (this.frameworkControls) {
Page.extensions = Object.assign(Page.extensions, this.frameworkControls);
}
if (this.stylings) {
for (const key of Object.keys(this.stylings)) {
Page.registerStyling(key, this.stylings[key]);
}
}
if (this.funAfterInstall) {
for (const fun of this.funAfterInstall) {
fun();
}
}
}
}

1
src/generators/defaultGenerators.js

@ -0,0 +1 @@
const singlepage = new CompelGenerator();

313
src/generators/generator.js

@ -0,0 +1,313 @@
/**
* This class defines the Component generator.
* It externalizes all decision making about script or style storage from the component.
* The component stores the generator (if set, if not =default or passed down from parent component).
* The CompelGenerator class enables the setup/definition of storage, generation and distribution.
*
* Further if other frameworks are targeted:
* if the components should be generated in a manner
* that they fullfill the setup/look of other framework-components.
* Only the generator has to be modified, implemented, extended ...
* not the component, modifier or any other of the classes.
*
* Therefore the usages of CompelGenerator-feature-logic resets all style and script storages to local.
* Only towards the end (when "generate()" is called) any of that will be resolved.
*/
class CompelGenerator {
/**
* @param {ExtStorage} styleStore default ExtStoreType.INTERNALIZED_WITHIN
* @param {ExtStorage} functionStore default ExtStoreType.CENTRALIZED_DOC_HEAD
*/
constructor(
styleStore = ExtStoreType.INTERNALIZED_WITHIN
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE),
functionStore = ExtStoreType.CENTRALIZED_DOC_HEAD
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE)
) {
this._styleStore = styleStore;
this._functionStore = functionStore;
}
/**
* Deals with the direct component stylings
* @param {Component} component
* @param {Array<WebTrinity>} childrenWenity
* @param {ExtStorage} extStore
* @returns {Array<SStoreDefinition>}
*/
processStyles(component, extStore = null) {
extStore = (extStore
? extStore
: component._stylesExtStore
)
.setupForGeneralStyling();
let forCollection = [];
let counter = 0;
for (const ssd of component._styles) {
/* Make sure that the type is unified for later processing */
if (ssd._definition instanceof Modifier) {
ssd._definition = ssd._definition._modifications;
}
/* Check/Ensure proper ExtStorageType for following comparison */
/**
* @type {ExtStorage}
*/
let curExtStore = extStore;
if (ssd.hasOwnProperty("_extStore") && ssd._extStore) {
curExtStore = ssd._extStore.setupForGeneralStyling();
}
if (curExtStore.getStylingDistribution()(ssd, component._element, counter)) {
forCollection.push(ssd);
}
}
return forCollection;
}
/**
* First deals with the scripts/functions.
*
* @param {Component} component
* @param {Array<WebTrinity>} childrenWenity
* @param {ExtStorage} extStore
* @returns {Array<SStoreDefinition>}
*/
processFunctions(component, extStore = null) {
extStore = (extStore
? extStore
: component._functionsExtStore
)
.setupForFunctions();
const forCollection = new Map();
const collectForBefore = [];
let counter = 0;
for (const ssd of component._functions) {
/* Make sure that the type is unified for later processing */
let curExtStore = extStore;
if (Object.hasOwn(ssd, "_extStore") && ssd._extStore) {
curExtStore = ssd._extStore.setupForFunctions();
}
if (curExtStore.getFunctionDistribution()(ssd, counter)) {
if (curExtStore._position.BEFORE) {
collectForBefore.push(ssd);
} else {
if (!forCollection.has(curExtStore)) {
forCollection.set(curExtStore, []);
}
forCollection.get(curExtStore).push(ssd);
}
}
}
return forCollection;
}
/**
* checks if the source has the extStoreType
* fills the target extStoreType-array with the corr. elements of source.
* @param {Map<ExtStoreType, Array<SStoreDefinition>>} source
* @param {Map<ExtStoreType, Array<SStoreDefinition>>} target
* @param {ExtStoreType} extStoreType
* @returns
*/
transferCollectedFunctions(source, target, extStoreType) {
if (source) {
if (source.has(extStoreType)) {
if (funcCollections.has(extStoreType)) {
target.get(extStoreType)
.push(source.get(extStoreType))
} else {
target.set(
extStoreType,
source.get(extStoreType)
);
}
}
}
return target;
}
/**
*
*
* @param {Map<ExtStoreType, *>} extFuncMap
* @param {ExtStorageType} extStoreType
*/
dealCollectedFuncs(extFuncMap, extStoreType) {
if (extFuncMap.has(extStoreType)) {
let collectionScriptTag = generateAndFillScriptTag(extFuncMap.get(extStoreType));
if (extStoreType === ExtStoreType.COLLECTED_SEGMENT_BEGIN) {
this._element.insertAdjacentElement(
"afterbegin",
generateAndFillScriptTag(segment)
);
} else {
Page.addElementToPage(
collectionScriptTag,
extStoreType
);
}
}
}
/**
* Generates and appends a child Component.
* @param {Component} parent component the child component to add it.
* @param {Component|WebTrinity|string} child
* @returns {WebTrinity}
*/
appendChildComponent(parent, child) {
let childWT = new WebTrinity();
if (child instanceof Component) {
childWT = child.generate(this);
}
if (child instanceof WebTrinity) {
childWT = child;
}
if (child instanceof HTMLElement) {
console.log("No wenity set - htmlEl was given");
childWT.compext = child;
}
parent._element.append(childWT.compext);
return childWT;
}
/**
* Iterates over the children of the component
* and calls generate on each child.
* The resulting compext (the text of the component) is added/appended accordingly.
* If the generation returns with delegatable scripts or styles
* the WebTrinity object is collected in an array,
* which will be returned.
*
* @param {Component} component
* @returns {Array<WebTrinity>}
*/
resolveChildren(component, styleStore, functionStore) {
/**
* @type {Array<WebTrinity>}
*/
let wenities = [];
for (let child of component._children) {
child = child.generate(this, styleStore, functionStore);
let wenity = this.appendChildComponent(component, child);
if (!wenity.isSSEmpty()) {
wenities.push(wenity);
}
}
return wenities;
}
/**
*
* @param {Component} component
* @param {ExtStorage} [styleStore=null]
* @param {ExtStorage} [functionStore=null]
* @returns {WebTrinity}
*/
generate(component, styleStore = null, functionStore = null) {
if (!styleStore) {
styleStore = component._stylesExtStore;
}
if (!functionStore) {
functionStore = component._functionsExtStore;
}
/**
* DEAL WITH COMPONENT MODIFICATION FIRST
*
* @todo pay attention to the "overwrite" behaviour
* the local modifier styles are the "closest"
* it might be appropriate to use this._styles.unshift(...) instead.
*/
component._styles.push(new SStoreDefinition(
(styleStore._aggregation !== ESAggregation.INTERNALIZED
? "."
: "")
+ component._compName,
component._modifier,
component._stylesExtStore
));
/**
* DEAL WITH CHILDREN
*
* Depending on the setup of the generator/-tion
* The children might return scripts or styles
* that are supposed to be collected
* and dealt with as a collection.
*/
let childrenWenities = this.resolveChildren(component, styleStore, functionStore);
/**
* DEAL WITH STYLES AND SCRIPTS
*/
/**
* @type {Array<SStoreDefinition>}
*/
let styleCollection = this.processStyles(component, styleStore);
/**
* @type {Map<ExtStoreType, Array<SStoreDefinition>>}
*/
let funcCollections = this.processFunctions(component, functionStore);
/**
* DEAL WITH CHILDREN WENITY SCRIPTS
*/
for (const child of childrenWenities) {
if (child.scripts) {
executeOnExtStoreTypeCollectedTriple(
(extstoretype) => this.transferCollectedFunctions(child.scripts, funcCollections, extstoretype)
);
}
}
let wenity = new WebTrinity();
/**
* DEAL WITH CHILDREN WENITY STYLE
*/
if (component._isCompel) {
executeOnExtStoreTypeCollectedTriple((est) => this.dealCollectedFuncs(funcCollections, est));
} else {
wenity.scripts = funcCollections;
wenity.stylings = styleCollection;
}
wenity.compext = component._element
for (const group of component._toRegister) {
Page.subscribeComponentToGroup(group, component._compName);
}
return wenity;
}
}

6
src/commonEvents.js → src/handlers/commonEvents.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Enum to access common events
*/

14
src/modifications/contextMenu.js → src/handlers/contextMenu.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* Default implementation of a contextmenu-behaviour
*/
@ -29,8 +23,8 @@ const DefaultContextMenu = {
menu.style.left = `${refPos.getByIndex(SideDirections.LEFT)}px`;
menu.style.top = `${refPos.getByIndex(SideDirections.TOP)}px`;
toggleElementVisibility(menu, true);
toggleElementVisibility(menu);
helperFun.toggleElementVisibility(menu, true);
helperFun.toggleElementVisibility(menu);
document.addEventListener(
"click",
@ -48,7 +42,7 @@ const DefaultContextMenu = {
return function (event) {
if (event.key === "Escape") {
let menu = document.querySelector(`[data-autocompel="${identifier}"`);
toggleElementVisibility(menu, true);
helperFun.toggleElementVisibility(menu, true);
document.removeEventListener("keyup");
}
}
@ -61,7 +55,7 @@ const DefaultContextMenu = {
let area = getEnclosingBounds(menu);
if (!areXYInArea(area, event.clientX, event.clientY)) {
toggleElementVisibility(menu, true);
helperFun.toggleElementVisibility(menu, true);
document.removeEventListener("click")
}
}

6
src/modifications/dragAndDrop.js → src/handlers/dragAndDrop.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
const EventDrag = Object.freeze({
OVER: "over",
START: "start",

55
src/helper/ObjectAccessObject.js

@ -0,0 +1,55 @@
/**
*
*/
class ObjectAccessObject {
/**
*
* @param {Object} object
*/
constructor(object = null) {
/**
* @type {Array<string>}
*/
this.keys = (object ? Object.keys(object) : []);
/**
* @type {Object}
*/
this.objects = (object ? object : {});
}
/**
*
* @param {Array<string>} keyArr
* @param {Object} refObject
* @returns
*/
fillByArrayReference(keyArr, refObject) {
this.keys = keyArr;
refObject = keyArr.reduce((a, c) => Object.assign(a, { [c]: refObject[c] }), {});
return this;
}
/**
*
* @param {string} key
* @param {*} value
* @returns {ObjectAccessObject}
*/
add(key, value) {
this.objects[key, value];
this.keys.push(key);
return this;
}
/**
*
* @param {string} key
* @returns {*}
*/
remove(key) {
let tmp = this.objects[key];
delete this.objects[key];
return tmp;
}
}

70
src/context/generalHelpers.js → src/helper/general.js

@ -1,73 +1,11 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
*
*/
class ObjectAccessObject {
/**
*
* @param {Object} object
*/
constructor(object = null) {
/**
* @type {Array<string>}
*/
this.keys = (object ? Object.keys(object) : []);
/**
* @type {Object}
*/
this.objects = (object ? object : {});
}
/**
*
* @param {Array<string>} keyArr
* @param {Object} refObject
* @returns
*/
fillByArrayReference(keyArr, refObject) {
this.keys = keyArr;
refObject = keyArr.reduce((a, c) => Object.assign(a, { [c]: refObject[c] }), {});
return this;
}
/**
*
* @param {string} key
* @param {*} value
* @returns {ObjectAccessObject}
*/
add(key, value) {
this.objects[key, value];
this.keys.push(key);
return this;
}
/**
*
* @param {string} key
* @returns {*}
*/
remove(key) {
let tmp = this.objects[key];
delete this.objects[key];
return tmp;
}
}
/**
*
* @param {Object | Array<Object>} singleOrArray
* @param {Function} fun
* @returns {Object | Array<Object>}
*/
function onSingleOrArray(singleOrArray, fun){
if(singleOrArray instanceof Array){
function onSingleOrArray(singleOrArray, fun) {
if (singleOrArray instanceof Array) {
return singleOrArray.map(fun);
}
return fun(singleOrArray);
@ -131,7 +69,7 @@ const helperFun = {
*
* @param {HTMLElement} element
* @param {boolean} ensureHidden
* @returns {boolean}
* @returns {boolean} true if element is now hidden
*/
toggleElementVisibility: function (element, ensureHidden = false) {
element.classList.toggle("compel-mech-hidden");
@ -149,7 +87,7 @@ const helperFun = {
}
if (ensureHidden && !isNowHidden) {
return helperFun.toggleSelectorElementVisibility(selector)
return helperFun.toggleElementVisibility(element);
} else {
return isNowHidden;
}

84
src/helper/indices.js

@ -0,0 +1,84 @@
/**
*
* @param {number} start
* @param {number} end
* @param {number} value
* @param {number} tolerance
* @param {boolean} usePercentage
* @returns {boolean}
*/
function isValueInBounds(start, end, value, tolerance = 0, usePercentage = false) {
if (tolerance !== 0) {
if (usePercentage) {
start = start * (1 - tolerance / 100);
end = end * (1 + tolerance / 100);
} else {
start = start - tolerance;
end = end + tolerance;
}
}
return value >= start && value <= end;
}
/**
* @param {number} x
* @param {number} y
* @param {Map<SideDirections,number>} area
* @param {number} tolerance
* @param {boolean} usePercentage if tolerance is given and this is set to true,
* the tolerance will be calculated by percentage,
* otherwise it will be subtracted/added
* @returns {boolean}
*/
function areXYInArea(x, y, area, tolerance = 0, usePercentage = false) {
return isValueInBounds(
area.get(SideDirections.LEFT),
area.get(SideDirections.RIGHT),
x,
tolerance,
usePercentage
) && isValueInBounds(
area.get(SideDirections.TOP),
area.get(SideDirections.BOTTOM),
y,
tolerance,
usePercentage
);
}
/**
*
* @param {TwoDimPoint} point
* @param {Map<SideDirections,number>} area
* @param {number} tolerance
* @param {boolean} usePercentage if tolerance is given and this is set to true,
* the tolerance will be calculated by percentage,
* otherwise it will be subtracted/added
*/
function isPointInArea(point, area, tolerance = 0, usePercentage = false) {
return areXYInArea(
point.x,
point.y,
area,
tolerance,
usePercentage
);
}
/**
*
* @param {HTMLElement} element
* @returns {Object<SideDirections, number}
*/
function getEnclosingBounds(element) {
let area = element.getBoundingClientRect();
let parentArea = element.parentElement.getBoundingClientRect();
return {
[SideDirections.LEFT]: Math.min(area.left, parentArea.left),
[SideDirections.RIGHT]: Math.max(area.right, parentArea.right),
[SideDirections.TOP]: Math.min(area.top, parentArea.top),
[SideDirections.BOTTOM]: Math.max(area.bottom, parentArea.bottom)
}
}

86
src/modifiers/twoDimPoint.js → src/helper/twoDimPoint.js

@ -1,4 +1,3 @@
/**
* Class containing two numbers.
* Usually they represent coordinates,
@ -347,88 +346,3 @@ class TwoDimPoint {
}
}
/**
*
* @param {number} start
* @param {number} end
* @param {number} value
* @param {number} tolerance
* @param {boolean} usePercentage
* @returns {boolean}
*/
function isValueInBounds(start, end, value, tolerance = 0, usePercentage = false) {
if (tolerance !== 0) {
if (usePercentage) {
start = start * (1 - tolerance / 100);
end = end * (1 + tolerance / 100);
} else {
start = start - tolerance;
end = end + tolerance;
}
}
return value >= start && value <= end;
}
/**
* @param {number} x
* @param {number} y
* @param {Map<SideDirections,number>} area
* @param {number} tolerance
* @param {boolean} usePercentage if tolerance is given and this is set to true,
* the tolerance will be calculated by percentage,
* otherwise it will be subtracted/added
* @returns {boolean}
*/
function areXYInArea(x, y, area, tolerance = 0, usePercentage = false) {
return isValueInBounds(
area.get(SideDirections.LEFT),
area.get(SideDirections.RIGHT),
x,
tolerance,
usePercentage
) && isValueInBounds(
area.get(SideDirections.TOP),
area.get(SideDirections.BOTTOM),
y,
tolerance,
usePercentage
);
}
/**
*
* @param {TwoDimPoint} point
* @param {Map<SideDirections,number>} area
* @param {number} tolerance
* @param {boolean} usePercentage if tolerance is given and this is set to true,
* the tolerance will be calculated by percentage,
* otherwise it will be subtracted/added
*/
function isPointInArea(point, area, tolerance = 0, usePercentage = false) {
return areXYInArea(
point.x,
point.y,
area,
tolerance,
usePercentage
);
}
/**
*
* @param {HTMLElement} element
* @returns {Object<SideDirections, number}
*/
function getEnclosingBounds(element) {
let area = element.getBoundingClientRect();
let parentArea = element.parentElement.getBoundingClientRect();
return {
[SideDirections.LEFT]: Math.min(area.left, parentArea.left),
[SideDirections.RIGHT]: Math.max(area.right, parentArea.right),
[SideDirections.TOP]: Math.min(area.top, parentArea.top),
[SideDirections.BOTTOM]: Math.max(area.bottom, parentArea.bottom)
}
}

187
src/modifier/ChainableModifier.js

@ -0,0 +1,187 @@
/**
* @extends Modifier
* @inheritdoc
*/
class ChainableModifier extends Modifier {
/**
* @type {Component}
*/
_component;
/**
*
* @param {Component} component
*/
constructor(component) {
super();
this._component = component;
}
/**
* @inheritdoc
* @override
* @returns {ChainableModifier}
*/
fillMaxSize(widthFraction = 1, heightFraction = 1) {
return super.fillMaxSize(widthFraction, heightFraction);
}
/**
* @inheritdoc
* @override
* @returns {ChainableModifier}
*/
fillMaxWidth(fraction = 1) {
return super.fillMaxWidth(fraction);
}
/**
* @inheritdoc
* @override
* @returns {ChainableModifier}
*/
fillMaxHeight(fraction = 1) {
return super.fillMaxHeight(fraction);
}
/**
* @inheritdoc
* @override
* @returns {ChainableModifier}
*/
background(color) {
return super.background(color);
}
/**
* @inheritdoc
* @override
* @returns {ChainableModifier}
*/
color(color) {
return super.color(color);
}
/**
* @inheritdoc
* @override
* @returns {ChainableModifier}
*/
setStyleRule(key, value) {
return super.setStyleRule(key, value);
}
/**
* @inheritdoc
* @override
* @returns {ChainableModifier}
*/
addStyleRuleMap(rulemap) {
return super.addStyleRuleMap(rulemap);
}
/**
* @inheritdoc
* @override
* @returns {ChainableModifier}
*/
removeStyleRule(key) {
return super.removeStyleRule(key);
}
/**
* @inheritdoc
*
* In Case it is called from a ChainableModifier chain,
* the Return type would be DimensionsChainedModifier instead of DimensionsChain.
* @override
* @param {Dimensions | number | undefined} [modify=null] dimensions
* @returns {ChainableModifier | DimensionsChainedModifier}
*/
dimensions(modify = null) {
if (modify instanceof Dimensions || Number.isInteger(modify)) {
return super.dimensions(modify);
}
return new DimensionsChainedModifier(this);
}
/**
* @inheritdoc
* @override
* @param {Padding | number | undefined} [modify=null] modify as in modifiers
* @returns {ChainableModifier | PaddingChainedModifier}
*/
padding(modify = null) {
if (modify instanceof Padding || Number.isInteger(modify)) {
return super.padding(modify);
}
return new PaddingChainedModifier(this);
}
/**
* @inheritdoc
* @override
* @param {Margin | number | undefined} [modify=null] modify as in modifiers
* @returns {ChainableModifier | MarginChainedModifier}
*/
margin(modify = null) {
if (modify instanceof Margin || Number.isInteger(modify)) {
return super.margin(modify);
}
return new MarginChainedModifier(this);
}
/**
* @inheritdoc
*
* @override
* @param {Shape | number | undefined} [modify=null] modify
* @returns {ChainableModifier | ShapeChainedModifier}
*/
clip(modify = null) {
if (modify instanceof Shape || Number.isInteger(modify)) {
return super.clip(modify);
}
return new ShapeChainedModifier(this);
}
/**
*
* @inheritdoc
*
* @override
* @param {Border | number | undefined} [modify=null] modify
* @returns {ChainableModifier | BorderChainedModifier}
*/
border(modify = null) {
if (modify instanceof Border || Number.isInteger(modify)) {
return super.border(modify);
}
return new BorderChainedModifier(this);
}
/**
*
* @returns {Component}
*/
toComponent() {
return this._component.modifier(this);
}
/**
*
* @param {Component|Array<Component>} innerComponent
* @returns {Component} the parent Component
*/
childContext(innerComponent) {
return this._component
.modifier(this)
.childContext(innerComponent);
}
/**
* Calls chainChild() from Component (ChildbearerComponent)
* @see {ChildbearerComponent.chainChild}
* @returns {builder}
*/
chainChild() {
return this._component
.modifier(this)
.chainChild();
}
}

87
src/modifier/ModificationSubChain.js

@ -0,0 +1,87 @@
/**
* @abstract
*/
class ModificationSubChain {
/**
* @type {Modifier}
*/
_modifier;
/**
* @type {string}
*/
_modMethod;
/**
*
* @param {Modifier} modifier
* @param {string} modMethod
*/
constructor(modifier, modMethod) {
this._modifier = modifier;
this._modMethod = modMethod;
}
/**
* Returns the Modifier SubChain to the Modifier
* @returns {Modifier|ChainableModifier}
*/
toModifier() {
return this._modifier[this._modMethod](this);
}
/**
* Returns chain to the Modifier
* @returns {Modifier|ChainableModifier}
*/
ensureModifier() {
return this.toModifier();
}
}
/**
* @inheritdoc
* @extends ModificationSubChain
* @abstract
*/
class ModificationSubChainReComp extends ModificationSubChain {
/**
*
* @param {ChainableModifier} modifier
* @param {string} modMethod
*/
constructor(modifier) {
super();
this._modifier = modifier;
}
/**
* Returns chain to the component that is under modification
* @returns {Component} the Component that was (supposed to be) modified by this obj.
*/
toComponent() {
return this._modifier[this._modMethod](this)
.toComponent();
}
/**
* Returns chain to the component that is under modification
* and adds the given innerComponent as children to the component.
* @param {Component|Array<Component>} innerComponent
* @returns {Component}
*/
childContext(innerComponent) {
return this._modifier[this._modMethod](this)
.toComponent()
.childContext(innerComponent);
}
/**
* Closes modifier chain and returns builder to define the next child of the component
* @returns {Component}
*/
chainChild() {
return this._modifier[this._modMethod](this)
.toComponent()
.chainChild();
}
}

150
src/modifier.js → src/modifier/Modifier.js

@ -1,9 +1,3 @@
/**
* This file is part of the jps-like-websites lib
* URL: https://git.labos.goip.de/chris/jpc-like-websites
* @copyright by its creator Christian Martin
*/
/**
* A chained class that sets most of the stylings of an element
* Attributes:
@ -133,7 +127,7 @@ class Modifier {
return this;
} else {
let modSub = new DimensionsChain(this);
if (modify instanceof Number && modify > 0) {
if (Number.isInteger(modify) && modify > 0) {
return modSub.all(modify).ensureModifier();
}
// case dimension is number but < 0 or dimensions == null or anything else
@ -146,7 +140,7 @@ class Modifier {
* Currently the padding will always be set
* to the most recent padding/padding.
* @param {Padding | number | undefined} modify as in modifiers
* @returns {Modifier} this modifier object
* @returns {Modifier | PaddingChain} this modifier object
*/
padding(modify = null) {
if (modify instanceof Sides && !(modify instanceof Padding)) {
@ -177,7 +171,7 @@ class Modifier {
* it is recommended to use padding and to stick to that as often as possible.
* Padding values take affect inside/within the element.
* @param {Margin | number | undefined} modify
* @returns {Modifier} this modifier object
* @returns {Modifier | MarginChain} this modifier object
*/
margin(modify = null) {
if (modify instanceof Sides && !(modify instanceof Margin)) {
@ -278,6 +272,17 @@ class Modifier {
return this;
}
/**
* Sets the style rules to deactivate text-selection in the component.
* @returns {Modifier}
*/
noneSelect() {
return this
.setStyleRule("user-select", "none")
.setStyleRule("-ms-user-select", "none")
.setStyleRule("-webkit-user-select", "none")
}
/**
*
* @param {StylePropertyMap} rulemap
@ -341,7 +346,7 @@ class Modifier {
return this;
} else {
let modSub = new BorderChain(this);
if (modify instanceof Number && modify > 0) {
if (Number.isInteger(modify) && modify > 0) {
return modSub.width(modify).ensureModifier();
}
return modSub;
@ -373,7 +378,7 @@ class Modifier {
return this;
} else {
let modSub = new ShapeChain(this);
if (modify instanceof Number && modify > 0) {
if (Number.isInteger(modify) && modify > 0) {
return modSub.all(modify).ensureModifier();
}
return modSub;
@ -450,7 +455,7 @@ class Modifier {
/**
*
* @returns {Modifier|ChainableModifier}
* @returns {Modifier}
*/
ensureModifier() {
return this;
@ -458,125 +463,4 @@ class Modifier {
}
/**
* @extends Modifier
* @inheritdoc
*/
class ChainableModifier extends Modifier {
/**
* @type {Component}
*/
_component;
/**
*
* @param {Component} component
*/
constructor(component) {
super();
this._component = component;
}
/**
* @inheritdoc
*
* In Case it is called from a ChainableModifier chain,
* the Return type would be DimensionsChainedModifier instead of DimensionsChain.
* @override
* @param {Dimensions | number | undefined} [modify=null] dimensions
* @returns {ChainableModifier | DimensionsChainedModifier}
*/
dimensions(modify = null) {
if (modify instanceof Dimensions || modify instanceof Number) {
return super.dimensions(modify);
}
return new DimensionsChainedModifier(this);
}
/**
* @inheritdoc
* @override
* @param {Padding | number | undefined} [modify=null] modify as in modifiers
* @returns {ChainableModifier | PaddingChainedModifier}
*/
padding(modify = null) {
if (modify instanceof Padding || Number.isInteger(modify)) {
return super.padding(modify);
}
return new PaddingChainedModifier(this);
}
/**
* @inheritdoc
* @override
* @param {Margin | number | undefined} [modify=null] modify as in modifiers
* @returns {ChainableModifier | MarginChainedModifier}
*/
margin(modify = null) {
if (modify instanceof Margin || Number.isInteger(modify)) {
return super.margin(modify);
}
return new MarginChainedModifier(this);
}
/**
* @inheritdoc
*
* @override
* @param {Shape | number | undefined} [Shape=null] shape
* @returns {ChainableModifier | ShapeChainedModifier}
*/
clip(shape = null) {
if (shape instanceof Shape || shhaape instanceof Number) {
return super.clip(shape);
}
return new ShapeChainedModifier(this);
}
/**
*
* @inheritdoc
*
* @override
* @param {Border | number | undefined} [border=null] border
* @returns {ChainableModifier | BorderChainedModifier}
*/
border(border = null) {
if (border instanceof Border || border instanceof Number) {
return super.border(border);
}
return new BorderChainedModifier(this);
}
/**
*
* @returns {Component}
*/
toComponent() {
return this._component.modifier(this);
}
/**
*
* @param {Component|Array<Component>} innerComponent
* @returns {Component} the parent Component
*/
childContext(innerComponent) {
return this._component
.modifier(this)
.childContext(innerComponent);
}
/**
* Calls chainChild() from Component (ChildbearerComponent)
* @see {ChildbearerComponent.chainChild}
* @returns {builder}
*/
chainChild() {
return this._component
.modifier(this)
.chainChild()
}
}

82
src/modifiers/modificationSubChainMixins.js → src/modifier/mixinModSubChain.js

@ -1,81 +1,3 @@
class ModificationSubChain {
_modifier;
_modMethod;
/**
*
* @param {Modifier} modifier
* @param {string} modMethod
*/
constructor(modifier, modMethod) {
this._modifier = modifier;
this._modMethod = modMethod;
}
/**
* Returns the Modifier SubChain to the Modifier
* @returns {Modifier|ChainableModifier}
*/
toModifier() {
return this._modifier[this._modMethod](this);
}
/**
* Returns chain to the Modifier
* @returns {Modifier|ChainableModifier}
*/
ensureModifier() {
return this.toModifier()
}
}
class ModificationSubChainReComp extends ModificationSubChain {
/**
*
* @param {ChainableModifier} modifier
* @param {string} modMethod
*/
constructor(modifier) {
super();
this._modifier = modifier;
}
/**
* Returns chain to the component that is under modification
* @returns {Component} the Component that was (supposed to be) modified by this obj.
*/
toComponent() {
return this._modifier[this._modMethod](this)
.toComponent();
}
/**
* Returns chain to the component that is under modification
* and adds the given innerComponent as children to the component.
* @param {Component|Array<Component>} innerComponent
* @returns {Component}
*/
childContext(innerComponent) {
return this._modifier[this._modMethod](this)
.toComponent()
.childContext(innerComponent);
}
/**
* Closes modifier chain and returns builder to define the next child of the component
* @returns {Component}
*/
chainChild() {
return this._modifier[this._modMethod](this)
.toComponent()
.chainChild();
}
}
/**
* Function is a mixin to add endings to a Modifier SubChain.
* Explicitly used for "link..." methods called from a Modifier,
@ -86,7 +8,9 @@ class ModificationSubChainReComp extends ModificationSubChain {
*/
function mixinModSubChainEndings(classToExtend) {
return class extends classToExtend {
/**
* @type {Modifier}
*/
_modifier;
/**
Loading…
Cancel
Save