CTCP handling
[KiwiIRC.git] / js / front.js
1 var front = {
2 revision: 38,
3
4 cur_channel: '',
5 windows: {},
6 tabviews: {},
7 boxes: {},
8
9 buffer: [],
10 buffer_pos: 0,
11
12 init: function () {
13 gateway.nick = 'kiwi_' + Math.ceil(100 * Math.random()) + Math.ceil(100 * Math.random());
14 gateway.session_id = null;
15
16 $(gateway).bind("onmsg", front.onMsg);
17 $(gateway).bind("onnotice", front.onNotice);
18 $(gateway).bind("onaction", front.onAction);
19 $(gateway).bind("onmotd", front.onMOTD);
20 $(gateway).bind("onoptions", front.onOptions);
21 $(gateway).bind("onconnect", front.onConnect);
22 $(gateway).bind("ondisconnect", front.onDisconnect);
23 $(gateway).bind("onnick", front.onNick);
24 $(gateway).bind("onuserlist", front.onUserList);
25 $(gateway).bind("onuserlist_end", front.onUserListEnd);
26 $(gateway).bind("onjoin", front.onJoin);
27 $(gateway).bind("ontopic", front.onTopic);
28 $(gateway).bind("onpart", front.onPart);
29 $(gateway).bind("onkick", front.onKick);
30 $(gateway).bind("onquit", front.onQuit);
31 $(gateway).bind("onwhois", front.onWhois);
32 $(gateway).bind("onsync", front.onSync);
33 $(gateway).bind("onchannel_redirect", front.onChannelRedirect);
34 $(gateway).bind("ondebug", front.onDebug);
35 $(dateway).bind("onctcp_request", front.onCTCPRequest);
36 $(dateway).bind("onctcp_response", front.onCTCPResponse);
37
38 this.buffer = [];
39
40 // Build the about box
41 front.boxes.about = new box("about");
42 var about_info = 'UI adapted for ' + agent;
43 if (touchscreen) about_info += ' touchscreen ';
44 about_info += 'usage';
45 $('#tmpl_about_box').tmpl({
46 about:about_info,
47 front_revision:front.revision,
48 gateway_revision:gateway.revision
49 }).appendTo(front.boxes.about.content);
50
51 //$(window).bind("beforeunload", function(){ gateway.quit(); });
52
53 if(touchscreen){
54 $('#kiwi').addClass('touchscreen');
55
56 // Single touch scrolling through scrollback for touchscreens
57 scroll_opts = {};
58 touch_scroll = new iScroll('windows', scroll_opts);
59 }
60
61 front.registerKeys();
62
63 $('#kiwi .cur_topic').resize(front.doLayoutSize);
64
65 $('#kiwi .formconnectwindow').submit(function () {
66 var netsel = $('#kiwi .formconnectwindow .network');
67 var nick = $('#kiwi .formconnectwindow .nick');
68
69 if (nick.val() === '') {
70 nick.val('Nick please!');
71 nick.focus();
72 return false;
73 }
74
75 var tmp = nick.val().split(' ');
76 gateway.nick = tmp[0];
77 front.doLayout();
78 try {
79 front.run('/connect ' + netsel.val());
80 } catch (e) {
81 alert(e);
82 }
83
84 $('#kiwi .connectwindow').slideUp();
85 $('#windows').click(function(){ $('#kiwi_msginput').focus(); });
86
87 return false;
88 });
89
90 var supportsOrientationChange = "onorientationchange" in window,
91 orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
92 window.addEventListener(orientationEvent, front.doLayoutSize, false);
93 //$('#kiwi').bind("resize", front.doLayoutSize, false);
94
95 front.doLayout();
96 //front.windowAdd('server');
97 front.tabviewAdd('server');
98
99 // Any pre-defined nick?
100 if (typeof init_data.nick === "string") {
101 $('#kiwi .formconnectwindow .nick').val(init_data.nick);
102 }
103
104 //gateway.session_id = 'testses';
105
106 gateway.start();
107 //front.sync();
108 },
109
110 doLayoutSize: function () {
111 var kiwi = $('#kiwi');
112 if (kiwi.width() < 330 && !kiwi.hasClass('small_kiwi')) {
113 console.log("switching to small kiwi");
114 kiwi.removeClass('large_kiwi');
115 kiwi.addClass('small_kiwi');
116 } else if (kiwi.width() >= 330 && !kiwi.hasClass('large_kiwi')) {
117 kiwi.removeClass('small_kiwi');
118 kiwi.addClass('large_kiwi');
119 }
120
121 var ct = $('#kiwi .cur_topic');
122 var ul = $('#kiwi .userlist');
123
124 var n_top = parseInt(ct.offset().top) + parseInt(ct.height());
125 n_top = n_top + parseInt(ct.css('border-top-width').replace('px', ''));
126 n_top = n_top + parseInt(ct.css('border-bottom-width').replace('px', ''));
127 n_top = n_top + parseInt(ct.css('padding-top').replace('px', ''));
128 n_top = n_top + parseInt(ct.css('padding-bottom').replace('px', ''));
129 n_top = n_top + 1; // Dunno why this is needed.. but it's always 1 px out :/
130
131 var n_bottom = $(document).height() - parseInt($('#kiwi .control').offset().top);
132
133 $('#kiwi .windows').css({top: n_top + 'px', bottom: n_bottom + 'px'});
134 $('#kiwi .userlist').css({top: n_top + 'px', bottom: n_bottom + 'px'});
135 },
136
137
138 doLayout: function () {
139 $('#kiwi .msginput .nick a').text(gateway.nick);
140 $('#kiwi_msginput').val(' ');
141 $('#kiwi_msginput').focus();
142 },
143
144
145 joinChannel: function (chan_name) {
146 var chans = chan_name.split(','),
147 i;
148 for (i in chans) {
149 chan = chans[i];
150 if (front.tabviews[chan.toLowerCase()] === undefined) {
151 gateway.join(chan);
152 front.tabviewAdd(chan);
153 } else {
154 front.tabviews[chan.toLowerCase()].show();
155 }
156 }
157 },
158
159
160 run: function (msg) {
161 console.log("running "+msg);
162 if (msg.substring(0, 1) === '/') {
163 var parts = msg.split(' ');
164 switch (parts[0].toLowerCase()) {
165 case '/j':
166 case '/join':
167 front.joinChannel(parts[1]);
168 break;
169
170 case '/connect':
171 case '/server':
172 if (parts[1] === undefined) {
173 alert('Usage: /connect servername [port]');
174 break;
175 }
176
177 if (parts[2] === undefined) {
178 parts[2] = 6667;
179 }
180 front.cur_channel.addMsg(null, ' ', '=== Connecting to ' + parts[1] + '...', 'status');
181 gateway.connect(parts[1], parts[2], 0);
182 break;
183
184 case '/nick':
185 console.log("/nick");
186 if (parts[1] === undefined) {
187 console.log("calling show nick");
188 front.showChangeNick();
189 } else {
190 console.log("sending raw");
191 gateway.raw(msg.substring(1));
192 }
193 break;
194
195 case '/part':
196 if (typeof parts[1] === "undefined") {
197 gateway.raw(msg.substring(1) + ' ' + front.cur_channel.name);
198 } else {
199 gateway.raw(msg.substring(1));
200 }
201 break;
202
203 case '/names':
204 if (typeof parts[1] !== "undefined") {
205 gateway.raw(msg.substring(1));
206 }
207 break;
208
209 case '/debug':
210 gateway.debug();
211 break;
212
213 case '/q':
214 case '/query':
215 if (typeof parts[1] !== "undefined") {
216 front.tabviewAdd(parts[1]);
217 }
218 break;
219
220 case '/quote':
221 gateway.raw(msg.replace(/^\/quote /i, ''));
222 break;
223
224 case '/me':
225 gateway.action(front.cur_channel.name, msg.substring(4));
226 //front.tabviews[destination.toLowerCase()].addMsg(null, ' ', '* '+data.nick+' '+data.msg, 'color:green;');
227 front.cur_channel.addMsg(null, ' ', '* ' + gateway.nick + ' ' + msg.substring(4), 'action', 'color:#555;');
228 break;
229
230 case '/notice':
231 var dest, msg;
232 dest = parts[1];
233 msg = parts.slice(2).join(' ');
234
235 gateway.notice(dest, msg);
236 this.onNotice({}, {nick:gateway.nick, channel:dest, msg:msg});
237 break;
238
239 case '/win':
240 if (parts[1] !== undefined) {
241 front.windowsShow(parseInt(parts[1]));
242 }
243 break;
244
245 case '/quit':
246 gateway.quit(msg.split(" ",2)[1]);
247 break;
248
249 default:
250 //front.cur_channel.addMsg(null, ' ', '--> Invalid command: '+parts[0].substring(1));
251 gateway.raw(msg.substring(1));
252 }
253
254 } else {
255 //alert('Sending message: '+msg);
256 if (msg.trim() === '') {
257 return;
258 }
259 gateway.msg(front.cur_channel.name, msg);
260 var d = new Date();
261 d = d.getHours() + ":" + d.getMinutes();
262 //front.addMsg(d, gateway.nick, msg);
263 front.cur_channel.addMsg(null, gateway.nick, msg);
264 }
265 },
266
267
268 onMsg: function (e, data) {
269 var destination;
270 // Is this message from a user?
271 if (data.channel === gateway.nick) {
272 destination = data.nick.toLowerCase();
273 } else {
274 destination = data.channel.toLowerCase();
275 }
276
277 if (!front.tabviewExists(destination)) {
278 front.tabviewAdd(destination);
279 }
280 front.tabviews[destination].addMsg(null, data.nick, data.msg);
281 },
282
283 onDebug: function (e, data) {
284 if (!front.tabviewExists('kiwi_debug')) {
285 front.tabviewAdd('kiwi_debug');
286 }
287 front.tabviews.kiwi_debug.addMsg(null, ' ', data.msg);
288 },
289
290 onAction: function (e, data) {
291 var destination;
292 // Is this message from a user?
293 if (data.channel === gateway.nick) {
294 destination = data.nick;
295 } else {
296 destination = data.channel;
297 }
298
299 if (!front.tabviewExists(destination)) {
300 front.tabviewAdd(destination);
301 }
302 front.tabviews[destination.toLowerCase()].addMsg(null, ' ', '* ' + data.nick + ' ' + data.msg, 'action', 'color:#555;');
303 },
304
305 onTopic: function (e, data) {
306 if (front.tabviewExists(data.channel)) {
307 front.tabviews[data.channel.toLowerCase()].changeTopic(data.topic);
308 }
309 },
310
311 onNotice: function (e, data) {
312 var nick = (data.nick === "") ? "" : '[' + data.nick + ']';
313 if (data.channel !== undefined) {
314 //alert('notice for '+data.channel);
315 if (front.tabviewExists(data.channel)) {
316 front.tabviews[data.channel.toLowerCase()].addMsg(null, nick, data.msg, 'notice');
317 }
318 } else {
319 //alert('direct notice');
320 front.tabviews.server.addMsg(null, nick, data.msg, 'notice');
321 }
322 },
323
324 onCTCPRequest: function (e, data) {
325 var msg = data.msg.split(" ", 2);
326 switch (msg[0]) {
327 case 'PING':
328 gateway.notice(data.nick, '\001PING ' + msg[1] + '\001');
329 break;
330 case 'TIME';
331 gateway.notice(data.nick, '\001TIME ' + (new Date()).toLocaleString() + '\001');
332 break;
333 }
334 front.tabviews.server.addMsg(null, data.server, data.msg, 'ctcp');
335 },
336
337 on CTCPResponse: function(e, data) {
338 },
339
340 onConnect: function (e, data) {
341 if (data.connected) {
342 front.tabviews.server.addMsg(null, ' ', '=== Connected OK :)', 'status');
343 if (typeof init_data.channel === "string") {
344 front.joinChannel(init_data.channel);
345 }
346 } else {
347 front.tabviews.server.addMsg(null, ' ', '=== Failed to connect :(', 'status');
348 }
349 },
350 onDisconnect: function(e, data){
351 var tab;
352 for(tab in front.tabviews){
353 front.tabviews[tab].addMsg(null, '', 'Disconnected from server!', 'error')
354 }
355 },
356 onOptions: function (e, data) {
357 if (typeof gateway.network_name === "string" && gateway.network_name !== "") {
358 front.tabviews.server.tab.text(gateway.network_name);
359 }
360 },
361 onMOTD: function (e, data) {
362 front.tabviews.server.addMsg(null, data.server, data.msg, 'motd');
363 },
364 onWhois: function (e, data) {
365 var d;
366 if (data.msg) {
367 front.cur_channel.addMsg(null, data.nick, data.msg, 'whois');
368 } else if (data.logon) {
369 d = new Date();
370 d.setTime(data.logon * 1000);
371 d = d.toLocaleString();
372 front.cur_channel.addMsg(null, data.nick, 'idle for ' + data.idle + ' second' + ((data.idle !== 1) ? 's' : '') + ', signed on ' + d, 'whois');
373 } else {
374 front.cur_channel.addMsg(null, data.nick, 'idle for ' + data.idle + ' seconds', 'whois');
375 }
376 },
377 onUserList: function (e, data) {
378 if (front.tabviews[data.channel.toLowerCase()] === undefined) {
379 return;
380 }
381 var ul = front.tabviews[data.channel.toLowerCase()].userlist;
382
383 if (!document.userlist_updating) {
384 document.userlist_updating = true;
385 ul.empty();
386 }
387
388 $.each(data.users, function (i, item) {
389 var nick = i; //i.match(/^.+!/g);
390 var mode = item;
391 $('<li><a class="nick" onclick="front.userClick(this);">' + mode + nick + '</a></li>').appendTo(ul);
392 });
393
394 front.tabviews[data.channel.toLowerCase()].userlistSort();
395 },
396 onUserListEnd: function (e, data) {
397 document.userlist_updating = false;
398 },
399
400 onJoin: function (e, data) {
401 if (!front.tabviewExists(data.channel)) {
402 front.tabviewAdd(data.channel.toLowerCase());
403 }
404
405 if (data.nick === gateway.nick) {
406 return; // Not needed as it's already in nicklist
407 }
408 front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '--> ' + data.nick + ' has joined', 'action', 'color:#009900;');
409 $('<li><a class="nick" onclick="front.userClick(this);">' + data.nick + '</a></li>').appendTo(front.tabviews[data.channel.toLowerCase()].userlist);
410 front.tabviews[data.channel.toLowerCase()].userlistSort();
411 },
412 onPart: function (e, data) {
413 if (front.tabviewExists(data.channel)) {
414 // If this is us, close the tabview
415 if (data.nick === gateway.nick) {
416 front.tabviews[data.channel.toLowerCase()].close();
417 front.tabviews.server.show();
418 return;
419 }
420
421 front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '<-- ' + data.nick + ' has left (' + data.message + ')', 'action', 'color:#990000;');
422 front.tabviews[data.channel.toLowerCase()].userlist.children().each(function () {
423 if ($(this).text() === data.nick) {
424 $(this).remove();
425 }
426 });
427 }
428 },
429 onKick: function (e, data) {
430 if (front.tabviewExists(data.channel)) {
431 // If this is us, close the tabvi ew
432 if (data.kicked === gateway.nick) {
433 front.tabviews[data.channel.toLowerCase()].close();
434 return;
435 }
436
437 front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '<-- ' + data.kicked + ' kicked by ' + data.nick + '(' + data.message + ')', 'action', 'color:#990000;');
438 front.tabviews[data.channel.toLowerCase()].userlist.children().each(function () {
439 if ($(this).text() === data.nick) {
440 $(this).remove();
441 }
442 });
443 }
444 },
445 onNick: function (e, data) {
446 if (data.nick === gateway.nick) {
447 gateway.nick = data.newnick;
448 front.doLayout();
449 }
450
451 $.each(front.tabviews, function (i, item) {
452 $.each(front.tabviews, function (i, item) {
453 item.changeNick(data.newnick, data.nick);
454 });
455 });
456 },
457 onQuit: function (e, data) {
458 $.each(front.tabviews, function (i, item) {
459 $.each(front.tabviews, function (i, item) {
460 item.userlist.children().each(function () {
461 if ($(this).text() === data.nick) {
462 $(this).remove();
463 item.addMsg(null, ' ', '<-- ' + data.nick + ' has quit (' + data.message + ')', 'action', 'color:#990000;');
464 }
465 });
466 });
467 });
468 },
469 onChannelRedirect: function (e, data) {
470 front.tabviews[data.from.toLowerCase()].close();
471 front.tabviewAdd(data.to.toLowerCase());
472 front.tabviews[data.to.toLowerCase()].addMsg(null, ' ', '=== Redirected from ' + data.from, 'action');
473 },
474
475 registerKeys: function () {
476 $('#kiwi_msginput').bind('keydown', function (e) {
477 var windows = $('#windows');
478 console.log(e.which);
479 //$('input').keypress(function(e){
480 switch (true) {
481 case (e.which >= 48) && (e.which <= 57):
482 if(e.altKey){
483 var num = e.which - 48;
484 if(num === 0) num = 10;
485 num = num - 1;
486 front.windowsShow(num);
487 return false;
488 }
489 break;
490 case e.which === 27: // escape
491 return false;
492 case e.which === 13: // return
493 var msg = $('#kiwi_msginput').val();
494 msg = msg.trim();
495
496 front.buffer.push(msg);
497 front.buffer_pos = front.buffer.length;
498
499 front.run(msg);
500 $('#kiwi_msginput').val('');
501
502 break;
503 case e.which === 33: // page up
504 console.log("page up");
505 windows[0].scrollTop = windows[0].scrollTop - windows.height();
506 return false;
507 break;
508 case e.which === 34: // page down
509 windows[0].scrollTop = windows[0].scrollTop + windows.height();
510 return false;
511 break;
512 case e.which === 37: // left
513 if(e.altKey){
514 front.windowsPrevious();
515 return false;
516 }
517 break;
518 case e.which === 38: // up
519 if (front.buffer_pos > 0) {
520 front.buffer_pos--;
521 $('#kiwi_msginput').val(front.buffer[front.buffer_pos]);
522 }
523 break;
524 case e.which === 39: // right
525 if(e.altKey){
526 front.windowsNext();
527 return false;
528 }
529 break;
530 case e.which === 40: // down
531 if (front.buffer_pos < front.buffer.length) {
532 front.buffer_pos++;
533 $('#kiwi_msginput').val(front.buffer[front.buffer_pos]);
534 }
535 break;
536
537 case e.which === 9: // tab
538 // Get possible autocompletions
539 var data = [];
540 front.cur_channel.userlist.children().each(function () {
541 nick = front.nickStripPrefix($('a.nick', this).text());
542 data.push(nick);
543 });
544
545 // Do the autocomplete
546 if (this.value.length === this.selectionStart && this.value.length === this.selectionEnd) {
547 var candidates = [];
548
549 var word_pos = this.value.lastIndexOf(' ');
550 var word = "";
551 if (word_pos === -1) {
552 word = this.value;
553 } else {
554 word = this.value.substr(word_pos);
555 }
556 word = word.trim();
557
558 // filter data to find only strings that start with existing value
559 for (i = 0; i < data.length; i++) {
560 if (data[i].indexOf(word) === 0 && data[i].length > word.length) {
561 candidates.push(data[i]);
562 }
563 }
564
565 if (candidates.length > 0) {
566 // some candidates for autocompletion are found
567 this.value = this.value.substring(0, word_pos) + ' ' + candidates[0] + ': ';
568 this.selectionStart = this.value.length;
569 }
570 }
571 return false;
572 }
573 });
574
575
576 $('#kiwi .control .msginput .nick').click(function () {
577 front.showChangeNick();
578 });
579
580
581
582
583
584 $('#kiwi .plugins .load_plugin_file').click(function () {
585 if (typeof front.boxes.plugins !== "undefined") {
586 return;
587 }
588
589 front.boxes.plugins = new box("plugin_file");
590 $('#tmpl_plugins').tmpl({}).appendTo(front.boxes.plugins.content);
591 front.boxes.plugins.box.css('top', -(front.boxes.plugins.height + 40));
592
593 // Populate the plugin list..
594 var lst = $('#plugin_list');
595 lst.find('option').remove();
596 var j;
597 for (j in plugins.privmsg) {
598 var txt = plugins.privmsg[j].name;
599 lst.append('<option value="' + txt + '">' + txt + '</option>');
600 }
601
602 // Event bindings
603 $('#kiwi .plugin_file').submit(function () {
604 $.getJSON($('.txtpluginfile').val(), function (data) {
605 var plg = {};
606 plg.name = data.name;
607 eval("plg.onprivmsg = " + data.onprivmsg);
608 eval("plg.onload = " + data.onload);
609 eval("plg.onunload = " + data.onunload);
610 plugins.privmsg.push(plg);
611
612 if (plg.onload instanceof Function) {
613 plg.onload();
614 }
615 });
616 return false;
617 });
618 $('#kiwi .cancelpluginfile').click(function () {
619 front.boxes.plugins.destroy();
620 });
621
622 $('#kiwi #plugins_list_unload').click(function () {
623 var selected_plugin = $('#plugin_list').val();
624 console.log("removing plugin: "+selected_plugin);
625 for (var i in plugins.privmsg) {
626 if (plugins.privmsg[i].name === selected_plugin) {
627 if (plugins.privmsg[i].onunload instanceof Function)
628 plugins.privmsg[i].onunload();
629
630 delete plugins.privmsg[i];
631 }
632 }
633 });
634
635 $('#kiwi .txtpluginfile').focus();
636
637 });
638
639 $('#kiwi .plugins .reload_css').click(function () {
640 var links = document.getElementsByTagName("link");
641 for (var i=0; i < links.length; i++) {
642 if (links[i].rel === "stylesheet") {
643 if (links[i].href.indexOf("?")===-1) {
644 links[i].href += "?";
645 }
646 links[i].href += "x";
647 }
648 }
649 });
650
651
652 $('#kiwi .about .about_close').click(function () {
653 $('#kiwi .about').css('display', 'none');
654 });
655
656
657 $('#kiwi .poweredby').click(function () {
658 $('#kiwi .about').css('display', 'block');
659 });
660
661 },
662
663
664 showChangeNick: function(){
665 $('#kiwi').append($('#tmpl_change_nick').tmpl({}));
666
667 $('#kiwi .form_newnick').submit(function () {
668 front.run('/NICK ' + $('#kiwi .txtnewnick').val());
669 $('#kiwi .newnick').remove();
670 return false;
671 });
672
673 $('#kiwi .txtnewnick').keypress(function(ev){
674 if(!this.first_press) {
675 this.first_press=true;
676 return false;
677 }
678 });
679
680 $('#kiwi .txtnewnick').keydown(function(ev){
681 if(ev.which === 27){ // ESC
682 $('#kiwi_msginput').focus();
683 $('#kiwi .newnick').remove();
684 }
685 });
686
687 $('#kiwi .cancelnewnick').click(function () {
688 $('#kiwi .newnick').remove();
689 });
690
691 $('#kiwi .txtnewnick').focus();
692 },
693
694
695 tabviewExists: function (name) {
696 return !(front.tabviews[name.toLowerCase()] == undefined);
697 },
698
699 tabviewAdd: function (v_name) {
700 if (v_name.charAt(0) == gateway.channel_prefix) {
701 var re = new RegExp(gateway.channel_prefix,"g");
702 var htmlsafe_name = v_name.replace(re, 'pre');
703 htmlsafe_name = "chan_" + htmlsafe_name;
704 } else {
705 var htmlsafe_name = 'query_' + v_name;
706 }
707
708 var tmp_divname = 'kiwi_window_' + htmlsafe_name;
709 var tmp_userlistname = 'kiwi_userlist_' + htmlsafe_name;
710 var tmp_tabname = 'kiwi_tab_' + htmlsafe_name
711
712 $('#kiwi .windows .scroller').append('<div id="' + tmp_divname + '" class="messages"></div>');
713 $('#kiwi .userlist').append('<ul id="' + tmp_userlistname + '"></ul>');
714 $('#kiwi .windowlist ul').append('<li id="' + tmp_tabname + '" onclick="front.tabviews[\'' + v_name.toLowerCase() + '\'].show();">' + v_name + '</li>');
715 //$('#kiwi .windowlist ul .window_'+v_name).click(function(){ front.windowShow(v_name); });
716 //front.windowShow(v_name);
717
718 front.tabviews[v_name.toLowerCase()] = new tabview();
719 front.tabviews[v_name.toLowerCase()].name = v_name;
720 front.tabviews[v_name.toLowerCase()].div = $('#'+tmp_divname);
721 front.tabviews[v_name.toLowerCase()].userlist = $('#'+tmp_userlistname);
722 front.tabviews[v_name.toLowerCase()].tab = $('#'+tmp_tabname);
723 front.tabviews[v_name.toLowerCase()].show();
724
725 if (typeof registerTouches === "function") {
726 //alert("Registering touch interface");
727 //registerTouches($('#'+tmp_divname));
728 registerTouches(document.getElementById(tmp_divname));
729 }
730 /*
731 front.tabviews[v_name.toLowerCase()].userlist.click(function(){
732 alert($(this).attr('id'));
733 });
734 */
735
736 front.doLayoutSize();
737 },
738
739
740 userClick: function (item) {
741 // Remove any existing userboxes
742 $('#kiwi .userbox').remove();
743
744 var li = $(item).parent();
745 /*var html = '<div class="userbox">\
746 <input type="hidden" class="userbox_nick" value="' + front.nickStripPrefix($(item).text()) + '" />\
747 <a href="#" class="userbox_query">Message</a>\
748 <a href="#" class="userbox_whois">Info</a>\
749 </div>';
750 li.append(html);*/
751 $('#tmpl_user_box').tmpl({nick: front.nickStripPrefix($(item).text())}).appendTo(li);
752
753 $('#kiwi .userbox .userbox_query').click(function (ev) {
754 var nick = $('#kiwi .userbox_nick').val();
755 front.run('/query ' + nick);
756 });
757
758 $('#kiwi .userbox .userbox_whois').click(function (ev) {
759 var nick = $('#kiwi .userbox_nick').val();
760 front.run('/whois ' + nick);
761 });
762 },
763
764
765 sync: function () {
766 gateway.sync();
767 },
768
769 onSync: function (e, data) {
770 // Set any settings
771 if (data.nick != undefined) gateway.nick = data.nick;
772
773 // Add the tabviews
774 if (data.tabviews != undefined) {
775 $.each(data.tabviews, function (i, tab) {
776 if(!front.tabviewExists(tab.name)){
777 front.tabviewAdd(gateway.channel_prefix + tab.name);
778
779 if (tab.userlist !== undefined)
780 front.onUserList({'channel':gateway.channel_prefix + tab.name, 'users':tab.userlist});
781 }
782 });
783 }
784
785 front.doLayout();
786 },
787
788
789 setTopicText: function (new_topic) {
790 $('#kiwi .cur_topic .topic').text(new_topic);
791 front.doLayoutSize();
792 },
793
794
795
796
797
798
799
800 nickStripPrefix: function (nick) {
801 var tmp = nick;
802
803 prefix = tmp.charAt(0);
804 if (typeof gateway.user_prefixes[prefix] != "undefined") tmp = tmp.substring(1);
805
806 return tmp;
807 },
808
809 nickGetPrefix: function (nick) {
810 var tmp = nick;
811
812 prefix = tmp.charAt(0);
813 if (typeof gateway.user_prefixes[prefix] == "undefined") {
814 prefix = "";
815 }
816
817 return prefix;
818 },
819
820 isChannel: function (name) {
821 prefix = name.charAt(0);
822 if (gateway.channel_prefix.indexOf(prefix) > -1) {
823 is_chan = true;
824 } else {
825 is_chan = false;
826 }
827
828 return is_chan;
829 },
830
831 tabviewsNext: function(){
832 var wl = $('#kiwi .windowlist ul');
833 var next_left = parseInt(wl.css('text-indent').replace('px', ''))+170;
834 wl.css('text-indent', next_left);
835 },
836
837 tabviewsPrevious: function(){
838 var wl = $('#kiwi .windowlist ul');
839 var next_left = parseInt(wl.css('text-indent').replace('px', ''))-170;
840 wl.css('text-indent', next_left);
841 },
842
843 windowsNext: function(){
844 var tab, next;
845 next = false;
846 for(tab in front.tabviews){
847 if(!next){
848 if(front.tabviews[tab] == front.cur_channel){
849 next = true;
850 continue;
851 }
852 } else {
853 front.tabviews[tab].show();
854 return;
855 }
856 };
857 },
858
859 windowsPrevious: function(){
860 var tab, prev_tab, next;
861 next = false;
862 for(tab in front.tabviews){
863 if(front.tabviews[tab] == front.cur_channel){
864 if(prev_tab) prev_tab.show();
865 return;
866 }
867 prev_tab = front.tabviews[tab];
868 };
869 },
870
871 windowsShow: function(num){
872 num = parseInt(num);
873 console.log('Showing window '+num.toString());
874 var i = 0, tab;
875 for(tab in front.tabviews){
876 if(i === num){
877 front.tabviews[tab].show();
878 return;
879 }
880 i++;
881 }
882 }
883 }
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901 /*
902 *
903 * TABVIEWS
904 *
905 */
906
907
908 var tabview = function(){}
909 tabview.prototype.name = null;
910 tabview.prototype.div = null;
911 tabview.prototype.userlist = null;
912 tabview.prototype.tab = null;
913 tabview.prototype.topic = "";
914
915 tabview.prototype.show = function(){
916 $('#kiwi .messages').removeClass("active");
917 $('#kiwi .userlist ul').removeClass("active");
918 $('#kiwi .windowlist ul li').removeClass("active");
919
920 // Activate this tab!
921 this.div.addClass('active');
922 this.userlist.addClass('active');
923 this.tab.addClass('active');
924
925 document.tmp = this.div;
926 // Add the part image to the tab
927 this.addPartImage();
928
929 this.clearHighlight();
930 front.setTopicText(this.topic);
931 front.cur_channel = this;
932
933 // If we're using fancy scrolling, refresh it
934 if(touch_scroll) touch_scroll.refresh();
935
936 this.scrollBottom();
937 if(!touchscreen) $('#kiwi_msginput').focus();
938 }
939
940 tabview.prototype.close = function(){
941 this.div.remove();
942 this.userlist.remove();
943 this.tab.remove();
944
945 front.tabviews['server'].show();
946 delete front.tabviews[this.name.toLowerCase()];
947 }
948
949 tabview.prototype.addPartImage = function(){
950 this.clearPartImage();
951
952 var del_html = '<img src="img/redcross.png" class="tab_part" />';
953 this.tab.append(del_html);
954
955 $('.tab_part', this.tab).click(function(){
956 if(front.isChannel($(this).parent().text())){
957 front.run("/part");
958 } else {
959 // Make sure we don't close the server tab
960 if(front.cur_channel.name != "server") front.cur_channel.close();
961 }
962 });
963 }
964
965 tabview.prototype.clearPartImage = function(){
966 $('#kiwi .windowlist .tab_part').remove();
967 }
968
969 tabview.prototype.addMsg = function(time, nick, msg, type, style){
970 //if(nick.charAt(0) != "[" && nick != ""){
971 // var html_nick = $('<div/>').text('<'+nick+'>').html();
972 //} else {
973 var html_nick = $('<div/>').text(nick).html();
974 //}
975
976 var self = this;
977
978 var tmp = msg;
979 var plugin_ret = '';
980 for(var i in plugins.privmsg){
981 if ((plugins.privmsg[i].onprivmsg instanceof Function)) {
982 plugin_ret = '';
983 try {
984 plugin_ret = plugins.privmsg[i].onprivmsg(tmp, this.name);
985
986 // If this plugin has returned false, do not add this message
987 if(plugin_ret === false) return;
988 } catch (e){}
989
990 // If we actually have a string from the plugin, use it
991 if(typeof plugin_ret == "string") tmp = plugin_ret;
992 }
993 }
994 msg = tmp;
995
996 //var html_msg = $('<div/>').text(msg).html()+' '; // Add the space so the styling always has at least 1 character to go from
997 if(time == null){
998 var d = new Date();
999 time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0");
1000 }
1001
1002 // The CSS class (action, topic, notice, etc)
1003 if(typeof type != "string") type = '';
1004
1005 // Make sure we don't have NaN or something
1006 if(typeof msg != "string") msg = '';
1007
1008 // Text formatting
1009 // bold
1010 if(msg.indexOf(String.fromCharCode(2))){
1011 next = '<b>';
1012 while(msg.indexOf(String.fromCharCode(2)) != -1){
1013 msg = msg.replace(String.fromCharCode(2), next);
1014 next = (next=='<b>') ? '</b>' : '<b>';
1015 }
1016 if(next == '</b>') msg =+ '</b>';
1017 }
1018
1019 // Wierd thing noticed by Dux0r on the irc.esper.net server
1020 if(typeof msg != "string") msg = '';
1021
1022 // underline
1023 if(msg.indexOf(String.fromCharCode(31))){
1024 next = '<u>';
1025 while(msg.indexOf(String.fromCharCode(31)) != -1){
1026 msg = msg.replace(String.fromCharCode(31), next);
1027 next = (next=='<u>') ? '</u>' : '<u>';
1028 }
1029 if(next == '</u>') msg =+ '</u>';
1030 }
1031
1032 var re = '\\B(' + gateway.channel_prefix + '[^ ,\\007]+)';
1033 re = new RegExp(re, 'g');
1034
1035 msg = msg.replace(re, function(match) {
1036 return '<a class="chan" href="#">' + match + '</a>';
1037 });
1038
1039 var line_msg = $('<div class="msg '+type+'"><div class="time">'+time+'</div><div class="nick">'+html_nick+'</div><div class="text" style="'+style+'">'+msg+' </div></div>');
1040 this.div.append(line_msg);
1041
1042 if(!touchscreen){
1043 this.scrollBottom();
1044 } else {
1045 touch_scroll.refresh();
1046 //console.log(this.div.attr("scrollHeight") +" - "+ $('#windows').height());
1047 this.scrollBottom();
1048 //if(this.div.attr("scrollHeight") > $('#windows').height()){
1049 // touch_scroll.scrollTo(0, this.div.height());
1050 //}
1051 }
1052 }
1053
1054 tabview.prototype.scrollBottom = function(){
1055 var w = $('#windows');
1056 w[0].scrollTop = w[0].scrollHeight;
1057 }
1058
1059 tabview.prototype.changeNick = function(newNick, oldNick){
1060 this.userlist.children().each(function(){
1061 var item = $('a.nick', this);
1062 if(front.nickStripPrefix(item.text()) == oldNick){
1063 item.text(front.nickGetPrefix(item.text())+newNick);
1064 document.temp_chan = 1;
1065 }
1066 });
1067
1068 if(typeof document.temp_chan != "undefined"){
1069 this.addMsg(null, ' ', '=== '+oldNick+' is now known as '+newNick, 'action');
1070 delete document.temp_chan;
1071 this.userlistSort();
1072 }
1073 }
1074
1075 tabview.prototype.userlistSort = function(){
1076 var ul = this.userlist;
1077 var listitems = ul.children('li').get();
1078 listitems.sort(function(a, b) {
1079 var compA = $(a).text().toUpperCase();
1080 var compB = $(b).text().toUpperCase();
1081
1082 // Sort by prefixes first
1083 for (var i in gateway.user_prefixes) {
1084 prefix = gateway.user_prefixes[i];
1085
1086 if(compA.charAt(0) == prefix && compB.charAt(0) == prefix){
1087 // Both have the same prefix, string compare time
1088 return 0;
1089 }
1090
1091 if(compA.charAt(0) == prefix && compB.charAt(0) != prefix){
1092 return -1;
1093 }
1094
1095 if(compA.charAt(0) != prefix && compB.charAt(0) == prefix){
1096 return 1;
1097 }
1098 }
1099
1100 // No prefixes, compare by string
1101 return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
1102 })
1103 $.each(listitems, function(idx, itm) { ul.append(itm); });
1104 }
1105
1106 tabview.prototype.highlight = function(){
1107 this.tab.addClass('highlight');
1108 }
1109 tabview.prototype.activity = function(){
1110 this.tab.addClass('activity');
1111 }
1112 tabview.prototype.clearHighlight = function(){
1113 this.tab.removeClass('highlight');
1114 this.tab.removeClass('activity');
1115 }
1116 tabview.prototype.changeTopic = function(new_topic){
1117 this.topic = new_topic;
1118 this.addMsg(null, ' ', '=== Topic for '+this.name+' is: '+new_topic, 'topic');
1119 if(front.cur_channel.name == this.name) front.setTopicText(new_topic);
1120 }
1121
1122
1123
1124
1125
1126 var box = function(classname){
1127 this.id = randomString(10);
1128 var tmp = $('<div id="'+this.id+'" class="box '+classname+'"><div class="boxarea"></div></div>');
1129 $('#kiwi').append(tmp);
1130 this.box = $('#'+this.id);
1131 this.content = $('#'+this.id+' .boxarea');
1132
1133 this.box.draggable({ stack: ".box" });
1134 this.content.click(function(){});
1135 //this.box.click(function(){ $(this)..css });
1136 }
1137 box.prototype.create = function(name, classname){
1138
1139 }
1140 box.prototype.id = null;
1141 box.prototype.box = null;
1142 box.prototype.content = null;
1143 box.prototype.destroy = function(){
1144 this.box.remove();
1145 for (var name in front.boxes) if(front.boxes[name].id = this.id) delete front.boxes[name];
1146 }
1147 box.prototype.height = function(){ return this.box.height(); }