Merge branch 'development'
[KiwiIRC.git] / client / src / views / mediamessage.js
CommitLineData
50ac472f
D
1_kiwi.view.MediaMessage = Backbone.View.extend({
2 events: {
3 'click .media_close': 'close'
4 },
5
6 initialize: function () {
7 // Get the URL from the data
8 this.url = this.$el.data('url');
9 },
10
975f9705
D
11 toggle: function () {
12 if (!this.$content || !this.$content.is(':visible')) {
13 this.open();
14 } else {
15 this.close();
16 }
17 },
18
50ac472f
D
19 // Close the media content and remove it from display
20 close: function () {
21 var that = this;
22 this.$content.slideUp('fast', function () {
23 that.$content.remove();
24 });
25 },
26
27 // Open the media content within its wrapper
28 open: function () {
29 // Create the content div if we haven't already
30 if (!this.$content) {
880239e8 31 this.$content = $('<div class="media_content"><a class="media_close"><i class="fa fa-chevron-up"></i> ' + _kiwi.global.i18n.translate('client_views_mediamessage_close').fetch() + '</a><br /><div class="content"></div></div>');
247dd7ac 32 this.$content.find('.content').append(this.mediaTypes[this.$el.data('type')].apply(this, []) || _kiwi.global.i18n.translate('client_views_mediamessage_notfound').fetch() + ' :(');
50ac472f
D
33 }
34
35 // Now show the content if not already
36 if (!this.$content.is(':visible')) {
37 // Hide it first so the slideDown always plays
38 this.$content.hide();
39
40 // Add the media content and slide it into view
41 this.$el.append(this.$content);
42 this.$content.slideDown();
43 }
44 },
45
46
47
48 // Generate the media content for each recognised type
49 mediaTypes: {
50 twitter: function () {
51 var tweet_id = this.$el.data('tweetid');
52 var that = this;
53
54 $.getJSON('https://api.twitter.com/1/statuses/oembed.json?id=' + tweet_id + '&callback=?', function (data) {
55 that.$content.find('.content').html(data.html);
56 });
57
247dd7ac 58 return $('<div>' + _kiwi.global.i18n.translate('client_views_mediamessage_load_tweet').fetch() + '...</div>');
50ac472f
D
59 },
60
61
62 image: function () {
63 return $('<a href="' + this.url + '" target="_blank"><img height="100" src="' + this.url + '" /></a>');
64 },
65
d513dc2c 66
390de62e 67 imgur: function () {
68 var that = this;
69
70 $.getJSON('http://api.imgur.com/oembed?url=' + this.url, function (data) {
8ffcb297 71 var img_html = '<a href="' + data.url + '" target="_blank"><img height="100" src="' + data.url + '" /></a>';
390de62e 72 that.$content.find('.content').html(img_html);
73 });
50ac472f 74
247dd7ac 75 return $('<div>' + _kiwi.global.i18n.translate('client_views_mediamessage_load_image').fetch() + '...</div>');
390de62e 76 },
77
d513dc2c 78
50ac472f
D
79 reddit: function () {
80 var that = this;
81 var matches = (/reddit\.com\/r\/([a-zA-Z0-9_\-]+)\/comments\/([a-z0-9]+)\/([^\/]+)?/gi).exec(this.url);
82
83 $.getJSON('http://www.' + matches[0] + '.json?jsonp=?', function (data) {
84 console.log('Loaded reddit data', data);
85 var post = data[0].data.children[0].data;
86 var thumb = '';
87
88 // Show a thumbnail if there is one
89 if (post.thumbnail) {
90 //post.thumbnail = 'http://www.eurotunnel.com/uploadedImages/commercial/back-steps-icon-arrow.png';
91
92 // Hide the thumbnail if an over_18 image
93 if (post.over_18) {
94 thumb = '<span class="thumbnail_nsfw" onclick="$(this).find(\'p\').remove(); $(this).find(\'img\').css(\'visibility\', \'visible\');">';
95 thumb += '<p style="font-size:0.9em;line-height:1.2em;cursor:pointer;">Show<br />NSFW</p>';
96 thumb += '<img src="' + post.thumbnail + '" class="thumbnail" style="visibility:hidden;" />';
97 thumb += '</span>';
98 } else {
99 thumb = '<img src="' + post.thumbnail + '" class="thumbnail" />';
100 }
101 }
102
103 // Build the template string up
104 var tmpl = '<div>' + thumb + '<b><%- title %></b><br />Posted by <%- author %>. &nbsp;&nbsp; ';
880239e8 105 tmpl += '<i class="fa fa-arrow-up"></i> <%- ups %> &nbsp;&nbsp; <i class="fa fa-arrow-down"></i> <%- downs %><br />';
50ac472f
D
106 tmpl += '<%- num_comments %> comments made. <a href="http://www.reddit.com<%- permalink %>">View post</a></div>';
107
108 that.$content.find('.content').html(_.template(tmpl, post));
109 });
110
247dd7ac 111 return $('<div>' + _kiwi.global.i18n.translate('client_views_mediamessage_load_reddit').fetch() + '...</div>');
9ff10506 112 },
d513dc2c
D
113
114
1cee8867 115 youtube: function () {
116 var ytid = this.$el.data('ytid');
9ff10506 117 var that = this;
b99b615e 118 var yt_html = '<iframe width="480" height="270" src="https://www.youtube.com/embed/'+ ytid +'?feature=oembed" frameborder="0" allowfullscreen=""></iframe>';
1cee8867 119 that.$content.find('.content').html(yt_html);
390de62e 120
121 return $('');
5b01f32b
D
122 },
123
124
125 gist: function () {
126 var that = this,
127 matches = (/https?:\/\/gist\.github\.com\/(?:[a-z0-9-]*\/)?([a-z0-9]+)(\#(.+))?$/i).exec(this.url);
128
129 $.getJSON('https://gist.github.com/'+matches[1]+'.json?callback=?' + (matches[2] || ''), function (data) {
130 $('body').append('<link rel="stylesheet" href="' + data.stylesheet + '" type="text/css" />');
131 that.$content.find('.content').html(data.div);
132 });
133
247dd7ac 134 return $('<div>' + _kiwi.global.i18n.translate('client_views_mediamessage_load_gist').fetch() + '...</div>');
b3996e54 135 },
50ac472f 136
b3996e54 137 spotify: function () {
6388af17
D
138 var uri = this.$el.data('uri'),
139 method = this.$el.data('method'),
140 spot, html;
b3996e54
L
141
142 switch (method) {
143 case "track":
144 case "album":
6388af17
D
145 spot = {
146 url: 'https://embed.spotify.com/?uri=' + uri,
147 width: 300,
148 height: 80
149 };
150 break;
b3996e54 151 case "artist":
6388af17
D
152 spot = {
153 url: 'https://embed.spotify.com/follow/1/?uri=' + uri +'&size=detail&theme=dark',
154 width: 300,
155 height: 56
156 };
157 break;
158 }
159
160 html = '<iframe src="' + spot.url + '" width="' + spot.width + '" height="' + spot.height + '" frameborder="0" allowtransparency="true"></iframe>';
b3996e54
L
161
162 return $(html);
163 },
f1452889 164
a00899c0
NF
165 soundcloud: function () {
166 var url = this.$el.data('url'),
75381955 167 $content = $('<div></div>').text(_kiwi.global.i18n.translate('client_models_applet_loading').fetch());
a00899c0 168
b38966d8 169 $.getJSON('https://soundcloud.com/oembed', { url: url })
a00899c0
NF
170 .then(function (data) {
171 $content.empty().append(
172 $(data.html).attr('height', data.height - 100)
173 );
174 }, function () {
75381955 175 $content.text(_kiwi.global.i18n.translate('client_views_mediamessage_notfound').fetch());
a00899c0
NF
176 });
177
75381955 178 return $content;
a00899c0 179 },
f1452889 180
2ce6d6e4
D
181 custom: function() {
182 var type = this.constructor.types[this.$el.data('index')];
183
184 if (!type)
185 return;
186
187 return $(type.buildHtml(this.$el.data('url')));
188 }
189
b3996e54
L
190 }
191 }, {
192
8dcc4808
L
193 /**
194 * Add a media message type to append HTML after a matching URL
2ce6d6e4
D
195 * match() should return a truthy value if it wants to handle this URL
196 * buildHtml() should return the HTML string to be used within the drop down
8dcc4808
L
197 */
198 addType: function(match, buildHtml) {
199 if (typeof match !== 'function' || typeof buildHtml !== 'function')
200 return;
201
202 this.types = this.types || [];
203 this.types.push({match: match, buildHtml: buildHtml});
204 },
205
206
50ac472f
D
207 // Build the closed media HTML from a URL
208 buildHtml: function (url) {
209 var html = '', matches;
210
2ce6d6e4 211 _.each(this.types || [], function(type, type_idx) {
8dcc4808
L
212 if (!type.match(url))
213 return;
214
2ce6d6e4 215 // Add which media type should handle this media message. Will be read when it's clicked on
880239e8 216 html += '<span class="media" title="Open" data-type="custom" data-index="'+type_idx+'" data-url="' + _.escape(url) + '"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
8dcc4808
L
217 });
218
50ac472f
D
219 // Is it an image?
220 if (url.match(/(\.jpe?g|\.gif|\.bmp|\.png)\??$/i)) {
880239e8 221 html += '<span class="media image" data-type="image" data-url="' + url + '" title="Open Image"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
50ac472f 222 }
d513dc2c
D
223
224 // Is this an imgur link not picked up by the images regex?
390de62e 225 matches = (/imgur\.com\/[^/]*(?!=\.[^!.]+($|\?))/ig).exec(url);
d513dc2c 226 if (matches && !url.match(/(\.jpe?g|\.gif|\.bmp|\.png)\??$/i)) {
880239e8 227 html += '<span class="media imgur" data-type="imgur" data-url="' + url + '" title="Open Image"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
d513dc2c 228 }
50ac472f
D
229
230 // Is it a tweet?
231 matches = (/https?:\/\/twitter.com\/([a-zA-Z0-9_]+)\/status\/([0-9]+)/ig).exec(url);
232 if (matches) {
880239e8 233 html += '<span class="media twitter" data-type="twitter" data-url="' + url + '" data-tweetid="' + matches[2] + '" title="Show tweet information"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
50ac472f
D
234 }
235
236 // Is reddit?
237 matches = (/reddit\.com\/r\/([a-zA-Z0-9_\-]+)\/comments\/([a-z0-9]+)\/([^\/]+)?/gi).exec(url);
238 if (matches) {
880239e8 239 html += '<span class="media reddit" data-type="reddit" data-url="' + url + '" title="Reddit thread"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
50ac472f 240 }
d513dc2c 241
9ff10506 242 // Is youtube?
1cee8867 243 matches = (/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/gi).exec(url);
9ff10506 244 if (matches) {
880239e8 245 html += '<span class="media youtube" data-type="youtube" data-url="' + url + '" data-ytid="' + matches[1] + '" title="YouTube Video"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
9ff10506 246 }
390de62e 247
5b01f32b
D
248 // Is a github gist?
249 matches = (/https?:\/\/gist\.github\.com\/(?:[a-z0-9-]*\/)?([a-z0-9]+)(\#(.+))?$/i).exec(url);
250 if (matches) {
880239e8 251 html += '<span class="media gist" data-type="gist" data-url="' + url + '" data-gist_id="' + matches[1] + '" title="GitHub Gist"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
5b01f32b
D
252 }
253
b3996e54
L
254 // Is this a spotify link?
255 matches = (/http:\/\/(?:play|open\.)?spotify.com\/(album|track|artist)\/([a-zA-Z0-9]+)\/?/i).exec(url);
256 if (matches) {
257 // Make it a Spotify URI! (spotify:<type>:<id>)
258 var method = matches[1],
259 uri = "spotify:" + matches[1] + ":" + matches[2];
880239e8 260 html += '<span class="media spotify" data-type="spotify" data-uri="' + uri + '" data-method="' + method + '" title="Spotify ' + method + '"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
b3996e54
L
261 }
262
a00899c0
NF
263 matches = (/(?:m\.)?(soundcloud\.com(?:\/.+))/i).exec(url);
264 if (matches) {
265 html += '<span class="media soundcloud" data-type="soundcloud" data-url="http://' + matches[1] + '" title="SoundCloud player"><a class="open"><i class="fa fa-chevron-right"></i></a></span>';
266 }
267
50ac472f
D
268 return html;
269 }
9ff10506 270});