Displaying kick actions
[KiwiIRC.git] / client_backbone / dev / utils.js
CommitLineData
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
6/**
7* Suppresses console.log
8* @param {Boolean} debug Whether to re-enable console.log or not
9*/
10function manageDebug(debug) {
2dd6a025
D
11 var log, consoleBackUp;
12 if (window.console) {
13 consoleBackUp = window.console.log;
14 window.console.log = function () {
15 if (debug) {
16 consoleBackUp.apply(console, arguments);
17 }
18 };
19 } else {
20 log = window.opera ? window.opera.postError : alert;
21 window.console = {};
22 window.console.log = function (str) {
23 if (debug) {
24 log(str);
25 }
26 };
27 }
28}
29
30/**
31* Generate a random string of given length
32* @param {Number} string_length The length of the random string
33* @returns {String} The random string
34*/
35function randomString(string_length) {
36 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz",
37 randomstring = '',
38 i,
39 rnum;
40 for (i = 0; i < string_length; i++) {
41 rnum = Math.floor(Math.random() * chars.length);
42 randomstring += chars.substring(rnum, rnum + 1);
43 }
44 return randomstring;
45}
46
47/**
48* String.trim shim
49*/
50if (typeof String.prototype.trim === 'undefined') {
51 String.prototype.trim = function () {
52 return this.replace(/^\s+|\s+$/g, "");
53 };
54}
55
56/**
57* String.lpad shim
58* @param {Number} length The length of padding
59* @param {String} characher The character to pad with
60* @returns {String} The padded string
61*/
62if (typeof String.prototype.lpad === 'undefined') {
63 String.prototype.lpad = function (length, character) {
64 var padding = "",
65 i;
66 for (i = 0; i < length; i++) {
67 padding += character;
68 }
69 return (padding + this).slice(-length);
70 };
71}
72
73
74/**
75* Convert seconds into hours:minutes:seconds
76* @param {Number} secs The number of seconds to converts
77* @returns {Object} An object representing the hours/minutes/second conversion of secs
78*/
79function secondsToTime(secs) {
80 var hours, minutes, seconds, divisor_for_minutes, divisor_for_seconds, obj;
81 hours = Math.floor(secs / (60 * 60));
82
83 divisor_for_minutes = secs % (60 * 60);
84 minutes = Math.floor(divisor_for_minutes / 60);
85
86 divisor_for_seconds = divisor_for_minutes % 60;
87 seconds = Math.ceil(divisor_for_seconds);
88
89 obj = {
90 "h": hours,
91 "m": minutes,
92 "s": seconds
93 };
94 return obj;
95}
96
97
98
99
100
2dd6a025
D
101/**
102* Formats a message. Adds bold, underline and colouring
103* @param {String} msg The message to format
104* @returns {String} The HTML formatted message
105*/
106function formatIRCMsg (msg) {
107 var re, next;
108
109 if ((!msg) || (typeof msg !== 'string')) {
110 return '';
111 }
112
113 // bold
114 if (msg.indexOf(String.fromCharCode(2)) !== -1) {
115 next = '<b>';
116 while (msg.indexOf(String.fromCharCode(2)) !== -1) {
117 msg = msg.replace(String.fromCharCode(2), next);
118 next = (next === '<b>') ? '</b>' : '<b>';
119 }
120 if (next === '</b>') {
121 msg = msg + '</b>';
122 }
123 }
124
125 // underline
126 if (msg.indexOf(String.fromCharCode(31)) !== -1) {
127 next = '<u>';
128 while (msg.indexOf(String.fromCharCode(31)) !== -1) {
129 msg = msg.replace(String.fromCharCode(31), next);
130 next = (next === '<u>') ? '</u>' : '<u>';
131 }
132 if (next === '</u>') {
133 msg = msg + '</u>';
134 }
135 }
136
137 // colour
138 /**
139 * @inner
140 */
141 msg = (function (msg) {
142 var replace, colourMatch, col, i, match, to, endCol, fg, bg, str;
143 replace = '';
144 /**
145 * @inner
146 */
147 colourMatch = function (str) {
148 var re = /^\x03([0-9][0-5]?)(,([0-9][0-5]?))?/;
149 return re.exec(str);
150 };
151 /**
152 * @inner
153 */
154 col = function (num) {
155 switch (parseInt(num, 10)) {
156 case 0:
157 return '#FFFFFF';
158 case 1:
159 return '#000000';
160 case 2:
161 return '#000080';
162 case 3:
163 return '#008000';
164 case 4:
165 return '#FF0000';
166 case 5:
167 return '#800040';
168 case 6:
169 return '#800080';
170 case 7:
171 return '#FF8040';
172 case 8:
173 return '#FFFF00';
174 case 9:
175 return '#80FF00';
176 case 10:
177 return '#008080';
178 case 11:
179 return '#00FFFF';
180 case 12:
181 return '#0000FF';
182 case 13:
183 return '#FF55FF';
184 case 14:
185 return '#808080';
186 case 15:
187 return '#C0C0C0';
188 default:
189 return null;
190 }
191 };
192 if (msg.indexOf('\x03') !== -1) {
193 i = msg.indexOf('\x03');
194 replace = msg.substr(0, i);
195 while (i < msg.length) {
196 /**
197 * @inner
198 */
199 match = colourMatch(msg.substr(i, 6));
200 if (match) {
201 //console.log(match);
202 // Next colour code
203 to = msg.indexOf('\x03', i + 1);
204 endCol = msg.indexOf(String.fromCharCode(15), i + 1);
205 if (endCol !== -1) {
206 if (to === -1) {
207 to = endCol;
208 } else {
209 to = ((to < endCol) ? to : endCol);
210 }
211 }
212 if (to === -1) {
213 to = msg.length;
214 }
215 //console.log(i, to);
216 fg = col(match[1]);
217 bg = col(match[3]);
218 str = msg.substring(i + 1 + match[1].length + ((bg !== null) ? match[2].length + 1 : 0), to);
219 //console.log(str);
220 replace += '<span style="' + ((fg !== null) ? 'color: ' + fg + '; ' : '') + ((bg !== null) ? 'background-color: ' + bg + ';' : '') + '">' + str + '</span>';
221 i = to;
222 } else {
223 if ((msg[i] !== '\x03') && (msg[i] !== String.fromCharCode(15))) {
224 replace += msg[i];
225 }
226 i++;
227 }
228 }
229 return replace;
230 }
231 return msg;
232 }(msg));
233
234 return msg;
235}
236
237
238
239
240
241
242
243
244/*
245 PLUGINS
246 Each function in each object is looped through and ran. The resulting text
247 is expected to be returned.
248*/
249var plugins = [
250 {
251 name: "images",
252 onaddmsg: function (event, opts) {
253 if (!event.msg) {
254 return event;
255 }
256
257 event.msg = event.msg.replace(/^((https?\:\/\/|ftp\:\/\/)|(www\.))(\S+)(\w{2,4})(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?(\.jpg|\.jpeg|\.gif|\.bmp|\.png)$/gi, function (url) {
258 // Don't let any future plugins change it (ie. html_safe plugins)
259 event.event_bubbles = false;
260
261 var img = '<img class="link_img_a" src="' + url + '" height="100%" width="100%" />';
262 return '<a class="link_ext link_img" target="_blank" rel="nofollow" href="' + url + '" style="height:50px;width:50px;display:block">' + img + '<div class="tt box"></div></a>';
263 });
264
265 return event;
266 }
267 },
268
269 {
270 name: "html_safe",
271 onaddmsg: function (event, opts) {
272 event.msg = $('<div/>').text(event.msg).html();
273 event.nick = $('<div/>').text(event.nick).html();
274
275 return event;
276 }
277 },
278
279 {
280 name: "activity",
281 onaddmsg: function (event, opts) {
282 //if (kiwi.front.cur_channel.name.toLowerCase() !== kiwi.front.tabviews[event.tabview.toLowerCase()].name) {
283 // kiwi.front.tabviews[event.tabview].activity();
284 //}
285
286 return event;
287 }
288 },
289
290 {
291 name: "highlight",
292 onaddmsg: function (event, opts) {
293 //var tab = Tabviews.getTab(event.tabview.toLowerCase());
294
295 // If we have a highlight...
296 //if (event.msg.toLowerCase().indexOf(kiwi.gateway.nick.toLowerCase()) > -1) {
297 // if (Tabview.getCurrentTab() !== tab) {
298 // tab.highlight();
299 // }
300 // if (kiwi.front.isChannel(tab.name)) {
301 // event.msg = '<span style="color:red;">' + event.msg + '</span>';
302 // }
303 //}
304
305 // If it's a PM, highlight
306 //if (!kiwi.front.isChannel(tab.name) && tab.name !== "server"
307 // && Tabview.getCurrentTab().name.toLowerCase() !== tab.name
308 //) {
309 // tab.highlight();
310 //}
311
312 return event;
313 }
314 },
315
316
317
318 {
319 //Following method taken from: http://snipplr.com/view/13533/convert-text-urls-into-links/
320 name: "linkify_plain",
321 onaddmsg: function (event, opts) {
322 if (!event.msg) {
323 return event;
324 }
325
326 event.msg = event.msg.replace(/((https?\:\/\/|ftp\:\/\/)|(www\.))(\S+)(\w{2,4})(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/gi, function (url) {
327 var nice;
328 // If it's any of the supported images in the images plugin, skip it
329 if (url.match(/(\.jpg|\.jpeg|\.gif|\.bmp|\.png)$/)) {
330 return url;
331 }
332
333 nice = url;
334 if (url.match('^https?:\/\/')) {
335 //nice = nice.replace(/^https?:\/\//i,'')
336 nice = url; // Shutting up JSLint...
337 } else {
338 url = 'http://' + url;
339 }
340
341 //return '<a class="link_ext" target="_blank" rel="nofollow" href="' + url + '">' + nice + '<div class="tt box"></div></a>';
342 return '<a class="link_ext" target="_blank" rel="nofollow" href="' + url + '">' + nice + '</a>';
343 });
344
345 return event;
346 }
347 },
348
349 {
350 name: "lftobr",
351 onaddmsg: function (event, opts) {
352 if (!event.msg) {
353 return event;
354 }
355
356 event.msg = event.msg.replace(/\n/gi, function (txt) {
357 return '<br/>';
358 });
359
360 return event;
361 }
362 },
363
364
365 /*
366 * Disabled due to many websites closing kiwi with iframe busting
367 {
368 name: "inBrowser",
369 oninit: function (event, opts) {
370 $('#windows a.link_ext').live('mouseover', this.mouseover);
371 $('#windows a.link_ext').live('mouseout', this.mouseout);
372 $('#windows a.link_ext').live('click', this.mouseclick);
373 },
374
375 onunload: function (event, opts) {
376 // TODO: make this work (remove all .link_ext_browser as created in mouseover())
377 $('#windows a.link_ext').die('mouseover', this.mouseover);
378 $('#windows a.link_ext').die('mouseout', this.mouseout);
379 $('#windows a.link_ext').die('click', this.mouseclick);
380 },
381
382
383
384 mouseover: function (e) {
385 var a = $(this),
386 tt = $('.tt', a),
387 tooltip;
388
389 if (tt.text() === '') {
390 tooltip = $('<a class="link_ext_browser">Open in Kiwi..</a>');
391 tt.append(tooltip);
392 }
393
394 tt.css('top', -tt.outerHeight() + 'px');
395 tt.css('left', (a.outerWidth() / 2) - (tt.outerWidth() / 2));
396 },
397
398 mouseout: function (e) {
399 var a = $(this),
400 tt = $('.tt', a);
401 },
402
403 mouseclick: function (e) {
404 var a = $(this),
405 t;
406
407 switch (e.target.className) {
408 case 'link_ext':
409 case 'link_img_a':
410 return true;
411 //break;
412 case 'link_ext_browser':
413 t = new Utilityview('Browser');
414 t.topic = a.attr('href');
415
416 t.iframe = $('<iframe border="0" class="utility_view" src="" style="width:100%;height:100%;border:none;"></iframe>');
417 t.iframe.attr('src', a.attr('href'));
418 t.div.append(t.iframe);
419 t.show();
420 break;
421 }
422 return false;
423
424 }
425 },
426 */
427
428 {
429 name: "nick_colour",
430 onaddmsg: function (event, opts) {
431 if (!event.msg) {
432 return event;
433 }
434
435 //if (typeof kiwi.front.tabviews[event.tabview].nick_colours === 'undefined') {
436 // kiwi.front.tabviews[event.tabview].nick_colours = {};
437 //}
438
439 //if (typeof kiwi.front.tabviews[event.tabview].nick_colours[event.nick] === 'undefined') {
440 // kiwi.front.tabviews[event.tabview].nick_colours[event.nick] = this.randColour();
441 //}
442
443 //var c = kiwi.front.tabviews[event.tabview].nick_colours[event.nick];
444 var c = this.randColour();
445 event.nick = '<span style="color:' + c + ';">' + event.nick + '</span>';
446
447 return event;
448 },
449
450
451
452 randColour: function () {
453 var h = this.rand(-250, 0),
454 s = this.rand(30, 100),
455 l = this.rand(20, 70);
456 return 'hsl(' + h + ',' + s + '%,' + l + '%)';
457 },
458
459
460 rand: function (min, max) {
461 return parseInt(Math.random() * (max - min + 1), 10) + min;
462 }
463 },
464
465 {
466 name: "kiwitest",
467 oninit: function (event, opts) {
468 console.log('registering namespace');
469 $(gateway).bind("kiwi.lol.browser", function (e, data) {
470 console.log('YAY kiwitest');
471 console.log(data);
472 });
473 }
474 }
475];
476
477
478
479
480
481
482
483/**
484* @namespace
485*/
486kiwi.plugs = {};
487/**
488* Loaded plugins
489*/
490kiwi.plugs.loaded = {};
491/**
492* Load a plugin
493* @param {Object} plugin The plugin to be loaded
494* @returns {Boolean} True on success, false on failure
495*/
496kiwi.plugs.loadPlugin = function (plugin) {
497 var plugin_ret;
498 if (typeof plugin.name !== 'string') {
499 return false;
500 }
501
502 plugin_ret = kiwi.plugs.run('plugin_load', {plugin: plugin});
503 if (typeof plugin_ret === 'object') {
504 kiwi.plugs.loaded[plugin_ret.plugin.name] = plugin_ret.plugin;
505 kiwi.plugs.loaded[plugin_ret.plugin.name].local_data = new kiwi.dataStore('kiwi_plugin_' + plugin_ret.plugin.name);
506 }
507 kiwi.plugs.run('init', {}, {run_only: plugin_ret.plugin.name});
508
509 return true;
510};
511
512/**
513* Unload a plugin
514* @param {String} plugin_name The name of the plugin to unload
515*/
516kiwi.plugs.unloadPlugin = function (plugin_name) {
517 if (typeof kiwi.plugs.loaded[plugin_name] !== 'object') {
518 return;
519 }
520
521 kiwi.plugs.run('unload', {}, {run_only: plugin_name});
522 delete kiwi.plugs.loaded[plugin_name];
523};
524
525
526
527/**
528* Run an event against all loaded plugins
529* @param {String} event_name The name of the event
530* @param {Object} event_data The data to pass to the plugin
531* @param {Object} opts Options
532* @returns {Object} Event data, possibly modified by the plugins
533*/
534kiwi.plugs.run = function (event_name, event_data, opts) {
535 var ret = event_data,
536 ret_tmp,
537 plugin_name;
538
539 // Set some defaults if not provided
540 event_data = (typeof event_data === 'undefined') ? {} : event_data;
541 opts = (typeof opts === 'undefined') ? {} : opts;
542
543 for (plugin_name in kiwi.plugs.loaded) {
544 // If we're only calling 1 plugin, make sure it's that one
545 if (typeof opts.run_only === 'string' && opts.run_only !== plugin_name) {
546 continue;
547 }
548
549 if (typeof kiwi.plugs.loaded[plugin_name]['on' + event_name] === 'function') {
550 try {
551 ret_tmp = kiwi.plugs.loaded[plugin_name]['on' + event_name](ret, opts);
552 if (ret_tmp === null) {
553 return null;
554 }
555 ret = ret_tmp;
556
557 if (typeof ret.event_bubbles === 'boolean' && ret.event_bubbles === false) {
558 delete ret.event_bubbles;
559 return ret;
560 }
561 } catch (e) {
562 }
563 }
564 }
565
566 return ret;
567};
568
569
570
571/**
572* @constructor
573* @param {String} data_namespace The namespace for the data store
574*/
575kiwi.dataStore = function (data_namespace) {
576 var namespace = data_namespace;
577
578 this.get = function (key) {
579 return $.jStorage.get(data_namespace + '_' + key);
580 };
581
582 this.set = function (key, value) {
583 return $.jStorage.set(data_namespace + '_' + key, value);
584 };
585};
586
587kiwi.data = new kiwi.dataStore('kiwi');
588
589
590
591
592/*
593 * jQuery jStorage plugin
594 * https://github.com/andris9/jStorage/
595 */
596(function(f){if(!f||!(f.toJSON||Object.toJSON||window.JSON)){throw new Error("jQuery, MooTools or Prototype needs to be loaded before jStorage!")}var g={},d={jStorage:"{}"},h=null,j=0,l=f.toJSON||Object.toJSON||(window.JSON&&(JSON.encode||JSON.stringify)),e=f.evalJSON||(window.JSON&&(JSON.decode||JSON.parse))||function(m){return String(m).evalJSON()},i=false;_XMLService={isXML:function(n){var m=(n?n.ownerDocument||n:0).documentElement;return m?m.nodeName!=="HTML":false},encode:function(n){if(!this.isXML(n)){return false}try{return new XMLSerializer().serializeToString(n)}catch(m){try{return n.xml}catch(o){}}return false},decode:function(n){var m=("DOMParser" in window&&(new DOMParser()).parseFromString)||(window.ActiveXObject&&function(p){var q=new ActiveXObject("Microsoft.XMLDOM");q.async="false";q.loadXML(p);return q}),o;if(!m){return false}o=m.call("DOMParser" in window&&(new DOMParser())||window,n,"text/xml");return this.isXML(o)?o:false}};function k(){if("localStorage" in window){try{if(window.localStorage){d=window.localStorage;i="localStorage"}}catch(p){}}else{if("globalStorage" in window){try{if(window.globalStorage){d=window.globalStorage[window.location.hostname];i="globalStorage"}}catch(o){}}else{h=document.createElement("link");if(h.addBehavior){h.style.behavior="url(#default#userData)";document.getElementsByTagName("head")[0].appendChild(h);h.load("jStorage");var n="{}";try{n=h.getAttribute("jStorage")}catch(m){}d.jStorage=n;i="userDataBehavior"}else{h=null;return}}}b()}function b(){if(d.jStorage){try{g=e(String(d.jStorage))}catch(m){d.jStorage="{}"}}else{d.jStorage="{}"}j=d.jStorage?String(d.jStorage).length:0}function c(){try{d.jStorage=l(g);if(h){h.setAttribute("jStorage",d.jStorage);h.save("jStorage")}j=d.jStorage?String(d.jStorage).length:0}catch(m){}}function a(m){if(!m||(typeof m!="string"&&typeof m!="number")){throw new TypeError("Key name must be string or numeric")}return true}f.jStorage={version:"0.1.5.1",set:function(m,n){a(m);if(_XMLService.isXML(n)){n={_is_xml:true,xml:_XMLService.encode(n)}}g[m]=n;c();return n},get:function(m,n){a(m);if(m in g){if(g[m]&&typeof g[m]=="object"&&g[m]._is_xml&&g[m]._is_xml){return _XMLService.decode(g[m].xml)}else{return g[m]}}return typeof(n)=="undefined"?null:n},deleteKey:function(m){a(m);if(m in g){delete g[m];c();return true}return false},flush:function(){g={};c();return true},storageObj:function(){function m(){}m.prototype=g;return new m()},index:function(){var m=[],n;for(n in g){if(g.hasOwnProperty(n)){m.push(n)}}return m},storageSize:function(){return j},currentBackend:function(){return i},storageAvailable:function(){return !!i},reInit:function(){var m,o;if(h&&h.addBehavior){m=document.createElement("link");h.parentNode.replaceChild(m,h);h=m;h.style.behavior="url(#default#userData)";document.getElementsByTagName("head")[0].appendChild(h);h.load("jStorage");o="{}";try{o=h.getAttribute("jStorage")}catch(n){}d.jStorage=o;i="userDataBehavior"}b()}};k()})(window.jQuery||window.$);