layer class, events, injected parameters

This commit is contained in:
2025-08-03 20:07:43 +07:00
parent a6389235eb
commit c94542bfd3
2 changed files with 747 additions and 302 deletions

View File

@@ -1 +1 @@
"use strict";export default class pechatalka{#wrap=document.getElementById("pechatalka");get wrap(){return this.#wrap}#canvas=document.getElementById("pechatalka")?.querySelector(".canvas");get canvas(){return this.#canvas}#result=document.getElementById("pechatalka")?.querySelector(".result");get result(){return this.#result}#layers=new Set();get layers(){return this.#layers}#cost=0;get cost(){return this.#cost}prices={pin:{image:150}};constructor(wrap,canvas,result,inject=false){if(wrap instanceof HTMLElement){this.#wrap=wrap;if(inject){this.#wrap.pechatalka=this}}if(canvas instanceof HTMLElement){this.#canvas=canvas}if(result instanceof HTMLElement){this.#result=result}}moving(target){const canvas=this.#canvas;const from={x:0,y:0};function moving(event){target.style.left=event.clientX-from.x+"px";target.style.top=event.clientY-from.y+"px"}function restore(){target.style.top=target.style.left=null}function start(event){if(event.button===0){[from.x,from.y]=[event.clientX-(parseInt(target.style.left)||0),event.clientY-(parseInt(target.style.top)||0)];window.addEventListener("mousemove",moving,true)}}function end(){window.removeEventListener("mousemove",moving,true)}target.addEventListener("mousedown",start,false);window.addEventListener("mouseup",end,false);canvas.addEventListener("mouseleave",end,false)}scaling(target,type="scale"){function scroll(event){if(type==="scale"){let scale=(parseFloat(target.style.scale)||1)+event.deltaY/1000;if(scale<0.4){scale=0.4}else if(scale>3){scale=3}target.style.scale=scale}else if(type==="width"){const change=event.deltaY/2;const cut=target.parentElement.offsetWidth;const bounds={minimum:cut/2-cut,maximum:cut*2-cut};let zoom=(parseFloat(target.style.getPropertyValue("--width-zoom"))||0)+change;if(zoom<bounds.minimum){zoom=bounds.minimum}else if(zoom>bounds.maximum){zoom=bounds.maximum}else{target.style.left=(parseInt(target.style.left)||0)-change/2+"px";target.style.top=(parseInt(target.style.top)||0)-change/2+"px"}target.style.setProperty("--width-zoom",zoom+"px")}}target.addEventListener("wheel",scroll,false)}image(file){const identifier=this.#layers.entries.length??1;const layer=document.createElement("div");layer.classList.add("layer");layer.setAttribute("id","pechatalka_layer_"+identifier);const button_delete=document.createElement("button");button_delete.classList.add("delete","rounded");button_delete.addEventListener("click",(event)=>{layer.remove();this.#cost-=this.prices.pin.image??0;this.#result.querySelector(".cost").innerText=this.#cost});const trash=document.createElement("i");trash.classList.add("icon","trash");const image=document.createElement("img");image.classList.add("rounded");image.setAttribute("draggable",false);image.setAttribute("src",URL.createObjectURL(file));layer.appendChild(image);button_delete.appendChild(trash);layer.appendChild(button_delete);this.#canvas.appendChild(layer);this.#cost+=this.prices.pin.image??0;this.#result.querySelector(".cost").innerText=this.#cost;this.moving(layer);this.scaling(layer)}} "use strict";export default class pechatalka{#wrap=document.getElementById("pechatalka");get wrap(){return this.#wrap}#canvas=document.getElementById("pechatalka")?.querySelector(".canvas");get canvas(){return this.#canvas}#result=document.getElementById("pechatalka")?.querySelector(".result");get result(){return this.#result}#layers=new Set();get layers(){return this.#layers}#preset=new Map();get preset(){return this.#preset}#cost=0;set cost(value){if(typeof value==="number"){const from=this.#cost;this.#cost=value;if(this.#cost<0){this.#cost=0}this.#events.get("cost")?.get("changed")(this.#cost,from)}}get cost(){return this.#cost}prices={pin:{image:150}};#events=new Map([["layers",new Map([["create",(layer)=>{}]])],["cost",new Map([["changed",(to,from)=>{}]])]]);get events(){return this.#events}constructor(wrap,canvas,result,preset,inject=false){if(wrap instanceof HTMLElement){this.#wrap=wrap;if(inject){this.#wrap.pechatalka=this}}if(canvas instanceof HTMLElement){this.#canvas=canvas}if(result instanceof HTMLElement){this.#result=result}if(preset instanceof Map){this.#preset=preset}}global(name,value=null,preset=false){if(typeof name==="string"){for(const layer of this.#layers){layer.set(name,value)}if(preset){this.#preset.set(name,value)}}}moving(layer){const from={x:0,y:0};function moving(event){layer.wrap.style.left=event.clientX-from.x+"px";layer.wrap.style.top=event.clientY-from.y+"px"}function restore(){layer.wrap.style.top=layer.wrap.style.left=null}function start(event){if(event.button===0){[from.x,from.y]=[event.clientX-(parseInt(layer.wrap.style.left)||0),event.clientY-(parseInt(layer.wrap.style.top)||0)];window.addEventListener("mousemove",moving,true)}}function end(){window.removeEventListener("mousemove",moving,true)}layer.wrap.addEventListener("mousedown",start,false);window.addEventListener("mouseup",end,false);this.#canvas.addEventListener("mouseleave",end,false)}scaling(layer,type="scale"){function scroll(event){if(type==="scale"){let scale=(parseFloat(layer.wrap.style.scale)||1)+event.deltaY/1000;if(scale<0.4){scale=0.4}else if(scale>3){scale=3}layer.wrap.style.scale=scale}else if(type==="width"){const change=event.deltaY/1.5;const cut=target.parentElement.offsetWidth;const bounds={minimum:cut/1.5-cut,maximum:cut*1.5-cut};let zoom=(parseFloat(layer.wrap.style.getPropertyValue("--width-zoom"))||0)+change;if(zoom<bounds.minimum){zoom=bounds.minimum}else if(zoom>bounds.maximum){zoom=bounds.maximum}else{layer.wrap.style.left=(parseInt(layer.wrap.style.left)||0)-change/2+"px";layer.wrap.style.top=(parseInt(layer.wrap.style.top)||0)-change/2+"px"}layer.wrap.style.setProperty("--width-zoom",zoom+"px")}}layer.wrap.addEventListener("wheel",scroll,false)}image(file,cost=0){const identifier=this.#layers.size+1;const wrap=document.createElement("div");wrap.classList.add("layer");wrap.setAttribute("id","pechatalka_layer_"+identifier);const button_delete=document.createElement("button");button_delete.classList.add("delete");const trash=document.createElement("i");trash.classList.add("icon","trash");const image=document.createElement("img");image.setAttribute("draggable",false);image.setAttribute("src",URL.createObjectURL(file));wrap.appendChild(image);button_delete.appendChild(trash);wrap.appendChild(button_delete);this.#canvas.appendChild(wrap);const instance=new layer("image",cost,wrap,image,{delete:button_delete},this.#preset,);this.#layers.add(instance);this.#events.get("layers")?.get("create")(instance);this.cost+=instance.cost;this.moving(instance);this.scaling(instance);button_delete.addEventListener("click",(event)=>{instance.wrap.remove();this.#layers.delete(instance);this.cost-=instance.cost})}}export class layer{#type;set type(value){const types=new Set(["image","film"]);if(types.has(value)){this.#type=value}}get type(){return this.#type}#cost=0;set cost(value){if(typeof value==="number"){const from=this.#cost;this.#cost=value;if(this.#cost<0){this.#cost=0}this.#events.get("cost")?.get("changed")(from,this.#cost)}}get cost(){return this.#cost}#wrap;get wrap(){return this.#wrap}#content;get content(){return this.#content}#buttons=new Map();get buttons(){return this.#buttons}#events=new Map([["cost",new Map([["changed",(to,from)=>{}]])]]);get events(){return this.#events}constructor(type,cost,wrap,content,buttons,preset,inject=false){this.type=type;if(typeof this.#type==="string"){this.cost=cost;if(wrap instanceof HTMLElement){this.#wrap=wrap;if(inject){this.#wrap.layer=this}}if(content instanceof HTMLElement){this.#content=content}if(buttons instanceof Object){for(const[name,element]of Object.entries(buttons)){this.#buttons.set(name,element)}}for(const[name,value]of preset.entries()){this[name]=value}}}set(name,value){const from=this[name];this[name]=value;this.#events.get(name)?.get("set")(this[name],from);return this[name]}toggle(name){this[name]=!this[name]??true;this.#events.get(name)?.get("toggle")(this[name]);return this[name]}}

View File

@@ -107,18 +107,78 @@ export default class pechatalka {
return this.#layers; return this.#layers;
} }
/**
* @name Preset
*
* @description
* Registry of parameters that will be write into created layers
*
* @type {Map}
*
* @protected
*/
#preset = new Map();
/**
* @name Preset (get)
*
* @description
* Registry of parameters that will be write into created layers
*
* @return {Map}
*
* @public
*/
get preset() {
return this.#preset;
}
/** /**
* @name Cost * @name Cost
* *
* @description
* The total cost
*
* @type {number} * @type {number}
* *
* @protected * @protected
*/ */
#cost = 0; #cost = 0;
/**
* @name Cost (set)
*
* @description
* The total cost
*
* @return {number}
*
* @public
*/
set cost(value) {
if (typeof value === "number") {
// Validated the value
// Initializing the deprecated cost
const from = this.#cost;
// Writing the value
this.#cost = value;
// Filtering by the minimal value
if (this.#cost < 0) this.#cost = 0;
// Processing the `cost changed` event function
this.#events.get("cost")?.get("changed")(this.#cost, from);
}
}
/** /**
* @name Cost (get) * @name Cost (get)
* *
* @description
* The total cost
*
* @return {number} * @return {number}
* *
* @public * @public
@@ -139,22 +199,46 @@ export default class pechatalka {
*/ */
prices = { prices = {
pin: { pin: {
image: 150 image: 150,
} },
}; };
/**
* @name Events
*
* @type {Map}
*
* @protected
*/
#events = new Map([
["layers", new Map([["create", (layer) => {}]])],
["cost", new Map([["changed", (to, from) => {}]])],
]);
/**
* @name Events (get)
*
* @type {Map}
*
* @public
*/
get events() {
return this.#events;
}
/** /**
* @name Constructor * @name Constructor
* *
* @description * @description
* Initialize the instance * Initialize the instance of Pechatalka
* *
* @param {HTMLElement} wrap The wrap element * @param {HTMLElement} wrap The wrap element
* @param {HTMLElement} canvas The canvas element * @param {HTMLElement} canvas The canvas element
* @param {HTMLElement} result The result element * @param {HTMLElement} result The result element
* @param {(Map|null)} [preset=null] Preset parameters for layers
* @param {boolean} [inject=false] Write the instance into the wrap element? * @param {boolean} [inject=false] Write the instance into the wrap element?
*/ */
constructor(wrap, canvas, result, inject = false) { constructor(wrap, canvas, result, preset, inject = false) {
if (wrap instanceof HTMLElement) { if (wrap instanceof HTMLElement) {
// Initialized the wrap element // Initialized the wrap element
@@ -178,20 +262,54 @@ export default class pechatalka {
// Writing the result // Writing the result
this.#result = result; this.#result = result;
} }
if (preset instanceof Map) {
// Received the preset registry
// Writing the preset registry
this.#preset = preset;
}
}
/**
* @name Global
*
* @description
* Write the parameter into all layers
*
* @param {string} name Name of the parameter
* @param {(Object|string|number|boolean|null)} [value=null] Value of the parameter
* @param {boolean} [preset=false] Reinitialize the parameter in the preset registry?
*/
global(name, value = null, preset = false) {
if (typeof name === "string") {
// Received required arguments
for (const layer of this.#layers) {
// Iterating over layers
// Reinitializing the layer parameter
layer.set(name, value);
}
if (preset) {
// Requested to reinitialize the parameter in the preset registry
// Writing the parameter into the preset registry
this.#preset.set(name, value);
}
}
} }
/** /**
* @name Moving * @name Moving
* *
* @description * @description
* Add moving for the target * Add moving for the layer
* *
* @param {HTMLElement} target * @param {layer} layer
*/ */
moving(target) { moving(layer) {
// Initializing the link to the canvas
const canvas = this.#canvas;
// Initializing the start moving cursor coordinates buffer // Initializing the start moving cursor coordinates buffer
const from = { x: 0, y: 0 }; const from = { x: 0, y: 0 };
@@ -200,10 +318,10 @@ export default class pechatalka {
*/ */
function moving(event) { function moving(event) {
// Writing the X coordinate // Writing the X coordinate
target.style.left = event.clientX - from.x + "px"; layer.wrap.style.left = event.clientX - from.x + "px";
// Writing the Y coordinate // Writing the Y coordinate
target.style.top = event.clientY - from.y + "px"; layer.wrap.style.top = event.clientY - from.y + "px";
} }
/** /**
@@ -211,7 +329,7 @@ export default class pechatalka {
*/ */
function restore() { function restore() {
// Restoring initial coordinates // Restoring initial coordinates
target.style.top = target.style.left = null; layer.wrap.style.top = layer.wrap.style.left = null;
} }
/** /**
@@ -223,8 +341,8 @@ export default class pechatalka {
// Writing the start moving cursor coordinates // Writing the start moving cursor coordinates
[from.x, from.y] = [ [from.x, from.y] = [
event.clientX - (parseInt(target.style.left) || 0), event.clientX - (parseInt(layer.wrap.style.left) || 0),
event.clientY - (parseInt(target.style.top) || 0) event.clientY - (parseInt(layer.wrap.style.top) || 0),
]; ];
// Initializing the event listener // Initializing the event listener
@@ -241,16 +359,16 @@ export default class pechatalka {
} }
// Initializing event listeners // Initializing event listeners
target.addEventListener("mousedown", start, false); layer.wrap.addEventListener("mousedown", start, false);
window.addEventListener("mouseup", end, false); window.addEventListener("mouseup", end, false);
canvas.addEventListener("mouseleave", end, false); this.#canvas.addEventListener("mouseleave", end, false);
} }
/** /**
* @name Scaling * @name Scaling
* *
* @description * @description
* Add resizing for the target * Add resizing for the layer
* *
* 1. Resizing by changing the `scale` parameter disables the buttons visibility * 1. Resizing by changing the `scale` parameter disables the buttons visibility
* outside the cut borders (`overflow: fixed` did not work) * outside the cut borders (`overflow: fixed` did not work)
@@ -258,10 +376,10 @@ export default class pechatalka {
* 2. Resizing by changing the `width` parameter has problems with boundaries, * 2. Resizing by changing the `width` parameter has problems with boundaries,
* that is it has movement glitches * that is it has movement glitches
* *
* @param {HTMLElement} target * @param {layer} layer
* @param {string} [type='scale'] Type of scaling (scale, width) * @param {string} [type='scale'] Type of scaling (scale, width)
*/ */
scaling(target, type = "scale") { scaling(layer, type = "scale") {
/** /**
* @name Scroll * @name Scroll
*/ */
@@ -270,32 +388,34 @@ export default class pechatalka {
// Scaling by changing scale // Scaling by changing scale
// Initializing new scale // Initializing new scale
let scale = (parseFloat(target.style.scale) || 1) + event.deltaY / 1000; let scale = (parseFloat(layer.wrap.style.scale) || 1) +
event.deltaY / 1000;
// Normalization and protection against out of scale boundaries // Normalization and protection against out of scale boundaries
if (scale < 0.4) scale = 0.4; if (scale < 0.4) scale = 0.4;
else if (scale > 3) scale = 3; else if (scale > 3) scale = 3;
// Writing the scale // Writing the scale
target.style.scale = scale; layer.wrap.style.scale = scale;
} else if (type === "width") { } else if (type === "width") {
// Scaling by changing width // Scaling by changing width
// Initializing the zoom changing value // Initializing the zoom changing value
const change = event.deltaY / 2; const change = event.deltaY / 1.5;
// Initializing width of the cut space // Initializing width of the cut space
const cut = target.parentElement.offsetWidth; const cut = target.parentElement.offsetWidth;
// Initializing bounds for zooming // Initializing bounds for zooming
const bounds = { const bounds = {
minimum: cut / 2 - cut, minimum: cut / 1.5 - cut,
maximum: cut * 2 - cut maximum: cut * 1.5 - cut,
}; };
// Initializing new scale // Initializing new scale
let zoom = let zoom =
(parseFloat(target.style.getPropertyValue("--width-zoom")) || 0) + (parseFloat(layer.wrap.style.getPropertyValue("--width-zoom")) ||
0) +
change; change;
if (zoom < bounds.minimum) zoom = bounds.minimum; if (zoom < bounds.minimum) zoom = bounds.minimum;
@@ -304,53 +424,46 @@ export default class pechatalka {
// The layer scale was changed // The layer scale was changed
// Writing the X coordinate // Writing the X coordinate
target.style.left = layer.wrap.style.left = (parseInt(layer.wrap.style.left) || 0) -
(parseInt(target.style.left) || 0) - change / 2 + "px"; change / 2 +
"px";
// Writing the Y coordinate // Writing the Y coordinate
target.style.top = layer.wrap.style.top = (parseInt(layer.wrap.style.top) || 0) -
(parseInt(target.style.top) || 0) - change / 2 + "px"; change / 2 +
"px";
} }
// Writing the scale // Writing the scale
target.style.setProperty("--width-zoom", zoom + "px"); layer.wrap.style.setProperty("--width-zoom", zoom + "px");
} }
} }
// Initializing the even listeners // Initializing the even listeners
target.addEventListener("wheel", scroll, false); layer.wrap.addEventListener("wheel", scroll, false);
} }
/** /**
* @name Image * @name Image
* *
* @description * @description
* Add the image into the canvas * Generate and write the image into the canvas
* *
* @param {File} file The file from input FileList * @param {File} file The file from input FileList
* @param {number} [cost=0] The layer cost
*/ */
image(file) { image(file, cost = 0) {
// Initializing identifier // Initializing identifier
const identifier = this.#layers.entries.length ?? 1; const identifier = this.#layers.size + 1;
// Creating the layer <div> element // Creating the layer wrap <div> element
const layer = document.createElement("div"); const wrap = document.createElement("div");
layer.classList.add("layer"); wrap.classList.add("layer");
layer.setAttribute("id", "pechatalka_layer_" + identifier); wrap.setAttribute("id", "pechatalka_layer_" + identifier);
// Creating the button <button> element // Creating the button <button> element
const button_delete = document.createElement("button"); const button_delete = document.createElement("button");
button_delete.classList.add("delete", "rounded"); button_delete.classList.add("delete");
button_delete.addEventListener("click", (event) => {
// Deleting the wrap
layer.remove();
// Removing from the total cost
this.#cost -= this.prices.pin.image ?? 0;
// Writing the total cost into the document
this.#result.querySelector(".cost").innerText = this.#cost;
});
// Creating the trash icon <i> element // Creating the trash icon <i> element
const trash = document.createElement("i"); const trash = document.createElement("i");
@@ -358,26 +471,358 @@ export default class pechatalka {
// Creating the image <img> element // Creating the image <img> element
const image = document.createElement("img"); const image = document.createElement("img");
image.classList.add("rounded");
image.setAttribute("draggable", false); image.setAttribute("draggable", false);
image.setAttribute("src", URL.createObjectURL(file)); image.setAttribute("src", URL.createObjectURL(file));
// Writing into the gallery // Writing into the gallery
layer.appendChild(image); wrap.appendChild(image);
button_delete.appendChild(trash); button_delete.appendChild(trash);
layer.appendChild(button_delete); wrap.appendChild(button_delete);
this.#canvas.appendChild(layer); this.#canvas.appendChild(wrap);
// Initializing the layer instance
const instance = new layer(
"image",
cost,
wrap,
image,
{
delete: button_delete,
},
this.#preset,
);
// Writing into the layers registry
this.#layers.add(instance);
// Processing the `layer create` event function
this.#events.get("layers")?.get("create")(instance);
// Adding to the total cost // Adding to the total cost
this.#cost += this.prices.pin.image ?? 0; this.cost += instance.cost;
// Writing the total cost into the document
this.#result.querySelector(".cost").innerText = this.#cost;
// Adding moving for the layer // Adding moving for the layer
this.moving(layer); this.moving(instance);
// Adding scaling for the layer // Adding scaling for the layer
this.scaling(layer); this.scaling(instance);
// Initializing the event listener function
button_delete.addEventListener("click", (event) => {
// Deleting the layer root element
instance.wrap.remove();
// Deleting from the layer registry
this.#layers.delete(instance);
// Substraction from the total cost
this.cost -= instance.cost;
});
}
}
export class layer {
/**
* @name Type
*
* @description
* The layr type
*
* @type {string}
*
* @protected
*/
#type;
/**
* @name Type (set)
*
* @description
* The layr type
*
* @public
*/
set type(value) {
// Initializing types of layers
const types = new Set(["image", "film"]);
// Writing the value
if (types.has(value)) this.#type = value;
}
/**
* @name Type (get)
*
* @description
* The layr type
*
* @return {string}
*
* @public
*/
get type() {
// Exit (success)
return this.#type;
}
/**
* @name Cost
*
* @description
* The layr cost
*
* @type {number}
*
* @protected
*/
#cost = 0;
/**
* @name Cost (set)
*
* @description
* The layer cost
*
* @return {number}
*
* @public
*/
set cost(value) {
if (typeof value === "number") {
// Validated the value
// Initializing the deprecated cost
const from = this.#cost;
// Writing the value
this.#cost = value;
// Filtering by the minimal value
if (this.#cost < 0) this.#cost = 0;
// Processing the `cost changed` event function
this.#events.get("cost")?.get("changed")(from, this.#cost);
}
}
/**
* @name Cost (get)
*
* @description
* The layer cost
*
* @return {number}
*
* @public
*/
get cost() {
return this.#cost;
}
/**
* @name Wrap
*
* @description
* The layer root element
*
* @type {HTMLElement}
*
* @protected
*/
#wrap;
/**
* @name Wrap (get)
*
* @description
* The layer root element
*
* @return {HTMLElement}
*
* @public
*/
get wrap() {
return this.#wrap;
}
/**
* @name Content
*
* @description
* The layer target content element
*
* @type {HTMLElement}
*
* @protected
*/
#content;
/**
* @name Content (get)
*
* @description
* The layer target content element
*
* @return {HTMLElement}
*
* @public
*/
get content() {
return this.#content;
}
/**
* @name Buttons
*
* @description
* The layer buttons elements registry
*
* @type {Map}
*
* @protected
*/
#buttons = new Map();
/**
* @name Buttons (get)
*
* @description
* The layer buttons elements registry
*
* @type {Map}
*
* @public
*/
get buttons() {
return this.#buttons;
}
/**
* @name Events
*
* @type {Map}
*
* @protected
*/
#events = new Map([
["cost", new Map([["changed", (to, from) => {}]])],
]);
/**
* @name Events (get)
*
* @type {Map}
*
* @public
*/
get events() {
return this.#events;
}
/**
* @name Constructor
*
* @description
* Initialize the instance of the layer
*
* @param {string} type The layer type
* @param {number} cost The layer cost
* @param {HTMLElement} wrap The layer root element
* @param {HTMLElement} content The layer target content element
* @param {object} buttons The layer buttons elements
* @param {Map} preset Preset parameters
* @param {boolean} [inject=false] Write the instance into the element?
*/
constructor(type, cost, wrap, content, buttons, preset, inject = false) {
// Writing the layer type
this.type = type;
if (typeof this.#type === "string") {
// Initialized the layer type
// Writing the layer cost
this.cost = cost;
if (wrap instanceof HTMLElement) {
// Received the layer root element
// Writing the layer root element
this.#wrap = wrap;
// Writing the instance into the layer root element
if (inject) this.#wrap.layer = this;
}
if (content instanceof HTMLElement) {
// Received the layer target content element
// Writing the layer target content element
this.#content = content;
}
if (buttons instanceof Object) {
// Received the layer buttons elements
for (const [name, element] of Object.entries(buttons)) {
// Iterating over the layers buttons elements
// Writing into the layer buttons registry
this.#buttons.set(name, element);
}
}
for (const [name, value] of preset.entries()) {
// Iterating over preset parameters
// Writing the parameter
this[name] = value;
}
}
}
/**
* @name Set
*
* @description
* Set the parameter value
*
* @param {string} name Name of the parameter
* @param {(Object|string|number|boolean|null)} value Value of the parameter
*
* @return {boolean} The new parameter value
*/
set(name, value) {
// Initializing the old parameter value
const from = this[name];
// Writing the value
this[name] = value;
// Processing the parameter `set` event function
this.#events.get(name)?.get("set")(this[name], from);
// Exit (success)
return this[name];
}
/**
* @name Toggle
*
* @description
* Toggle the parameter valu
*
* @param {string} name Name of the parameter
*
* @return {boolean} The new parameter value
*/
toggle(name) {
// Writing the value
this[name] = !this[name] ?? true;
// Processing the parameter `toggle` event function
this.#events.get(name)?.get("toggle")(this[name]);
// Exit (success)
return this[name];
} }
} }