Commit | Line | Data |
---|---|---|
8343584e D |
1 | /*jslint white:true, regexp: true, nomen: true, devel: true, undef: true, browser: true, continue: true, sloppy: true, forin: true, newcap: true, plusplus: true, maxerr: 50, indent: 4 */ |
2 | /*global kiwi, _, io, $, iScroll, agent, touchscreen, init_data, plugs, plugins, registerTouches, randomString */ | |
5a29866a JA |
3 | /** |
4 | * @namespace | |
5 | */ | |
673a7c8f | 6 | kiwi.front = { |
5a29866a JA |
7 | /** |
8 | * The current channel | |
9 | * @type Object | |
10 | */ | |
11 | cur_channel: null, | |
12 | /** | |
13 | * A list of windows | |
14 | * @type Object | |
15 | */ | |
a3364605 | 16 | windows: {}, |
5a29866a JA |
17 | /** |
18 | * A list of Tabviews | |
19 | * @type Object | |
20 | */ | |
a3364605 | 21 | tabviews: {}, |
5a29866a JA |
22 | /** |
23 | * A list of Utilityviews | |
24 | * @type Object | |
25 | */ | |
604c5174 | 26 | utilityviews: {}, |
5a29866a JA |
27 | /** |
28 | * A list of Boxes | |
29 | * @type Object | |
30 | */ | |
a3364605 | 31 | boxes: {}, |
8343584e | 32 | |
5a29866a JA |
33 | /** |
34 | * The command history | |
35 | * @type Array | |
36 | */ | |
37 | buffer: [], | |
38 | /** | |
39 | * The current command history position | |
40 | * @type Number | |
41 | */ | |
42 | buffer_pos: 0, | |
43 | ||
44 | /** | |
45 | * Container for misc data (eg. userlist generation) | |
46 | * @type Object | |
47 | */ | |
bfdeb872 | 48 | cache: {original_topic: '', userlist: {}}, |
8343584e | 49 | |
5a29866a JA |
50 | /** |
51 | * Initialisation function | |
52 | */ | |
a3364605 | 53 | init: function () { |
1fce4b40 JA |
54 | /*global Box, touch_scroll:true, Tabview */ |
55 | var about_info, supportsOrientationChange, orientationEvent, scroll_opts, server_tabview; | |
673a7c8f D |
56 | kiwi.gateway.nick = 'kiwi_' + Math.ceil(100 * Math.random()) + Math.ceil(100 * Math.random()); |
57 | kiwi.gateway.session_id = null; | |
8343584e | 58 | |
b41a381f D |
59 | // Bind to the gateway events |
60 | kiwi.front.events.bindAll(); | |
8343584e | 61 | |
a3364605 | 62 | // Build the about box |
673a7c8f | 63 | kiwi.front.boxes.about = new Box("about"); |
a3364605 JA |
64 | about_info = 'UI adapted for ' + agent; |
65 | if (touchscreen) { | |
66 | about_info += ' touchscreen '; | |
67 | } | |
68 | about_info += 'usage'; | |
69 | $('#tmpl_about_box').tmpl({ | |
47468e80 | 70 | about: about_info |
673a7c8f | 71 | }).appendTo(kiwi.front.boxes.about.content); |
a3364605 | 72 | |
673a7c8f | 73 | //$(window).bind("beforeunload", function(){ kiwi.gateway.quit(); }); |
8343584e | 74 | |
a3364605 JA |
75 | if (touchscreen) { |
76 | $('#kiwi').addClass('touchscreen'); | |
77 | ||
78 | // Single touch scrolling through scrollback for touchscreens | |
79 | scroll_opts = {}; | |
80 | touch_scroll = new iScroll('windows', scroll_opts); | |
81 | } | |
82 | ||
b41a381f | 83 | kiwi.front.ui.registerKeys(); |
8343584e | 84 | |
b41a381f D |
85 | $('#kiwi .toolbars').resize(kiwi.front.ui.doLayoutSize); |
86 | $(window).resize(kiwi.front.ui.doLayoutSize); | |
b10afa2d D |
87 | |
88 | // Add the resizer for the userlist | |
b6ee5d82 | 89 | $('<div id="nicklist_resize"></div>').appendTo('#kiwi'); |
80c584e7 JA |
90 | $('#nicklist_resize').draggable({axis: "x", drag: function () { |
91 | var t = $(this), | |
7779d29a | 92 | ul = $('#kiwi .userlist'), |
fde6ea95 | 93 | new_width = $(document).width() - parseInt(t.css('left'), 10); |
8343584e | 94 | |
7779d29a D |
95 | new_width = new_width - parseInt(ul.css('margin-left'), 10); |
96 | new_width = new_width - parseInt(ul.css('margin-right'), 10); | |
b10afa2d D |
97 | |
98 | // Make sure we don't remove the userlist alltogether | |
b10afa2d D |
99 | if (new_width < 20) { |
100 | $(this).data('draggable').offset.click.left = 10; | |
101 | console.log('whoaa'); | |
102 | } | |
103 | ||
1fce4b40 | 104 | Tabview.getCurrentTab().userlist.setWidth(new_width); |
7779d29a | 105 | $('#windows').css('right', ul.outerWidth(true)); |
b10afa2d D |
106 | }}); |
107 | ||
a3364605 JA |
108 | |
109 | $('#kiwi .formconnectwindow').submit(function () { | |
110 | var netsel = $('#kiwi .formconnectwindow .network'), | |
46f98bec JA |
111 | netport = $('#kiwi .formconnectwindow .port'), |
112 | netssl = $('#kiwi .formconnectwindow .ssl'), | |
e8a707e7 | 113 | netpass = $('#kiwi .formconnectwindow .password'), |
a3364605 | 114 | nick = $('#kiwi .formconnectwindow .nick'), |
6849bc6c JA |
115 | tmp, |
116 | forwardKeys; | |
8343584e | 117 | |
a3364605 JA |
118 | if (nick.val() === '') { |
119 | nick.val('Nick please!'); | |
120 | nick.focus(); | |
121 | return false; | |
122 | } | |
8343584e | 123 | |
a3364605 | 124 | tmp = nick.val().split(' '); |
673a7c8f | 125 | kiwi.gateway.nick = tmp[0]; |
c89b9fdf D |
126 | |
127 | init_data.channel = $('#channel').val(); | |
128 | ||
b41a381f | 129 | kiwi.front.ui.doLayout(); |
a3364605 | 130 | try { |
de578961 D |
131 | tmp = '/connect ' + netsel.val() + ' ' + netport.val() + ' '; |
132 | tmp += (netssl.is(':checked') ? 'true' : 'false') + ' ' + netpass.val(); | |
133 | kiwi.front.run(tmp); | |
4c408915 D |
134 | } catch (e) { |
135 | console.log(e); | |
136 | } | |
8343584e | 137 | |
b41a381f | 138 | $('#kiwi .connectwindow').slideUp('', kiwi.front.ui.barsShow); |
6849bc6c | 139 | |
5a29866a JA |
140 | /** |
141 | * Listen for keyboard activity on any window, and forward it to the | |
142 | * input box so users can type even if the input box is not in focus | |
143 | * @inner | |
144 | * @param {eventObject} event The event to forward | |
145 | */ | |
6849bc6c JA |
146 | forwardKeys = function (event) { |
147 | $('#kiwi_msginput').focus(); | |
148 | $('#kiwi_msginput').trigger(event); | |
149 | }; | |
150 | $('#kiwi_msginput').attr('tabindex', 0); | |
151 | $('#kiwi_msginput').focus(); | |
152 | $('#windows').attr('tabindex',100); | |
153 | $('#windows').keydown(forwardKeys).keypress(forwardKeys).keyup(forwardKeys); | |
a3364605 JA |
154 | |
155 | return false; | |
156 | }); | |
157 | ||
158 | supportsOrientationChange = (typeof window.onorientationchange !== undefined); | |
159 | orientationEvent = supportsOrientationChange ? "orientationchange" : "resize"; | |
d30da6a0 | 160 | if (window.addEventListener) { |
b41a381f | 161 | window.addEventListener(orientationEvent, kiwi.front.ui.doLayoutSize, false); |
d30da6a0 D |
162 | } else { |
163 | // < IE9 | |
b41a381f | 164 | window.attachEvent(orientationEvent, kiwi.front.ui.doLayoutSize, false); |
d30da6a0 | 165 | } |
b41a381f | 166 | //$('#kiwi').bind("resize", kiwi.front.ui.doLayoutSize, false); |
a3364605 | 167 | |
b41a381f D |
168 | kiwi.front.ui.doLayout(); |
169 | kiwi.front.ui.barsHide(); | |
8343584e | 170 | |
f7a9a13c JA |
171 | kiwi.bbchans = new kiwi.model.ChannelList(); |
172 | kiwi.bbtabs = new kiwi.view.Tabs({"el": $('#kiwi .windowlist ul')[0], "model": kiwi.bbchans}); | |
173 | ||
174 | ||
1fce4b40 | 175 | server_tabview = new Tabview('server'); |
0f439a3b | 176 | server_tabview.userlist.setWidth(0); // Disable the userlist |
3586a76e | 177 | server_tabview.setIcon('/img/app_menu.png'); |
3586a76e D |
178 | $('.icon', server_tabview.tab).tipTip({ |
179 | delay: 0, | |
180 | keepAlive: true, | |
181 | content: $('#tmpl_network_menu').tmpl({}).html(), | |
182 | activation: 'click' | |
183 | }); | |
8343584e | 184 | |
a3364605 | 185 | // Any pre-defined nick? |
c89b9fdf | 186 | if (typeof window.init_data.nick === "string") { |
bad1ea63 JA |
187 | $('#kiwi .formconnectwindow .nick').val(init_data.nick); |
188 | } | |
c89b9fdf D |
189 | |
190 | // Any pre-defined channels? | |
191 | if (typeof window.init_data.channel === 'string') { | |
192 | $('#channel').val(init_data.channel); | |
193 | } | |
8343584e | 194 | |
8ee99eba JA |
195 | // Fix for Opera inserting a spurious <br/> |
196 | $('#kiwi .cur_topic br').remove(); | |
8343584e | 197 | |
a3364605 | 198 | $('#kiwi .cur_topic').keydown(function (e) { |
aa191535 D |
199 | if (e.which === 13) { |
200 | // enter | |
201 | e.preventDefault(); | |
202 | $(this).change(); | |
203 | $('#kiwi_msginput').focus(); | |
204 | } else if (e.which === 27) { | |
205 | // escape | |
206 | e.preventDefault(); | |
bfdeb872 | 207 | $(this).text(kiwi.front.cache.original_topic); |
aa191535 D |
208 | $('#kiwi_msginput').focus(); |
209 | } | |
a3364605 | 210 | }); |
aa191535 | 211 | /*$('.cur_topic').live('keypress', function(e) { |
110ce6d4 | 212 | if (e.keyCode === 13) { |
1666d8d9 | 213 | // enter |
110ce6d4 JA |
214 | e.preventDefault(); |
215 | $(this).change(); | |
216 | $('#kiwi_msginput').focus(); | |
1666d8d9 JA |
217 | } else if (e.keyCode === 27) { |
218 | // escape | |
219 | e.preventDefault(); | |
bfdeb872 | 220 | $(this).text(kiwi.front.cache.original_topic); |
110ce6d4 | 221 | } |
aa191535 | 222 | });*/ |
a3364605 | 223 | $('.cur_topic').live('change', function () { |
110ce6d4 JA |
224 | var chan, text; |
225 | text = $(this).text(); | |
bfdeb872 | 226 | if (text !== kiwi.front.cache.original_topic) { |
1fce4b40 | 227 | chan = Tabview.getCurrentTab().name; |
312d2d7c | 228 | kiwi.gateway.topic(chan, text); |
110ce6d4 JA |
229 | } |
230 | }); | |
ff19dc74 D |
231 | |
232 | ||
c6ef62a3 | 233 | $('#windows a.chan').live('click', function () { |
673a7c8f | 234 | kiwi.front.joinChannel($(this).text()); |
ff19dc74 D |
235 | return false; |
236 | }); | |
8343584e | 237 | |
fde6ea95 | 238 | kiwi.data.set('chanList', []); |
abb46d2d | 239 | |
604eaa7d | 240 | // Load any client plugins |
2fc64ec2 JA |
241 | (function () { |
242 | var i; | |
243 | for (i in plugins) { | |
673a7c8f | 244 | kiwi.plugs.loadPlugin(plugins[i]); |
2fc64ec2 JA |
245 | } |
246 | }()); | |
a3364605 | 247 | }, |
8343584e | 248 | |
a3364605 | 249 | |
8343584e | 250 | |
5a29866a JA |
251 | /** |
252 | * Joins a channel | |
253 | * @param {String} chan_name The name of the channel to join | |
254 | */ | |
a3364605 JA |
255 | joinChannel: function (chan_name) { |
256 | var chans = chan_name.split(','), | |
c6ef62a3 | 257 | i, |
1fce4b40 JA |
258 | chan, |
259 | tab; | |
a3364605 JA |
260 | for (i in chans) { |
261 | chan = chans[i]; | |
1fce4b40 JA |
262 | tab = Tabview.getTab(chan); |
263 | if ((!tab) || (tab.safe_to_close === true)) { | |
673a7c8f | 264 | kiwi.gateway.join(chan); |
1fce4b40 | 265 | tab = new Tabview(chan); |
a3364605 | 266 | } else { |
1fce4b40 | 267 | tab.show(); |
a3364605 JA |
268 | } |
269 | } | |
270 | }, | |
8343584e | 271 | |
5a29866a JA |
272 | /** |
273 | * Parses and executes text and commands entered into the input msg box | |
274 | * @param {String} msg The message string to parse | |
275 | */ | |
a3364605 | 276 | run: function (msg) { |
312d2d7c | 277 | var parts, dest, t, pos, textRange, plugin_event, msg_sliced, tab, nick; |
8343584e | 278 | |
875d0c71 D |
279 | // Run through any plugins |
280 | plugin_event = {command: msg}; | |
673a7c8f | 281 | plugin_event = kiwi.plugs.run('command_run', plugin_event); |
c6ef62a3 JA |
282 | if (!plugin_event || typeof plugin_event.command === 'undefined') { |
283 | return; | |
284 | } | |
875d0c71 D |
285 | |
286 | // Update msg if it's been changed by any plugins | |
287 | msg = plugin_event.command.toString(); | |
288 | ||
8343584e | 289 | |
a3364605 | 290 | if (msg.substring(0, 1) === '/') { |
cd81360a | 291 | console.log("running " + msg); |
a3364605 JA |
292 | parts = msg.split(' '); |
293 | switch (parts[0].toLowerCase()) { | |
294 | case '/j': | |
295 | case '/join': | |
673a7c8f | 296 | kiwi.front.joinChannel(parts[1]); |
a3364605 | 297 | break; |
8343584e | 298 | |
a3364605 JA |
299 | case '/connect': |
300 | case '/server': | |
4c408915 | 301 | if (typeof parts[1] === 'undefined') { |
e8a707e7 | 302 | alert('Usage: /connect servername [port] [ssl] [password]'); |
a3364605 JA |
303 | break; |
304 | } | |
8343584e | 305 | |
4c408915 | 306 | if (typeof parts[2] === 'undefined') { |
bad1ea63 JA |
307 | parts[2] = 6667; |
308 | } | |
8343584e | 309 | |
4c408915 | 310 | if ((typeof parts[3] === 'undefined') || !parts[3] || (parts[3] === 'false') || (parts[3] === 'no')) { |
46f98bec JA |
311 | parts[3] = false; |
312 | } else { | |
313 | parts[3] = true; | |
314 | } | |
8343584e | 315 | |
1fce4b40 | 316 | Tabview.getCurrentTab().addMsg(null, ' ', '=== Connecting to ' + parts[1] + ' on port ' + parts[2] + (parts[3] ? ' using SSL' : '') + '...', 'status'); |
e8a707e7 | 317 | kiwi.gateway.connect(parts[1], parts[2], parts[3], parts[4]); |
a3364605 | 318 | break; |
8343584e | 319 | |
a3364605 JA |
320 | case '/nick': |
321 | console.log("/nick"); | |
322 | if (parts[1] === undefined) { | |
323 | console.log("calling show nick"); | |
b41a381f | 324 | kiwi.front.ui.showChangeNick(); |
a3364605 | 325 | } else { |
312d2d7c | 326 | console.log("sending nick"); |
5d57d62d | 327 | kiwi.gateway.changeNick(parts[1]); |
a3364605 JA |
328 | } |
329 | break; | |
330 | ||
331 | case '/part': | |
332 | if (typeof parts[1] === "undefined") { | |
1fce4b40 JA |
333 | if (Tabview.getCurrentTab().safe_to_close) { |
334 | Tabview.getCurrentTab().close(); | |
a3364605 | 335 | } else { |
312d2d7c | 336 | kiwi.gateway.part(Tabview.getCurrentTab().name); |
a3364605 JA |
337 | } |
338 | } else { | |
312d2d7c | 339 | kiwi.gateway.part(msg.substring(6)); |
a3364605 JA |
340 | } |
341 | break; | |
8343584e | 342 | |
a3364605 JA |
343 | case '/names': |
344 | if (typeof parts[1] !== "undefined") { | |
673a7c8f | 345 | kiwi.gateway.raw(msg.substring(1)); |
a3364605 JA |
346 | } |
347 | break; | |
8343584e | 348 | |
a3364605 | 349 | case '/debug': |
673a7c8f | 350 | kiwi.gateway.debug(); |
a3364605 | 351 | break; |
8343584e | 352 | |
a3364605 JA |
353 | case '/q': |
354 | case '/query': | |
355 | if (typeof parts[1] !== "undefined") { | |
1fce4b40 | 356 | tab = new Tabview(parts[1]); |
a3364605 JA |
357 | } |
358 | break; | |
323e90f6 | 359 | |
8343584e | 360 | |
323e90f6 D |
361 | case '/m': |
362 | case '/msg': | |
363 | if (typeof parts[1] !== "undefined") { | |
c6ef62a3 | 364 | msg_sliced = msg.split(' ').slice(2).join(' '); |
312d2d7c | 365 | kiwi.gateway.privmsg(parts[1], msg_sliced); |
a5ffcf00 | 366 | |
1fce4b40 JA |
367 | tab = Tabview.getTab(parts[1]); |
368 | if (!tab) { | |
369 | tab = new Tabview(parts[1]); | |
a5ffcf00 | 370 | } |
1fce4b40 | 371 | tab.addMsg(null, kiwi.gateway.nick, msg_sliced); |
323e90f6 D |
372 | } |
373 | break; | |
8343584e | 374 | |
cdd803f6 D |
375 | case '/k': |
376 | case '/kick': | |
80c584e7 | 377 | if (typeof parts[1] === 'undefined') { |
fde6ea95 JA |
378 | return; |
379 | } | |
312d2d7c JA |
380 | t = msg.split(' ', 3); |
381 | nick = t[1]; | |
382 | kiwi.gateway.kick(Tabview.getCurrentTab().name, nick, t[2]); | |
cdd803f6 D |
383 | break; |
384 | ||
a3364605 | 385 | case '/quote': |
673a7c8f | 386 | kiwi.gateway.raw(msg.replace(/^\/quote /i, '')); |
a3364605 | 387 | break; |
8343584e | 388 | |
a3364605 | 389 | case '/me': |
1fce4b40 | 390 | tab = Tabview.getCurrentTab(); |
312d2d7c | 391 | kiwi.gateway.ctcp(true, 'ACTION', tab.name, msg.substring(4)); |
1fce4b40 | 392 | tab.addMsg(null, ' ', '* ' + kiwi.gateway.nick + ' ' + msg.substring(4), 'action', 'color:#555;'); |
a3364605 JA |
393 | break; |
394 | ||
395 | case '/notice': | |
396 | dest = parts[1]; | |
397 | msg = parts.slice(2).join(' '); | |
398 | ||
673a7c8f | 399 | kiwi.gateway.notice(dest, msg); |
b41a381f | 400 | kiwi.front.events.onNotice({}, {nick: kiwi.gateway.nick, channel: dest, msg: msg}); |
a3364605 JA |
401 | break; |
402 | ||
403 | case '/win': | |
404 | if (parts[1] !== undefined) { | |
b41a381f | 405 | kiwi.front.ui.windowsShow(parseInt(parts[1], 10)); |
a3364605 JA |
406 | } |
407 | break; | |
408 | ||
409 | case '/quit': | |
b575fa08 | 410 | kiwi.gateway.quit(parts.slice(1).join(' ')); |
f4f7781b JA |
411 | break; |
412 | ||
45c03116 | 413 | case '/topic': |
a3364605 JA |
414 | if (parts[1] === undefined) { |
415 | t = $('.cur_topic'); | |
416 | if (t.createTextRange) { | |
417 | pos = t.text().length(); | |
418 | textRange = t.createTextRange(); | |
419 | textRange.collapse(true); | |
420 | textRange.moveEnd(pos); | |
421 | textRange.moveStart(pos); | |
422 | textRange.select(); | |
423 | } else if (t.setSelectionRange) { | |
424 | t.setSelectionRange(pos, pos); | |
425 | } | |
426 | } else { | |
312d2d7c | 427 | kiwi.gateway.topic(Tabview.getCurrentTab().name, msg.split(' ', 2)[1]); |
aa191535 | 428 | } |
45c03116 | 429 | break; |
abb46d2d D |
430 | |
431 | case '/kiwi': | |
312d2d7c | 432 | kiwi.gateway.ctcp(true, 'KIWI', Tabview.getCurrentTab().name, msg.substring(6)); |
abb46d2d D |
433 | break; |
434 | ||
a3c7edd4 JA |
435 | case '/ctcp': |
436 | parts = parts.slice(1); | |
437 | dest = parts.shift(); | |
312d2d7c | 438 | t = parts.shift(); |
a3c7edd4 | 439 | msg = parts.join(' '); |
312d2d7c JA |
440 | console.log(parts); |
441 | ||
442 | kiwi.gateway.ctcp(true, t, dest, msg); | |
443 | Tabview.getServerTab().addMsg(null, 'CTCP Request', '[to ' + dest + '] ' + t + ' ' + msg, 'ctcp'); | |
a3c7edd4 | 444 | break; |
a3364605 | 445 | default: |
1fce4b40 | 446 | //Tabview.getCurrentTab().addMsg(null, ' ', '--> Invalid command: '+parts[0].substring(1)); |
8343584e | 447 | kiwi.gateway.raw(msg.substring(1)); |
bfdeb872 | 448 | break; |
a3364605 JA |
449 | } |
450 | ||
451 | } else { | |
452 | //alert('Sending message: '+msg); | |
453 | if (msg.trim() === '') { | |
bad1ea63 JA |
454 | return; |
455 | } | |
1fce4b40 | 456 | if (Tabview.getCurrentTab().name !== 'server') { |
312d2d7c | 457 | kiwi.gateway.privmsg(Tabview.getCurrentTab().name, msg); |
1fce4b40 | 458 | Tabview.getCurrentTab().addMsg(null, kiwi.gateway.nick, msg); |
a3364605 JA |
459 | } |
460 | } | |
461 | }, | |
8343584e D |
462 | |
463 | ||
8343584e | 464 | |
8343584e | 465 | |
7af36ece | 466 | |
0b399cb0 D |
467 | /** |
468 | * Sort the window list | |
469 | */ | |
470 | sortWindowList: function () { | |
f93aafe5 JA |
471 | var win_list = $('#kiwi .windowlist ul'), |
472 | listitems = win_list.children('li').get(); | |
c32b30d6 | 473 | |
0b399cb0 | 474 | listitems.sort(function (a, b) { |
f93aafe5 | 475 | if (a === Tabview.getServerTab().tab[0]) { |
0b399cb0 D |
476 | return -1; |
477 | } | |
f93aafe5 | 478 | if (b === Tabview.getServerTab().tab[0]) { |
b16d21f2 JA |
479 | return 1; |
480 | } | |
f93aafe5 JA |
481 | var compA = $(a).text().toUpperCase(), |
482 | compB = $(b).text().toUpperCase(); | |
0b399cb0 | 483 | return (compA < compB) ? -1 : (compA > compB) ? 1 : 0; |
f93aafe5 | 484 | }); |
0b399cb0 D |
485 | |
486 | $.each(listitems, function(idx, itm) { | |
487 | win_list.append(itm); | |
488 | }); | |
489 | }, | |
490 | ||
491 | ||
492 | ||
a3364605 | 493 | |
5a29866a JA |
494 | /** |
495 | * Syncs with the Kiwi server | |
496 | * Not implemented | |
497 | */ | |
a3364605 | 498 | sync: function () { |
673a7c8f | 499 | kiwi.gateway.sync(); |
a3364605 | 500 | }, |
8343584e | 501 | |
5a29866a JA |
502 | /** |
503 | * Checks if a given name is the name of a channel | |
504 | * @param {String} name The name to check | |
505 | * @returns {Boolean} True if name is the name of a channel, false if it is not | |
506 | */ | |
a3364605 | 507 | isChannel: function (name) { |
c6ef62a3 | 508 | var prefix, is_chan; |
a3364605 | 509 | prefix = name.charAt(0); |
673a7c8f | 510 | if (kiwi.gateway.channel_prefix.indexOf(prefix) > -1) { |
a3364605 JA |
511 | is_chan = true; |
512 | } else { | |
513 | is_chan = false; | |
514 | } | |
8343584e | 515 | |
a3364605 JA |
516 | return is_chan; |
517 | }, | |
8343584e | 518 | |
5a29866a JA |
519 | /** |
520 | * Formats a message. Adds bold, underline and colouring | |
521 | * @param {String} msg The message to format | |
522 | * @returns {String} The HTML formatted message | |
523 | */ | |
0a202119 | 524 | formatIRCMsg: function (msg) { |
8343584e D |
525 | var re, next; |
526 | ||
9d34a1ca | 527 | if ((!msg) || (typeof msg !== 'string')) { |
b91949aa | 528 | return ''; |
9d34a1ca | 529 | } |
8343584e | 530 | |
24552b4b JA |
531 | // bold |
532 | if (msg.indexOf(String.fromCharCode(2)) !== -1) { | |
533 | next = '<b>'; | |
534 | while (msg.indexOf(String.fromCharCode(2)) !== -1) { | |
535 | msg = msg.replace(String.fromCharCode(2), next); | |
536 | next = (next === '<b>') ? '</b>' : '<b>'; | |
537 | } | |
538 | if (next === '</b>') { | |
539 | msg = msg + '</b>'; | |
540 | } | |
541 | } | |
8343584e | 542 | |
24552b4b JA |
543 | // underline |
544 | if (msg.indexOf(String.fromCharCode(31)) !== -1) { | |
545 | next = '<u>'; | |
546 | while (msg.indexOf(String.fromCharCode(31)) !== -1) { | |
547 | msg = msg.replace(String.fromCharCode(31), next); | |
548 | next = (next === '<u>') ? '</u>' : '<u>'; | |
549 | } | |
550 | if (next === '</u>') { | |
551 | msg = msg + '</u>'; | |
552 | } | |
553 | } | |
8343584e | 554 | |
24552b4b | 555 | // colour |
5a29866a JA |
556 | /** |
557 | * @inner | |
558 | */ | |
52a45f8c JA |
559 | msg = (function (msg) { |
560 | var replace, colourMatch, col, i, match, to, endCol, fg, bg, str; | |
561 | replace = ''; | |
5a29866a JA |
562 | /** |
563 | * @inner | |
564 | */ | |
52a45f8c JA |
565 | colourMatch = function (str) { |
566 | var re = /^\x03([0-9][0-5]?)(,([0-9][0-5]?))?/; | |
567 | return re.exec(str); | |
568 | }; | |
5a29866a JA |
569 | /** |
570 | * @inner | |
571 | */ | |
52a45f8c JA |
572 | col = function (num) { |
573 | switch (parseInt(num, 10)) { | |
574 | case 0: | |
575 | return '#FFFFFF'; | |
576 | case 1: | |
577 | return '#000000'; | |
578 | case 2: | |
579 | return '#000080'; | |
580 | case 3: | |
581 | return '#008000'; | |
582 | case 4: | |
583 | return '#FF0000'; | |
584 | case 5: | |
585 | return '#800040'; | |
586 | case 6: | |
587 | return '#800080'; | |
588 | case 7: | |
589 | return '#FF8040'; | |
590 | case 8: | |
591 | return '#FFFF00'; | |
592 | case 9: | |
593 | return '#80FF00'; | |
594 | case 10: | |
595 | return '#008080'; | |
596 | case 11: | |
597 | return '#00FFFF'; | |
598 | case 12: | |
599 | return '#0000FF'; | |
600 | case 13: | |
601 | return '#FF55FF'; | |
602 | case 14: | |
603 | return '#808080'; | |
604 | case 15: | |
605 | return '#C0C0C0'; | |
606 | default: | |
607 | return null; | |
608 | } | |
609 | }; | |
610 | if (msg.indexOf('\x03') !== -1) { | |
611 | i = msg.indexOf('\x03'); | |
612 | replace = msg.substr(0, i); | |
613 | while (i < msg.length) { | |
5a29866a JA |
614 | /** |
615 | * @inner | |
616 | */ | |
52a45f8c JA |
617 | match = colourMatch(msg.substr(i, 6)); |
618 | if (match) { | |
619 | //console.log(match); | |
620 | // Next colour code | |
621 | to = msg.indexOf('\x03', i + 1); | |
622 | endCol = msg.indexOf(String.fromCharCode(15), i + 1); | |
623 | if (endCol !== -1) { | |
624 | if (to === -1) { | |
625 | to = endCol; | |
626 | } else { | |
627 | to = ((to < endCol) ? to : endCol); | |
628 | } | |
629 | } | |
630 | if (to === -1) { | |
631 | to = msg.length; | |
632 | } | |
633 | //console.log(i, to); | |
634 | fg = col(match[1]); | |
635 | bg = col(match[3]); | |
636 | str = msg.substring(i + 1 + match[1].length + ((bg !== null) ? match[2].length + 1 : 0), to); | |
637 | //console.log(str); | |
638 | replace += '<span style="' + ((fg !== null) ? 'color: ' + fg + '; ' : '') + ((bg !== null) ? 'background-color: ' + bg + ';' : '') + '">' + str + '</span>'; | |
639 | i = to; | |
640 | } else { | |
641 | if ((msg[i] !== '\x03') && (msg[i] !== String.fromCharCode(15))) { | |
642 | replace += msg[i]; | |
643 | } | |
644 | i++; | |
24552b4b | 645 | } |
52a45f8c JA |
646 | } |
647 | return replace; | |
648 | } | |
649 | return msg; | |
650 | }(msg)); | |
651 | ||
24552b4b | 652 | return msg; |
cbcccdbd | 653 | }, |
5a29866a JA |
654 | |
655 | /** | |
656 | * Registers Kiwi IRC as a handler for the irc:// protocol in the browser | |
657 | */ | |
cbcccdbd D |
658 | registerProtocolHandler: function () { |
659 | var state, uri; | |
660 | url = kiwi_server.replace(/\/kiwi$/, '/?ircuri=%s'); | |
661 | try { | |
662 | //state = window.navigator.isProtocolHandlerRegistered('irc', url); | |
663 | //if (state !== 'registered') { | |
664 | window.navigator.registerProtocolHandler('irc', url, 'Kiwi IRC'); | |
665 | //} | |
666 | } catch (e) { | |
667 | console.log('Unable to register Kiwi IRC as a handler for irc:// links'); | |
668 | console.error(e); | |
669 | } | |
a3364605 | 670 | } |
8343584e | 671 | |
a3364605 | 672 | }; |
54f4a22e D |
673 | |
674 | ||
675 | ||
676 | ||
677 | ||
5a29866a JA |
678 | /** |
679 | * @constructor | |
680 | */ | |
dde5dcd9 JA |
681 | var ChannelList = function () { |
682 | /*globals Utilityview */ | |
683 | var chanList, view, table, obj, renderTable, waiting; | |
684 | chanList = []; | |
685 | ||
686 | view = new Utilityview('Channel List'); | |
687 | view.div.css('overflow-y', 'scroll'); | |
688 | ||
689 | table = $('<table style="margin:1em 2em;"><thead style="font-weight: bold;"><tr><td>Channel Name</td><td>Members</td><td style="padding-left: 2em;">Topic</td></tr></thead><tbody style="vertical-align: top;"></tbody>'); | |
690 | table = table.appendTo(view.div); | |
691 | ||
692 | waiting = false; | |
5a29866a JA |
693 | /** |
694 | * @inner | |
695 | */ | |
dde5dcd9 JA |
696 | renderTable = function () { |
697 | var tbody; | |
698 | tbody = table.children('tbody:first').detach(); | |
699 | /*tbody.children().each(function (child) { | |
700 | var i, chan; | |
701 | child = $(child); | |
702 | chan = child.children('td:first').text(); | |
703 | for (i = 0; i < chanList.length; i++) { | |
704 | if (chanList[i].channel === chan) { | |
705 | chanList[i].html = child.detach(); | |
706 | break; | |
707 | } | |
708 | } | |
709 | });*/ | |
710 | _.each(chanList, function (chan) { | |
711 | chan.html = $(chan.html).appendTo(tbody); | |
712 | }); | |
713 | table = table.append(tbody); | |
714 | waiting = false; | |
715 | }; | |
5a29866a JA |
716 | /** |
717 | * @lends ChannelList | |
718 | */ | |
719 | return { | |
720 | /** | |
721 | * Adds a channel or channels to the list | |
722 | * @param {Object} channels The channel or Array of channels to add | |
723 | */ | |
dde5dcd9 JA |
724 | addChannel: function (channels) { |
725 | if (!_.isArray(channels)) { | |
726 | channels = [channels]; | |
727 | } | |
728 | _.each(channels, function (chan) { | |
729 | var html, channel; | |
730 | html = $('<tr><td><a class="chan">' + chan.channel + '</a></td><td class="num_users" style="text-align: center;">' + chan.num_users + '</td><td style="padding-left: 2em;">' + kiwi.front.formatIRCMsg(chan.topic) + '</td></tr>'); | |
731 | chan.html = html; | |
732 | chanList.push(chan); | |
733 | }); | |
734 | chanList.sort(function (a, b) { | |
735 | return b.num_users - a.num_users; | |
736 | }); | |
737 | if (!waiting) { | |
738 | waiting = true; | |
739 | _.defer(renderTable); | |
740 | } | |
741 | }, | |
5a29866a JA |
742 | /** |
743 | * Show the {@link UtilityView} that will display this channel list | |
744 | */ | |
dde5dcd9 JA |
745 | show: function () { |
746 | view.show(); | |
747 | }, | |
5a29866a JA |
748 | /** |
749 | * @private | |
750 | */ | |
dde5dcd9 JA |
751 | prototype: {constructor: this} |
752 | }; | |
dde5dcd9 | 753 | }; |
54f4a22e | 754 | |
5a29866a JA |
755 | /** |
756 | * @constructor | |
757 | * @param {String} name The name of the UserList | |
758 | */ | |
8343584e | 759 | var UserList = function (name) { |
7af36ece JA |
760 | /*globals User */ |
761 | var userlist, list_html, sortUsers; | |
8343584e D |
762 | |
763 | userlist = []; | |
764 | ||
765 | $('#kiwi .userlist').append($('<ul id="kiwi_userlist_' + name + '"></ul>')); | |
766 | list_html = $('#kiwi_userlist_' + name); | |
767 | $('a.nick', list_html[0]).live('click', this.clickHandler); | |
768 | ||
5a29866a JA |
769 | /** |
770 | * @inner | |
771 | */ | |
8343584e D |
772 | sortUsers = function () { |
773 | var parent; | |
774 | parent = list_html.parent(); | |
775 | list_html = list_html.detach(); | |
776 | ||
777 | // Not sure this is needed. | |
778 | // It's O(n^2) as well, so need to test to see if it works without. | |
779 | // Alternative to test: list_html.children('li').detach(); | |
780 | list_html.children().each(function (child) { | |
781 | var i, nick; | |
782 | child = $(child); | |
783 | nick = child.data('nick'); | |
784 | for (i = 0; i < userlist.length; i++) { | |
785 | if (userlist[i].nick === nick) { | |
786 | userlist[i].html = child.detach(); | |
787 | break; | |
788 | } | |
789 | } | |
790 | }); | |
791 | ||
7af36ece | 792 | userlist.sort(User.compare); |
8343584e | 793 | |
8343584e D |
794 | _.each(userlist, function (user) { |
795 | user.html = user.html.appendTo(list_html); | |
796 | }); | |
54f4a22e | 797 | |
8343584e D |
798 | list_html = list_html.appendTo(parent); |
799 | }; | |
800 | ||
5a29866a JA |
801 | /** |
802 | * Adds a user or users to the UserList. | |
803 | * Chainable method. | |
804 | * @param {Object} users The user or Array of users to add | |
805 | * @returns {UserList} This UserList | |
806 | */ | |
8343584e D |
807 | this.addUser = function (users) { |
808 | if (!_.isArray(users)) { | |
809 | users = [users]; | |
810 | } | |
811 | _.each(users, function (user) { | |
7af36ece JA |
812 | user = new User(user.nick, user.modes); |
813 | user.html = $('<li><a class="nick">' + user.prefix + user.nick + '</a></li>'); | |
814 | user.html.data('user', user); | |
815 | userlist.push(user); | |
8343584e D |
816 | }); |
817 | sortUsers(); | |
818 | ||
819 | return this; | |
820 | }; | |
821 | ||
5a29866a JA |
822 | /** |
823 | * Removes a user or users from the UserList. | |
824 | * Chainable method. | |
825 | * @param {String} nicks The nick or Array of nicks to remove | |
826 | * @returns {UserList} This UserList | |
827 | */ | |
8343584e D |
828 | this.removeUser = function (nicks) { |
829 | var toRemove; | |
830 | if (!_.isArray(nicks)) { | |
831 | nicks = [nicks]; | |
832 | } | |
833 | toRemove = _.select(userlist, function (user) { | |
834 | return _.any(nicks, function (n) { | |
835 | return n === user.nick; | |
836 | }); | |
837 | }); | |
838 | ||
839 | _.each(toRemove, function (user) { | |
840 | user.html.remove(); | |
841 | }); | |
842 | ||
843 | userlist = _.difference(userlist, toRemove); | |
844 | ||
845 | return this; | |
846 | }; | |
847 | ||
5a29866a JA |
848 | /** |
849 | * Renames a user in the UserList. | |
850 | * Chainable method. | |
851 | * @param {String} oldNick The old nick | |
852 | * @param {String} newNick The new nick | |
853 | * @returns {UserList} This UserList | |
854 | */ | |
8343584e D |
855 | this.renameUser = function (oldNick, newNick) { |
856 | var user = _.detect(userlist, function (u) { | |
857 | return u.nick === oldNick; | |
858 | }); | |
859 | if (user) { | |
860 | user.nick = newNick; | |
7af36ece | 861 | user.html.text(User.getPrefix(user.modes) + newNick); |
8343584e D |
862 | } |
863 | ||
864 | sortUsers(); | |
865 | ||
866 | return this; | |
867 | }; | |
868 | ||
5a29866a JA |
869 | /** |
870 | * Lists the users in this UserList. | |
871 | * @param {Boolean} modesort True to enable sorting by mode, false for lexicographical sort | |
872 | * @param {Array} mode If specified, only return those users who have the specified modes | |
873 | * @returns {Array} The users in the UserList that match the criteria | |
874 | */ | |
8343584e D |
875 | this.listUsers = function (modesort, modes) { |
876 | var users = userlist; | |
877 | if (modes) { | |
878 | users = _.select(users, function (user) { | |
879 | return _.any(modes, function (m) { | |
880 | return _.any(user.modes, function (um) { | |
881 | return m === um; | |
882 | }); | |
883 | }); | |
884 | }); | |
885 | } | |
886 | if ((modesort === true) || (typeof modesort === undefined)) { | |
887 | return users; | |
888 | } else { | |
889 | return _.sortBy(users, function (user) { | |
890 | return user.nick; | |
891 | }); | |
892 | } | |
893 | }; | |
894 | ||
5a29866a JA |
895 | /** |
896 | * Remove this UserList from the DOM. | |
897 | */ | |
8343584e D |
898 | this.remove = function () { |
899 | list_html.remove(); | |
900 | list_html = null; | |
901 | userlist = null; | |
902 | }; | |
903 | ||
5a29866a JA |
904 | /** |
905 | * Empty the UserList. | |
906 | * Chainable method. | |
907 | * @returns {UserList} This UserList | |
908 | */ | |
8343584e D |
909 | this.empty = function () { |
910 | list_html.children().remove(); | |
911 | userlist = []; | |
912 | ||
913 | return this; | |
914 | }; | |
915 | ||
5a29866a JA |
916 | /** |
917 | * Checks whether a given nick is in the UserList. | |
918 | * @param {String} nick The nick to search for | |
919 | * @returns {Boolean} True if the nick is in the userlist, false otherwise | |
920 | */ | |
8343584e D |
921 | this.hasUser = function (nick) { |
922 | return _.any(userlist, function (user) { | |
923 | return user.nick === nick; | |
924 | }); | |
925 | }; | |
926 | ||
5a29866a JA |
927 | /** |
928 | * Returns the object representing the user with the given nick, if it is in the UserList. | |
929 | * @param {String} nick The nick to retrieve | |
930 | * @returns {Object} An object representing the user, if it exists, null otherwise | |
931 | */ | |
7af36ece JA |
932 | this.getUser = function (nick) { |
933 | if (this.hasUser(nick)) { | |
934 | return _.detect(userlist, function (user) { | |
935 | return user.nick === nick; | |
936 | }); | |
937 | } else { | |
938 | return null; | |
939 | } | |
940 | }; | |
941 | ||
5a29866a JA |
942 | /** |
943 | * Sets the UserList's activity. | |
944 | * Chainable method. | |
945 | * @param {Boolean} active If true, sets the UserList to active. If False, sets it to inactive | |
946 | * @returns {UserList} This UserList | |
947 | */ | |
8343584e D |
948 | this.active = function (active) { |
949 | if ((arguments.length === 0) || (active)) { | |
950 | list_html.addClass('active'); | |
951 | list_html.show(); | |
952 | } else { | |
953 | list_html.removeClass('active'); | |
954 | list_html.hide(); | |
955 | } | |
956 | ||
957 | return this; | |
958 | }; | |
959 | ||
5a29866a JA |
960 | /** |
961 | * Updates a user's mode. | |
962 | * Chainable method. | |
963 | * @param {String} nick The nick of the user to modify | |
964 | * @param {String} mode The mode to add or remove | |
965 | * @param {Boolean} add Adds the mode if true, removes it otherwise | |
966 | * @returns {UserList} This UserList | |
967 | */ | |
8343584e | 968 | this.changeUserMode = function (nick, mode, add) { |
7af36ece | 969 | var user, prefix; |
8343584e | 970 | if (this.hasUser(nick)) { |
7af36ece | 971 | user = _.detect(userlist, function (u) { |
8343584e D |
972 | return u.nick === nick; |
973 | }); | |
974 | ||
7af36ece | 975 | prefix = user.prefix; |
8343584e | 976 | if ((arguments.length < 3) || (add)) { |
7af36ece | 977 | user.addMode(mode); |
8343584e | 978 | } else { |
7af36ece JA |
979 | user.removeMode(mode); |
980 | } | |
981 | if (prefix !== user.prefix) { | |
982 | user.html.children('a:first').text(user.prefix + user.nick); | |
8343584e | 983 | } |
8343584e D |
984 | sortUsers(); |
985 | } | |
986 | ||
987 | return this; | |
988 | }; | |
989 | }; | |
5a29866a JA |
990 | /** |
991 | * @memberOf UserList | |
992 | */ | |
0f439a3b | 993 | UserList.prototype.width = 100; // 0 to disable |
5a29866a JA |
994 | /** |
995 | * Sets the width of the UserList. | |
996 | * Chainable method. | |
997 | * @param {Number} newWidth The new width of the UserList | |
998 | * @returns {UserList} This UserList | |
999 | */ | |
8343584e D |
1000 | UserList.prototype.setWidth = function (newWidth) { |
1001 | var w, u; | |
7779d29a | 1002 | if (typeof newWidth === 'number') { |
8343584e | 1003 | this.width = newWidth; |
7779d29a | 1004 | } |
8343584e | 1005 | |
7779d29a D |
1006 | w = $('#windows'); |
1007 | u = $('#kiwi .userlist'); | |
8343584e | 1008 | |
7779d29a | 1009 | u.width(this.width); |
8343584e D |
1010 | |
1011 | return this; | |
1012 | }; | |
5a29866a JA |
1013 | /** |
1014 | * The click handler for this UserList | |
1015 | */ | |
8343584e | 1016 | UserList.prototype.clickHandler = function () { |
7af36ece | 1017 | var li = $(this).parent(), |
0dc1dc79 D |
1018 | user = li.data('user'), |
1019 | userbox; | |
1020 | ||
8343584e D |
1021 | // Remove any existing userboxes |
1022 | $('#kiwi .userbox').remove(); | |
1023 | ||
0dc1dc79 D |
1024 | if (li.data('userbox') === true) { |
1025 | // This li already has the userbox, show remove it instead | |
1026 | li.removeData('userbox'); | |
1027 | ||
8343584e | 1028 | } else { |
0dc1dc79 D |
1029 | // We don't have a userbox so create one |
1030 | userbox = $('#tmpl_user_box').tmpl({nick: user.nick}).appendTo(li); | |
8343584e | 1031 | |
0dc1dc79 | 1032 | $('.userbox_query', userbox).click(function (ev) { |
8343584e D |
1033 | var nick = $('#kiwi .userbox_nick').val(); |
1034 | kiwi.front.run('/query ' + nick); | |
1035 | }); | |
1036 | ||
0dc1dc79 | 1037 | $('.userbox_whois', userbox).click(function (ev) { |
8343584e D |
1038 | var nick = $('#kiwi .userbox_nick').val(); |
1039 | kiwi.front.run('/whois ' + nick); | |
1040 | }); | |
0dc1dc79 | 1041 | li.data('userbox', true); |
8343584e D |
1042 | } |
1043 | }; | |
54f4a22e D |
1044 | |
1045 | ||
1046 | ||
5a29866a JA |
1047 | /** |
1048 | * @constructor | |
943caaef JA |
1049 | * The User class. Represents a user on a channel. |
1050 | * @param {String} nick The user's nickname | |
1051 | * @param {Array} modes An array of channel user modes | |
5a29866a | 1052 | */ |
7af36ece JA |
1053 | var User = function (nick, modes) { |
1054 | var sortModes; | |
5a29866a JA |
1055 | /** |
1056 | * @inner | |
1057 | */ | |
7af36ece JA |
1058 | sortModes = function (modes) { |
1059 | return modes.sort(function (a, b) { | |
1060 | var a_idx, b_idx, i; | |
1061 | for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) { | |
1062 | if (kiwi.gateway.user_prefixes[i].mode === a) { | |
1063 | a_idx = i; | |
1064 | } | |
1065 | } | |
1066 | for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) { | |
1067 | if (kiwi.gateway.user_prefixes[i].mode === b) { | |
1068 | b_idx = i; | |
1069 | } | |
1070 | } | |
1071 | if (a_idx < b_idx) { | |
1072 | return -1; | |
1073 | } else if (a_idx > b_idx) { | |
1074 | return 1; | |
1075 | } else { | |
1076 | return 0; | |
1077 | } | |
1078 | }); | |
1079 | }; | |
1080 | ||
1081 | this.nick = User.stripPrefix(nick); | |
1082 | this.modes = modes || []; | |
1083 | this.modes = sortModes(this.modes); | |
1084 | this.prefix = User.getPrefix(this.modes); | |
1085 | ||
943caaef JA |
1086 | /** |
1087 | * @inner | |
1088 | */ | |
7af36ece JA |
1089 | this.addMode = function (mode) { |
1090 | this.modes.push(mode); | |
1091 | this.modes = sortModes(this.modes); | |
1092 | this.prefix = User.getPrefix(this.modes); | |
1093 | return this; | |
1094 | }; | |
1095 | }; | |
1096 | ||
943caaef JA |
1097 | /** |
1098 | * Removes a channel mode from the user | |
1099 | * @param {String} mode The mode(s) to remove | |
1100 | * @returns {User} Returns the User object to allow chaining | |
1101 | */ | |
7af36ece JA |
1102 | User.prototype.removeMode = function (mode) { |
1103 | this.modes = _.reject(this.modes, function (m) { | |
1104 | return m === mode; | |
1105 | }); | |
1106 | this.prefix = User.getPrefix(this.modes); | |
1107 | return this; | |
1108 | }; | |
1109 | ||
943caaef JA |
1110 | /** |
1111 | * Checks to see if the user is an op on the channel | |
1112 | * @returns {Boolean} True if the user is an op, false otherwise | |
1113 | */ | |
7af36ece JA |
1114 | User.prototype.isOp = function () { |
1115 | // return true if this.mode[0] > o | |
1116 | return false; | |
1117 | }; | |
1118 | ||
943caaef JA |
1119 | /** |
1120 | * Returns the highest user prefix (e.g.~, @, or +) that matches the modes given | |
1121 | * @param {Array} modes An array of mode letters | |
1122 | * @returns {String} The user's prefix | |
1123 | */ | |
7af36ece JA |
1124 | User.getPrefix = function (modes) { |
1125 | var prefix = ''; | |
1126 | if (typeof modes[0] !== 'undefined') { | |
1127 | prefix = _.detect(kiwi.gateway.user_prefixes, function (prefix) { | |
1128 | return prefix.mode === modes[0]; | |
1129 | }); | |
1130 | prefix = (prefix) ? prefix.symbol : ''; | |
1131 | } | |
1132 | return prefix; | |
1133 | }; | |
1134 | ||
943caaef JA |
1135 | /** |
1136 | * Returns the user's nick without the mode prefix | |
1137 | * @param {String} nick The nick to strip the prefix from | |
1138 | * @returns {String} The nick without the prefix | |
1139 | */ | |
7af36ece JA |
1140 | User.stripPrefix = function (nick) { |
1141 | var tmp = nick, i, j, k; | |
1142 | i = 0; | |
1143 | for (j = 0; j < nick.length; j++) { | |
1144 | for (k = 0; k < kiwi.gateway.user_prefixes.length; k++) { | |
1145 | if (nick.charAt(j) === kiwi.gateway.user_prefixes[k].symbol) { | |
1146 | i++; | |
1147 | break; | |
1148 | } | |
1149 | } | |
1150 | } | |
1151 | ||
1152 | return tmp.substr(i); | |
1153 | }; | |
1154 | ||
943caaef JA |
1155 | /** |
1156 | * Comparison function to order nicks based on their modes and/or nicks | |
1157 | * @param {User} a The first User to evaluate | |
1158 | * @param {User} b The second User to evaluate | |
1159 | * @returns {Number} -1 if a should be sorted before b, 1 if b should be sorted before a, and 0 if the two Users are the same. | |
1160 | */ | |
7af36ece JA |
1161 | User.compare = function (a, b) { |
1162 | var i, a_idx, b_idx, a_nick, b_nick; | |
1163 | // Try to sort by modes first | |
1164 | if (a.modes.length > 0) { | |
1165 | // a has modes, but b doesn't so a should appear first | |
1166 | if (b.modes.length === 0) { | |
1167 | return -1; | |
1168 | } | |
1169 | a_idx = b_idx = -1; | |
1170 | // Compare the first (highest) mode | |
1171 | for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) { | |
1172 | if (kiwi.gateway.user_prefixes[i].mode === a.modes[0]) { | |
1173 | a_idx = i; | |
1174 | } | |
1175 | } | |
1176 | for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) { | |
1177 | if (kiwi.gateway.user_prefixes[i].mode === b.modes[0]) { | |
1178 | b_idx = i; | |
1179 | } | |
1180 | } | |
1181 | if (a_idx < b_idx) { | |
1182 | return -1; | |
1183 | } else if (a_idx > b_idx) { | |
1184 | return 1; | |
1185 | } | |
1186 | // If we get to here both a and b have the same highest mode so have to resort to lexicographical sorting | |
1187 | ||
1188 | } else if (b.modes.length > 0) { | |
1189 | // b has modes but a doesn't so b should appear first | |
1190 | return 1; | |
1191 | } | |
1192 | a_nick = a.nick.toLocaleUpperCase(); | |
1193 | b_nick = b.nick.toLocaleUpperCase(); | |
1194 | // Lexicographical sorting | |
1195 | if (a_nick < b_nick) { | |
1196 | return -1; | |
1197 | } else if (a_nick > b_nick) { | |
1198 | return 1; | |
1199 | } else { | |
1200 | // This should never happen; both users have the same nick. | |
1201 | console.log('Something\'s gone wrong somewhere - two users have the same nick!'); | |
1202 | return 0; | |
1203 | } | |
1204 | }; | |
1205 | ||
1206 | ||
54f4a22e | 1207 | |
1bb74900 D |
1208 | /* |
1209 | * MISC VIEW | |
1210 | */ | |
5a29866a JA |
1211 | /** |
1212 | * @constructor | |
943caaef JA |
1213 | * A tab to show non-channel and non-query windows to the user |
1214 | * @param {String} name The name of the view | |
5a29866a | 1215 | */ |
604c5174 | 1216 | var Utilityview = function (name) { |
c6ef62a3 JA |
1217 | var rand_name = randomString(15), |
1218 | tmp_divname = 'kiwi_window_' + rand_name, | |
c6ef62a3 | 1219 | tmp_tabname = 'kiwi_tab_' + rand_name; |
8343584e | 1220 | |
604c5174 D |
1221 | this.name = rand_name; |
1222 | this.title = name; | |
1223 | this.topic = ' '; | |
4e4ca8e6 | 1224 | this.panel = $('#panel1'); |
1bb74900 | 1225 | |
4e4ca8e6 D |
1226 | if (typeof $('.scroller', this.panel)[0] === 'undefined') { |
1227 | this.panel.append('<div id="' + tmp_divname + '" class="messages"></div>'); | |
1228 | } else { | |
1229 | $('.scroller', this.panel).append('<div id="' + tmp_divname + '" class="messages"></div>'); | |
1230 | } | |
604c5174 D |
1231 | |
1232 | this.tab = $('<li id="' + tmp_tabname + '">' + this.title + '</li>'); | |
c6ef62a3 | 1233 | this.tab.click(function () { |
673a7c8f | 1234 | kiwi.front.utilityviews[rand_name.toLowerCase()].show(); |
604c5174 D |
1235 | }); |
1236 | $('#kiwi .utilityviewlist ul').append(this.tab); | |
b41a381f | 1237 | kiwi.front.ui.doLayoutSize(); |
8343584e | 1238 | |
1bb74900 D |
1239 | this.div = $('#' + tmp_divname); |
1240 | this.div.css('overflow', 'hidden'); | |
1241 | ||
673a7c8f | 1242 | kiwi.front.utilityviews[rand_name.toLowerCase()] = this; |
1bb74900 D |
1243 | }; |
1244 | ||
1245 | Utilityview.prototype.name = null; | |
604c5174 | 1246 | Utilityview.prototype.title = null; |
1bb74900 D |
1247 | Utilityview.prototype.div = null; |
1248 | Utilityview.prototype.tab = null; | |
ca7e63ea | 1249 | Utilityview.prototype.topic = ' '; |
4e4ca8e6 | 1250 | Utilityview.prototype.panel = null; |
943caaef JA |
1251 | /** |
1252 | * Brings this view to the foreground | |
1253 | */ | |
1bb74900 | 1254 | Utilityview.prototype.show = function () { |
4e4ca8e6 | 1255 | $('.messages', this.panel).removeClass("active"); |
1bb74900 | 1256 | $('#kiwi .userlist ul').removeClass("active"); |
2b9dcc03 | 1257 | $('#kiwi .toolbars ul li').removeClass("active"); |
1bb74900 | 1258 | |
4e4ca8e6 | 1259 | this.panel.css('overflow-y', 'hidden'); |
2b9dcc03 | 1260 | $('#windows').css('right', 0); |
1bb74900 D |
1261 | // Activate this tab! |
1262 | this.div.addClass('active'); | |
1263 | this.tab.addClass('active'); | |
1264 | ||
1265 | this.addPartImage(); | |
1266 | ||
b41a381f | 1267 | kiwi.front.ui.setTopicText(this.topic); |
673a7c8f | 1268 | kiwi.front.cur_channel = this; |
1bb74900 D |
1269 | |
1270 | // If we're using fancy scrolling, refresh it | |
1271 | if (touch_scroll) { | |
1272 | touch_scroll.refresh(); | |
1273 | } | |
c6ef62a3 | 1274 | }; |
943caaef JA |
1275 | /** |
1276 | * Sets a new panel to be this view's parent | |
1277 | * @param {JQuery} new_panel The new parent | |
1278 | */ | |
4e4ca8e6 D |
1279 | Utilityview.prototype.setPanel = function (new_panel) { |
1280 | this.div.detach(); | |
1281 | this.panel = new_panel; | |
1282 | this.panel.append(this.div); | |
1283 | this.show(); | |
1284 | }; | |
943caaef JA |
1285 | /** |
1286 | * Removes the panel from the UI and destroys its contents | |
1287 | */ | |
1bb74900 D |
1288 | Utilityview.prototype.close = function () { |
1289 | this.div.remove(); | |
1290 | this.tab.remove(); | |
8343584e | 1291 | |
1fce4b40 | 1292 | if (Tabview.getCurrentTab() === this) { |
673a7c8f | 1293 | kiwi.front.tabviews.server.show(); |
1bb74900 | 1294 | } |
673a7c8f | 1295 | delete kiwi.front.utilityviews[this.name.toLowerCase()]; |
1bb74900 | 1296 | }; |
943caaef JA |
1297 | /** |
1298 | * Adds the close image to the tab | |
1299 | */ | |
1bb74900 D |
1300 | Utilityview.prototype.addPartImage = function () { |
1301 | this.clearPartImage(); | |
8343584e | 1302 | |
1bb74900 D |
1303 | // We can't close this tab, so don't have the close image |
1304 | if (this.name === 'server') { | |
1305 | return; | |
1306 | } | |
1307 | ||
8397d902 | 1308 | var del_html = '<img src="/img/redcross.png" class="tab_part" />'; |
1bb74900 | 1309 | this.tab.append(del_html); |
8343584e | 1310 | |
1bb74900 | 1311 | $('.tab_part', this.tab).click(function () { |
1fce4b40 JA |
1312 | if (Tabview.getCurrentTab().name !== 'server') { |
1313 | Tabview.getCurrentTab().close(); | |
1bb74900 D |
1314 | } |
1315 | }); | |
1316 | }; | |
943caaef JA |
1317 | /** |
1318 | * Removes the close image from the tab | |
1319 | */ | |
1bb74900 | 1320 | Utilityview.prototype.clearPartImage = function () { |
2b9dcc03 | 1321 | $('#kiwi .toolbars .tab_part').remove(); |
1bb74900 D |
1322 | }; |
1323 | ||
1324 | ||
1325 | ||
1326 | ||
54f4a22e D |
1327 | |
1328 | /* | |
1329 | * | |
1330 | * TABVIEWS | |
1331 | * | |
1332 | */ | |
1333 | ||
5a29866a JA |
1334 | /** |
1335 | * @constructor | |
943caaef JA |
1336 | * A tab to show a channel or query window |
1337 | * @param {String} v_name The window's target's name (i.e. channel name or nickname) | |
5a29866a | 1338 | */ |
0f439a3b D |
1339 | var Tabview = function (v_name) { |
1340 | /*global Tabview, UserList */ | |
3586a76e | 1341 | var re, htmlsafe_name, tmp_divname, tmp_userlistname, tmp_tabname, tmp_tab, userlist_enabled = true; |
0a202119 D |
1342 | |
1343 | if (v_name.charAt(0) === kiwi.gateway.channel_prefix) { | |
0b399cb0 | 1344 | htmlsafe_name = 'chan_' + randomString(15); |
0f439a3b | 1345 | } else { |
0b399cb0 | 1346 | htmlsafe_name = 'query_' + randomString(15); |
0f439a3b D |
1347 | userlist_enabled = false; |
1348 | } | |
1349 | ||
1350 | tmp_divname = 'kiwi_window_' + htmlsafe_name; | |
1351 | tmp_userlistname = 'kiwi_userlist_' + htmlsafe_name; | |
1352 | tmp_tabname = 'kiwi_tab_' + htmlsafe_name; | |
1353 | ||
1fce4b40 | 1354 | if (!Tabview.tabExists(v_name)) { |
0b399cb0 | 1355 | // Create the window |
0f439a3b | 1356 | $('#kiwi .windows .scroller').append('<div id="' + tmp_divname + '" class="messages"></div>'); |
0b399cb0 | 1357 | |
c32b30d6 | 1358 | // Create the window tab |
f7a9a13c | 1359 | |
0b399cb0 D |
1360 | tmp_tab = $('<li id="' + tmp_tabname + '"><span></span></li>'); |
1361 | $('span', tmp_tab).text(v_name); | |
3586a76e D |
1362 | $('#kiwi .windowlist ul').append(tmp_tab); |
1363 | tmp_tab.click(function (e) { | |
1fce4b40 JA |
1364 | var tab = Tabview.getTab(v_name); |
1365 | if (tab) { | |
1366 | tab.show(); | |
1367 | } | |
1368 | }); | |
c32b30d6 D |
1369 | |
1370 | kiwi.front.sortWindowList(); | |
0f439a3b | 1371 | } |
0f439a3b | 1372 | |
0a202119 | 1373 | kiwi.front.tabviews[v_name.toLowerCase()] = this; |
0f439a3b D |
1374 | this.name = v_name; |
1375 | this.div = $('#' + tmp_divname); | |
1376 | this.userlist = new UserList(htmlsafe_name); | |
1377 | this.tab = $('#' + tmp_tabname); | |
4e4ca8e6 | 1378 | this.panel = $('#panel1'); |
0f439a3b D |
1379 | |
1380 | if (!userlist_enabled) { | |
1381 | this.userlist.setWidth(0); | |
1382 | } | |
1383 | this.show(); | |
1384 | ||
1385 | if (typeof registerTouches === "function") { | |
1386 | //alert("Registering touch interface"); | |
1387 | //registerTouches($('#'+tmp_divname)); | |
1388 | registerTouches(document.getElementById(tmp_divname)); | |
1389 | } | |
1390 | ||
b41a381f | 1391 | kiwi.front.ui.doLayoutSize(); |
4e4ca8e6 | 1392 | }; |
a3364605 JA |
1393 | Tabview.prototype.name = null; |
1394 | Tabview.prototype.div = null; | |
1395 | Tabview.prototype.userlist = null; | |
1396 | Tabview.prototype.tab = null; | |
1397 | Tabview.prototype.topic = ""; | |
1398 | Tabview.prototype.safe_to_close = false; // If we have been kicked/banned/etc from this channel, don't wait for a part message | |
4e4ca8e6 | 1399 | Tabview.prototype.panel = null; |
182e307e | 1400 | Tabview.prototype.msg_count = 0; |
943caaef JA |
1401 | /** |
1402 | * Brings this view to the foreground | |
1403 | */ | |
a3364605 | 1404 | Tabview.prototype.show = function () { |
875d0c71 D |
1405 | var w, u; |
1406 | ||
4e4ca8e6 | 1407 | $('.messages', this.panel).removeClass("active"); |
a3364605 | 1408 | $('#kiwi .userlist ul').removeClass("active"); |
2b9dcc03 | 1409 | $('#kiwi .toolbars ul li').removeClass("active"); |
8343584e | 1410 | |
875d0c71 D |
1411 | w = $('#windows'); |
1412 | u = $('#kiwi .userlist'); | |
1413 | ||
8536a327 | 1414 | this.panel.css('overflow-y', 'scroll'); |
875d0c71 D |
1415 | |
1416 | // Set the window size accordingly | |
7779d29a D |
1417 | if (this.userlist.width > 0) { |
1418 | this.userlist.setWidth(); | |
1419 | w.css('right', u.outerWidth(true)); | |
8343584e | 1420 | this.userlist.active(true); |
b10afa2d D |
1421 | // Enable the userlist resizer |
1422 | $('#nicklist_resize').css('display', 'block'); | |
1423 | } else { | |
7779d29a | 1424 | w.css('right', 0); |
b10afa2d D |
1425 | // Disable the userlist resizer |
1426 | $('#nicklist_resize').css('display', 'none'); | |
c6ef62a3 | 1427 | } |
7779d29a D |
1428 | |
1429 | this.div.addClass('active'); | |
a3364605 | 1430 | this.tab.addClass('active'); |
8343584e | 1431 | |
a3364605 JA |
1432 | // Add the part image to the tab |
1433 | this.addPartImage(); | |
8343584e | 1434 | |
a3364605 | 1435 | this.clearHighlight(); |
b41a381f | 1436 | kiwi.front.ui.setTopicText(this.topic); |
673a7c8f | 1437 | kiwi.front.cur_channel = this; |
8343584e | 1438 | |
a3364605 JA |
1439 | // If we're using fancy scrolling, refresh it |
1440 | if (touch_scroll) { | |
1441 | touch_scroll.refresh(); | |
1442 | } | |
1443 | ||
1444 | this.scrollBottom(); | |
1445 | if (!touchscreen) { | |
1446 | $('#kiwi_msginput').focus(); | |
1447 | } | |
1448 | }; | |
943caaef JA |
1449 | /** |
1450 | * Removes the panel from the UI and destroys its contents | |
1451 | */ | |
a3364605 JA |
1452 | Tabview.prototype.close = function () { |
1453 | this.div.remove(); | |
1454 | this.userlist.remove(); | |
8343584e | 1455 | this.userlist = null; |
a3364605 | 1456 | this.tab.remove(); |
8343584e | 1457 | |
673a7c8f D |
1458 | if (kiwi.front.cur_channel === this) { |
1459 | kiwi.front.tabviews.server.show(); | |
a3364605 | 1460 | } |
673a7c8f | 1461 | delete kiwi.front.tabviews[this.name.toLowerCase()]; |
a3364605 | 1462 | }; |
943caaef JA |
1463 | /** |
1464 | * Adds the close image to the tab | |
1465 | */ | |
a3364605 JA |
1466 | Tabview.prototype.addPartImage = function () { |
1467 | this.clearPartImage(); | |
8343584e | 1468 | |
a3364605 JA |
1469 | // We can't close this tab, so don't have the close image |
1470 | if (this.name === 'server') { | |
1471 | return; | |
1472 | } | |
1473 | ||
8397d902 | 1474 | var del_html = '<img src="/img/redcross.png" class="tab_part" />'; |
a3364605 | 1475 | this.tab.append(del_html); |
8343584e | 1476 | |
a3364605 | 1477 | $('.tab_part', this.tab).click(function () { |
673a7c8f D |
1478 | if (kiwi.front.isChannel($(this).parent().text())) { |
1479 | kiwi.front.run("/part"); | |
a3364605 JA |
1480 | } else { |
1481 | // Make sure we don't close the server tab | |
673a7c8f D |
1482 | if (kiwi.front.cur_channel.name !== 'server') { |
1483 | kiwi.front.cur_channel.close(); | |
a3364605 JA |
1484 | } |
1485 | } | |
1486 | }); | |
1487 | }; | |
943caaef JA |
1488 | /** |
1489 | * Removes the close image from the tab | |
1490 | */ | |
a3364605 | 1491 | Tabview.prototype.clearPartImage = function () { |
2b9dcc03 | 1492 | $('#kiwi .toolbars .tab_part').remove(); |
a3364605 | 1493 | }; |
943caaef JA |
1494 | /** |
1495 | * Sets the tab's icon | |
1496 | * @param {String} url The URL of the icon to display | |
1497 | */ | |
3586a76e D |
1498 | Tabview.prototype.setIcon = function (url) { |
1499 | this.tab.prepend('<img src="' + url + '" class="icon" />'); | |
1500 | this.tab.css('padding-left', '33px'); | |
7af36ece | 1501 | }; |
943caaef JA |
1502 | /** |
1503 | * Sets the tab's label | |
1504 | */ | |
3586a76e D |
1505 | Tabview.prototype.setTabText = function (text) { |
1506 | $('span', this.tab).text(text); | |
7af36ece | 1507 | }; |
943caaef JA |
1508 | /** |
1509 | * Adds a message to the window. | |
1510 | * This method will automatically format the message (bold, underline, colours etc.) | |
1511 | * @param {Date} time The timestamp of the message. May be null. | |
1512 | * @param {String} nick The origin of the message | |
1513 | * @param {String} msg The message to display | |
1514 | * @param {String} type The CSS class to assign to the whole message line | |
1515 | * @param {String} style Extra CSS commands to apply just to the msg | |
1516 | */ | |
a3364605 | 1517 | Tabview.prototype.addMsg = function (time, nick, msg, type, style) { |
8343584e D |
1518 | var self, tmp, d, re, line_msg; |
1519 | ||
a3364605 | 1520 | self = this; |
8343584e | 1521 | |
ca7e63ea | 1522 | tmp = {msg: msg, time: time, nick: nick, tabview: this.name}; |
673a7c8f | 1523 | tmp = kiwi.plugs.run('addmsg', tmp); |
c6ef62a3 JA |
1524 | if (!tmp) { |
1525 | return; | |
1526 | } | |
8343584e | 1527 | |
ca7e63ea D |
1528 | |
1529 | msg = tmp.msg; | |
1530 | time = tmp.time; | |
1531 | nick = tmp.nick; | |
1532 | ||
a3364605 JA |
1533 | if (time === null) { |
1534 | d = new Date(); | |
1535 | time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0"); | |
1536 | } | |
8343584e | 1537 | |
a3364605 JA |
1538 | // The CSS class (action, topic, notice, etc) |
1539 | if (typeof type !== "string") { | |
1540 | type = ''; | |
1541 | } | |
8343584e | 1542 | |
a3364605 JA |
1543 | // Make sure we don't have NaN or something |
1544 | if (typeof msg !== "string") { | |
1545 | msg = ''; | |
1546 | } | |
8343584e | 1547 | |
ca7e63ea | 1548 | // Make the channels clickable |
673a7c8f | 1549 | re = new RegExp('\\B(' + kiwi.gateway.channel_prefix + '[^ ,.\\007]+)', 'g'); |
a3364605 | 1550 | msg = msg.replace(re, function (match) { |
ca7e63ea | 1551 | return '<a class="chan">' + match + '</a>'; |
9545f343 JA |
1552 | }); |
1553 | ||
0a202119 | 1554 | msg = kiwi.front.formatIRCMsg(msg); |
8343584e | 1555 | |
ca7e63ea D |
1556 | // Build up and add the line |
1557 | line_msg = $('<div class="msg ' + type + '"><div class="time">' + time + '</div><div class="nick">' + nick + '</div><div class="text" style="' + style + '">' + msg + ' </div></div>'); | |
a3364605 JA |
1558 | this.div.append(line_msg); |
1559 | ||
182e307e D |
1560 | this.msg_count++; |
1561 | if (this.msg_count > 250) { | |
1562 | $('.msg:first', this.div).remove(); | |
1563 | this.msg_count--; | |
1564 | } | |
1565 | ||
a3364605 JA |
1566 | if (!touchscreen) { |
1567 | this.scrollBottom(); | |
1568 | } else { | |
1569 | touch_scroll.refresh(); | |
1570 | //console.log(this.div.attr("scrollHeight") +" - "+ $('#windows').height()); | |
1571 | this.scrollBottom(); | |
1572 | //if(this.div.attr("scrollHeight") > $('#windows').height()){ | |
1573 | // touch_scroll.scrollTo(0, this.div.height()); | |
1574 | //} | |
1575 | } | |
1576 | }; | |
943caaef JA |
1577 | /** |
1578 | * Scroll to the bottom of the window | |
1579 | */ | |
a3364605 | 1580 | Tabview.prototype.scrollBottom = function () { |
4e4ca8e6 | 1581 | var panel = this.panel; |
4e4ca8e6 | 1582 | panel[0].scrollTop = panel[0].scrollHeight; |
a3364605 | 1583 | }; |
943caaef JA |
1584 | /** |
1585 | * Change a user's nick on the channel | |
1586 | * @param {String} newNick The new nick | |
1587 | * @param {String} oldNick The old nick | |
1588 | */ | |
a3364605 | 1589 | Tabview.prototype.changeNick = function (newNick, oldNick) { |
8343584e D |
1590 | var inChan = this.userlist.hasUser(oldNick); |
1591 | if (inChan) { | |
1592 | this.userlist.renameUser(oldNick, newNick); | |
673a7c8f | 1593 | this.addMsg(null, ' ', '=== ' + oldNick + ' is now known as ' + newNick, 'action changenick'); |
a3364605 JA |
1594 | } |
1595 | }; | |
943caaef JA |
1596 | /** |
1597 | * Highlight the tab | |
1598 | */ | |
a3364605 JA |
1599 | Tabview.prototype.highlight = function () { |
1600 | this.tab.addClass('highlight'); | |
1601 | }; | |
943caaef JA |
1602 | /** |
1603 | * Indicate activity on the tab | |
1604 | */ | |
a3364605 JA |
1605 | Tabview.prototype.activity = function () { |
1606 | this.tab.addClass('activity'); | |
1607 | }; | |
943caaef JA |
1608 | /** |
1609 | * Clear the tab's highlight | |
1610 | */ | |
a3364605 JA |
1611 | Tabview.prototype.clearHighlight = function () { |
1612 | this.tab.removeClass('highlight'); | |
1613 | this.tab.removeClass('activity'); | |
1614 | }; | |
943caaef JA |
1615 | /** |
1616 | * Change the channel's topic | |
1617 | * @param {String} new_topic The new channel topic | |
1618 | */ | |
a3364605 JA |
1619 | Tabview.prototype.changeTopic = function (new_topic) { |
1620 | this.topic = new_topic; | |
1621 | this.addMsg(null, ' ', '=== Topic for ' + this.name + ' is: ' + new_topic, 'topic'); | |
673a7c8f | 1622 | if (kiwi.front.cur_channel.name === this.name) { |
b41a381f | 1623 | kiwi.front.ui.setTopicText(new_topic); |
a3364605 JA |
1624 | } |
1625 | }; | |
1fce4b40 | 1626 | // Static functions |
943caaef JA |
1627 | /** |
1628 | * Checks to see if a tab by the given name exists | |
1629 | * @param {String} name The name to check | |
1630 | * @returns {Boolean} True if the tab exists, false otherwise | |
1631 | */ | |
1fce4b40 | 1632 | Tabview.tabExists = function (name) { |
0b399cb0 | 1633 | return (Tabview.getTab(name) !== null); |
1fce4b40 | 1634 | }; |
943caaef JA |
1635 | /** |
1636 | * Returns the tab which has the given name | |
1637 | * @param {String} name The name of the tab to return | |
1638 | * @returns {Tabview} The Tabview with the given name, or null if it does not exist | |
1639 | */ | |
1fce4b40 | 1640 | Tabview.getTab = function (name) { |
0b399cb0 D |
1641 | var tab; |
1642 | ||
1643 | // Make sure we actually have a name | |
f93aafe5 JA |
1644 | if (typeof name !== 'string') { |
1645 | return null; | |
1646 | } | |
0b399cb0 D |
1647 | |
1648 | // Go through each tabview and pick out the matching one | |
1649 | $.each(kiwi.front.tabviews, function (i, item) { | |
f93aafe5 | 1650 | if (item.name.toLowerCase() === name.toLowerCase()) { |
0b399cb0 D |
1651 | tab = item; |
1652 | return false; | |
1653 | } | |
1654 | }); | |
1655 | ||
1656 | // If we we didn't find one, return null instead | |
1657 | tab = tab || null; | |
1658 | ||
1659 | return tab; | |
1fce4b40 | 1660 | }; |
943caaef JA |
1661 | /** |
1662 | * Returns the tab that corresponds to the server | |
1663 | * @retruns {Tabview} The server Tabview | |
1664 | */ | |
1fce4b40 | 1665 | Tabview.getServerTab = function () { |
0b399cb0 | 1666 | return Tabview.getTab('server'); |
1fce4b40 | 1667 | }; |
943caaef JA |
1668 | /** |
1669 | * Returns all tabs | |
1670 | * @returns {Array} All of the tabs | |
1671 | */ | |
1fce4b40 JA |
1672 | Tabview.getAllTabs = function () { |
1673 | return kiwi.front.tabviews; | |
1674 | }; | |
943caaef JA |
1675 | /** |
1676 | * Returns the tab that's currently showing | |
1677 | * @returns {Tabview} The tab that's currently showing | |
1678 | */ | |
1fce4b40 JA |
1679 | Tabview.getCurrentTab = function () { |
1680 | return kiwi.front.cur_channel; | |
1681 | }; | |
a3364605 | 1682 | |
b41a381f D |
1683 | |
1684 | ||
1685 | ||
1686 | ||
1687 | ||
5a29866a JA |
1688 | /** |
1689 | * @constructor | |
943caaef JA |
1690 | * Floating message box |
1691 | * @param {String} classname The CSS classname to apply to the box | |
5a29866a | 1692 | */ |
a3364605 JA |
1693 | var Box = function (classname) { |
1694 | this.id = randomString(10); | |
1695 | var tmp = $('<div id="' + this.id + '" class="box ' + classname + '"><div class="boxarea"></div></div>'); | |
1696 | $('#kiwi').append(tmp); | |
1697 | this.box = $('#' + this.id); | |
1698 | this.content = $('#' + this.id + ' .boxarea'); | |
8343584e | 1699 | |
a3364605 JA |
1700 | this.box.draggable({ stack: ".box" }); |
1701 | this.content.click(function () {}); | |
1702 | //this.box.click(function(){ $(this)..css }); | |
1703 | }; | |
1704 | Box.prototype.create = function (name, classname) { | |
8343584e | 1705 | |
a3364605 JA |
1706 | }; |
1707 | Box.prototype.id = null; | |
1708 | Box.prototype.box = null; | |
1709 | Box.prototype.content = null; | |
1710 | Box.prototype.destroy = function () { | |
1711 | var name; | |
1712 | this.box.remove(); | |
673a7c8f D |
1713 | for (name in kiwi.front.boxes) { |
1714 | if (kiwi.front.boxes[name].id === this.id) { | |
1715 | delete kiwi.front.boxes[name]; | |
a3364605 JA |
1716 | } |
1717 | } | |
1718 | }; | |
8343584e | 1719 | Box.prototype.height = function () { |
a3364605 JA |
1720 | return this.box.height(); |
1721 | }; |