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