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