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