Commit | Line | Data |
---|---|---|
50ac472f | 1 | _kiwi.view.Channel = _kiwi.view.Panel.extend({ |
9b807765 | 2 | events: function(){ |
c794b877 | 3 | var parent_events = this.constructor.__super__.events; |
3499d625 | 4 | |
9b807765 D |
5 | if(_.isFunction(parent_events)){ |
6 | parent_events = parent_events(); | |
7 | } | |
8 | return _.extend({}, parent_events, { | |
3499d625 D |
9 | 'click .msg .nick' : 'nickClick', |
10 | "click .chan": "chanClick", | |
11 | 'click .media .open': 'mediaClick', | |
12 | 'mouseenter .msg .nick': 'msgEnter', | |
13 | 'mouseleave .msg .nick': 'msgLeave' | |
9b807765 | 14 | }); |
dfb5209c JA |
15 | }, |
16 | ||
50ac472f D |
17 | initialize: function (options) { |
18 | this.initializePanel(options); | |
c794b877 D |
19 | |
20 | // Container for all the messages | |
21 | this.$messages = $('<div class="messages"></div>'); | |
22 | this.$el.append(this.$messages); | |
23 | ||
50ac472f D |
24 | this.model.bind('change:topic', this.topic, this); |
25 | ||
7d2a2771 D |
26 | if (this.model.get('members')) { |
27 | this.model.get('members').bind('add', function (member) { | |
28 | if (member.get('nick') === this.model.collection.network.get('nick')) { | |
29 | this.$el.find('.initial_loader').slideUp(function () { | |
30 | $(this).remove(); | |
31 | }); | |
32 | } | |
33 | }, this); | |
34 | } | |
660e1427 | 35 | |
50ac472f D |
36 | // Only show the loader if this is a channel (ie. not a query) |
37 | if (this.model.isChannel()) { | |
247dd7ac | 38 | this.$el.append('<div class="initial_loader" style="margin:1em;text-align:center;"> ' + _kiwi.global.i18n.translate('client_views_channel_joining').fetch() + ' <span class="loader"></span></div>'); |
50ac472f | 39 | } |
c794b877 D |
40 | |
41 | this.model.bind('msg', this.newMsg, this); | |
42 | this.msg_count = 0; | |
50ac472f D |
43 | }, |
44 | ||
c794b877 | 45 | |
41a9c836 D |
46 | render: function () { |
47 | var that = this; | |
48 | ||
49 | this.$messages.empty(); | |
50 | _.each(this.model.get('scrollback'), function (msg) { | |
51 | that.newMsg(msg); | |
52 | }); | |
53 | }, | |
54 | ||
55 | ||
c794b877 D |
56 | newMsg: function (msg) { |
57 | var re, line_msg, | |
58 | nick_colour_hex, nick_hex, is_highlight, msg_css_classes = '', | |
59 | time_difference, | |
60 | sb = this.model.get('scrollback'), | |
61 | prev_msg = sb[sb.length-2]; | |
62 | ||
63 | // Nick highlight detecting | |
64 | if ((new RegExp('(^|\\W)(' + escapeRegex(_kiwi.app.connections.active_connection.get('nick')) + ')(\\W|$)', 'i')).test(msg.msg)) { | |
65 | is_highlight = true; | |
66 | msg_css_classes += ' highlight'; | |
67 | } | |
68 | ||
69 | // Escape any HTML that may be in here | |
70 | msg.msg = $('<div />').text(msg.msg).html(); | |
71 | ||
72 | // Make the channels clickable | |
73 | re = new RegExp('(?:^|\\s)([' + escapeRegex(_kiwi.gateway.get('channel_prefix')) + '][^ ,\\007]+)', 'g'); | |
74 | msg.msg = msg.msg.replace(re, function (match) { | |
75 | return '<a class="chan" data-channel="' + match.trim() + '">' + match + '</a>'; | |
76 | }); | |
77 | ||
78 | ||
79 | // Parse any links found | |
80 | msg.msg = msg.msg.replace(/(([A-Za-z][A-Za-z0-9\-]*\:\/\/)|(www\.))([\w.\-]+)([a-zA-Z]{2,6})(:[0-9]+)?(\/[\w#!:.?$'()[\]*,;~+=&%@!\-\/]*)?/gi, function (url) { | |
81 | var nice = url, | |
82 | extra_html = ''; | |
83 | ||
84 | // Add the http if no protoocol was found | |
85 | if (url.match(/^www\./)) { | |
86 | url = 'http://' + url; | |
87 | } | |
88 | ||
89 | // Shorten the displayed URL if it's going to be too long | |
90 | if (nice.length > 100) { | |
91 | nice = nice.substr(0, 100) + '...'; | |
92 | } | |
93 | ||
94 | // Get any media HTML if supported | |
95 | extra_html = _kiwi.view.MediaMessage.buildHtml(url); | |
96 | ||
97 | // Make the link clickable | |
98 | return '<a class="link_ext" target="_blank" rel="nofollow" href="' + url + '">' + nice + '</a>' + extra_html; | |
99 | }); | |
100 | ||
101 | ||
102 | // Convert IRC formatting into HTML formatting | |
103 | msg.msg = formatIRCMsg(msg.msg); | |
104 | ||
2eacc942 JA |
105 | // Replace text emoticons with images |
106 | if (_kiwi.global.settings.get('show_emoticons')) { | |
107 | msg.msg = emoticonFromText(msg.msg); | |
108 | } | |
c794b877 D |
109 | |
110 | // Add some colours to the nick (Method based on IRSSIs nickcolor.pl) | |
111 | nick_colour_hex = (function (nick) { | |
112 | var nick_int = 0, rgb; | |
113 | ||
114 | _.map(nick.split(''), function (i) { nick_int += i.charCodeAt(0); }); | |
115 | rgb = hsl2rgb(nick_int % 255, 70, 35); | |
116 | rgb = rgb[2] | (rgb[1] << 8) | (rgb[0] << 16); | |
117 | ||
118 | return '#' + rgb.toString(16); | |
119 | })(msg.nick); | |
120 | ||
121 | msg.nick_style = 'color:' + nick_colour_hex + ';'; | |
122 | ||
123 | // Generate a hex string from the nick to be used as a CSS class name | |
124 | nick_hex = msg.nick_css_class = ''; | |
125 | if (msg.nick) { | |
126 | _.map(msg.nick.split(''), function (char) { | |
127 | nick_hex += char.charCodeAt(0).toString(16); | |
128 | }); | |
129 | msg_css_classes += ' nick_' + nick_hex; | |
130 | } | |
131 | ||
132 | if (prev_msg) { | |
133 | // Time difference between this message and the last (in minutes) | |
697a76c5 | 134 | time_difference = (msg.time.getTime() - prev_msg.time.getTime())/1000/60; |
c794b877 D |
135 | if (prev_msg.nick === msg.nick && time_difference < 1) { |
136 | msg_css_classes += ' repeated_nick'; | |
137 | } | |
138 | } | |
139 | ||
140 | // Build up and add the line | |
141 | msg.msg_css_classes = msg_css_classes; | |
697a76c5 JA |
142 | msg.time_string = msg.time.getHours().toString().lpad(2, "0") + ":" + msg.time.getMinutes().toString().lpad(2, "0") + ":" + msg.time.getSeconds().toString().lpad(2, "0"); |
143 | line_msg = '<div class="msg <%= type %> <%= msg_css_classes %>"><div class="time"><%- time_string %></div><div class="nick" style="<%= nick_style %>"><%- nick %></div><div class="text" style="<%= style %>"><%= msg %> </div></div>'; | |
c794b877 D |
144 | this.$messages.append(_.template(line_msg, msg)); |
145 | ||
146 | // Activity/alerts based on the type of new message | |
147 | if (msg.type.match(/^action /)) { | |
148 | this.alert('action'); | |
149 | ||
150 | } else if (is_highlight) { | |
151 | _kiwi.app.view.alertWindow('* ' + _kiwi.global.i18n.translate('client_views_panel_activity').fetch()); | |
152 | _kiwi.app.view.favicon.newHighlight(); | |
153 | _kiwi.app.view.playSound('highlight'); | |
ee2f0962 | 154 | _kiwi.app.view.showNotification(this.model.get('name'), msg.msg); |
c794b877 D |
155 | this.alert('highlight'); |
156 | ||
157 | } else { | |
158 | // If this is the active panel, send an alert out | |
159 | if (this.model.isActive()) { | |
160 | _kiwi.app.view.alertWindow('* ' + _kiwi.global.i18n.translate('client_views_panel_activity').fetch()); | |
161 | } | |
162 | this.alert('activity'); | |
163 | } | |
164 | ||
165 | if (this.model.isQuery() && !this.model.isActive()) { | |
166 | _kiwi.app.view.alertWindow('* ' + _kiwi.global.i18n.translate('client_views_panel_activity').fetch()); | |
ee2f0962 D |
167 | |
168 | // Highlights have already been dealt with above | |
c794b877 D |
169 | if (!is_highlight) { |
170 | _kiwi.app.view.favicon.newHighlight(); | |
171 | } | |
ee2f0962 D |
172 | |
173 | _kiwi.app.view.showNotification(this.model.get('name'), msg.msg); | |
c794b877 D |
174 | _kiwi.app.view.playSound('highlight'); |
175 | } | |
176 | ||
177 | // Update the activity counters | |
178 | (function () { | |
179 | // Only inrement the counters if we're not the active panel | |
180 | if (this.model.isActive()) return; | |
181 | ||
182 | var $act = this.model.tab.find('.activity'); | |
223d53e5 TL |
183 | var count_joins_parts = _kiwi.global.settings.get('count_joins_parts'); |
184 | if (typeof count_joins_parts === 'undefined') { | |
185 | count_joins_parts = true; | |
186 | } | |
187 | ||
188 | if (count_joins_parts || msg.type === 'privmsg') { | |
189 | $act.text((parseInt($act.text(), 10) || 0) + 1); | |
190 | } else { | |
191 | $act.text((parseInt($act.text(), 10) || 0)); | |
192 | } | |
193 | ||
c794b877 D |
194 | if ($act.text() === '0') { |
195 | $act.addClass('zero'); | |
196 | } else { | |
197 | $act.removeClass('zero'); | |
198 | } | |
199 | }).apply(this); | |
200 | ||
201 | this.scrollToBottom(); | |
202 | ||
203 | // Make sure our DOM isn't getting too large (Acts as scrollback) | |
204 | this.msg_count++; | |
205 | if (this.msg_count > (parseInt(_kiwi.global.settings.get('scrollback'), 10) || 250)) { | |
206 | $('.msg:first', this.$messages).remove(); | |
207 | this.msg_count--; | |
208 | } | |
50ac472f D |
209 | }, |
210 | ||
c794b877 | 211 | |
50ac472f D |
212 | topic: function (topic) { |
213 | if (typeof topic !== 'string' || !topic) { | |
214 | topic = this.model.get("topic"); | |
215 | } | |
216 | ||
247dd7ac | 217 | this.model.addMsg('', '== ' + _kiwi.global.i18n.translate('client_views_channel_topic').fetch(this.model.get('name'), topic), 'topic'); |
50ac472f D |
218 | |
219 | // If this is the active channel then update the topic bar | |
220 | if (_kiwi.app.panels().active === this) { | |
221 | _kiwi.app.topicbar.setCurrentTopic(this.model.get("topic")); | |
222 | } | |
dfb5209c JA |
223 | }, |
224 | ||
225 | // Click on a nickname | |
226 | nickClick: function (event) { | |
227 | var nick = $(event.currentTarget).text(), | |
228 | members = this.model.get('members'), | |
229 | member, query, userbox, menubox; | |
230 | ||
231 | if (members) { | |
232 | member = members.getByNick(nick); | |
233 | if (member) { | |
dfb5209c JA |
234 | userbox = new _kiwi.view.UserBox(); |
235 | userbox.member = member; | |
236 | userbox.channel = this.model; | |
237 | ||
0826460d D |
238 | // Hide the op related items if we're not an op |
239 | if (!members.getByNick(_kiwi.app.connections.active_connection.get('nick')).get('is_op')) { | |
dfb5209c JA |
240 | userbox.$el.children('.if_op').remove(); |
241 | } | |
0826460d | 242 | |
dfb5209c JA |
243 | menubox = new _kiwi.view.MenuBox(member.get('nick') || 'User'); |
244 | menubox.addItem('userbox', userbox.$el); | |
dfb5209c | 245 | menubox.show(); |
0826460d | 246 | |
dfb5209c JA |
247 | // Position the userbox + menubox |
248 | (function() { | |
249 | var t = event.pageY, | |
250 | m_bottom = t + menubox.$el.outerHeight(), // Where the bottom of menu will be | |
251 | memberlist_bottom = this.$el.parent().offset().top + this.$el.parent().outerHeight(); | |
252 | ||
253 | // If the bottom of the userbox is going to be too low.. raise it | |
254 | if (m_bottom > memberlist_bottom){ | |
255 | t = memberlist_bottom - menubox.$el.outerHeight(); | |
256 | } | |
257 | ||
258 | // Set the new positon | |
259 | menubox.$el.offset({ | |
260 | left: event.clientX, | |
261 | top: t | |
262 | }); | |
263 | }).call(this); | |
264 | } | |
265 | } | |
3499d625 D |
266 | }, |
267 | ||
268 | ||
269 | chanClick: function (event) { | |
270 | if (event.target) { | |
271 | _kiwi.gateway.join(null, $(event.target).data('channel')); | |
272 | } else { | |
273 | // IE... | |
274 | _kiwi.gateway.join(null, $(event.srcElement).data('channel')); | |
275 | } | |
276 | }, | |
277 | ||
278 | ||
279 | mediaClick: function (event) { | |
280 | var $media = $(event.target).parents('.media'); | |
281 | var media_message; | |
282 | ||
283 | if ($media.data('media')) { | |
284 | media_message = $media.data('media'); | |
285 | } else { | |
286 | media_message = new _kiwi.view.MediaMessage({el: $media[0]}); | |
287 | ||
288 | // Cache this MediaMessage instance for when it's opened again | |
289 | $media.data('media', media_message); | |
290 | } | |
291 | ||
292 | media_message.toggle(); | |
293 | }, | |
294 | ||
295 | ||
296 | // Cursor hovers over a message | |
297 | msgEnter: function (event) { | |
298 | var nick_class; | |
299 | ||
300 | // Find a valid class that this element has | |
301 | _.each($(event.currentTarget).parent('.msg').attr('class').split(' '), function (css_class) { | |
302 | if (css_class.match(/^nick_[a-z0-9]+/i)) { | |
303 | nick_class = css_class; | |
304 | } | |
305 | }); | |
306 | ||
307 | // If no class was found.. | |
308 | if (!nick_class) return; | |
309 | ||
310 | $('.'+nick_class).addClass('global_nick_highlight'); | |
311 | }, | |
312 | ||
313 | ||
314 | // Cursor leaves message | |
315 | msgLeave: function (event) { | |
316 | var nick_class; | |
317 | ||
318 | // Find a valid class that this element has | |
319 | _.each($(event.currentTarget).parent('.msg').attr('class').split(' '), function (css_class) { | |
320 | if (css_class.match(/^nick_[a-z0-9]+/i)) { | |
321 | nick_class = css_class; | |
322 | } | |
323 | }); | |
324 | ||
325 | // If no class was found.. | |
326 | if (!nick_class) return; | |
327 | ||
328 | $('.'+nick_class).removeClass('global_nick_highlight'); | |
329 | }, | |
dfb5209c | 330 | }); |