/** * This file is part of the jps-like-websites lib * URL: https://git.labos.goip.de/chris/jpc-like-websites * @copyright by its creator Christian Martin */ /** * Enum providing predefined set of Size-Units */ const SizeUnits = Object.freeze({ PIXEL: "px", PERCENT: "%" }) /** * @abstract */ 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} */ 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; } } const SideDirections = Object.freeze({ LEFT: 1, TOP: 2, RIGHT: 3, BOTTOM: 4 }); const SideTransitionDirection = Object.freeze({ HORIZONTAL: 0, VERTICAL: 1 }); const Corners = Object.freeze({ TOP_LEFT: 0, TOP_RIGHT: 1, BOTTOM_LEFT: 2, BOTTOM_RIGHT: 3 }); const CornerTransitionDirection = Object.freeze({ TOP_LEFT_BOTTOM_RIGHT: 0, TOP_RIGHT_BOTTOM_LEFT: 1 }); /** * @inheritdoc * @extends DirectionUnitDependentAttribute * */ 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); } /** * * @returns {Object} */ getValues() { return { "left": this._fFirst, "top": this._fSecond, "right": this._fThird, "bottom": this._fForth, "horizontal": this._fFirst + this._fThird, "vertical": this._fSecond + this._fForth } } 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 } ] } } /** * @inheritdoc * @extends Sides */ 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} */ 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} innerComponent children of the Component under modification. * @returns {Component} */ childContext(innerComponent) { return this._modifier .padding(this) .toComponent() .childContext(innerComponent); } } /** * */ class TwoDimPoint { /** * * @param {number} x * @param {number} y */ constructor(x, y) { this.x = x; this.y = y; } /** * * @param {number} delta * @returns {TwoDimPoint} */ xMinus(delta) { this.x = this.x - delta; return this; } /** * * @param {number} delta * @returns {TwoDimPoint} */ xPlus(delta) { this.x = this.x + delta; return this; } /** * * @param {number} delta * @returns {TwoDimPoint} */ yMinus(delta) { this.y = this.y - delta; return this; } /** * * @param {number} delta * @returns {TwoDimPoint} */ yPlus(delta) { this.y = this.y + delta; return this; } /** * * @param {TwoDimPoint} delta * @returns {TwoDimPoint} */ minusTDP(delta) { this.x = this.x - delta.x; this.y = this.y - delta.y; return this; } /** * * @param {TwoDimPoint} delta * @returns {TwoDimPoint} */ plusTDP(delta) { this.x = this.x + delta.x; this.y = this.y + delta.y; return this; } } /** * * @param {number} start * @param {number} end * @param {number} value * @param {number} tolerance * @param {boolean} usePercentage * @returns {boolean} */ function isValueInBounds(start, end, value, tolerance = 0, usePercentage = false) { if (tolerance !== 0) { if (usePercentage) { start = start * (1 - tolerance / 100); end = end * (1 + tolerance / 100); } else { start = start - tolerance; end = end + tolerance; } } return value >= start && value <= end; } /** * @param {number} x * @param {number} y * @param {Map} area * @param {number} tolerance * @param {boolean} usePercentage if tolerance is given and this is set to true, * the tolerance will be calculated by percentage, * otherwise it will be subtracted/added * @returns {boolean} */ function areXYInArea(x, y, area, tolerance = 0, usePercentage = false) { return isValueInBounds( area.get(SideDirections.LEFT), area.get(SideDirections.RIGHT), x, tolerance, usePercentage ) && isValueInBounds( area.get(SideDirections.TOP), area.get(SideDirections.BOTTOM), y, tolerance, usePercentage ); } /** * * @param {TwoDimPoint} point * @param {Map} area * @param {number} tolerance * @param {boolean} usePercentage if tolerance is given and this is set to true, * the tolerance will be calculated by percentage, * otherwise it will be subtracted/added */ function isPointInArea(point, area, tolerance = 0, usePercentage = false) { return areXYInArea( point.x, point.y, area, tolerance, usePercentage ); } /** * * @param {HTMLElement} element * @returns {Object