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