]> jfr.im git - irc/quakenet/qwebirc.git/blob - js/ui/qui.js
Redo window naming system to use window name identifiers.
[irc/quakenet/qwebirc.git] / js / ui / qui.js
1 qwebirc.ui.QUI = new Class({
2 Extends: qwebirc.ui.NewLoginUI,
3 initialize: function(parentElement, theme) {
4 this.parent(parentElement, qwebirc.ui.QUI.Window, "qui");
5 this.theme = theme;
6 this.parentElement = parentElement;
7 },
8 postInitialize: function() {
9 this.qjsui = new qwebirc.ui.QUI.JSUI("qwebirc-qui", this.parentElement);
10 this.qjsui.addEvent("reflow", function() {
11 var w = this.getActiveWindow();
12 if($defined(w))
13 w.onResize();
14 }.bind(this));
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
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 */
38 this.prevWindow();
39 }
40 event.stop();
41 }.bind(this));
42
43 this.createInput();
44 this.reflow();
45 },
46 createInput: function() {
47 var form = new Element("form");
48 this.input.appendChild(form);
49 form.addClass("input");
50
51 var inputbox = new Element("input");
52 form.appendChild(inputbox);
53 this.inputbox = inputbox;
54
55 form.addEvent("submit", function(e) {
56 new Event(e).stop();
57
58 if(inputbox.value == "")
59 return;
60
61 this.resetTabComplete();
62 this.getActiveWindow().historyExec(inputbox.value);
63 inputbox.value = "";
64 }.bind(this));
65
66 inputbox.addEvent("focus", this.resetTabComplete.bind(this));
67 inputbox.addEvent("mousedown", this.resetTabComplete.bind(this));
68
69 inputbox.addEvent("keydown", function(e) {
70 var resultfn;
71 var cvalue = inputbox.value;
72
73 if(e.key == "up") {
74 resultfn = this.commandhistory.upLine;
75 } else if(e.key == "down") {
76 resultfn = this.commandhistory.downLine;
77 } else if(e.key == "tab") {
78 new Event(e).stop();
79 this.tabComplete(inputbox);
80 return;
81 } else {
82 /* ideally alt and other keys wouldn't break this */
83 this.resetTabComplete();
84 return;
85 }
86
87 this.resetTabComplete();
88 if((cvalue != "") && (this.lastcvalue != cvalue))
89 this.commandhistory.addLine(cvalue, true);
90
91 var result = resultfn.bind(this.commandhistory)();
92
93 new Event(e).stop();
94 if(!result)
95 result = "";
96 this.lastcvalue = result;
97
98 inputbox.value = result;
99 qwebirc.util.setAtEnd(inputbox);
100 }.bind(this));
101 },
102 setLines: function(lines) {
103 this.lines.parentNode.replaceChild(lines, this.lines);
104 this.qjsui.middle = this.lines = lines;
105 },
106 setChannelItems: function(nicklist, topic) {
107 if(!$defined(nicklist)) {
108 nicklist = this.orignicklist;
109 topic = this.origtopic;
110 }
111 this.nicklist.parentNode.replaceChild(nicklist, this.nicklist);
112 this.qjsui.right = this.nicklist = nicklist;
113
114 this.topic.parentNode.replaceChild(topic, this.topic);
115 this.qjsui.topic = this.topic = topic;
116 }
117 });
118
119 qwebirc.ui.QUI.JSUI = new Class({
120 Implements: [Events],
121 initialize: function(class_, parent, sizer) {
122 this.parent = parent;
123 this.sizer = $defined(sizer)?sizer:parent;
124
125 this.class_ = class_;
126 this.create();
127
128 this.reflowevent = null;
129
130 window.addEvent("resize", function() {
131 this.reflow(100);
132 }.bind(this));
133 },
134 applyClasses: function(pos, l) {
135 l.addClass("dynamicpanel");
136 l.addClass(this.class_);
137
138 if(pos == "middle") {
139 l.addClass("leftboundpanel");
140 } else if(pos == "top") {
141 l.addClass("topboundpanel");
142 l.addClass("widepanel");
143 } else if(pos == "topic") {
144 l.addClass("widepanel");
145 } else if(pos == "right") {
146 l.addClass("rightboundpanel");
147 } else if(pos == "bottom") {
148 l.addClass("bottomboundpanel");
149 l.addClass("widepanel");
150 }
151 },
152 create: function() {
153 var XE = function(pos) {
154 var element = new Element("div");
155 this.applyClasses(pos, element);
156
157 this.parent.appendChild(element);
158 return element;
159 }.bind(this);
160
161 this.top = XE("top");
162 this.topic = XE("topic");
163 this.middle = XE("middle");
164 this.right = XE("right");
165 this.bottom = XE("bottom");
166 },
167 reflow: function(delay) {
168 if(!delay)
169 delay = 1;
170
171 if(this.reflowevent)
172 $clear(this.reflowevent);
173 this.__reflow();
174 this.reflowevent = this.__reflow.delay(delay, this);
175 },
176 __reflow: function() {
177 var bottom = this.bottom;
178 var middle = this.middle;
179 var right = this.right;
180 var topic = this.topic;
181 var top = this.top;
182
183 var topicsize = topic.getSize();
184 var topsize = top.getSize();
185 var rightsize = right.getSize();
186 var bottomsize = bottom.getSize();
187 var docsize = this.sizer.getSize();
188
189 var mheight = (docsize.y - topsize.y - bottomsize.y - topicsize.y);
190 var mwidth = (docsize.x - rightsize.x);
191
192 topic.setStyle("top", topsize.y + "px");
193
194 middle.setStyle("top", (topsize.y + topicsize.y) + "px");
195 if(mheight > 0) {
196 middle.setStyle("height", mheight + "px");
197 right.setStyle("height", mheight + "px");
198 }
199
200 if(mwidth > 0)
201 middle.setStyle("width", mwidth + "px");
202 right.setStyle("top", (topsize.y + topicsize.y) + "px");
203 right.setStyle("left", mwidth + "px");
204
205 bottom.setStyle("top", (docsize.y - bottomsize.y) + "px");
206 this.fireEvent("reflow");
207 },
208 showChannel: function(state) {
209 var display = "none";
210 if(state)
211 display = "block";
212
213 this.right.setStyle("display", display);
214 this.topic.setStyle("display", display);
215 },
216 showInput: function(state) {
217 this.bottom.setStyle("display", state?"block":"none");
218 }
219 });
220
221 qwebirc.ui.QUI.Window = new Class({
222 Extends: qwebirc.ui.Window,
223
224 initialize: function(parentObject, client, type, name, identifier) {
225 this.parent(parentObject, client, type, name, identifier);
226
227 this.tab = new Element("a", {"href": "#"});
228 this.tab.addClass("tab");
229 this.tab.addEvent("focus", function() { this.blur() }.bind(this.tab));;
230
231 parentObject.tabs.appendChild(this.tab);
232
233 this.tab.appendText(name);
234 this.tab.addEvent("click", function(e) {
235 new Event(e).stop();
236
237 if(this.closed)
238 return;
239
240 parentObject.selectWindow(this);
241 }.bind(this));
242
243 if(type != qwebirc.ui.WINDOW_STATUS && type != qwebirc.ui.WINDOW_CONNECT) {
244 var tabclose = new Element("span");
245 tabclose.set("text", "X");
246 tabclose.addClass("tabclose");
247 var close = function(e) {
248 new Event(e).stop();
249
250 if(this.closed)
251 return;
252
253 if(type == qwebirc.ui.WINDOW_CHANNEL)
254 this.client.exec("/PART " + name);
255
256 this.close();
257
258 parentObject.inputbox.focus();
259 }.bind(this);
260
261 tabclose.addEvent("click", close);
262 this.tab.addEvent("mouseup", function(e) {
263 var button = 1;
264
265 if(Browser.Engine.trident)
266 button = 4;
267
268 if(e.event.button == button)
269 close(e);
270 }.bind(this));
271
272 this.tab.appendChild(tabclose);
273 }
274
275 this.lines = new Element("div");
276 this.parentObject.qjsui.applyClasses("middle", this.lines);
277 this.lines.addClass("lines");
278
279 this.lines.addEvent("scroll", function() {
280 this.scrolleddown = this.scrolledDown();
281 this.scrollpos = this.getScrollParent().getScroll();
282 }.bind(this));
283
284 if(type == qwebirc.ui.WINDOW_CHANNEL) {
285 this.topic = new Element("div");
286 this.topic.addClass("topic");
287 this.topic.addClass("tab-invisible");
288 this.topic.set("html", "&nbsp;");
289 this.parentObject.qjsui.applyClasses("topic", this.topic);
290
291 this.prevNick = null;
292 this.nicklist = new Element("div");
293 this.nicklist.addClass("nicklist");
294 this.nicklist.addClass("tab-invisible");
295 this.nicklist.addEvent("click", this.removePrevMenu.bind(this));
296 this.parentObject.qjsui.applyClasses("nicklist", this.nicklist);
297 }
298
299 if(type == qwebirc.ui.WINDOW_CHANNEL) {
300 this.updateTopic("");
301 } else {
302 this.reflow();
303 }
304 },
305 reflow: function() {
306 this.parentObject.reflow();
307 },
308 onResize: function() {
309 if(this.scrolleddown) {
310 if(Browser.Engine.trident) {
311 this.scrollToBottom.delay(5, this);
312 } else {
313 this.scrollToBottom();
314 }
315 } else if($defined(this.scrollpos)) {
316 if(Browser.Engine.trident) {
317 this.getScrollParent().scrollTo(this.scrollpos.x, this.scrollpos.y);
318 } else {
319 this.getScrollParent().scrollTo.delay(5, this, [this.scrollpos.x, this.scrollpos.y]);
320 }
321 }
322 },
323 createMenu: function(nick, parent) {
324 var e = new Element("div");
325 parent.appendChild(e);
326 e.addClass("menu");
327
328 qwebirc.ui.MENU_ITEMS.forEach(function(x) {
329 var e2 = new Element("a");
330 e.appendChild(e2);
331
332 e2.href = "#";
333 e2.set("text", "- " + x[0]);
334
335 e2.addEvent("focus", function() { this.blur() }.bind(e2));
336 e2.addEvent("click", function(ev) { new Event(ev.stop()); this.menuClick(x[1]); }.bind(this));
337 }.bind(this));
338 return e;
339 },
340 menuClick: function(fn) {
341 /*
342 this.prevNick.removeChild(this.prevNick.menu);
343 this.prevNick.menu = null;
344 */
345 fn.bind(this)(this.prevNick.realNick);
346 this.removePrevMenu();
347 },
348 moveMenuClass: function() {
349 if(!this.prevNick)
350 return;
351 if(this.nicklist.firstChild == this.prevNick) {
352 this.prevNick.removeClass("selected-middle");
353 } else {
354 this.prevNick.addClass("selected-middle");
355 }
356 },
357 removePrevMenu: function() {
358 if(!this.prevNick)
359 return;
360
361 this.prevNick.removeClass("selected");
362 this.prevNick.removeClass("selected-middle");
363 if(this.prevNick.menu)
364 this.prevNick.removeChild(this.prevNick.menu);
365 this.prevNick = null;
366 },
367 nickListAdd: function(nick, position) {
368 var e = new Element("a");
369 qwebirc.ui.insertAt(position, this.nicklist, e);
370
371 e.href = "#";
372 e.appendChild(document.createTextNode(nick));
373
374 e.realNick = this.client.stripPrefix(nick);
375
376 e.addEvent("click", function(x) {
377 if(this.prevNick == e) {
378 this.removePrevMenu();
379 return;
380 }
381
382 this.removePrevMenu();
383 this.prevNick = e;
384 e.addClass("selected");
385 this.moveMenuClass();
386 e.menu = this.createMenu(x.realNick, e);
387 new Event(x).stop();
388 }.bind(this));
389 e.addEvent("dblclick", function(x) {
390 new Event(x).stop();
391 this.client.exec("/QUERY " + e.realNick);
392 }.bind(this));
393
394 e.addEvent("focus", function() { this.blur() }.bind(e));
395 this.moveMenuClass();
396 return e;
397 },
398 nickListRemove: function(nick, stored) {
399 this.nicklist.removeChild(stored);
400 this.moveMenuClass();
401 },
402 updateTopic: function(topic) {
403 var t = this.topic;
404
405 while(t.firstChild)
406 t.removeChild(t.firstChild);
407
408 if(topic) {
409 this.parent(topic, t);
410 } else {
411 var e = new Element("div");
412 e.set("text", "(no topic set)");
413 e.addClass("emptytopic");
414 t.appendChild(e);
415 }
416 this.reflow();
417 },
418 select: function() {
419 var inputVisible = this.type != qwebirc.ui.WINDOW_CONNECT && this.type != qwebirc.ui.WINDOW_CUSTOM;
420
421 this.tab.removeClass("tab-unselected");
422 this.tab.addClass("tab-selected");
423
424 this.parentObject.setLines(this.lines);
425 this.parentObject.setChannelItems(this.nicklist, this.topic);
426 this.parentObject.qjsui.showInput(inputVisible);
427 this.parentObject.qjsui.showChannel($defined(this.nicklist));
428
429 this.reflow();
430
431 this.parent();
432
433 if(inputVisible)
434 this.parentObject.inputbox.focus();
435 },
436 deselect: function() {
437 this.parent();
438
439 this.tab.removeClass("tab-selected");
440 this.tab.addClass("tab-unselected");
441 },
442 close: function() {
443 this.parent();
444
445 this.parentObject.tabs.removeChild(this.tab);
446 },
447 addLine: function(type, line, colour) {
448 var e = new Element("div");
449
450 if(colour) {
451 e.setStyles({"background": colour});
452 } else if(this.lastcolour) {
453 e.addClass("linestyle1");
454 } else {
455 e.addClass("linestyle2");
456 }
457 this.lastcolour = !this.lastcolour;
458
459 this.parent(type, line, colour, e);
460 },
461 setHilighted: function(state) {
462 laststate = this.hilighted;
463
464 this.parent(state);
465
466 if(state == laststate)
467 return;
468
469 this.tab.removeClass("tab-hilight-activity");
470 this.tab.removeClass("tab-hilight-us");
471 this.tab.removeClass("tab-hilight-speech");
472
473 switch(this.hilighted) {
474 case qwebirc.ui.HILIGHT_US:
475 this.tab.addClass("tab-hilight-us");
476 break;
477 case qwebirc.ui.HILIGHT_SPEECH:
478 this.tab.addClass("tab-hilight-speech");
479 break;
480 case qwebirc.ui.HILIGHT_ACTIVITY:
481 this.tab.addClass("tab-hilight-activity");
482 break;
483 }
484 }
485 });