#include utility.js var AmiWatcher = function() { var 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(var i in watchers) watchers[i].apply(thisArg, args); }, }; }; var AmiWatcherCollection = function() { var collection = new Map; var watch = function(name, watcher, thisArg, args) { var watchers = collection.get(name); if(watchers === undefined) throw 'undefined watcher name'; watchers.watch(watcher, thisArg, args); }; var unwatch = function(name, watcher) { var 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(var i in names) collection.set(names[i], new AmiWatcher); }, call: function(name, thisArg, args) { var 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; }, }; };