concerto_remote_video 0.3 → 0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/concerto_remote_video/remote_video.js +86 -80
- data/app/controllers/concerto_remote_video/application_controller.rb +1 -1
- data/app/controllers/concerto_remote_video/remote_video_controller.rb +12 -0
- data/app/helpers/concerto_remote_video/application_helper.rb +1 -1
- data/app/models/remote_video.rb +89 -96
- data/app/views/frontend/_concerto_remote_video.html +37 -0
- data/config/routes.rb +4 -0
- data/lib/concerto_remote_video/engine.rb +9 -1
- data/lib/concerto_remote_video/version.rb +1 -1
- data/lib/concerto_remote_video.rb +1 -1
- metadata +30 -17
- data/lib/generators/concerto_remote_video/install_generator.rb +0 -31
- data/lib/tasks/concerto_remote_video_tasks.rake +0 -4
- data/public/frontend_js/contents/remote_video.js +0 -97
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: caf9e3fc8733e9ce4f3bf12f9106c12ec940bb19
|
|
4
|
+
data.tar.gz: 45a04bab69ebc87c2b0416853278d26f8607f455
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fc8385b9186679c85d221bddd20a4d3e94d4120ba91c983abbb4fd10b5ca3cc93014770fc9c7b9dd1c7b22cfe9caa9c0cc1a8d7c1794110a316471341d96f12a
|
|
7
|
+
data.tar.gz: 194518905108f1541db8f329ecdb7d6209f17530426e2e484ddb84bebe5bf32ef58ca008ac409045c23d5f8fe426553fb8d51295550a7a89a7aa97d34a51f89b
|
|
@@ -2,104 +2,110 @@ var initializedRemoteVideoHandlers = false;
|
|
|
2
2
|
function initializeRemoteVideoHandlers() {
|
|
3
3
|
if (!initializedRemoteVideoHandlers) {
|
|
4
4
|
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
// will place title, description, duration into 'div.remote-video-info'
|
|
5
|
+
function getVideoPreview() {
|
|
6
|
+
var preview_url = '/concerto-remote-video/preview';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
var vendor = $('select#remote_video_config_video_vendor').val();
|
|
8
|
+
// Form video details
|
|
11
9
|
var video_id = $('input#remote_video_config_video_id').val();
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
var video_vendor = $('select#remote_video_config_video_vendor').val();
|
|
11
|
+
|
|
12
|
+
// Loading icon
|
|
13
|
+
if (video_id.length != 0) {
|
|
14
|
+
$(preview_div).empty().html('<i class=\"ficon-spinner icon-spin\"></i> searching...');
|
|
15
|
+
$('.remote-video-info').empty();
|
|
16
|
+
// Video preview request
|
|
17
|
+
$.ajax({
|
|
18
|
+
type: 'POST',
|
|
19
|
+
url: preview_url,
|
|
20
|
+
data: {
|
|
21
|
+
video_id: video_id,
|
|
22
|
+
video_vendor: video_vendor
|
|
23
|
+
},
|
|
24
|
+
success: function(data) {
|
|
25
|
+
loadVideoInfo(data);
|
|
26
|
+
loadVideoPreview(data);
|
|
27
|
+
},
|
|
28
|
+
error: function(e) {
|
|
29
|
+
loadVideoPreview({video_available: false});
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
15
34
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
timeout: 4000,
|
|
47
|
-
success: function (data) {
|
|
48
|
-
if (data.length > 0) {
|
|
49
|
-
// we got something
|
|
50
|
-
$(info_el).empty().html('<img src="' + data[0].thumbnail_small + '"/><h4>' + data[0].title + '</h4><i>' + data[0].duration + ' secs</i><br/><p>' + data[0].description + '</p>');
|
|
51
|
-
previewVideo();
|
|
52
|
-
} else {
|
|
53
|
-
$(info_el).empty().html(info);
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
error: function (xoptions, textStatus) {
|
|
57
|
-
$(info_el).empty().html(info);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
} else if (vendor == 'HTTPVideo') {
|
|
61
|
-
$(info_el).empty();
|
|
62
|
-
if (video_id != "")
|
|
63
|
-
{
|
|
64
|
-
previewVideo();
|
|
35
|
+
function loadVideoInfo(data) {
|
|
36
|
+
if (data['video_available']) {
|
|
37
|
+
// Target elements for setting video info
|
|
38
|
+
var info_el = $('.remote-video-info');
|
|
39
|
+
var name_el = $('input#remote_video_name');
|
|
40
|
+
var duration_el = $('input#remote_video_duration');
|
|
41
|
+
// Initialize info content
|
|
42
|
+
var title = '';
|
|
43
|
+
var description = '<p></p>';
|
|
44
|
+
var duration = '';
|
|
45
|
+
var vendor = data['video_vendor'];
|
|
46
|
+
|
|
47
|
+
if (vendor == 'HTTPVideo') {
|
|
48
|
+
$(info_el).empty();
|
|
49
|
+
return;
|
|
50
|
+
} else {
|
|
51
|
+
// YouTube no longer returns these details without an API key
|
|
52
|
+
if (vendor != 'YouTube') {
|
|
53
|
+
if (data['description']) {
|
|
54
|
+
// Preview video description
|
|
55
|
+
var description = '<p>' + data['description'] + '</p>';
|
|
56
|
+
}
|
|
57
|
+
if (data['title']) {
|
|
58
|
+
// Set content title to video returned title
|
|
59
|
+
name_el.val(data['title']);
|
|
60
|
+
}
|
|
61
|
+
if (data['duration']) {
|
|
62
|
+
// Set content duration to video duration
|
|
63
|
+
duration = '<i>' + data['duration'] + ' secs</i>';
|
|
64
|
+
duration_el.val(data['duration']);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Load video info
|
|
70
|
+
var info = '<img src="'+data['thumb_url']+'"/></h4>'+duration+'<br/>'+description;
|
|
71
|
+
$(info_el).empty().html(info);
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
function
|
|
72
|
-
var
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
$("#preview_div").load(url, { data: {
|
|
78
|
-
video_vendor: $('select#remote_video_config_video_vendor').val(),
|
|
79
|
-
video_id: video_id,
|
|
80
|
-
allow_flash: $('input#remote_video_config_allow_flash').val(),
|
|
81
|
-
duration: $('input#remote_video_duration').val(),
|
|
82
|
-
name: $('input#remote_video_name').val()
|
|
83
|
-
}, type: 'RemoteVideo' });
|
|
75
|
+
function loadVideoPreview(data) {
|
|
76
|
+
var preview_el = $('#preview_div');
|
|
77
|
+
if (data['video_available']) {
|
|
78
|
+
$(preview_div).empty().html(data['preview_code']);
|
|
79
|
+
} else {
|
|
80
|
+
$(preview_div).empty();
|
|
84
81
|
}
|
|
85
82
|
}
|
|
86
83
|
|
|
87
84
|
function updateTooltip() {
|
|
88
85
|
var vendor = $('select#remote_video_config_video_vendor').val();
|
|
86
|
+
var hint_el = $('div#video_id_hint');
|
|
87
|
+
var id_el = $('input#remote_video_config_video_id');
|
|
88
|
+
|
|
89
89
|
if (vendor == 'YouTube') {
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
id_el.attr('placeholder', 'DGbqvYbPZBY');
|
|
91
|
+
hint_el.html('Specify the exact YouTube video id');
|
|
92
92
|
} else if (vendor == 'Vimeo') {
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
id_el.attr('placeholder', '4224811');
|
|
94
|
+
hint_el.html('Specify the exact vimeo video id');
|
|
95
95
|
} else if (vendor == 'HTTPVideo') {
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
id_el.attr('placeholder', 'http://media.w3.org/2010/05/sintel/trailer.mp4');
|
|
97
|
+
hint_el.html('Specify the url of the video');
|
|
98
|
+
} else if (vendor == 'Wistia') {
|
|
99
|
+
id_el.attr('placeholder', 'g5pnf59ala');
|
|
100
|
+
hint_el.html('Specify the exact Wistia video id');
|
|
101
|
+
} else if (vendor == 'DailyMotion') {
|
|
102
|
+
id_el.attr('placeholder', 'x23shps');
|
|
103
|
+
hint_el.html('Specify the exact DailyMotion video id');
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
|
|
101
|
-
$('input#remote_video_config_video_id').on('blur',
|
|
102
|
-
$('select#remote_video_config_video_vendor').on('change',
|
|
107
|
+
$('input#remote_video_config_video_id').on('blur', getVideoPreview);
|
|
108
|
+
$('select#remote_video_config_video_vendor').on('change', getVideoPreview);
|
|
103
109
|
$('select#remote_video_config_video_vendor').on('change', updateTooltip);
|
|
104
110
|
|
|
105
111
|
initializedRemoteVideoHandlers = true;
|
|
@@ -107,4 +113,4 @@ function initializeRemoteVideoHandlers() {
|
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
$(document).ready(initializeRemoteVideoHandlers);
|
|
110
|
-
$(document).on('page:change', initializeRemoteVideoHandlers);
|
|
116
|
+
$(document).on('page:change', initializeRemoteVideoHandlers);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module ConcertoRemoteVideo
|
|
2
|
+
class RemoteVideoController < ConcertoRemoteVideo::ApplicationController
|
|
3
|
+
def preview
|
|
4
|
+
@video_data = RemoteVideo.preview({
|
|
5
|
+
video_vendor: params[:video_vendor],
|
|
6
|
+
video_id: params[:video_id]
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
render json: @video_data
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/app/models/remote_video.rb
CHANGED
|
@@ -13,9 +13,11 @@ class RemoteVideo < Content
|
|
|
13
13
|
|
|
14
14
|
DISPLAY_NAME = 'Video'
|
|
15
15
|
VIDEO_VENDORS = {
|
|
16
|
-
|
|
16
|
+
:HTTPVideo => { :id => "HTTPVideo", :name => "Self-hosted Video", :url => ""},
|
|
17
17
|
:YouTube => { :id => "YouTube", :name => "YouTube", :url => "https://www.youtube.com/embed/" },
|
|
18
|
-
:Vimeo => { :id => "Vimeo", :name => "Vimeo", :url => "https://player.vimeo.com/video/" }
|
|
18
|
+
:Vimeo => { :id => "Vimeo", :name => "Vimeo", :url => "https://player.vimeo.com/video/" },
|
|
19
|
+
:Wistia => { :id => "Wistia", :name => "Wistia", :url => "https://fast.wistia.net/embed/iframe/" },
|
|
20
|
+
:DailyMotion => { :id => "DailyMotion", :name => "DailyMotion", :url => "https://www.dailymotion.com/embed/video/" }
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
attr_accessor :config
|
|
@@ -56,111 +58,61 @@ class RemoteVideo < Content
|
|
|
56
58
|
|
|
57
59
|
# Load some info about this video from YouTube.
|
|
58
60
|
def load_info
|
|
61
|
+
require 'video_info'
|
|
62
|
+
|
|
59
63
|
# dont abort if there is a duration specified
|
|
60
64
|
return if self.config['video_id'].nil? #|| !self.duration.nil?
|
|
61
65
|
return if !self.new_record?
|
|
62
|
-
|
|
63
|
-
require 'net/http'
|
|
64
66
|
if self.config['video_vendor'] == VIDEO_VENDORS[:YouTube][:id]
|
|
65
|
-
|
|
66
|
-
video_id = URI.escape(self.config['video_id'])
|
|
67
|
-
url = "http://gdata.youtube.com/feeds/api/videos?q=#{video_id}&v=2&max-results=1&format=5&alt=jsonc"
|
|
68
|
-
json = Net::HTTP.get_response(URI.parse(url)).body
|
|
69
|
-
data = ActiveSupport::JSON.decode(json)
|
|
70
|
-
rescue MultiJson::ParseError => e
|
|
71
|
-
Rails.logger.error("Could not parse results from YouTube @ #{url}: #{e.message}: #{json}")
|
|
72
|
-
errors.add(:video_id, "Could not parse results from YouTube")
|
|
73
|
-
return
|
|
74
|
-
rescue
|
|
75
|
-
Rails.logger.error("YouTube not reachable @ #{url}.")
|
|
76
|
-
errors.add(:video_id, "Could not get information about video from YouTube")
|
|
77
|
-
return
|
|
78
|
-
end
|
|
79
|
-
if data['data']['totalItems'].to_i <= 0
|
|
80
|
-
Rails.logger.error('No video found from ' + url)
|
|
81
|
-
self.config['video_id'] = ''
|
|
82
|
-
return
|
|
83
|
-
end
|
|
84
|
-
return if data['data'].nil? || data['data']['items'].nil?
|
|
85
|
-
video_data = data['data']['items'][0]
|
|
86
|
-
self.config['video_id'] = video_data['id']
|
|
87
|
-
self.duration = video_data['duration'].to_i
|
|
88
|
-
self.config['thumb_url'] = video_data['thumbnail']['hqDefault']
|
|
89
|
-
self.config['title'] = video_data['title']
|
|
90
|
-
self.config['description'] = video_data['description']
|
|
67
|
+
video = VideoInfo.new("http://www.youtube.com/watch?v=#{URI.escape(self.config['video_id'])}")
|
|
91
68
|
elsif self.config['video_vendor'] == VIDEO_VENDORS[:Vimeo][:id]
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
|
98
|
-
request = Net::HTTP::Get.new(uri.request_uri)
|
|
99
|
-
response = http.request(request)
|
|
100
|
-
if response.code == '200' #ok
|
|
101
|
-
json = response.body
|
|
102
|
-
data = ActiveSupport::JSON.decode(json)
|
|
103
|
-
end
|
|
104
|
-
rescue => e
|
|
105
|
-
Rails.logger.error("Could not get information about video from Vimeo @ #{url}: #{e.message}")
|
|
106
|
-
config['video_id'] = ''
|
|
107
|
-
return
|
|
108
|
-
end
|
|
109
|
-
if data.empty?
|
|
110
|
-
Rails.logger.debug('No video found from ' + url)
|
|
111
|
-
self.config['video_id'] = ''
|
|
112
|
-
return
|
|
113
|
-
end
|
|
114
|
-
video_data = data[0]
|
|
115
|
-
# some vimeo videos have zero for their duration, so in that case use what the user supplied
|
|
116
|
-
self.duration = (video_data['duration'].to_i > 0 ? video_data['duration'].to_i : self.duration.to_i)
|
|
117
|
-
self.config['thumb_url'] = video_data['thumbnail_small']
|
|
118
|
-
self.config['title'] = video_data['title']
|
|
119
|
-
self.config['description'] = video_data['description']
|
|
69
|
+
video = VideoInfo.new("http://vimeo.com/#{URI.escape(self.config['video_id'])}")
|
|
70
|
+
elsif self.config['video_vendor'] == VIDEO_VENDORS[:Wistia][:id]
|
|
71
|
+
video = VideoInfo.new("http://fast.wistia.com/embed/medias/#{URI.escape(self.config['video_id'])}")
|
|
72
|
+
elsif self.config['video_vendor'] == VIDEO_VENDORS[:DailyMotion][:id]
|
|
73
|
+
video = VideoInfo.new("http://dailymotion.com/video/#{URI.escape(self.config['video_id'])}")
|
|
120
74
|
elsif self.config['video_vendor'] == VIDEO_VENDORS[:HTTPVideo][:id]
|
|
121
|
-
self
|
|
122
|
-
self.config['
|
|
123
|
-
self.config['
|
|
124
|
-
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Build a URL for an iframe player.
|
|
128
|
-
def player_url(params={})
|
|
129
|
-
url = VIDEO_VENDORS[self.config['video_vendor'].to_sym][:url] + self.config['video_id']
|
|
130
|
-
if self.config['allow_flash'] == '0'
|
|
131
|
-
params['html5'] = 1
|
|
75
|
+
# self hosted video, skip video info gem configuration below
|
|
76
|
+
self.config['preview_code'] = "<video preload controls width=\"100%\"><source src=\"#{self.config['video_id']}\" /></video>"
|
|
77
|
+
self.config['video_available'] = true
|
|
78
|
+
return
|
|
132
79
|
end
|
|
133
|
-
url += '?' + URI.escape(params.collect{|k,v| "#{k}=#{v}"}.join('&'))
|
|
134
|
-
return url
|
|
135
|
-
end
|
|
136
80
|
|
|
137
|
-
|
|
138
|
-
if
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
81
|
+
# Video info gem details
|
|
82
|
+
if !video.nil? and video.available?
|
|
83
|
+
# some vimeo videos have zero for their duration, so in that case use what the user supplied
|
|
84
|
+
self.duration = (video.duration.to_i > 0 ? video.duration.to_i : self.duration.to_i)
|
|
85
|
+
self.config['title'] = video.title
|
|
86
|
+
self.config['description'] = video.description
|
|
87
|
+
self.config['video_id'] = video.video_id
|
|
88
|
+
self.config['duration'] = video.duration
|
|
89
|
+
self.config['preview_url'] = video.embed_url
|
|
90
|
+
self.config['preview_code'] = video.embed_code
|
|
91
|
+
# set video thumbnail using video info or using YouTube image url to bypass API restrictions
|
|
92
|
+
if video.provider == VIDEO_VENDORS[:YouTube][:id]
|
|
93
|
+
self.config['thumb_url'] = "https://i.ytimg.com/vi/" + video.video_id + "/hqdefault.jpg"
|
|
94
|
+
else
|
|
95
|
+
self.config['thumb_url'] = video.thumbnail_large
|
|
96
|
+
end
|
|
146
97
|
end
|
|
98
|
+
# Store video availablility to skip preview rendering
|
|
99
|
+
self.config['video_available'] = video.available?
|
|
147
100
|
end
|
|
148
101
|
|
|
149
102
|
def self.preview(data)
|
|
103
|
+
require 'video_info'
|
|
104
|
+
|
|
150
105
|
begin
|
|
151
106
|
o = RemoteVideo.new()
|
|
152
107
|
o.config['video_id'] = data[:video_id]
|
|
153
108
|
o.config['video_vendor'] = data[:video_vendor]
|
|
154
|
-
o.
|
|
155
|
-
o.name = data[:name]
|
|
156
|
-
o.duration = data[:duration]
|
|
109
|
+
o.load_info
|
|
157
110
|
|
|
158
|
-
results = o.render_preview
|
|
159
111
|
rescue => e
|
|
160
|
-
|
|
112
|
+
return "Unable to preview. #{e.message}"
|
|
161
113
|
end
|
|
162
114
|
|
|
163
|
-
return
|
|
115
|
+
return o.config
|
|
164
116
|
end
|
|
165
117
|
|
|
166
118
|
def preview
|
|
@@ -173,6 +125,28 @@ class RemoteVideo < Content
|
|
|
173
125
|
return results
|
|
174
126
|
end
|
|
175
127
|
|
|
128
|
+
# Build a URL for an iframe player.
|
|
129
|
+
def player_url(params={})
|
|
130
|
+
url = VIDEO_VENDORS[self.config['video_vendor'].to_sym][:url] + self.config['video_id']
|
|
131
|
+
if self.config['allow_flash'] == '0'
|
|
132
|
+
params['html5'] = 1
|
|
133
|
+
end
|
|
134
|
+
url += '?' + URI.escape(params.collect{|k,v| "#{k}=#{v}"}.join('&'))
|
|
135
|
+
return url
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def video_id_must_exist
|
|
139
|
+
if config['video_id'].empty?
|
|
140
|
+
errors.add(:video_id, 'could not be found')
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def video_vendor_supported
|
|
145
|
+
if config['video_vendor'].empty? || !VIDEO_VENDORS.collect { |a,b| b[:id] }.include?(config['video_vendor'])
|
|
146
|
+
errors.add(:video_vendor, 'must be ' + VIDEO_VENDORS.collect { |a,b| b[:id] }.join(" or "))
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
176
150
|
def render_details
|
|
177
151
|
if self.config['video_vendor'] == VIDEO_VENDORS[:YouTube][:id]
|
|
178
152
|
settings = {
|
|
@@ -186,14 +160,30 @@ class RemoteVideo < Content
|
|
|
186
160
|
}
|
|
187
161
|
elsif self.config['video_vendor'] == VIDEO_VENDORS[:Vimeo][:id]
|
|
188
162
|
settings = {
|
|
189
|
-
:api => 1,
|
|
190
|
-
:player_id => 'playerv',
|
|
191
|
-
:byline => 0,
|
|
192
|
-
:
|
|
193
|
-
:
|
|
163
|
+
:api => 1, # use Javascript API
|
|
164
|
+
:player_id => 'playerv', #arbitrary id of iframe
|
|
165
|
+
:byline => 0, # Hide video byline
|
|
166
|
+
:badge => 0, # Hide vendor logo
|
|
167
|
+
:portrait => 0, # Don't show user's portrait
|
|
168
|
+
:autoplay => 1, # Autostart the video
|
|
169
|
+
:title => 0 # Hide video title
|
|
170
|
+
}
|
|
171
|
+
elsif self.config['video_vendor'] == VIDEO_VENDORS[:Wistia][:id]
|
|
172
|
+
settings = {
|
|
173
|
+
:autoPlay => true, # Autostart the video
|
|
174
|
+
:chromeless => true, # Don't show any controls
|
|
175
|
+
:playerColor => 'black' # Change player outlines to black
|
|
176
|
+
}
|
|
177
|
+
elsif self.config['video_vendor'] == VIDEO_VENDORS[:DailyMotion][:id]
|
|
178
|
+
settings = {
|
|
179
|
+
:autoplay => 1, # Autostart the video
|
|
180
|
+
:chromeless => 1, # Don't show any controls
|
|
181
|
+
:info => 0, # Hide video information
|
|
182
|
+
:logo => 0, # Hide vendor logo
|
|
183
|
+
:related => 0 # Don't show related videos at end
|
|
194
184
|
}
|
|
195
185
|
elsif self.config['video_vendor'] == VIDEO_VENDORS[:HTTPVideo][:id]
|
|
196
|
-
settings = {
|
|
186
|
+
settings = {
|
|
197
187
|
:autoplay => 1, # Autostart the video
|
|
198
188
|
:end => self.duration, # Stop it around the duration
|
|
199
189
|
:controls => 0, # Don't show any controls
|
|
@@ -203,11 +193,14 @@ class RemoteVideo < Content
|
|
|
203
193
|
end
|
|
204
194
|
|
|
205
195
|
def render_preview
|
|
206
|
-
if self.config['video_vendor'] == RemoteVideo::VIDEO_VENDORS[:YouTube][:id] ||
|
|
196
|
+
if self.config['video_vendor'] == RemoteVideo::VIDEO_VENDORS[:YouTube][:id] ||
|
|
197
|
+
self.config['video_vendor'] == RemoteVideo::VIDEO_VENDORS[:Vimeo][:id] ||
|
|
198
|
+
self.config['video_vendor'] == RemoteVideo::VIDEO_VENDORS[:Wistia][:id] ||
|
|
199
|
+
self.config['video_vendor'] == RemoteVideo::VIDEO_VENDORS[:DailyMotion][:id]
|
|
207
200
|
player_settings = { :end => self.duration, :rel => 0, :theme => 'light', :iv_load_policy => 3 }
|
|
208
|
-
results =
|
|
201
|
+
results = self.config['preview_code']
|
|
209
202
|
elsif self.config['video_vendor'] == RemoteVideo::VIDEO_VENDORS[:HTTPVideo][:id]
|
|
210
|
-
results =
|
|
203
|
+
results = self.config['preview_code']
|
|
211
204
|
end
|
|
212
205
|
|
|
213
206
|
results
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
The `concerto-remote-video` element provides embedded video.
|
|
3
|
+
@element concerto-content
|
|
4
|
+
@status alpha
|
|
5
|
+
-->
|
|
6
|
+
<polymer-element name="concerto-remote-video" attributes="path" constructor="ConcertoRemoteVideo" extends="concerto-content">
|
|
7
|
+
<template>
|
|
8
|
+
<style>
|
|
9
|
+
:host {
|
|
10
|
+
display: block;
|
|
11
|
+
width: 100%;
|
|
12
|
+
height: 100%;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
:host(.core-transition) {
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#video {
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
}
|
|
23
|
+
</style>
|
|
24
|
+
<iframe id="video" frameBorder="0"></iframe>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
Polymer({
|
|
29
|
+
domReady: function() {
|
|
30
|
+
this.$.video.src = this.path;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
34
|
+
</polymer-element>
|
|
35
|
+
<script>
|
|
36
|
+
registerContentType("concerto-remote-video", "ConcertoRemoteVideo");
|
|
37
|
+
</script>
|
data/config/routes.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
Rails.application.routes.draw do
|
|
2
2
|
resources :remote_videos, :controller => :contents, :except => [:index, :show], :path => "content"
|
|
3
3
|
end
|
|
4
|
+
|
|
5
|
+
ConcertoRemoteVideo::Engine.routes.draw do
|
|
6
|
+
post "preview", to: ConcertoRemoteVideo::RemoteVideoController.action(:preview)
|
|
7
|
+
end
|
|
@@ -5,5 +5,13 @@ module ConcertoRemoteVideo
|
|
|
5
5
|
initializer "register content type" do |app|
|
|
6
6
|
app.config.content_types << RemoteVideo
|
|
7
7
|
end
|
|
8
|
+
|
|
9
|
+
# Define plugin information for the Concerto application to read
|
|
10
|
+
def plugin_info(plugin_info_class)
|
|
11
|
+
@plugin_info ||= plugin_info_class.new do
|
|
12
|
+
add_route("concerto-remote-video", ConcertoRemoteVideo::Engine)
|
|
13
|
+
add_view_hook "frontend/ScreensController", :concerto_frontend_plugins, partial: "frontend/concerto_remote_video.html"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
8
16
|
end
|
|
9
|
-
end
|
|
17
|
+
end
|
metadata
CHANGED
|
@@ -1,27 +1,41 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: concerto_remote_video
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.4'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Michalski
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2015-05-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '0'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- -
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: video_info
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
25
39
|
- !ruby/object:Gem::Version
|
|
26
40
|
version: '0'
|
|
27
41
|
description: Adds support for remotely hosted videos, like YouTube or vimeo, in Concerto
|
|
@@ -32,11 +46,15 @@ executables: []
|
|
|
32
46
|
extensions: []
|
|
33
47
|
extra_rdoc_files: []
|
|
34
48
|
files:
|
|
49
|
+
- LICENSE
|
|
50
|
+
- README.md
|
|
51
|
+
- Rakefile
|
|
35
52
|
- app/assets/javascripts/concerto_remote_video/application.js
|
|
36
53
|
- app/assets/javascripts/concerto_remote_video/remote_video.js
|
|
37
54
|
- app/assets/stylesheets/concerto_remote_video/application.css
|
|
38
55
|
- app/assets/stylesheets/concerto_remote_video/remote_video.css
|
|
39
56
|
- app/controllers/concerto_remote_video/application_controller.rb
|
|
57
|
+
- app/controllers/concerto_remote_video/remote_video_controller.rb
|
|
40
58
|
- app/helpers/concerto_remote_video/application_helper.rb
|
|
41
59
|
- app/models/remote_video.rb
|
|
42
60
|
- app/views/contents/remote_video/_form_middle.html.erb
|
|
@@ -45,22 +63,20 @@ files:
|
|
|
45
63
|
- app/views/contents/remote_video/_render_grid.html.erb
|
|
46
64
|
- app/views/contents/remote_video/_render_tile.html.erb
|
|
47
65
|
- app/views/contents/remote_video/_tab_icon.html.erb
|
|
66
|
+
- app/views/frontend/_concerto_remote_video.html
|
|
48
67
|
- config/routes.rb
|
|
68
|
+
- lib/concerto_remote_video.rb
|
|
49
69
|
- lib/concerto_remote_video/engine.rb
|
|
50
70
|
- lib/concerto_remote_video/version.rb
|
|
51
|
-
- lib/concerto_remote_video.rb
|
|
52
|
-
- lib/generators/concerto_remote_video/install_generator.rb
|
|
53
|
-
- lib/tasks/concerto_remote_video_tasks.rake
|
|
54
|
-
- public/frontend_js/contents/remote_video.js
|
|
55
|
-
- LICENSE
|
|
56
|
-
- Rakefile
|
|
57
|
-
- README.md
|
|
58
71
|
- test/concerto_remote_video_test.rb
|
|
72
|
+
- test/dummy/README.rdoc
|
|
73
|
+
- test/dummy/Rakefile
|
|
59
74
|
- test/dummy/app/assets/javascripts/application.js
|
|
60
75
|
- test/dummy/app/assets/stylesheets/application.css
|
|
61
76
|
- test/dummy/app/controllers/application_controller.rb
|
|
62
77
|
- test/dummy/app/helpers/application_helper.rb
|
|
63
78
|
- test/dummy/app/views/layouts/application.html.erb
|
|
79
|
+
- test/dummy/config.ru
|
|
64
80
|
- test/dummy/config/application.rb
|
|
65
81
|
- test/dummy/config/boot.rb
|
|
66
82
|
- test/dummy/config/database.yml
|
|
@@ -76,13 +92,10 @@ files:
|
|
|
76
92
|
- test/dummy/config/initializers/wrap_parameters.rb
|
|
77
93
|
- test/dummy/config/locales/en.yml
|
|
78
94
|
- test/dummy/config/routes.rb
|
|
79
|
-
- test/dummy/config.ru
|
|
80
95
|
- test/dummy/public/404.html
|
|
81
96
|
- test/dummy/public/422.html
|
|
82
97
|
- test/dummy/public/500.html
|
|
83
98
|
- test/dummy/public/favicon.ico
|
|
84
|
-
- test/dummy/Rakefile
|
|
85
|
-
- test/dummy/README.rdoc
|
|
86
99
|
- test/dummy/script/rails
|
|
87
100
|
- test/fixtures/concerto_remote_video/remote_videos.yml
|
|
88
101
|
- test/integration/navigation_test.rb
|
|
@@ -98,17 +111,17 @@ require_paths:
|
|
|
98
111
|
- lib
|
|
99
112
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
113
|
requirements:
|
|
101
|
-
- -
|
|
114
|
+
- - ">="
|
|
102
115
|
- !ruby/object:Gem::Version
|
|
103
116
|
version: '0'
|
|
104
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
118
|
requirements:
|
|
106
|
-
- -
|
|
119
|
+
- - ">="
|
|
107
120
|
- !ruby/object:Gem::Version
|
|
108
121
|
version: '0'
|
|
109
122
|
requirements: []
|
|
110
123
|
rubyforge_project:
|
|
111
|
-
rubygems_version: 2.
|
|
124
|
+
rubygems_version: 2.2.2
|
|
112
125
|
signing_key:
|
|
113
126
|
specification_version: 4
|
|
114
127
|
summary: Remotely hosted video for Concerto 2
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
require 'rails/generators'
|
|
2
|
-
|
|
3
|
-
module ConcertoRemoteVideo
|
|
4
|
-
class InstallGenerator < Rails::Generators::Base
|
|
5
|
-
source_root File.expand_path('../../../../', __FILE__)
|
|
6
|
-
|
|
7
|
-
desc 'Copy the RemoteVideo JavaScript to the frontend and register it.'
|
|
8
|
-
|
|
9
|
-
def install
|
|
10
|
-
copy_js
|
|
11
|
-
register
|
|
12
|
-
recompile
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
private
|
|
16
|
-
def copy_js
|
|
17
|
-
copy_file 'public/frontend_js/contents/remote_video.js', 'public/frontend_js/contents/remote_video.js'
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def register
|
|
21
|
-
append_file 'public/frontend_js/content_types.js', "goog.require('concerto.frontend.Content.RemoteVideo');\n"
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def recompile
|
|
25
|
-
inside 'public/frontend_js' do
|
|
26
|
-
run('/bin/bash compile.sh', {:verbose => true})
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
goog.provide('concerto.frontend.Content.RemoteVideo');
|
|
2
|
-
|
|
3
|
-
goog.require('concerto.frontend.Content');
|
|
4
|
-
goog.require('concerto.frontend.ContentTypeRegistry');
|
|
5
|
-
goog.require('goog.Uri');
|
|
6
|
-
goog.require('goog.dom');
|
|
7
|
-
goog.require('goog.events');
|
|
8
|
-
goog.require('goog.events.EventType');
|
|
9
|
-
goog.require('goog.style');
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Remote Video.
|
|
15
|
-
*
|
|
16
|
-
* @param {Object} data Properties for this piece of content.
|
|
17
|
-
* @constructor
|
|
18
|
-
* @extends {concerto.frontend.Content}
|
|
19
|
-
*/
|
|
20
|
-
concerto.frontend.Content.RemoteVideo = function(data) {
|
|
21
|
-
concerto.frontend.Content.call(this, data);
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The height of the field the image is being shown in.
|
|
25
|
-
* @type {number}
|
|
26
|
-
* @private
|
|
27
|
-
*/
|
|
28
|
-
this.field_height_ = parseFloat(data['field']['size']['height']);
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* The width of the field the image is being shown in.
|
|
32
|
-
* @type {number}
|
|
33
|
-
* @private
|
|
34
|
-
*/
|
|
35
|
-
this.field_width_ = parseFloat(data['field']['size']['width']);
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The iframe being displayed.
|
|
39
|
-
* @type {Object}
|
|
40
|
-
*/
|
|
41
|
-
this.iframe = null;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* The URL for the video / iframe.
|
|
45
|
-
* @type {string}
|
|
46
|
-
*/
|
|
47
|
-
this.video_url = data['render_details']['path'];
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Extra parameters to include in the URL.
|
|
51
|
-
* @type {?string}
|
|
52
|
-
* @private
|
|
53
|
-
*/
|
|
54
|
-
this.url_parms_ = (data['field']['config'] ? data['field']['config']['url_parms'] : null);
|
|
55
|
-
if (goog.isDefAndNotNull(this.url_parms_)) {
|
|
56
|
-
this.url_parms_ = this.url_parms_.trim();
|
|
57
|
-
if (goog.string.startsWith(this.url_parms_, '?'))
|
|
58
|
-
this.url_parms_ = goog.string.remove(this.url_parms_, '?');
|
|
59
|
-
if (goog.string.startsWith(this.url_parms_, '&'))
|
|
60
|
-
this.url_parms_ = goog.string.remove(this.url_parms_, '&');
|
|
61
|
-
if (goog.string.contains(this.video_url, '?')) {
|
|
62
|
-
this.url_parms_ = '&' + this.url_parms_;
|
|
63
|
-
} else {
|
|
64
|
-
this.url_parms_ = '?' + this.url_parms_;
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
this.url_parms_ = '';
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Bump the duration of this content by 1 second.
|
|
72
|
-
* This attempts to account for 1 second of load time and should be
|
|
73
|
-
* improved in the future.
|
|
74
|
-
*/
|
|
75
|
-
this.duration = this.duration + 1;
|
|
76
|
-
};
|
|
77
|
-
goog.inherits(concerto.frontend.Content.RemoteVideo, concerto.frontend.Content);
|
|
78
|
-
|
|
79
|
-
// Register the content type.
|
|
80
|
-
concerto.frontend.ContentTypeRegistry['RemoteVideo'] =
|
|
81
|
-
concerto.frontend.Content.RemoteVideo;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Build the embed iframe and signal that we're ready to use it.
|
|
86
|
-
* @private
|
|
87
|
-
*/
|
|
88
|
-
concerto.frontend.Content.RemoteVideo.prototype.load_ = function() {
|
|
89
|
-
this.iframe = goog.dom.createElement('iframe');
|
|
90
|
-
this.iframe.src = this.video_url + this.url_parms_;
|
|
91
|
-
this.iframe.frameborder = 0;
|
|
92
|
-
goog.style.setSize(this.iframe, '100%', '100%');
|
|
93
|
-
goog.style.setSize(this.div_, '100%', '100%');
|
|
94
|
-
goog.style.setStyle(this.iframe, 'border', 0);
|
|
95
|
-
goog.dom.appendChild(this.div_, this.iframe);
|
|
96
|
-
this.finishLoad();
|
|
97
|
-
};
|