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