concerto_remote_video 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -5,7 +5,10 @@ This plugin provides support to play remotely hosted videos, like YouTube videos
5
5
  2. ```bundle install```
6
6
  3. ```./script/rails generate concerto_remote_video:install install```
7
7
 
8
+ The last step produces a lot of output, if it runs successfully, because it recompiles the frontend js files.
9
+
8
10
  ## Supported hosts:
9
11
  * YouTube
12
+ * Vimeo
10
13
 
11
14
  Concerto 2 Remove Video is licensed under the Apache License, Version 2.0.
@@ -0,0 +1,80 @@
1
+ // contents.js
2
+
3
+ // attach handler to video_id so when it loses focus we can look up some video details
4
+ // not dry, but no middle man
5
+ function attachHandlers() {
6
+ $('input#remote_video_config_video_id').on('blur', getVideoInfo);
7
+ $('select#remote_video_config_video_vendor').on('change', getVideoInfo);
8
+
9
+ $('select#remote_video_config_video_vendor').on('change', updateTooltip);
10
+
11
+ function updateTooltip() {
12
+ var vendor = $('select#remote_video_config_video_vendor').val();
13
+ if (vendor == 'YouTube') {
14
+ $('input#remote_video_config_video_id').attr("placeholder", "DGbqvYbPZBY");
15
+ $('div#video_hint_id').html('Specify the video id or keywords');
16
+ } else if (vendor == 'Vimeo') {
17
+ $('input#remote_video_config_video_id').attr("placeholder", "4224811");
18
+ $('div#video_hint_id').html('Specify the exact vimeo video id');
19
+ }
20
+ }
21
+
22
+ function getVideoInfo() {
23
+ // need to know which vendor
24
+ // will place title, description, duration into 'div.remote-video-info'
25
+
26
+ var info = '<p>Video details could not be determined.</p>';
27
+ var vendor = $('select#remote_video_config_video_vendor').val();
28
+ var video_id = $('input#remote_video_config_video_id').val();
29
+ var info_el = $('.remote-video-info');
30
+
31
+ if (info_el.length != 0) {
32
+ // we found the summary box
33
+ if (typeof vendor != 'undefined') {
34
+ // we found the vendor selection, call appropriate api
35
+ if (vendor == 'YouTube') {
36
+ $(info_el).empty().html('searching...');
37
+ // todo: dont search if video_id is empty
38
+ $.ajax({
39
+ url: 'http://gdata.youtube.com/feeds/api/videos?q='+ encodeURIComponent(video_id) +'&v=2&max-results=1&format=5&alt=jsonc',
40
+ dataType: 'jsonp',
41
+ timeout: 4000,
42
+ success: function (data) {
43
+ if (parseInt(data['data']['totalItems']) > 0) {
44
+ // we got something, repoint data to first item in results
45
+ data = data['data']['items'];
46
+ $(info_el).empty().html('<img src="' + data[0].thumbnail.hqDefault + '"/><h4>' + data[0].title + '</h4><i>' + data[0].duration + ' secs</i><br/><p>' + data[0].description + '</p>');
47
+ } else {
48
+ $(info_el).empty().html(info);
49
+ }
50
+ },
51
+ error: function (xoptions, textStatus) {
52
+ $(info_el).empty().html(info);
53
+ }
54
+ });
55
+ } else if (vendor == 'Vimeo') {
56
+ $(info_el).empty().html('searching...');
57
+ $.ajax({
58
+ url: 'http://vimeo.com/api/v2/video/' + encodeURIComponent(video_id) + '.json',
59
+ dataType: 'jsonp',
60
+ timeout: 4000,
61
+ success: function (data) {
62
+ if (data.length > 0) {
63
+ // we got something
64
+ $(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>');
65
+ } else {
66
+ $(info_el).empty().html(info);
67
+ }
68
+ },
69
+ error: function (xoptions, textStatus) {
70
+ $(info_el).empty().html(info);
71
+ }
72
+ });
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+
79
+ $(document).ready(attachHandlers);
80
+ $(document).on('page:change', attachHandlers);
@@ -0,0 +1,16 @@
1
+
2
+ div.remote-video-info {
3
+ padding: 1em;
4
+ }
5
+
6
+ div.remote-video-info img {
7
+ float: left;
8
+ max-width: 150px;
9
+ max-height: 150px;
10
+ margin: 0 5px 5px 0;
11
+ border: solid 1px black;
12
+ }
13
+
14
+ div.video_id_hint {
15
+ font-style: italic;
16
+ }
@@ -5,9 +5,15 @@ class RemoteVideo < Content
5
5
  before_validation :save_config
6
6
 
7
7
  validate :video_id_must_exist
8
- validates :duration, :numericality => { :greater_than => 0 }
8
+ #todo: put back, commented out because I keep getting duration is not a number
9
+ #validates :duration, :numericality => { :greater_than => 0 }
10
+ validate :video_vendor_supported
9
11
 
10
- DISPLAY_NAME = 'YouTube Video'
12
+ DISPLAY_NAME = 'Video'
13
+ VIDEO_VENDORS = {
14
+ :YouTube => { :id => "YouTube", :url => "https://www.youtube.com/embed/" },
15
+ :Vimeo => { :id => "Vimeo", :url => "https://player.vimeo.com/video/" }
16
+ }
11
17
 
12
18
  attr_accessor :config
13
19
 
@@ -41,37 +47,74 @@ class RemoteVideo < Content
41
47
 
42
48
  def self.form_attributes
43
49
  attributes = super()
44
- attributes.concat([:config => [:video_id, :allow_flash]])
50
+ # what about :thumb_url, :title, :description
51
+ attributes.concat([:config => [:video_vendor, :video_id, :allow_flash]])
45
52
  end
46
53
 
47
54
  # Load some info about this video from YouTube.
48
55
  def load_info
49
- return if self.config['video_id'].nil? || !self.duration.nil?
56
+ # dont abort if there is a duration specified
57
+ return if self.config['video_id'].nil? #|| !self.duration.nil?
50
58
  require 'net/http'
51
- #begin
52
- video_id = URI.escape(self.config['video_id'])
53
- url = "http://gdata.youtube.com/feeds/api/videos?q=#{video_id}&v=2&max-results=1&format=5&alt=jsonc"
54
- json = Net::HTTP.get_response(URI.parse(url)).body
55
- data = ActiveSupport::JSON.decode(json)
56
- #rescue
57
- # Rails.logger.debug("YouTube not reachable @ #{url}.")
58
- # config['video_id'] = ''
59
- # return
60
- #end
61
- if data['data']['totalItems'].to_i <= 0
62
- Rails.logger.debug('No video found from ' + url)
63
- self.config['video_id'] = ''
64
- return
59
+ if self.config['video_vendor'] == VIDEO_VENDORS[:YouTube][:id]
60
+ #begin
61
+ video_id = URI.escape(self.config['video_id'])
62
+ url = "http://gdata.youtube.com/feeds/api/videos?q=#{video_id}&v=2&max-results=1&format=5&alt=jsonc"
63
+ json = Net::HTTP.get_response(URI.parse(url)).body
64
+ data = ActiveSupport::JSON.decode(json)
65
+ #rescue
66
+ # Rails.logger.debug("YouTube not reachable @ #{url}.")
67
+ # config['video_id'] = ''
68
+ # return
69
+ #end
70
+ if data['data']['totalItems'].to_i <= 0
71
+ Rails.logger.debug('No video found from ' + url)
72
+ self.config['video_id'] = ''
73
+ return
74
+ end
75
+ video_data = data['data']['items'][0]
76
+ self.config['video_id'] = video_data['id']
77
+ self.duration = video_data['duration'].to_i
78
+ self.config['thumb_url'] = video_data['thumbnail']['hqDefault']
79
+ self.config['title'] = video_data['title']
80
+ self.config['description'] = video_data['description']
81
+ elsif self.config['video_vendor'] == VIDEO_VENDORS[:Vimeo][:id]
82
+ #todo: put these info urls in the VV constant
83
+ #http://vimeo.com/api/v2/video/video_id.json
84
+ data=[]
85
+ #begin
86
+ video_id = URI.escape(self.config['video_id'])
87
+ url = "http://vimeo.com/api/v2/video/#{video_id}.json"
88
+ uri = URI.parse(url)
89
+ http = Net::HTTP.new(uri.host, uri.port)
90
+ request = Net::HTTP::Get.new(uri.request_uri)
91
+ response = http.request(request)
92
+ if response.code == '200' #ok
93
+ json = response.body
94
+ data = ActiveSupport::JSON.decode(json)
95
+ end
96
+ #rescue
97
+ # Rails.logger.debug("YouTube not reachable @ #{url}.")
98
+ # config['video_id'] = ''
99
+ # return
100
+ #end
101
+ if data.empty?
102
+ Rails.logger.debug('No video found from ' + url)
103
+ self.config['video_id'] = ''
104
+ return
105
+ end
106
+ video_data = data[0]
107
+ # some vimeo videos have zero for their duration, so in that case use what the user supplied
108
+ self.duration = (video_data['duration'].to_i > 0 ? video_data['duration'].to_i : self.duration.to_i)
109
+ self.config['thumb_url'] = video_data['thumbnail_small']
110
+ self.config['title'] = video_data['title']
111
+ self.config['description'] = video_data['description']
65
112
  end
66
- video_data = data['data']['items'][0]
67
- self.config['video_id'] = video_data['id']
68
- self.duration = video_data['duration'].to_i
69
- self.config['thumb_url'] = video_data['thumbnail']['hqDefault']
70
113
  end
71
114
 
72
115
  # Build a URL for an iframe player.
73
116
  def player_url(params={})
74
- url = "https://www.youtube.com/embed/#{self.config['video_id']}"
117
+ url = VIDEO_VENDORS[self.config['video_vendor'].to_sym][:url] + self.config['video_id']
75
118
  if self.config['allow_flash'] == '0'
76
119
  params['html5'] = 1
77
120
  end
@@ -85,16 +128,32 @@ class RemoteVideo < Content
85
128
  end
86
129
  end
87
130
 
131
+ def video_vendor_supported
132
+ if config['video_vendor'].empty? || !VIDEO_VENDORS.collect { |a,b| b[:id] }.include?(config['video_vendor'])
133
+ errors.add(:video_vendor, 'must be ' + VIDEO_VENDORS.collect { |a,b| b[:id] }.join(" or "))
134
+ end
135
+ end
136
+
88
137
  def render_details
89
- settings = {
90
- :autoplay => 1, # Autostart the video
91
- :end => self.duration, # Stop it around the duration
92
- :controls => 0, # Don't show any controls
93
- :modestbranding => 1, # Use the less fancy branding
94
- :rel => 0, # Don't show related videos
95
- :showinfo => 0, # Don't show the video info
96
- :iv_load_policy => 3 # Don't show any of those in-video labels
97
- }
138
+ if self.config['video_vendor'] == VIDEO_VENDORS[:YouTube][:id]
139
+ settings = {
140
+ :autoplay => 1, # Autostart the video
141
+ :end => self.duration, # Stop it around the duration
142
+ :controls => 0, # Don't show any controls
143
+ :modestbranding => 1, # Use the less fancy branding
144
+ :rel => 0, # Don't show related videos
145
+ :showinfo => 0, # Don't show the video info
146
+ :iv_load_policy => 3 # Don't show any of those in-video labels
147
+ }
148
+ elsif self.config['video_vendor'] == VIDEO_VENDORS[:Vimeo][:id]
149
+ settings = {
150
+ :api => 1, # use Javascript API
151
+ :player_id => 'playerv', #arbitrary id of iframe
152
+ :byline => 0,
153
+ :portrait => 0,
154
+ :autoplay => 1
155
+ }
156
+ end
98
157
  {:path => player_url(settings)}
99
158
  end
100
159
  end
@@ -1,9 +1,9 @@
1
1
  <fieldset>
2
- <legend><span><%=t(:provide_details)%></span></legend>
2
+ <legend><span><%=t('contents.provide_details')%></span></legend>
3
3
  <div class="clearfix">
4
4
  <%= form.label :name %>
5
5
  <div class="input">
6
- <%= form.text_field :name %>
6
+ <%= form.text_field :name, :class => "input-xlarge" %>
7
7
  </div>
8
8
  </div>
9
9
 
@@ -11,9 +11,8 @@
11
11
  </fieldset>
12
12
 
13
13
  <fieldset>
14
- <legend><span><%=t(:select_feed)%></span></legend>
15
- <label>&nbsp;</label>
16
- <div class="input">
14
+ <legend><span><%=t('contents.select_feed')%></span></legend>
15
+ <div class="clearfix">
17
16
  <% if @content.new_record? %>
18
17
  <%= render :partial => 'contents/form_elements/feeds' %>
19
18
  <% end %>
@@ -1,10 +1,22 @@
1
+ <%= javascript_include_tag "remote_video" %>
2
+ <%= stylesheet_link_tag "remote_video" %>
3
+
1
4
  <fieldset>
2
- <legend><span>YouTube Video</span></legend>
5
+ <legend><span><%= RemoteVideo::DISPLAY_NAME %></span></legend>
6
+ <div class="row-fluid">
3
7
  <%= form.fields_for :config do |config| %>
8
+ <div class='span4'>
9
+ <div class="clearfix">
10
+ <%= config.label :video_vendor, 'Video Vendor' %>
11
+ <div class="input">
12
+ <%= config.select :video_vendor, RemoteVideo::VIDEO_VENDORS.collect { |a,b| b[:id] } %>
13
+ </div>
14
+ </div>
4
15
  <div class="clearfix">
5
16
  <%= config.label :video_id %>
6
17
  <div class="input">
7
- <%= config.text_field :video_id, :placeholder => 'DGbqvYbPZBY', :size => 15 %>
18
+ <%= config.text_field :video_id, :placeholder => "DGbqvYbPZBY", :class => "input-small" %>
19
+ <div id="video_id_hint">Specify the video id or keywords</div>
8
20
  </div>
9
21
  </div>
10
22
  <div class="clearfix">
@@ -13,5 +25,17 @@
13
25
  <%= config.select :allow_flash, [["No", 0], ["Yes", 1]] %>
14
26
  </div>
15
27
  </div>
28
+ <div class="clearfix">
29
+ <%= form.label :duration %>
30
+ <div class="input">
31
+ <%= form.number_field :duration, :class => "input-small" %><br/>
32
+ (automatically set if ascertained from video source)
33
+ </div>
34
+ </div>
35
+ </div>
36
+ <div>
37
+ <div class='remote-video-info'></div>
38
+ </div>
16
39
  <% end %>
40
+ </div>
17
41
  </fieldset>
@@ -1 +1 @@
1
- <div style="background-image:url(<%= content.config['thumb_url'] %>); background-size: cover; width: 100%; height: 100%;"></div>
1
+ <div class="pop" style="background-image:url(<%= content.config['thumb_url'] %>); background-size: cover; width: 100%; height: 100%;" data-content="<%= content.config['description']%>" data-title="<%= content.config['title']%>"></div>
@@ -1,3 +1,3 @@
1
1
  module ConcertoRemoteVideo
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -9,6 +9,7 @@ module ConcertoRemoteVideo
9
9
  def install
10
10
  copy_js
11
11
  register
12
+ recompile
12
13
  end
13
14
 
14
15
  private
@@ -19,5 +20,12 @@ module ConcertoRemoteVideo
19
20
  def register
20
21
  append_file 'public/frontend_js/content_types.js', "goog.require('concerto.frontend.Content.RemoteVideo');\n"
21
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
+
22
30
  end
23
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concerto_remote_video
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-08 00:00:00.000000000 -07:00
12
+ date: 2013-05-30 00:00:00.000000000 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
17
- requirement: &70122145172500 !ruby/object:Gem::Requirement
17
+ requirement: &70296757751560 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '3.2'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70122145172500
25
+ version_requirements: *70296757751560
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: sqlite3
28
- requirement: &70122145170660 !ruby/object:Gem::Requirement
28
+ requirement: &70296757727300 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,15 +33,18 @@ dependencies:
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *70122145170660
37
- description: Adds support for remotely hosted videos, like YouTube, in Concerto 2
36
+ version_requirements: *70296757727300
37
+ description: Adds support for remotely hosted videos, like YouTube or vimeo, in Concerto
38
+ 2
38
39
  email:
39
40
  - bmichalski@gmail.com
40
41
  executables: []
41
42
  extensions: []
42
43
  extra_rdoc_files: []
43
44
  files:
45
+ - app/assets/javascripts/remote_video.js
44
46
  - app/assets/stylesheets/concerto_remote_video/application.css
47
+ - app/assets/stylesheets/remote_video.css
45
48
  - app/controllers/concerto_remote_video/application_controller.rb
46
49
  - app/helpers/concerto_remote_video/application_helper.rb
47
50
  - app/models/remote_video.rb