Support for changing port and using SSL on client
[KiwiIRC.git] / js / front.js
1 /*jslint nomen: true, devel: true, undef: true, browser: true, continue: true, sloppy: true, forin: true, newcap: true, plusplus: true, maxerr: 50, indent: 4 */
2 /*global gateway, io, $, iScroll, agent, touchscreen, init_data, plugs, plugins, registerTouches, randomString */
3 kiwi.front = {
4 revision: 38,
5
6 cur_channel: '',
7 windows: {},
8 tabviews: {},
9 utilityviews: {},
10 boxes: {},
11
12 buffer: [],
13 buffer_pos: 0,
14
15 cache: {},
16
17 original_topic: '',
18
19 init: function () {
20 /*global Box, touch_scroll:true */
21 var about_info, supportsOrientationChange, orientationEvent, scroll_opts;
22 kiwi.gateway.nick = 'kiwi_' + Math.ceil(100 * Math.random()) + Math.ceil(100 * Math.random());
23 kiwi.gateway.session_id = null;
24
25 $(kiwi.gateway).bind("onmsg", kiwi.front.onMsg);
26 $(kiwi.gateway).bind("onnotice", kiwi.front.onNotice);
27 $(kiwi.gateway).bind("onaction", kiwi.front.onAction);
28 $(kiwi.gateway).bind("onmotd", kiwi.front.onMOTD);
29 $(kiwi.gateway).bind("onoptions", kiwi.front.onOptions);
30 $(kiwi.gateway).bind("onconnect", kiwi.front.onConnect);
31 $(kiwi.gateway).bind("onconnect_fail", kiwi.front.onConnectFail);
32 $(kiwi.gateway).bind("ondisconnect", kiwi.front.onDisconnect);
33 $(kiwi.gateway).bind("onnick", kiwi.front.onNick);
34 $(kiwi.gateway).bind("onuserlist", kiwi.front.onUserList);
35 $(kiwi.gateway).bind("onuserlist_end", kiwi.front.onUserListEnd);
36 $(kiwi.gateway).bind("onlist_start", kiwi.front.onChannelListStart);
37 $(kiwi.gateway).bind("onlist_channel", kiwi.front.onChannelList);
38 $(kiwi.gateway).bind("onlist_end", kiwi.front.onChannelListEnd);
39 $(kiwi.gateway).bind("onjoin", kiwi.front.onJoin);
40 $(kiwi.gateway).bind("ontopic", kiwi.front.onTopic);
41 $(kiwi.gateway).bind("onpart", kiwi.front.onPart);
42 $(kiwi.gateway).bind("onkick", kiwi.front.onKick);
43 $(kiwi.gateway).bind("onquit", kiwi.front.onQuit);
44 $(kiwi.gateway).bind("onmode", kiwi.front.onMode);
45 $(kiwi.gateway).bind("onwhois", kiwi.front.onWhois);
46 $(kiwi.gateway).bind("onsync", kiwi.front.onSync);
47 $(kiwi.gateway).bind("onchannel_redirect", kiwi.front.onChannelRedirect);
48 $(kiwi.gateway).bind("ondebug", kiwi.front.onDebug);
49 $(kiwi.gateway).bind("onctcp_request", kiwi.front.onCTCPRequest);
50 $(kiwi.gateway).bind("onctcp_response", kiwi.front.onCTCPResponse);
51 $(kiwi.gateway).bind("onirc_error", kiwi.front.onIRCError);
52 $(kiwi.gateway).bind("onkiwi", kiwi.front.onKiwi);
53
54 this.buffer = [];
55
56 // Build the about box
57 kiwi.front.boxes.about = new Box("about");
58 about_info = 'UI adapted for ' + agent;
59 if (touchscreen) {
60 about_info += ' touchscreen ';
61 }
62 about_info += 'usage';
63 $('#tmpl_about_box').tmpl({
64 about: about_info,
65 front_revision: kiwi.front.revision,
66 gateway_revision: kiwi.gateway.revision
67 }).appendTo(kiwi.front.boxes.about.content);
68
69 //$(window).bind("beforeunload", function(){ kiwi.gateway.quit(); });
70
71 if (touchscreen) {
72 $('#kiwi').addClass('touchscreen');
73
74 // Single touch scrolling through scrollback for touchscreens
75 scroll_opts = {};
76 touch_scroll = new iScroll('windows', scroll_opts);
77 }
78
79 kiwi.front.registerKeys();
80
81 $('#kiwi .toolbars').resize(kiwi.front.doLayoutSize);
82 $(window).resize(kiwi.front.doLayoutSize);
83
84 // Add the resizer for the userlist
85 $('<div id="nicklist_resize" style="position:absolute; cursor:w-resize; width:5px;"></div>').appendTo('#kiwi');
86 $('#nicklist_resize').draggable({axis: "x", drag: function () {
87 var t = $(this),
88 new_width = $(document).width() - parseInt(t.css('left'), 10);
89
90 new_width = new_width - parseInt($('#kiwi .userlist').css('margin-left'), 10);
91 new_width = new_width - parseInt($('#kiwi .userlist').css('margin-right'), 10);
92
93 // Make sure we don't remove the userlist alltogether
94 console.log(new_width);
95 if (new_width < 20) {
96 $(this).data('draggable').offset.click.left = 10;
97 console.log('whoaa');
98 }
99
100 kiwi.front.cur_channel.setUserlistWidth(new_width);
101 }});
102
103
104 $('#kiwi .formconnectwindow').submit(function () {
105 var netsel = $('#kiwi .formconnectwindow .network'),
106 netport = $('#kiwi .formconnectwindow .port'),
107 netssl = $('#kiwi .formconnectwindow .ssl'),
108 nick = $('#kiwi .formconnectwindow .nick'),
109 tmp;
110
111 if (nick.val() === '') {
112 nick.val('Nick please!');
113 nick.focus();
114 return false;
115 }
116
117 tmp = nick.val().split(' ');
118 kiwi.gateway.nick = tmp[0];
119
120 init_data.channel = $('#channel').val();
121
122 kiwi.front.doLayout();
123 try {
124 kiwi.front.run('/connect ' + netsel.val() + ' ' + netport.val() + ' ' + (netssl.attr('checked') ? 'true' : ''));
125 } catch (e) {}
126
127 $('#kiwi .connectwindow').slideUp('', kiwi.front.barsShow);
128 $('#windows').click(function () { $('#kiwi_msginput').focus(); });
129
130 return false;
131 });
132
133 supportsOrientationChange = (typeof window.onorientationchange !== undefined);
134 orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
135 if (window.addEventListener) {
136 window.addEventListener(orientationEvent, kiwi.front.doLayoutSize, false);
137 } else {
138 // < IE9
139 window.attachEvent(orientationEvent, kiwi.front.doLayoutSize, false);
140 }
141 //$('#kiwi').bind("resize", kiwi.front.doLayoutSize, false);
142
143 kiwi.front.doLayout();
144 kiwi.front.barsHide();
145
146 kiwi.front.tabviewAdd('server');
147 kiwi.front.tabviews.server.userlist_width = 0; // Disable the userlist
148
149 // Any pre-defined nick?
150 if (typeof window.init_data.nick === "string") {
151 $('#kiwi .formconnectwindow .nick').val(init_data.nick);
152 }
153
154 // Any pre-defined channels?
155 if (typeof window.init_data.channel === 'string') {
156 $('#channel').val(init_data.channel);
157 }
158
159 // Fix for Opera inserting a spurious <br/>
160 $('#kiwi .cur_topic br').remove();
161
162 $('#kiwi .cur_topic').keydown(function (e) {
163 if (e.which === 13) {
164 // enter
165 e.preventDefault();
166 $(this).change();
167 $('#kiwi_msginput').focus();
168 } else if (e.which === 27) {
169 // escape
170 e.preventDefault();
171 $(this).text(kiwi.front.original_topic);
172 $('#kiwi_msginput').focus();
173 }
174 });
175 /*$('.cur_topic').live('keypress', function(e) {
176 if (e.keyCode === 13) {
177 // enter
178 e.preventDefault();
179 $(this).change();
180 $('#kiwi_msginput').focus();
181 } else if (e.keyCode === 27) {
182 // escape
183 e.preventDefault();
184 $(this).text(kiwi.front.original_topic);
185 }
186 });*/
187 $('.cur_topic').live('change', function () {
188 var chan, text;
189 text = $(this).text();
190 if (text !== kiwi.front.original_topic) {
191 chan = kiwi.front.cur_channel.name;
192 kiwi.gateway.setTopic(chan, text);
193 }
194 });
195
196
197 $('#windows a.chan').live('click', function () {
198 kiwi.front.joinChannel($(this).text());
199 return false;
200 });
201
202 kiwi.data.set('chanList', []);
203
204 (function () {
205 var i;
206 for (i in plugins) {
207 kiwi.plugs.loadPlugin(plugins[i]);
208 }
209 }());
210 },
211
212 doLayoutSize: function () {
213 var kiwi, toolbars, ul, n_top, n_bottom, nl;
214 kiwi = $('#kiwi');
215
216 if (kiwi.width() < 330 && !kiwi.hasClass('small_kiwi')) {
217 console.log("switching to small kiwi");
218 kiwi.removeClass('large_kiwi');
219 kiwi.addClass('small_kiwi');
220 } else if (kiwi.width() >= 330 && !kiwi.hasClass('large_kiwi')) {
221 kiwi.removeClass('small_kiwi');
222 kiwi.addClass('large_kiwi');
223 }
224
225 toolbars = $('#kiwi .cur_topic');
226 ul = $('#kiwi .userlist');
227
228 n_top = parseInt(toolbars.offset().top, 10) + parseInt(toolbars.outerHeight(true), 10);
229 n_bottom = $(document).height() - parseInt($('#kiwi .control').offset().top, 10);
230
231 $('#kiwi .windows').css({top: n_top + 'px', bottom: n_bottom + 'px'});
232 ul.css({top: n_top + 'px', bottom: n_bottom + 'px'});
233
234 nl = $('#nicklist_resize');
235 nl.css({top: n_top + 'px', bottom: n_bottom + 'px', left: $(document).width() - ul.outerWidth(true)});
236 },
237
238
239 doLayout: function () {
240 $('#kiwi .msginput .nick a').text(kiwi.gateway.nick);
241 $('#kiwi_msginput').val(' ');
242 $('#kiwi_msginput').focus();
243 },
244
245
246 joinChannel: function (chan_name) {
247 var chans = chan_name.split(','),
248 i,
249 chan;
250 for (i in chans) {
251 chan = chans[i];
252 if (kiwi.front.tabviews[chan.toLowerCase()] === undefined || (kiwi.front.tabviews[chan.toLowerCase()] !== undefined && kiwi.front.tabviews[chan.toLowerCase()].safe_to_close === true)) {
253 kiwi.gateway.join(chan);
254 kiwi.front.tabviewAdd(chan);
255 } else {
256 kiwi.front.tabviews[chan.toLowerCase()].show();
257 }
258 }
259 },
260
261
262 run: function (msg) {
263 var parts, dest, t, pos, textRange, d, plugin_event, msg_sliced;
264
265 // Run through any plugins
266 plugin_event = {command: msg};
267 plugin_event = kiwi.plugs.run('command_run', plugin_event);
268 if (!plugin_event || typeof plugin_event.command === 'undefined') {
269 return;
270 }
271
272 // Update msg if it's been changed by any plugins
273 msg = plugin_event.command.toString();
274
275 console.log("running " + msg);
276 if (msg.substring(0, 1) === '/') {
277 parts = msg.split(' ');
278 switch (parts[0].toLowerCase()) {
279 case '/j':
280 case '/join':
281 kiwi.front.joinChannel(parts[1]);
282 break;
283
284 case '/connect':
285 case '/server':
286 if (parts[1] === undefined) {
287 alert('Usage: /connect servername [[port] [ssl]]');
288 break;
289 }
290
291 if (parts[2] === undefined) {
292 parts[2] = 6667;
293 }
294
295 if ((parts[3] === undefined) || (parts[3] === 'false') || (parts[3] === 'no')) {
296 parts[3] = false;
297 } else {
298 parts[3] = true;
299 }
300
301 kiwi.front.cur_channel.addMsg(null, ' ', '=== Connecting to ' + parts[1] + ' on port ' + parts[2] + ((parts[3]) ? ' using SSL' : '') + '...', 'status');
302 kiwi.gateway.connect(parts[1], parts[2], parts[3]);
303 break;
304
305 case '/nick':
306 console.log("/nick");
307 if (parts[1] === undefined) {
308 console.log("calling show nick");
309 kiwi.front.showChangeNick();
310 } else {
311 console.log("sending raw");
312 kiwi.gateway.raw(msg.substring(1));
313 }
314 break;
315
316 case '/part':
317 if (typeof parts[1] === "undefined") {
318 if (kiwi.front.cur_channel.safe_to_close) {
319 kiwi.front.cur_channel.close();
320 } else {
321 kiwi.gateway.raw(msg.substring(1) + ' ' + kiwi.front.cur_channel.name);
322 }
323 } else {
324 kiwi.gateway.raw(msg.substring(1));
325 }
326 break;
327
328 case '/names':
329 if (typeof parts[1] !== "undefined") {
330 kiwi.gateway.raw(msg.substring(1));
331 }
332 break;
333
334 case '/debug':
335 kiwi.gateway.debug();
336 break;
337
338 case '/q':
339 case '/query':
340 if (typeof parts[1] !== "undefined") {
341 kiwi.front.tabviewAdd(parts[1]);
342 }
343 break;
344
345
346 case '/m':
347 case '/msg':
348 if (typeof parts[1] !== "undefined") {
349 msg_sliced = msg.split(' ').slice(2).join(' ');
350 kiwi.gateway.msg(parts[1], msg_sliced);
351
352 if (!kiwi.front.tabviewExists(parts[1])) {
353 kiwi.front.tabviewAdd(parts[1]);
354 }
355 kiwi.front.tabviews[parts[1].toLowerCase()].addMsg(null, kiwi.gateway.nick, msg_sliced);
356 }
357 break;
358
359 case '/k':
360 case '/kick':
361 if (typeof parts[1] === 'undefined') {
362 return;
363 }
364 kiwi.gateway.raw('KICK ' + kiwi.front.cur_channel.name + ' ' + msg.split(' ', 2)[1]);
365 break;
366
367 case '/quote':
368 kiwi.gateway.raw(msg.replace(/^\/quote /i, ''));
369 break;
370
371 case '/me':
372 kiwi.gateway.action(kiwi.front.cur_channel.name, msg.substring(4));
373 //kiwi.front.tabviews[destination.toLowerCase()].addMsg(null, ' ', '* '+data.nick+' '+data.msg, 'color:green;');
374 kiwi.front.cur_channel.addMsg(null, ' ', '* ' + kiwi.gateway.nick + ' ' + msg.substring(4), 'action', 'color:#555;');
375 break;
376
377 case '/notice':
378 dest = parts[1];
379 msg = parts.slice(2).join(' ');
380
381 kiwi.gateway.notice(dest, msg);
382 this.onNotice({}, {nick: kiwi.gateway.nick, channel: dest, msg: msg});
383 break;
384
385 case '/win':
386 if (parts[1] !== undefined) {
387 kiwi.front.windowsShow(parseInt(parts[1], 10));
388 }
389 break;
390
391 case '/quit':
392 kiwi.gateway.quit(parts.slice(1).join(' '));
393 break;
394
395 case '/topic':
396 if (parts[1] === undefined) {
397 t = $('.cur_topic');
398 if (t.createTextRange) {
399 pos = t.text().length();
400 textRange = t.createTextRange();
401 textRange.collapse(true);
402 textRange.moveEnd(pos);
403 textRange.moveStart(pos);
404 textRange.select();
405 } else if (t.setSelectionRange) {
406 t.setSelectionRange(pos, pos);
407 }
408 } else {
409 kiwi.gateway.setTopic(kiwi.front.cur_channel.name, msg.split(' ', 2)[1]);
410 //kiwi.gateway.raw('TOPIC ' + kiwi.front.cur_channel.name + ' :' + msg.split(' ', 2)[1]);
411 }
412 break;
413
414 case '/kiwi':
415 kiwi.gateway.kiwi(kiwi.front.cur_channel.name, msg.substring(6));
416 break;
417
418 default:
419 //kiwi.front.cur_channel.addMsg(null, ' ', '--> Invalid command: '+parts[0].substring(1));
420 kiwi.gateway.raw(msg.substring(1));
421 }
422
423 } else {
424 //alert('Sending message: '+msg);
425 if (msg.trim() === '') {
426 return;
427 }
428 if (kiwi.front.cur_channel.name !== 'server') {
429 kiwi.gateway.msg(kiwi.front.cur_channel.name, msg);
430 d = new Date();
431 d = d.getHours() + ":" + d.getMinutes();
432 //kiwi.front.addMsg(d, kiwi.gateway.nick, msg);
433 kiwi.front.cur_channel.addMsg(null, kiwi.gateway.nick, msg);
434 }
435 }
436 },
437
438
439 onMsg: function (e, data) {
440 var destination, plugin_event;
441 // Is this message from a user?
442 if (data.channel === kiwi.gateway.nick) {
443 destination = data.nick.toLowerCase();
444 } else {
445 destination = data.channel.toLowerCase();
446 }
447
448 plugin_event = {nick: data.nick, msg: data.msg, destination: destination};
449 plugin_event = kiwi.plugs.run('msg_recieved', plugin_event);
450 if (!plugin_event) {
451 return;
452 }
453
454 if (!kiwi.front.tabviewExists(plugin_event.destination)) {
455 kiwi.front.tabviewAdd(plugin_event.destination);
456 }
457 kiwi.front.tabviews[plugin_event.destination].addMsg(null, plugin_event.nick, plugin_event.msg);
458 },
459
460 onDebug: function (e, data) {
461 if (!kiwi.front.tabviewExists('kiwi_debug')) {
462 kiwi.front.tabviewAdd('kiwi_debug');
463 }
464 kiwi.front.tabviews.kiwi_debug.addMsg(null, ' ', data.msg);
465 },
466
467 onAction: function (e, data) {
468 var destination;
469 // Is this message from a user?
470 if (data.channel === kiwi.gateway.nick) {
471 destination = data.nick;
472 } else {
473 destination = data.channel;
474 }
475
476 if (!kiwi.front.tabviewExists(destination)) {
477 kiwi.front.tabviewAdd(destination);
478 }
479 kiwi.front.tabviews[destination.toLowerCase()].addMsg(null, ' ', '* ' + data.nick + ' ' + data.msg, 'action', 'color:#555;');
480 },
481
482 onTopic: function (e, data) {
483 if (kiwi.front.tabviewExists(data.channel)) {
484 kiwi.front.tabviews[data.channel.toLowerCase()].changeTopic(data.topic);
485 }
486 },
487
488 onNotice: function (e, data) {
489 var nick = (data.nick === undefined) ? '' : data.nick,
490 enick = '[' + nick + ']';
491
492 if (kiwi.front.tabviewExists(data.target)) {
493 kiwi.front.tabviews[data.target.toLowerCase()].addMsg(null, enick, data.msg, 'notice');
494 } else if (kiwi.front.tabviewExists(nick)) {
495 kiwi.front.tabviews[nick.toLowerCase()].addMsg(null, enick, data.msg, 'notice');
496 } else {
497 kiwi.front.tabviews.server.addMsg(null, enick, data.msg, 'notice');
498 }
499 },
500
501 onCTCPRequest: function (e, data) {
502 var msg = data.msg.split(" ", 2);
503 switch (msg[0]) {
504 case 'PING':
505 if (typeof msg[1] === 'undefined') {
506 msg[1] = '';
507 }
508 kiwi.gateway.notice(data.nick, String.fromCharCode(1) + 'PING ' + msg[1] + String.fromCharCode(1));
509 break;
510 case 'TIME':
511 kiwi.gateway.notice(data.nick, String.fromCharCode(1) + 'TIME ' + (new Date()).toLocaleString() + String.fromCharCode(1));
512 break;
513 }
514 kiwi.front.tabviews.server.addMsg(null, 'CTCP [' + data.nick + ']', data.msg, 'ctcp');
515 },
516
517 onCTCPResponse: function (e, data) {
518 },
519
520 onKiwi: function (e, data) {
521 //console.log(data);
522 },
523
524 onConnect: function (e, data) {
525 if (data.connected) {
526 if (kiwi.gateway.nick !== data.nick) {
527 kiwi.gateway.nick = data.nick;
528 kiwi.front.doLayout();
529 }
530
531 kiwi.front.tabviews.server.addMsg(null, ' ', '=== Connected OK :)', 'status');
532 if (typeof init_data.channel === "string") {
533 kiwi.front.joinChannel(init_data.channel);
534 }
535 kiwi.plugs.run('connect', {success: true});
536 } else {
537 kiwi.front.tabviews.server.addMsg(null, ' ', '=== Failed to connect :(', 'status');
538 kiwi.plugs.run('connect', {success: false});
539 }
540 },
541 onConnectFail: function (e, data) {
542 var reason = (typeof data.reason === 'string') ? data.reason : '';
543 kiwi.front.tabviews.server.addMsg(null, '', 'There\'s a problem connecting! (' + reason + ')', 'error');
544 kiwi.plugs.run('connect', {success: false});
545 },
546 onDisconnect: function (e, data) {
547 var tab;
548 for (tab in kiwi.front.tabviews) {
549 kiwi.front.tabviews[tab].addMsg(null, '', 'Disconnected from server!', 'error');
550 }
551 kiwi.plugs.run('disconnect', {success: false});
552 },
553 onOptions: function (e, data) {
554 if (typeof kiwi.gateway.network_name === "string" && kiwi.gateway.network_name !== "") {
555 kiwi.front.tabviews.server.tab.text(kiwi.gateway.network_name);
556 }
557 },
558 onMOTD: function (e, data) {
559 kiwi.front.tabviews.server.addMsg(null, data.server, data.msg, 'motd');
560 },
561 onWhois: function (e, data) {
562 var d;
563 if (data.msg) {
564 kiwi.front.cur_channel.addMsg(null, data.nick, data.msg, 'whois');
565 } else if (data.logon) {
566 d = new Date();
567 d.setTime(data.logon * 1000);
568 d = d.toLocaleString();
569 kiwi.front.cur_channel.addMsg(null, data.nick, 'idle for ' + data.idle + ' second' + ((data.idle !== 1) ? 's' : '') + ', signed on ' + d, 'whois');
570 } else {
571 kiwi.front.cur_channel.addMsg(null, data.nick, 'idle for ' + data.idle + ' seconds', 'whois');
572 }
573 },
574 onMode: function (e, data) {
575 var i, new_nick_text;
576
577 // TODO: Store the modes in the elements data, then work out the current
578 // mode symbol from the highest mode. Eg. -h may leave +o from previous modes; It
579 // doesn't simply clear it! ~Darren
580 if (typeof data.channel === 'string' && typeof data.effected_nick === 'string') {
581 kiwi.front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '[' + data.mode + '] ' + data.effected_nick + ' by ' + data.nick, 'mode', '');
582 kiwi.front.tabviews[data.channel.toLowerCase()].userlist.children().each(function () {
583 if (kiwi.front.nickStripPrefix($(this).text()) === data.effected_nick) {
584
585 if (data.mode.split('')[0] === '+') {
586 for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) {
587 if (kiwi.gateway.user_prefixes[i].mode === data.mode.split('')[1]) {
588 new_nick_text = kiwi.gateway.user_prefixes[i].symbol + data.effected_nick;
589 break;
590 }
591 }
592 } else if (data.mode.split('')[0] === '-') {
593 new_nick_text = data.effected_nick;
594 }
595
596 if (new_nick_text !== '') {
597 $(this).text(new_nick_text);
598 return false;
599 }
600
601 }
602 });
603 }
604 },
605 onUserList: function (e, data) {
606 var ul, nick, mode;
607 if (kiwi.front.tabviews[data.channel.toLowerCase()] === undefined) {
608 return;
609 }
610 ul = kiwi.front.tabviews[data.channel.toLowerCase()].userlist;
611
612 if (!document.userlist_updating) {
613 document.userlist_updating = true;
614 ul.empty();
615 }
616
617 $.each(data.users, function (i, item) {
618 nick = i; //i.match(/^.+!/g);
619 mode = item;
620 $('<li><a class="nick" onclick="kiwi.front.userClick(this);">' + mode + nick + '</a></li>').appendTo(ul);
621 });
622
623 kiwi.front.tabviews[data.channel.toLowerCase()].userlistSort();
624 },
625 onUserListEnd: function (e, data) {
626 document.userlist_updating = false;
627 },
628
629 onChannelListStart: function (e, data) {
630 var tab, table;
631 console.log('/list start');
632 console.profile('list');
633
634 tab = new Utilityview('Channel List');
635 tab.div.css('overflow-y', 'scroll');
636 table = $('<table><thead style="font-weight: bold;"><tr><td>Channel Name</td><td>Members</td><td style="padding-left: 2em;">Topic</td></tr></thead><tbody style="vertical-align: top;"></tbody>');
637 tab.div.append(table);
638
639 kiwi.front.cache.list = {chans: [], tab: tab, table: table,
640 update: function (newChans) {
641 var body = this.table.children('tbody:first').detach(),
642 chan,
643 html;
644
645 html = '';
646 for (chan in newChans) {
647 this.chans.push(newChans[chan]);
648 html += newChans[chan].html;
649 }
650 body.append(html);
651 this.table.append(body);
652
653 },
654 finalise: function () {
655 var body = this.table.children('tbody:first').detach(),
656 list,
657 chan;
658
659 list = $.makeArray($(body).children());
660
661 for (chan in list) {
662 list[chan] = $(list[chan]).detach();
663 }
664
665 list = _.sortBy(list, function (channel) {
666 return parseInt(channel.children('.num_users').first().text(), 10);
667 }).reverse();
668
669 for (chan in list) {
670 body.append(list[chan]);
671 }
672
673 this.table.append(body);
674
675 }};
676 },
677 onChannelList: function (e, data) {
678 var chans;
679 console.log(data);
680 data = data.chans;
681 //data = [data];
682 for (chans in data) {
683 data[chans] = {data: data[chans], html: '<tr><td><a class="chan">' + data[chans].channel + '</a></td><td class="num_users" style="text-align: center;">' + data[chans].num_users + '</td><td style="padding-left: 2em;">' + kiwi.front.format(data[chans].topic) + '</td></tr>'};
684 }
685 kiwi.front.cache.list.update(data);
686 },
687 onChannelListEnd: function (e, data) {
688 kiwi.front.cache.list.finalise();
689 kiwi.front.cache.list.tab.show();
690 console.profileEnd();
691 console.log('/list end.');
692 },
693
694
695 onJoin: function (e, data) {
696 if (!kiwi.front.tabviewExists(data.channel)) {
697 kiwi.front.tabviewAdd(data.channel.toLowerCase());
698 }
699
700 if (data.nick === kiwi.gateway.nick) {
701 return; // Not needed as it's already in nicklist
702 }
703 kiwi.front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '--> ' + data.nick + ' has joined', 'action join', 'color:#009900;');
704 $('<li><a class="nick" onclick="kiwi.front.userClick(this);">' + data.nick + '</a></li>').appendTo(kiwi.front.tabviews[data.channel.toLowerCase()].userlist);
705 kiwi.front.tabviews[data.channel.toLowerCase()].userlistSort();
706 },
707 onPart: function (e, data) {
708 if (kiwi.front.tabviewExists(data.channel)) {
709 // If this is us, close the tabview
710 if (data.nick === kiwi.gateway.nick) {
711 kiwi.front.tabviews[data.channel.toLowerCase()].close();
712 kiwi.front.tabviews.server.show();
713 return;
714 }
715
716 kiwi.front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '<-- ' + data.nick + ' has left (' + data.message + ')', 'action part', 'color:#990000;');
717 kiwi.front.tabviews[data.channel.toLowerCase()].userlist.children().each(function () {
718 if ($(this).text() === data.nick) {
719 $(this).remove();
720 }
721 });
722 }
723 },
724 onKick: function (e, data) {
725 if (kiwi.front.tabviewExists(data.channel)) {
726 // If this is us, close the tabview
727 if (data.kicked === kiwi.gateway.nick) {
728 //kiwi.front.tabviews[data.channel.toLowerCase()].close();
729 kiwi.front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '=== You have been kicked from ' + data.channel + '. ' + data.message, 'status kick');
730 kiwi.front.tabviews[data.channel.toLowerCase()].safe_to_close = true;
731 $('li', kiwi.front.tabviews[data.channel.toLowerCase()].userlist).remove();
732 return;
733 }
734
735 kiwi.front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '<-- ' + data.kicked + ' kicked by ' + data.nick + '(' + data.message + ')', 'action kick', 'color:#990000;');
736 kiwi.front.tabviews[data.channel.toLowerCase()].userlist.children().each(function () {
737 if ($(this).text() === data.nick) {
738 $(this).remove();
739 }
740 });
741 }
742 },
743 onNick: function (e, data) {
744 if (data.nick === kiwi.gateway.nick) {
745 kiwi.gateway.nick = data.newnick;
746 kiwi.front.doLayout();
747 }
748
749 $.each(kiwi.front.tabviews, function (i, item) {
750 $.each(kiwi.front.tabviews, function (i, item) {
751 item.changeNick(data.newnick, data.nick);
752 });
753 });
754 },
755 onQuit: function (e, data) {
756 $.each(kiwi.front.tabviews, function (i, item) {
757 $.each(kiwi.front.tabviews, function (i, item) {
758 item.userlist.children().each(function () {
759 if ($(this).text() === data.nick) {
760 $(this).remove();
761 item.addMsg(null, ' ', '<-- ' + data.nick + ' has quit (' + data.message + ')', 'action quit', 'color:#990000;');
762 }
763 });
764 });
765 });
766 },
767 onChannelRedirect: function (e, data) {
768 kiwi.front.tabviews[data.from.toLowerCase()].close();
769 kiwi.front.tabviewAdd(data.to.toLowerCase());
770 kiwi.front.tabviews[data.to.toLowerCase()].addMsg(null, ' ', '=== Redirected from ' + data.from, 'action');
771 },
772
773 onIRCError: function (e, data) {
774 var t_view;
775 if (data.channel !== undefined && kiwi.front.tabviewExists(data.channel)) {
776 t_view = data.channel;
777 } else {
778 t_view = 'server';
779 }
780
781 switch (data.error) {
782 case 'banned_from_channel':
783 kiwi.front.tabviews[t_view].addMsg(null, ' ', '=== You are banned from ' + data.channel + '. ' + data.reason, 'status');
784 if (t_view !== 'server') {
785 kiwi.front.tabviews[t_view].safe_to_close = true;
786 }
787 break;
788 case 'bad_channel_key':
789 kiwi.front.tabviews[t_view].addMsg(null, ' ', '=== Bad channel key for ' + data.channel, 'status');
790 if (t_view !== 'server') {
791 kiwi.front.tabviews[t_view].safe_to_close = true;
792 }
793 break;
794 case 'invite_only_channel':
795 kiwi.front.tabviews[t_view].addMsg(null, ' ', '=== ' + data.channel + ' is invite only.', 'status');
796 if (t_view !== 'server') {
797 kiwi.front.tabviews[t_view].safe_to_close = true;
798 }
799 break;
800 case 'channel_is_full':
801 kiwi.front.tabviews[t_view].addMsg(null, ' ', '=== ' + data.channel + ' is full.', 'status');
802 if (t_view !== 'server') {
803 kiwi.front.tabviews[t_view].safe_to_close = true;
804 }
805 break;
806 case 'chanop_privs_needed':
807 kiwi.front.tabviews[data.channel].addMsg(null, ' ', '=== ' + data.reason, 'status');
808 break;
809 case 'no_such_nick':
810 kiwi.front.tabviews.server.addMsg(null, ' ', '=== ' + data.nick + ': ' + data.reason, 'status');
811 break;
812 case 'nickname_in_use':
813 kiwi.front.tabviews.server.addMsg(null, ' ', '=== The nickname ' + data.nick + ' is already in use. Please select a new nickname', 'status');
814 kiwi.front.showChangeNick();
815 break;
816 default:
817 // We don't know what data contains, so don't do anything with it.
818 //kiwi.front.tabviews.server.addMsg(null, ' ', '=== ' + data, 'status');
819 }
820 },
821
822 registerKeys: function () {
823 $('#kiwi_msginput').bind('keydown', function (e) {
824 var windows, meta, num, msg, data, candidates, word_pos, word, i;
825 windows = $('#windows');
826 //var meta = e.altKey;
827 meta = e.ctrlKey;
828
829 switch (true) {
830 case (e.which >= 48) && (e.which <= 57):
831 if (meta) {
832 num = e.which - 48;
833 if (num === 0) {
834 num = 10;
835 }
836 num = num - 1;
837 kiwi.front.windowsShow(num);
838 return false;
839 }
840 break;
841 case e.which === 27: // escape
842 return false;
843 case e.which === 13: // return
844 msg = $('#kiwi_msginput').val();
845 msg = msg.trim();
846
847 kiwi.front.buffer.push(msg);
848 kiwi.front.buffer_pos = kiwi.front.buffer.length;
849
850 kiwi.front.run(msg);
851 $('#kiwi_msginput').val('');
852
853 break;
854 case e.which === 33: // page up
855 console.log("page up");
856 windows[0].scrollTop = windows[0].scrollTop - windows.height();
857 return false;
858 case e.which === 34: // page down
859 windows[0].scrollTop = windows[0].scrollTop + windows.height();
860 return false;
861 case e.which === 37: // left
862 if (meta) {
863 kiwi.front.windowsPrevious();
864 return false;
865 }
866 break;
867 case e.which === 38: // up
868 if (kiwi.front.buffer_pos > 0) {
869 kiwi.front.buffer_pos--;
870 $('#kiwi_msginput').val(kiwi.front.buffer[kiwi.front.buffer_pos]);
871 }
872 break;
873 case e.which === 39: // right
874 if (meta) {
875 kiwi.front.windowsNext();
876 return false;
877 }
878 break;
879 case e.which === 40: // down
880 if (kiwi.front.buffer_pos < kiwi.front.buffer.length) {
881 kiwi.front.buffer_pos++;
882 $('#kiwi_msginput').val(kiwi.front.buffer[kiwi.front.buffer_pos]);
883 }
884 break;
885
886 case e.which === 9: // tab
887 // Get possible autocompletions
888 data = [];
889 kiwi.front.cur_channel.userlist.children().each(function () {
890 var nick;
891 nick = kiwi.front.nickStripPrefix($('a.nick', this).text());
892 data.push(nick);
893 });
894
895 // Do the autocomplete
896 if (this.value.length === this.selectionStart && this.value.length === this.selectionEnd) {
897 candidates = [];
898
899 word_pos = this.value.lastIndexOf(' ');
900 word = "";
901 if (word_pos === -1) {
902 word = this.value;
903 } else {
904 word = this.value.substr(word_pos);
905 }
906 word = word.trim();
907
908 // filter data to find only strings that start with existing value
909 for (i = 0; i < data.length; i++) {
910 if (data[i].indexOf(word) === 0 && data[i].length > word.length) {
911 candidates.push(data[i]);
912 }
913 }
914
915 if (candidates.length > 0) {
916 // some candidates for autocompletion are found
917 this.value = this.value.substring(0, word_pos) + ' ' + candidates[0] + ': ';
918 this.selectionStart = this.value.length;
919 }
920 }
921 return false;
922 }
923 });
924
925
926 $('#kiwi .control .msginput .nick').click(function () {
927 kiwi.front.showChangeNick();
928 });
929
930
931
932
933
934 $('#kiwi .plugins .load_plugin_file').click(function () {
935 if (typeof kiwi.front.boxes.plugins !== "undefined") {
936 return;
937 }
938
939 kiwi.front.boxes.plugins = new Box("plugin_file");
940 $('#tmpl_plugins').tmpl({}).appendTo(kiwi.front.boxes.plugins.content);
941 kiwi.front.boxes.plugins.box.css('top', -(kiwi.front.boxes.plugins.height + 40));
942
943 // Populate the plugin list..
944 function enumPlugins() {
945 var lst, j, txt;
946 lst = $('#plugin_list');
947 lst.find('option').remove();
948 for (j in kiwi.plugs.loaded) {
949 txt = kiwi.plugs.loaded[j].name;
950 lst.append('<option value="' + txt + '">' + txt + '</option>');
951 }
952 }
953 enumPlugins();
954
955 // Event bindings
956 $('#kiwi .plugin_file').submit(function () {
957 $('<div></div>').load($('.txtpluginfile').val(), function (e) {
958 enumPlugins();
959 });
960 return false;
961 });
962 $('#kiwi .cancelpluginfile').click(function () {
963 kiwi.front.boxes.plugins.destroy();
964 });
965
966 $('#kiwi #plugins_list_unload').click(function () {
967 var selected_plugin;
968 selected_plugin = $('#plugin_list').val();
969 kiwi.plugs.unloadPlugin(selected_plugin);
970 enumPlugins();
971 });
972
973 $('#kiwi .txtpluginfile').focus();
974
975 });
976
977 $('#kiwi .plugins .reload_css').click(function () {
978 var links = document.getElementsByTagName("link"),
979 i;
980 for (i = 0; i < links.length; i++) {
981 if (links[i].rel === "stylesheet") {
982 if (links[i].href.indexOf("?") === -1) {
983 links[i].href += "?";
984 }
985 links[i].href += "x";
986 }
987 }
988 });
989
990
991 $('#kiwi .about .about_close').click(function () {
992 $('#kiwi .about').css('display', 'none');
993 });
994
995
996 $('#kiwi .poweredby').click(function () {
997 $('#kiwi .about').css('display', 'block');
998 });
999
1000 },
1001
1002
1003 showChangeNick: function () {
1004 $('#kiwi').append($('#tmpl_change_nick').tmpl({}));
1005
1006 $('#kiwi .form_newnick').submit(function () {
1007 kiwi.front.run('/NICK ' + $('#kiwi .txtnewnick').val());
1008 $('#kiwi .newnick').remove();
1009 return false;
1010 });
1011
1012 $('#kiwi .txtnewnick').keypress(function (ev) {
1013 if (!this.first_press) {
1014 this.first_press = true;
1015 return false;
1016 }
1017 });
1018
1019 $('#kiwi .txtnewnick').keydown(function (ev) {
1020 if (ev.which === 27) { // ESC
1021 $('#kiwi_msginput').focus();
1022 $('#kiwi .newnick').remove();
1023 }
1024 });
1025
1026 $('#kiwi .cancelnewnick').click(function () {
1027 $('#kiwi .newnick').remove();
1028 });
1029
1030 $('#kiwi .txtnewnick').focus();
1031 },
1032
1033
1034 tabviewExists: function (name) {
1035 return (typeof kiwi.front.tabviews[name.toLowerCase()] !== 'undefined');
1036 },
1037
1038 tabviewAdd: function (v_name) {
1039 /*global Tabview */
1040 var re, htmlsafe_name, tmp_divname, tmp_userlistname, tmp_tabname, userlist_enabled = true;
1041
1042 if (v_name.charAt(0) === kiwi.gateway.channel_prefix) {
1043 re = new RegExp(kiwi.gateway.channel_prefix, "g");
1044 htmlsafe_name = v_name.replace(re, 'pre');
1045 htmlsafe_name = "chan_" + htmlsafe_name;
1046 } else {
1047 htmlsafe_name = 'query_' + v_name;
1048 userlist_enabled = false;
1049 }
1050
1051 tmp_divname = 'kiwi_window_' + htmlsafe_name;
1052 tmp_userlistname = 'kiwi_userlist_' + htmlsafe_name;
1053 tmp_tabname = 'kiwi_tab_' + htmlsafe_name;
1054
1055 if (!kiwi.front.tabviewExists(v_name)) {
1056 $('#kiwi .windows .scroller').append('<div id="' + tmp_divname + '" class="messages"></div>');
1057 $('#kiwi .userlist').append('<ul id="' + tmp_userlistname + '"></ul>');
1058 $('#kiwi .windowlist ul').append('<li id="' + tmp_tabname + '" onclick="kiwi.front.tabviews[\'' + v_name.toLowerCase() + '\'].show();">' + v_name + '</li>');
1059 }
1060 //$('#kiwi .windowlist ul .window_'+v_name).click(function(){ kiwi.front.windowShow(v_name); });
1061 //kiwi.front.windowShow(v_name);
1062
1063 kiwi.front.tabviews[v_name.toLowerCase()] = new Tabview();
1064 kiwi.front.tabviews[v_name.toLowerCase()].name = v_name;
1065 kiwi.front.tabviews[v_name.toLowerCase()].div = $('#' + tmp_divname);
1066 kiwi.front.tabviews[v_name.toLowerCase()].userlist = $('#' + tmp_userlistname);
1067 kiwi.front.tabviews[v_name.toLowerCase()].tab = $('#' + tmp_tabname);
1068 if (!userlist_enabled) {
1069 kiwi.front.tabviews[v_name.toLowerCase()].userlist_width = 0;
1070 }
1071 kiwi.front.tabviews[v_name.toLowerCase()].show();
1072
1073 if (typeof registerTouches === "function") {
1074 //alert("Registering touch interface");
1075 //registerTouches($('#'+tmp_divname));
1076 registerTouches(document.getElementById(tmp_divname));
1077 }
1078 /*
1079 kiwi.front.tabviews[v_name.toLowerCase()].userlist.click(function(){
1080 alert($(this).attr('id'));
1081 });
1082 */
1083
1084 kiwi.front.doLayoutSize();
1085 },
1086
1087
1088 userClick: function (item) {
1089 var li = $(item).parent();
1090
1091 // Remove any existing userboxes
1092 $('#kiwi .userbox').remove();
1093
1094 if ($(li).data('userbox') === item) {
1095 $(li).removeData('userbox');
1096 } else {
1097 $('#tmpl_user_box').tmpl({nick: kiwi.front.nickStripPrefix($(item).text())}).appendTo(li);
1098
1099 $('#kiwi .userbox .userbox_query').click(function (ev) {
1100 var nick = $('#kiwi .userbox_nick').val();
1101 kiwi.front.run('/query ' + nick);
1102 });
1103
1104 $('#kiwi .userbox .userbox_whois').click(function (ev) {
1105 var nick = $('#kiwi .userbox_nick').val();
1106 kiwi.front.run('/whois ' + nick);
1107 });
1108 $(li).data('userbox', item);
1109 }
1110 },
1111
1112
1113 sync: function () {
1114 kiwi.gateway.sync();
1115 },
1116
1117 onSync: function (e, data) {
1118 // Set any settings
1119 if (data.nick !== undefined) {
1120 kiwi.gateway.nick = data.nick;
1121 }
1122
1123 // Add the tabviews
1124 if (data.tabviews !== undefined) {
1125 $.each(data.tabviews, function (i, tab) {
1126 if (!kiwi.front.tabviewExists(tab.name)) {
1127 kiwi.front.tabviewAdd(kiwi.gateway.channel_prefix + tab.name);
1128
1129 if (tab.userlist !== undefined) {
1130 kiwi.front.onUserList({'channel': kiwi.gateway.channel_prefix + tab.name, 'users': tab.userlist});
1131 }
1132 }
1133 });
1134 }
1135
1136 kiwi.front.doLayout();
1137 },
1138
1139
1140 setTopicText: function (new_topic) {
1141 kiwi.front.original_topic = new_topic;
1142 $('#kiwi .cur_topic .topic').text(kiwi.front.format(new_topic));
1143 kiwi.front.doLayoutSize();
1144 },
1145
1146 nickStripPrefix: function (nick) {
1147 var tmp = nick, i, prefix;
1148
1149 prefix = tmp.charAt(0);
1150 for (i in kiwi.gateway.user_prefixes) {
1151 if (kiwi.gateway.user_prefixes[i].symbol === prefix) {
1152 return tmp.substring(1);
1153 }
1154 }
1155
1156 return tmp;
1157 },
1158
1159 nickGetPrefix: function (nick) {
1160 var tmp = nick, i, prefix;
1161
1162 prefix = tmp.charAt(0);
1163 for (i in kiwi.gateway.user_prefixes) {
1164 if (kiwi.gateway.user_prefixes[i].symbol === prefix) {
1165 return prefix;
1166 }
1167 }
1168
1169 return '';
1170 },
1171
1172 isChannel: function (name) {
1173 var prefix, is_chan;
1174 prefix = name.charAt(0);
1175 if (kiwi.gateway.channel_prefix.indexOf(prefix) > -1) {
1176 is_chan = true;
1177 } else {
1178 is_chan = false;
1179 }
1180
1181 return is_chan;
1182 },
1183
1184 tabviewsNext: function () {
1185 var wl = $('#kiwi .windowlist ul'),
1186 next_left = parseInt(wl.css('text-indent').replace('px', ''), 10) + 170;
1187 wl.css('text-indent', next_left);
1188 },
1189
1190 tabviewsPrevious: function () {
1191 var wl = $('#kiwi .windowlist ul'),
1192 next_left = parseInt(wl.css('text-indent').replace('px', ''), 10) - 170;
1193 wl.css('text-indent', next_left);
1194 },
1195
1196 windowsNext: function () {
1197 var tab, next;
1198 next = false;
1199 for (tab in kiwi.front.tabviews) {
1200 if (!next) {
1201 if (kiwi.front.tabviews[tab] === kiwi.front.cur_channel) {
1202 next = true;
1203 continue;
1204 }
1205 } else {
1206 kiwi.front.tabviews[tab].show();
1207 return;
1208 }
1209 }
1210 },
1211
1212 windowsPrevious: function () {
1213 var tab, prev_tab, next;
1214 next = false;
1215 for (tab in kiwi.front.tabviews) {
1216 if (kiwi.front.tabviews[tab] === kiwi.front.cur_channel) {
1217 if (prev_tab) {
1218 prev_tab.show();
1219 }
1220 return;
1221 }
1222 prev_tab = kiwi.front.tabviews[tab];
1223 }
1224 },
1225
1226 windowsShow: function (num) {
1227 num = parseInt(num, 10);
1228 console.log('Showing window ' + num.toString());
1229 var i = 0, tab;
1230 for (tab in kiwi.front.tabviews) {
1231 if (i === num) {
1232 kiwi.front.tabviews[tab].show();
1233 return;
1234 }
1235 i++;
1236 }
1237 },
1238
1239
1240
1241 barsShow: function () {
1242 $('#kiwi .toolbars').slideDown();
1243 $('#kiwi .control').slideDown();
1244 },
1245
1246 barsHide: function () {
1247 $('#kiwi .toolbars').slideUp();
1248 $('#kiwi .control').slideUp();
1249 },
1250
1251 format: function (msg) {
1252 var re;
1253
1254 if ((!msg) || (typeof msg !== 'string')) {
1255 return;
1256 }
1257
1258 // bold
1259 if (msg.indexOf(String.fromCharCode(2)) !== -1) {
1260 next = '<b>';
1261 while (msg.indexOf(String.fromCharCode(2)) !== -1) {
1262 msg = msg.replace(String.fromCharCode(2), next);
1263 next = (next === '<b>') ? '</b>' : '<b>';
1264 }
1265 if (next === '</b>') {
1266 msg = msg + '</b>';
1267 }
1268 }
1269
1270 // underline
1271 if (msg.indexOf(String.fromCharCode(31)) !== -1) {
1272 next = '<u>';
1273 while (msg.indexOf(String.fromCharCode(31)) !== -1) {
1274 msg = msg.replace(String.fromCharCode(31), next);
1275 next = (next === '<u>') ? '</u>' : '<u>';
1276 }
1277 if (next === '</u>') {
1278 msg = msg + '</u>';
1279 }
1280 }
1281
1282 // colour
1283 re = /\x03([0-9][0-5]?)(,([0-9][0-5]?))?(.*?)\x03/g;
1284
1285 msg = msg.replace(re, function (str, p1, p2, p3, p4) {
1286 var fg, bg,
1287 col = function (num) {
1288 switch (parseInt(num, 10)) {
1289 case 0:
1290 return '#FFFFFF';
1291 case 1:
1292 return '#000000';
1293 case 2:
1294 return '#000080';
1295 case 3:
1296 return '#008000';
1297 case 4:
1298 return '#FF0000';
1299 case 5:
1300 return '#800040';
1301 case 6:
1302 return '#800080';
1303 case 7:
1304 return '#FF8040';
1305 case 8:
1306 return '#FFFF00';
1307 case 9:
1308 return '#80FF00';
1309 case 10:
1310 return '#008080';
1311 case 11:
1312 return '#00FFFF';
1313 case 12:
1314 return '#0000FF';
1315 case 13:
1316 return '#FF55FF';
1317 case 14:
1318 return '#808080';
1319 case 15:
1320 return '#C0C0C0';
1321 default:
1322 return null;
1323 }
1324 };
1325 fg = col(p1);
1326 bg = col(p3);
1327 return '<span style="' + ((fg !== null) ? 'color: ' + fg + '; ' : '') + ((bg !== null) ? 'background-color: ' + bg + ';' : '') + '">' + p4 + '</span>';
1328 });
1329 return msg;
1330 }
1331
1332 };
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349 /*
1350 * MISC VIEW
1351 */
1352
1353 var Utilityview = function (name) {
1354 var rand_name = randomString(15),
1355 tmp_divname = 'kiwi_window_' + rand_name,
1356 tmp_userlistname = 'kiwi_userlist_' + rand_name,
1357 tmp_tabname = 'kiwi_tab_' + rand_name;
1358
1359 this.name = rand_name;
1360 this.title = name;
1361 this.topic = ' ';
1362
1363 $('#kiwi .windows .scroller').append('<div id="' + tmp_divname + '" class="messages"></div>');
1364
1365 this.tab = $('<li id="' + tmp_tabname + '">' + this.title + '</li>');
1366 this.tab.click(function () {
1367 kiwi.front.utilityviews[rand_name.toLowerCase()].show();
1368 });
1369 $('#kiwi .utilityviewlist ul').append(this.tab);
1370
1371 this.div = $('#' + tmp_divname);
1372 this.div.css('overflow', 'hidden');
1373
1374 kiwi.front.utilityviews[rand_name.toLowerCase()] = this;
1375 };
1376
1377 Utilityview.prototype.name = null;
1378 Utilityview.prototype.title = null;
1379 Utilityview.prototype.div = null;
1380 Utilityview.prototype.tab = null;
1381 Utilityview.prototype.topic = ' ';
1382 Utilityview.prototype.show = function () {
1383 $('#kiwi .messages').removeClass("active");
1384 $('#kiwi .userlist ul').removeClass("active");
1385 $('#kiwi .toolbars ul li').removeClass("active");
1386
1387 $('#windows').css('overflow-y', 'hidden');
1388 $('#windows').css('right', 0);
1389 // Activate this tab!
1390 this.div.addClass('active');
1391 this.tab.addClass('active');
1392
1393 this.addPartImage();
1394
1395 kiwi.front.setTopicText(this.topic);
1396 kiwi.front.cur_channel = this;
1397
1398 // If we're using fancy scrolling, refresh it
1399 if (touch_scroll) {
1400 touch_scroll.refresh();
1401 }
1402 };
1403
1404 Utilityview.prototype.close = function () {
1405 this.div.remove();
1406 this.tab.remove();
1407
1408 if (kiwi.front.cur_channel === this) {
1409 kiwi.front.tabviews.server.show();
1410 }
1411 delete kiwi.front.utilityviews[this.name.toLowerCase()];
1412 };
1413
1414 Utilityview.prototype.addPartImage = function () {
1415 this.clearPartImage();
1416
1417 // We can't close this tab, so don't have the close image
1418 if (this.name === 'server') {
1419 return;
1420 }
1421
1422 var del_html = '<img src="/img/redcross.png" class="tab_part" />';
1423 this.tab.append(del_html);
1424
1425 $('.tab_part', this.tab).click(function () {
1426 if (kiwi.front.cur_channel.name !== 'server') {
1427 kiwi.front.cur_channel.close();
1428 }
1429 });
1430 };
1431
1432 Utilityview.prototype.clearPartImage = function () {
1433 $('#kiwi .toolbars .tab_part').remove();
1434 };
1435
1436
1437
1438
1439
1440 /*
1441 *
1442 * TABVIEWS
1443 *
1444 */
1445
1446
1447 var Tabview = function () {};
1448 Tabview.prototype.name = null;
1449 Tabview.prototype.div = null;
1450 Tabview.prototype.userlist = null;
1451 Tabview.prototype.userlist_width = 100; // 0 for disabled
1452 Tabview.prototype.tab = null;
1453 Tabview.prototype.topic = "";
1454 Tabview.prototype.safe_to_close = false; // If we have been kicked/banned/etc from this channel, don't wait for a part message
1455
1456 Tabview.prototype.show = function () {
1457 var w, u;
1458
1459 $('#kiwi .messages').removeClass("active");
1460 $('#kiwi .userlist ul').removeClass("active");
1461 $('#kiwi .toolbars ul li').removeClass("active");
1462
1463 w = $('#windows');
1464 u = $('#kiwi .userlist');
1465
1466 w.css('overflow-y', 'scroll');
1467
1468 // Set the window size accordingly
1469 this.setUserlistWidth();
1470
1471 // Activate this tab!
1472 this.div.addClass('active');
1473 if (this.userlist_width > 0) {
1474 this.userlist.addClass('active');
1475 // Enable the userlist resizer
1476 $('#nicklist_resize').css('display', 'block');
1477 } else {
1478 // Disable the userlist resizer
1479 $('#nicklist_resize').css('display', 'none');
1480 }
1481 this.tab.addClass('active');
1482
1483 // Add the part image to the tab
1484 this.addPartImage();
1485
1486 this.clearHighlight();
1487 kiwi.front.setTopicText(this.topic);
1488 kiwi.front.cur_channel = this;
1489
1490 // If we're using fancy scrolling, refresh it
1491 if (touch_scroll) {
1492 touch_scroll.refresh();
1493 }
1494
1495 this.scrollBottom();
1496 if (!touchscreen) {
1497 $('#kiwi_msginput').focus();
1498 }
1499 };
1500
1501 Tabview.prototype.close = function () {
1502 this.div.remove();
1503 this.userlist.remove();
1504 this.tab.remove();
1505
1506 if (kiwi.front.cur_channel === this) {
1507 kiwi.front.tabviews.server.show();
1508 }
1509 delete kiwi.front.tabviews[this.name.toLowerCase()];
1510 };
1511
1512 Tabview.prototype.setUserlistWidth = function (new_width) {
1513 var w, u;
1514 if (typeof new_width === 'number') {
1515 this.userlist_width = new_width;
1516 }
1517
1518 w = $('#windows');
1519 u = $('#kiwi .userlist');
1520
1521 // Set the window size accordingly
1522 if (this.userlist_width > 0) {
1523 u.width(this.userlist_width);
1524 w.css('right', u.outerWidth(true));
1525 } else {
1526 w.css('right', 0);
1527 }
1528 };
1529
1530 Tabview.prototype.addPartImage = function () {
1531 this.clearPartImage();
1532
1533 // We can't close this tab, so don't have the close image
1534 if (this.name === 'server') {
1535 return;
1536 }
1537
1538 var del_html = '<img src="/img/redcross.png" class="tab_part" />';
1539 this.tab.append(del_html);
1540
1541 $('.tab_part', this.tab).click(function () {
1542 if (kiwi.front.isChannel($(this).parent().text())) {
1543 kiwi.front.run("/part");
1544 } else {
1545 // Make sure we don't close the server tab
1546 if (kiwi.front.cur_channel.name !== 'server') {
1547 kiwi.front.cur_channel.close();
1548 }
1549 }
1550 });
1551 };
1552
1553 Tabview.prototype.clearPartImage = function () {
1554 $('#kiwi .toolbars .tab_part').remove();
1555 };
1556
1557 Tabview.prototype.addMsg = function (time, nick, msg, type, style) {
1558 var self, tmp, plugin_ret, i, d, re, line_msg, next;
1559
1560 self = this;
1561
1562 tmp = {msg: msg, time: time, nick: nick, tabview: this.name};
1563 tmp = kiwi.plugs.run('addmsg', tmp);
1564 if (!tmp) {
1565 return;
1566 }
1567
1568
1569 msg = tmp.msg;
1570 time = tmp.time;
1571 nick = tmp.nick;
1572
1573 if (time === null) {
1574 d = new Date();
1575 time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0");
1576 }
1577
1578 // The CSS class (action, topic, notice, etc)
1579 if (typeof type !== "string") {
1580 type = '';
1581 }
1582
1583 // Make sure we don't have NaN or something
1584 if (typeof msg !== "string") {
1585 msg = '';
1586 }
1587
1588 // Make the channels clickable
1589 re = new RegExp('\\B(' + kiwi.gateway.channel_prefix + '[^ ,.\\007]+)', 'g');
1590 msg = msg.replace(re, function (match) {
1591 return '<a class="chan">' + match + '</a>';
1592 });
1593
1594 msg = kiwi.front.format(msg);
1595
1596 // Build up and add the line
1597 line_msg = $('<div class="msg ' + type + '"><div class="time">' + time + '</div><div class="nick">' + nick + '</div><div class="text" style="' + style + '">' + msg + ' </div></div>');
1598 this.div.append(line_msg);
1599
1600 if (!touchscreen) {
1601 this.scrollBottom();
1602 } else {
1603 touch_scroll.refresh();
1604 //console.log(this.div.attr("scrollHeight") +" - "+ $('#windows').height());
1605 this.scrollBottom();
1606 //if(this.div.attr("scrollHeight") > $('#windows').height()){
1607 // touch_scroll.scrollTo(0, this.div.height());
1608 //}
1609 }
1610 };
1611
1612 Tabview.prototype.scrollBottom = function () {
1613 var w = $('#windows');
1614 w[0].scrollTop = w[0].scrollHeight;
1615 };
1616
1617 Tabview.prototype.changeNick = function (newNick, oldNick) {
1618 this.userlist.children().each(function () {
1619 var item = $('a.nick', this);
1620 if (kiwi.front.nickStripPrefix(item.text()) === oldNick) {
1621 item.text(kiwi.front.nickGetPrefix(item.text()) + newNick);
1622 document.temp_chan = 1;
1623 }
1624 });
1625
1626 if (typeof document.temp_chan !== "undefined") {
1627 this.addMsg(null, ' ', '=== ' + oldNick + ' is now known as ' + newNick, 'action changenick');
1628 delete document.temp_chan;
1629 this.userlistSort();
1630 }
1631 };
1632
1633 Tabview.prototype.userlistSort = function () {
1634 var ul = this.userlist,
1635 listitems = ul.children('li').get(),
1636 prefix;
1637 listitems.sort(function (a, b) {
1638 var compA = $(a).text().toUpperCase(),
1639 compB = $(b).text().toUpperCase(),
1640 i;
1641
1642 // Sort by prefixes first
1643 for (i in kiwi.gateway.user_prefixes) {
1644 prefix = kiwi.gateway.user_prefixes[i].symbol;
1645
1646 if (compA.charAt(0) === prefix && compB.charAt(0) === prefix) {
1647 // Both have the same prefix, string compare time
1648 return 0;
1649 }
1650
1651 if (compA.charAt(0) === prefix && compB.charAt(0) !== prefix) {
1652 return -1;
1653 }
1654
1655 if (compA.charAt(0) !== prefix && compB.charAt(0) === prefix) {
1656 return 1;
1657 }
1658 }
1659
1660 // No prefixes, compare by string
1661 return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
1662 });
1663 $.each(listitems, function (idx, itm) { ul.append(itm); });
1664 };
1665
1666 Tabview.prototype.highlight = function () {
1667 this.tab.addClass('highlight');
1668 };
1669 Tabview.prototype.activity = function () {
1670 this.tab.addClass('activity');
1671 };
1672 Tabview.prototype.clearHighlight = function () {
1673 this.tab.removeClass('highlight');
1674 this.tab.removeClass('activity');
1675 };
1676 Tabview.prototype.changeTopic = function (new_topic) {
1677 this.topic = new_topic;
1678 this.addMsg(null, ' ', '=== Topic for ' + this.name + ' is: ' + new_topic, 'topic');
1679 if (kiwi.front.cur_channel.name === this.name) {
1680 kiwi.front.setTopicText(new_topic);
1681 }
1682 };
1683
1684
1685
1686
1687
1688 var Box = function (classname) {
1689 this.id = randomString(10);
1690 var tmp = $('<div id="' + this.id + '" class="box ' + classname + '"><div class="boxarea"></div></div>');
1691 $('#kiwi').append(tmp);
1692 this.box = $('#' + this.id);
1693 this.content = $('#' + this.id + ' .boxarea');
1694
1695 this.box.draggable({ stack: ".box" });
1696 this.content.click(function () {});
1697 //this.box.click(function(){ $(this)..css });
1698 };
1699 Box.prototype.create = function (name, classname) {
1700
1701 };
1702 Box.prototype.id = null;
1703 Box.prototype.box = null;
1704 Box.prototype.content = null;
1705 Box.prototype.destroy = function () {
1706 var name;
1707 this.box.remove();
1708 for (name in kiwi.front.boxes) {
1709 if (kiwi.front.boxes[name].id === this.id) {
1710 delete kiwi.front.boxes[name];
1711 }
1712 }
1713 };
1714 Box.prototype.height = function () {
1715 return this.box.height();
1716 };