minsky-kit
Version:
Kit of components for MINSKY web agency
223 lines (182 loc) • 5.9 kB
JavaScript
// imports
import _pullAll from 'lodash/pull';
import _clone from 'lodash/clone';
import EventDispatcher from './EventDispatcher';
// private statics
// class definition
export default class InstanceManager extends EventDispatcher {
// constructor
constructor (args = {}, objectName = 'InstanceManager') {
args.debug = args.debug || false;
// super
super(args, objectName);
// set properties
this._instances = {};
}
// methods
add (key, ...instances) {
// process instances array
instances = processInstancesParam(instances);
// ensure key's existence
if (!this._instances[key]) this._instances[key] = [];
// get list by key
const list = this._instances[key];
// push given instances to list
list.push(...instances);
}
addOnce (key, ...instances) {
// process instances array
instances = processInstancesParam(instances);
// get list
const list = this._instances[key];
if (list) {
instances.forEach((instance) => {
if (list.indexOf(instance) > -1) list.push(instance);
});
}
else {
this.add(key, ...instances);
}
}
initAdd (key, Class, params = {}) {
this.add(key, new Class(params));
}
initAddOnce (key, Class, params = {}) {
if (!this.get(key).length) {
this.add(key, Class, params);
}
}
initAddComponent (key, Class, itemList, params = {}, $parent = null) {
// ensure parent
if (!$parent) $parent = document;
// make sure its
if (typeof itemList === 'string') {
itemList = $parent.querySelectorAll(itemList);
}
// convert into an array list
if (!Array.isArray(itemList)) {
if (itemList.length !== undefined) {
itemList = Array.from(itemList);
}
else {
itemList = [itemList];
}
}
// init all & keep
itemList.forEach(($item) => {
// Process params
const processedParam = ((typeof params === 'function') ? params($item) : _clone(params));
// provide $el if not yet set (could be overridden externally by adding a value)
if (processedParam.$el === undefined) processedParam.$el = $item;
// addInit instance
this.initAdd(key, Class, processedParam);
});
}
get (key) {
return this._instances[key] || [];
}
run (keys, prop, ...values) {
// process key parameter
keys = processKeys(keys);
// run over all given keys
keys.forEach((key) => {
// grab list
const list = this._instances[key];
// loop over list if it exists & apply
if (list) {
switch (true) {
case typeof prop === 'function':
list.forEach((instance) => {
prop(instance, ...values);
});
break;
case typeof prop === 'object':
list.forEach((instance) => {
Object.keys(prop).forEach((k) => {
assignValueToProp(instance, k, prop[k]);
});
});
break;
default:
list.forEach((instance) => {
assignValueToProp(instance, prop, ...values);
});
}
}
});
}
runDispatchers (keys, event, data = {}, process = null) {
// shortcut to keep things tidy and readable in classes
this.run(keys, 'dispatch', event, data, process);
}
clear (key) {
if (this._instances[key]) this._instances[key].length = 0;
}
remove (keys, ...instances) {
// process instances array
keys = processKeys(keys);
instances = processInstancesParam(instances);
keys.forEach((key) => {
// get list
const list = this._instances[key];
// find & remove instance from list
if (list) {
if (!instances.length) {
list.length = 0;
}
else if (instances.length) {
_pullAll(list, instances);
}
}
});
}
destroy (keys) {
// process keys
keys = processKeys(keys);
// destroy instances
if (keys && keys.length) {
this.run(keys, 'destroy');
this.remove(keys);
}
// full destroy
else {
// clear instances
Object.keys(this._instances).forEach((list) => {
list.length = 0;
});
this._instances = null;
// super destroy
super.destroy();
}
}
// getters & setters
get instances () {
// shallow copy
return { ...this._instances };
}
}
// Utils
function processInstancesParam (instances) {
if (!Array.isArray(instances)) {
instances = [instances];
}
else if (instances.length === 1 && Array.isArray(instances[0])) {
instances = instances[0];
}
return instances;
}
function processKeys (keys) {
if (!Array.isArray(keys)) keys = [keys];
return keys;
}
function assignValueToProp (instance, prop, ...values) {
const currentValue = instance[prop];
if (typeof currentValue === 'function') {
instance[prop](...values);
}
else {
// should always be just 1 in this case
instance[prop] = values[0];
}
}
// Event handlers