Userlist disabling for server tab and query windows
[KiwiIRC.git] / js / front.js
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*/
3 var front = {
4 revision: 38,
5
6 cur_channel: '',
7 windows: {},
8 tabviews: {},
9 boxes: {},
10
11 buffer: [],
12 buffer_pos: 0,
13
14 original_topic: '',
15
16 init: function () {
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;
20
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("onconnect_fail", front.onConnectFail);
28 $(gateway).bind("ondisconnect", front.onDisconnect);
29 $(gateway).bind("onnick", front.onNick);
30 $(gateway).bind("onuserlist", front.onUserList);
31 $(gateway).bind("onuserlist_end", front.onUserListEnd);
32 $(gateway).bind("onjoin", front.onJoin);
33 $(gateway).bind("ontopic", front.onTopic);
34 $(gateway).bind("onpart", front.onPart);
35 $(gateway).bind("onkick", front.onKick);
36 $(gateway).bind("onquit", front.onQuit);
37 $(gateway).bind("onwhois", front.onWhois);
38 $(gateway).bind("onsync", front.onSync);
39 $(gateway).bind("onchannel_redirect", front.onChannelRedirect);
40 $(gateway).bind("ondebug", front.onDebug);
41 $(gateway).bind("onctcp_request", front.onCTCPRequest);
42 $(gateway).bind("onctcp_response", front.onCTCPResponse);
43 $(gateway).bind("onirc_error", front.onIRCError);
44
45 this.buffer = [];
46
47 // Build the about box
48 front.boxes.about = new Box("about");
49 about_info = 'UI adapted for ' + agent;
50 if (touchscreen) {
51 about_info += ' touchscreen ';
52 }
53 about_info += 'usage';
54 $('#tmpl_about_box').tmpl({
55 about: about_info,
56 front_revision: front.revision,
57 gateway_revision: gateway.revision
58 }).appendTo(front.boxes.about.content);
59
60 //$(window).bind("beforeunload", function(){ gateway.quit(); });
61
62 if (touchscreen) {
63 $('#kiwi').addClass('touchscreen');
64
65 // Single touch scrolling through scrollback for touchscreens
66 scroll_opts = {};
67 touch_scroll = new iScroll('windows', scroll_opts);
68 }
69
70 front.registerKeys();
71
72 $('#kiwi .cur_topic').resize(front.doLayoutSize);
73
74 $('#kiwi .formconnectwindow').submit(function () {
75 var netsel = $('#kiwi .formconnectwindow .network'),
76 nick = $('#kiwi .formconnectwindow .nick'),
77 tmp;
78
79 if (nick.val() === '') {
80 nick.val('Nick please!');
81 nick.focus();
82 return false;
83 }
84
85 tmp = nick.val().split(' ');
86 gateway.nick = tmp[0];
87
88 init_data.channel = $('#channel').val();
89
90 front.doLayout();
91 try {
92 front.run('/connect ' + netsel.val());
93 } catch (e) {
94 alert(e);
95 }
96
97 $('#kiwi .connectwindow').slideUp();
98 $('#windows').click(function () { $('#kiwi_msginput').focus(); });
99
100 return false;
101 });
102
103 supportsOrientationChange = (typeof window.onorientationchange !== undefined);
104 orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
105 if (window.addEventListener) {
106 window.addEventListener(orientationEvent, front.doLayoutSize, false);
107 } else {
108 // < IE9
109 window.attachEvent(orientationEvent, front.doLayoutSize, false);
110 }
111 //$('#kiwi').bind("resize", front.doLayoutSize, false);
112
113 front.doLayout();
114
115 front.tabviewAdd('server');
116 front.tabviews.server.userlist_width = 0; // Disable the userlist
117
118 // Any pre-defined nick?
119 if (typeof window.init_data.nick === "string") {
120 $('#kiwi .formconnectwindow .nick').val(init_data.nick);
121 }
122
123 // Any pre-defined channels?
124 if (typeof window.init_data.channel === 'string') {
125 $('#channel').val(init_data.channel);
126 }
127
128
129 $('#kiwi .cur_topic').keydown(function (e) {
130 if (e.which === 13) {
131 // enter
132 e.preventDefault();
133 $(this).change();
134 $('#kiwi_msginput').focus();
135 } else if (e.which === 27) {
136 // escape
137 e.preventDefault();
138 $(this).text(front.original_topic);
139 $('#kiwi_msginput').focus();
140 }
141 });
142 /*$('.cur_topic').live('keypress', function(e) {
143 if (e.keyCode === 13) {
144 // enter
145 e.preventDefault();
146 $(this).change();
147 $('#kiwi_msginput').focus();
148 } else if (e.keyCode === 27) {
149 // escape
150 e.preventDefault();
151 $(this).text(front.original_topic);
152 }
153 });*/
154 $('.cur_topic').live('change', function () {
155 var chan, text;
156 text = $(this).text();
157 if (text !== front.original_topic) {
158 chan = front.cur_channel.name;
159 gateway.setTopic(chan, text);
160 }
161 });
162
163
164 $('#windows a.chan').live('click', function() {
165 front.joinChannel($(this).text());
166 return false;
167 });
168
169 $('#windows a.link_ext').live('mouseover', function () {
170 var a = $(this);
171 var tt = $('.tt', a);
172
173 if (tt.text() === '') {
174 var tooltip = $('<a class="link_ext_browser">Open in Kiwi..</a>');
175 tt.append(tooltip);
176 }
177
178 tt.css('top', -tt.outerHeight()+'px');
179 tt.css('left', (a.outerWidth() / 2) - (tt.outerWidth() / 2));
180 });
181 $('#windows a.link_ext').live('mouseout', function () {
182 var a = $(this);
183 var tt = $('.tt', a);
184 });
185 $('#windows a.link_ext').live('click', function (e) {
186 var a = $(this);
187
188 switch (e.target.className) {
189 case 'link_ext':
190 case 'link_img_a':
191 return true;
192 break;
193 case 'link_ext_browser':
194 var t = new Utilityview('Browser', a.attr('href'));
195 t.show();
196 break;
197 }
198 return false;
199 });
200
201 },
202
203 doLayoutSize: function () {
204 var kiwi, toolbars, ul, n_top, n_bottom;
205 kiwi = $('#kiwi');
206
207 if (kiwi.width() < 330 && !kiwi.hasClass('small_kiwi')) {
208 console.log("switching to small kiwi");
209 kiwi.removeClass('large_kiwi');
210 kiwi.addClass('small_kiwi');
211 } else if (kiwi.width() >= 330 && !kiwi.hasClass('large_kiwi')) {
212 kiwi.removeClass('small_kiwi');
213 kiwi.addClass('large_kiwi');
214 }
215
216 toolbars = $('#kiwi .cur_topic');
217 ul = $('#kiwi .userlist');
218
219 n_top = parseInt(toolbars.offset().top, 10) + parseInt(toolbars.outerHeight(true), 10);
220 n_bottom = $(document).height() - parseInt($('#kiwi .control').offset().top, 10);
221
222 $('#kiwi .windows').css({top: n_top + 'px', bottom: n_bottom + 'px'});
223 $('#kiwi .userlist').css({top: n_top + 'px', bottom: n_bottom + 'px'});
224 },
225
226
227 doLayout: function () {
228 $('#kiwi .msginput .nick a').text(gateway.nick);
229 $('#kiwi_msginput').val(' ');
230 $('#kiwi_msginput').focus();
231 },
232
233
234 joinChannel: function (chan_name) {
235 var chans = chan_name.split(','),
236 i;
237 for (i in chans) {
238 chan = chans[i];
239 if (front.tabviews[chan.toLowerCase()] === undefined || (front.tabviews[chan.toLowerCase()] !== undefined && front.tabviews[chan.toLowerCase()].safe_to_close === true)) {
240 gateway.join(chan);
241 front.tabviewAdd(chan);
242 } else {
243 front.tabviews[chan.toLowerCase()].show();
244 }
245 }
246 },
247
248
249 run: function (msg) {
250 var parts, dest, t, pos, textRange, d, plugin_event;
251
252 // Run through any plugins
253 plugin_event = {command: msg};
254 plugin_event = plugs.run('command_run', plugin_event);
255 if (!plugin_event || typeof plugin_event.command === 'undefined') return;
256
257 // Update msg if it's been changed by any plugins
258 msg = plugin_event.command.toString();
259
260 console.log("running " + msg);
261 if (msg.substring(0, 1) === '/') {
262 parts = msg.split(' ');
263 switch (parts[0].toLowerCase()) {
264 case '/j':
265 case '/join':
266 front.joinChannel(parts[1]);
267 break;
268
269 case '/connect':
270 case '/server':
271 if (parts[1] === undefined) {
272 alert('Usage: /connect servername [port]');
273 break;
274 }
275
276 if (parts[2] === undefined) {
277 parts[2] = 6667;
278 }
279 front.cur_channel.addMsg(null, ' ', '=== Connecting to ' + parts[1] + '...', 'status');
280 gateway.connect(parts[1], parts[2], 0);
281 break;
282
283 case '/nick':
284 console.log("/nick");
285 if (parts[1] === undefined) {
286 console.log("calling show nick");
287 front.showChangeNick();
288 } else {
289 console.log("sending raw");
290 gateway.raw(msg.substring(1));
291 }
292 break;
293
294 case '/part':
295 if (typeof parts[1] === "undefined") {
296 if (front.cur_channel.safe_to_close) {
297 front.cur_channel.close();
298 } else {
299 gateway.raw(msg.substring(1) + ' ' + front.cur_channel.name);
300 }
301 } else {
302 gateway.raw(msg.substring(1));
303 }
304 break;
305
306 case '/names':
307 if (typeof parts[1] !== "undefined") {
308 gateway.raw(msg.substring(1));
309 }
310 break;
311
312 case '/debug':
313 gateway.debug();
314 break;
315
316 case '/q':
317 case '/query':
318 if (typeof parts[1] !== "undefined") {
319 front.tabviewAdd(parts[1]);
320 }
321 break;
322
323
324 case '/m':
325 case '/msg':
326 if (typeof parts[1] !== "undefined") {
327 var msg_sliced = msg.split(' ').slice(2).join(' ');
328 gateway.msg(parts[1], msg_sliced);
329
330 if (!front.tabviewExists(parts[1])) {
331 front.tabviewAdd(parts[1]);
332 }
333 front.tabviews[parts[1].toLowerCase()].addMsg(null, gateway.nick, msg_sliced);
334 }
335 break;
336
337
338 case '/quote':
339 gateway.raw(msg.replace(/^\/quote /i, ''));
340 break;
341
342 case '/me':
343 gateway.action(front.cur_channel.name, msg.substring(4));
344 //front.tabviews[destination.toLowerCase()].addMsg(null, ' ', '* '+data.nick+' '+data.msg, 'color:green;');
345 front.cur_channel.addMsg(null, ' ', '* ' + gateway.nick + ' ' + msg.substring(4), 'action', 'color:#555;');
346 break;
347
348 case '/notice':
349 dest = parts[1];
350 msg = parts.slice(2).join(' ');
351
352 gateway.notice(dest, msg);
353 this.onNotice({}, {nick: gateway.nick, channel: dest, msg: msg});
354 break;
355
356 case '/win':
357 if (parts[1] !== undefined) {
358 front.windowsShow(parseInt(parts[1], 10));
359 }
360 break;
361
362 case '/quit':
363 gateway.quit(msg.split(" ", 2)[1]);
364 break;
365
366 case '/topic':
367 if (parts[1] === undefined) {
368 t = $('.cur_topic');
369 if (t.createTextRange) {
370 pos = t.text().length();
371 textRange = t.createTextRange();
372 textRange.collapse(true);
373 textRange.moveEnd(pos);
374 textRange.moveStart(pos);
375 textRange.select();
376 } else if (t.setSelectionRange) {
377 t.setSelectionRange(pos, pos);
378 }
379 } else {
380 gateway.setTopic(front.cur_channel.name, msg.split(' ', 2)[1]);
381 //gateway.raw('TOPIC ' + front.cur_channel.name + ' :' + msg.split(' ', 2)[1]);
382 }
383 break;
384 default:
385 //front.cur_channel.addMsg(null, ' ', '--> Invalid command: '+parts[0].substring(1));
386 gateway.raw(msg.substring(1));
387 }
388
389 } else {
390 //alert('Sending message: '+msg);
391 if (msg.trim() === '') {
392 return;
393 }
394 if (front.cur_channel.name !== 'server') {
395 gateway.msg(front.cur_channel.name, msg);
396 d = new Date();
397 d = d.getHours() + ":" + d.getMinutes();
398 //front.addMsg(d, gateway.nick, msg);
399 front.cur_channel.addMsg(null, gateway.nick, msg);
400 }
401 }
402 },
403
404
405 onMsg: function (e, data) {
406 var destination, plugin_event;
407 // Is this message from a user?
408 if (data.channel === gateway.nick) {
409 destination = data.nick.toLowerCase();
410 } else {
411 destination = data.channel.toLowerCase();
412 }
413
414 plugin_event = {nick: data.nick, msg:data.msg, destination: destination};
415 plugin_event = plugs.run('msg_recieved', plugin_event);
416 if (!plugin_event) return;
417
418 if (!front.tabviewExists(plugin_event.destination)) {
419 front.tabviewAdd(plugin_event.destination);
420 }
421 front.tabviews[plugin_event.destination].addMsg(null, plugin_event.nick, plugin_event.msg);
422 },
423
424 onDebug: function (e, data) {
425 if (!front.tabviewExists('kiwi_debug')) {
426 front.tabviewAdd('kiwi_debug');
427 }
428 front.tabviews.kiwi_debug.addMsg(null, ' ', data.msg);
429 },
430
431 onAction: function (e, data) {
432 var destination;
433 // Is this message from a user?
434 if (data.channel === gateway.nick) {
435 destination = data.nick;
436 } else {
437 destination = data.channel;
438 }
439
440 if (!front.tabviewExists(destination)) {
441 front.tabviewAdd(destination);
442 }
443 front.tabviews[destination.toLowerCase()].addMsg(null, ' ', '* ' + data.nick + ' ' + data.msg, 'action', 'color:#555;');
444 },
445
446 onTopic: function (e, data) {
447 if (front.tabviewExists(data.channel)) {
448 front.tabviews[data.channel.toLowerCase()].changeTopic(data.topic);
449 }
450 },
451
452 onNotice: function (e, data) {
453 var nick = (data.nick === undefined) ? '' : data.nick;
454 var enick = '[' + nick + ']';
455
456 if (front.tabviewExists(data.target)) {
457 front.tabviews[data.target.toLowerCase()].addMsg(null, enick, data.msg, 'notice');
458 } else if (front.tabviewExists(nick)) {
459 front.tabviews[nick.toLowerCase()].addMsg(null, enick, data.msg, 'notice');
460 } else {
461 front.tabviews.server.addMsg(null, enick, data.msg, 'notice');
462 }
463 },
464
465 onCTCPRequest: function (e, data) {
466 var msg = data.msg.split(" ", 2);
467 switch (msg[0]) {
468 case 'PING':
469 if (typeof msg[1] === 'undefined') {
470 msg[1] = '';
471 }
472 gateway.notice(data.nick, String.fromCharCode(1) + 'PING ' + msg[1] + String.fromCharCode(1));
473 break;
474 case 'TIME':
475 gateway.notice(data.nick, String.fromCharCode(1) + 'TIME ' + (new Date()).toLocaleString() + String.fromCharCode(1));
476 break;
477 }
478 front.tabviews.server.addMsg(null, 'CTCP [' + data.nick + ']', data.msg, 'ctcp');
479 },
480
481 onCTCPResponse: function (e, data) {
482 },
483
484 onConnect: function (e, data) {
485 if (data.connected) {
486 front.tabviews.server.addMsg(null, ' ', '=== Connected OK :)', 'status');
487 if (typeof init_data.channel === "string") {
488 front.joinChannel(init_data.channel);
489 }
490 plugs.run('connect', {success: true});
491 } else {
492 front.tabviews.server.addMsg(null, ' ', '=== Failed to connect :(', 'status');
493 plugs.run('connect', {success: false});
494 }
495 },
496 onConnectFail: function (e, data) {
497 var reason = (typeof data.reason === 'string') ? data.reason : '';
498 front.tabviews.server.addMsg(null, '', 'There\'s a problem connecting! (' + reason + ')', 'error');
499 plugs.run('connect', {success: false});
500 },
501 onDisconnect: function (e, data) {
502 var tab;
503 for (tab in front.tabviews) {
504 front.tabviews[tab].addMsg(null, '', 'Disconnected from server!', 'error');
505 }
506 plugs.run('disconnect', {success: false});
507 },
508 onOptions: function (e, data) {
509 if (typeof gateway.network_name === "string" && gateway.network_name !== "") {
510 front.tabviews.server.tab.text(gateway.network_name);
511 }
512 },
513 onMOTD: function (e, data) {
514 front.tabviews.server.addMsg(null, data.server, data.msg, 'motd');
515 },
516 onWhois: function (e, data) {
517 var d;
518 if (data.msg) {
519 front.cur_channel.addMsg(null, data.nick, data.msg, 'whois');
520 } else if (data.logon) {
521 d = new Date();
522 d.setTime(data.logon * 1000);
523 d = d.toLocaleString();
524 front.cur_channel.addMsg(null, data.nick, 'idle for ' + data.idle + ' second' + ((data.idle !== 1) ? 's' : '') + ', signed on ' + d, 'whois');
525 } else {
526 front.cur_channel.addMsg(null, data.nick, 'idle for ' + data.idle + ' seconds', 'whois');
527 }
528 },
529 onUserList: function (e, data) {
530 var ul, nick, mode;
531 if (front.tabviews[data.channel.toLowerCase()] === undefined) {
532 return;
533 }
534 ul = front.tabviews[data.channel.toLowerCase()].userlist;
535
536 if (!document.userlist_updating) {
537 document.userlist_updating = true;
538 ul.empty();
539 }
540
541 $.each(data.users, function (i, item) {
542 nick = i; //i.match(/^.+!/g);
543 mode = item;
544 $('<li><a class="nick" onclick="front.userClick(this);">' + mode + nick + '</a></li>').appendTo(ul);
545 });
546
547 front.tabviews[data.channel.toLowerCase()].userlistSort();
548 },
549 onUserListEnd: function (e, data) {
550 document.userlist_updating = false;
551 },
552
553 onJoin: function (e, data) {
554 if (!front.tabviewExists(data.channel)) {
555 front.tabviewAdd(data.channel.toLowerCase());
556 }
557
558 if (data.nick === gateway.nick) {
559 return; // Not needed as it's already in nicklist
560 }
561 front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '--> ' + data.nick + ' has joined', 'action', 'color:#009900;');
562 $('<li><a class="nick" onclick="front.userClick(this);">' + data.nick + '</a></li>').appendTo(front.tabviews[data.channel.toLowerCase()].userlist);
563 front.tabviews[data.channel.toLowerCase()].userlistSort();
564 },
565 onPart: function (e, data) {
566 if (front.tabviewExists(data.channel)) {
567 // If this is us, close the tabview
568 if (data.nick === gateway.nick) {
569 front.tabviews[data.channel.toLowerCase()].close();
570 front.tabviews.server.show();
571 return;
572 }
573
574 front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '<-- ' + data.nick + ' has left (' + data.message + ')', 'action', 'color:#990000;');
575 front.tabviews[data.channel.toLowerCase()].userlist.children().each(function () {
576 if ($(this).text() === data.nick) {
577 $(this).remove();
578 }
579 });
580 }
581 },
582 onKick: function (e, data) {
583 if (front.tabviewExists(data.channel)) {
584 // If this is us, close the tabview
585 if (data.kicked === gateway.nick) {
586 //front.tabviews[data.channel.toLowerCase()].close();
587 front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '=== You have been kicked from ' + data.channel + '. ' + data.message, 'status');
588 front.tabviews[data.channel.toLowerCase()].safe_to_close = true;
589 $('li', front.tabviews[data.channel.toLowerCase()].userlist).remove();
590 return;
591 }
592
593 front.tabviews[data.channel.toLowerCase()].addMsg(null, ' ', '<-- ' + data.kicked + ' kicked by ' + data.nick + '(' + data.message + ')', 'action', 'color:#990000;');
594 front.tabviews[data.channel.toLowerCase()].userlist.children().each(function () {
595 if ($(this).text() === data.nick) {
596 $(this).remove();
597 }
598 });
599 }
600 },
601 onNick: function (e, data) {
602 if (data.nick === gateway.nick) {
603 gateway.nick = data.newnick;
604 front.doLayout();
605 }
606
607 $.each(front.tabviews, function (i, item) {
608 $.each(front.tabviews, function (i, item) {
609 item.changeNick(data.newnick, data.nick);
610 });
611 });
612 },
613 onQuit: function (e, data) {
614 $.each(front.tabviews, function (i, item) {
615 $.each(front.tabviews, function (i, item) {
616 item.userlist.children().each(function () {
617 if ($(this).text() === data.nick) {
618 $(this).remove();
619 item.addMsg(null, ' ', '<-- ' + data.nick + ' has quit (' + data.message + ')', 'action', 'color:#990000;');
620 }
621 });
622 });
623 });
624 },
625 onChannelRedirect: function (e, data) {
626 front.tabviews[data.from.toLowerCase()].close();
627 front.tabviewAdd(data.to.toLowerCase());
628 front.tabviews[data.to.toLowerCase()].addMsg(null, ' ', '=== Redirected from ' + data.from, 'action');
629 },
630
631 onIRCError: function (e, data) {
632 var t_view;
633 if (data.channel !== undefined && front.tabviewExists(data.channel)) {
634 t_view = data.channel;
635 } else {
636 t_view = 'server';
637 }
638
639 switch (data.error) {
640 case 'banned_from_channel':
641 front.tabviews[t_view].addMsg(null, ' ', '=== You are banned from ' + data.channel + '. ' + data.reason, 'status');
642 if (t_view !== 'server') {
643 front.tabviews[t_view].safe_to_close = true;
644 }
645 break;
646 case 'bad_channel_key':
647 front.tabviews[t_view].addMsg(null, ' ', '=== Bad channel key for ' + data.channel, 'status');
648 if (t_view !== 'server') {
649 front.tabviews[t_view].safe_to_close = true;
650 }
651 break;
652 case 'invite_only_channel':
653 front.tabviews[t_view].addMsg(null, ' ', '=== ' + data.channel + ' is invite only.', 'status');
654 if (t_view !== 'server') {
655 front.tabviews[t_view].safe_to_close = true;
656 }
657 break;
658 case 'channel_is_full':
659 front.tabviews[t_view].addMsg(null, ' ', '=== ' + data.channel + ' is full.', 'status');
660 if (t_view !== 'server') {
661 front.tabviews[t_view].safe_to_close = true;
662 }
663 break;
664 case 'chanop_privs_needed':
665 front.tabviews[data.channel].addMsg(null, ' ', '=== ' + data.reason, 'status');
666 break;
667 case 'no_such_nick':
668 front.tabviews.server.addMsg(null, ' ', '=== ' + data.nick + ': ' + data.reason, 'status');
669 break;
670 default:
671 // We don't know what data contains, so don't do anything with it.
672 //front.tabviews.server.addMsg(null, ' ', '=== ' + data, 'status');
673 }
674 },
675
676 registerKeys: function () {
677 $('#kiwi_msginput').bind('keydown', function (e) {
678 var windows, meta, num, msg, data, candidates, word_pos, word;
679 windows = $('#windows');
680 //var meta = e.altKey;
681 meta = e.ctrlKey;
682
683 switch (true) {
684 case (e.which >= 48) && (e.which <= 57):
685 if (meta) {
686 num = e.which - 48;
687 if (num === 0) {
688 num = 10;
689 }
690 num = num - 1;
691 front.windowsShow(num);
692 return false;
693 }
694 break;
695 case e.which === 27: // escape
696 return false;
697 case e.which === 13: // return
698 msg = $('#kiwi_msginput').val();
699 msg = msg.trim();
700
701 front.buffer.push(msg);
702 front.buffer_pos = front.buffer.length;
703
704 front.run(msg);
705 $('#kiwi_msginput').val('');
706
707 break;
708 case e.which === 33: // page up
709 console.log("page up");
710 windows[0].scrollTop = windows[0].scrollTop - windows.height();
711 return false;
712 case e.which === 34: // page down
713 windows[0].scrollTop = windows[0].scrollTop + windows.height();
714 return false;
715 case e.which === 37: // left
716 if (meta) {
717 front.windowsPrevious();
718 return false;
719 }
720 break;
721 case e.which === 38: // up
722 if (front.buffer_pos > 0) {
723 front.buffer_pos--;
724 $('#kiwi_msginput').val(front.buffer[front.buffer_pos]);
725 }
726 break;
727 case e.which === 39: // right
728 if (meta) {
729 front.windowsNext();
730 return false;
731 }
732 break;
733 case e.which === 40: // down
734 if (front.buffer_pos < front.buffer.length) {
735 front.buffer_pos++;
736 $('#kiwi_msginput').val(front.buffer[front.buffer_pos]);
737 }
738 break;
739
740 case e.which === 9: // tab
741 // Get possible autocompletions
742 data = [];
743 front.cur_channel.userlist.children().each(function () {
744 nick = front.nickStripPrefix($('a.nick', this).text());
745 data.push(nick);
746 });
747
748 // Do the autocomplete
749 if (this.value.length === this.selectionStart && this.value.length === this.selectionEnd) {
750 candidates = [];
751
752 word_pos = this.value.lastIndexOf(' ');
753 word = "";
754 if (word_pos === -1) {
755 word = this.value;
756 } else {
757 word = this.value.substr(word_pos);
758 }
759 word = word.trim();
760
761 // filter data to find only strings that start with existing value
762 for (i = 0; i < data.length; i++) {
763 if (data[i].indexOf(word) === 0 && data[i].length > word.length) {
764 candidates.push(data[i]);
765 }
766 }
767
768 if (candidates.length > 0) {
769 // some candidates for autocompletion are found
770 this.value = this.value.substring(0, word_pos) + ' ' + candidates[0] + ': ';
771 this.selectionStart = this.value.length;
772 }
773 }
774 return false;
775 }
776 });
777
778
779 $('#kiwi .control .msginput .nick').click(function () {
780 front.showChangeNick();
781 });
782
783
784
785
786
787 $('#kiwi .plugins .load_plugin_file').click(function () {
788 var lst, j, txt;
789 if (typeof front.boxes.plugins !== "undefined") {
790 return;
791 }
792
793 front.boxes.plugins = new Box("plugin_file");
794 $('#tmpl_plugins').tmpl({}).appendTo(front.boxes.plugins.content);
795 front.boxes.plugins.box.css('top', -(front.boxes.plugins.height + 40));
796
797 // Populate the plugin list..
798 lst = $('#plugin_list');
799 lst.find('option').remove();
800 for (j in plugins.privmsg) {
801 txt = plugins.privmsg[j].name;
802 lst.append('<option value="' + txt + '">' + txt + '</option>');
803 }
804
805 // Event bindings
806 $('#kiwi .plugin_file').submit(function () {
807 $.getJSON($('.txtpluginfile').val(), function (data) {
808 var plg = {};
809 plg.name = data.name;
810 eval("plg.onprivmsg = " + data.onprivmsg);
811 eval("plg.onload = " + data.onload);
812 eval("plg.onunload = " + data.onunload);
813 plugins.privmsg.push(plg);
814
815 if (plg.onload instanceof Function) {
816 plg.onload();
817 }
818 });
819 return false;
820 });
821 $('#kiwi .cancelpluginfile').click(function () {
822 front.boxes.plugins.destroy();
823 });
824
825 $('#kiwi #plugins_list_unload').click(function () {
826 var selected_plugin, i;
827 selected_plugin = $('#plugin_list').val();
828 console.log("removing plugin: " + selected_plugin);
829 for (i in plugins.privmsg) {
830 if (plugins.privmsg[i].name === selected_plugin) {
831 if (plugins.privmsg[i].onunload instanceof Function) {
832 plugins.privmsg[i].onunload();
833 }
834 delete plugins.privmsg[i];
835 }
836 }
837 });
838
839 $('#kiwi .txtpluginfile').focus();
840
841 });
842
843 $('#kiwi .plugins .reload_css').click(function () {
844 var links = document.getElementsByTagName("link"),
845 i;
846 for (i = 0; i < links.length; i++) {
847 if (links[i].rel === "stylesheet") {
848 if (links[i].href.indexOf("?") === -1) {
849 links[i].href += "?";
850 }
851 links[i].href += "x";
852 }
853 }
854 });
855
856
857 $('#kiwi .about .about_close').click(function () {
858 $('#kiwi .about').css('display', 'none');
859 });
860
861
862 $('#kiwi .poweredby').click(function () {
863 $('#kiwi .about').css('display', 'block');
864 });
865
866 },
867
868
869 showChangeNick: function () {
870 $('#kiwi').append($('#tmpl_change_nick').tmpl({}));
871
872 $('#kiwi .form_newnick').submit(function () {
873 front.run('/NICK ' + $('#kiwi .txtnewnick').val());
874 $('#kiwi .newnick').remove();
875 return false;
876 });
877
878 $('#kiwi .txtnewnick').keypress(function (ev) {
879 if (!this.first_press) {
880 this.first_press = true;
881 return false;
882 }
883 });
884
885 $('#kiwi .txtnewnick').keydown(function (ev) {
886 if (ev.which === 27) { // ESC
887 $('#kiwi_msginput').focus();
888 $('#kiwi .newnick').remove();
889 }
890 });
891
892 $('#kiwi .cancelnewnick').click(function () {
893 $('#kiwi .newnick').remove();
894 });
895
896 $('#kiwi .txtnewnick').focus();
897 },
898
899
900 tabviewExists: function (name) {
901 return (typeof front.tabviews[name.toLowerCase()] !== 'undefined');
902 },
903
904 tabviewAdd: function (v_name) {
905 var re, htmlsafe_name, tmp_divname, tmp_userlistname, tmp_tabname, userlist_enabled = true;
906
907 if (v_name.charAt(0) === gateway.channel_prefix) {
908 re = new RegExp(gateway.channel_prefix, "g");
909 htmlsafe_name = v_name.replace(re, 'pre');
910 htmlsafe_name = "chan_" + htmlsafe_name;
911 } else {
912 htmlsafe_name = 'query_' + v_name;
913 userlist_enabled = false;
914 }
915
916 tmp_divname = 'kiwi_window_' + htmlsafe_name;
917 tmp_userlistname = 'kiwi_userlist_' + htmlsafe_name;
918 tmp_tabname = 'kiwi_tab_' + htmlsafe_name;
919
920 if (!front.tabviewExists(v_name)) {
921 $('#kiwi .windows .scroller').append('<div id="' + tmp_divname + '" class="messages"></div>');
922 $('#kiwi .userlist').append('<ul id="' + tmp_userlistname + '"></ul>');
923 $('#kiwi .windowlist ul').append('<li id="' + tmp_tabname + '" onclick="front.tabviews[\'' + v_name.toLowerCase() + '\'].show();">' + v_name + '</li>');
924 }
925 //$('#kiwi .windowlist ul .window_'+v_name).click(function(){ front.windowShow(v_name); });
926 //front.windowShow(v_name);
927
928 front.tabviews[v_name.toLowerCase()] = new Tabview();
929 front.tabviews[v_name.toLowerCase()].name = v_name;
930 front.tabviews[v_name.toLowerCase()].div = $('#' + tmp_divname);
931 front.tabviews[v_name.toLowerCase()].userlist = $('#' + tmp_userlistname);
932 front.tabviews[v_name.toLowerCase()].tab = $('#' + tmp_tabname);
933 if (!userlist_enabled) front.tabviews[v_name.toLowerCase()].userlist_width = 0;
934 front.tabviews[v_name.toLowerCase()].show();
935
936 if (typeof registerTouches === "function") {
937 //alert("Registering touch interface");
938 //registerTouches($('#'+tmp_divname));
939 registerTouches(document.getElementById(tmp_divname));
940 }
941 /*
942 front.tabviews[v_name.toLowerCase()].userlist.click(function(){
943 alert($(this).attr('id'));
944 });
945 */
946
947 front.doLayoutSize();
948 },
949
950
951 userClick: function (item) {
952 // Remove any existing userboxes
953 $('#kiwi .userbox').remove();
954
955 var li = $(item).parent();
956 /*var html = '<div class="userbox">\
957 <input type="hidden" class="userbox_nick" value="' + front.nickStripPrefix($(item).text()) + '" />\
958 <a href="#" class="userbox_query">Message</a>\
959 <a href="#" class="userbox_whois">Info</a>\
960 </div>';
961 li.append(html);*/
962 $('#tmpl_user_box').tmpl({nick: front.nickStripPrefix($(item).text())}).appendTo(li);
963
964 $('#kiwi .userbox .userbox_query').click(function (ev) {
965 var nick = $('#kiwi .userbox_nick').val();
966 front.run('/query ' + nick);
967 });
968
969 $('#kiwi .userbox .userbox_whois').click(function (ev) {
970 var nick = $('#kiwi .userbox_nick').val();
971 front.run('/whois ' + nick);
972 });
973 },
974
975
976 sync: function () {
977 gateway.sync();
978 },
979
980 onSync: function (e, data) {
981 // Set any settings
982 if (data.nick !== undefined) {
983 gateway.nick = data.nick;
984 }
985
986 // Add the tabviews
987 if (data.tabviews !== undefined) {
988 $.each(data.tabviews, function (i, tab) {
989 if (!front.tabviewExists(tab.name)) {
990 front.tabviewAdd(gateway.channel_prefix + tab.name);
991
992 if (tab.userlist !== undefined) {
993 front.onUserList({'channel': gateway.channel_prefix + tab.name, 'users': tab.userlist});
994 }
995 }
996 });
997 }
998
999 front.doLayout();
1000 },
1001
1002
1003 setTopicText: function (new_topic) {
1004 front.original_topic = new_topic;
1005 $('#kiwi .cur_topic .topic').text(new_topic);
1006 front.doLayoutSize();
1007 },
1008
1009
1010
1011
1012
1013
1014
1015 nickStripPrefix: function (nick) {
1016 var tmp = nick, i;
1017
1018 prefix = tmp.charAt(0);
1019 for (i in gateway.user_prefixes) {
1020 if (gateway.user_prefixes[i].symbol !== prefix) {
1021 continue;
1022 }
1023 return tmp.substring(1);
1024 }
1025
1026 return tmp;
1027 },
1028
1029 nickGetPrefix: function (nick) {
1030 var tmp = nick, i;
1031
1032 prefix = tmp.charAt(0);
1033 for (i in gateway.user_prefixes) {
1034 if (gateway.user_prefixes[i].symbol === prefix) {
1035 return prefix;
1036 }
1037 }
1038
1039 return '';
1040 },
1041
1042 isChannel: function (name) {
1043 prefix = name.charAt(0);
1044 if (gateway.channel_prefix.indexOf(prefix) > -1) {
1045 is_chan = true;
1046 } else {
1047 is_chan = false;
1048 }
1049
1050 return is_chan;
1051 },
1052
1053 tabviewsNext: function () {
1054 var wl = $('#kiwi .windowlist ul'),
1055 next_left = parseInt(wl.css('text-indent').replace('px', ''), 10) + 170;
1056 wl.css('text-indent', next_left);
1057 },
1058
1059 tabviewsPrevious: function () {
1060 var wl = $('#kiwi .windowlist ul'),
1061 next_left = parseInt(wl.css('text-indent').replace('px', ''), 10) - 170;
1062 wl.css('text-indent', next_left);
1063 },
1064
1065 windowsNext: function () {
1066 var tab, next;
1067 next = false;
1068 for (tab in front.tabviews) {
1069 if (!next) {
1070 if (front.tabviews[tab] === front.cur_channel) {
1071 next = true;
1072 continue;
1073 }
1074 } else {
1075 front.tabviews[tab].show();
1076 return;
1077 }
1078 }
1079 },
1080
1081 windowsPrevious: function () {
1082 var tab, prev_tab, next;
1083 next = false;
1084 for (tab in front.tabviews) {
1085 if (front.tabviews[tab] === front.cur_channel) {
1086 if (prev_tab) {
1087 prev_tab.show();
1088 }
1089 return;
1090 }
1091 prev_tab = front.tabviews[tab];
1092 }
1093 },
1094
1095 windowsShow: function (num) {
1096 num = parseInt(num, 10);
1097 console.log('Showing window ' + num.toString());
1098 var i = 0, tab;
1099 for (tab in front.tabviews) {
1100 if (i === num) {
1101 front.tabviews[tab].show();
1102 return;
1103 }
1104 i++;
1105 }
1106 }
1107 };
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124 /*
1125 * MISC VIEW
1126 */
1127
1128 var Utilityview = function (name, src) {
1129
1130 var tmp_divname = 'kiwi_window_' + name;
1131 var tmp_userlistname = 'kiwi_userlist_' + name;
1132 var tmp_tabname = 'kiwi_tab_' + name;
1133
1134 this.name = name;
1135 this.topic = src;
1136
1137 if (!front.tabviewExists(name)) {
1138 $('#kiwi .windows .scroller').append('<div id="' + tmp_divname + '" class="messages"></div>');
1139 $('#kiwi .windowlist ul').append('<li id="' + tmp_tabname + '" onclick="front.tabviews[\'' + name.toLowerCase() + '\'].show();">' + name + '</li>');
1140 }
1141
1142 this.div = $('#' + tmp_divname);
1143 this.div.css('overflow', 'hidden');
1144
1145 this.tab = $('#' + tmp_tabname);
1146
1147 this.iframe = $('<iframe border="0" class="utility_view" src="" style="width:100%;height:100%;border:none;"></iframe>');
1148 if(src) this.iframe.attr('src', src);
1149 this.div.append(this.iframe);
1150
1151 front.tabviews[name.toLowerCase()] = this;
1152 };
1153
1154 Utilityview.prototype.name = null;
1155 Utilityview.prototype.div = null;
1156 Utilityview.prototype.tab = null;
1157 Utilityview.prototype.iframe = null;
1158 Utilityview.prototype.topic = ' ';
1159 Utilityview.prototype.show = function () {
1160 $('#kiwi .messages').removeClass("active");
1161 $('#kiwi .userlist ul').removeClass("active");
1162 $('#kiwi .windowlist ul li').removeClass("active");
1163
1164 $('#windows').css('overflow-y', 'hidden');
1165
1166 // Activate this tab!
1167 this.div.addClass('active');
1168 this.tab.addClass('active');
1169
1170 this.addPartImage();
1171
1172 front.setTopicText(this.topic);
1173 front.cur_channel = this;
1174
1175 // If we're using fancy scrolling, refresh it
1176 if (touch_scroll) {
1177 touch_scroll.refresh();
1178 }
1179 }
1180
1181 Utilityview.prototype.close = function () {
1182 this.div.remove();
1183 this.tab.remove();
1184
1185 if (front.cur_channel === this) {
1186 front.tabviews.server.show();
1187 }
1188 delete front.tabviews[this.name.toLowerCase()];
1189 };
1190
1191 Utilityview.prototype.addPartImage = function () {
1192 this.clearPartImage();
1193
1194 // We can't close this tab, so don't have the close image
1195 if (this.name === 'server') {
1196 return;
1197 }
1198
1199 var del_html = '<img src="img/redcross.png" class="tab_part" />';
1200 this.tab.append(del_html);
1201
1202 $('.tab_part', this.tab).click(function () {
1203 if (front.cur_channel.name !== 'server') {
1204 front.cur_channel.close();
1205 }
1206 });
1207 };
1208
1209 Utilityview.prototype.clearPartImage = function () {
1210 $('#kiwi .windowlist .tab_part').remove();
1211 };
1212
1213
1214
1215
1216
1217 /*
1218 *
1219 * TABVIEWS
1220 *
1221 */
1222
1223
1224 var Tabview = function () {};
1225 Tabview.prototype.name = null;
1226 Tabview.prototype.div = null;
1227 Tabview.prototype.userlist = null;
1228 Tabview.prototype.userlist_width = 100; // 0 for disabled
1229 Tabview.prototype.tab = null;
1230 Tabview.prototype.topic = "";
1231 Tabview.prototype.safe_to_close = false; // If we have been kicked/banned/etc from this channel, don't wait for a part message
1232
1233 Tabview.prototype.show = function () {
1234 var w, u;
1235
1236 $('#kiwi .messages').removeClass("active");
1237 $('#kiwi .userlist ul').removeClass("active");
1238 $('#kiwi .windowlist ul li').removeClass("active");
1239
1240 w = $('#windows');
1241 u = $('#kiwi .userlist');
1242
1243 w.css('overflow-y', 'scroll');
1244
1245 // Set the window size accordingly
1246 if (this.userlist_width > 0) {
1247 u.width(this.userlist_width);
1248 w.css('right', u.outerWidth(true));
1249 } else {
1250 w.css('right', 0);
1251 }
1252
1253 // Activate this tab!
1254 this.div.addClass('active');
1255 if (this.userlist_width > 0) this.userlist.addClass('active');
1256 this.tab.addClass('active');
1257
1258 // Add the part image to the tab
1259 this.addPartImage();
1260
1261 this.clearHighlight();
1262 front.setTopicText(this.topic);
1263 front.cur_channel = this;
1264
1265 // If we're using fancy scrolling, refresh it
1266 if (touch_scroll) {
1267 touch_scroll.refresh();
1268 }
1269
1270 this.scrollBottom();
1271 if (!touchscreen) {
1272 $('#kiwi_msginput').focus();
1273 }
1274 };
1275
1276 Tabview.prototype.close = function () {
1277 this.div.remove();
1278 this.userlist.remove();
1279 this.tab.remove();
1280
1281 if (front.cur_channel === this) {
1282 front.tabviews.server.show();
1283 }
1284 delete front.tabviews[this.name.toLowerCase()];
1285 };
1286
1287 Tabview.prototype.addPartImage = function () {
1288 this.clearPartImage();
1289
1290 // We can't close this tab, so don't have the close image
1291 if (this.name === 'server') {
1292 return;
1293 }
1294
1295 var del_html = '<img src="img/redcross.png" class="tab_part" />';
1296 this.tab.append(del_html);
1297
1298 $('.tab_part', this.tab).click(function () {
1299 if (front.isChannel($(this).parent().text())) {
1300 front.run("/part");
1301 } else {
1302 // Make sure we don't close the server tab
1303 if (front.cur_channel.name !== 'server') {
1304 front.cur_channel.close();
1305 }
1306 }
1307 });
1308 };
1309
1310 Tabview.prototype.clearPartImage = function () {
1311 $('#kiwi .windowlist .tab_part').remove();
1312 };
1313
1314 Tabview.prototype.addMsg = function (time, nick, msg, type, style) {
1315 var self, tmp, plugin_ret, i, d, re, line_msg;
1316
1317 self = this;
1318
1319 tmp = {msg: msg, time: time, nick: nick, tabview: this.name};
1320 tmp = plugs.run('addmsg', tmp);
1321 if (!tmp) return;
1322
1323
1324 msg = tmp.msg;
1325 time = tmp.time;
1326 nick = tmp.nick;
1327
1328 if (time === null) {
1329 d = new Date();
1330 time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0");
1331 }
1332
1333 // The CSS class (action, topic, notice, etc)
1334 if (typeof type !== "string") {
1335 type = '';
1336 }
1337
1338 // Make sure we don't have NaN or something
1339 if (typeof msg !== "string") {
1340 msg = '';
1341 }
1342
1343 // Text formatting
1344 // bold
1345 if (msg.indexOf(String.fromCharCode(2)) !== -1) {
1346 next = '<b>';
1347 while (msg.indexOf(String.fromCharCode(2)) !== -1) {
1348 msg = msg.replace(String.fromCharCode(2), next);
1349 next = (next === '<b>') ? '</b>' : '<b>';
1350 }
1351 if (next === '</b>') {
1352 msg = msg + '</b>';
1353 }
1354 }
1355
1356 // Wierd thing noticed by Dux0r on the irc.esper.net server
1357 if (typeof msg !== "string") {
1358 msg = '';
1359 }
1360
1361 // underline
1362 if (msg.indexOf(String.fromCharCode(31)) !== -1) {
1363 next = '<u>';
1364 while (msg.indexOf(String.fromCharCode(31)) !== -1) {
1365 msg = msg.replace(String.fromCharCode(31), next);
1366 next = (next === '<u>') ? '</u>' : '<u>';
1367 }
1368 if (next === '</u>') {
1369 msg = msg + '</u>';
1370 }
1371 }
1372
1373 // Make the channels clickable
1374 re = new RegExp('\\B(' + gateway.channel_prefix + '[^ ,.\\007]+)', 'g');
1375 msg = msg.replace(re, function (match) {
1376 return '<a class="chan">' + match + '</a>';
1377 });
1378
1379 // Build up and add the line
1380 line_msg = $('<div class="msg ' + type + '"><div class="time">' + time + '</div><div class="nick">' + nick + '</div><div class="text" style="' + style + '">' + msg + ' </div></div>');
1381 this.div.append(line_msg);
1382
1383 if (!touchscreen) {
1384 this.scrollBottom();
1385 } else {
1386 touch_scroll.refresh();
1387 //console.log(this.div.attr("scrollHeight") +" - "+ $('#windows').height());
1388 this.scrollBottom();
1389 //if(this.div.attr("scrollHeight") > $('#windows').height()){
1390 // touch_scroll.scrollTo(0, this.div.height());
1391 //}
1392 }
1393 };
1394
1395 Tabview.prototype.scrollBottom = function () {
1396 var w = $('#windows');
1397 w[0].scrollTop = w[0].scrollHeight;
1398 };
1399
1400 Tabview.prototype.changeNick = function (newNick, oldNick) {
1401 this.userlist.children().each(function () {
1402 var item = $('a.nick', this);
1403 if (front.nickStripPrefix(item.text()) === oldNick) {
1404 item.text(front.nickGetPrefix(item.text()) + newNick);
1405 document.temp_chan = 1;
1406 }
1407 });
1408
1409 if (typeof document.temp_chan !== "undefined") {
1410 this.addMsg(null, ' ', '=== ' + oldNick + ' is now known as ' + newNick, 'action');
1411 delete document.temp_chan;
1412 this.userlistSort();
1413 }
1414 };
1415
1416 Tabview.prototype.userlistSort = function () {
1417 var ul = this.userlist,
1418 listitems = ul.children('li').get();
1419 listitems.sort(function (a, b) {
1420 var compA = $(a).text().toUpperCase(),
1421 compB = $(b).text().toUpperCase(),
1422 i;
1423
1424 // Sort by prefixes first
1425 for (i in gateway.user_prefixes) {
1426 prefix = gateway.user_prefixes[i].symbol;
1427
1428 if (compA.charAt(0) === prefix && compB.charAt(0) === prefix) {
1429 // Both have the same prefix, string compare time
1430 return 0;
1431 }
1432
1433 if (compA.charAt(0) === prefix && compB.charAt(0) !== prefix) {
1434 return -1;
1435 }
1436
1437 if (compA.charAt(0) !== prefix && compB.charAt(0) === prefix) {
1438 return 1;
1439 }
1440 }
1441
1442 // No prefixes, compare by string
1443 return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
1444 });
1445 $.each(listitems, function (idx, itm) { ul.append(itm); });
1446 };
1447
1448 Tabview.prototype.highlight = function () {
1449 this.tab.addClass('highlight');
1450 };
1451 Tabview.prototype.activity = function () {
1452 this.tab.addClass('activity');
1453 };
1454 Tabview.prototype.clearHighlight = function () {
1455 this.tab.removeClass('highlight');
1456 this.tab.removeClass('activity');
1457 };
1458 Tabview.prototype.changeTopic = function (new_topic) {
1459 this.topic = new_topic;
1460 this.addMsg(null, ' ', '=== Topic for ' + this.name + ' is: ' + new_topic, 'topic');
1461 if (front.cur_channel.name === this.name) {
1462 front.setTopicText(new_topic);
1463 }
1464 };
1465
1466
1467
1468
1469
1470 var Box = function (classname) {
1471 this.id = randomString(10);
1472 var tmp = $('<div id="' + this.id + '" class="box ' + classname + '"><div class="boxarea"></div></div>');
1473 $('#kiwi').append(tmp);
1474 this.box = $('#' + this.id);
1475 this.content = $('#' + this.id + ' .boxarea');
1476
1477 this.box.draggable({ stack: ".box" });
1478 this.content.click(function () {});
1479 //this.box.click(function(){ $(this)..css });
1480 };
1481 Box.prototype.create = function (name, classname) {
1482
1483 };
1484 Box.prototype.id = null;
1485 Box.prototype.box = null;
1486 Box.prototype.content = null;
1487 Box.prototype.destroy = function () {
1488 var name;
1489 this.box.remove();
1490 for (name in front.boxes) {
1491 if (front.boxes[name].id === this.id) {
1492 delete front.boxes[name];
1493 }
1494 }
1495 };
1496 Box.prototype.height = function () {
1497 return this.box.height();
1498 };