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