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