]> jfr.im git - irc/quakenet/qwebirc.git/blob - js/ui/baseui.js
Block backspace and /.
[irc/quakenet/qwebirc.git] / js / ui / baseui.js
1 qwebirc.ui.WINDOW_STATUS = 1;
2 qwebirc.ui.WINDOW_QUERY = 2;
3 qwebirc.ui.WINDOW_CHANNEL = 3;
4 qwebirc.ui.WINDOW_CUSTOM = 4;
5 qwebirc.ui.WINDOW_CONNECT = 5;
6 qwebirc.ui.WINDOW_MESSAGES = 6;
7 qwebirc.ui.CUSTOM_CLIENT = "custom";
8
9 qwebirc.ui.BaseUI = new Class({
10 Implements: [Events, Options],
11 options: {
12 appTitle: "QuakeNet Web IRC",
13 singleWindow: true
14 },
15 initialize: function(parentElement, windowClass, uiName, options) {
16 this.setOptions(options);
17
18 this.windows = {};
19 this.clients = {};
20 this.windows[qwebirc.ui.CUSTOM_CLIENT] = {};
21 this.windowArray = [];
22 this.windowClass = windowClass;
23 this.parentElement = parentElement;
24 this.parentElement.addClass("qwebirc");
25 this.parentElement.addClass("qwebirc-" + uiName);
26 this.firstClient = false;
27 this.commandhistory = new qwebirc.irc.CommandHistory();
28 this.clientId = 0;
29 },
30 newClient: function(client) {
31 client.id = this.clientId++;
32 client.hilightController = new qwebirc.ui.HilightController(client);
33
34 this.windows[client.id] = {}
35 this.clients[client.id] = client;
36 var w = this.newWindow(client, qwebirc.ui.WINDOW_STATUS, "Status");
37 this.selectWindow(w);
38 if(!this.firstClient) {
39 this.firstClient = true;
40 w.addLine("", "qwebirc v" + qwebirc.VERSION);
41 w.addLine("", "Copyright (C) 2008 Chris Porter. All rights reserved.");
42 w.addLine("", "http://webchat.quakenet.org/");
43 w.addLine("", "This is BETA quality software, please report bugs to slug@quakenet.org");
44 }
45 return w;
46 },
47 getClientId: function(client) {
48 if(client == qwebirc.ui.CUSTOM_CLIENT) {
49 return qwebirc.ui.CUSTOM_CLIENT;
50 } else {
51 return client.id;
52 }
53 },
54 getWindowIdentifier: function(type, name) {
55 if(type == qwebirc.ui.WINDOW_MESSAGES)
56 return "-M";
57 if(type == qwebirc.ui.WINDOW_STATUS)
58 return "";
59 return "_" + name.toIRCLower();
60 },
61 newWindow: function(client, type, name) {
62 var w = this.getWindow(client, type, name);
63 if($defined(w))
64 return w;
65
66 var wId = this.getWindowIdentifier(type, name);
67 var w = this.windows[this.getClientId(client)][wId] = new this.windowClass(this, client, type, name, wId);
68 this.windowArray.push(w);
69
70 return w;
71 },
72 getWindow: function(client, type, name) {
73 var c = this.windows[this.getClientId(client)];
74 if(!$defined(c))
75 return null;
76
77 return c[this.getWindowIdentifier(type, name)];
78 },
79 getActiveWindow: function() {
80 return this.active;
81 },
82 getActiveIRCWindow: function(client) {
83 if(!this.active || this.active.type == qwebirc.ui.WINDOW_CUSTOM) {
84 return this.windows[this.getClientId(client)][this.getWindowIdentifier(qwebirc.ui.WINDOW_STATUS)];
85 } else {
86 return this.active;
87 }
88 },
89 __setActiveWindow: function(window) {
90 this.active = window;
91 },
92 selectWindow: function(window) {
93 if(this.active)
94 this.active.deselect();
95 window.select(); /* calls setActiveWindow */
96 document.title = window.name + " - " + this.options.appTitle;
97 },
98 nextWindow: function(direction) {
99 if(this.windowArray.length == 0 || !this.active)
100 return;
101
102 if(!direction)
103 direction = 1;
104
105 var index = this.windowArray.indexOf(this.active);
106 if(index == -1)
107 return;
108
109 index = index + direction;
110 if(index < 0) {
111 index = this.windowArray.length - 1;
112 } else if(index >= this.windowArray.length) {
113 index = 0;
114 }
115
116 this.selectWindow(this.windowArray[index]);
117 },
118 prevWindow: function() {
119 this.nextWindow(-1);
120 },
121 __closed: function(window) {
122 if(window.active) {
123 this.active = undefined;
124 if(this.windowArray.length == 1) {
125 this.windowArray = [];
126 } else {
127 var index = this.windowArray.indexOf(window);
128 if(index == -1) {
129 return;
130 } else if(index == 0) {
131 this.selectWindow(this.windowArray[1]);
132 } else {
133 this.selectWindow(this.windowArray[index - 1]);
134 }
135 }
136 }
137
138 this.windowArray = this.windowArray.erase(window);
139 delete this.windows[this.getClientId(window.client)][window.identifier];
140 },
141 /*
142 this shouldn't be called by overriding classes!
143 they should implement their own!
144 some form of user input MUST be received before an
145 IRC connection is made, else users are going to get
146 tricked into getting themselves glined
147 */
148 loginBox: function(callback, initialNickname, initialChannels, autoConnect, autoNick) {
149 qwebirc.ui.GenericLoginBox(this.parentElement, callback, initialNickname, initialChannels, autoConnect, autoNick);
150 }
151 });
152
153 qwebirc.ui.StandardUI = new Class({
154 Extends: qwebirc.ui.BaseUI,
155 initialize: function(parentElement, windowClass, uiName, options) {
156 this.parent(parentElement, windowClass, uiName, options);
157
158 this.tabCompleter = new qwebirc.ui.TabCompleterFactory(this);
159 this.uiOptions = new qwebirc.ui.DefaultOptionsClass(this);
160 this.customWindows = {};
161
162 if(Browser.Engine.trident) {
163 ev = "keydown";
164 } else {
165 ev = "keypress";
166 }
167 document.addEvent(ev, this.__handleHotkey.bind(this));
168 },
169 __handleHotkey: function(x) {
170 if(!x.alt || x.control) {
171 if(x.key == "backspace" || x.key == "/")
172 if(!this.getInputFocused(x))
173 new Event(x).stop();
174 return;
175 }
176 var success = false;
177 if(x.key == "a" || x.key == "A") {
178 var highestNum = 0;
179 var highestIndex = -1;
180 success = true;
181
182 new Event(x).stop();
183 for(var i=0;i<this.windowArray.length;i++) {
184 var h = this.windowArray[i].hilighted;
185 if(h > highestNum) {
186 highestIndex = i;
187 highestNum = h;
188 }
189 }
190 if(highestIndex > -1)
191 this.selectWindow(this.windowArray[highestIndex]);
192 } else if(x.key >= '0' && x.key <= '9') {
193 success = true;
194
195 number = x.key - '0';
196 if(number == 0)
197 number = 10
198
199 number = number - 1;
200
201 if(number >= this.windowArray.length)
202 return;
203
204 this.selectWindow(this.windowArray[number]);
205 } else if(x.key == "left") {
206 this.prevWindow();
207 success = true;
208 } else if(x.key == "right") {
209 this.nextWindow();
210 success = true;
211 }
212 if(success)
213 new Event(x).stop();
214 },
215 getInputFocused: function(x) {
216 return $$("input").indexOf(x.target) > -1;
217 },
218 newCustomWindow: function(name, select, type) {
219 if(!type)
220 type = qwebirc.ui.WINDOW_CUSTOM;
221
222 var w = this.newWindow(qwebirc.ui.CUSTOM_CLIENT, type, name);
223 w.addEvent("close", function(w) {
224 delete this.windows[qwebirc.ui.CUSTOM_CLIENT][w.identifier];
225 }.bind(this));
226
227 if(select)
228 this.selectWindow(w);
229
230 return w;
231 },
232 addCustomWindow: function(windowName, class_, cssClass, options) {
233 if(!$defined(options))
234 options = {};
235
236 if(this.customWindows[windowName]) {
237 this.selectWindow(this.customWindows[windowName]);
238 return;
239 }
240
241 var d = this.newCustomWindow(windowName, true);
242 this.customWindows[windowName] = d;
243
244 d.addEvent("close", function() {
245 this.customWindows[windowName] = null;
246 }.bind(this));
247
248 if(cssClass)
249 d.lines.addClass("qwebirc-" + cssClass);
250
251 var ew = new class_(d.lines, options);
252 ew.addEvent("close", function() {
253 d.close();
254 }.bind(this));
255 },
256 embeddedWindow: function() {
257 this.addCustomWindow("Embedded Wizard", qwebirc.ui.EmbedWizard, "embeddedwizard");
258 },
259 optionsWindow: function() {
260 this.addCustomWindow("Options", qwebirc.ui.OptionsPane, "optionspane", this.uiOptions);
261 },
262 aboutWindow: function() {
263 this.addCustomWindow("About", qwebirc.ui.AboutPane, "aboutpane", this.uiOptions);
264 },
265 urlDispatcher: function(name) {
266 if(name == "embedded")
267 return ["a", this.embeddedWindow.bind(this)];
268
269 if(name == "options")
270 return ["a", this.optionsWindow.bind(this)];
271
272 return null;
273 },
274 tabComplete: function(element) {
275 this.tabCompleter.tabComplete(element);
276 },
277 resetTabComplete: function() {
278 this.tabCompleter.reset();
279 }
280 });
281
282 qwebirc.ui.SoundUI = new Class({
283 Extends: qwebirc.ui.StandardUI,
284 initialize: function(parentElement, windowClass, uiName, options) {
285 this.parent(parentElement, windowClass, uiName, options);
286
287 this.soundInited = false;
288 this.soundReady = false;
289
290 this.setBeepOnMention(this.uiOptions.BEEP_ON_MENTION);
291 },
292 soundInit: function() {
293 if(this.soundInited)
294 return;
295 if(!$defined(Browser.Plugins.Flash) || Browser.Plugins.Flash.version < 8)
296 return;
297 this.soundInited = true;
298
299 this.soundPlayer = new qwebirc.sound.SoundPlayer();
300 this.soundPlayer.addEvent("ready", function() {
301 this.soundReady = true;
302 }.bind(this));
303 this.soundPlayer.go();
304 },
305 setBeepOnMention: function(value) {
306 if(value)
307 this.soundInit();
308 this.beepOnMention = value;
309 },
310 beep: function() {
311 if(!this.soundReady || !this.beepOnMention)
312 return;
313
314 this.soundPlayer.beep();
315 }
316 });
317
318 qwebirc.ui.QuakeNetUI = new Class({
319 Extends: qwebirc.ui.SoundUI,
320 urlDispatcher: function(name, window) {
321 if(name == "qwhois") {
322 return ["span", function(auth) {
323 this.client.exec("/MSG Q whois #" + auth);
324 }.bind(window)];
325 }
326 if(name == "whois") {
327 return ["span", function(nick) {
328 this.client.exec("/WHOIS " + nick);
329 }.bind(window)];
330 }
331 return this.parent(name);
332 },
333 logout: function() {
334 if(!qwebirc.auth.loggedin())
335 return;
336 if(confirm("Log out?")) {
337 for(var client in this.clients) {
338 this.clients[client].quit("Logged out");
339 };
340 document.location = "/auth?logout=1";
341 }
342 }
343 });
344
345 qwebirc.ui.NewLoginUI = new Class({
346 Extends: qwebirc.ui.QuakeNetUI,
347 loginBox: function(callbackfn, initialNickname, initialChannels, autoConnect, autoNick) {
348 this.postInitialize();
349
350 var w = this.newCustomWindow("Connect", true, qwebirc.ui.WINDOW_CONNECT);
351 var callback = function(args) {
352 w.close();
353 callbackfn(args);
354 };
355
356 qwebirc.ui.GenericLoginBox(w.lines, callback, initialNickname, initialChannels, autoConnect, autoNick);
357 }
358 });