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