Compare commits

...

12 Commits

Author SHA1 Message Date
chris 825ba24ad6 FEAT: Component subscription and functions after load 9 months ago
chris 012e2e8afa IMPRO,REFA: Minor changes 9 months ago
chris dd4ac1d771 REFA: Fusion of "Chainable..." and "...Chain" constructs 9 months ago
chris b98c3be3be REFA,DOC: several things 9 months ago
chris a2765d9383 FEAT,IMPRO: added linkBorder functionallity 9 months ago
chris 2d3b2c0f46 FEAT,REFA: replaced componentChild(ren) with childContext 9 months ago
chris 1f962b8695 REFA,IMPRO: Changed Comp-Attributes-Behaviour 9 months ago
chris 5bf4f2e856 IMPRO,DEV: DEV intervall control as well as log 9 months ago
chris 0a2d16ecea REFA,IMPRO: Introduced funcitons and swapped high level attributes access 9 months ago
chris d3dbd4ecd3 REFA: component attributes 9 months ago
chris 060918fe51 REFA: fefactored base classes/logic of SideUnitDependendAttributes 9 months ago
chris 62b85b35b5 MAJOR-REFA 10 months ago
  1. 6
      README.md
  2. 25
      join_js_files.sh
  3. 15
      package-lock.json
  4. 2
      package.json
  5. 37
      src/alignment.js
  6. 12
      src/arrangement.js
  7. 99
      src/baseComponents.js
  8. 220
      src/builder.js
  9. 19
      src/color.js
  10. 8
      src/commonEvents.js
  11. 234
      src/component.js
  12. 130
      src/context.js
  13. 89
      src/js/baseComponents.js
  14. 44
      src/js/builder.js
  15. 161
      src/js/component.js
  16. 212
      src/js/componentAttribute.js
  17. 32
      src/js/context.js
  18. 179
      src/js/modifier.js
  19. 246
      src/modifier.js
  20. 210
      src/sizeSide/border.js
  21. 105
      src/sizeSide/dimensions.js
  22. 131
      src/sizeSide/shapes.js
  23. 260
      src/sizeSide/siding.js
  24. 7
      tsconfig.json

6
README.md

@ -32,4 +32,8 @@ Javascript is by far not my strongest field,
typescript even less. typescript even less.
So it is recommended to not expect to much, So it is recommended to not expect to much,
you have been warned. you have been warned.
```sh
sh join_js_files.sh
```

25
join_js_files.sh

@ -1,9 +1,28 @@
TARGET="jpc-like-websites.js" TARGET="jpc-like-websites.js"
SRC="src/js" SRC="src"
ORDERED_LIST="context.js componentAttribute.js color.js modifier.js component.js baseComponents.js builder.js"
SUB_LIST="siding.js shapes.js border.js dimensions.js"
MODIFIERS_LIST="alignment.js arrangement.js modifier.js"
HIGHER_LIST="commonEvents.js context.js component.js baseComponents.js builder.js"
echo "" > $TARGET echo "" > $TARGET
echo "/* ## color.js ## */" >> $TARGET
cat $SRC/color.js >> $TARGET
echo "/* # SUB_LIST # */" >> $TARGET
for i in $SUB_LIST; do
echo "/* ## $i ## */" >> $TARGET
cat $SRC/sizeSide/$i >> $TARGET
done
echo "/* # MODIFIERS_LIST # */" >> $TARGET
for i in $MODIFIERS_LIST; do
echo "/* ## $i ## */" >> $TARGET
cat $SRC/$i >> $TARGET
done
for i in $ORDERED_LIST; do echo "/* # HIGHER_LIST # */" >> $TARGET
for i in $HIGHER_LIST; do
echo "/* ## $i ## */" >> $TARGET
cat $SRC/$i >> $TARGET cat $SRC/$i >> $TARGET
done done

15
package-lock.json

@ -5,16 +5,17 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "websites-like-jpc",
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"typescript": "^5.5.4" "typescript": "^5.6.2"
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.5.4", "version": "5.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
@ -27,9 +28,9 @@
}, },
"dependencies": { "dependencies": {
"typescript": { "typescript": {
"version": "5.5.4", "version": "5.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
"dev": true "dev": true
} }
} }

2
package.json

@ -15,6 +15,6 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"typescript": "^5.5.4" "typescript": "^5.6.2"
} }
} }

37
src/alignment.js

@ -0,0 +1,37 @@
/**
* Enum providing common alignment rules
*/
const Alignment = Object.freeze({
/* Normal alignment */
NORMAL: "normal",
/* Basic positional alignment */
/* align-content does not take left and right values */
START: "start",
CENTER: "center",
END: "end",
FLEX_START: "flex-start",
FLEX_END: "flex-end",
/* Baseline alignment */
BASELINE: "baseline",
FIRST_BASELINE: "first baseline",
LAST_BASELINE: "last baseline",
/* Distributed alignment */
SPACE_BETWEEN: "space-between",
SPACE_AROUND: "space-around",
SPACE_EVENLY: "space-evenly",
STRETCH: "stretch",
/* Overflow alignment */
SAFE_CENTER: "safe center",
UNSAFE_CENTER: "unsafe center",
/* Global values */
INHERIT: "inherit",
INITIAL: "initial",
REVERT: "revert",
REVERT_LAYER: "revert-layer",
UNSET: "unset"
})

12
src/arrangement.js

@ -0,0 +1,12 @@
/**
* Enum providing common alignment rules
*/
const Arrangement = Object.freeze({
START: "start",
END: "end",
CENTER: "center",
SPACE_BETWEEN: "space-between",
SPACE_EVENLY: "space-evenly",
SPACE_AROUND: "space-around",
})

99
src/baseComponents.js

@ -0,0 +1,99 @@
/**
* Represents container Components.
* Some predefined modifications are applied on the child components.
*/
class FlexContainerComponent extends Component {
constructor(attr = {}) {
super(document.createElement("div"), attr)
.addStyleClass("flex-container-component")
}
/**
*
* @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);
}
}
/**
* A FlexContainerComponent, which organizes the children in a column like manner.
*/
class Column extends FlexContainerComponent {
constructor(attr = {}) {
super(attr)
.addStyleClass("column-component")
.modifier(
new Modifier()
.setStyleRule("flex-direction", "column")
);
}
}
/**
* A FlexContainerComponent, which organizes the children in a row like manner.
*/
class Row extends FlexContainerComponent {
constructor(attr = {}) {
super(attr)
.addStyleClass("row-component")
.modifier(
new Modifier()
.fillMaxWidth()
.setStyleRule("flex-direction", "row")
)
}
/**
*
* @param {*} innerComponent
* @returns {Row}
*/
childContext(innerComponent) {
if (innerComponent instanceof Array) {
innerComponent
.map(cl => (cl instanceof Component ? cl : cl.ensureModifier().toComponent()))
.forEach((icomp, i) => {
/* 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 = new Modifier()
.setStyleRule("float", (i === 0 ? "left" : "right"))
.join(icomp._modifier)
})
}
return super.childContext(innerComponent)
}
/**
*
* @returns {Row}
*/
distibuteSpacingEvenly() {
this._element.children.forEach(child => {
child.style["width"] = (100 / innerComponent.length);
})
return this;
}
}

220
src/builder.js

@ -0,0 +1,220 @@
/**
* Method Collection with predefined HTMLElements
*/
const builder = {
components: {
parent: {},
current: {},
previous: {},
next: {},
openedChain: {}
},
/**
*
* @param {string} tag
* @param {Map<string,string>} attr
* @returns {Component}
*/
genTag: function (tag, attr = {}) { return new Component(document.createElement(tag), attr).addStyleClass(`el-${tag}`); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
anchor: function (attr = {}) { return builder.genTag("a", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
label: function (attr = {}) { return builder.genTag("label", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
button: function (attr = {}) { return builder.genTag("button", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
input: function (attr = {}) { return builder.genTag("input", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
div: function (attr = {}) { return builder.genTag("div", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
span: function (attr = {}) { return builder.genTag("span", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
paragraph: function (attr = {}) { return builder.genTag("paragraph", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
header: function (sizeGroup, attr = {}) { return builder.genTag(`h${sizeGroup}`, attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
checkbox: function (attr = {}) { return builder.input({ "type": "checkbox" }) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
select: function (attr = {}) { return builder.genTag("select", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
option: function (attr = {}) { return builder.genTag("option", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
select: function (attr = {}) { return builder.genTag("select", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
radioBtn: function (attr = {}) { return builder.genTag("radioBtn", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
icon: function (attr = {}) { return builder.genTag("icon", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
img: function (attr = {}) { return builder.genTag("img", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
textarea: function (attr = {}) { return builder.genTag("textarea", attr); },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
table: function (attr = {}) { return builder.genTag("table", attr) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
tableRow: function (attr = {}) { return builder.genTag("tr", attr) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
tableCell: function (attr = {}) { return builder.genTag("td", attr) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
tableCaption: function (attr = {}) { return builder.genTag("caption", attr) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
tableHeadCell: function (attr = {}) { return builder.genTag("th", attr) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
tableBody: function (attr = {}) { return builder.genTag("tbody", attr) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
tableHead: function (attr = {}) { return builder.genTag("thead", attr) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
tableFooter: function (attr = {}) { return builder.genTag("tfoot", attr) },
/**
*
* @param {Map<string,string>} attr
* @returns {Component}
*/
form: function (attr = {}) {
return builder.genTag("form", attr)
.addStyleClass("flex-container-component")
.chainModifier()
.setStyleRule("flex-direction", "column")
.ensureModifier()
.toComponent()
},
/**
*
* @param {*} attr
* @returns {Row}
*/
row: function (attr = {}) { return new Row(attr) },
/**
*
* @param {*} attr
* @returns {Column}
*/
column: function (attr = {}) { return new Column(attr) },
/**
*
* @param {*} innerComponents
*/
page: function (innerComponents) {
let main = document.querySelector('main')
main.parentElement.insertAdjacentElement(
"afterbegin",
builder.genTag("main")
.alignment(Alignment.CENTER)
.arrangement(Arrangement.CENTER)
.childContext(innerComponents)
.generate()
)
Page.generate();
main.remove();
}
}

19
src/js/color.js → src/color.js

@ -583,3 +583,22 @@ const Colors = Object.freeze({
gray_2: new Color(5, 5, 5).hex('#050505'), gray_2: new Color(5, 5, 5).hex('#050505'),
gray_1: new Color(3, 3, 3).hex('#030303') gray_1: new Color(3, 3, 3).hex('#030303')
}); });
const MaterialFiveHundredlColors = Object.freeze({
SOFT_ORANGE: new Color(244, 67, 54),
SOFT_RED: new Color(233, 30, 99),
MAGENTA: new Color(156, 39, 176),
VIOLET: new Color(103, 58, 183),
DARGK_BLUE: new Color(63, 81, 181),
BLUE: new Color(33, 150, 243),
LIGHT_BLUE: new Color(3, 169, 244),
BLUE_GREEN: new Color(0, 188, 212),
SEA_GREEN: new Color(0, 150, 136),
GREEN: new Color(76, 175, 80),
LIGHT_GREEN: new Color(139, 195, 74),
YELLOW: new Color(205, 220, 57),
GOLD: new Color(255, 235, 59),
YELLO_ORANGE: new Color(255, 152, 0),
ORANGE: new Color(255, 87, 34),
})

8
src/commonEvents.js

@ -0,0 +1,8 @@
/**
* Enum to access common events
*/
const CommonEvents = Object.freeze({
ONCLICK: "onclick",
ONCHANGE: "onchange"
})

234
src/component.js

@ -0,0 +1,234 @@
/**
* A chainable HTMLElement builder.
*/
class Component {
_element;
_modifier
_alignment;
_arrangement;
_toRegister;
constructor(element, attr = {}) {
this._modifier = new Modifier().margin(new Sides().all(0));
var akeys = Object.keys(attr);
for (let i = 0; i < akeys.length; i++) {
element.setAttribute(akeys[i], attr[akeys[i]]);
}
this._element = element;
this._toRegister = [];
}
/**
* Sets the alignment (modifications) for this element or more specific for its children.
* @param {Alignment} alignment
* @returns {Component} this component object
*/
alignment(alignment) {
this._alignment = alignment;
this._modifier._modifications["display"] = "flex";
this._modifier._modifications["align-content"] = alignment;
this._modifier._modifications["align-items"] = alignment;
this._modifier._modifications["text-align"] = alignment;
//this._modifier._modifications["justify-content"] = alignment;
return this;
}
/**
* Sets the arrangement (modifications) for this element or more specific for its children.
* @param {Arrangement} arrangement
* @returns {Component} this component object
*/
arrangement(arrangement) {
this._arrangement = arrangement;
switch (arrangement) {
case Arrangement.START:
this._modifier._modifications["justify-content"] = "start";
break;
case Arrangement.END:
this._modifier._modifications["justify-content"] = "end";
break;
case Arrangement.CENTER:
this._modifier._modifications["justify-content"] = "center";
break;
case Arrangement.SPACE_AROUND:
this._modifier._modifications["justify-content"] = "space-around";
break;
case Arrangement.SPACE_BETWEEN:
this._modifier._modifications["justify-content"] = "space-between";
break;
case Arrangement.SPACE_EVENLY:
this._modifier._modifications["justify-content"] = "space-evenly";
break;
}
return this;
}
/**
*
* @param {Modifier} modifier
* @returns {Component} this component object
*/
modifier(modifier) {
this._modifier = this._modifier.join(modifier.ensureModifier())
return this;
}
/**
* Sets the innerText of the element
* @param {string} text
* @returns {Component} this component object
*/
text(text) {
this._element.innerText = text;
return this;
}
title(text) {
this._element.title = text;
return this;
}
/**
*
* @param {string} styleClass
* @returns {Component} this component object
*/
addStyleClass(styleClass) {
this._element.classList.add(styleClass);
return this;
}
registerStyleClass(styleClass, styleRuleMap){
Page.registerStyling('.'+styleClass, styleRuleMap);
return this.addStyleClass(styleClass);
}
/**
*
* @param {string} key
* @param {string} value
* @returns {Component} this component object
*/
setAttribute(key, value) {
this._element.setAttribute(key, value);
return this;
}
/**
* Ends chain.
* Applies all modifications on the element.
* @returns {HTMLElemment} the html element
*/
generate() {
/* apply styling to element */
var mkeys = Object.keys(this._modifier._modifications);
for (let i = 0; i < mkeys.length; i++) {
this._element.style[mkeys[i]] = this._modifier._modifications[mkeys[i]];
}
/* subscribe/register to lists */
for (let i = 0; i < this._toRegister.length; i++) {
this._toRegister[i].push(this._element);
}
return this._element;
}
/**
* Opens a context to create element children.
* Either as one component or a list/array of components.
* @param {Component|Array<Component>} component
* @returns {Component} this component object
*/
childContext(component) {
if (arguments.length > 1) {
for (let i = 0; i < arguments.length; i++) {
this.childContext(arguments[i]);
}
} else if (component instanceof Array) {
for (let i = 0; i < component.length; i++) {
this.childContext(component[i]);
}
} else {
this._element.append(
(component instanceof Component
? component
: component.toComponent()
)
.generate()
);
}
return this;
}
/**
* @deprecated
* @param {Array<Component>} innerComponent
* @returns {Component} this component object
*/
componentChildren(innerComponent) {
for (let i = 0; i < innerComponent.length; i++) {
this.childContext(innerComponent[i]);
}
return this;
}
/**
*
* @param {CommonEvent} commonEvent
* @param {string} functionName
* @returns {Component} this component object
*/
setEvent(commonEvent, functionName) {
return this.setAttribute(commonEvent, `${functionName}(this)`);
}
/**
*
* @returns {ChainableModifier}
*/
chainModifier() {
return new ChainableModifier(this);
}
/**
* Collects the given List in the _toRegister attribute.
* When generate() is called,
* the created Element will be registered (added) in every list
* within the list.
* @param {Array} listName
*/
registerOnGenerate(listName){
this._toRegister.push(listName);
return this;
}
/*
clickable(eventName) {
let cssClass = "button-like"
this.addStyleClass(cssClass)
this._modifier._modifications["box-shadow"] = "4px 6px #999";
let bckk = "background-color";
if (this._modifier._modifications.hasOwnProperty(bckk)) {
let bckc = this._modifier._modifications[bckk];
delete this._modifier._modifications[bckk];
Page.registerStyling(`.${cssClass}`, {
[bckk]: bckc
})
}
Page.registerStyling(`.${cssClass}:hover`, {
"background-color": Colors.greenyellow.cssRGBString(),
})
Page.registerStyling(`.${cssClass}:active`, {
"background-color": Colors.greenyellow.cssRGBString(),
"box-shadow": "1px 2px #666",
"transform": "translateY(4px)"
})
return this.setEvent(CommonEvents.ONCLICK, eventName);
}
*/
}

130
src/context.js

@ -0,0 +1,130 @@
/**
* The class provides overreaching options for building the website.
*/
class PageBuilder {
#cssClasses;
#functions;
#delayedFunctions;
#repeatingFunctions;
#functionNames;
#cssElementIdentifiers;
constructor() {
this.#cssClasses = document.createElement("style");
this.#functions = document.createElement("script");
this.#functionNames = [];
this.#cssElementIdentifiers = [];
this.#delayedFunctions = [];
this.#repeatingFunctions = {};
}
/**
* Registers a function to be added later in a script tag in the head of the document.
* @param {string} name
* @param {func} fun
*/
registerFunction(name, fun) {
if (!this.#functionNames.includes(name)) {
this.#functions.innerText += `const ${name} = ${fun};`;
this.#functionNames.push(name);
}
}
/**
* @experimental Attention is adviced, registration mechanism doesn't work yet
* @param {string} name The name the interval will be tied to
* @param {Function} fun the function that is supposed to be executed repeatedly
* @param {number} interval the time in ms between executions
*/
registerRepeatingFunction(name, fun, interval) {
if (!Object.keys(this.#repeatingFunctions).includes(name)) {
this.#repeatingFunctions[name] = {
name: name,
fun: fun,
interval: interval
};
}
}
/**
* Adds the styling rules to the element identifiers into the style tag.
* An elementDefinition can only be used once, repeated use will be ignored.
* @param {string} elementDefinition The element identifier
* @param {Map<string, string>} styleRuleMap The Styling rules/values
*/
registerStyling(elementDefinition, styleRuleMap) {
if (!this.#cssElementIdentifiers.includes(elementDefinition)) {
this.#cssClasses.innerText += `${elementDefinition
} {${Object.keys(styleRuleMap)
.map(e => e + ": " + styleRuleMap[e] + "; ")
.join(" ")
}} `
this.#cssElementIdentifiers.push(elementDefinition)
}
}
/**
* Adds into the (head) document.
* - script tag
* - function tag
* - sets and registers repeatedly executed functions
* - sets (timeout and) functions that are supposed to be executed after load
*/
generate() {
let head = document.querySelector("head");
head.appendChild(this.#functions)
head.appendChild(this.#cssClasses)
/* set repeating functions */
let repeatedFun = Object.values(this.#repeatingFunctions)
.reduce((a, c, i, arr) => Object.assign(a, {
[c.name]: setInterval(c.fun, c.interval)
}), {});
/* set timeouts for funcitons executed after load */
for (let i = 0; i < this.#delayedFunctions.length; i++) {
let func = this.#delayedFunctions[i];
if (func.repeat) {
setTimeout(setInterval(func.func, func.interval), func.dl, func.args);
} else {
setTimeout(func.func, func.dl, func.args);
}
}
console.log(this.#functionNames);
}
/**
* Registeres a function to be executed after page-load
* @param {Function} func the function that will be executed
* @param {number} delay the time in ms the execution is delayed after load
* @param {string} name if provided the function will be registered as well
* @param {Array<any>} args arguments for the function
* @param {boolean} repeat defines if the function is supposed to be repeated as well
* @param {number} interval if the function is supposed to repeat, this defines the interval of repetition
*/
executeAfterLoad(func, delay = 1000, name = '', args = [], repeat = false, interval = 5000) {
if (name !== '') {
this.registerFunction(name, func);
}
this.#delayedFunctions.push({ dl: delay, func: func, args: args, repeat: repeat, interval: interval });
}
/**
*
* @param {number} relaunchSeconds timeinterval for page to reload (changes)
*/
inDev(relaunchSeconds = 20) {
let head = document.querySelector("head");
let meta = document.createElement("meta");
meta.setAttribute("http-equiv", "refresh");
meta.setAttribute("content", `${relaunchSeconds}`);
head.insertAdjacentElement("beforeend", meta);
this.#functions.innerText = `
let ts = new Date();
console.log("Refreshed at: ", ts.getHours()+':'+ts.getMinutes()+':'+ts.getSeconds(), "Intervall ${relaunchSeconds}s");
`;
}
}
const Page = new PageBuilder();

89
src/js/baseComponents.js

@ -1,89 +0,0 @@
/**
* Represents container Components.
* Some predefined modifications are applied on the child components.
*/
class FlexContainerComponent extends Component {
constructor(attr = {}) {
super(document.createElement("div"), attr)
.addStyleClass("flex-container-component")
}
/**
*
* @param {Component|Array<Component>} innerComponent
* @returns this component object
*/
childComponents(innerComponent) {
if (innerComponent instanceof Array) {
innerComponent.forEach(icomp => {
(icomp instanceof Component
? icomp
: icomp.backToComponent()
)
.chainModifier()
.setStyleRule("flex", "none")
})
} else if (!innerComponent instanceof Component) {
innerComponent
.backToComponent()
.chainModifier()
.setStyleRule("flex", "none")
}
return super.childComponents(innerComponent);
}
}
/**
* A FlexContainerComponent, which organizes the children in a column like manner.
*/
class Column extends FlexContainerComponent {
constructor(attr = {}) {
super(document.createElement("div"), attr)
.addStyleClass("column-component")
.modifier(
new Modifier()
.fillMaxHeight()
.setStyleRule("flex-direction", "column")
);
}
}
/**
* A FlexContainerComponent, which organizes the children in a row like manner.
*/
class Row extends FlexContainerComponent {
constructor(attr = {}) {
super(attr)
.addStyleClass("row-component")
.modifier(
new Modifier()
.fillMaxWidth()
.setStyleRule("flex-direction", "row")
)
}
childComponents(innerComponent) {
if (innerComponent instanceof Array) {
innerComponent.forEach((icomp, i) => {
(icomp instanceof Component
? icomp
: icomp.backToComponent()
).modifier(
/* sets the width for all elements,
to avoid overlapping or line break because of lacking width,
a percent is subtracted for every child element */
new Modifier()
.setStyleRule("float", (i === 0 ? "left" : "right"))
.fillMaxWidth((Math.floor((10000 - 100 * innerComponent.length) / innerComponent.length) / 10000))
)
})
} else {
innerComponent.modifier(
new Modifier()
.setStyleRule("flex", "none")
)
}
return super.childComponents(innerComponent)
}
}

44
src/js/builder.js

@ -1,44 +0,0 @@
const builder = {
components: {
parent: {},
current: {},
previous: {},
next: {},
openedChain: {}
},
genTag: function (tag, attr = {}) { return new Component(document.createElement(tag), attr); },
anchor: function (attr = {}) { return builder.genTag("a", attr); },
label: function (attr = {}) { return builder.genTag("label", attr); },
button: function (attr = {}) { return builder.genTag("button", attr); },
input: function (attr = {}) { return builder.genTag("input", attr); },
div: function (attr = {}) { return builder.genTag("div", attr); },
paragraph: function (attr = {}) { return builder.genTag("paragraph", attr); },
header: function (sizeGroup, attr = {}) { return builder.genTag(`h${sizeGroup}`, attr); },
checkbox: function (attr = {}) { return builder.genTag("checkbox", attr); },
selection: function (attr = {}) { return builder.genTag("selection", attr); },
option: function (attr = {}) { return builder.genTag("option", attr); },
section: function (attr = {}) { return builder.genTag("section", attr); },
radioBtn: function (attr = {}) { return builder.genTag("radioBtn", attr); },
icon: function (attr = {}) { return builder.genTag("icon", attr); },
img: function (attr = {}) { return builder.genTag("img", attr); },
textarea: function (attr = {}) { return builder.genTag("textarea", attr); },
table: function (attr = {}) { return builder.genTag("table", attr) },
tableRow: function (attr = {}) { return builder.genTag("tr", attr) },
tableCell: function (attr = {}) { return builder.genTag("td", attr) },
tableCaption: function (attr = {}) { return builder.genTag("caption", attr) },
tableHeadCell: function (attr = {}) { return builder.genTag("th", attr) },
tableBody: function (attr = {}) { return builder.genTag("tbody", attr) },
tableHead: function (attr = {}) { return builder.genTag("thead", attr) },
tableFooter: function (attr = {}) { return builder.genTag("tfoot", attr) },
row: function (attr = {}) { return new Row(attr) },
column: function (attr = {}) { return new Column(attr) },
page: function (innerComponents) {
Page.generate();
document.querySelector('main').appendChild(innerComponents.generate())
}
}

161
src/js/component.js

@ -1,161 +0,0 @@
/**
* A chainable HTMLElement builder.
*/
class Component {
_element;
_modifier
_alignment;
_arrangement;
constructor(element, attr = {}) {
this._modifier = new Modifier().margin(new Siding().all(0));
var akeys = Object.keys(attr);
for (let i = 0; i < akeys.length; i++) {
element.setAttribute(akeys[i], attr[akeys[i]]);
}
this._element = element;
}
/**
* Sets the alignment (modifications) for this element or more specific for its children.
* @param {Alignment} alignment
* @returns this component object
*/
alignment(alignment) {
this._alignment = alignment;
return this;
}
/**
* Sets the arrangement (modifications) for this element or more specific for its children.
* @param {Arrangement} arrangement
* @returns this component object
*/
arrangement(arrangement) {
this._arrangement = arrangement;
switch (arrangement) {
case Arrangement.START:
this._modifier.modifications["justify-content", "start"]
break;
case Arrangement.END:
this._modifier.modifications["justify-content", "end"]
break;
case Arrangement.CENTER:
this._modifier.modifications["justify-content", "center"]
break;
case Arrangement.SPACE_AROUND:
this._modifier.modifications["justify-content", "space-around"]
break;
case Arrangement.SPACE_BETWEEN:
this._modifier.modifications["justify-content", "space-between"]
break;
case Arrangement.SPACE_EVENLY:
this._modifier.modifications["justify-content", "space-evenly"]
break;
}
return this;
}
/**
*
* @param {Modifier} modifier
* @returns this component object
*/
modifier(modifier) {
this._modifier = this._modifier.join(modifier)
return this;
}
/**
* Sets the innerText of the element
* @param {string} text
* @returns this component object
*/
text(text) {
this._element.innerText = text;
return this;
}
/**
*
* @param {string} styleClass
* @returns this component object
*/
addStyleClass(styleClass) {
this._element.classList.add(styleClass);
return this;
}
/**
*
* @param {string} key
* @param {string} value
* @returns this component object
*/
setAttribute(key, value) {
this._element.setAttribute(key, value);
return this;
}
/**
* Ends chain.
* Applies all modifications on the element.
* @returns {HTMLElemment} the html element
*/
generate() {
var mkeys = Object.keys(this._modifier.modifications);
for (let i = 0; i < mkeys.length; i++) {
this._element.style[mkeys[i]] = this._modifier.modifications[mkeys[i]];
}
return this._element;
}
/**
*
* @param {Component} component
* @returns this component object
*/
child(component) {
this._element.append(
(component instanceof Component
?component
:component.backToComponent()
)
.generate()
);
return this;
}
/**
*
* @param {Array<Component>} innerComponent
* @returns this component object
*/
childComponents(innerComponent) {
for (let i = 0; i < innerComponent.length; i++) {
this.child(innerComponent[i]);
}
return this;
}
/**
*
* @param {CommonEvent} commonEvent
* @param {string} functionName
* @returns this component object
*/
setEvent(commonEvent, functionName) {
return this.setAttribute(commonEvent, `${functionName}(this)`);
}
/**
*
* @returns {ChainableModifier}
*/
chainModifier() {
return new ChainableModifier(this);
}
}

212
src/js/componentAttribute.js

@ -1,212 +0,0 @@
/**
* Enum to access common events
*/
const CommonEvents = Object.freeze({
ONCLICK: "onClick",
})
/**
* Simple Dimensions container for the height and width in pixels.
*/
class Dimensions {
#x;
#y;
/**
* Sets width (x) value of pixels
* @param {number} pixels
* @returns this Dimensions Modifier
*/
width(pixels) {
this.#x = pixels;
return this;
}
/**
* Sets height (y) value of pixels
* @param {number} pixels
* @returns this Dimensions Modifier
*/
height(pixels) {
this.#y = pixels;
return this;
}
}
/**
* The Class holds values from each side/direction of an element.
* Used for margin/padding.
*/
class Siding {
pxLeft = 0;
pxRight = 0;
pxTop = 0;
pxBottom = 0;
/**
* sets the pixels-value for all sides.
* @param {number} pixels siding from all sides
* @returns this Siding Object
*/
all(pixels) {
this.pxLeft = pixels;
this.pxRight = pixels;
this.pxTop = pixels;
this.pxBottom = pixels;
return this;
}
/**
* sets the pixels-value for the horizontal sides (left and right).
* @param {number} pixels siding for left and right.
* @returns this Siding Object
*/
horizontal(pixels) {
this.pxLeft = pixels;
this.pxRight = pixels;
return this;
}
/**
* sets the pixels-value for the vertical sides (left and right).
* @param {number} pixels siding for top and bottom.
* @returns this Siding Object
*/
vertical(pixels) {
this.pxTop = pixels;
this.pxBottom = pixels;
return this;
}
/**
* sets the pixels-value for the left side.
* @param {number} pixels siding for left
* @returns this Siding Object
*/
left(pixels) {
this.pxLeft = pixels;
return this;
}
/**
* sets the pixels-value for the right side.
* @param {number} pixels siding for right
* @returns this Siding Object
*/
right(pixels) {
this.pxRight = pixels;
return this;
}
/**
* sets the pixels-value for the top side.
* @param {number} pixels siding for top
* @returns this Siding Object
*/
top(pixels) {
this.pxTop = pixels;
return this;
}
/**
* sets the pixels-value for the bottom side.
* @param {number} pixels siding for bottom
* @returns this Siding Object
*/
bottom(pixels) {
this.pxBottom = pixels;
return this;
}
}
/**
* Enum providing common alignment rules
*/
const Alignment = Object.freeze({
BEGIN_BORDER: 0,
CENTER: 1,
END_BORDER: 2,
})
/**
* Enum providing common alignment rules
*/
const Arrangement = Object.freeze({
START: 0,
END: 1,
CENTER: 2,
SPACE_BETWEEN: 3,
SPACE_EVENLY: 4,
SPACE_AROUND: 5,
})
class ChainableDimensions extends Dimensions {
#modifier;
constructor(modifier) {
super();
this.#modifier = modifier;
}
backToModifier() {
return this.#modifier;
}
backToComponent() {
return this.#modifier.backToComponent();
}
componentChild(innerComponent) {
return this.#modifier.backToComponent()
.child(innerComponent);
}
componentChildComponents(innerComponent) {
return this.#modifier.backToComponent()
.childComponents(innerComponent);
}
}
class ChainableSiding extends Siding {
#modifier;
constructor(modifier) {
super();
this.#modifier = modifier;
}
backToModifier() {
return this.#modifier;
}
backToComponent() {
return this.#modifier.backToComponent();
}
componentChild(innerComponent) {
return this.#modifier
.backToComponent()
.child(innerComponent);
}
componentChildComponents(innerComponent) {
return this.#modifier
.backToComponent()
.childComponents(innerComponent);
}
}
const LineStyles = Object.freeze({
dotted: 0,
dashed: 1,
solid: 2,
double: 3,
groove: 4,
ridge: 5,
inset: 6,
outset: 7,
none: 8,
hidden: 9
})

32
src/js/context.js

@ -1,32 +0,0 @@
/**
* The class provides overreaching options for building the website.
*/
class PageBuilder {
#cssClasses;
#functions;
constructor() {
this.#cssClasses = document.createElement("style");
this.#functions = document.createElement("script");
}
/**
* Registers a function to be added later in a script tag in the head of the document.
* @param {string} name
* @param {func} fun
*/
registerFunction(name, fun) {
this.#functions.innerText += `const ${name} = ${fun}`;
}
/**
* Adds a script tag into the head of the document.
*/
generate() {
document.querySelector("head")
.appendChild(this.#functions)
}
}
const Page = new PageBuilder();

179
src/js/modifier.js

@ -1,179 +0,0 @@
/**
* A chained class that sets most of the stylings of an element.
*/
class Modifier {
modifications = {};
constructor() {
this.modifications = new Object();
}
/**
* Sets the modifications for widht and height to 100%.
* @returns this modifier object
*/
fillMaxSize() {
this.modifications["width"] = "100%";
this.modifications["height"] = "100%";
return this;
}
/**
* Sets the modification for width to 100%.
* @param {number} fraction
* @returns this modifier object
*/
fillMaxWidth(fraction) {
this.modifications["width"] = (100 * fraction) + "%";
return this;
}
/**
* Sets the modification for height to 100%.
* @param {number} fraction
* @returns this modifier object
*/
fillMaxHeight(fraction) {
this.modifications["height"] = (100 * fraction) + "%";
return this;
}
/**
* Sets modifications according to the dimensions object.
* @param {Dimensions} dimensions
* @returns this modifier object
*/
size(dimensions) {
this.modifications["height"] = dimensions.height + "px";
this.modifications["width"] = dimensions.width + "px";
return this;
}
/**
* Sets the padding on all sides according to the given siding object.
* Currently the padding will always be set
* to the most recent padding/siding.
* @param {Siding} siding
* @returns this modifier object
*/
padding(siding) {
this.modifications["padding-right"] = siding.pxRight + "px";
this.modifications["padding-left"] = siding.pxLeft + "px";
this.modifications["padding-top"] = siding.pxTop + "px";
this.modifications["padding-bottom"] = siding.pxBottom + "px";
return this;
}
/**
* Sets the margin on all sides according to the given siding object.
* Currently the margin will always be set
* to the most recent margin/siding.
* @param {Siding} siding
* @returns this modifier object
*/
margin(siding) {
this.modifications["margin-right"] = siding.pxRight + "px";
this.modifications["margin-left"] = siding.pxLeft + "px";
this.modifications["margin-top"] = siding.pxTop + "px";
this.modifications["margin-bottom"] = siding.pxBottom + "px";
return this;
}
/**
* Sets the background-color as a rgb color.
* @param {Color} color
* @returns this modifier object
*/
background(color) {
this.modifications["background-color"] = color.cssRGBString();
return this;
}
/**
* Sets the color as a rgb color.
* @param {Color} color
* @returns this modifier object
*/
color(color) {
this.modifications["color"] = color.cssRGBString();
return this;
}
/**
* Adds the modifications of the given Modifier to current Modifier.
* This is especailly used in the cases of extending existing/pre defined
* Components.
* CAUTION matching existing modifications will be ignored.
* @param modifier The "new" Modifier
* @returns The "old/current" Modifier,
* extended with the modifications of the given Modifier.
*/
join(modifier, modifications = {}) {
var keys = Object.keys(modifier.modifications);
for (let i = 0; i < keys.length; i++) {
if (!this.modifications.hasOwnProperty(keys[i]))
this.modifications[keys[i]] = modifier.modifications[keys[i]];
}
return this;
}
/**
*
* @param {string} key a css style rule
* @param {string} value the corresponding value to the css style rule
* @returns this modifier object
*/
setStyleRule(key, value) {
this.modifications[key] = value;
return this;
}
/**
* Sets a border line (with given linestyle) to all sides.
* If lineStyle is an array, the containing LineStyles,
* are applied in the order: [top, right, bottom, left].
* @param {LineStyles|Array<LineStyles>} lineStyle the style of the border line
* @returns this modifier object
*/
border(lineStyle, width = 1, color = Colors.black) {
var lstyle = (lineStyle instanceof Array
? lineStyle.join(" ")
: lineStyle);
this.modifications["border"] = `${width}px ${lstyle} ${color.cssRGBString}`;
return this;
}
}
class ChainableModifier extends Modifier {
_component;
constructor(component) {
super();
this._component = component;
}
backToComponent() {
return this._component.modifier(this);
}
chainSize() {
return new ChainableDimensions(this);
}
chainPaddingSiding() {
return new ChainableSiding(this);
}
componentChild(innerComponent) {
return this._component
.modifier(this)
.child(innerComponent);
}
componentChildComponents(innerComponent) {
return this._component
.modifier(this)
.childComponents(innerComponent);
}
}

246
src/modifier.js

@ -0,0 +1,246 @@
/**
* A chained class that sets most of the stylings of an element.
*/
class Modifier {
_modifications;
constructor() {
this._modifications = new Object();
}
/**
* Sets the modifications for widht and height to 100%.
* @returns {Modifier} this modifier object
*/
fillMaxSize(widthFraction = 1, heightFraction = 1) {
return this.fillMaxWidth(widthFraction)
.fillMaxHeight(heightFraction);
}
/**
* Sets the modification for width to 100%.
* @param {number} fraction
* @returns {Modifier} this modifier object
*/
fillMaxWidth(fraction = 1) {
this._modifications["width"] = (100 * fraction) + "%";
return this;
}
/**
* Sets the modification for height to 100%.
* @param {number} fraction
* @returns {Modifier} this modifier object
*/
fillMaxHeight(fraction = 1) {
this._modifications["height"] = (100 * fraction) + "%";
return this;
}
/**
* Sets modifications according to the dimensions object.
* @param {Dimensions} dimensions
* @returns {Modifier} this modifier object
*/
dimensions(dimensions) {
dimensions.toModifications()
.forEach(kvpair => {
this._modifications[kvpair.key] = kvpair.value;
})
return this;
}
/**
* Sets the padding on all sides according to the given padding object.
* Currently the padding will always be set
* to the most recent padding/padding.
* @param {Sides} siding
* @returns {Modifier} this modifier object
*/
padding(siding) {
let keyToAdd = "";
if (siding instanceof PaddingChain) {
} else if (siding instanceof Sides) {
keyToAdd = "padding-"
}
siding.toModifications()
.forEach(kvpair => {
this._modifications[keyToAdd + kvpair.key] = kvpair.value;
})
return this;
}
/**
* Sets the margin on all sides according to the given siding object.
* Currently the margin will always be set
* to the most recent margin/siding.
* @param {Sides} siding
* @returns {Modifier} this modifier object
*/
margin(siding) {
this._modifications["margin"] = siding.getOrderedValues().join(' ');
return this;
}
/**
* Sets the background-color as a rgb color.
* @param {Color} color
* @returns {Modifier} this modifier object
*/
background(color) {
this._modifications["background-color"] = color.cssRGBString();
return this;
}
/**
* Sets the color as a rgb color.
* @param {Color} color
* @returns {Modifier} this modifier object
*/
color(color) {
this._modifications["color"] = color.cssRGBString();
return this;
}
/**
* Adds the modifications of the given Modifier to current Modifier.
* This is especailly used in the cases of extending existing/pre defined
* Components.
* CAUTION matching existing modifications will be overwritten.
* @param modifier The "new" Modifier
* @returns {Modifier} The "old/current" Modifier,
* extended with the modifications of the given Modifier.
*/
join(modifier, modifications = {}) {
var keys = Object.keys(modifier.ensureModifier()._modifications);
for (let i = 0; i < keys.length; i++) {
/* if (!this._modifications.hasOwnProperty(keys[i])) */
this._modifications[keys[i]] = modifier.ensureModifier()._modifications[keys[i]];
}
return this;
}
/**
*
* @param {string} key a css style rule
* @param {string} value the corresponding value to the css style rule
* @returns {Modifier} this modifier object
*/
setStyleRule(key, value) {
this._modifications[key] = value;
return this;
}
/**
* Sets a border line (with given linestyle) to all sides.
* If lineStyle is an array, the containing LineStyles,
* are applied in the order: [top, right, bottom, left].
* @param {Border} border the style of the border line
* @returns {Modifier} this modifier object
*/
border(border) {
border.toModifications()
.forEach(e => this._modifications[e.key] = e.value);
return this.clip(border._shape)
}
/**
*
* @param {Shape} shape
* @returns {Modifier}
*/
clip(shape) {
this._modifications["border-radius"] = shape.getOrderedValues().join(' ');
return this;
}
/**
*
* @param {number} size of width and height in pixels
* @returns {DimensionsChain}
*/
linkDimensions(size = -1) {
if (size === -1) {
return new DimensionsChain(this);
} else {
return new DimensionsChain(this).all(size).ensureModifier()
}
}
/**
*
* @param {number} amount the padding for all four sides
* @returns {PaddingChain}
*/
linkPadding(amount = -1) {
if (amount === -1) {
return new PaddingChain(this);
} else {
return new PaddingChain(this).all(amount);
}
}
/**
*
* @param {number} cornerRadius will create a rounded rectangle with the given cornerRadius
* @returns {ShapeChain}
*/
linkClip(cornerRadius = -1) {
if (cornerRadius === -1) {
return new ShapeChain(this);
} else {
return new ShapeChain(this).all(cornerRadius);
}
}
/**
*
* @param {number} borderWidth sets the width of all four border sides
* @returns {BorderChain}
*/
linkBorder(borderWidth = -1) {
if (borderWidth === -1) {
return new BorderChain(this);
} else {
return new BorderChain(this).width(borderWidth);
}
}
/**
*
* @returns {Modifier}
*/
ensureModifier() {
return this;
}
}
class ChainableModifier extends Modifier {
_component;
constructor(component) {
super();
this._component = component;
}
/**
*
* @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);
}
}

210
src/sizeSide/border.js

@ -0,0 +1,210 @@
const LineStyles = Object.freeze({
dotted: "dotted",
dashed: "dashed",
solid: "solid",
double: "double",
groove: "groove",
ridge: "ridge",
inset: "inset",
outset: "outset",
none: "none",
hidden: "hidden"
})
class BorderDefinition {
constructor(width = 0, color = Colors.black, style = LineStyles.solid) {
this._width = width;
this._color = color;
this._style = style;
}
width(width) {
this._width = width;
return this;
}
color(color) {
this._color = color;
return this;
}
style(style) {
this._style = style;
return this;
}
join(def) {
Object.keys(def)
.forEach(key => this[key] = def[key]);
return this;
}
}
const Define = Object.freeze({
width: new BorderDefinition().width,
style: new BorderDefinition().style,
color: new BorderDefinition().color
})
class Border extends Sides {
constructor(width = 0, color = Colors.black, style = LineStyles.solid, defaultUnit = SizeUnits.PIXEL, shape = Shapes.Rectangle) {
super(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;
}
setByIndex(index, value) {
if (value instanceof BorderDefinition) {
this.getByIndex(index).join(value)
} else {
this.getByIndex(index)._width = value
}
return this;
}
/**
*
* @param {string} key
* @param {*} value
*/
setOnDirections(key, value) {
let orderedAttributes = this.getOrderedAttributes()
for (let i = 0; i < this.getOrderedAttributes.length; i++) {
orderedAttributes[i][key] = value;
}
return this;
}
/**
*
* @param {number} width
* @returns {Border}
*/
width(width) {
this._fFirst._width = width;
this._fSecond._width = width;
this._fThird._width = width;
this._fForth._width = width;
return this;
}
/**
*
* @param {*} color
* @returns {Border}
*/
color(color) {
this._fFirst._color = color;
this._fSecond._color = color;
this._fThird._color = color;
this._fForth._color = color;
return this;
}
shape(shape) {
this._shape = shape;
return this;
}
/**
* Sets the border-style of all sides to the given.
* @param {LineStyles} lineStyle style of the border
* @returns {Border}
*/
setStyleAll(lineStyle) {
this._fFirst._style = lineStyle;
this._fSecond._style = lineStyle;
this._fThird._style = lineStyle;
this._fForth._style = lineStyle;
return this;
}
/**
*
* @param {LineStyles} lineStyle
* @param {*} sidingRefSide
* @returns {Border}
*/
setLineStyle(lineStyle, sidingRefSide) {
this._sidingStyles.setBySidingRef(sidingRefSide, lineStyle)
return this;
}
/**
*
* @param {Map<SidingRefSides, LineStyles} refSideStyleMap
* @returns {Border}
*/
setLineStyles(refSideStyleMap) {
let rkeys = Object.keys(refSideStyleMap);
for (let i = 0; i < array.length; i++) {
this._sidingStyles.setBySidingRef(rkeys[i]) = refSideStyleMap[rkeys[i]];
}
return this;
}
toModifications() {
let names = ["left", "top", "right", "bottom"];
return this.getOrderedAttributes()
.flatMap((bdef, i) => {
if (bdef.width == 0)
return []
return [
{ key: `border-${names[i]}-width`, value: bdef._width + this._unit },
{ key: `border-${names[i]}-color`, value: bdef._color },
{ key: `border-${names[i]}-style`, value: bdef._style }
]
})
}
}
class BorderChain extends Border {
constructor(modifier){
super();
this._modifier = modifier;
}
/**
*
* @returns {Modifier|ChainableModifier}
*/
toModifier() {
return this._modifier
.border(this);
}
/**
*
* @returns {Modifier|ChainableModifier}
*/
ensureModifier() {
return this.toModifier()
}
/**
* Applies the border modification on the modifier
* and returns (through the modifier) to the corresponding component.
* @returns {Component}
*/
toComponent() {
return this._modifier
.dimensions(this)
.toComponent();
}
/**
*
* @param {Component} innerComponent will be set to the corresponding component
* @returns {Component} the corr. Component after the childContext was applied.
*/
childContext(innerComponent) {
return this._modifier
.dimensions(this)
.toComponent()
.childContext(innerComponent);
}
}

105
src/sizeSide/dimensions.js

@ -0,0 +1,105 @@
/**
* Simple Dimensions container for the height and width in pixels.
*/
class Dimensions extends DirectionUnitDependentAttribute {
constructor(defaultValue = 0, defaultUnit = SizeUnits.PIXEL) {
super();
this._unit = defaultUnit;
this._fFirst = defaultValue;
this._fSecond = defaultValue;
}
/**
* Sets width (x) value of amount
* @param {number} amount
* @returns {Dimensions} this Dimensions Modifier
*/
width(amount) {
this._fFirst = amount;
return this;
}
/**
* Sets height (y) value of amount
* @param {number} amount
* @returns {Dimensions} this Dimensions Modifier
*/
height(amount) {
this._fSecond = amount;
return this;
}
all(size) {
return this.width(size).height(size);
}
getOrderedValues() {
return this.getOrderedValues().slice(2)
}
toModifications() {
let w = { key: "width", value: this._fFirst + this._unit }
let h = { key: "height", value: this._fSecond + this._unit }
let is_w = this._fFirst > 0;
let is_h = this._fSecond > 0;
if (is_h && is_w) {
return [w, h]
} else if (is_w) {
return [w]
} else if (is_h) {
return [h]
} else {
return []
}
}
}
class DimensionsChain extends Dimensions {
_modifier;
constructor(modifier) {
super();
this._modifier = modifier;
}
/**
*
* @returns {Modifier|ChainableModifier}
*/
toModifier() {
return this._modifier
.dimensions(this);
}
/**
*
* @returns {Modifier|ChainableModifier}
*/
ensureModifier() {
return this.toModifier()
}
/**
*
* @returns {Component} the Component that was (supposed to be) modified by this obj.
*/
toComponent() {
return this._modifier
.dimensions(this)
.toComponent();
}
/**
*
* @param {Component|Array<Component>} innerComponent children of the Component under modification.
* @returns {Component}
*/
childContext(innerComponent) {
return this._modifier
.dimensions(this)
.toComponent()
.childContext(innerComponent);
}
}

131
src/sizeSide/shapes.js

@ -0,0 +1,131 @@
class Shape extends DirectionUnitDependentAttribute {
constructor(defaultValue = 0, defaultUnit = SizeUnits.PIXEL) {
super(defaultValue, defaultUnit);
}
/**
*
* @param {*} amount
* @returns {Shape}
*/
topLeft(amount) {
this._fFirst = amount;
return this;
}
/**
*
* @param {*} amount
* @returns {Shape}
*/
topRight(amount) {
this._fSecond = amount;
return this;
}
/**
*
* @param {*} amount
* @returns {Shape}
*/
bottomLeft(amount) {
this._fThird = amount;
return this;
}
/**
*
* @param {*} amount
* @returns {Shape}
*/
bottomRight(amount) {
this._fForth = amount;
return this;
}
/**
*
* @param {*} amount
* @returns {Shape}
*/
diagonalPositive(amount) {
return this.bottomLeft(amount).topRight(amount);
}
/**
*
* @param {*} amount
* @returns {Shape}
*/
diagonalNegative(amount) {
return this.topLeft(amount).bottomRight(amount);
}
left(amount) {
return this.topLeft(amount).bottomLeft(amount);
}
right(amount) {
return this.topRight(amount).bottomRight(amount);
}
/**
*
* @param {*} amount
*/
getSidingRefValueMap() {
return {
[SidingRefCorners.TOPLEFT]: this.getBySidingRef(SidingRefCorners.TOPLEFT),
[SidingRefCorners.TOPRIGHT]: this.getBySidingRef(SidingRefCorners.TOPRIGHT),
[SidingRefCorners.BOTTOMLEFT]: this.getBySidingRef(SidingRefCorners.BOTTOMLEFT),
[SidingRefCorners.BOTTOMRIGHT]: this.getBySidingRef(SidingRefCorners.BOTTOMRIGHT),
}
}
}
class ShapeChain extends Shape {
_modifier;
constructor(modifier) {
super();
this._modifier = modifier;
}
/**
*
* @returns {Modifier|ChainableModifier}
*/
toModifier() {
return this._modifier
.clip(this);
}
/**
*
* @returns {Modifier|ChainableModifier}
*/
ensureModifier() {
return this.toModifier()
}
/**
*
* @returns {Component} the Component that was (supposed to be) modified by this obj.
*/
toComponent() {
return this._modifier
.clip(this)
.toComponent();
}
/**
*
* @param {Component|Array<Component>} innerComponent children of the Component under modification.
* @returns {Component}
*/
childContext(innerComponent) {
return this._modifier
.clip(this)
.toComponent()
.childContext(innerComponent);
}
}
const Shapes = Object.freeze({
Rectangle: new Shape(),
RoundedCorner: new Shape(),
Circle: new Shape(49, SizeUnits.PERCENT)
})

260
src/sizeSide/siding.js

@ -0,0 +1,260 @@
const SizeUnits = Object.freeze({
PIXEL: "px",
PERCENT: "%"
})
class DirectionUnitDependentAttribute {
_unit;
_fFirst;
_fSecond;
_fThird;
_fForth;
constructor(defaultValue = 0, defaultUnit = SizeUnits.PIXEL) {
this._unit = defaultUnit;
this._fFirst = defaultValue;
this._fSecond = defaultValue;
this._fThird = defaultValue;
this._fForth = defaultValue;
}
/**
*
* @param {Units} unit The unit of the amount or style
* @returns {DirectionUnitDependentAttribute} this - Object
*/
setUnit(unit) {
this._unit = unit;
return this;
}
/**
*
* @returns {array<*>} list of attributes
*/
getOrderedAttributes() {
return [this._fFirst, this._fSecond, this._fThird, this._fForth];
}
/**
* @returns {Array<string>}
*/
getOrderedValues() {
return this.getOrderedAttributes().map(a => a + this._unit);
}
/**
* Since the basic values are from "first" to "fourth",
* they can be also accessed in the ordered way.
*
* Mainly used by the setup of directions of subclasses.
* @param {number} index [1,4]
* @param {number} value
* @returns {DirectionUnitDependentAttribute} this
*/
setByIndex(index, value) {
switch (index) {
case 1:
this._fFirst = value;
break;
case 2:
this._fSecond = value;
break;
case 3:
this._fThird = value;
break;
case 4:
this._fForth = value;
break;
default:
this._fFirst = value;
break;
}
return this;
}
/**
* Since the basic values are from "first" to "fourth",
* they can be also accessed in the ordered way.
*
* Mainly used by the setup of directions of subclasses.
* @param {number} index [1,4]
* @returns {*} this value of index
*/
getByIndex(index) {
switch (index) {
case 1:
return this._fFirst;
case 2:
return this._fSecond;
case 3:
return this._fThird;
case 4:
return this._fForth;
default:
return this._fFirst;
}
}
/**
* Placeholder for overrides
* @returns {Object}
*/
toModifications() {
return this.getOrderedValues()
}
/**
* sets the amount-value for all directions.
* @param {number} amount value to set for all directions
* @returns {DirectionUnitDependentAttribute} this
*/
all(amount) {
this._fFirst = amount;
this._fSecond = amount;
this._fThird = amount;
this._fForth = amount;
return this;
}
}
class Sides extends DirectionUnitDependentAttribute {
/**
*
* @param {number|string} defaultValue
* @param {SizeUnits} defaultUnit
*/
constructor(defaultValue = 0, defaultUnit = SizeUnits.PIXEL) {
super(defaultValue, defaultUnit);
}
/**
* sets the amount-value for the left side.
* @param {number} amount siding for left
* @returns {Siding} this Siding Object
*/
left(amount) {
return this.setByIndex(1, amount);
}
/**
* sets the amount-value for the right side.
* @param {number} amount siding for right
* @returns {Siding} this Siding Object
*/
right(amount) {
return this.setByIndex(3, amount);
}
/**
* sets the amount-value for the top side.
* @param {number} amount siding for top
* @returns {Siding} this Siding Object
*/
top(amount) {
return this.setByIndex(2, amount);
}
/**
* sets the amount-value for the bottom side.
* @param {number} amount siding for bottom
* @returns {Siding} this Siding Object
*/
bottom(amount) {
return this.setByIndex(4, amount);
}
/**
* sets the amount-value for the horizontal sides (left and right).
* @param {number} amount siding for left and right.
* @returns {Sides} this Siding Object
*/
horizontal(amount) {
return this.left(amount).right(amount);
}
/**
* sets the amount-value for the vertical sides (left and right).
* @param {number} amount siding for top and bottom.
* @returns {Sides} this Siding Object
*/
vertical(amount) {
return this.top(amount).bottom(amount);
}
toModifications() {
return [
{ key: "left", value: this._fFirst + this._unit },
{ key: "top", value: this._fSecond + this._unit },
{ key: "right", value: this._fThird + this._unit },
{ key: "bottom", value: this._fForth + this._unit }
]
}
}
class PaddingChain extends Sides {
_modifier;
constructor(modifier) {
super();
this._modifier = modifier;
}
toModifier() {
return this._modifier
.padding(this);
}
/**
* Returns the corresponding Modifier.
* Basically climbs up the chain level.
* @returns {Modifier}
*/
ensureModifier() {
return this.toModifier()
}
/**
* Returns the style-modifications of the class.
* @returns {Map<string,string>}
*/
toModifications() {
return [
{ key: "padding-left", value: this._fFirst + this._unit },
{ key: "padding-top", value: this._fSecond + this._unit },
{ key: "padding-right", value: this._fThird + this._unit },
{ key: "padding-bottom", value: this._fForth + this._unit }
]
}
/**
*
* @returns {Component} the Component that was (supposed to be) modified by this obj.
*/
toComponent() {
return this._modifier
.padding(this)
.toComponent();
}
/**
*
* @param {Component|Array<Component>} innerComponent children of the Component under modification.
* @returns {Component}
*/
childContext(innerComponent) {
return this._modifier
.padding(this)
.toComponent()
.childContext(innerComponent);
}
}

7
tsconfig.json

@ -1,9 +1,10 @@
{ {
"compilerOptions": { "compilerOptions": {
"module": "CommonJS", "module": "AMD",
"target": "ES2020", "target": "ES2015",
"declaration": true, "declaration": true,
"outDir": "./lib" "outDir": "./lib",
"outFile": "jpc-like-websites.js"
}, },
"include": [ "include": [
"./src/ts/*" "./src/ts/*"

Loading…
Cancel
Save