Commit | Line | Data |
---|---|---|
2dd6a025 D |
1 | /*jslint devel: true, browser: true, continue: true, sloppy: true, forin: true, plusplus: true, maxerr: 50, indent: 4, nomen: true, regexp: true*/ |
2 | /*globals $, front, gateway, Utilityview */ | |
3 | ||
2dd6a025 D |
4 | |
5 | ||
2dd6a025 D |
6 | /** |
7 | * Generate a random string of given length | |
8 | * @param {Number} string_length The length of the random string | |
9 | * @returns {String} The random string | |
10 | */ | |
11 | function randomString(string_length) { | |
12 | var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz", | |
13 | randomstring = '', | |
14 | i, | |
15 | rnum; | |
16 | for (i = 0; i < string_length; i++) { | |
17 | rnum = Math.floor(Math.random() * chars.length); | |
18 | randomstring += chars.substring(rnum, rnum + 1); | |
19 | } | |
20 | return randomstring; | |
21 | } | |
22 | ||
23 | /** | |
24 | * String.trim shim | |
25 | */ | |
26 | if (typeof String.prototype.trim === 'undefined') { | |
27 | String.prototype.trim = function () { | |
28 | return this.replace(/^\s+|\s+$/g, ""); | |
29 | }; | |
30 | } | |
31 | ||
32 | /** | |
33 | * String.lpad shim | |
34 | * @param {Number} length The length of padding | |
35 | * @param {String} characher The character to pad with | |
36 | * @returns {String} The padded string | |
37 | */ | |
38 | if (typeof String.prototype.lpad === 'undefined') { | |
39 | String.prototype.lpad = function (length, character) { | |
40 | var padding = "", | |
41 | i; | |
42 | for (i = 0; i < length; i++) { | |
43 | padding += character; | |
44 | } | |
45 | return (padding + this).slice(-length); | |
46 | }; | |
47 | } | |
48 | ||
49 | ||
50 | /** | |
51 | * Convert seconds into hours:minutes:seconds | |
52 | * @param {Number} secs The number of seconds to converts | |
53 | * @returns {Object} An object representing the hours/minutes/second conversion of secs | |
54 | */ | |
55 | function secondsToTime(secs) { | |
56 | var hours, minutes, seconds, divisor_for_minutes, divisor_for_seconds, obj; | |
57 | hours = Math.floor(secs / (60 * 60)); | |
58 | ||
59 | divisor_for_minutes = secs % (60 * 60); | |
60 | minutes = Math.floor(divisor_for_minutes / 60); | |
61 | ||
62 | divisor_for_seconds = divisor_for_minutes % 60; | |
63 | seconds = Math.ceil(divisor_for_seconds); | |
64 | ||
65 | obj = { | |
66 | "h": hours, | |
67 | "m": minutes, | |
68 | "s": seconds | |
69 | }; | |
70 | return obj; | |
71 | } | |
72 | ||
73 | ||
64c6bcb4 D |
74 | /* Command input Alias + re-writing */ |
75 | function InputPreProcessor () { | |
76 | this.recursive_depth = 3; | |
77 | ||
78 | this.aliases = {}; | |
79 | this.vars = {version: 1}; | |
80 | ||
81 | // Current recursive depth | |
82 | var depth = 0; | |
83 | ||
84 | ||
85 | // Takes an array of words to process! | |
86 | this.processInput = function (input) { | |
87 | var words = input || [], | |
88 | alias = this.aliases[words[0]], | |
89 | alias_len, | |
90 | current_alias_word = '', | |
91 | compiled = []; | |
92 | ||
93 | // If an alias wasn't found, return the original input | |
94 | if (!alias) return input; | |
95 | ||
96 | // Split the alias up into useable words | |
97 | alias = alias.split(' '); | |
98 | alias_len = alias.length; | |
99 | ||
100 | // Iterate over each word and pop them into the final compiled array. | |
101 | // Any $ words are processed with the result ending into the compiled array. | |
102 | for (var i=0; i<alias_len; i++) { | |
103 | current_alias_word = alias[i]; | |
104 | ||
105 | // Non $ word | |
106 | if (current_alias_word[0] !== '$') { | |
107 | compiled.push(current_alias_word); | |
108 | continue; | |
109 | } | |
110 | ||
111 | // Refering to an input word ($N) | |
112 | if (!isNaN(current_alias_word[1])) { | |
113 | var num = current_alias_word.match(/\$(\d+)(\+)?(\d+)?/); | |
114 | ||
115 | // Did we find anything or does the word it refers to non-existant? | |
116 | if (!num || !words[num[1]]) continue; | |
64bdb2ff | 117 | |
64c6bcb4 D |
118 | if (num[2] === '+' && num[3]) { |
119 | // Add X number of words | |
120 | compiled = compiled.concat(words.slice(parseInt(num[1], 10), parseInt(num[1], 10) + parseInt(num[3], 10))); | |
121 | } else if (num[2] === '+') { | |
122 | // Add the remaining of the words | |
123 | compiled = compiled.concat(words.slice(parseInt(num[1], 10))); | |
124 | } else { | |
125 | // Add a single word | |
126 | compiled.push(words[parseInt(num[1], 10)]); | |
127 | } | |
128 | ||
129 | continue; | |
130 | } | |
131 | ||
132 | ||
133 | // Refering to a variable | |
134 | if (typeof this.vars[current_alias_word.substr(1)] !== 'undefined') { | |
135 | ||
136 | // Get the variable | |
137 | compiled.push(this.vars[current_alias_word.substr(1)]); | |
138 | ||
139 | continue; | |
140 | } | |
141 | ||
142 | } | |
143 | ||
144 | return compiled; | |
145 | }; | |
146 | ||
147 | ||
148 | this.process = function (input) { | |
149 | input = input || ''; | |
150 | ||
151 | var words = input.split(' '); | |
152 | ||
153 | depth++; | |
154 | if (depth >= this.recursive_depth) { | |
155 | depth--; | |
156 | return input; | |
157 | } | |
158 | ||
159 | if (this.aliases[words[0]]) { | |
160 | words = this.processInput(words); | |
64bdb2ff | 161 | |
64c6bcb4 D |
162 | if (this.aliases[words[0]]) { |
163 | words = this.process(words.join(' ')).split(' '); | |
164 | } | |
165 | ||
166 | } | |
167 | ||
168 | depth--; | |
169 | return words.join(' '); | |
170 | }; | |
171 | } | |
172 | ||
173 | ||
1167a85d D |
174 | /** |
175 | * Convert HSL to RGB formatted colour | |
176 | */ | |
177 | function hsl2rgb(h, s, l) { | |
178 | var m1, m2, hue; | |
179 | var r, g, b | |
180 | s /=100; | |
181 | l /= 100; | |
182 | if (s == 0) | |
183 | r = g = b = (l * 255); | |
184 | else { | |
185 | function HueToRgb(m1, m2, hue) { | |
186 | var v; | |
187 | if (hue < 0) | |
188 | hue += 1; | |
189 | else if (hue > 1) | |
190 | hue -= 1; | |
191 | ||
192 | if (6 * hue < 1) | |
193 | v = m1 + (m2 - m1) * hue * 6; | |
194 | else if (2 * hue < 1) | |
195 | v = m2; | |
196 | else if (3 * hue < 2) | |
197 | v = m1 + (m2 - m1) * (2/3 - hue) * 6; | |
198 | else | |
199 | v = m1; | |
200 | ||
201 | return 255 * v; | |
202 | } | |
203 | if (l <= 0.5) | |
204 | m2 = l * (s + 1); | |
205 | else | |
206 | m2 = l + s - l * s; | |
207 | m1 = l * 2 - m2; | |
208 | hue = h / 360; | |
209 | r = HueToRgb(m1, m2, hue + 1/3); | |
210 | g = HueToRgb(m1, m2, hue); | |
211 | b = HueToRgb(m1, m2, hue - 1/3); | |
212 | } | |
213 | return [r,g,b]; | |
214 | } | |
215 | ||
216 | ||
2dd6a025 D |
217 | /** |
218 | * Formats a message. Adds bold, underline and colouring | |
219 | * @param {String} msg The message to format | |
220 | * @returns {String} The HTML formatted message | |
221 | */ | |
222 | function formatIRCMsg (msg) { | |
f47955d3 JA |
223 | "use strict"; |
224 | var out = '', | |
225 | currentTag = '', | |
226 | openTags = { | |
227 | bold: false, | |
228 | italic: false, | |
229 | underline: false, | |
230 | colour: false | |
231 | }, | |
f47955d3 JA |
232 | spanFromOpen = function () { |
233 | var style = '', | |
234 | colours; | |
643ca730 | 235 | if (!(openTags.bold || openTags.italic || openTags.underline || openTags.colour)) { |
f47955d3 JA |
236 | return ''; |
237 | } else { | |
238 | style += (openTags.bold) ? 'font-weight: bold; ' : ''; | |
239 | style += (openTags.italic) ? 'font-style: italic; ' : ''; | |
240 | style += (openTags.underline) ? 'text-decoration: underline; ' : ''; | |
241 | if (openTags.colour) { | |
242 | colours = openTags.colour.split(','); | |
243 | style += 'color: ' + colours[0] + ((colours[1]) ? '; background-color: ' + colours[1] + ';' : ''); | |
244 | } | |
9d8f8dfe | 245 | return '<span class="format_span" style="' + style + '">'; |
f47955d3 JA |
246 | } |
247 | }, | |
2dd6a025 | 248 | colourMatch = function (str) { |
f47955d3 | 249 | var re = /^\x03(([0-9][0-9]?)(,([0-9][0-9]?))?)/; |
2dd6a025 | 250 | return re.exec(str); |
f47955d3 JA |
251 | }, |
252 | hexFromNum = function (num) { | |
2dd6a025 D |
253 | switch (parseInt(num, 10)) { |
254 | case 0: | |
255 | return '#FFFFFF'; | |
256 | case 1: | |
257 | return '#000000'; | |
258 | case 2: | |
259 | return '#000080'; | |
260 | case 3: | |
261 | return '#008000'; | |
262 | case 4: | |
263 | return '#FF0000'; | |
264 | case 5: | |
265 | return '#800040'; | |
266 | case 6: | |
267 | return '#800080'; | |
268 | case 7: | |
269 | return '#FF8040'; | |
270 | case 8: | |
271 | return '#FFFF00'; | |
272 | case 9: | |
273 | return '#80FF00'; | |
274 | case 10: | |
275 | return '#008080'; | |
276 | case 11: | |
277 | return '#00FFFF'; | |
278 | case 12: | |
279 | return '#0000FF'; | |
280 | case 13: | |
281 | return '#FF55FF'; | |
282 | case 14: | |
283 | return '#808080'; | |
284 | case 15: | |
285 | return '#C0C0C0'; | |
286 | default: | |
287 | return null; | |
288 | } | |
f47955d3 JA |
289 | }, |
290 | i = 0, | |
291 | colours = [], | |
292 | match; | |
293 | ||
294 | for (i = 0; i < msg.length; i++) { | |
295 | switch (msg[i]) { | |
296 | case '\x02': | |
643ca730 | 297 | if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) { |
f47955d3 JA |
298 | out += currentTag + '</span>'; |
299 | } | |
300 | openTags.bold = !openTags.bold; | |
301 | currentTag = spanFromOpen(); | |
302 | break; | |
303 | case '\x1D': | |
2cb3c82e | 304 | if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) { |
f47955d3 JA |
305 | out += currentTag + '</span>'; |
306 | } | |
307 | openTags.italic = !openTags.italic; | |
308 | currentTag = spanFromOpen(); | |
309 | break; | |
310 | case '\x1F': | |
643ca730 | 311 | if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) { |
f47955d3 JA |
312 | out += currentTag + '</span>'; |
313 | } | |
314 | openTags.underline = !openTags.underline; | |
315 | currentTag = spanFromOpen(); | |
316 | break; | |
317 | case '\x03': | |
643ca730 | 318 | if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) { |
f47955d3 JA |
319 | out += currentTag + '</span>'; |
320 | } | |
321 | match = colourMatch(msg.substr(i, 6)); | |
322 | if (match) { | |
f47955d3 JA |
323 | i += match[1].length; |
324 | // 2 & 4 | |
325 | colours[0] = hexFromNum(match[2]); | |
326 | if (match[4]) { | |
327 | colours[1] = hexFromNum(match[4]); | |
2dd6a025 | 328 | } |
f47955d3 JA |
329 | openTags.colour = colours.join(','); |
330 | } else { | |
331 | openTags.colour = false; | |
332 | } | |
333 | currentTag = spanFromOpen(); | |
334 | break; | |
335 | case '\x0F': | |
643ca730 | 336 | if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) { |
f47955d3 | 337 | out += currentTag + '</span>'; |
2dd6a025 | 338 | } |
f47955d3 JA |
339 | openTags.bold = openTags.italic = openTags.underline = openTags.colour = false; |
340 | break; | |
341 | default: | |
643ca730 | 342 | if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) { |
f47955d3 JA |
343 | currentTag += msg[i]; |
344 | } else { | |
345 | out += msg[i]; | |
346 | } | |
347 | break; | |
2dd6a025 | 348 | } |
f47955d3 | 349 | } |
643ca730 | 350 | if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) { |
f47955d3 JA |
351 | out += currentTag + '</span>'; |
352 | } | |
353 | return out; | |
2dd6a025 D |
354 | } |
355 | ||
356 | ||
51a4c383 D |
357 | function formatDate (d) { |
358 | d = d || new Date(); | |
359 | return d.toLocaleDateString() + ', ' + d.getHours().toString() + ':' + d.getMinutes().toString() + ':' + d.getSeconds().toString(); | |
0260a968 JA |
360 | } |
361 | ||
362 | function escapeRegex (str) { | |
363 | return str.replace(/[\[\\\^\$\.\|\?\*\+\(\)]/g, '\\$&'); | |
364 | } | |
2eacc942 JA |
365 | |
366 | function emoticonFromText(str) { | |
367 | var words_in = str.split(' '), | |
368 | words_out = [], | |
369 | i, | |
e62f5be1 D |
370 | pushEmoticon = function (alt, emote_name) { |
371 | words_out.push('<i class="emoticon ' + emote_name + '">' + alt + '</i>'); | |
2eacc942 JA |
372 | }; |
373 | ||
374 | for (i = 0; i < words_in.length; i++) { | |
375 | switch(words_in[i]) { | |
376 | case ':)': | |
e62f5be1 | 377 | pushEmoticon(':)', 'smile'); |
2eacc942 JA |
378 | break; |
379 | case ':(': | |
e62f5be1 | 380 | pushEmoticon(':(', 'sad'); |
2eacc942 JA |
381 | break; |
382 | case ':3': | |
e62f5be1 | 383 | pushEmoticon(':3', 'lion'); |
2eacc942 JA |
384 | break; |
385 | case ';3': | |
e62f5be1 | 386 | pushEmoticon(';3', 'winky_lion'); |
2eacc942 JA |
387 | break; |
388 | case ':s': | |
e62f5be1 D |
389 | case ':S': |
390 | pushEmoticon(':s', 'confused'); | |
2eacc942 JA |
391 | break; |
392 | case ';(': | |
e62f5be1 D |
393 | case ';_;': |
394 | pushEmoticon(';(', 'cry'); | |
2eacc942 JA |
395 | break; |
396 | case ';)': | |
e62f5be1 | 397 | pushEmoticon(';)', 'wink'); |
2eacc942 JA |
398 | break; |
399 | case ';D': | |
e62f5be1 | 400 | pushEmoticon(';D"', 'wink_happy'); |
2eacc942 JA |
401 | break; |
402 | case ':P': | |
e62f5be1 D |
403 | case ':p': |
404 | pushEmoticon(':P', 'tongue'); | |
2eacc942 JA |
405 | break; |
406 | case 'xP': | |
e62f5be1 | 407 | pushEmoticon('xP', 'cringe_tongue'); |
2eacc942 JA |
408 | break; |
409 | case ':o': | |
410 | case ':O': | |
e62f5be1 D |
411 | case ':0': |
412 | pushEmoticon(':o', 'shocked'); | |
2eacc942 JA |
413 | break; |
414 | case ':D': | |
e62f5be1 | 415 | pushEmoticon(':D', 'happy'); |
2eacc942 | 416 | break; |
e62f5be1 D |
417 | case '^^': |
418 | case '^.^': | |
419 | pushEmoticon('^^,', 'eyebrows'); | |
2eacc942 JA |
420 | break; |
421 | case '<3': | |
e62f5be1 | 422 | pushEmoticon('<3', 'heart'); |
2eacc942 JA |
423 | break; |
424 | case '>_<': | |
e62f5be1 D |
425 | case '>.<': |
426 | pushEmoticon('>_<', 'doh'); | |
2eacc942 JA |
427 | break; |
428 | case 'XD': | |
429 | case 'xD': | |
e62f5be1 | 430 | pushEmoticon('xD', 'big_grin'); |
2eacc942 JA |
431 | break; |
432 | case 'o.0': | |
e62f5be1 D |
433 | case 'o.O': |
434 | pushEmoticon('o.0', 'wide_eye_right'); | |
2eacc942 JA |
435 | break; |
436 | case '0.o': | |
e62f5be1 D |
437 | case 'O.o': |
438 | pushEmoticon('0.o', 'wide_eye_left'); | |
2eacc942 JA |
439 | break; |
440 | case ':\\': | |
441 | case '=\\': | |
2eacc942 JA |
442 | case ':/': |
443 | case '=/': | |
e62f5be1 | 444 | pushEmoticon(':\\', 'unsure'); |
2eacc942 JA |
445 | break; |
446 | default: | |
447 | words_out.push(words_in[i]); | |
448 | } | |
449 | } | |
450 | ||
451 | return words_out.join(' '); | |
452 | } | |
697a76c5 JA |
453 | |
454 | // Code based on http://anentropic.wordpress.com/2009/06/25/javascript-iso8601-parser-and-pretty-dates/#comment-154 | |
455 | function parseISO8601(str) { | |
456 | if (Date.prototype.toISOString) { | |
457 | return new Date(str); | |
458 | } else { | |
459 | var parts = str.split('T'), | |
460 | dateParts = parts[0].split('-'), | |
461 | timeParts = parts[1].split('Z'), | |
462 | timeSubParts = timeParts[0].split(':'), | |
463 | timeSecParts = timeSubParts[2].split('.'), | |
464 | timeHours = Number(timeSubParts[0]), | |
465 | _date = new Date(); | |
466 | ||
467 | _date.setUTCFullYear(Number(dateParts[0])); | |
468 | _date.setUTCDate(1); | |
469 | _date.setUTCMonth(Number(dateParts[1])-1); | |
470 | _date.setUTCDate(Number(dateParts[2])); | |
471 | _date.setUTCHours(Number(timeHours)); | |
472 | _date.setUTCMinutes(Number(timeSubParts[1])); | |
473 | _date.setUTCSeconds(Number(timeSecParts[0])); | |
474 | if (timeSecParts[1]) { | |
475 | _date.setUTCMilliseconds(Number(timeSecParts[1])); | |
476 | } | |
477 | ||
478 | return _date; | |
479 | } | |
480 | } |