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