Compare commits

...

12 Commits

Author SHA1 Message Date
chris 825ba24ad6 FEAT: Component subscription and functions after load 6 months ago
chris 012e2e8afa IMPRO,REFA: Minor changes 6 months ago
chris dd4ac1d771 REFA: Fusion of "Chainable..." and "...Chain" constructs 6 months ago
chris b98c3be3be REFA,DOC: several things 6 months ago
chris a2765d9383 FEAT,IMPRO: added linkBorder functionallity 6 months ago
chris 2d3b2c0f46 FEAT,REFA: replaced componentChild(ren) with childContext 6 months ago
chris 1f962b8695 REFA,IMPRO: Changed Comp-Attributes-Behaviour 6 months ago
chris 5bf4f2e856 IMPRO,DEV: DEV intervall control as well as log 6 months ago
chris 0a2d16ecea REFA,IMPRO: Introduced funcitons and swapped high level attributes access 6 months ago
chris d3dbd4ecd3 REFA: component attributes 6 months ago
chris 060918fe51 REFA: fefactored base classes/logic of SideUnitDependendAttributes 6 months ago
chris 62b85b35b5 MAJOR-REFA 6 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.
So it is recommended to not expect to much,
you have been warned.
```sh
sh join_js_files.sh
```

25
join_js_files.sh

@ -1,9 +1,28 @@
TARGET="jpc-like-websites.js"
SRC="src/js"
ORDERED_LIST="context.js componentAttribute.js color.js modifier.js component.js baseComponents.js builder.js"
SRC="src"
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 "/* ## 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
done

15
package-lock.json

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

2
package.json

@ -15,6 +15,6 @@
"author": "",
"license": "ISC",
"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_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": {
"module": "CommonJS",
"target": "ES2020",
"module": "AMD",
"target": "ES2015",
"declaration": true,
"outDir": "./lib"
"outDir": "./lib",
"outFile": "jpc-like-websites.js"
},
"include": [
"./src/ts/*"

Loading…
Cancel
Save