minsky-kit
Version:
Kit of components for MINSKY web agency
183 lines (144 loc) • 5.24 kB
JavaScript
// imports
import EventDispatcher from './EventDispatcher';
import Ticker from './Ticker';
import MQDefinition from './MQDefinition';
// private static
// class definition
export default class MQManager extends EventDispatcher {
// constructor
constructor (args = {}, objectName = 'MQ MGR') {
args.debug = args.debug || false;
// call super constructor
super(args, objectName);
// set properties
this._definitions = [];
this._matchChangedDefinitions = [];
// debouncer
this.debouncer = new Ticker({
timeout: args.debounce || 0,
});
// prep some listeners
this.blm.add('onMqMatchChange', onMqMatchChange);
this.blm.add('onMqWeightChange', onMqWeightChange);
// add listeners
this.debouncer.on('timeout', this.blm.add('onDebounceTimeout', onDebounceTimeout));
}
// methods
add (mqDefinitions) {
this.log('add', mqDefinitions);
// force it to be an array
mqDefinitions = forceArray(mqDefinitions);
// create instances or just add them if they are already an instance
mqDefinitions.forEach((definition) => {
// make sure it's an instance
if (!instanceOfMQDefinition(definition)) {
// clone definition for altering
const defClone = { ...definition };
// force debug state
defClone.debug = this._debug;
// use clone defintiion to create instance
definition = new MQDefinition(defClone);
}
// add listeners
definition.on('matchChange', this.blm.get('onMqMatchChange'));
definition.on('weightChange', this.blm.get('onMqWeightChange'));
// apply weight if none is given
if (!definition.weight) {
definition.weight = this._definitions.length ? this._definitions[this._definitions.length - 1].weight + 1 : 0;
}
// add to list
this._definitions.push(definition);
});
// re-order list by weight
fixOrderOfDefinitions(this._definitions);
}
get (mqDefinition) {
if (!instanceOfMQDefinition(mqDefinition)) {
const keys = Object.keys(mqDefinition);
return this._definitions.filter((def) => {
for (const k of keys) {
if (this.mqDefinitions[k] !== def[k]) return false;
}
return [];
});
}
if (this._definitions.indexOf(mqDefinition)) {
return [mqDefinition];
}
return [];
}
remove (mqDefinitions) {
this.log('remove', mqDefinitions);
// force it to be an array
mqDefinitions = forceArray(mqDefinitions);
for (const def of mqDefinitions) {
if (!instanceOfMQDefinition(def)) {
if (this.get(def).length) {
this.log('Given definition was not a correct instance, filtering will be done + all matching will be removed.');
this.remove(def);
}
}
else {
const index = this._definitions.indexOf(def);
if (index > -1) this._definitions.splice(index, 1);
}
}
// re-order list by weight
fixOrderOfDefinitions(this._definitions);
}
check () {
this.log('check');
this._definitions.forEach((def) => def.check());
}
resetMatches () {
this.log('reset matches');
this._definitions.forEach((def) => def.resetMatch());
}
destroy () {
// call super
super.destroy();
}
// statics
get matchingDefinitions () {
return this._definitions.filter((def) => def.matches);
}
}
// utils
function fixOrderOfDefinitions (definitions) {
// re-order list by weight
return definitions.sort((def1, def2) => def1.weight - def2.weight);
}
function instanceOfMQDefinition (definition) {
return definition instanceof MQDefinition;
}
function forceArray (item) {
if (!Array.isArray(item)) item = [item];
return item;
}
function dispatchMatchChanges () {
this.dispatch('matchChanges', {
definitions: fixOrderOfDefinitions(this._matchChangedDefinitions.slice()),
});
// reset length for new list
this._matchChangedDefinitions.length = 0;
}
// event handlers
function onMqMatchChange (e) {
this.log('MQ Match Change', e.currentTarget.name, e.currentTarget._query);
// keep definition for debounced dispatch, make sure it happens only once
if (this._matchChangedDefinitions.indexOf(e.currentTarget) === -1) this._matchChangedDefinitions.push(e.currentTarget);
// instant dispatch
this.dispatch('singleMatchChange', {
definition: e.currentTarget,
});
// start debouncer
this.debouncer.start(true);
}
function onMqWeightChange (e) {
this.log('MQ Weight Change', e.currentTarget.name, e.currentTarget._query);
// re-order items
fixOrderOfDefinitions(this._definitions);
}
function onDebounceTimeout () {
dispatchMatchChanges.call(this);
}