]> jfr.im git - irc/quakenet/qwebirc.git/blame - js/ui/baseui.js
add some stupid logging
[irc/quakenet/qwebirc.git] / js / ui / baseui.js
CommitLineData
3e66d49c
CP
1qwebirc.ui.WINDOW_STATUS = 0x01;
2qwebirc.ui.WINDOW_QUERY = 0x02;
3qwebirc.ui.WINDOW_CHANNEL = 0x04;
4qwebirc.ui.WINDOW_CUSTOM = 0x08;
5qwebirc.ui.WINDOW_CONNECT = 0x10;
8c3e644b 6qwebirc.ui.WINDOW_MESSAGES = 0x20;
3e66d49c 7
e20e5a6b 8qwebirc.ui.CUSTOM_CLIENT = "custom";
9e769c12 9
e20e5a6b 10qwebirc.ui.BaseUI = new Class({
2cad083e 11 Implements: [Events],
a59dc700 12 initialize: function(parentElement, windowClass, uiName, options) {
2cad083e 13 this.options = options;
a59dc700 14
9e769c12 15 this.windows = {};
ffbb638d 16 this.clients = {};
e20e5a6b 17 this.windows[qwebirc.ui.CUSTOM_CLIENT] = {};
9e769c12
CP
18 this.windowArray = [];
19 this.windowClass = windowClass;
20 this.parentElement = parentElement;
21 this.parentElement.addClass("qwebirc");
22 this.parentElement.addClass("qwebirc-" + uiName);
e8db8558 23 this.firstClient = false;
e20e5a6b 24 this.commandhistory = new qwebirc.irc.CommandHistory();
ffbb638d 25 this.clientId = 0;
eb271d86
CP
26
27 this.windowFocused = true;
85449eee
CP
28
29 if(Browser.Engine.trident) {
30 var checkFocus = function() {
31 var hasFocus = document.hasFocus();
32 if(hasFocus != this.windowFocused) {
33 this.windowFocused = hasFocus;
34 this.focusChange(hasFocus);
35 }
36 }
37
38 checkFocus.periodical(100, this);
39 } else {
40 var blur = function() { if(this.windowFocused) { this.windowFocused = false; this.focusChange(false); } }.bind(this);
41 var focus = function() { if(!this.windowFocused) { this.windowFocused = true; this.focusChange(true); } }.bind(this);
42
43 /* firefox requires both */
44
45 document.addEvent("blur", blur);
46 window.addEvent("blur", blur);
47 document.addEvent("focus", focus);
48 window.addEvent("focus", focus);
49 }
e87f9924
CP
50
51 qwebirc.util.__log = function(x) {
52 if(QWEBIRC_DEBUG) {
53 if(typeof console != "undefined")
54 console.log(x);
55 this.getActiveWindow().addLine(null, x);
56 }
57 }.bind(this);
9e769c12
CP
58 },
59 newClient: function(client) {
ffbb638d 60 client.id = this.clientId++;
96f28062
CP
61 client.hilightController = new qwebirc.ui.HilightController(client);
62
ffbb638d
CP
63 this.windows[client.id] = {}
64 this.clients[client.id] = client;
e20e5a6b 65 var w = this.newWindow(client, qwebirc.ui.WINDOW_STATUS, "Status");
9e769c12 66 this.selectWindow(w);
e8db8558
CP
67 if(!this.firstClient) {
68 this.firstClient = true;
e20e5a6b 69 w.addLine("", "qwebirc v" + qwebirc.VERSION);
f191a80b 70 w.addLine("", "Copyright (C) 2008-2012 Chris Porter and the qwebirc project.");
2dfab0e1
CP
71 w.addLine("", "http://www.qwebirc.org");
72 w.addLine("", "Licensed under the GNU General Public License, Version 2.");
e8db8558 73 }
9e769c12
CP
74 return w;
75 },
ffbb638d
CP
76 getClientId: function(client) {
77 if(client == qwebirc.ui.CUSTOM_CLIENT) {
78 return qwebirc.ui.CUSTOM_CLIENT;
79 } else {
80 return client.id;
81 }
82 },
fd3734d4 83 getWindowIdentifier: function(client, type, name) {
f74802c5
CP
84 if(type == qwebirc.ui.WINDOW_MESSAGES)
85 return "-M";
e20e5a6b 86 if(type == qwebirc.ui.WINDOW_STATUS)
f74802c5 87 return "";
fd3734d4
CP
88
89 if(client == qwebirc.ui.CUSTOM_CLIENT) /* HACK */
90 return "_" + name;
91
92 return "_" + client.toIRCLower(name);
f74802c5
CP
93 },
94 newWindow: function(client, type, name) {
95 var w = this.getWindow(client, type, name);
96 if($defined(w))
97 return w;
9e769c12 98
fd3734d4 99 var wId = this.getWindowIdentifier(client, type, name);
f74802c5 100 var w = this.windows[this.getClientId(client)][wId] = new this.windowClass(this, client, type, name, wId);
9e769c12
CP
101 this.windowArray.push(w);
102
103 return w;
104 },
f74802c5
CP
105 getWindow: function(client, type, name) {
106 var c = this.windows[this.getClientId(client)];
107 if(!$defined(c))
108 return null;
109
fd3734d4 110 return c[this.getWindowIdentifier(client, type, name)];
f74802c5 111 },
9e769c12
CP
112 getActiveWindow: function() {
113 return this.active;
114 },
1d42a76f
CP
115 getActiveIRCWindow: function(client) {
116 if(!this.active || this.active.type == qwebirc.ui.WINDOW_CUSTOM) {
fd3734d4 117 return this.windows[this.getClientId(client)][this.getWindowIdentifier(client, qwebirc.ui.WINDOW_STATUS)];
1d42a76f
CP
118 } else {
119 return this.active;
120 }
121 },
9e769c12
CP
122 __setActiveWindow: function(window) {
123 this.active = window;
124 },
5aa173fb
CP
125 renameWindow: function(window, name) {
126 if(this.getWindow(window.client, window.type, name))
127 return null;
128
129 var clientId = this.getClientId(window.client);
130 var index = this.windowArray.indexOf(window);
131 if(index == -1)
132 return null;
133
134 delete this.windows[clientId][window.identifier];
135
136 var window = this.windowArray[index];
137 window.name = name;
138 window.identifier = this.getWindowIdentifier(window.client, window.type, window.name);
139
140 this.windows[clientId][window.identifier] = this.windowArray[index];
141
142 if(window.active)
143 this.updateTitle(window.name + " - " + this.options.appTitle);
144
145 window.rename(window.name);
146 return window;
147 },
9e769c12
CP
148 selectWindow: function(window) {
149 if(this.active)
150 this.active.deselect();
151 window.select(); /* calls setActiveWindow */
326478c2
CP
152 this.updateTitle(window.name + " - " + this.options.appTitle);
153 },
154 updateTitle: function(text) {
155 document.title = text;
9e769c12 156 },
ff4befd8
CP
157 nextWindow: function(direction) {
158 if(this.windowArray.length == 0 || !this.active)
159 return;
160
161 if(!direction)
162 direction = 1;
163
164 var index = this.windowArray.indexOf(this.active);
165 if(index == -1)
166 return;
167
168 index = index + direction;
169 if(index < 0) {
170 index = this.windowArray.length - 1;
171 } else if(index >= this.windowArray.length) {
172 index = 0;
173 }
174
175 this.selectWindow(this.windowArray[index]);
176 },
177 prevWindow: function() {
178 this.nextWindow(-1);
179 },
9e769c12
CP
180 __closed: function(window) {
181 if(window.active) {
182 this.active = undefined;
183 if(this.windowArray.length == 1) {
184 this.windowArray = [];
185 } else {
186 var index = this.windowArray.indexOf(window);
6f2e4a37
CP
187 if(index == -1) {
188 return;
189 } else if(index == 0) {
9e769c12
CP
190 this.selectWindow(this.windowArray[1]);
191 } else {
192 this.selectWindow(this.windowArray[index - 1]);
193 }
9e769c12
CP
194 }
195 }
196
404cfb58 197 this.windowArray = this.windowArray.erase(window);
ffbb638d 198 delete this.windows[this.getClientId(window.client)][window.identifier];
eb9b087b 199 },
eb9b087b
CP
200 /*
201 this shouldn't be called by overriding classes!
66de775f 202 they should implement their own!
eb9b087b
CP
203 some form of user input MUST be received before an
204 IRC connection is made, else users are going to get
205 tricked into getting themselves glined
206 */
66de775f 207 loginBox: function(callback, initialNickname, initialChannels, autoConnect, autoNick) {
2cad083e 208 qwebirc.ui.GenericLoginBox(this.parentElement, callback, initialNickname, initialChannels, autoConnect, autoNick, this.options.networkName);
eb271d86
CP
209 },
210 focusChange: function(newValue) {
211 var window_ = this.getActiveWindow();
212 if($defined(window_))
213 window_.focusChange(newValue);
9e769c12
CP
214 }
215});
381fddfd 216
e20e5a6b
CP
217qwebirc.ui.StandardUI = new Class({
218 Extends: qwebirc.ui.BaseUI,
f3d0c9f5 219 UICommands: qwebirc.ui.UI_COMMANDS,
381fddfd
CP
220 initialize: function(parentElement, windowClass, uiName, options) {
221 this.parent(parentElement, windowClass, uiName, options);
3184781b
CP
222
223 this.tabCompleter = new qwebirc.ui.TabCompleterFactory(this);
c0f2f367 224 this.uiOptions = new qwebirc.ui.DefaultOptionsClass(this, options.uiOptionsArg);
ebb21d2e
CP
225 this.customWindows = {};
226
6f8a20df
CP
227 this.__styleValues = {hue: this.uiOptions.STYLE_HUE, saturation: 0, lightness: 0};
228 if($defined(this.options.hue)) this.__styleValues.hue = this.options.hue;
229 if($defined(this.options.saturation)) this.__styleValues.saturation = this.options.saturation;
230 if($defined(this.options.lightness)) this.__styleValues.lightness = this.options.lightness;
656385a2
CP
231
232 if(this.options.thue !== null) this.__styleValues.textHue = this.options.thue;
233 if(this.options.tsaturation !== null) this.__styleValues.textSaturation = this.options.tsaturation;
234 if(this.options.tlightness !== null) this.__styleValues.textLightness = this.options.tlightness;
6f8a20df 235
2a802692 236 var ev;
20157c51
CP
237 if(Browser.Engine.trident) {
238 ev = "keydown";
239 } else {
240 ev = "keypress";
241 }
242 document.addEvent(ev, this.__handleHotkey.bind(this));
243 },
244 __handleHotkey: function(x) {
245 if(!x.alt || x.control) {
246 if(x.key == "backspace" || x.key == "/")
247 if(!this.getInputFocused(x))
248 new Event(x).stop();
249 return;
250 }
251 var success = false;
252 if(x.key == "a" || x.key == "A") {
253 var highestNum = 0;
254 var highestIndex = -1;
255 success = true;
256
257 new Event(x).stop();
258 for(var i=0;i<this.windowArray.length;i++) {
259 var h = this.windowArray[i].hilighted;
260 if(h > highestNum) {
261 highestIndex = i;
262 highestNum = h;
381fddfd 263 }
20157c51
CP
264 }
265 if(highestIndex > -1)
266 this.selectWindow(this.windowArray[highestIndex]);
267 } else if(x.key >= '0' && x.key <= '9') {
268 success = true;
269
270 number = x.key - '0';
271 if(number == 0)
272 number = 10
424608ac 273
20157c51
CP
274 number = number - 1;
275
276 if(number >= this.windowArray.length)
277 return;
381fddfd 278
20157c51
CP
279 this.selectWindow(this.windowArray[number]);
280 } else if(x.key == "left") {
281 this.prevWindow();
282 success = true;
283 } else if(x.key == "right") {
284 this.nextWindow();
285 success = true;
286 }
287 if(success)
288 new Event(x).stop();
289 },
290 getInputFocused: function(x) {
deebe19a
CP
291 if($$("input").indexOf(x.target) == -1 && $$("textarea").indexOf(x.target) == -1)
292 return false;
293 return true;
841a451d 294 },
8af49135
CP
295 newCustomWindow: function(name, select, type) {
296 if(!type)
e20e5a6b 297 type = qwebirc.ui.WINDOW_CUSTOM;
8af49135 298
e20e5a6b 299 var w = this.newWindow(qwebirc.ui.CUSTOM_CLIENT, type, name);
8af49135 300 w.addEvent("close", function(w) {
f74802c5 301 delete this.windows[qwebirc.ui.CUSTOM_CLIENT][w.identifier];
8af49135
CP
302 }.bind(this));
303
304 if(select)
305 this.selectWindow(w);
6c19eb8f 306
8af49135
CP
307 return w;
308 },
ebb21d2e
CP
309 addCustomWindow: function(windowName, class_, cssClass, options) {
310 if(!$defined(options))
311 options = {};
312
313 if(this.customWindows[windowName]) {
314 this.selectWindow(this.customWindows[windowName]);
8af49135 315 return;
841a451d 316 }
8af49135 317
ebb21d2e
CP
318 var d = this.newCustomWindow(windowName, true);
319 this.customWindows[windowName] = d;
320
321 d.addEvent("close", function() {
322 this.customWindows[windowName] = null;
8af49135
CP
323 }.bind(this));
324
ebb21d2e 325 if(cssClass)
e1a91a8a 326 d.lines.addClass("qwebirc-" + cssClass);
ebb21d2e
CP
327
328 var ew = new class_(d.lines, options);
8af49135 329 ew.addEvent("close", function() {
ebb21d2e 330 d.close();
8af49135 331 }.bind(this));
17f40fd9
CP
332
333 d.setSubWindow(ew);
841a451d 334 },
ebb21d2e 335 embeddedWindow: function() {
bcd2d24f 336 this.addCustomWindow("Add webchat to your site", qwebirc.ui.EmbedWizard, "embeddedwizard", {baseURL: this.options.baseURL, uiOptions: this.uiOptions, optionsCallback: function() {
c0f2f367
CP
337 this.optionsWindow();
338 }.bind(this)});
ebb21d2e
CP
339 },
340 optionsWindow: function() {
341 this.addCustomWindow("Options", qwebirc.ui.OptionsPane, "optionspane", this.uiOptions);
342 },
e1a91a8a
CP
343 aboutWindow: function() {
344 this.addCustomWindow("About", qwebirc.ui.AboutPane, "aboutpane", this.uiOptions);
345 },
b35116e2
CP
346 privacyWindow: function() {
347 this.addCustomWindow("Privacy policy", qwebirc.ui.PrivacyPolicyPane, "privacypolicypane", this.uiOptions);
348 },
391f51ff
CP
349 feedbackWindow: function() {
350 this.addCustomWindow("Feedback", qwebirc.ui.FeedbackPane, "feedbackpane", this.uiOptions);
351 },
f3d0c9f5
CP
352 faqWindow: function() {
353 this.addCustomWindow("FAQ", qwebirc.ui.FAQPane, "faqpane", this.uiOptions);
354 },
144ee52f 355 urlDispatcher: function(name, window) {
8af49135 356 if(name == "embedded")
925fc357 357 return ["a", this.embeddedWindow.bind(this)];
ebb21d2e
CP
358
359 if(name == "options")
360 return ["a", this.optionsWindow.bind(this)];
8af49135 361
5f2808af
CP
362 /* doesn't really belong here */
363 if(name == "whois") {
364 return ["span", function(nick) {
cbef082a
CP
365 if(this.uiOptions.QUERY_ON_NICK_CLICK) {
366 window.client.exec("/QUERY " + nick);
367 } else {
368 window.client.exec("/WHOIS " + nick);
369 }
370 }.bind(this)];
5f2808af
CP
371 }
372
8af49135 373 return null;
3184781b
CP
374 },
375 tabComplete: function(element) {
376 this.tabCompleter.tabComplete(element);
377 },
378 resetTabComplete: function() {
379 this.tabCompleter.reset();
4dd199c3
CP
380 },
381 setModifiableStylesheet: function(name) {
fbe5af77 382 this.__styleSheet = new qwebirc.ui.style.ModifiableStylesheet(qwebirc.global.staticBaseURL + "css/" + name + qwebirc.FILE_SUFFIX + ".mcss");
6f8a20df 383 this.setModifiableStylesheetValues({});
4dd199c3 384 },
6f8a20df
CP
385 setModifiableStylesheetValues: function(values) {
386 for(var k in values)
387 this.__styleValues[k] = values[k];
388
4dd199c3
CP
389 if(!$defined(this.__styleSheet))
390 return;
6f8a20df 391
656385a2
CP
392 var back = {hue: this.__styleValues.hue, lightness: this.__styleValues.lightness, saturation: this.__styleValues.saturation};
393 var front = {hue: this.__styleValues.textHue, lightness: this.__styleValues.textLightness, saturation: this.__styleValues.textSaturation};
394
395 if(!this.__styleValues.textHue && !this.__styleValues.textLightness && !this.__styleValues.textSaturation)
396 front = back;
397
398 var colours = {
399 back: back,
400 front: front
401 };
402
6f8a20df
CP
403 this.__styleSheet.set(function() {
404 var mode = arguments[0];
405 if(mode == "c") {
656385a2 406 var t = colours[arguments[2]];
6f8a20df 407 var x = new Color(arguments[1]);
656385a2 408 var c = x.setHue(t.hue).setSaturation(x.hsb[1] + t.saturation).setBrightness(x.hsb[2] + t.lightness);
6f8a20df
CP
409 if(c == "255,255,255") /* IE confuses white with transparent... */
410 c = "255,255,254";
411
412 return "rgb(" + c + ")";
413 } else if(mode == "o") {
414 return this.uiOptions[arguments[1]] ? arguments[2] : arguments[3];
415 }
416 }.bind(this));
8af49135 417 }
381fddfd 418});
6f2e4a37 419
326478c2 420qwebirc.ui.NotificationUI = new Class({
e20e5a6b 421 Extends: qwebirc.ui.StandardUI,
fb71087a
CP
422 initialize: function(parentElement, windowClass, uiName, options) {
423 this.parent(parentElement, windowClass, uiName, options);
424
326478c2
CP
425 this.__beeper = new qwebirc.ui.Beeper(this.uiOptions);
426 this.__flasher = new qwebirc.ui.Flasher(this.uiOptions);
fb71087a 427
326478c2 428 this.beep = this.__beeper.beep.bind(this.__beeper);
127631e0 429
326478c2
CP
430 this.flash = this.__flasher.flash.bind(this.__flasher);
431 this.cancelFlash = this.__flasher.cancelFlash.bind(this.__flasher);
fb71087a 432 },
127631e0
CP
433 setBeepOnMention: function(value) {
434 if(value)
326478c2
CP
435 this.__beeper.soundInit();
436 },
437 updateTitle: function(text) {
438 if(this.__flasher.updateTitle(text))
439 this.parent(text);
eb271d86
CP
440 },
441 focusChange: function(value) {
442 this.parent(value);
443 this.__flasher.focusChange(value);
1211ddcd 444 }
fb71087a
CP
445});
446
5f2808af 447qwebirc.ui.NewLoginUI = new Class({
326478c2 448 Extends: qwebirc.ui.NotificationUI,
5f2808af
CP
449 loginBox: function(callbackfn, initialNickname, initialChannels, autoConnect, autoNick) {
450 this.postInitialize();
451
c837b844
CP
452 /* I'd prefer something shorter and snappier! */
453 var w = this.newCustomWindow("Connection details", true, qwebirc.ui.WINDOW_CONNECT);
5f2808af
CP
454 var callback = function(args) {
455 w.close();
456 callbackfn(args);
457 };
458
459 qwebirc.ui.GenericLoginBox(w.lines, callback, initialNickname, initialChannels, autoConnect, autoNick, this.options.networkName);
460 }
461});
462
463qwebirc.ui.QuakeNetUI = new Class({
464 Extends: qwebirc.ui.NewLoginUI,
2cd9e32d
CP
465 urlDispatcher: function(name, window) {
466 if(name == "qwhois") {
7cb09779 467 return ["span", function(auth) {
2cd9e32d 468 this.client.exec("/MSG Q whois #" + auth);
925fc357
CP
469 }.bind(window)];
470 }
144ee52f 471 return this.parent(name, window);
ffbb638d
CP
472 },
473 logout: function() {
474 if(!qwebirc.auth.loggedin())
475 return;
476 if(confirm("Log out?")) {
477 for(var client in this.clients) {
478 this.clients[client].quit("Logged out");
479 };
4b9f894d
CP
480
481 /* HACK */
fbe5af77 482 var foo = function() { document.location = qwebirc.global.dynamicBaseURL + "auth?logout=1"; };
4b9f894d 483 foo.delay(500);
ffbb638d 484 }
2cd9e32d
CP
485 }
486});
144ee52f
CP
487
488qwebirc.ui.RootUI = qwebirc.ui.QuakeNetUI;
fbe5af77
CP
489
490qwebirc.ui.RequestTransformHTML = function(options) {
491 var HREF_ELEMENTS = {
492 "IMG": 1
493 };
494
495 var update = options.update;
496 var onSuccess = options.onSuccess;
497
498 var fixUp = function(node) {
499 if(node.nodeType != 1)
500 return;
501
502 var tagName = node.nodeName.toUpperCase();
503 if(HREF_ELEMENTS[tagName]) {
504 var attr = node.getAttribute("transform_attr");
505 var value = node.getAttribute("transform_value");
506 if($defined(attr) && $defined(value)) {
507 node.removeAttribute("transform_attr");
508 node.removeAttribute("transform_value");
509 node.setAttribute(attr, qwebirc.global.staticBaseURL + value);
510 }
511 }
512
513 for(var i=0;i<node.childNodes.length;i++)
514 fixUp(node.childNodes[i]);
515 };
516
517 delete options["update"];
518 options.onSuccess = function(tree, elements, html, js) {
519 var container = new Element("div");
520 container.set("html", html);
521 fixUp(container);
522 update.empty();
523
524 while(container.childNodes.length > 0) {
525 var x = container.firstChild;
526 container.removeChild(x);
527 update.appendChild(x);
528 }
529 onSuccess();
530 };
531
532 return new Request.HTML(options);
533};
534