Merge pull request #26 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;">' + 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(new_topic);
1094 kiwi.front.doLayoutSize();
1095 },
1096
1097
1098
1099
1100
1101
1102
1103 nickStripPrefix: function (nick) {
1104 var tmp = nick, i, prefix;
1105
1106 prefix = tmp.charAt(0);
1107 for (i in kiwi.gateway.user_prefixes) {
1108 if (kiwi.gateway.user_prefixes[i].symbol === prefix) {
1109 return tmp.substring(1);
1110 }
1111 }
1112
1113 return tmp;
1114 },
1115
1116 nickGetPrefix: function (nick) {
1117 var tmp = nick, i, prefix;
1118
1119 prefix = tmp.charAt(0);
1120 for (i in kiwi.gateway.user_prefixes) {
1121 if (kiwi.gateway.user_prefixes[i].symbol === prefix) {
1122 return prefix;
1123 }
1124 }
1125
1126 return '';
1127 },
1128
1129 isChannel: function (name) {
1130 var prefix, is_chan;
1131 prefix = name.charAt(0);
1132 if (kiwi.gateway.channel_prefix.indexOf(prefix) > -1) {
1133 is_chan = true;
1134 } else {
1135 is_chan = false;
1136 }
1137
1138 return is_chan;
1139 },
1140
1141 tabviewsNext: 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 tabviewsPrevious: function () {
1148 var wl = $('#kiwi .windowlist ul'),
1149 next_left = parseInt(wl.css('text-indent').replace('px', ''), 10) - 170;
1150 wl.css('text-indent', next_left);
1151 },
1152
1153 windowsNext: function () {
1154 var tab, next;
1155 next = false;
1156 for (tab in kiwi.front.tabviews) {
1157 if (!next) {
1158 if (kiwi.front.tabviews[tab] === kiwi.front.cur_channel) {
1159 next = true;
1160 continue;
1161 }
1162 } else {
1163 kiwi.front.tabviews[tab].show();
1164 return;
1165 }
1166 }
1167 },
1168
1169 windowsPrevious: function () {
1170 var tab, prev_tab, next;
1171 next = false;
1172 for (tab in kiwi.front.tabviews) {
1173 if (kiwi.front.tabviews[tab] === kiwi.front.cur_channel) {
1174 if (prev_tab) {
1175 prev_tab.show();
1176 }
1177 return;
1178 }
1179 prev_tab = kiwi.front.tabviews[tab];
1180 }
1181 },
1182
1183 windowsShow: function (num) {
1184 num = parseInt(num, 10);
1185 console.log('Showing window ' + num.toString());
1186 var i = 0, tab;
1187 for (tab in kiwi.front.tabviews) {
1188 if (i === num) {
1189 kiwi.front.tabviews[tab].show();
1190 return;
1191 }
1192 i++;
1193 }
1194 },
1195
1196
1197
1198 barsShow: function () {
1199 $('#kiwi .toolbars').slideDown();
1200 $('#kiwi .control').slideDown();
1201 },
1202
1203 barsHide: function () {
1204 $('#kiwi .toolbars').slideUp();
1205 $('#kiwi .control').slideUp();
1206 }
1207 };
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224 /*
1225 * MISC VIEW
1226 */
1227
1228 var Utilityview = function (name) {
1229 var rand_name = randomString(15),
1230 tmp_divname = 'kiwi_window_' + rand_name,
1231 tmp_userlistname = 'kiwi_userlist_' + rand_name,
1232 tmp_tabname = 'kiwi_tab_' + rand_name;
1233
1234 this.name = rand_name;
1235 this.title = name;
1236 this.topic = ' ';
1237
1238 $('#kiwi .windows .scroller').append('<div id="' + tmp_divname + '" class="messages"></div>');
1239
1240 this.tab = $('<li id="' + tmp_tabname + '">' + this.title + '</li>');
1241 this.tab.click(function () {
1242 kiwi.front.utilityviews[rand_name.toLowerCase()].show();
1243 });
1244 $('#kiwi .utilityviewlist ul').append(this.tab);
1245
1246 this.div = $('#' + tmp_divname);
1247 this.div.css('overflow', 'hidden');
1248
1249 kiwi.front.utilityviews[rand_name.toLowerCase()] = this;
1250 };
1251
1252 Utilityview.prototype.name = null;
1253 Utilityview.prototype.title = null;
1254 Utilityview.prototype.div = null;
1255 Utilityview.prototype.tab = null;
1256 Utilityview.prototype.topic = ' ';
1257 Utilityview.prototype.show = function () {
1258 $('#kiwi .messages').removeClass("active");
1259 $('#kiwi .userlist ul').removeClass("active");
1260 $('#kiwi .toolbars ul li').removeClass("active");
1261
1262 $('#windows').css('overflow-y', 'hidden');
1263 $('#windows').css('right', 0);
1264 // Activate this tab!
1265 this.div.addClass('active');
1266 this.tab.addClass('active');
1267
1268 this.addPartImage();
1269
1270 kiwi.front.setTopicText(this.topic);
1271 kiwi.front.cur_channel = this;
1272
1273 // If we're using fancy scrolling, refresh it
1274 if (touch_scroll) {
1275 touch_scroll.refresh();
1276 }
1277 };
1278
1279 Utilityview.prototype.close = function () {
1280 this.div.remove();
1281 this.tab.remove();
1282
1283 if (kiwi.front.cur_channel === this) {
1284 kiwi.front.tabviews.server.show();
1285 }
1286 delete kiwi.front.utilityviews[this.name.toLowerCase()];
1287 };
1288
1289 Utilityview.prototype.addPartImage = function () {
1290 this.clearPartImage();
1291
1292 // We can't close this tab, so don't have the close image
1293 if (this.name === 'server') {
1294 return;
1295 }
1296
1297 var del_html = '<img src="/img/redcross.png" class="tab_part" />';
1298 this.tab.append(del_html);
1299
1300 $('.tab_part', this.tab).click(function () {
1301 if (kiwi.front.cur_channel.name !== 'server') {
1302 kiwi.front.cur_channel.close();
1303 }
1304 });
1305 };
1306
1307 Utilityview.prototype.clearPartImage = function () {
1308 $('#kiwi .toolbars .tab_part').remove();
1309 };
1310
1311
1312
1313
1314
1315 /*
1316 *
1317 * TABVIEWS
1318 *
1319 */
1320
1321
1322 var Tabview = function () {};
1323 Tabview.prototype.name = null;
1324 Tabview.prototype.div = null;
1325 Tabview.prototype.userlist = null;
1326 Tabview.prototype.userlist_width = 100; // 0 for disabled
1327 Tabview.prototype.tab = null;
1328 Tabview.prototype.topic = "";
1329 Tabview.prototype.safe_to_close = false; // If we have been kicked/banned/etc from this channel, don't wait for a part message
1330
1331 Tabview.prototype.show = function () {
1332 var w, u;
1333
1334 $('#kiwi .messages').removeClass("active");
1335 $('#kiwi .userlist ul').removeClass("active");
1336 $('#kiwi .toolbars ul li').removeClass("active");
1337
1338 w = $('#windows');
1339 u = $('#kiwi .userlist');
1340
1341 w.css('overflow-y', 'scroll');
1342
1343 // Set the window size accordingly
1344 this.setUserlistWidth();
1345
1346 // Activate this tab!
1347 this.div.addClass('active');
1348 if (this.userlist_width > 0) {
1349 this.userlist.addClass('active');
1350 // Enable the userlist resizer
1351 $('#nicklist_resize').css('display', 'block');
1352 } else {
1353 // Disable the userlist resizer
1354 $('#nicklist_resize').css('display', 'none');
1355 }
1356 this.tab.addClass('active');
1357
1358 // Add the part image to the tab
1359 this.addPartImage();
1360
1361 this.clearHighlight();
1362 kiwi.front.setTopicText(this.topic);
1363 kiwi.front.cur_channel = this;
1364
1365 // If we're using fancy scrolling, refresh it
1366 if (touch_scroll) {
1367 touch_scroll.refresh();
1368 }
1369
1370 this.scrollBottom();
1371 if (!touchscreen) {
1372 $('#kiwi_msginput').focus();
1373 }
1374 };
1375
1376 Tabview.prototype.close = function () {
1377 this.div.remove();
1378 this.userlist.remove();
1379 this.tab.remove();
1380
1381 if (kiwi.front.cur_channel === this) {
1382 kiwi.front.tabviews.server.show();
1383 }
1384 delete kiwi.front.tabviews[this.name.toLowerCase()];
1385 };
1386
1387 Tabview.prototype.setUserlistWidth = function (new_width) {
1388 var w, u;
1389 if (typeof new_width === 'number') {
1390 this.userlist_width = new_width;
1391 }
1392
1393 w = $('#windows');
1394 u = $('#kiwi .userlist');
1395
1396 // Set the window size accordingly
1397 if (this.userlist_width > 0) {
1398 u.width(this.userlist_width);
1399 w.css('right', u.outerWidth(true));
1400 } else {
1401 w.css('right', 0);
1402 }
1403 };
1404
1405 Tabview.prototype.addPartImage = function () {
1406 this.clearPartImage();
1407
1408 // We can't close this tab, so don't have the close image
1409 if (this.name === 'server') {
1410 return;
1411 }
1412
1413 var del_html = '<img src="/img/redcross.png" class="tab_part" />';
1414 this.tab.append(del_html);
1415
1416 $('.tab_part', this.tab).click(function () {
1417 if (kiwi.front.isChannel($(this).parent().text())) {
1418 kiwi.front.run("/part");
1419 } else {
1420 // Make sure we don't close the server tab
1421 if (kiwi.front.cur_channel.name !== 'server') {
1422 kiwi.front.cur_channel.close();
1423 }
1424 }
1425 });
1426 };
1427
1428 Tabview.prototype.clearPartImage = function () {
1429 $('#kiwi .toolbars .tab_part').remove();
1430 };
1431
1432 Tabview.prototype.addMsg = function (time, nick, msg, type, style) {
1433 var self, tmp, plugin_ret, i, d, re, line_msg, next;
1434
1435 self = this;
1436
1437 tmp = {msg: msg, time: time, nick: nick, tabview: this.name};
1438 tmp = kiwi.plugs.run('addmsg', tmp);
1439 if (!tmp) {
1440 return;
1441 }
1442
1443
1444 msg = tmp.msg;
1445 time = tmp.time;
1446 nick = tmp.nick;
1447
1448 if (time === null) {
1449 d = new Date();
1450 time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0");
1451 }
1452
1453 // The CSS class (action, topic, notice, etc)
1454 if (typeof type !== "string") {
1455 type = '';
1456 }
1457
1458 // Make sure we don't have NaN or something
1459 if (typeof msg !== "string") {
1460 msg = '';
1461 }
1462
1463 // Text formatting
1464 // bold
1465 if (msg.indexOf(String.fromCharCode(2)) !== -1) {
1466 next = '<b>';
1467 while (msg.indexOf(String.fromCharCode(2)) !== -1) {
1468 msg = msg.replace(String.fromCharCode(2), next);
1469 next = (next === '<b>') ? '</b>' : '<b>';
1470 }
1471 if (next === '</b>') {
1472 msg = msg + '</b>';
1473 }
1474 }
1475
1476 // Wierd thing noticed by Dux0r on the irc.esper.net server
1477 if (typeof msg !== "string") {
1478 msg = '';
1479 }
1480
1481 // underline
1482 if (msg.indexOf(String.fromCharCode(31)) !== -1) {
1483 next = '<u>';
1484 while (msg.indexOf(String.fromCharCode(31)) !== -1) {
1485 msg = msg.replace(String.fromCharCode(31), next);
1486 next = (next === '<u>') ? '</u>' : '<u>';
1487 }
1488 if (next === '</u>') {
1489 msg = msg + '</u>';
1490 }
1491 }
1492
1493 // Make the channels clickable
1494 re = new RegExp('\\B(' + kiwi.gateway.channel_prefix + '[^ ,.\\007]+)', 'g');
1495 msg = msg.replace(re, function (match) {
1496 return '<a class="chan">' + match + '</a>';
1497 });
1498
1499 // Build up and add the line
1500 line_msg = $('<div class="msg ' + type + '"><div class="time">' + time + '</div><div class="nick">' + nick + '</div><div class="text" style="' + style + '">' + msg + ' </div></div>');
1501 this.div.append(line_msg);
1502
1503 if (!touchscreen) {
1504 this.scrollBottom();
1505 } else {
1506 touch_scroll.refresh();
1507 //console.log(this.div.attr("scrollHeight") +" - "+ $('#windows').height());
1508 this.scrollBottom();
1509 //if(this.div.attr("scrollHeight") > $('#windows').height()){
1510 // touch_scroll.scrollTo(0, this.div.height());
1511 //}
1512 }
1513 };
1514
1515 Tabview.prototype.scrollBottom = function () {
1516 var w = $('#windows');
1517 w[0].scrollTop = w[0].scrollHeight;
1518 };
1519
1520 Tabview.prototype.changeNick = function (newNick, oldNick) {
1521 this.userlist.children().each(function () {
1522 var item = $('a.nick', this);
1523 if (kiwi.front.nickStripPrefix(item.text()) === oldNick) {
1524 item.text(kiwi.front.nickGetPrefix(item.text()) + newNick);
1525 document.temp_chan = 1;
1526 }
1527 });
1528
1529 if (typeof document.temp_chan !== "undefined") {
1530 this.addMsg(null, ' ', '=== ' + oldNick + ' is now known as ' + newNick, 'action changenick');
1531 delete document.temp_chan;
1532 this.userlistSort();
1533 }
1534 };
1535
1536 Tabview.prototype.userlistSort = function () {
1537 var ul = this.userlist,
1538 listitems = ul.children('li').get(),
1539 prefix;
1540 listitems.sort(function (a, b) {
1541 var compA = $(a).text().toUpperCase(),
1542 compB = $(b).text().toUpperCase(),
1543 i;
1544
1545 // Sort by prefixes first
1546 for (i in kiwi.gateway.user_prefixes) {
1547 prefix = kiwi.gateway.user_prefixes[i].symbol;
1548
1549 if (compA.charAt(0) === prefix && compB.charAt(0) === prefix) {
1550 // Both have the same prefix, string compare time
1551 return 0;
1552 }
1553
1554 if (compA.charAt(0) === prefix && compB.charAt(0) !== prefix) {
1555 return -1;
1556 }
1557
1558 if (compA.charAt(0) !== prefix && compB.charAt(0) === prefix) {
1559 return 1;
1560 }
1561 }
1562
1563 // No prefixes, compare by string
1564 return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
1565 });
1566 $.each(listitems, function (idx, itm) { ul.append(itm); });
1567 };
1568
1569 Tabview.prototype.highlight = function () {
1570 this.tab.addClass('highlight');
1571 };
1572 Tabview.prototype.activity = function () {
1573 this.tab.addClass('activity');
1574 };
1575 Tabview.prototype.clearHighlight = function () {
1576 this.tab.removeClass('highlight');
1577 this.tab.removeClass('activity');
1578 };
1579 Tabview.prototype.changeTopic = function (new_topic) {
1580 this.topic = new_topic;
1581 this.addMsg(null, ' ', '=== Topic for ' + this.name + ' is: ' + new_topic, 'topic');
1582 if (kiwi.front.cur_channel.name === this.name) {
1583 kiwi.front.setTopicText(new_topic);
1584 }
1585 };
1586
1587
1588
1589
1590
1591 var Box = function (classname) {
1592 this.id = randomString(10);
1593 var tmp = $('<div id="' + this.id + '" class="box ' + classname + '"><div class="boxarea"></div></div>');
1594 $('#kiwi').append(tmp);
1595 this.box = $('#' + this.id);
1596 this.content = $('#' + this.id + ' .boxarea');
1597
1598 this.box.draggable({ stack: ".box" });
1599 this.content.click(function () {});
1600 //this.box.click(function(){ $(this)..css });
1601 };
1602 Box.prototype.create = function (name, classname) {
1603
1604 };
1605 Box.prototype.id = null;
1606 Box.prototype.box = null;
1607 Box.prototype.content = null;
1608 Box.prototype.destroy = function () {
1609 var name;
1610 this.box.remove();
1611 for (name in kiwi.front.boxes) {
1612 if (kiwi.front.boxes[name].id === this.id) {
1613 delete kiwi.front.boxes[name];
1614 }
1615 }
1616 };
1617 Box.prototype.height = function () {
1618 return this.box.height();
1619 };