misuzu/assets/js/misuzu/watcher.js

84 lines
2.3 KiB
JavaScript

const MszWatcher = function() {
let watchers = [];
return {
watch: function(watcher, thisArg, args) {
if(typeof watcher !== 'function')
throw 'watcher must be a function';
if(watchers.indexOf(watcher) >= 0)
return;
watchers.push(watcher);
if(thisArg !== undefined) {
if(!Array.isArray(args)) {
if(args !== undefined)
args = [args];
else args = [];
}
// initial call
args.push(true);
watcher.apply(thisArg, args);
}
},
unwatch: function(watcher) {
$ari(watchers, watcher);
},
call: function(thisArg, args) {
if(!Array.isArray(args)) {
if(args !== undefined)
args = [args];
else args = [];
}
args.push(false);
for(const watcher of watchers)
watcher.apply(thisArg, args);
},
};
};
const MszWatcherCollection = function() {
const collection = new Map;
const watch = function(name, watcher, thisArg, args) {
const watchers = collection.get(name);
if(watchers === undefined)
throw 'undefined watcher name';
watchers.watch(watcher, thisArg, args);
};
const unwatch = function(name, watcher) {
const watchers = collection.get(name);
if(watchers === undefined)
throw 'undefined watcher name';
watchers.unwatch(watcher);
};
return {
define: function(names) {
if(!Array.isArray(names))
names = [names];
for(const name of names)
collection.set(name, new MszWatcher);
},
call: function(name, thisArg, args) {
const watchers = collection.get(name);
if(watchers === undefined)
throw 'undefined watcher name';
watchers.call(thisArg, args);
},
watch: watch,
unwatch: unwatch,
proxy: function(obj) {
obj.watch = function(name, watcher) {
watch(name, watcher);
};
obj.unwatch = unwatch;
},
};
};