1 /*jslint undef: true, browser: true, continue: true, sloppy: true, evil: true, forin: true, newcap: false, plusplus: true, maxerr: 50, indent: 4 */
2 /*global gateway, io, $, iScroll, agent, touchscreen*/
17 var about_info
, supportsOrientationChange
, orientationEvent
;
18 gateway
.nick
= 'kiwi_' + Math
.ceil(100 * Math
.random()) + Math
.ceil(100 * Math
.random());
19 gateway
.session_id
= null;
21 $(gateway
).bind("onmsg", front
.onMsg
);
22 $(gateway
).bind("onnotice", front
.onNotice
);
23 $(gateway
).bind("onaction", front
.onAction
);
24 $(gateway
).bind("onmotd", front
.onMOTD
);
25 $(gateway
).bind("onoptions", front
.onOptions
);
26 $(gateway
).bind("onconnect", front
.onConnect
);
27 $(gateway
).bind("ondisconnect", front
.onDisconnect
);
28 $(gateway
).bind("onnick", front
.onNick
);
29 $(gateway
).bind("onuserlist", front
.onUserList
);
30 $(gateway
).bind("onuserlist_end", front
.onUserListEnd
);
31 $(gateway
).bind("onjoin", front
.onJoin
);
32 $(gateway
).bind("ontopic", front
.onTopic
);
33 $(gateway
).bind("onpart", front
.onPart
);
34 $(gateway
).bind("onkick", front
.onKick
);
35 $(gateway
).bind("onquit", front
.onQuit
);
36 $(gateway
).bind("onwhois", front
.onWhois
);
37 $(gateway
).bind("onsync", front
.onSync
);
38 $(gateway
).bind("onchannel_redirect", front
.onChannelRedirect
);
39 $(gateway
).bind("ondebug", front
.onDebug
);
40 $(gateway
).bind("onctcp_request", front
.onCTCPRequest
);
41 $(gateway
).bind("onctcp_response", front
.onCTCPResponse
);
42 $(gateway
).bind("onirc_error", front
.onIRCError
);
46 // Build the about box
47 front
.boxes
.about
= new Box("about");
48 about_info
= 'UI adapted for ' + agent
;
50 about_info
+= ' touchscreen ';
52 about_info
+= 'usage';
53 $('#tmpl_about_box').tmpl({
55 front_revision
: front
.revision
,
56 gateway_revision
: gateway
.revision
57 }).appendTo(front
.boxes
.about
.content
);
59 //$(window).bind("beforeunload", function(){ gateway.quit(); });
62 $('#kiwi').addClass('touchscreen');
64 // Single touch scrolling through scrollback for touchscreens
66 touch_scroll
= new iScroll('windows', scroll_opts
);
71 $('#kiwi .cur_topic').resize(front
.doLayoutSize
);
73 $('#kiwi .formconnectwindow').submit(function () {
74 var netsel
= $('#kiwi .formconnectwindow .network'),
75 nick
= $('#kiwi .formconnectwindow .nick'),
78 if (nick
.val() === '') {
79 nick
.val('Nick please!');
84 tmp
= nick
.val().split(' ');
85 gateway
.nick
= tmp
[0];
88 front
.run('/connect ' + netsel
.val());
93 $('#kiwi .connectwindow').slideUp();
94 $('#windows').click(function () { $('#kiwi_msginput').focus(); });
99 supportsOrientationChange
= (typeof window
.onorientationchange
!== undefined);
100 orientationEvent
= supportsOrientationChange
? "orientationchange" : "resize";
101 window
.addEventListener(orientationEvent
, front
.doLayoutSize
, false);
102 //$('#kiwi').bind("resize", front.doLayoutSize, false);
105 //front.windowAdd('server');
106 front
.tabviewAdd('server');
108 // Any pre-defined nick?
109 if (typeof init_data
.nick
=== "string") {
110 $('#kiwi .formconnectwindow .nick').val(init_data
.nick
);
113 //gateway.session_id = 'testses';
115 $('#kiwi .cur_topic').keydown(function (e
) {
116 if (e
.which
=== 13) {
120 $('#kiwi_msginput').focus();
121 } else if (e
.which
=== 27) {
124 $(this).text(front
.original_topic
);
125 $('#kiwi_msginput').focus();
128 /*$('.cur_topic').live('keypress', function(e) {
129 if (e.keyCode === 13) {
133 $('#kiwi_msginput').focus();
134 } else if (e.keyCode === 27) {
137 $(this).text(front.original_topic);
140 $('.cur_topic').live('change', function () {
142 text
= $(this).text();
143 if (text
!== front
.original_topic
) {
144 chan
= front
.cur_channel
.name
;
145 gateway
.setTopic(chan
, text
);
153 doLayoutSize: function () {
154 var kiwi
, ct
, ul
, n_top
, n_bottom
;
156 if (kiwi
.width() < 330 && !kiwi
.hasClass('small_kiwi')) {
157 console
.log("switching to small kiwi");
158 kiwi
.removeClass('large_kiwi');
159 kiwi
.addClass('small_kiwi');
160 } else if (kiwi
.width() >= 330 && !kiwi
.hasClass('large_kiwi')) {
161 kiwi
.removeClass('small_kiwi');
162 kiwi
.addClass('large_kiwi');
165 ct
= $('#kiwi .cur_topic');
166 ul
= $('#kiwi .userlist');
168 n_top
= parseInt(ct
.offset().top
, 10) + parseInt(ct
.height(), 10);
169 n_top
= n_top
+ parseInt(ct
.css('border-top-width').replace('px', ''), 10);
170 n_top
= n_top
+ parseInt(ct
.css('border-bottom-width').replace('px', ''), 10);
171 n_top
= n_top
+ parseInt(ct
.css('padding-top').replace('px', ''), 10);
172 n_top
= n_top
+ parseInt(ct
.css('padding-bottom').replace('px', ''), 10);
173 n_top
+= 1; // Dunno why this is needed.. but it's always 1 px out :/
175 n_bottom
= $(document
).height() - parseInt($('#kiwi .control').offset().top
, 10);
177 $('#kiwi .windows').css({top
: n_top
+ 'px', bottom
: n_bottom
+ 'px'});
178 $('#kiwi .userlist').css({top
: n_top
+ 'px', bottom
: n_bottom
+ 'px'});
182 doLayout: function () {
183 $('#kiwi .msginput .nick a').text(gateway
.nick
);
184 $('#kiwi_msginput').val(' ');
185 $('#kiwi_msginput').focus();
189 joinChannel: function (chan_name
) {
190 var chans
= chan_name
.split(','),
194 if (front
.tabviews
[chan
.toLowerCase()] === undefined || (front
.tabviews
[chan
.toLowerCase()] !== undefined && front
.tabviews
[chan
.toLowerCase()].safe_to_close
=== true)) {
196 front
.tabviewAdd(chan
);
198 front
.tabviews
[chan
.toLowerCase()].show();
204 run: function (msg
) {
205 var parts
, dest
, t
, pos
, textRange
, d
;
206 console
.log("running " + msg
);
207 if (msg
.substring(0, 1) === '/') {
208 parts
= msg
.split(' ');
209 switch (parts
[0].toLowerCase()) {
212 front
.joinChannel(parts
[1]);
217 if (parts
[1] === undefined) {
218 alert('Usage: /connect servername [port]');
222 if (parts
[2] === undefined) {
225 front
.cur_channel
.addMsg(null, ' ', '=== Connecting to ' + parts
[1] + '...', 'status');
226 gateway
.connect(parts
[1], parts
[2], 0);
230 console
.log("/nick");
231 if (parts
[1] === undefined) {
232 console
.log("calling show nick");
233 front
.showChangeNick();
235 console
.log("sending raw");
236 gateway
.raw(msg
.substring(1));
241 if (typeof parts
[1] === "undefined") {
242 if (front
.cur_channel
.safe_to_close
) {
243 front
.cur_channel
.close();
245 gateway
.raw(msg
.substring(1) + ' ' + front
.cur_channel
.name
);
248 gateway
.raw(msg
.substring(1));
253 if (typeof parts
[1] !== "undefined") {
254 gateway
.raw(msg
.substring(1));
264 if (typeof parts
[1] !== "undefined") {
265 front
.tabviewAdd(parts
[1]);
270 gateway
.raw(msg
.replace(/^\/quote /i, ''));
274 gateway
.action(front
.cur_channel
.name
, msg
.substring(4));
275 //front.tabviews[destination.toLowerCase()].addMsg(null, ' ', '* '+data.nick+' '+data.msg, 'color:green;');
276 front
.cur_channel
.addMsg(null, ' ', '* ' + gateway
.nick
+ ' ' + msg
.substring(4), 'action', 'color:#555;');
281 msg
= parts
.slice(2).join(' ');
283 gateway
.notice(dest
, msg
);
284 this.onNotice({}, {nick
: gateway
.nick
, channel
: dest
, msg
: msg
});
288 if (parts
[1] !== undefined) {
289 front
.windowsShow(parseInt(parts
[1], 10));
294 gateway
.quit(msg
.split(" ", 2)[1]);
298 if (parts
[1] === undefined) {
300 if (t
.createTextRange
) {
301 pos
= t
.text().length();
302 textRange
= t
.createTextRange();
303 textRange
.collapse(true);
304 textRange
.moveEnd(pos
);
305 textRange
.moveStart(pos
);
307 } else if (t
.setSelectionRange
) {
308 t
.setSelectionRange(pos
, pos
);
311 gateway
.setTopic(front
.cur_channel
.name
, msg
.split(' ', 2)[1]);
312 //gateway.raw('TOPIC ' + front.cur_channel.name + ' :' + msg.split(' ', 2)[1]);
316 //front.cur_channel.addMsg(null, ' ', '--> Invalid command: '+parts[0].substring(1));
317 gateway
.raw(msg
.substring(1));
321 //alert('Sending message: '+msg);
322 if (msg
.trim() === '') {
325 if (front
.cur_channel
.name
!== 'server') {
326 gateway
.msg(front
.cur_channel
.name
, msg
);
328 d
= d
.getHours() + ":" + d
.getMinutes();
329 //front.addMsg(d, gateway.nick, msg);
330 front
.cur_channel
.addMsg(null, gateway
.nick
, msg
);
336 onMsg: function (e
, data
) {
338 // Is this message from a user?
339 if (data
.channel
=== gateway
.nick
) {
340 destination
= data
.nick
.toLowerCase();
342 destination
= data
.channel
.toLowerCase();
345 if (!front
.tabviewExists(destination
)) {
346 front
.tabviewAdd(destination
);
348 front
.tabviews
[destination
].addMsg(null, data
.nick
, data
.msg
);
351 onDebug: function (e
, data
) {
352 if (!front
.tabviewExists('kiwi_debug')) {
353 front
.tabviewAdd('kiwi_debug');
355 front
.tabviews
.kiwi_debug
.addMsg(null, ' ', data
.msg
);
358 onAction: function (e
, data
) {
360 // Is this message from a user?
361 if (data
.channel
=== gateway
.nick
) {
362 destination
= data
.nick
;
364 destination
= data
.channel
;
367 if (!front
.tabviewExists(destination
)) {
368 front
.tabviewAdd(destination
);
370 front
.tabviews
[destination
.toLowerCase()].addMsg(null, ' ', '* ' + data
.nick
+ ' ' + data
.msg
, 'action', 'color:#555;');
373 onTopic: function (e
, data
) {
374 if (front
.tabviewExists(data
.channel
)) {
375 front
.tabviews
[data
.channel
.toLowerCase()].changeTopic(data
.topic
);
379 onNotice: function (e
, data
) {
380 var nick
= (data
.nick
=== undefined || data
.nick
=== '') ? '' : '[' + data
.nick
+ ']';
381 if (data
.channel
!== undefined) {
382 if (front
.tabviewExists(data
.channel
)) {
383 front
.tabviews
[data
.channel
.toLowerCase()].addMsg(null, nick
, data
.msg
, 'notice');
385 front
.tabviews
.server
.addMsg(null, nick
, data
.msg
, 'notice');
388 front
.tabviews
.server
.addMsg(null, nick
, data
.msg
, 'notice');
392 onCTCPRequest: function (e
, data
) {
393 var msg
= data
.msg
.split(" ", 2);
396 if (typeof msg
[1] === 'undefined') {
399 gateway
.notice(data
.nick
, String
.fromCharCode(1) + 'PING ' + msg
[1] + String
.fromCharCode(1));
402 gateway
.notice(data
.nick
, String
.fromCharCode(1) + 'TIME ' + (new Date()).toLocaleString() + String
.fromCharCode(1));
405 front
.tabviews
.server
.addMsg(null, 'CTCP [' + data
.nick
+ ']', data
.msg
, 'ctcp');
408 onCTCPResponse: function (e
, data
) {
411 onConnect: function (e
, data
) {
412 if (data
.connected
) {
413 front
.tabviews
.server
.addMsg(null, ' ', '=== Connected OK :)', 'status');
414 if (typeof init_data
.channel
=== "string") {
415 front
.joinChannel(init_data
.channel
);
418 front
.tabviews
.server
.addMsg(null, ' ', '=== Failed to connect :(', 'status');
421 onDisconnect: function (e
, data
) {
423 for (tab
in front
.tabviews
) {
424 front
.tabviews
[tab
].addMsg(null, '', 'Disconnected from server!', 'error');
427 onOptions: function (e
, data
) {
428 if (typeof gateway
.network_name
=== "string" && gateway
.network_name
!== "") {
429 front
.tabviews
.server
.tab
.text(gateway
.network_name
);
432 onMOTD: function (e
, data
) {
433 front
.tabviews
.server
.addMsg(null, data
.server
, data
.msg
, 'motd');
435 onWhois: function (e
, data
) {
438 front
.cur_channel
.addMsg(null, data
.nick
, data
.msg
, 'whois');
439 } else if (data
.logon
) {
441 d
.setTime(data
.logon
* 1000);
442 d
= d
.toLocaleString();
443 front
.cur_channel
.addMsg(null, data
.nick
, 'idle for ' + data
.idle
+ ' second' + ((data
.idle
!== 1) ? 's' : '') + ', signed on ' + d
, 'whois');
445 front
.cur_channel
.addMsg(null, data
.nick
, 'idle for ' + data
.idle
+ ' seconds', 'whois');
448 onUserList: function (e
, data
) {
450 if (front
.tabviews
[data
.channel
.toLowerCase()] === undefined) {
453 ul
= front
.tabviews
[data
.channel
.toLowerCase()].userlist
;
455 if (!document
.userlist_updating
) {
456 document
.userlist_updating
= true;
460 $.each(data
.users
, function (i
, item
) {
461 nick
= i
; //i.match(/^.+!/g);
463 $('<li><a class="nick" onclick="front.userClick(this);">' + mode
+ nick
+ '</a></li>').appendTo(ul
);
466 front
.tabviews
[data
.channel
.toLowerCase()].userlistSort();
468 onUserListEnd: function (e
, data
) {
469 document
.userlist_updating
= false;
472 onJoin: function (e
, data
) {
473 if (!front
.tabviewExists(data
.channel
)) {
474 front
.tabviewAdd(data
.channel
.toLowerCase());
477 if (data
.nick
=== gateway
.nick
) {
478 return; // Not needed as it's already in nicklist
480 front
.tabviews
[data
.channel
.toLowerCase()].addMsg(null, ' ', '--> ' + data
.nick
+ ' has joined', 'action', 'color:#009900;');
481 $('<li><a class="nick" onclick="front.userClick(this);">' + data
.nick
+ '</a></li>').appendTo(front
.tabviews
[data
.channel
.toLowerCase()].userlist
);
482 front
.tabviews
[data
.channel
.toLowerCase()].userlistSort();
484 onPart: function (e
, data
) {
485 if (front
.tabviewExists(data
.channel
)) {
486 // If this is us, close the tabview
487 if (data
.nick
=== gateway
.nick
) {
488 front
.tabviews
[data
.channel
.toLowerCase()].close();
489 front
.tabviews
.server
.show();
493 front
.tabviews
[data
.channel
.toLowerCase()].addMsg(null, ' ', '<-- ' + data
.nick
+ ' has left (' + data
.message
+ ')', 'action', 'color:#990000;');
494 front
.tabviews
[data
.channel
.toLowerCase()].userlist
.children().each(function () {
495 if ($(this).text() === data
.nick
) {
501 onKick: function (e
, data
) {
502 if (front
.tabviewExists(data
.channel
)) {
503 // If this is us, close the tabview
504 if (data
.kicked
=== gateway
.nick
) {
505 //front.tabviews[data.channel.toLowerCase()].close();
506 front
.tabviews
[data
.channel
.toLowerCase()].addMsg(null, ' ', '=== You have been kicked from ' + data
.channel
+ '. ' + data
.message
, 'status');
507 front
.tabviews
[data
.channel
.toLowerCase()].safe_to_close
= true;
508 $('li', front
.tabviews
[data
.channel
.toLowerCase()].userlist
).remove();
512 front
.tabviews
[data
.channel
.toLowerCase()].addMsg(null, ' ', '<-- ' + data
.kicked
+ ' kicked by ' + data
.nick
+ '(' + data
.message
+ ')', 'action', 'color:#990000;');
513 front
.tabviews
[data
.channel
.toLowerCase()].userlist
.children().each(function () {
514 if ($(this).text() === data
.nick
) {
520 onNick: function (e
, data
) {
521 if (data
.nick
=== gateway
.nick
) {
522 gateway
.nick
= data
.newnick
;
526 $.each(front
.tabviews
, function (i
, item
) {
527 $.each(front
.tabviews
, function (i
, item
) {
528 item
.changeNick(data
.newnick
, data
.nick
);
532 onQuit: function (e
, data
) {
533 $.each(front
.tabviews
, function (i
, item
) {
534 $.each(front
.tabviews
, function (i
, item
) {
535 item
.userlist
.children().each(function () {
536 if ($(this).text() === data
.nick
) {
538 item
.addMsg(null, ' ', '<-- ' + data
.nick
+ ' has quit (' + data
.message
+ ')', 'action', 'color:#990000;');
544 onChannelRedirect: function (e
, data
) {
545 front
.tabviews
[data
.from.toLowerCase()].close();
546 front
.tabviewAdd(data
.to
.toLowerCase());
547 front
.tabviews
[data
.to
.toLowerCase()].addMsg(null, ' ', '=== Redirected from ' + data
.from, 'action');
550 onIRCError: function (e
, data
) {
552 if (data
.channel
!== undefined && front
.tabviewExists(data
.channel
)) {
553 t_view
= data
.channel
;
558 switch (data
.error
) {
559 case 'banned_from_channel':
560 front
.tabviews
[t_view
].addMsg(null, ' ', '=== You are banned from ' + data
.channel
+ '. ' + data
.reason
, 'status');
561 if (t_view
!== 'server') {
562 front
.tabviews
[t_view
].safe_to_close
= true;
565 case 'bad_channel_key':
566 front
.tabviews
[t_view
].addMsg(null, ' ', '=== Bad channel key for ' + data
.channel
, 'status');
567 if (t_view
!== 'server') {
568 front
.tabviews
[t_view
].safe_to_close
= true;
571 case 'invite_only_channel':
572 front
.tabviews
[t_view
].addMsg(null, ' ', '=== ' + data
.channel
+ ' is invite only.', 'status');
573 if (t_view
!== 'server') {
574 front
.tabviews
[t_view
].safe_to_close
= true;
577 case 'channel_is_full':
578 front
.tabviews
[t_view
].addMsg(null, ' ', '=== ' + data
.channel
+ ' is full.', 'status');
579 if (t_view
!== 'server') {
580 front
.tabviews
[t_view
].safe_to_close
= true;
583 case 'chanop_privs_needed':
584 front
.tabviews
[data
.channel
].addMsg(null, ' ', '=== ' + data
.reason
, 'status');
587 front
.tabviews
.server
.addMsg(null, ' ', '=== ' + data
.nick
+ ': ' + data
.reason
, 'status');
590 // We don't know what data contains, so don't do anything with it.
591 //front.tabviews.server.addMsg(null, ' ', '=== ' + data, 'status');
595 registerKeys: function () {
596 $('#kiwi_msginput').bind('keydown', function (e
) {
597 var windows
, meta
, num
, msg
, data
, candidates
, word_pos
, word
;
598 windows
= $('#windows');
599 //var meta = e.altKey;
603 case (e
.which
>= 48) && (e
.which
<= 57):
610 front
.windowsShow(num
);
614 case e
.which
=== 27: // escape
616 case e
.which
=== 13: // return
617 msg
= $('#kiwi_msginput').val();
620 front
.buffer
.push(msg
);
621 front
.buffer_pos
= front
.buffer
.length
;
624 $('#kiwi_msginput').val('');
627 case e
.which
=== 33: // page up
628 console
.log("page up");
629 windows
[0].scrollTop
= windows
[0].scrollTop
- windows
.height();
631 case e
.which
=== 34: // page down
632 windows
[0].scrollTop
= windows
[0].scrollTop
+ windows
.height();
634 case e
.which
=== 37: // left
636 front
.windowsPrevious();
640 case e
.which
=== 38: // up
641 if (front
.buffer_pos
> 0) {
643 $('#kiwi_msginput').val(front
.buffer
[front
.buffer_pos
]);
646 case e
.which
=== 39: // right
652 case e
.which
=== 40: // down
653 if (front
.buffer_pos
< front
.buffer
.length
) {
655 $('#kiwi_msginput').val(front
.buffer
[front
.buffer_pos
]);
659 case e
.which
=== 9: // tab
660 // Get possible autocompletions
662 front
.cur_channel
.userlist
.children().each(function () {
663 nick
= front
.nickStripPrefix($('a.nick', this).text());
667 // Do the autocomplete
668 if (this.value
.length
=== this.selectionStart
&& this.value
.length
=== this.selectionEnd
) {
671 word_pos
= this.value
.lastIndexOf(' ');
673 if (word_pos
=== -1) {
676 word
= this.value
.substr(word_pos
);
680 // filter data to find only strings that start with existing value
681 for (i
= 0; i
< data
.length
; i
++) {
682 if (data
[i
].indexOf(word
) === 0 && data
[i
].length
> word
.length
) {
683 candidates
.push(data
[i
]);
687 if (candidates
.length
> 0) {
688 // some candidates for autocompletion are found
689 this.value
= this.value
.substring(0, word_pos
) + ' ' + candidates
[0] + ': ';
690 this.selectionStart
= this.value
.length
;
698 $('#kiwi .control .msginput .nick').click(function () {
699 front
.showChangeNick();
706 $('#kiwi .plugins .load_plugin_file').click(function () {
708 if (typeof front
.boxes
.plugins
!== "undefined") {
712 front
.boxes
.plugins
= new Box("plugin_file");
713 $('#tmpl_plugins').tmpl({}).appendTo(front
.boxes
.plugins
.content
);
714 front
.boxes
.plugins
.box
.css('top', -(front
.boxes
.plugins
.height
+ 40));
716 // Populate the plugin list..
717 lst
= $('#plugin_list');
718 lst
.find('option').remove();
719 for (j
in plugins
.privmsg
) {
720 txt
= plugins
.privmsg
[j
].name
;
721 lst
.append('<option value="' + txt
+ '">' + txt
+ '</option>');
725 $('#kiwi .plugin_file').submit(function () {
726 $.getJSON($('.txtpluginfile').val(), function (data
) {
728 plg
.name
= data
.name
;
729 eval("plg.onprivmsg = " + data
.onprivmsg
);
730 eval("plg.onload = " + data
.onload
);
731 eval("plg.onunload = " + data
.onunload
);
732 plugins
.privmsg
.push(plg
);
734 if (plg
.onload
instanceof Function
) {
740 $('#kiwi .cancelpluginfile').click(function () {
741 front
.boxes
.plugins
.destroy();
744 $('#kiwi #plugins_list_unload').click(function () {
745 var selected_plugin
, i
;
746 selected_plugin
= $('#plugin_list').val();
747 console
.log("removing plugin: " + selected_plugin
);
748 for (i
in plugins
.privmsg
) {
749 if (plugins
.privmsg
[i
].name
=== selected_plugin
) {
750 if (plugins
.privmsg
[i
].onunload
instanceof Function
) {
751 plugins
.privmsg
[i
].onunload();
753 delete plugins
.privmsg
[i
];
758 $('#kiwi .txtpluginfile').focus();
762 $('#kiwi .plugins .reload_css').click(function () {
763 var links
= document
.getElementsByTagName("link"),
765 for (i
= 0; i
< links
.length
; i
++) {
766 if (links
[i
].rel
=== "stylesheet") {
767 if (links
[i
].href
.indexOf("?") === -1) {
768 links
[i
].href
+= "?";
770 links
[i
].href
+= "x";
776 $('#kiwi .about .about_close').click(function () {
777 $('#kiwi .about').css('display', 'none');
781 $('#kiwi .poweredby').click(function () {
782 $('#kiwi .about').css('display', 'block');
788 showChangeNick: function () {
789 $('#kiwi').append($('#tmpl_change_nick').tmpl({}));
791 $('#kiwi .form_newnick').submit(function () {
792 front
.run('/NICK ' + $('#kiwi .txtnewnick').val());
793 $('#kiwi .newnick').remove();
797 $('#kiwi .txtnewnick').keypress(function (ev
) {
798 if (!this.first_press
) {
799 this.first_press
= true;
804 $('#kiwi .txtnewnick').keydown(function (ev
) {
805 if (ev
.which
=== 27) { // ESC
806 $('#kiwi_msginput').focus();
807 $('#kiwi .newnick').remove();
811 $('#kiwi .cancelnewnick').click(function () {
812 $('#kiwi .newnick').remove();
815 $('#kiwi .txtnewnick').focus();
819 tabviewExists: function (name
) {
820 return (typeof front
.tabviews
[name
.toLowerCase()] !== 'undefined');
823 tabviewAdd: function (v_name
) {
824 var re
, htmlsafe_name
, tmp_divname
, tmp_userlistname
, tmp_tabname
;
825 if (v_name
.charAt(0) === gateway
.channel_prefix
) {
826 re
= new RegExp(gateway
.channel_prefix
, "g");
827 htmlsafe_name
= v_name
.replace(re
, 'pre');
828 htmlsafe_name
= "chan_" + htmlsafe_name
;
830 htmlsafe_name
= 'query_' + v_name
;
833 tmp_divname
= 'kiwi_window_' + htmlsafe_name
;
834 tmp_userlistname
= 'kiwi_userlist_' + htmlsafe_name
;
835 tmp_tabname
= 'kiwi_tab_' + htmlsafe_name
;
837 if (!front
.tabviewExists(v_name
)) {
838 $('#kiwi .windows .scroller').append('<div id="' + tmp_divname
+ '" class="messages"></div>');
839 $('#kiwi .userlist').append('<ul id="' + tmp_userlistname
+ '"></ul>');
840 $('#kiwi .windowlist ul').append('<li id="' + tmp_tabname
+ '" onclick="front.tabviews[\'' + v_name
.toLowerCase() + '\'].show();">' + v_name
+ '</li>');
842 //$('#kiwi .windowlist ul .window_'+v_name).click(function(){ front.windowShow(v_name); });
843 //front.windowShow(v_name);
845 front
.tabviews
[v_name
.toLowerCase()] = new Tabview();
846 front
.tabviews
[v_name
.toLowerCase()].name
= v_name
;
847 front
.tabviews
[v_name
.toLowerCase()].div
= $('#' + tmp_divname
);
848 front
.tabviews
[v_name
.toLowerCase()].userlist
= $('#' + tmp_userlistname
);
849 front
.tabviews
[v_name
.toLowerCase()].tab
= $('#' + tmp_tabname
);
850 front
.tabviews
[v_name
.toLowerCase()].show();
852 if (typeof registerTouches
=== "function") {
853 //alert("Registering touch interface");
854 //registerTouches($('#'+tmp_divname));
855 registerTouches(document
.getElementById(tmp_divname
));
858 front.tabviews[v_name.toLowerCase()].userlist.click(function(){
859 alert($(this).attr('id'));
863 front
.doLayoutSize();
867 userClick: function (item
) {
868 // Remove any existing userboxes
869 $('#kiwi .userbox').remove();
871 var li
= $(item
).parent();
872 /*var html = '<div class="userbox">\
873 <input type="hidden" class="userbox_nick" value="' + front.nickStripPrefix($(item).text()) + '" />\
874 <a href="#" class="userbox_query">Message</a>\
875 <a href="#" class="userbox_whois">Info</a>\
878 $('#tmpl_user_box').tmpl({nick
: front
.nickStripPrefix($(item
).text())}).appendTo(li
);
880 $('#kiwi .userbox .userbox_query').click(function (ev
) {
881 var nick
= $('#kiwi .userbox_nick').val();
882 front
.run('/query ' + nick
);
885 $('#kiwi .userbox .userbox_whois').click(function (ev
) {
886 var nick
= $('#kiwi .userbox_nick').val();
887 front
.run('/whois ' + nick
);
896 onSync: function (e
, data
) {
898 if (data
.nick
!== undefined) {
899 gateway
.nick
= data
.nick
;
903 if (data
.tabviews
!== undefined) {
904 $.each(data
.tabviews
, function (i
, tab
) {
905 if (!front
.tabviewExists(tab
.name
)) {
906 front
.tabviewAdd(gateway
.channel_prefix
+ tab
.name
);
908 if (tab
.userlist
!== undefined) {
909 front
.onUserList({'channel': gateway
.channel_prefix
+ tab
.name
, 'users': tab
.userlist
});
919 setTopicText: function (new_topic
) {
920 front
.original_topic
= new_topic
;
921 $('#kiwi .cur_topic .topic').text(new_topic
);
922 front
.doLayoutSize();
931 nickStripPrefix: function (nick
) {
934 prefix
= tmp
.charAt(0);
935 for (i
in gateway
.user_prefixes
) {
936 if (gateway
.user_prefixes
[i
].symbol
!== prefix
) {
939 return tmp
.substring(1);
945 nickGetPrefix: function (nick
) {
948 prefix
= tmp
.charAt(0);
949 for (i
in gateway
.user_prefixes
) {
950 if (gateway
.user_prefixes
[i
].symbol
=== prefix
) {
958 isChannel: function (name
) {
959 prefix
= name
.charAt(0);
960 if (gateway
.channel_prefix
.indexOf(prefix
) > -1) {
969 tabviewsNext: function () {
970 var wl
= $('#kiwi .windowlist ul'),
971 next_left
= parseInt(wl
.css('text-indent').replace('px', ''), 10) + 170;
972 wl
.css('text-indent', next_left
);
975 tabviewsPrevious: function () {
976 var wl
= $('#kiwi .windowlist ul'),
977 next_left
= parseInt(wl
.css('text-indent').replace('px', ''), 10) - 170;
978 wl
.css('text-indent', next_left
);
981 windowsNext: function () {
984 for (tab
in front
.tabviews
) {
986 if (front
.tabviews
[tab
] === front
.cur_channel
) {
991 front
.tabviews
[tab
].show();
997 windowsPrevious: function () {
998 var tab
, prev_tab
, next
;
1000 for (tab
in front
.tabviews
) {
1001 if (front
.tabviews
[tab
] === front
.cur_channel
) {
1007 prev_tab
= front
.tabviews
[tab
];
1011 windowsShow: function (num
) {
1012 num
= parseInt(num
, 10);
1013 console
.log('Showing window ' + num
.toString());
1015 for (tab
in front
.tabviews
) {
1017 front
.tabviews
[tab
].show();
1048 var Tabview = function () {};
1049 Tabview
.prototype.name
= null;
1050 Tabview
.prototype.div
= null;
1051 Tabview
.prototype.userlist
= null;
1052 Tabview
.prototype.tab
= null;
1053 Tabview
.prototype.topic
= "";
1054 Tabview
.prototype.safe_to_close
= false; // If we have been kicked/banned/etc from this channel, don't wait for a part message
1056 Tabview
.prototype.show = function () {
1057 $('#kiwi .messages').removeClass("active");
1058 $('#kiwi .userlist ul').removeClass("active");
1059 $('#kiwi .windowlist ul li').removeClass("active");
1061 // Activate this tab!
1062 this.div
.addClass('active');
1063 this.userlist
.addClass('active');
1064 this.tab
.addClass('active');
1066 document
.tmp
= this.div
;
1067 // Add the part image to the tab
1068 this.addPartImage();
1070 this.clearHighlight();
1071 front
.setTopicText(this.topic
);
1072 front
.cur_channel
= this;
1074 // If we're using fancy scrolling, refresh it
1076 touch_scroll
.refresh();
1079 this.scrollBottom();
1081 $('#kiwi_msginput').focus();
1085 Tabview
.prototype.close = function () {
1087 this.userlist
.remove();
1090 if (front
.cur_channel
=== this) {
1091 front
.tabviews
.server
.show();
1093 delete front
.tabviews
[this.name
.toLowerCase()];
1096 Tabview
.prototype.addPartImage = function () {
1097 this.clearPartImage();
1099 // We can't close this tab, so don't have the close image
1100 if (this.name
=== 'server') {
1104 var del_html
= '<img src="img/redcross.png" class="tab_part" />';
1105 this.tab
.append(del_html
);
1107 $('.tab_part', this.tab
).click(function () {
1108 if (front
.isChannel($(this).parent().text())) {
1111 // Make sure we don't close the server tab
1112 if (front
.cur_channel
.name
!== 'server') {
1113 front
.cur_channel
.close();
1119 Tabview
.prototype.clearPartImage = function () {
1120 $('#kiwi .windowlist .tab_part').remove();
1123 Tabview
.prototype.addMsg = function (time
, nick
, msg
, type
, style
) {
1124 var html_nick
, self
, tmp
, plugin_ret
, i
, d
, re
, line_msg
;
1125 html_nick
= $('<div/>').text(nick
).html();
1131 for (i
in plugins
.privmsg
) {
1132 if ((plugins
.privmsg
[i
].onprivmsg
instanceof Function
)) {
1135 plugin_ret
= plugins
.privmsg
[i
].onprivmsg(tmp
, this.name
);
1137 // If this plugin has returned false, do not add this message
1138 if (plugin_ret
=== false) {
1144 // If we actually have a string from the plugin, use it
1145 if (typeof plugin_ret
=== "string") {
1152 //var html_msg = $('<div/>').text(msg).html()+' '; // Add the space so the styling always has at least 1 character to go from
1153 if (time
=== null) {
1155 time
= d
.getHours().toString().lpad(2, "0") + ":" + d
.getMinutes().toString().lpad(2, "0") + ":" + d
.getSeconds().toString().lpad(2, "0");
1158 // The CSS class (action, topic, notice, etc)
1159 if (typeof type
!== "string") {
1163 // Make sure we don't have NaN or something
1164 if (typeof msg
!== "string") {
1170 if (msg
.indexOf(String
.fromCharCode(2)) !== -1) {
1172 while (msg
.indexOf(String
.fromCharCode(2)) !== -1) {
1173 msg
= msg
.replace(String
.fromCharCode(2), next
);
1174 next
= (next
=== '<b>') ? '</b>' : '<b>';
1176 if (next
=== '</b>') {
1181 // Wierd thing noticed by Dux0r on the irc.esper.net server
1182 if (typeof msg
!== "string") {
1187 if (msg
.indexOf(String
.fromCharCode(31)) !== -1) {
1189 while (msg
.indexOf(String
.fromCharCode(31)) !== -1) {
1190 msg
= msg
.replace(String
.fromCharCode(31), next
);
1191 next
= (next
=== '<u>') ? '</u>' : '<u>';
1193 if (next
=== '</u>') {
1198 re
= new RegExp('\\B(' + gateway
.channel_prefix
+ '[^ ,.\\007]+)', 'g');
1200 msg
= msg
.replace(re
, function (match
) {
1201 return '<a class="chan" href="#">' + match
+ '</a>';
1204 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>');
1205 this.div
.append(line_msg
);
1208 this.scrollBottom();
1210 touch_scroll
.refresh();
1211 //console.log(this.div.attr("scrollHeight") +" - "+ $('#windows').height());
1212 this.scrollBottom();
1213 //if(this.div.attr("scrollHeight") > $('#windows').height()){
1214 // touch_scroll.scrollTo(0, this.div.height());
1219 Tabview
.prototype.scrollBottom = function () {
1220 var w
= $('#windows');
1221 w
[0].scrollTop
= w
[0].scrollHeight
;
1224 Tabview
.prototype.changeNick = function (newNick
, oldNick
) {
1225 this.userlist
.children().each(function () {
1226 var item
= $('a.nick', this);
1227 if (front
.nickStripPrefix(item
.text()) === oldNick
) {
1228 item
.text(front
.nickGetPrefix(item
.text()) + newNick
);
1229 document
.temp_chan
= 1;
1233 if (typeof document
.temp_chan
!== "undefined") {
1234 this.addMsg(null, ' ', '=== ' + oldNick
+ ' is now known as ' + newNick
, 'action');
1235 delete document
.temp_chan
;
1236 this.userlistSort();
1240 Tabview
.prototype.userlistSort = function () {
1241 var ul
= this.userlist
,
1242 listitems
= ul
.children('li').get();
1243 listitems
.sort(function (a
, b
) {
1244 var compA
= $(a
).text().toUpperCase(),
1245 compB
= $(b
).text().toUpperCase(),
1248 // Sort by prefixes first
1249 for (i
in gateway
.user_prefixes
) {
1250 prefix
= gateway
.user_prefixes
[i
].symbol
;
1252 if (compA
.charAt(0) === prefix
&& compB
.charAt(0) === prefix
) {
1253 // Both have the same prefix, string compare time
1257 if (compA
.charAt(0) === prefix
&& compB
.charAt(0) !== prefix
) {
1261 if (compA
.charAt(0) !== prefix
&& compB
.charAt(0) === prefix
) {
1266 // No prefixes, compare by string
1267 return (compA
< compB
) ? -1 : (compA
> compB
) ? 1 : 0;
1269 $.each(listitems
, function (idx
, itm
) { ul
.append(itm
); });
1272 Tabview
.prototype.highlight = function () {
1273 this.tab
.addClass('highlight');
1275 Tabview
.prototype.activity = function () {
1276 this.tab
.addClass('activity');
1278 Tabview
.prototype.clearHighlight = function () {
1279 this.tab
.removeClass('highlight');
1280 this.tab
.removeClass('activity');
1282 Tabview
.prototype.changeTopic = function (new_topic
) {
1283 this.topic
= new_topic
;
1284 this.addMsg(null, ' ', '=== Topic for ' + this.name
+ ' is: ' + new_topic
, 'topic');
1285 if (front
.cur_channel
.name
=== this.name
) {
1286 front
.setTopicText(new_topic
);
1294 var Box = function (classname
) {
1295 this.id
= randomString(10);
1296 var tmp
= $('<div id="' + this.id
+ '" class="box ' + classname
+ '"><div class="boxarea"></div></div>');
1297 $('#kiwi').append(tmp
);
1298 this.box
= $('#' + this.id
);
1299 this.content
= $('#' + this.id
+ ' .boxarea');
1301 this.box
.draggable({ stack
: ".box" });
1302 this.content
.click(function () {});
1303 //this.box.click(function(){ $(this)..css });
1305 Box
.prototype.create = function (name
, classname
) {
1308 Box
.prototype.id
= null;
1309 Box
.prototype.box
= null;
1310 Box
.prototype.content
= null;
1311 Box
.prototype.destroy = function () {
1314 for (name
in front
.boxes
) {
1315 if (front
.boxes
[name
].id
=== this.id
) {
1316 delete front
.boxes
[name
];
1320 Box
.prototype.height = function () {
1321 return this.box
.height();