diff --git a/public/js/bootstrap.js b/public/js/bootstrap.js
index f109547..f012f80 100644
--- a/public/js/bootstrap.js
+++ b/public/js/bootstrap.js
@@ -25,6 +25,10 @@ fandango.defaults({
 // Require main cryptalk module.
 require(['cryptalk'], function () {}, function (e) {
 	document.getElementById('chat').innerHTML = '<li><i class="fatal">Fatal: An error was thrown during initialization causing the application to stop.<br>Examine the logs for more details.</i></li>';
-	console.log && console.log(e);
+
+	if (console.log) {
+		console.log(e);
+	}
+	
 	throw e;
 });
\ No newline at end of file
diff --git a/public/js/cryptalk_modules/$.js b/public/js/cryptalk_modules/$.js
index 71492ce..ad482fe 100644
--- a/public/js/cryptalk_modules/$.js
+++ b/public/js/cryptalk_modules/$.js
@@ -30,7 +30,7 @@ define(['fandango', 'websocket', 'aes'], function (fandango, websocket, aes) {
 		} else {
 			selector = selector.slice(1);
 
-			if (match = document.getElementById(selector)) {
+			if ((match = document.getElementById(selector))) {
 				matches.push(match);
 			}
 		}
@@ -69,7 +69,7 @@ define(['fandango', 'websocket', 'aes'], function (fandango, websocket, aes) {
 
 	utils.activeElement = function () {
 		try { return document.activeElement; } catch (e) {}
-	}
+	};
 
 	/**
 	 * Removes all characters but 0 - 9 from given string.
diff --git a/public/js/cryptalk_modules/audio.js b/public/js/cryptalk_modules/audio.js
index ce8fa9f..b1a1304 100644
--- a/public/js/cryptalk_modules/audio.js
+++ b/public/js/cryptalk_modules/audio.js
@@ -1,8 +1,8 @@
 /* Usage:
  
-	channel.emit('audio:play',message);
-	channel.emit('audio:on');
-	channel.emit('audio:off');
+	mediator.emit('audio:play',message);
+	mediator.emit('audio:on');
+	mediator.emit('audio:off');
  
 */
  
@@ -12,8 +12,6 @@ define(['queue','mediator'], function (queue,mediator) {
 	var ac = false,
 		enabled = true,
  
-		channel = mediator(),
- 
 		// Recursive function for playing tones, takes an array of [tone,start_ms,duration_ms] - entries
 		// i is only used for recursion
 		playTones = function (tones, i) {
@@ -22,7 +20,9 @@ define(['queue','mediator'], function (queue,mediator) {
 			i = (i === undefined) ? 0 : i;
  
 			// Stop if we've reached the end of iteration, and require ac
-			if( !(i < Object.keys(tones).length) || !ac || !enabled ) return;
+			if (!ac || !enabled || !(i < Object.keys(tones).length)) {
+				return;
+			}
  
 			// Add tones to execution queue
 			var 	current_tones = tones[i],
@@ -58,10 +58,12 @@ define(['queue','mediator'], function (queue,mediator) {
 			enabled = false;
 		};
  
-	if( window.AudioContext || window.webkitAudioContext ) ac = new ( window.AudioContext || window.webkitAudioContext );
+	if (window.AudioContext || window.webkitAudioContext) {
+		ac = new (window.AudioContext || window.webkitAudioContext);
+	}
  
-	channel.on('audio:play',function(message) { playTones(message) });
-	channel.on('audio:on',function(message) { on(); });
-	channel.on('audio:off',function(message) { off(); });
+	mediator.on('audio:play', function (message) { playTones(message); });
+	mediator.on('audio:on', function (message) { on(); });
+	mediator.on('audio:off', function (message) { off(); });
  
 });
\ No newline at end of file
diff --git a/public/js/cryptalk_modules/cryptalk.js b/public/js/cryptalk_modules/cryptalk.js
index da8783d..817c304 100644
--- a/public/js/cryptalk_modules/cryptalk.js
+++ b/public/js/cryptalk_modules/cryptalk.js
@@ -1,9 +1,8 @@
 // Main cryptalk module
 define({
 	compiles: ['$'],
-	requires: ['mediator','hosts', 'templates', 'audio', 'fandango','notifications','sounds','win']
+	requires: ['mediator','hosts', 'templates', 'audio', 'fandango','notifications', 'sounds', 'win']
 }, function ($, requires, data) {
-
 	var socket,
 		key,
 		host,
@@ -29,9 +28,9 @@ define({
 		// Shortcut
 		hosts = requires.hosts,
 		fandango = requires.fandango,
+		mediator = requires.mediator,
 		templates = requires.templates,
 		sounds = requires.sounds,
-		channel = requires.mediator(),
 		win = requires.win,
 
 		lockInput = function () {
@@ -51,7 +50,7 @@ define({
 				icon = (type == 'message') ? 'gfx/icon_128x128.png' : (type == 'error') ? 'gfx/icon_128x128_error.png' : 'gfx/icon_128x128_info.png';
 
 			// Emit notification
-			channel.emit('notification:send', 
+			mediator.emit('notification:send', 
 				{ 
 					title: 	title.substring(0, 20), 
 					body: 	text.substring(0, 80), 
@@ -59,7 +58,7 @@ define({
 				});
 
 			// Emit sound
-			if ( type == 'message' ) channel.emit('audio:play',sounds.message);
+			if ( type == 'message' ) mediator.emit('audio:play',sounds.message);
 		
 		},
 
@@ -81,7 +80,7 @@ define({
 				clearInput();
 			}
 
-			showNotification(type, nick, text)
+			showNotification(type, nick, text);
 
 			// Append the post to the chat DOM element
 			components.chat[clearChat ? 'html' : 'append'](post);
@@ -117,14 +116,14 @@ define({
 								post('info', strhosts);
 								done();
 							}
-						}
+						};
 					};
 
 				// 
 				force = (force && force.toLowerCase() === 'force');
 
 				// Loop through all the hosts
-				while (host = hosts.hosts[i]) {
+				while ((host = hosts.hosts[i])) {
 					if (!force && host.settings !== undefined) {
 						if (host.settings) {
 							callback(host, i, 1)();
@@ -150,7 +149,7 @@ define({
 				}
 
 				if ($.isDigits(toHost)) {
-					if (host = hosts.hosts[+toHost]) {
+					if ((host = hosts.hosts[+toHost])) {
 						if (host.settings) {
 							settings = host.settings;
 						} else {
@@ -213,7 +212,7 @@ define({
 					.on('message:send', function (data) {
 						var decrypted = $.AES.decrypt(data.msg, room + key),
 							sanitized = $.escapeHtml(decrypted),
-							nick = 		(data.nick == undefined || !data.nick ) ? templates.default_nick : $.escapeHtml($.AES.decrypt(data.nick, room + key));
+							nick = 		!data.nick ? templates.default_nick : $.escapeHtml($.AES.decrypt(data.nick, room + key));
 
 						if (!decrypted) {
 							post('error', templates.messages.unable_to_decrypt);
@@ -274,7 +273,7 @@ define({
 			reconnect: function (foo, done) {
 				if (host) {
 					if (host.connected) {
-						commands.disconnect()
+						commands.disconnect();
 						commands.connect(host, done);
 					} else {
 						commands.connect(host, done);
@@ -503,7 +502,7 @@ define({
 				socket.emit('message:send', {
 					room: room,
 					msg: $.AES.encrypt(buffer, room + key).toString(),
-					nick: (nick && nick != undefined) ? $.AES.encrypt(nick, room + key).toString() : false
+					nick: nick ? $.AES.encrypt(nick, room + key).toString() : false
 				});
 
 				// And clear the the buffer
@@ -524,13 +523,13 @@ define({
 	post('motd', templates.motd, true);
 
 	// Route mediator messages
-	channel.on('window:focused',function() {
-		channel.emit('audio:off');
-		channel.emit('notification:off');
+	mediator.on('window:focused',function() {
+		mediator.emit('audio:off');
+		mediator.emit('notification:off');
 	});
-	channel.on('window:blurred',function() {
-		if( !mute ) channel.emit('audio:on');
-		channel.emit('notification:on');
+	mediator.on('window:blurred',function() {
+		if( !mute ) mediator.emit('audio:on');
+		mediator.emit('notification:on');
 	});
 
 	unlockInput();
diff --git a/public/js/cryptalk_modules/mediator.js b/public/js/cryptalk_modules/mediator.js
index d2b52d3..eb9e4f0 100644
--- a/public/js/cryptalk_modules/mediator.js
+++ b/public/js/cryptalk_modules/mediator.js
@@ -1 +1,188 @@
-define(function(){function f(d,a,b){var c=e[d],g=c.length,h=g,f=h,k=[],l=b?function(a){a&&k.push(a);!--h&&b(k,g)}:m;if(c)for(;d=c[--f];)d[1](a,l),2>d[1].length&&h--;else b&&b(k,g)}var l=0,e={},m=function(){};return function(){var d=l++;return{emit:function(a,b,c){f(a,b,c);return this},on:function(a,b){(e[a]||(e[a]=[])).push([d,b]);return this},off:function(a){var b=0,c=e[a];if(c)for(;a=c[b++];)a[0]===d&&c.splice(--b,1);return this}}}});
+(function (self, factory) {
+    if (typeof define === 'function' && define.amd) {
+    	// AMD. Register as an anonymous module.
+        define([], factory);
+    } else if (typeof exports === 'object') { // Node
+        module.exports = factory();
+    } else {
+    	// Attaches to the current context
+        self.castrato = factory;
+  	}
+}(this, (function () {
+	var
+		/**
+		 * Contains the next unique node id.
+		 *
+		 * @property index
+		 * @type {Integer}
+		 * @private
+		 */
+		index = 0,
+
+		/**
+		 * Contains all subscriptions
+		 *
+		 * @property subs
+		 * @type {Object}
+		 * @private
+		 */
+		subs = {},
+
+		/**
+		 * An empty function.
+		 * This method does not accept any arguments.
+		 * 
+		 * @property noop
+		 * @type {function}
+		 * @private
+		 */
+		noop = function () {};
+
+	/**
+	 * Creates a new entry in the `subs` object.
+	 *
+	 * @method on
+	 * @private
+	 * @param {Integer} fromId The unique subscriber ID.
+	 * @param {String} event The event to subscribe to.
+	 * @param {Function} func A function to execute when the event is triggered.
+	 */
+	function on (fromId, event, func) {
+		(subs[event] || (subs[event] = [])).push([fromId, func, func.length]);
+	}
+
+	/**
+	 * Removes all event handlers originating from `fromId` and optionally filter by handler.
+	 *
+	 * @method off
+	 * @private
+	 * @param {Integer} fromId The unique subscriber ID.
+	 * @param {String} event The event to unsubscribe from.
+	 * @param {Function} [func=null] The original handler that was attached to this event. If not passed, all subscriptions will be removed.
+	 */
+	function off (fromId, event, func) {
+		var sub,
+			i = 0,
+			toSubs = subs[event];
+
+		if (toSubs) {
+			while ((sub = toSubs[i++])) {
+				if (sub[0] === fromId && (!func || func === sub[1])) {
+					toSubs.splice(--i, 1);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Loops through all subscriptions, calling all handlers attached to given `event`.
+	 *
+	 * @method emit
+	 * @private
+	 * @param {Integer} fromId The unique subscriber ID.
+	 * @param {String} event The event to emit
+	 * @param {Object} [data=undefined] Parameters to pass along to the event handler.
+	 * @param {Function} [func=undefined] A function to execute when all event handlers has returned.
+	 */
+	function emit (persistent, event, data, func) {
+		var sub,
+			toSubs = subs[event] || [],
+			total = toSubs.length,
+			left = total,
+			loop = total,
+			answers = [],
+			done;
+
+		if (loop) {
+			done = !func ? noop : function (data) {
+				if (data) {
+					answers.push(data);
+				}
+
+				if (!--left) {
+					func(answers, total);
+					func = 0;
+				}
+			};
+
+			while ((sub = toSubs[--loop])) {
+				sub[1](data, (sub[2] > 1) ? done : left--);
+			}
+		}
+
+		// `func` get destructed when called.
+		// It has to be called at least once - even if no one was subscribing.
+		// Execute it if it still exists.
+		if (func) {
+			func(answers, total);
+		}
+	}
+
+	return function () {
+		var nodeId = index++;
+
+		return {
+			/**
+			 * Execute all handlers attached to the given event.
+			 *
+			 * @method emit
+			 * @param {String} event The event to emit
+			 * @param {Object} [data=undefined] Parameters to pass along to the event handler.
+			 * @param {Function} [func=undefined] A function to execute when all event handlers has returned.
+			 * @return {Object} `this`
+			 * @example
+			 * 	$.emit('something');
+			 * 	$.emit('something', { foo: 'bar' });
+			 * 	$.emit('something', { foo: 'bar' }, function (data, subscribers) {
+			 * 		console.log('Emit done, a total of ' + subscribers + ' subscribers returned: ', data);
+			 * 	});
+			 */
+			emit: function (persistent, event, data, func) {
+				// emit('something', { data: true }, function () {});
+				if (persistent !== true || persistent !== false) {
+					func = data;
+					data = event;
+					event = persistent;
+					persistent = false;
+				}
+
+				emit(persistent, event, data, func);
+
+				return this;
+			},
+
+			/**
+			 * Attach an event handler function for one event.
+			 *
+			 * @method on
+			 * @param {String} event The event to subscribe to.
+			 * @param {Function} func A function to execute when the event is triggered.
+			 * @return {Object} `this`
+			 * @example
+			 * 	$.on('something', function (data) {
+			 * 		console.log('Got something!', data);
+			 * 	});
+			 */
+			on: function (event, func) {
+				on(nodeId, event, func);
+				return this;
+			},
+
+			/**
+			 * Removes an event handler function for one event.
+			 *
+			 * @method off
+			 * @param {String} event The event to unsubscribe from.
+			 * @param {Function} [func=null] The original handler that was attached to this event. If not passed, all subscriptions will be removed.
+			 * @return {Object} `this`
+			 * @example
+			 * 	$.off('something');
+			 * 	$.off('something else', handler);
+			 */
+			off: function (event) {
+				off(nodeId, event);
+				return this;
+			}
+		};
+	};
+}())));
\ No newline at end of file
diff --git a/public/js/cryptalk_modules/notifications.js b/public/js/cryptalk_modules/notifications.js
index 3125bc0..017b78a 100644
--- a/public/js/cryptalk_modules/notifications.js
+++ b/public/js/cryptalk_modules/notifications.js
@@ -2,20 +2,20 @@
 Usage
 
 	// Send an notification
-	channel.emit('notification:send',{
+	mediator.emit('notification:send',{
 		title: 'Woop',
 		body: 'Woop woop',
 		icon: 'gfx/icon.png'
 	});
 
 	// Turn notifications on
-	channel.emit('notification:on');
+	mediator.emit('notification:on');
 
 	// Turn notifications off
-	channel.emit('notification:off');
+	mediator.emit('notification:off');
 
 */
-define(['mediator','win'],function (mediator,win){
+define(['mediator','win'],function (mediator, win){
  
 	var enabled = true,
  
@@ -26,8 +26,6 @@ define(['mediator','win'],function (mediator,win){
 		blink_timer,
 		interval,
 
-		channel = mediator(),
-
 		now = function () {
 			return performance.now() || Date.now();
 		},
@@ -104,9 +102,9 @@ define(['mediator','win'],function (mediator,win){
 	 
 	native_supported = (window.Notification !== undefined);
 
-	channel.on('notification:send',function(data) { notify(data.title,data.body,data.icon,true); });
-	channel.on('notification:on',function() { on(); });
-	channel.on('notification:off',function() { off(); });
+	mediator.on('notification:send',function(data) { notify(data.title,data.body,data.icon,true); });
+	mediator.on('notification:on',function() { on(); });
+	mediator.on('notification:off',function() { off(); });
 
  	enableNative();
 
diff --git a/public/js/cryptalk_modules/win.js b/public/js/cryptalk_modules/win.js
index e787675..161f9c5 100644
--- a/public/js/cryptalk_modules/win.js
+++ b/public/js/cryptalk_modules/win.js
@@ -12,14 +12,13 @@
 define(['mediator'],function (mediator){
  
 	var exports = {},
-		channel = mediator(),
 
 		focusCallback = function() {
-			channel.emit('window:focused');
+			mediator.emit('window:focused');
 		},
  
 		blurCallback = function() {
-			channel.emit('window:blurred');
+			mediator.emit('window:blurred');
 		};
 
 	exports.setTitle = function(t) 	{ document.title = t; },
diff --git a/public/js/cryptalk_modules/window.js b/public/js/cryptalk_modules/window.js
deleted file mode 100644
index 115c35e..0000000
--- a/public/js/cryptalk_modules/window.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-
-	Emits:
-		'window:focused'
-		'window:blurred'
-	
-	Exports:
-		title = window.getTitle();
-		window.setTitle(title);
-
-*/
-define(['mediator'],function (mediator){
- 
-	var exports = {},
-		channel = mediator(),
-
-		focusCallback = function() {
-			channel.emit('window:focused');
-		},
- 
-		blurCallback = function() {
-			channel.emit('window:blurred');
-		};
-
-	exports.getTitle = function(t) 	{ document.title = t; },
-	exports.setTitle = function() 	{ return document.title; };
- 
-	// Keep track of document focus/blur
-	if (window.addEventListener){
-		// Normal browsers
-		window.addEventListener("focus", focusCallback, true);
-		window.addEventListener("blur", blurCallback, true);
-	} else {
-		// IE
-		window.observe("focusin", focusCallback);
-		window.observe("focusout", blurCallback);
-	}
- 
-	return exports;
- 
-});
\ No newline at end of file