Open donmccurdy opened 7 years ago
Untested implementation:
var FilteredEventListener = require('./FilteredEventListener');
var DEFAULT_LISTENER = {
listen: function () {},
unlisten: function () {},
expression: ''
};
var name = 'event';
var defaultValue = DEFAULT_LISTENER;
var parse = (function () {
var memo = {};
return function parse (string) {
string = string.trim();
if (!string) return DEFAULT_LISTENER;
if (!memo[string]) {
memo[string] = new FilteredEventListener(string);
}
return memo[string];
};
}());
var stringify = function stringify (listener) {
return listener.input;
};
module.exports = AFRAME.registerPropertyType(name, defaultValue, parse, stringify);
var expr = require('expression-eval');
function FilteredEventListener (input) {
this.input = input;
var parts = input.match(/^([^|]+)(?: \|(.*))?$/);
this.type = parts[1];
this.expression = parts[2];
if (!this.type) {
throw new Error('[filtered-event] Could not parse: "' + input + '"');
}
if (this.expression) {
this.evaluator = expr.compile(this.expression);
} else {
this.evaluator = function () { return true; };
}
this.nodeMap = new WeakMap();
this.nodeCounter = 0;
this.callbackMap = new WeakMap();
this.callbackCounter = 0;
this.listenerMap = new Map();
}
FilteredEventListener.prototype.listen = function (el, callback) {
var listeners = this.getListeners(el, callback);
var listener = function (e) {
if (this.evaluator(e)) callback(e);
}.bind(this);
el.addEventListener(this.type, listener);
listeners.push(listener);
};
FilteredEventListener.prototype.unlisten = function (el, callback) {
var listeners = this.getListeners(el, callback);
listeners.forEach(function(listener) {
el.removeEventListener(this.type, listener);
}.bind(this));
listeners.length = 0;
};
FilteredEventListener.prototype.getListeners = function (el, callback) {
var nodeID = String(this.nodeMap.get(el) || ++this.nodeCounter);
this.nodeMap.set(el, nodeID);
var callbackID = String(this.callbackMap.get(callback) || ++this.callbackCounter);
this.callbackMap.set(callback, callbackID);
var listenerID = nodeID + ':' + callbackID;
if (!this.listenerMap.has(listenerID)) {
this.listenerMap.set(listenerID, []);
}
return this.listenerMap.get(listenerID);
};
module.exports = FilteredEventListener;
Done on branch, usefulness TBD: https://github.com/donmccurdy/aframe-extras/tree/feat-state-machine
Nice feature to have would be: