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