concerto_remote_video 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
};
|