Client: Channel box now underneath Nick input
[KiwiIRC.git] / server / modules.js
CommitLineData
1920a38e 1var events = require('events'),
991091b7
D
2 util = require('util'),
3 _ = require('lodash');
1920a38e
D
4
5
991091b7
D
6/**
7 * Publisher
8 * The main point in which events are fired and bound to
9 */
10
1920a38e
D
11// Where events are bound to
12var active_publisher;
13
14
15// Create a publisher to allow event subscribing
16function Publisher (obj) {
991091b7
D
17 var EventPublisher = function modulePublisher() {};
18 util.inherits(EventPublisher, events.EventEmitter);
1920a38e 19
991091b7 20 return new EventPublisher();
874f28a5 21}
1920a38e
D
22
23
24// Register an already created Publisher() as the active instance
25function registerPublisher (obj) {
991091b7
D
26 active_publisher = obj;
27}
28
29
30
31
32
33
34/**
35 * Keeping track of modules
36 */
37
38// Hold the loaded modules
39var registered_modules = {};
40
41function loadModule (module_file) {
42 var module;
43
44 // Get an instance of the module and remove it from the cache
45 try {
46 module = require(module_file);
47 delete require.cache[require.resolve(module_file)];
48 } catch (err) {
49 // Module was not found
50 return false;
51 }
52
53 return module;
1920a38e
D
54}
55
56
991091b7
D
57// Find a registered collection, .dispose() of it and remove it
58function unloadModule (module) {
59 registered_modules = _.reject(registered_modules, function (registered_module) {
60 if (module === registered_module) {
61 module.dispose();
62 return true;
63 }
64 });
65}
66
67
68
69
1920a38e 70
1920a38e 71
874f28a5
D
72/**
73 * Module object
74 * To be created by modules to bind to server events
75 */
991091b7
D
76function Module (module_name) {
77 registered_modules[module_name] = this;
78}
1920a38e 79
1920a38e 80
874f28a5
D
81// Holder for all the bound events by this module
82Module.prototype._events = {};
1920a38e 83
1920a38e 84
874f28a5 85// Keep track of this modules events and bind
991091b7
D
86Module.prototype.on = function (event_name, fn) {
87 var internal_events = ['dispose'];
88
89 this._events[event_name] = this._events[event_name] || [];
90 this._events[event_name].push(fn);
1920a38e 91
991091b7
D
92 // If this is an internal event, do not propogate the event
93 if (internal_events.indexOf(event_name) !== -1) {
94 active_publisher.on(event_name, fn);
95 }
874f28a5 96};
1920a38e 97
1920a38e 98
874f28a5
D
99// Keep track of this modules events and bind once
100Module.prototype.once = function (event_name, fn) {
991091b7
D
101 this._events[event_name] = this._events[event_name] || [];
102 this._events[event_name].push(fn);
874f28a5 103
991091b7 104 active_publisher.once(event_name, fn);
874f28a5 105};
1920a38e
D
106
107
874f28a5 108// Remove any events by this module only
991091b7
D
109Module.prototype.off = function (event_name, fn) {
110 var idx;
111
112 if (typeof event_name === 'undefined') {
113 // Remove all events
114 this._events = [];
115
116 } else if (typeof fn === 'undefined') {
117 // Remove all of 1 event type
118 delete this._events[event_name];
119
120 } else {
121 // Remove a single event + callback
122 for (idx in (this._events[event_name] || [])) {
123 if (this._events[event_name][idx] === fn) {
124 delete this._events[event_name][idx];
125 }
126 }
127 }
128
129 active_publisher.removeListener(event_name, fn);
874f28a5 130};
1920a38e
D
131
132
991091b7 133
874f28a5
D
134// Clean up anything used by this module
135Module.prototype.dispose = function () {
991091b7
D
136 // Call any dispose callbacks
137 (this._events['dispose'] || []).forEach(function (callback) {
138 callback();
139 });
140
141 // Remove all bound event listeners
142 this.off();
1920a38e
D
143};
144
145
146
874f28a5
D
147
148
149
1920a38e 150module.exports = {
991091b7
D
151 // Objects
152 Module: Module,
153 Publisher: Publisher,
154
155 // Methods
156 registerPublisher: registerPublisher,
157 load: loadModule,
158 unload: unloadModule,
159 getRegisteredModules: function () { return registered_modules; }
1920a38e 160};