aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Kavlie <akavlie@gmail.com>2011-11-05 23:08:24 -0700
committerAaron Kavlie <akavlie@gmail.com>2011-11-05 23:08:24 -0700
commit9773b8732c87b8637c8fa2bbc5a99490b4609518 (patch)
tree4fdba0c337390781f804cd3ac84f50d46b9eac6c
parentde6b00eef455eec231d701a75e7890f4819000c6 (diff)
downloadreevo-webirc-9773b8732c87b8637c8fa2bbc5a99490b4609518.tar.gz
reevo-webirc-9773b8732c87b8637c8fa2bbc5a99490b4609518.zip
Support PMs
Open new frame when a PM is started, from either end. Also included focus switch when a tab is closed.
-rw-r--r--app.js72
-rw-r--r--js/util.js8
-rw-r--r--server.js1
3 files changed, 69 insertions, 12 deletions
diff --git a/app.js b/app.js
index 5aaf348..925463a 100644
--- a/app.js
+++ b/app.js
@@ -210,10 +210,10 @@ $(function() {
210 210
211 nickList.addAll(frame.participants); 211 nickList.addAll(frame.participants);
212 212
213 if (frame.get('name') == 'status') 213 if (frame.get('type') == 'channel')
214 this.$('.nicks').hide();
215 else
216 this.$('.nicks').show(); 214 this.$('.nicks').show();
215 else
216 this.$('.nicks').hide();
217 $(this.el).removeClass().addClass(frame.get('type')); 217 $(this.el).removeClass().addClass(frame.get('type'));
218 218
219 this.$('#output').scrollTop(this.position[frame.get('name')] || 0); 219 this.$('#output').scrollTop(this.position[frame.get('name')] || 0);
@@ -243,14 +243,30 @@ $(function() {
243 243
244 events: { 244 events: {
245 'click': 'setActive', 245 'click': 'setActive',
246 'click .close-frame': 'part' 246 'click .close-frame': 'close'
247 }, 247 },
248 248
249 // Send PART command to server
249 part: function() { 250 part: function() {
250 socket.emit('part', this.model.get('name')); 251 if (this.model.get('type') === 'channel') {
252 socket.emit('part', this.model.get('name'));
253 } else {
254 // PMs don't need an explicit PART
255 this.model.destroy();
256 }
251 }, 257 },
252 258
259 // Close frame
253 close: function() { 260 close: function() {
261 // Focus on next frame if this one has the focus
262 if ($(this.el).hasClass('active')) {
263 // Go to previous frame unless it's status
264 if ($(this.el).prev().text().trim() !== 'status') {
265 $(this.el).prev().click();
266 } else {
267 $(this.el).next().click();
268 }
269 }
254 $(this.el).remove(); 270 $(this.el).remove();
255 }, 271 },
256 272
@@ -276,8 +292,6 @@ $(function() {
276 $(this.el).html(html); 292 $(this.el).html(html);
277 return this; 293 return this;
278 } 294 }
279
280
281 }); 295 });
282 296
283 var AppView = Backbone.View.extend({ 297 var AppView = Backbone.View.extend({
@@ -292,7 +306,7 @@ $(function() {
292 }, 306 },
293 307
294 events: { 308 events: {
295 'keypress #prime-input': 'parseInput', 309 'keypress #prime-input': 'sendInput',
296 }, 310 },
297 311
298 addTab: function(frame) { 312 addTab: function(frame) {
@@ -305,20 +319,44 @@ $(function() {
305 socket.emit('join', name); 319 socket.emit('join', name);
306 }, 320 },
307 321
308 parseInput: function(e) { 322 // Map common IRC commands to standard (RFC 1459)
323 parse: function(text) {
324 var command = text.split(' ')[0];
325 console.log(command);
326 var revised = '';
327 switch (command) {
328 case 'msg':
329 revised = 'privmsg';
330 break;
331 default:
332 revised = command;
333 break;
334 }
335 return replaceString(command, revised, text);
336 },
337
338 sendInput: function(e) {
309 if (e.keyCode != 13) return; 339 if (e.keyCode != 13) return;
310 var frame = irc.frameWindow.focused, 340 var frame = irc.frameWindow.focused,
311 input = this.input.val(); 341 input = this.input.val();
312 342
313 if (input.indexOf('/') === 0) { 343 if (input.indexOf('/') === 0) {
314 console.log('IRC command detected -- sending to server'); 344 console.log('IRC command detected -- sending to server');
315 socket.emit('command', input.substr(1)); 345 var parsed = this.parse(input.substr(1))
346 socket.emit('command', parsed);
347 // special case -- no output emitted, yet we want a new frame
348 var msgParts = parsed.split(' ');
349 if (msgParts[0].toLowerCase() === 'privmsg') {
350 pm = frames.getByName(msgParts[1]) || new Frame({type: 'pm', name: msg.nick});
351 pm.stream.add({sender: msg.nick, text: msg.text})
352 frames.add(pm);
353 }
316 } else { 354 } else {
317 socket.emit('say', { 355 socket.emit('say', {
318 target: frame.get('name'), 356 target: frame.get('name'),
319 message: input 357 message: input
320 }); 358 });
321 frame.stream.add({sender: me.get('nick'), text: input}); 359 frame.stream.add({sender: irc.me.get('nick'), text: input});
322 } 360 }
323 361
324 this.input.val(''); 362 this.input.val('');
@@ -416,12 +454,22 @@ $(function() {
416 // SOCKET EVENTS 454 // SOCKET EVENTS
417 // ============= 455 // =============
418 socket.on('message', function(msg) { 456 socket.on('message', function(msg) {
457 // Filter out messages not aimed at a channel or status (i.e. PMs)
458 if (msg.to.indexOf('#') !== 0 &&
459 msg.to.indexOf('&') !== 0 &&
460 msg.to !== 'status') return;
419 frame = frames.getByName(msg.to); 461 frame = frames.getByName(msg.to);
420 if (frame) { 462 if (frame) {
421 frame.stream.add({sender: msg.from, text: msg.text}); 463 frame.stream.add({sender: msg.from, text: msg.text});
422 } 464 }
423 }); 465 });
424 466
467 socket.on('pm', function(msg) {
468 pm = frames.getByName(msg.nick) || new Frame({type: 'pm', name: msg.nick});
469 pm.stream.add({sender: msg.nick, text: msg.text})
470 frames.add(pm);
471 })
472
425 socket.on('motd', function(data) { 473 socket.on('motd', function(data) {
426 data.motd.split('\n').forEach(function(line) { 474 data.motd.split('\n').forEach(function(line) {
427 frames.getByName('status').stream.add({sender: '', text: line}); 475 frames.getByName('status').stream.add({sender: '', text: line});
@@ -471,7 +519,7 @@ $(function() {
471 oldNick: data.oldNick, 519 oldNick: data.oldNick,
472 newNick: data.newNick 520 newNick: data.newNick
473 }); 521 });
474 nickMessage.setText() 522 nickMessage.setText();
475 channel.stream.add(nickMessage); 523 channel.stream.add(nickMessage);
476 }); 524 });
477 }); 525 });
diff --git a/js/util.js b/js/util.js
index 3aa7d25..fc0c2a7 100644
--- a/js/util.js
+++ b/js/util.js
@@ -64,4 +64,12 @@ if ( !Array.prototype.forEach ) {
64 } 64 }
65 // 8. return undefined 65 // 8. return undefined
66 }; 66 };
67}
68
69// UTILITY FUNCTIONS
70// =================
71
72// Replaces oldString with newString in the string haystack
73function replaceString(oldString, newString, haystack) {
74 return haystack.split(oldString).join(newString);
67} \ No newline at end of file 75} \ No newline at end of file
diff --git a/server.js b/server.js
index 0dd22ef..c2c4cbb 100644
--- a/server.js
+++ b/server.js
@@ -48,6 +48,7 @@ io.sockets.on('connection', function(socket) {
48 'nick': ['oldNick', 'newNick', 'channels'], 48 'nick': ['oldNick', 'newNick', 'channels'],
49 'names': ['channel', 'nicks'], 49 'names': ['channel', 'nicks'],
50 'message': ['from', 'to', 'text'], 50 'message': ['from', 'to', 'text'],
51 'pm': ['nick', 'text'],
51 'motd': ['motd'], 52 'motd': ['motd'],
52 'error': ['message'] 53 'error': ['message']
53 }; 54 };