aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Kavlie <akavlie@gmail.com>2011-11-08 23:57:52 -0700
committerAaron Kavlie <akavlie@gmail.com>2011-11-08 23:57:52 -0700
commit72f063d36e6d4ecba1e65438b59e8edca4f70770 (patch)
tree1c5ee420fffd97158f495d444006b7f6dcf9991d
parent96dde665268d449fcaa0609509d1c2d3d99f1f3c (diff)
downloadreevo-webirc-72f063d36e6d4ecba1e65438b59e8edca4f70770.tar.gz
reevo-webirc-72f063d36e6d4ecba1e65438b59e8edca4f70770.zip
Add channel topics
A whole bunch of CSS shenanigans necessary to accommodate this -- eventually got the scrolling right with a bunch of absolute positioning. Also got a box above the nicks for stats there (total in the channel etc.), but it's hidden for now as there's no code yet to show the stats.
-rw-r--r--app.css55
-rw-r--r--app.js66
-rw-r--r--index.html14
-rw-r--r--server.js1
4 files changed, 105 insertions, 31 deletions
diff --git a/app.css b/app.css
index 58ae57b..a1a51f7 100644
--- a/app.css
+++ b/app.css
@@ -38,14 +38,32 @@ header {
38 position: relative; 38 position: relative;
39} 39}
40 40
41#frame #output { 41#output {
42 font-size: 14px; 42 font-size: 14px;
43 border: 1px solid #444; 43 position: relative;
44 padding: 5px;
45 margin-bottom: 5px; 44 margin-bottom: 5px;
46 overflow: auto; 45 border: 1px solid #888;
46}
47
48#output #topic {
47 position: relative; 49 position: relative;
50 min-height: 40px;
51 padding: 5px;
52 background-color: #e2e2e2;
53 border-bottom: 1px solid #444;
54 display: none;
55 z-index: 2;
56}
57
58#output #messages {
59 position: absolute;
60 padding: 5px;
61 overflow: auto;
48 z-index: 10; 62 z-index: 10;
63 top: 0;
64 bottom: 0;
65 left: 0;
66 right: 0;
49} 67}
50 68
51#frame .gutter { 69#frame .gutter {
@@ -87,16 +105,35 @@ header {
87 margin-left: 0; 105 margin-left: 0;
88} 106}
89 107
90#frame .nicks { 108#sidebar {
91 float: right;
92 width: 200px; 109 width: 200px;
93 overflow: auto;
94 padding: 5px;
95 margin: 0 0 5px 5px; 110 margin: 0 0 5px 5px;
96 border: 1px solid gray; 111 border: 1px solid #888;
112 float: right;
113 position: relative;
114 display: none;
115}
116
117#sidebar .stats {
118 position: relative;
119 top: 0;
120 height: 40px;
121 background-color: #e2e2e2;
122 border-bottom: 1px solid #888;
97 display: none; 123 display: none;
98} 124}
99 125
126#sidebar .nicks {
127 position: absolute;
128 overflow: auto;
129 padding: 5px;
130 top: 0;
131 /*top: 40px;*/
132 bottom: 0;
133 left: 0;
134 right: 0;
135}
136
100#prime-input { 137#prime-input {
101 font-size: 15px; 138 font-size: 15px;
102 position: relative; 139 position: relative;
diff --git a/app.js b/app.js
index 6349585..25f556a 100644
--- a/app.js
+++ b/app.js
@@ -180,19 +180,24 @@ $(function() {
180 addMessage: function(message, single) { 180 addMessage: function(message, single) {
181 // Expensive -- only do this on single message additions 181 // Expensive -- only do this on single message additions
182 if (single) { 182 if (single) {
183 var position = $('#output').scrollTop(); 183 var position = $('#output #messages').scrollTop();
184 atBottom = $('#output')[0].scrollHeight - position 184 var atBottom = $('#output #messages')[0].scrollHeight - position
185 == $('#output').innerHeight(); 185 == $('#output #messages').innerHeight();
186 var position = this.$('#output').scrollTop(); 186 var position = this.$('#output #messages').scrollTop();
187 } 187 }
188 var view = new MessageView({model: message}); 188 var view = new MessageView({model: message});
189 $('#output').append(view.el); 189 $('#output #messages').append(view.el);
190 // Scroll to bottom on new message if already at bottom 190 // Scroll to bottom on new message if already at bottom
191 if (atBottom) { 191 if (atBottom) {
192 $('#output').scrollTop(position + 100); 192 $('#output').scrollTop(position + 100);
193 } 193 }
194 }, 194 },
195 195
196 updateTopic: function(channel) {
197 this.$('#topic').text(channel.get('topic')).show();
198 $('#messages').css('top', $('#topic').outerHeight(true));
199 },
200
196 // Switch focus to a different frame 201 // Switch focus to a different frame
197 focus: function(frame) { 202 focus: function(frame) {
198 // Save scroll position for frame before switching 203 // Save scroll position for frame before switching
@@ -201,7 +206,7 @@ $(function() {
201 } 206 }
202 this.focused = frame; 207 this.focused = frame;
203 frames.setActive(this.focused); 208 frames.setActive(this.focused);
204 this.$('#output').empty(); 209 this.$('#output #messages').empty();
205 210
206 var self = this; 211 var self = this;
207 frame.stream.each(function(message) { 212 frame.stream.each(function(message) {
@@ -210,19 +215,28 @@ $(function() {
210 215
211 nickList.addAll(frame.participants); 216 nickList.addAll(frame.participants);
212 217
213 if (frame.get('type') == 'channel') 218 if (frame.get('type') == 'channel') {
214 this.$('.nicks').show(); 219 this.$('#sidebar').show();
215 else 220 this.$('#topic').show();
216 this.$('.nicks').hide(); 221 $('.wrapper').css('margin-right', 205);
222 $('#messages').css('top', $('#topic').outerHeight(true));
223 } else {
224 this.$('#sidebar').hide();
225 this.$('#topic').hide();
226 $('.wrapper').css('margin-right', 0);
227 $('#messages').css('top', 0);
228 }
217 $(this.el).removeClass().addClass(frame.get('type')); 229 $(this.el).removeClass().addClass(frame.get('type'));
218 230
219 this.$('#output').scrollTop(this.position[frame.get('name')] || 0); 231 this.$('#output #messsages').scrollTop(this.position[frame.get('name')] || 0);
220 232
221 // Only the selected frame should send messages 233 // Only the selected frame should send messages
222 frames.each(function(frm) { 234 frames.each(function(frm) {
223 frm.stream.unbind('add'); 235 frm.stream.unbind('add');
224 frm.participants.unbind(); 236 frm.participants.unbind();
237 frm.unbind();
225 }); 238 });
239 frame.bind('change:topic', this.updateTopic, this);
226 frame.stream.bind('add', this.addMessage, this); 240 frame.stream.bind('add', this.addMessage, this);
227 nickList.switchChannel(frame); 241 nickList.switchChannel(frame);
228 }, 242 },
@@ -368,7 +382,8 @@ $(function() {
368 382
369 $(window).resize(function() { 383 $(window).resize(function() {
370 sizeContent($('#frame #output')); 384 sizeContent($('#frame #output'));
371 sizeContent($('#frame .nicks')); 385 sizeContent($('#frame #sidebar'));
386 sizeContent($('#sidebar .nicks', '.stats'));
372 }); 387 });
373 } 388 }
374 389
@@ -416,7 +431,8 @@ $(function() {
416 frames.add({name: 'status', type: 'status'}); 431 frames.add({name: 'status', type: 'status'});
417 432
418 sizeContent($('#frame #output')); 433 sizeContent($('#frame #output'));
419 sizeContent($('#frame .nicks')); 434 sizeContent($('#frame #sidebar'));
435 sizeContent($('#sidebar .nicks', '.stats'));
420 } 436 }
421 437
422 }); 438 });
@@ -436,11 +452,14 @@ $(function() {
436 } 452 }
437 453
438 // Set output window to full height, minus other elements 454 // Set output window to full height, minus other elements
439 function sizeContent(sel) { 455 function sizeContent(sel, additional) {
440 var newHeight = $('html').height() - $('header').outerHeight(true) - 456 var newHeight = $('html').height() - $('header').outerHeight(true)
441 $('#prime-input').outerHeight(true) - 457 - $('#prime-input').outerHeight(true)
442 (sel.outerHeight(true) - sel.height()) - 10; 458 - (sel.outerHeight(true) - sel.height()) - 10;
443 // (10 = #content padding) 459 // 10 = #content padding
460 if (additional) {
461 newHeight -= $(additional).outerHeight(true);
462 }
444 sel.height(newHeight); 463 sel.height(newHeight);
445 } 464 }
446 465
@@ -464,12 +483,14 @@ $(function() {
464 frames.add(pm); 483 frames.add(pm);
465 }) 484 })
466 485
486 // Message of the Day event (on joining a server)
467 socket.on('motd', function(data) { 487 socket.on('motd', function(data) {
468 data.motd.split('\n').forEach(function(line) { 488 data.motd.split('\n').forEach(function(line) {
469 frames.getByName('status').stream.add({sender: '', text: line}); 489 frames.getByName('status').stream.add({sender: '', text: line});
470 }); 490 });
471 }); 491 });
472 492
493 // Join channel event
473 socket.on('join', function(data) { 494 socket.on('join', function(data) {
474 console.log('Join event received for ' + data.channel + ' - ' + data.nick); 495 console.log('Join event received for ' + data.channel + ' - ' + data.nick);
475 if (data.nick == irc.me.get('nick')) { 496 if (data.nick == irc.me.get('nick')) {
@@ -483,6 +504,7 @@ $(function() {
483 } 504 }
484 }); 505 });
485 506
507 // Part channel event
486 socket.on('part', function(data) { 508 socket.on('part', function(data) {
487 console.log('Part event received for ' + data.channel + ' - ' + data.nick); 509 console.log('Part event received for ' + data.channel + ' - ' + data.nick);
488 if (data.nick == irc.me.get('nick')) { 510 if (data.nick == irc.me.get('nick')) {
@@ -496,6 +518,14 @@ $(function() {
496 } 518 }
497 }); 519 });
498 520
521 // Set topic event
522 socket.on('topic', function(data) {
523 var channel = frames.getByName(data.channel);
524 channel.set({topic: data.topic});
525 // TODO: Show this was changed by data.nick in the channel stream
526 });
527
528 // Nick change event
499 socket.on('nick', function(data) { 529 socket.on('nick', function(data) {
500 // Update my info, if it's me 530 // Update my info, if it's me
501 if (data.oldNick == irc.me.get('nick')) { 531 if (data.oldNick == irc.me.get('nick')) {
diff --git a/index.html b/index.html
index e6f1e32..2899b43 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
1<!doctype html> 1<!doctype html>
2<html> 2<html>
3<head> 3<head>
4 <title>Webby IRC</title> 4 <title>web-irc</title>
5 5
6 <link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css"> 6 <link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css">
7 <link rel="stylesheet" type="text/css" href="app.css"> 7 <link rel="stylesheet" type="text/css" href="app.css">
@@ -14,10 +14,16 @@
14 </header> 14 </header>
15 15
16 <div id="frame"> 16 <div id="frame">
17 <div class="nicks"></div> 17 <div id="sidebar">
18 <div class="stats">nick count here</div>
19 <div class="nicks"></div>
20 </div>
18 <div class="wrapper"> 21 <div class="wrapper">
19 <div id="output"></div> 22 <div id="output">
20 <div class="gutter"></div> 23 <div id="topic">channel topic here</div>
24 <div id="messages"></div>
25 <div class="gutter"></div>
26 </div>
21 </div> 27 </div>
22 <input id="prime-input" type="text"> 28 <input id="prime-input" type="text">
23 </div> 29 </div>
diff --git a/server.js b/server.js
index 5192e94..591db3b 100644
--- a/server.js
+++ b/server.js
@@ -24,6 +24,7 @@ io.sockets.on('connection', function(socket) {
24 var events = { 24 var events = {
25 'join': ['channel', 'nick'], 25 'join': ['channel', 'nick'],
26 'part': ['channel', 'nick'], 26 'part': ['channel', 'nick'],
27 'topic': ['channel', 'topic', 'nick'],
27 'nick': ['oldNick', 'newNick', 'channels'], 28 'nick': ['oldNick', 'newNick', 'channels'],
28 'names': ['channel', 'nicks'], 29 'names': ['channel', 'nicks'],
29 'message': ['from', 'to', 'text'], 30 'message': ['from', 'to', 'text'],