You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
551 lines
15 KiB
551 lines
15 KiB
|
|
/**
|
|
* 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();
|
|
/**
|
|
* Enum to access common events
|
|
*/
|
|
const CommonEvents = Object.freeze({
|
|
ONCLICK: "onClick",
|
|
})
|
|
|
|
/**
|
|
* A simple Color class for rgb set color values.
|
|
*/
|
|
class Color {
|
|
#red;
|
|
#green;
|
|
#blue;
|
|
|
|
constructor(red, green, blue) {
|
|
this.#red = red
|
|
this.#green = green
|
|
this.#blue = blue
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @returns {string} an rgb object string
|
|
*/
|
|
cssRGBString() {
|
|
return `rgb(${this.#red}, ${this.#green}, ${this.#blue})`;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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,
|
|
})
|
|
/**
|
|
* 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%.
|
|
* @returns this modifier object
|
|
*/
|
|
fillMaxWidth() {
|
|
this.modifications["width"] = "100%";
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the modification for height to 100%.
|
|
* @returns this modifier object
|
|
*/
|
|
fillMaxHeight() {
|
|
this.modifications["height"] = "100%";
|
|
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;
|
|
}
|
|
|
|
}
|
|
/**
|
|
* A chainable HTMLElement builder.
|
|
*/
|
|
class Component {
|
|
_element;
|
|
_modifier
|
|
_alignment;
|
|
_arrangement;
|
|
|
|
constructor(element, attr = {}) {
|
|
this._modifier = new Modifier().margin(new Siding().all(0));
|
|
this._element = element;
|
|
Object.keys(attr)
|
|
.forEach(key => {
|
|
this._element.setAttribute(key, attr[key]);
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 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|Array<Component>} innerComponent
|
|
* @returns this component object
|
|
*/
|
|
childContext(innerComponent) {
|
|
if (innerComponent instanceof Array) {
|
|
for (let i = 0; i < innerComponent.length; i++) {
|
|
this._element.append(innerComponent[i].generate());
|
|
}
|
|
} else {
|
|
this._element.append(innerComponent.generate());
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {CommonEvent} commonEvent
|
|
* @param {string} functionName
|
|
* @returns this component object
|
|
*/
|
|
setEvent(commonEvent, functionName) {
|
|
return this.setAttribute(commonEvent, `${functionName}(this)`)
|
|
}
|
|
|
|
}
|
|
/**
|
|
* 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
|
|
*/
|
|
childContext(innerComponent) {
|
|
if (innerComponent instanceof Array) {
|
|
innerComponent.forEach(icomp => {
|
|
icomp.modifier(
|
|
new Modifier()
|
|
.setStyleRule("flex", "none")
|
|
)
|
|
})
|
|
} else {
|
|
innerComponent.modifier(
|
|
new Modifier()
|
|
.setStyleRule("flex", "none")
|
|
)
|
|
}
|
|
return super.childContext(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()
|
|
.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()
|
|
.setStyleRule("flex-direction", "row")
|
|
)
|
|
}
|
|
}
|
|
const builder = {
|
|
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); },
|
|
|
|
row: function (attr = {}) { return new Row(attr) },
|
|
column: function (attr = {}) { return new Column(attr) },
|
|
page: function(innerComponents){
|
|
Page.generate();
|
|
document.querySelector('#root').appendChild(innerComponents.generate())
|
|
}
|
|
}
|
|
|