merging extensive changes from prawnsalad/KiwiIRC
[KiwiIRC.git] / client / js / mobile.js
CommitLineData
5d751307
D
1if (typeof String.prototype.lpad === 'undefined') {\r
2 String.prototype.lpad = function (length, character) {\r
3 var padding = "",\r
4 i;\r
5 for (i = 0; i < length; i++) {\r
6 padding += character;\r
7 }\r
8 return (padding + this).slice(-length);\r
9 };\r
10}\r
11\r
12\r
13var kiwi = {};\r
14kiwi.objects = {};\r
15kiwi.ui = {};\r
16kiwi.events = {};\r
17kiwi.gateway = {};\r
18\r
19\r
20/**\r
21 * Any user interface methods\r
22 */\r
23kiwi.ui = {\r
24 views: {},\r
25 current_view: null,\r
26\r
27 doLayout: function () {\r
28 var msgs = $('#msgs');\r
29 msgs.css('padding-top', $('#hover_top').outerHeight());\r
30 msgs.css('padding-bottom', $('#hover_bottom').outerHeight());\r
31 },\r
32\r
33\r
34 formatIRCMsg: function (msg) {\r
35 var re, next;\r
36\r
37 if ((!msg) || (typeof msg !== 'string')) {\r
38 return '';\r
39 }\r
40\r
41 // bold\r
42 if (msg.indexOf(String.fromCharCode(2)) !== -1) {\r
43 next = '<b>';\r
44 while (msg.indexOf(String.fromCharCode(2)) !== -1) {\r
45 msg = msg.replace(String.fromCharCode(2), next);\r
46 next = (next === '<b>') ? '</b>' : '<b>';\r
47 }\r
48 if (next === '</b>') {\r
49 msg = msg + '</b>';\r
50 }\r
51 }\r
52\r
53 // underline\r
54 if (msg.indexOf(String.fromCharCode(31)) !== -1) {\r
55 next = '<u>';\r
56 while (msg.indexOf(String.fromCharCode(31)) !== -1) {\r
57 msg = msg.replace(String.fromCharCode(31), next);\r
58 next = (next === '<u>') ? '</u>' : '<u>';\r
59 }\r
60 if (next === '</u>') {\r
61 msg = msg + '</u>';\r
62 }\r
63 }\r
64\r
65 // colour\r
66 /**\r
67 * @inner\r
68 */\r
69 msg = (function (msg) {\r
70 var replace, colourMatch, col, i, match, to, endCol, fg, bg, str;\r
71 replace = '';\r
72 /**\r
73 * @inner\r
74 */\r
75 colourMatch = function (str) {\r
76 var re = /^\x03([0-9][0-5]?)(,([0-9][0-5]?))?/;\r
77 return re.exec(str);\r
78 };\r
79 /**\r
80 * @inner\r
81 */\r
82 col = function (num) {\r
83 switch (parseInt(num, 10)) {\r
84 case 0:\r
85 return '#FFFFFF';\r
86 case 1:\r
87 return '#000000';\r
88 case 2:\r
89 return '#000080';\r
90 case 3:\r
91 return '#008000';\r
92 case 4:\r
93 return '#FF0000';\r
94 case 5:\r
95 return '#800040';\r
96 case 6:\r
97 return '#800080';\r
98 case 7:\r
99 return '#FF8040';\r
100 case 8:\r
101 return '#FFFF00';\r
102 case 9:\r
103 return '#80FF00';\r
104 case 10:\r
105 return '#008080';\r
106 case 11:\r
107 return '#00FFFF';\r
108 case 12:\r
109 return '#0000FF';\r
110 case 13:\r
111 return '#FF55FF';\r
112 case 14:\r
113 return '#808080';\r
114 case 15:\r
115 return '#C0C0C0';\r
116 default:\r
117 return null;\r
118 }\r
119 };\r
120 if (msg.indexOf('\x03') !== -1) {\r
121 i = msg.indexOf('\x03');\r
122 replace = msg.substr(0, i);\r
123 while (i < msg.length) {\r
124 /**\r
125 * @inner\r
126 */\r
127 match = colourMatch(msg.substr(i, 6));\r
128 if (match) {\r
129 //console.log(match);\r
130 // Next colour code\r
131 to = msg.indexOf('\x03', i + 1);\r
132 endCol = msg.indexOf(String.fromCharCode(15), i + 1);\r
133 if (endCol !== -1) {\r
134 if (to === -1) {\r
135 to = endCol;\r
136 } else {\r
137 to = ((to < endCol) ? to : endCol);\r
138 }\r
139 }\r
140 if (to === -1) {\r
141 to = msg.length;\r
142 }\r
143 //console.log(i, to);\r
144 fg = col(match[1]);\r
145 bg = col(match[3]);\r
146 str = msg.substring(i + 1 + match[1].length + ((bg !== null) ? match[2].length + 1 : 0), to);\r
147 //console.log(str);\r
148 replace += '<span style="' + ((fg !== null) ? 'color: ' + fg + '; ' : '') + ((bg !== null) ? 'background-color: ' + bg + ';' : '') + '">' + str + '</span>';\r
149 i = to;\r
150 } else {\r
151 if ((msg[i] !== '\x03') && (msg[i] !== String.fromCharCode(15))) {\r
152 replace += msg[i];\r
153 }\r
154 i++;\r
155 }\r
156 }\r
157 return replace;\r
158 }\r
159 return msg;\r
160 }(msg));\r
161 \r
162 return msg;\r
163 },\r
164\r
165\r
166 run: function (msg) {\r
167 var parts, dest, t, pos, textRange, plugin_event, msg_sliced, tab, nick;\r
168\r
169 if (msg.substring(0, 1) === '/') {\r
170 console.log("running " + msg);\r
171 parts = msg.split(' ');\r
172 switch (parts[0].toLowerCase()) {\r
173 case '/nick':\r
174 if (parts[1] === undefined) {\r
175 console.log("calling show nick");\r
176 kiwi.front.ui.showChangeNick();\r
177 } else {\r
178 console.log("sending nick");\r
179 kiwi.gateway.nick(msg.substring(1));\r
180 }\r
181 break;\r
182 \r
183 case '/q':\r
184 case '/query':\r
185 if (typeof parts[1] !== "undefined") {\r
186 tab = new kiwi.objects.MessageView(parts[1]);\r
187 }\r
188 break;\r
189 \r
190 case '/k':\r
191 case '/kick':\r
192 if (typeof parts[1] === 'undefined') {\r
193 return;\r
194 }\r
195 t = msg.split(' ', 3);\r
196 nick = t[1];\r
197 kiwi.gateway.kick(Tabview.getCurrent().title, nick, t[2]);\r
198 break;\r
199 \r
200 case '/j':\r
201 case '/join':\r
202 kiwi.ui.joinChannel(parts[1]);\r
203 break;\r
204\r
205 case '/part':\r
206 break;\r
207\r
208 case '/quote':\r
209 kiwi.gateway.raw(msg.replace(/^\/quote /i, ''));\r
210 break;\r
211 \r
212 case '/me':\r
213 tab = kiwi.objects.getCurrent();\r
214 kiwi.gateway.ctcp(true, 'ACTION', tab.title, msg.substring(4));\r
215 tab.addMsg(' ', '* ' + kiwi.gateway.nick + ' ' + msg.substring(4));\r
216 break;\r
217\r
218 case '/quit':\r
219 kiwi.gateway.quit(parts.slice(1).join(' '));\r
220 break;\r
221 }\r
222\r
223 } else {\r
224 if (msg.trim() === '') {\r
225 return;\r
226 }\r
227 tab = kiwi.objects.MessageView.getCurrent();\r
228 if (tab.title !== 'server') {\r
86921a5d 229 console.log(tab.title);\r
5d751307
D
230 kiwi.gateway.privmsg(tab.title, msg);\r
231 tab.addMsg(kiwi.gateway.nick, msg);\r
232 }\r
233 }\r
234\r
235 },\r
236\r
237 joinChannel: function (chan_name) {\r
238 var chans = chan_name.split(','),\r
239 i,\r
240 chan,\r
241 tab;\r
242 for (i in chans) {\r
243 chan = chans[i];\r
244 tab = kiwi.objects.MessageView.get(chan);\r
245 if ((!tab) || (tab.safe_to_close === true)) {\r
246 kiwi.gateway.join(chan);\r
247 tab = new kiwi.objects.MessageView(chan);\r
248 }\r
249 }\r
250\r
251 if (tab) {\r
252 tab.show();\r
253 }\r
254 },\r
255};\r
256\r
257\r
258/**\r
259 * Entry point for Kiwi\r
260 */\r
261kiwi.init = function () {\r
262 var server,\r
263 gateway = $(kiwi.gateway);\r
264 \r
265 server = new kiwi.objects.MessageView('server');\r
266 server.show();\r
267 server.addMsg('', 'KiwiIRC Mobile client');\r
268 console.log = function (w) {\r
269 server.addMsg('log', w);\r
270 }\r
271\r
272 kiwi.ui.doLayout();\r
273\r
274 $('#msginp').bind('keydown', function (e) {\r
275 switch (true) {\r
276 case e.which === 13: // return\r
277 msg = $(this).val();\r
278 msg = msg.trim();\r
279\r
280 kiwi.ui.run(msg);\r
281 $(this).val('');\r
282\r
283 break;\r
284 }\r
285 });\r
286\r
287 gateway.bind('onconnect', function (e, data) {\r
288 kiwi.objects.MessageView.getServer().addMsg('', 'Connected :)');\r
289 });\r
290 gateway.bind('onmotd', function (e, data) {\r
291 kiwi.objects.MessageView.getServer().addMsg('', data.msg);\r
292 });\r
293 gateway.bind('onmsg', function (e, data) {\r
294 var destination, plugin_event, tab;\r
295 // Is this message from a user?\r
296 if (data.channel === kiwi.gateway.nick) {\r
297 destination = data.nick.toLowerCase();\r
298 } else {\r
299 destination = data.channel.toLowerCase();\r
300 }\r
301 \r
302 tab = kiwi.objects.MessageView.get(destination);\r
303 if (!tab) {\r
304 tab = new kiwi.objects.MessageView(destination);\r
305 }\r
306 tab.addMsg(data.nick, data.msg);\r
307 });\r
86921a5d
D
308 gateway.bind('onjoin', function (e, data) {\r
309 var tab = kiwi.objects.MessageView.get(data.channel);\r
310 if (!tab) {\r
311 tab = new kiwi.objects.MessageView(data.channel);\r
312 }\r
313 tab.addMsg('', '--> ' + data.nick + ' has joined', 'join');\r
314 });\r
315 gateway.bind('onpart', function (e, data) {\r
316 var tab = kiwi.objects.MessageView.get(data.channel);\r
317 if (!tab) {\r
318 tab = new kiwi.objects.MessageView(data.channel);\r
319 }\r
320 tab.addMsg('', '<-- ' + data.nick + ' has left (' + data.message + ')', 'part');\r
321 });\r
5d751307
D
322};\r
323\r
324\r
325\r
326\r
327\r
328\r
329\r
330\r
331/**\r
332 * Basic container that holds content on the page\r
333 */\r
334kiwi.objects.View = function (title) {\r
335 var that = this;\r
336\r
337 this.title = title;\r
338 this.tab = $('<li>' + title + '</li>');\r
339 this.content = $('<div></div>');\r
340\r
341 $('#chan_list').append(this.tab);\r
342 $('#msgs').append(this.content);\r
343\r
344 this.tab.click(function () { that.show.call(that); });\r
345};\r
346kiwi.objects.View.prototype.title = 'View';\r
347kiwi.objects.View.prototype.tab = null;\r
348kiwi.objects.View.prototype.content = null;\r
349kiwi.objects.View.prototype.show = function () {\r
350 $('#msgs > div.active').removeClass('active');\r
351 this.content.addClass('active');\r
352 kiwi.ui.current_view = this;\r
353 this.scrollBottom();\r
354}\r
355kiwi.objects.View.prototype.scrollBottom = function () {\r
356 $(window).scrollTop($(document).height());\r
357}\r
358\r
359\r
360\r
361\r
362/**\r
363 * A type of View that contains mainly messages\r
364 */\r
365kiwi.objects.MessageView = function (name) {\r
366 // Call the parent constructor\r
367 kiwi.objects.View.prototype.constructor.call(this, name);\r
368\r
369 // Add this MessageView to the array\r
370 kiwi.ui.views[name.toLowerCase()] = this;\r
371}\r
372kiwi.objects.MessageView.prototype = new kiwi.objects.View();\r
86921a5d
D
373kiwi.objects.MessageView.prototype.msg_count = 0;\r
374kiwi.objects.MessageView.prototype.addMsg = function (nick, text, msg_class) {\r
5d751307
D
375 var msg, d = new Date(),\r
376 time;\r
377 \r
86921a5d
D
378 // The CSS class to use\r
379 msg_class = msg_class || '';\r
380\r
381 msg = $('<div class="msg ' + msg_class + '"><span class="time"></span><span class="nick"></span><span class="body"></span></div>');\r
5d751307
D
382 time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0");\r
383\r
384 $('.time', msg).text(time);\r
385 $('.nick', msg).text(nick);\r
386 $('.body', msg).text(kiwi.ui.formatIRCMsg(text));\r
387 this.content.append(msg);\r
388\r
86921a5d
D
389 this.msg_count++;\r
390 if (this.msg_count > 5) {\r
391 $('.msg:first', this.content).remove();\r
392 this.msg_count--;\r
393 }\r
394\r
5d751307
D
395 this.scrollBottom();\r
396}\r
397// Static functions\r
398kiwi.objects.MessageView.exists = function (name) {\r
399 if ((!name) || (typeof name !== 'string')) {\r
400 return false;\r
401 }\r
402 var ret = (typeof kiwi.ui.views[name.toLowerCase()] !== 'undefined');\r
403 return ret;\r
404};\r
405kiwi.objects.MessageView.get = function (name) {\r
406 if (kiwi.objects.MessageView.exists(name)) {\r
407 var ret = kiwi.ui.views[name.toLowerCase()];\r
408 return ret;\r
409 } else {\r
410 return null;\r
411 }\r
412};\r
413kiwi.objects.MessageView.getServer = function () {\r
414 return kiwi.ui.views.server;\r
415};\r
416kiwi.objects.MessageView.getAlls = function () {\r
417 return kiwi.ui.views;\r
418};\r
419kiwi.objects.MessageView.getCurrent = function () {\r
420 return kiwi.ui.current_view;\r
421};