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