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