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.
466 lines
14 KiB
466 lines
14 KiB
/**
|
|
* A chained class that sets most of the stylings of an element
|
|
* Attributes:
|
|
* _modifications: {Object}
|
|
*/
|
|
class Modifier {
|
|
/**
|
|
* @type {Map<string,string>} _modifications
|
|
*/
|
|
_modifications;
|
|
/**
|
|
* @type {Array<string>}
|
|
*/
|
|
_removeMods;
|
|
/**
|
|
* @type {Shape}
|
|
*/
|
|
_shape;
|
|
/**
|
|
* @type {Sides} paddingValues
|
|
*/
|
|
_paddingValues;
|
|
|
|
constructor() {
|
|
this._modifications = new Object();
|
|
this._removeMods = [];
|
|
}
|
|
|
|
/**
|
|
* 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 the given fraction of 1 (default 1 := 100%).
|
|
* @param {number} fraction
|
|
* @returns {Modifier} this modifier object
|
|
*/
|
|
fillMaxWidth(fraction = 1) {
|
|
this._modifications["width"] = (100 * fraction) + "%";
|
|
this._modifications["max-width"] = (100 * fraction) + "%";
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the modification for height to the given fraction of 1 (default 1 := 100%).
|
|
* @param {number} fraction
|
|
* @returns {Modifier} this modifier object
|
|
*/
|
|
fillMaxHeight(fraction = 1) {
|
|
this._modifications["height"] = (100 * fraction) + "%";
|
|
this._modifications["max-height"] = (100 * fraction) + "%";
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} keyWord weither 'height' or 'width' that will be adjusted and looked for
|
|
* @param {Sides} parentalPadding
|
|
*/
|
|
_updateDimensionsBy(parentalPadding) {
|
|
function updateDirection(keyWord, modifications, parentalAdjustment) {
|
|
let refKeys = Object.keys(modifications)
|
|
.filter(k => k.includes(keyWord));
|
|
|
|
if (refKeys.length > 0) {
|
|
for (let i = 0; i < refKeys.length; i++) {
|
|
let key = refKeys[i];
|
|
let value = modifications[key];
|
|
|
|
if (key.includes("calc")) {
|
|
console.log(
|
|
`Modifier._updateByParent... ${keyWord
|
|
} - unexpected value '${value
|
|
}' for '${key
|
|
}', skipping...`
|
|
);
|
|
} else {
|
|
let newValue = `calc(${value} - ${parentalAdjustment});`;
|
|
modifications[key] = newValue.trim();
|
|
}
|
|
}
|
|
}
|
|
return modifications;
|
|
}
|
|
|
|
if (parentalPadding) {
|
|
let pval = parentalPadding.getValues();
|
|
if (pval["horizontal"] > 0) {
|
|
this._modifications = updateDirection("width", this._modifications, pval["horizontal"] + parentalPadding._unit);
|
|
}
|
|
|
|
if (pval["vertical"] > 0) {
|
|
this._modifications = updateDirection("height", this._modifications, pval["vertical"] + parentalPadding._unit);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Takes dimensions as param which can be either of three:
|
|
*
|
|
* param == null (not given):
|
|
* Returns new DimensionsChain (to chain Dimensions-Modifications)
|
|
*
|
|
* param == number (>0):
|
|
* Applies Dimensions.all(dimension);
|
|
* Returns this modifier
|
|
*
|
|
* param == Dimensions:
|
|
* Sets modifications according to the dimensions object;
|
|
* Returns this modifier
|
|
* @param {Dimensions | number | undefined} [modify=null] modify as in modifiers
|
|
* @returns { Modifier | DimensionsChain } this modifier object or a DimensionsChain
|
|
*/
|
|
dimensions(modify = null) {
|
|
if (modify instanceof Dimensions) {
|
|
modify.toModifications()
|
|
.forEach(kvpair => {
|
|
this._modifications[kvpair.key] = kvpair.value;
|
|
});
|
|
return this;
|
|
} else {
|
|
let modSub = new DimensionsChain(this);
|
|
if (Number.isInteger(modify) && modify > 0) {
|
|
return modSub.all(modify).ensureModifier();
|
|
}
|
|
// case dimension is number but < 0 or dimensions == null or anything else
|
|
return modSub;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 {Padding | number | undefined} modify as in modifiers
|
|
* @returns {Modifier | PaddingChain} this modifier object
|
|
*/
|
|
padding(modify = null) {
|
|
if (modify instanceof Sides && !(modify instanceof Padding)) {
|
|
modify._modMethod = "padding";
|
|
modify = Object.assign(new Padding(), modify);
|
|
}
|
|
|
|
if (modify instanceof Padding) {
|
|
modify.toModifications()
|
|
.forEach(kvpair => {
|
|
this._modifications[kvpair.key] = kvpair.value;
|
|
});
|
|
} else {
|
|
let modSub = new PaddingChain(this);
|
|
if (Number.isInteger(modify) && modify > -1) {
|
|
return modSub.all(modify).ensureModifier();
|
|
}
|
|
return modSub
|
|
}
|
|
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.
|
|
* @ATTENTION since it just increases complexity to constantly use padding and margin
|
|
* it is recommended to use padding and to stick to that as often as possible.
|
|
* Padding values take affect inside/within the element.
|
|
* @param {Margin | number | undefined} modify
|
|
* @returns {Modifier | MarginChain} this modifier object
|
|
*/
|
|
margin(modify = null) {
|
|
if (modify instanceof Sides && !(modify instanceof Margin)) {
|
|
modify._modMethod = "margin";
|
|
modify = Object.assign(new Margin(), modify);
|
|
}
|
|
|
|
if (modify instanceof Margin) {
|
|
modify.toModifications()
|
|
.forEach(kvpair => {
|
|
this._modifications[kvpair.key] = kvpair.value;
|
|
});
|
|
} else {
|
|
let modSub = new MarginChain(this);
|
|
if (Number.isInteger(modify) && modify > -1) {
|
|
return modSub.all(modify).ensureModifier();
|
|
}
|
|
return modSub
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the background-color as a rgb color.
|
|
* If no color is given/specified the styling will be set to "inherit"
|
|
* and use the color setting from (one of) the parent.
|
|
* @param {Color} color
|
|
* @returns {Modifier} this modifier object
|
|
*/
|
|
background(color) {
|
|
if (color) {
|
|
if (color._hex) {
|
|
this._modifications["background-color"] = color._hex;
|
|
} else {
|
|
this._modifications["background-color"] = color.cssRGBString();
|
|
}
|
|
} else {
|
|
this._modifications["background-color"] = "inherit";
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the color as a rgb color.
|
|
* If no color is given/specified the styling will be set to "inherit"
|
|
* and use the color setting from (one of) the parent.
|
|
* @param {Color} color
|
|
* @returns {Modifier} this modifier object
|
|
*/
|
|
color(color) {
|
|
this._modifications["color"] = (
|
|
color
|
|
? color.cssRGBString()
|
|
: "inherit"
|
|
);
|
|
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.
|
|
*
|
|
* @todo finish second parameter "modifications" - logic
|
|
*
|
|
* @param modifier The "new" Modifier
|
|
* @returns {Modifier} The "old/current" Modifier,
|
|
* extended with the modifications of the given Modifier.
|
|
*/
|
|
join(modifier, modifications = {}) {
|
|
let 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]];
|
|
}
|
|
let removeMods = modifier.ensureModifier()._removeMods;
|
|
if (removeMods.length > 0) {
|
|
for (let i = 0; i < removeMods.length; i++) {
|
|
delete this._modifications[removeMods[i]];
|
|
}
|
|
}
|
|
if (modifier._paddingValues) {
|
|
this._paddingValues = modifier._paddingValues;
|
|
}
|
|
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 the style rules to deactivate text-selection in the component.
|
|
* @returns {Modifier}
|
|
*/
|
|
noneSelect() {
|
|
return this
|
|
.setStyleRule("user-select", "none")
|
|
.setStyleRule("-ms-user-select", "none")
|
|
.setStyleRule("-webkit-user-select", "none")
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {StylePropertyMap} rulemap
|
|
* @returns {Modifier}
|
|
*/
|
|
addStyleRuleMap(rulemap) {
|
|
for (const ruleKey of Object.keys(rulemap)) {
|
|
this._modifications[ruleKey] = rulemap[ruleKey];
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} key
|
|
* @returns {Modifier} this modifier object
|
|
*/
|
|
removeStyleRule(key) {
|
|
this._removeMods.push(key);
|
|
if (Object.keys(this._modifications).includes(key)) {
|
|
delete this._modifications[key];
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Takes border as param which can be either of three:
|
|
*
|
|
* param == null (not given):
|
|
* Returns new BorderChain (to chain Border-Modifications)
|
|
*
|
|
* param == number (>0):
|
|
* Applies Border.width(border);
|
|
* Rerturns this modifier
|
|
*
|
|
* param == Border:
|
|
*
|
|
* 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].
|
|
* If the border has a shape defined,
|
|
* this shape will override earlier shape definitions.
|
|
* Otherwise existing shape definitions will be applied;
|
|
*
|
|
* Rerturns this modifier
|
|
*
|
|
* @param {Border | number | undefined} [modify=null] modify as in modifiers
|
|
* @returns {Modifier | BorderChain} this modifier or BorderChain
|
|
*/
|
|
border(modify = null) {
|
|
if (modify instanceof Border) {
|
|
if (modify._shape) {
|
|
this.clip(modify._shape);
|
|
} else if (this._shape) {
|
|
modify._shape = this._shape;
|
|
}
|
|
|
|
modify.toModifications()
|
|
.forEach(e => this._modifications[e.key] = e.value);
|
|
|
|
return this;
|
|
} else {
|
|
let modSub = new BorderChain(this);
|
|
if (Number.isInteger(modify) && modify > 0) {
|
|
return modSub.width(modify).ensureModifier();
|
|
}
|
|
return modSub;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Takes shape as param which can be either of three:
|
|
*
|
|
* param == null (not given):
|
|
* Returns new ShapeChain (to chain Shape-Modifications)
|
|
*
|
|
* param == number (>0):
|
|
* Applies Shape.all(dimension);
|
|
* Returns this modifier
|
|
*
|
|
* param == Shape:
|
|
* Sets modifications according to the shape object;
|
|
* Returns this modifier
|
|
*
|
|
*
|
|
* @param {Shape | number | undefined} [modify=null] modify as in modifiers
|
|
* @returns { Modifier | ShapeChain }
|
|
*/
|
|
clip(modify = null) {
|
|
if (modify instanceof Shape) {
|
|
this._shape = modify;
|
|
this._modifications["border-radius"] = modify.getOrderedValues().join(' ');
|
|
return this;
|
|
} else {
|
|
let modSub = new ShapeChain(this);
|
|
if (Number.isInteger(modify) && modify > 0) {
|
|
return modSub.all(modify).ensureModifier();
|
|
}
|
|
return modSub;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated use Modifier.dimensions() instead
|
|
* @param {number} size of width and height in pixels
|
|
* @returns {DimensionsChain}
|
|
*/
|
|
linkDimensions(size = -1) {
|
|
if (size === -1) {
|
|
return new DimensionsChainedModifier(this);
|
|
} else {
|
|
return new DimensionsChain(this).all(size).ensureModifier()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated use Modifier.padding() instead
|
|
* @param {number} amount the padding for all four sides
|
|
* @returns {PaddingChain}
|
|
*/
|
|
linkPadding(amount = -1) {
|
|
if (amount === -1) {
|
|
return new PaddingChainedModifier(this);
|
|
} else {
|
|
return new PaddingChain(this).all(amount);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated use Modifier.margin() instead
|
|
* @ATTENTION since it just increases complexity to constantly use padding and margin
|
|
* it is recommended to use padding and to stick to that as often as possible.
|
|
* Padding values take affect inside/within the element.
|
|
* @param {number} amount the padding for all four sides
|
|
* @returns {PaddingChain}
|
|
*/
|
|
linkMargin(amount = -1) {
|
|
if (amount === -1) {
|
|
return new MarginChainedModifier(this);
|
|
} else {
|
|
return new MarginChain(this).all(amount);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated use Modifier.clip() instead
|
|
* @param {number} cornerRadius will create a rounded rectangle with the given cornerRadius
|
|
* @returns {ShapeChain}
|
|
*/
|
|
linkClip(cornerRadius = -1) {
|
|
if (cornerRadius === -1) {
|
|
return new ShapeChainedModifier(this);
|
|
} else {
|
|
return new ShapeChain(this).all(cornerRadius);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated use Modifier.border() instead
|
|
* @param {number} borderWidth sets the width of all four border sides
|
|
* @returns {BorderChain}
|
|
*/
|
|
linkBorder(borderWidth = -1) {
|
|
if (borderWidth === -1) {
|
|
return new BorderChainedModifier(this);
|
|
} else {
|
|
return new BorderChain(this).width(borderWidth);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @returns {Modifier}
|
|
*/
|
|
ensureModifier() {
|
|
return this;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|