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