]> jfr.im git - irc/quakenet/qwebirc.git/blame_incremental - js/ui/baseui.js
Split fetching and applying of options.
[irc/quakenet/qwebirc.git] / js / ui / baseui.js
... / ...
CommitLineData
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;
6qwebirc.ui.WINDOW_MESSAGES = 0x20;
7
8qwebirc.ui.CUSTOM_CLIENT = "custom";
9
10qwebirc.ui.BaseUI = new Class({
11 Implements: [Events],
12 initialize: function(parentElement, windowClass, uiName, options) {
13 this.options = options;
14
15 this.windows = {};
16 this.clients = {};
17 this.windows[qwebirc.ui.CUSTOM_CLIENT] = {};
18 this.windowArray = [];
19 this.windowClass = windowClass;
20 this.parentElement = parentElement;
21 this.parentElement.addClass("qwebirc");
22 this.parentElement.addClass("qwebirc-" + uiName);
23 this.firstClient = false;
24 this.commandhistory = new qwebirc.irc.CommandHistory();
25 this.clientId = 0;
26
27 this.windowFocused = true;
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 }
50 },
51 newClient: function(client) {
52 client.id = this.clientId++;
53 client.hilightController = new qwebirc.ui.HilightController(client);
54
55 this.windows[client.id] = {}
56 this.clients[client.id] = client;
57 var w = this.newWindow(client, qwebirc.ui.WINDOW_STATUS, "Status");
58 this.selectWindow(w);
59 if(!this.firstClient) {
60 this.firstClient = true;
61 w.addLine("", "qwebirc v" + qwebirc.VERSION);
62 w.addLine("", "Copyright (C) 2008-2011 Chris Porter and the qwebirc project.");
63 w.addLine("", "http://www.qwebirc.org");
64 w.addLine("", "Licensed under the GNU General Public License, Version 2.");
65 }
66 return w;
67 },
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 },
75 getWindowIdentifier: function(client, type, name) {
76 if(type == qwebirc.ui.WINDOW_MESSAGES)
77 return "-M";
78 if(type == qwebirc.ui.WINDOW_STATUS)
79 return "";
80
81 if(client == qwebirc.ui.CUSTOM_CLIENT) /* HACK */
82 return "_" + name;
83
84 return "_" + client.toIRCLower(name);
85 },
86 newWindow: function(client, type, name) {
87 var w = this.getWindow(client, type, name);
88 if($defined(w))
89 return w;
90
91 var wId = this.getWindowIdentifier(client, type, name);
92 var w = this.windows[this.getClientId(client)][wId] = new this.windowClass(this, client, type, name, wId);
93 this.windowArray.push(w);
94
95 return w;
96 },
97 getWindow: function(client, type, name) {
98 var c = this.windows[this.getClientId(client)];
99 if(!$defined(c))
100 return null;
101
102 return c[this.getWindowIdentifier(client, type, name)];
103 },
104 getActiveWindow: function() {
105 return this.active;
106 },
107 getActiveIRCWindow: function(client) {
108 if(!this.active || this.active.type == qwebirc.ui.WINDOW_CUSTOM) {
109 return this.windows[this.getClientId(client)][this.getWindowIdentifier(client, qwebirc.ui.WINDOW_STATUS)];
110 } else {
111 return this.active;
112 }
113 },
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 */
121 this.updateTitle(window.name + " - " + this.options.appTitle);
122 },
123 updateTitle: function(text) {
124 document.title = text;
125 },
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 },
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);
156 if(index == -1) {
157 return;
158 } else if(index == 0) {
159 this.selectWindow(this.windowArray[1]);
160 } else {
161 this.selectWindow(this.windowArray[index - 1]);
162 }
163 }
164 }
165
166 this.windowArray = this.windowArray.erase(window);
167 delete this.windows[this.getClientId(window.client)][window.identifier];
168 },
169 /*
170 this shouldn't be called by overriding classes!
171 they should implement their own!
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 */
176 loginBox: function(callback, initialNickname, initialChannels, autoConnect, autoNick) {
177 qwebirc.ui.GenericLoginBox(this.parentElement, callback, initialNickname, initialChannels, autoConnect, autoNick, this.options.networkName);
178 },
179 focusChange: function(newValue) {
180 var window_ = this.getActiveWindow();
181 if($defined(window_))
182 window_.focusChange(newValue);
183 }
184});
185
186qwebirc.ui.StandardUI = new Class({
187 Extends: qwebirc.ui.BaseUI,
188 UICommands: qwebirc.ui.UI_COMMANDS,
189 initialize: function(parentElement, windowClass, uiName, options) {
190 this.parent(parentElement, windowClass, uiName, options);
191
192 this.tabCompleter = new qwebirc.ui.TabCompleterFactory(this);
193 this.uiOptions = new qwebirc.ui.DefaultOptionsClass(this, options.uiOptionsArg);
194 this.customWindows = {};
195
196 var ev;
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;
223 }
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
233
234 number = number - 1;
235
236 if(number >= this.windowArray.length)
237 return;
238
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) {
251 if($$("input").indexOf(x.target) == -1 && $$("textarea").indexOf(x.target) == -1)
252 return false;
253 return true;
254 },
255 newCustomWindow: function(name, select, type) {
256 if(!type)
257 type = qwebirc.ui.WINDOW_CUSTOM;
258
259 var w = this.newWindow(qwebirc.ui.CUSTOM_CLIENT, type, name);
260 w.addEvent("close", function(w) {
261 delete this.windows[qwebirc.ui.CUSTOM_CLIENT][w.identifier];
262 }.bind(this));
263
264 if(select)
265 this.selectWindow(w);
266
267 return w;
268 },
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]);
275 return;
276 }
277
278 var d = this.newCustomWindow(windowName, true);
279 this.customWindows[windowName] = d;
280
281 d.addEvent("close", function() {
282 this.customWindows[windowName] = null;
283 }.bind(this));
284
285 if(cssClass)
286 d.lines.addClass("qwebirc-" + cssClass);
287
288 var ew = new class_(d.lines, options);
289 ew.addEvent("close", function() {
290 d.close();
291 }.bind(this));
292
293 d.setSubWindow(ew);
294 },
295 embeddedWindow: function() {
296 this.addCustomWindow("Add webchat to your site", qwebirc.ui.EmbedWizard, "embeddedwizard", {baseURL: this.options.baseURL, uiOptions: this.uiOptions, optionsCallback: function() {
297 this.optionsWindow();
298 }.bind(this)});
299 },
300 optionsWindow: function() {
301 this.addCustomWindow("Options", qwebirc.ui.OptionsPane, "optionspane", this.uiOptions);
302 },
303 aboutWindow: function() {
304 this.addCustomWindow("About", qwebirc.ui.AboutPane, "aboutpane", this.uiOptions);
305 },
306 privacyWindow: function() {
307 this.addCustomWindow("Privacy policy", qwebirc.ui.PrivacyPolicyPane, "privacypolicypane", this.uiOptions);
308 },
309 feedbackWindow: function() {
310 this.addCustomWindow("Feedback", qwebirc.ui.FeedbackPane, "feedbackpane", this.uiOptions);
311 },
312 faqWindow: function() {
313 this.addCustomWindow("FAQ", qwebirc.ui.FAQPane, "faqpane", this.uiOptions);
314 },
315 urlDispatcher: function(name, window) {
316 if(name == "embedded")
317 return ["a", this.embeddedWindow.bind(this)];
318
319 if(name == "options")
320 return ["a", this.optionsWindow.bind(this)];
321
322 /* doesn't really belong here */
323 if(name == "whois") {
324 return ["span", function(nick) {
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)];
331 }
332
333 return null;
334 },
335 tabComplete: function(element) {
336 this.tabCompleter.tabComplete(element);
337 },
338 resetTabComplete: function() {
339 this.tabCompleter.reset();
340 },
341 setModifiableStylesheet: function(name) {
342 this.__styleSheet = new qwebirc.ui.style.ModifiableStylesheet(qwebirc.global.staticBaseURL + "css/" + name + qwebirc.FILE_SUFFIX + ".mcss");
343
344 this.setModifiableStylesheetValues($defined(this.options.hue) ? this.options.hue : this.uiOptions.STYLE_HUE, $defined(this.options.saturation) ? this.options.saturation : 0, $defined(this.options.lightness) ? this.options.lightness : 0);
345 },
346 setModifiableStylesheetValues: function(hue, saturation, lightness) {
347 if(!$defined(this.__styleSheet))
348 return;
349 this.__styleSheet.set(function(x) {
350 return x.setHue(hue).setSaturation(x.hsb[1] + saturation).setBrightness(x.hsb[2] + lightness);
351 });
352 }
353});
354
355qwebirc.ui.NotificationUI = new Class({
356 Extends: qwebirc.ui.StandardUI,
357 initialize: function(parentElement, windowClass, uiName, options) {
358 this.parent(parentElement, windowClass, uiName, options);
359
360 this.__beeper = new qwebirc.ui.Beeper(this.uiOptions);
361 this.__flasher = new qwebirc.ui.Flasher(this.uiOptions);
362
363 this.beep = this.__beeper.beep.bind(this.__beeper);
364
365 this.flash = this.__flasher.flash.bind(this.__flasher);
366 this.cancelFlash = this.__flasher.cancelFlash.bind(this.__flasher);
367 },
368 setBeepOnMention: function(value) {
369 if(value)
370 this.__beeper.soundInit();
371 },
372 updateTitle: function(text) {
373 if(this.__flasher.updateTitle(text))
374 this.parent(text);
375 },
376 focusChange: function(value) {
377 this.parent(value);
378 this.__flasher.focusChange(value);
379 }
380});
381
382qwebirc.ui.NewLoginUI = new Class({
383 Extends: qwebirc.ui.NotificationUI,
384 loginBox: function(callbackfn, initialNickname, initialChannels, autoConnect, autoNick) {
385 this.postInitialize();
386
387 /* I'd prefer something shorter and snappier! */
388 var w = this.newCustomWindow("Connection details", true, qwebirc.ui.WINDOW_CONNECT);
389 var callback = function(args) {
390 w.close();
391 callbackfn(args);
392 };
393
394 qwebirc.ui.GenericLoginBox(w.lines, callback, initialNickname, initialChannels, autoConnect, autoNick, this.options.networkName);
395 }
396});
397
398qwebirc.ui.QuakeNetUI = new Class({
399 Extends: qwebirc.ui.NewLoginUI,
400 urlDispatcher: function(name, window) {
401 if(name == "qwhois") {
402 return ["span", function(auth) {
403 this.client.exec("/MSG Q whois #" + auth);
404 }.bind(window)];
405 }
406 return this.parent(name, window);
407 },
408 logout: function() {
409 if(!qwebirc.auth.loggedin())
410 return;
411 if(confirm("Log out?")) {
412 for(var client in this.clients) {
413 this.clients[client].quit("Logged out");
414 };
415
416 /* HACK */
417 var foo = function() { document.location = qwebirc.global.dynamicBaseURL + "auth?logout=1"; };
418 foo.delay(500);
419 }
420 }
421});
422
423qwebirc.ui.RootUI = qwebirc.ui.QuakeNetUI;
424
425qwebirc.ui.RequestTransformHTML = function(options) {
426 var HREF_ELEMENTS = {
427 "IMG": 1
428 };
429
430 var update = options.update;
431 var onSuccess = options.onSuccess;
432
433 var fixUp = function(node) {
434 if(node.nodeType != 1)
435 return;
436
437 var tagName = node.nodeName.toUpperCase();
438 if(HREF_ELEMENTS[tagName]) {
439 var attr = node.getAttribute("transform_attr");
440 var value = node.getAttribute("transform_value");
441 if($defined(attr) && $defined(value)) {
442 node.removeAttribute("transform_attr");
443 node.removeAttribute("transform_value");
444 node.setAttribute(attr, qwebirc.global.staticBaseURL + value);
445 }
446 }
447
448 for(var i=0;i<node.childNodes.length;i++)
449 fixUp(node.childNodes[i]);
450 };
451
452 delete options["update"];
453 options.onSuccess = function(tree, elements, html, js) {
454 var container = new Element("div");
455 container.set("html", html);
456 fixUp(container);
457 update.empty();
458
459 while(container.childNodes.length > 0) {
460 var x = container.firstChild;
461 container.removeChild(x);
462 update.appendChild(x);
463 }
464 onSuccess();
465 };
466
467 return new Request.HTML(options);
468};
469