137 lines
3.4 KiB
JavaScript
137 lines
3.4 KiB
JavaScript
import Emitter from './Emitter';
|
|
import Logger from './Logger';
|
|
class Cetra extends Emitter {
|
|
// class static globals
|
|
static #instances = new Map();
|
|
static #uidIndex = new Set();
|
|
static #defaultSettings = new Map([
|
|
['selector', 'ctra'],
|
|
['root', document.body],
|
|
#identifier;
|
|
#internals = new Map([
|
|
['settings', new Map()],
|
|
]);
|
|
|
|
/**
|
|
* Constructs a new instance of the Cetra framework.
|
|
* @class
|
|
* @classdesc The Cetra framework provides a reactive approach to DOM manipulation and component management.
|
|
* @param {Map} settings - A map object containing the framework settings.
|
|
*/
|
|
constructor(options = new Map()) {
|
|
super();
|
|
this.#identifier = this.uid();
|
|
this.#init();
|
|
}
|
|
|
|
/**
|
|
* Retrieves an instance of Cetra by its ID.
|
|
* @param {string} id - The ID of the Cetra instance to retrieve.
|
|
* @returns {Cetra} The Cetra instance with the specified ID.
|
|
*/
|
|
static getInstance(id) {
|
|
return Cetra.#instances.get(id);
|
|
}
|
|
|
|
/**
|
|
* Initializes the Cetra framework by setting up the mutation observer and processing existing components.
|
|
* @memberof Cetra
|
|
* @instance
|
|
* @method
|
|
*/
|
|
#init() {
|
|
this.#root =
|
|
this.#internals.get('settings').get('root') ||
|
|
document.querySelector(this.#internals.get('settings').get('root'));
|
|
|
|
if (typeof this.#root == 'string') {
|
|
this.#root = document.querySelector(this.#root);
|
|
|
|
if (!this.#root) {
|
|
Logger.error('No root found, defaulting to body');
|
|
this.#root = document.body;
|
|
}
|
|
}
|
|
|
|
this.#registerDefaults();
|
|
|
|
this.#root.setAttribute(
|
|
`data-${this.#internals.get('settings').get('selector')}-id`,
|
|
this.#identifier
|
|
);
|
|
|
|
Cetra.#instances.set(this.#identifier, this);
|
|
this.emit('afterInit', this);
|
|
}
|
|
|
|
/**
|
|
* Registers default properties, transformer or anything related to the functionality
|
|
* @returns {void}
|
|
*/
|
|
#registerDefaults() {
|
|
}
|
|
|
|
/**
|
|
* checks if the given url is valid
|
|
* @param {String} url the url to check
|
|
* @returns {Boolean} true if the url is valid, false otherwise
|
|
*/
|
|
#isUrl(url) {
|
|
if (typeof url != 'string') return false;
|
|
try {
|
|
// if there is no error this should be a valid url
|
|
const urlObj = new URL(url, window.location.href);
|
|
return this.#internals.get('settings').get('enforceSecureUrls')
|
|
? urlObj.protocol === 'https:'
|
|
: true;
|
|
} catch (err) {
|
|
// any error is a bad url
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates a (internally)unique identifier.
|
|
* @param {number} [numGroups=1] - The number of groups to generate.
|
|
* @param {number} [groupLength=6] - The length of each group.
|
|
* @memberof Cetra
|
|
* @method
|
|
* @returns {string} The unique identifier.
|
|
*/
|
|
uid(numGroups = 1, groupLength = 6) {
|
|
const usedIds = new Set(Cetra.#uidIndex.values());
|
|
|
|
let uid = undefined;
|
|
|
|
while (!uid || usedIds.has(uid)) {
|
|
uid = Array.from(Array(numGroups), () =>
|
|
Math.random()
|
|
.toString(36)
|
|
.substring(2, groupLength + 2)
|
|
).join('');
|
|
}
|
|
|
|
Cetra.#uidIndex.add(uid);
|
|
|
|
return uid;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the value of the specified option from the framework's settings.
|
|
* @memberof Cetra
|
|
* @instance
|
|
* @method
|
|
* @param {string} option - The name of the option to retrieve.
|
|
* @returns {*} The value of the specified option.
|
|
*/
|
|
getOption(key) {
|
|
if (typeof key != 'string')
|
|
throw new Error('given key is not a string!');
|
|
return this.#internals
|
|
.get('settings')
|
|
.get(key.toString().toLowerCase());
|
|
}
|
|
}
|
|
|
|
export default Cetra;
|