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