]> jfr.im git - irc/quakenet/qwebirc.git/blame - js/ui/frontends/qui.js
Produce compiled files based on hg id.
[irc/quakenet/qwebirc.git] / js / ui / frontends / qui.js
CommitLineData
e20e5a6b
CP
1qwebirc.ui.QUI = new Class({
2 Extends: qwebirc.ui.NewLoginUI,
2cad083e
CP
3 initialize: function(parentElement, theme, options) {
4 this.parent(parentElement, qwebirc.ui.QUI.Window, "qui", options);
e20e5a6b
CP
5 this.theme = theme;
6 this.parentElement = parentElement;
7 },
8 postInitialize: function() {
9 this.qjsui = new qwebirc.ui.QUI.JSUI("qwebirc-qui", this.parentElement);
bfbe72f9
CP
10 this.qjsui.addEvent("reflow", function() {
11 var w = this.getActiveWindow();
12 if($defined(w))
13 w.onResize();
14 }.bind(this));
941e1642 15 this.qjsui.top.addClass("outertabbar");
e20e5a6b
CP
16
17 this.qjsui.bottom.addClass("input");
18 this.qjsui.right.addClass("nicklist");
19 this.qjsui.topic.addClass("topic");
20 this.qjsui.middle.addClass("lines");
21
941e1642 22 this.outerTabs = this.qjsui.top;
0989d983
CP
23
24 this.__createDropdownMenu();
25 this.__createDropdownHint();
941e1642
CP
26
27 this.tabs = new Element("div");
28 this.tabs.addClass("tabbar");
29 this.outerTabs.appendChild(this.tabs);
e20e5a6b
CP
30 this.origtopic = this.topic = this.qjsui.topic;
31 this.origlines = this.lines = this.qjsui.middle;
32 this.orignicklist = this.nicklist = this.qjsui.right;
33
34 this.input = this.qjsui.bottom;
35 this.reflow = this.qjsui.reflow.bind(this.qjsui);
36
ff4befd8
CP
37 this.tabs.addEvent("mousewheel", function(x) {
38 var event = new Event(x);
39
40 /* up */
41 if(event.wheel > 0) {
42 this.nextWindow();
43 } else if(event.wheel < 0) {
44 /* down */
b35116e2 45 this.prevWindow();
ff4befd8
CP
46 }
47 event.stop();
48 }.bind(this));
49
e20e5a6b
CP
50 this.createInput();
51 this.reflow();
52 },
0989d983 53 __createDropdownMenu: function() {
e9837dce 54 var dropdownMenu = new Element("span");
43cb8910 55 dropdownMenu.addClass("dropdownmenu");
0989d983
CP
56
57 dropdownMenu.hide = function() {
43cb8910
CP
58 dropdownMenu.setStyle("display", "none");
59 dropdownMenu.visible = false;
e9837dce 60 document.removeEvent("mousedown", hideEvent);
43cb8910 61 }.bind(this);
e9837dce 62 var hideEvent = function() { dropdownMenu.hide(); };
0989d983
CP
63
64 dropdownMenu.hide();
43cb8910
CP
65 this.parentElement.appendChild(dropdownMenu);
66
67 this.UICommands.forEach(function(x) {
68 var text = x[0];
69 var fn = this[x[1] + "Window"].bind(this);
70 var e = new Element("a");
0989d983 71 e.addEvent("mousedown", function(e) { new Event(e).stop(); });
43cb8910
CP
72 e.addEvent("click", function() {
73 dropdownMenu.hide();
74 fn();
75 });
76 e.set("text", text);
77 dropdownMenu.appendChild(e);
78 }.bind(this));
79
941e1642 80 var dropdown = new Element("div");
43cb8910 81 dropdown.addClass("dropdown-tab");
941e1642 82 dropdown.appendChild(new Element("img", {src: "images/favicon.png", title: "menu", alt: "menu"}));
391f51ff
CP
83 dropdown.setStyle("opacity", 1);
84
85 var dropdownEffect = new Fx.Tween(dropdown, {duration: "long", property: "opacity", link: "chain"});
86 dropdownEffect.start(0.25);
87 dropdownEffect.start(1);
88 dropdownEffect.start(0.33);
89 dropdownEffect.start(1);
90
941e1642 91 this.outerTabs.appendChild(dropdown);
43cb8910
CP
92 dropdownMenu.show = function(x){
93 new Event(x).stop();
e9837dce 94 this.hideHint();
43cb8910
CP
95
96 if(dropdownMenu.visible) {
97 dropdownMenu.hide();
98 return;
99 }
e9837dce
CP
100 var top = this.outerTabs.getSize().y;
101
941e1642 102 dropdownMenu.setStyle("left", 0);
385143a6 103 dropdownMenu.setStyle("top", top-1); /* -1 == top border */
43cb8910
CP
104 dropdownMenu.setStyle("display", "inline-block");
105 dropdownMenu.visible = true;
e9837dce
CP
106
107 document.addEvent("mousedown", hideEvent);
43cb8910 108 }.bind(this);
e9837dce 109 dropdown.addEvent("mousedown", function(e) { new Event(e).stop(); });
43cb8910 110 dropdown.addEvent("click", dropdownMenu.show);
0989d983
CP
111 },
112 __createDropdownHint: function() {
43cb8910
CP
113 var dropdownhint = new Element("div");
114 dropdownhint.addClass("dropdownhint");
391f51ff 115 dropdownhint.set("text", "Click the icon for the main menu.");
e9837dce
CP
116 dropdownhint.setStyle("top", this.outerTabs.getSize().y + 5);
117
118 this.parentElement.appendChild(dropdownhint);
391f51ff
CP
119 new Fx.Morph(dropdownhint, {duration: "normal", transition: Fx.Transitions.Sine.easeOut}).start({left: [900, 5]});
120
43cb8910 121 var hider = function() {
391f51ff
CP
122 new Fx.Morph(dropdownhint, {duration: "long"}).start({left: [5, -900]});
123 }.delay(4000, this);
0989d983 124
391f51ff
CP
125 var hider2 = function() {
126 if(dropdownhint.hidden)
127 return;
e9837dce 128 this.parentElement.removeChild(dropdownhint);
391f51ff
CP
129 dropdownhint.hidden = 1;
130 }.bind(this);
131 hider2.delay(4000);
e9837dce 132 this.hideHint = hider2;
391f51ff
CP
133
134 document.addEvent("mousedown", hider2);
135 document.addEvent("keypress", hider2);
136
43cb8910 137 },
e20e5a6b
CP
138 createInput: function() {
139 var form = new Element("form");
140 this.input.appendChild(form);
141 form.addClass("input");
142
143 var inputbox = new Element("input");
144 form.appendChild(inputbox);
145 this.inputbox = inputbox;
146
147 form.addEvent("submit", function(e) {
148 new Event(e).stop();
149
150 if(inputbox.value == "")
151 return;
152
3184781b 153 this.resetTabComplete();
e20e5a6b
CP
154 this.getActiveWindow().historyExec(inputbox.value);
155 inputbox.value = "";
156 }.bind(this));
157
3184781b
CP
158 inputbox.addEvent("focus", this.resetTabComplete.bind(this));
159 inputbox.addEvent("mousedown", this.resetTabComplete.bind(this));
160
e20e5a6b
CP
161 inputbox.addEvent("keydown", function(e) {
162 var resultfn;
163 var cvalue = inputbox.value;
3184781b 164
e20e5a6b
CP
165 if(e.key == "up") {
166 resultfn = this.commandhistory.upLine;
167 } else if(e.key == "down") {
168 resultfn = this.commandhistory.downLine;
3184781b
CP
169 } else if(e.key == "tab") {
170 new Event(e).stop();
171 this.tabComplete(inputbox);
172 return;
e20e5a6b 173 } else {
3184781b
CP
174 /* ideally alt and other keys wouldn't break this */
175 this.resetTabComplete();
e20e5a6b
CP
176 return;
177 }
178
3184781b 179 this.resetTabComplete();
e20e5a6b
CP
180 if((cvalue != "") && (this.lastcvalue != cvalue))
181 this.commandhistory.addLine(cvalue, true);
182
183 var result = resultfn.bind(this.commandhistory)();
184
185 new Event(e).stop();
186 if(!result)
187 result = "";
188 this.lastcvalue = result;
189
190 inputbox.value = result;
1d6756bc 191 qwebirc.util.setAtEnd(inputbox);
e20e5a6b
CP
192 }.bind(this));
193 },
194 setLines: function(lines) {
195 this.lines.parentNode.replaceChild(lines, this.lines);
196 this.qjsui.middle = this.lines = lines;
197 },
198 setChannelItems: function(nicklist, topic) {
199 if(!$defined(nicklist)) {
200 nicklist = this.orignicklist;
201 topic = this.origtopic;
202 }
203 this.nicklist.parentNode.replaceChild(nicklist, this.nicklist);
204 this.qjsui.right = this.nicklist = nicklist;
205
206 this.topic.parentNode.replaceChild(topic, this.topic);
207 this.qjsui.topic = this.topic = topic;
208 }
209});
210
211qwebirc.ui.QUI.JSUI = new Class({
bfbe72f9 212 Implements: [Events],
b1ee83f3
CP
213 initialize: function(class_, parent, sizer) {
214 this.parent = parent;
215 this.sizer = $defined(sizer)?sizer:parent;
216
24ede2cb
CP
217 this.class_ = class_;
218 this.create();
219
6c19eb8f
CP
220 this.reflowevent = null;
221
b1ee83f3 222 window.addEvent("resize", function() {
6c19eb8f 223 this.reflow(100);
b1ee83f3
CP
224 }.bind(this));
225 },
24ede2cb 226 applyClasses: function(pos, l) {
6c19eb8f 227 l.addClass("dynamicpanel");
24ede2cb 228 l.addClass(this.class_);
6c19eb8f 229
24ede2cb
CP
230 if(pos == "middle") {
231 l.addClass("leftboundpanel");
232 } else if(pos == "top") {
233 l.addClass("topboundpanel");
234 l.addClass("widepanel");
235 } else if(pos == "topic") {
236 l.addClass("widepanel");
237 } else if(pos == "right") {
238 l.addClass("rightboundpanel");
239 } else if(pos == "bottom") {
240 l.addClass("bottomboundpanel");
241 l.addClass("widepanel");
242 }
243 },
244 create: function() {
245 var XE = function(pos) {
246 var element = new Element("div");
247 this.applyClasses(pos, element);
b1ee83f3 248
24ede2cb
CP
249 this.parent.appendChild(element);
250 return element;
b1ee83f3
CP
251 }.bind(this);
252
24ede2cb
CP
253 this.top = XE("top");
254 this.topic = XE("topic");
255 this.middle = XE("middle");
256 this.right = XE("right");
257 this.bottom = XE("bottom");
b1ee83f3 258 },
6c19eb8f
CP
259 reflow: function(delay) {
260 if(!delay)
261 delay = 1;
262
263 if(this.reflowevent)
264 $clear(this.reflowevent);
265 this.__reflow();
266 this.reflowevent = this.__reflow.delay(delay, this);
267 },
268 __reflow: function() {
b1ee83f3
CP
269 var bottom = this.bottom;
270 var middle = this.middle;
271 var right = this.right;
272 var topic = this.topic;
273 var top = this.top;
274
275 var topicsize = topic.getSize();
276 var topsize = top.getSize();
277 var rightsize = right.getSize();
278 var bottomsize = bottom.getSize();
279 var docsize = this.sizer.getSize();
280
281 var mheight = (docsize.y - topsize.y - bottomsize.y - topicsize.y);
282 var mwidth = (docsize.x - rightsize.x);
283
284 topic.setStyle("top", topsize.y + "px");
285
286 middle.setStyle("top", (topsize.y + topicsize.y) + "px");
287 if(mheight > 0) {
288 middle.setStyle("height", mheight + "px");
289 right.setStyle("height", mheight + "px");
290 }
291
6c19eb8f 292 if(mwidth > 0)
b1ee83f3 293 middle.setStyle("width", mwidth + "px");
b1ee83f3
CP
294 right.setStyle("top", (topsize.y + topicsize.y) + "px");
295 right.setStyle("left", mwidth + "px");
296
297 bottom.setStyle("top", (docsize.y - bottomsize.y) + "px");
bfbe72f9 298 this.fireEvent("reflow");
b1ee83f3
CP
299 },
300 showChannel: function(state) {
301 var display = "none";
302 if(state)
303 display = "block";
304
305 this.right.setStyle("display", display);
306 this.topic.setStyle("display", display);
6c19eb8f
CP
307 },
308 showInput: function(state) {
941e1642 309 this.bottom.isVisible = state;
6c19eb8f 310 this.bottom.setStyle("display", state?"block":"none");
b1ee83f3
CP
311 }
312});
35155ba7 313
e20e5a6b
CP
314qwebirc.ui.QUI.Window = new Class({
315 Extends: qwebirc.ui.Window,
f4ae92cc 316
f74802c5
CP
317 initialize: function(parentObject, client, type, name, identifier) {
318 this.parent(parentObject, client, type, name, identifier);
be0bd774 319
66de775f 320 this.tab = new Element("a", {"href": "#"});
f4ae92cc 321 this.tab.addClass("tab");
fd60516d
CP
322 this.tab.addEvent("focus", function() { this.blur() }.bind(this.tab));;
323
35155ba7 324 parentObject.tabs.appendChild(this.tab);
f4ae92cc
CP
325
326 this.tab.appendText(name);
66de775f
CP
327 this.tab.addEvent("click", function(e) {
328 new Event(e).stop();
f84bf379
CP
329
330 if(this.closed)
331 return;
332
f4ae92cc
CP
333 parentObject.selectWindow(this);
334 }.bind(this));
f4ae92cc 335
e20e5a6b
CP
336 if(type != qwebirc.ui.WINDOW_STATUS && type != qwebirc.ui.WINDOW_CONNECT) {
337 var tabclose = new Element("span");
338 tabclose.set("text", "X");
f4ae92cc 339 tabclose.addClass("tabclose");
f84bf379 340 var close = function(e) {
f4ae92cc
CP
341 new Event(e).stop();
342
f84bf379
CP
343 if(this.closed)
344 return;
345
e20e5a6b 346 if(type == qwebirc.ui.WINDOW_CHANNEL)
f4ae92cc
CP
347 this.client.exec("/PART " + name);
348
349 this.close();
3184781b 350
941e1642 351 //parentObject.inputbox.focus();
f84bf379
CP
352 }.bind(this);
353
354 tabclose.addEvent("click", close);
355 this.tab.addEvent("mouseup", function(e) {
b46f79e6
CP
356 var button = 1;
357
358 if(Browser.Engine.trident)
359 button = 4;
360
361 if(e.event.button == button)
f84bf379 362 close(e);
f4ae92cc 363 }.bind(this));
52090a1f 364
f4ae92cc
CP
365 this.tab.appendChild(tabclose);
366 }
be0bd774 367
be0bd774 368 this.lines = new Element("div");
6c19eb8f 369 this.parentObject.qjsui.applyClasses("middle", this.lines);
be0bd774 370 this.lines.addClass("lines");
e82478eb
CP
371 if(type != qwebirc.ui.WINDOW_CUSTOM && type != qwebirc.ui.WINDOW_CONNECT)
372 this.lines.addClass("ircwindow");
6c19eb8f 373
b1ee83f3
CP
374 this.lines.addEvent("scroll", function() {
375 this.scrolleddown = this.scrolledDown();
ff6a32cc 376 this.scrollpos = this.getScrollParent().getScroll();
be0bd774 377 }.bind(this));
be0bd774 378
e20e5a6b 379 if(type == qwebirc.ui.WINDOW_CHANNEL) {
be0bd774
CP
380 this.topic = new Element("div");
381 this.topic.addClass("topic");
b1ee83f3 382 this.topic.addClass("tab-invisible");
be0bd774 383 this.topic.set("html", "&nbsp;");
6c19eb8f 384 this.parentObject.qjsui.applyClasses("topic", this.topic);
be0bd774 385
52090a1f 386 this.prevNick = null;
66de775f
CP
387 this.nicklist = new Element("div");
388 this.nicklist.addClass("nicklist");
b1ee83f3 389 this.nicklist.addClass("tab-invisible");
cffd43cf 390 this.nicklist.addEvent("click", this.removePrevMenu.bind(this));
6c19eb8f 391 this.parentObject.qjsui.applyClasses("nicklist", this.nicklist);
be0bd774 392 }
b1ee83f3 393
e20e5a6b 394 if(type == qwebirc.ui.WINDOW_CHANNEL) {
359b7edd
CP
395 this.updateTopic("");
396 } else {
397 this.reflow();
398 }
b1ee83f3
CP
399 },
400 reflow: function() {
401 this.parentObject.reflow();
35155ba7
CP
402 },
403 onResize: function() {
ff6a32cc
CP
404 if(this.scrolleddown) {
405 if(Browser.Engine.trident) {
406 this.scrollToBottom.delay(5, this);
407 } else {
408 this.scrollToBottom();
409 }
410 } else if($defined(this.scrollpos)) {
411 if(Browser.Engine.trident) {
412 this.getScrollParent().scrollTo(this.scrollpos.x, this.scrollpos.y);
413 } else {
414 this.getScrollParent().scrollTo.delay(5, this, [this.scrollpos.x, this.scrollpos.y]);
415 }
416 }
359b7edd 417 },
cffd43cf 418 createMenu: function(nick, parent) {
d2512acf 419 var e = new Element("div");
cffd43cf
CP
420 parent.appendChild(e);
421 e.addClass("menu");
422
423 qwebirc.ui.MENU_ITEMS.forEach(function(x) {
d2512acf 424 var e2 = new Element("a");
cffd43cf
CP
425 e.appendChild(e2);
426
427 e2.href = "#";
428 e2.set("text", "- " + x[0]);
429
430 e2.addEvent("focus", function() { this.blur() }.bind(e2));
431 e2.addEvent("click", function(ev) { new Event(ev.stop()); this.menuClick(x[1]); }.bind(this));
432 }.bind(this));
433 return e;
434 },
435 menuClick: function(fn) {
436 /*
437 this.prevNick.removeChild(this.prevNick.menu);
438 this.prevNick.menu = null;
439 */
440 fn.bind(this)(this.prevNick.realNick);
441 this.removePrevMenu();
442 },
d8272bcb
CP
443 moveMenuClass: function() {
444 if(!this.prevNick)
445 return;
446 if(this.nicklist.firstChild == this.prevNick) {
447 this.prevNick.removeClass("selected-middle");
448 } else {
449 this.prevNick.addClass("selected-middle");
450 }
451 },
cffd43cf
CP
452 removePrevMenu: function() {
453 if(!this.prevNick)
454 return;
455
456 this.prevNick.removeClass("selected");
d8272bcb 457 this.prevNick.removeClass("selected-middle");
cffd43cf
CP
458 if(this.prevNick.menu)
459 this.prevNick.removeChild(this.prevNick.menu);
460 this.prevNick = null;
461 },
52090a1f
CP
462 nickListAdd: function(nick, position) {
463 var e = new Element("a");
464 qwebirc.ui.insertAt(position, this.nicklist, e);
f4ae92cc 465
52090a1f
CP
466 e.href = "#";
467 e.appendChild(document.createTextNode(nick));
468
469 e.realNick = this.client.stripPrefix(nick);
470
471 e.addEvent("click", function(x) {
aab6d06a
CP
472 if(this.prevNick == e) {
473 this.removePrevMenu();
474 return;
475 }
476
cffd43cf 477 this.removePrevMenu();
52090a1f
CP
478 this.prevNick = e;
479 e.addClass("selected");
d8272bcb 480 this.moveMenuClass();
cffd43cf 481 e.menu = this.createMenu(x.realNick, e);
52090a1f
CP
482 new Event(x).stop();
483 }.bind(this));
484 e.addEvent("dblclick", function(x) {
485 new Event(x).stop();
486 this.client.exec("/QUERY " + e.realNick);
487 }.bind(this));
488
fd60516d 489 e.addEvent("focus", function() { this.blur() }.bind(e));
d8272bcb 490 this.moveMenuClass();
52090a1f
CP
491 return e;
492 },
493 nickListRemove: function(nick, stored) {
494 this.nicklist.removeChild(stored);
d8272bcb 495 this.moveMenuClass();
f4ae92cc
CP
496 },
497 updateTopic: function(topic) {
f4ae92cc
CP
498 var t = this.topic;
499
500 while(t.firstChild)
501 t.removeChild(t.firstChild);
502
66de775f 503 if(topic) {
1f06a70a 504 this.parent(topic, t);
66de775f 505 } else {
359b7edd
CP
506 var e = new Element("div");
507 e.set("text", "(no topic set)");
66de775f 508 e.addClass("emptytopic");
359b7edd 509 t.appendChild(e);
66de775f 510 }
359b7edd 511 this.reflow();
f4ae92cc
CP
512 },
513 select: function() {
e20e5a6b 514 var inputVisible = this.type != qwebirc.ui.WINDOW_CONNECT && this.type != qwebirc.ui.WINDOW_CUSTOM;
6c19eb8f 515
f4ae92cc 516 this.tab.removeClass("tab-unselected");
f4ae92cc 517 this.tab.addClass("tab-selected");
359b7edd 518
6c19eb8f
CP
519 this.parentObject.setLines(this.lines);
520 this.parentObject.setChannelItems(this.nicklist, this.topic);
521 this.parentObject.qjsui.showInput(inputVisible);
522 this.parentObject.qjsui.showChannel($defined(this.nicklist));
523
524 this.reflow();
24ede2cb 525
7c633700 526 this.parent();
25be5960 527
6c19eb8f
CP
528 if(inputVisible)
529 this.parentObject.inputbox.focus();
f4ae92cc
CP
530 },
531 deselect: function() {
532 this.parent();
533
f4ae92cc
CP
534 this.tab.removeClass("tab-selected");
535 this.tab.addClass("tab-unselected");
536 },
537 close: function() {
538 this.parent();
539
f4ae92cc
CP
540 this.parentObject.tabs.removeChild(this.tab);
541 },
b35116e2 542 addLine: function(type, line, colourClass) {
f4ae92cc
CP
543 var e = new Element("div");
544
b35116e2
CP
545 if(colourClass) {
546 e.addClass(colourClass);
f4ae92cc
CP
547 } else if(this.lastcolour) {
548 e.addClass("linestyle1");
549 } else {
550 e.addClass("linestyle2");
551 }
f4ae92cc 552 this.lastcolour = !this.lastcolour;
35155ba7 553
b35116e2 554 this.parent(type, line, colourClass, e);
be0bd774
CP
555 },
556 setHilighted: function(state) {
96f28062
CP
557 laststate = this.hilighted;
558
be0bd774 559 this.parent(state);
96f28062
CP
560
561 if(state == laststate)
562 return;
563
564 this.tab.removeClass("tab-hilight-activity");
565 this.tab.removeClass("tab-hilight-us");
566 this.tab.removeClass("tab-hilight-speech");
f4ae92cc 567
96f28062
CP
568 switch(this.hilighted) {
569 case qwebirc.ui.HILIGHT_US:
570 this.tab.addClass("tab-hilight-us");
571 break;
572 case qwebirc.ui.HILIGHT_SPEECH:
573 this.tab.addClass("tab-hilight-speech");
574 break;
575 case qwebirc.ui.HILIGHT_ACTIVITY:
576 this.tab.addClass("tab-hilight-activity");
577 break;
be0bd774 578 }
f4ae92cc
CP
579 }
580});