refinerycms-videojs 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/app/assets/images/refinery/admin/add_video_icon.png +0 -0
  2. data/app/assets/javascripts/refinery/admin/wymeditor_monkeypatch.js +13 -0
  3. data/app/assets/stylesheets/refinery/admin/video.css +95 -0
  4. data/app/controllers/refinery/videos/admin/video_files_controller.rb +16 -0
  5. data/app/controllers/refinery/videos/admin/videos_controller.rb +59 -0
  6. data/app/models/refinery/videos/video.rb +119 -0
  7. data/app/models/refinery/videos/video_file.rb +63 -0
  8. data/app/views/refinery/admin/dashboard/_additional_dashboard_menu_items.html.erb +4 -0
  9. data/app/views/refinery/videos/admin/videos/_actions.html.erb +23 -0
  10. data/app/views/refinery/videos/admin/videos/_embed_video_fields.html.erb +45 -0
  11. data/app/views/refinery/videos/admin/videos/_file_fields.html.erb +94 -0
  12. data/app/views/refinery/videos/admin/videos/_form.html.erb +44 -0
  13. data/app/views/refinery/videos/admin/videos/_form_option_fields.html.erb +17 -0
  14. data/app/views/refinery/videos/admin/videos/_new_file_field.html.erb +75 -0
  15. data/app/views/refinery/videos/admin/videos/_preview_form.html.erb +16 -0
  16. data/app/views/refinery/videos/admin/videos/_records.html.erb +18 -0
  17. data/app/views/refinery/videos/admin/videos/_sortable_list.html.erb +5 -0
  18. data/app/views/refinery/videos/admin/videos/_video.html.erb +23 -0
  19. data/app/views/refinery/videos/admin/videos/_videojs_dependencies.html.erb +2 -0
  20. data/app/views/refinery/videos/admin/videos/_videos.html.erb +2 -0
  21. data/app/views/refinery/videos/admin/videos/append_to_wym.js.erb +4 -0
  22. data/app/views/refinery/videos/admin/videos/dialog_preview.js.erb +2 -0
  23. data/app/views/refinery/videos/admin/videos/edit.html.erb +1 -0
  24. data/app/views/refinery/videos/admin/videos/index.html.erb +7 -0
  25. data/app/views/refinery/videos/admin/videos/insert.html.erb +34 -0
  26. data/app/views/refinery/videos/admin/videos/new.html.erb +3 -0
  27. data/app/views/refinery/videos/admin/videos/show.html.erb +4 -0
  28. data/app/views/sitemap/index.xml.builder +25 -0
  29. data/config/initializers/refinery/core.rb +11 -0
  30. data/config/locales/en.yml +76 -0
  31. data/config/locales/ru.yml +77 -0
  32. data/config/routes.rb +24 -0
  33. data/db/migrate/1_create_videos_videos.rb +29 -0
  34. data/db/migrate/2_create_video_file.rb +25 -0
  35. data/lib/generators/refinery/videos/templates/assets/javascripts/videojs_loader.js +7 -0
  36. data/lib/generators/refinery/videos/templates/config/initializers/refinery/videos.rb.erb +20 -0
  37. data/lib/generators/refinery/videos_generator.rb +18 -0
  38. data/lib/refinery/videos/configuration.rb +42 -0
  39. data/lib/refinery/videos/dragonfly.rb +53 -0
  40. data/lib/refinery/videos/engine.rb +32 -0
  41. data/lib/refinery/videos/validators/file_size_validator.rb +19 -0
  42. data/lib/refinery/videos/validators.rb +7 -0
  43. data/lib/refinery/videos.rb +28 -0
  44. data/lib/refinerycms-videojs.rb +1 -0
  45. metadata +138 -0
@@ -0,0 +1,13 @@
1
+ $insert_video_link = "<ul id='add_video'><li><a href='/refinery/videos/insert?dialog=true'>Add Video</a></li></ul>";
2
+ window.onload = function ()
3
+ {
4
+ if ($.wymeditors(0)) {
5
+ $('.wym_area_top').append($insert_video_link);
6
+ init_modal_dialogs();
7
+ }
8
+ };
9
+
10
+ onCloseDialog = function(){
11
+ $('iframe#dialog_iframe').attr('src', '');
12
+ };
13
+
@@ -0,0 +1,95 @@
1
+ #add_video {
2
+ padding-top: 3px;
3
+ padding-left: 10px
4
+ }
5
+
6
+ #add_video li a{
7
+ height: 20px;
8
+ background-image: url('/assets/refinery/admin/add_video_icon.png');
9
+ background-repeat: no-repeat;
10
+ padding-left: 20px;
11
+ }
12
+
13
+ label.inline{
14
+ display: inline-block;
15
+ margin-bottom: 10px;
16
+ margin-top: 0
17
+ }
18
+
19
+ div.inline{
20
+ display: inline-block;
21
+ vertical-align: top;
22
+ margin: 1px 10px 0 0;
23
+ padding-left: 5px
24
+ }
25
+
26
+ div.parent{
27
+ margin-bottom: 20px
28
+ }
29
+
30
+ div.video_container{
31
+ margin: 10px;
32
+ }
33
+
34
+ div.tips{
35
+ margin: 10px 0 10px 0;
36
+ font-style: italic;
37
+ }
38
+
39
+ div.use_file{
40
+ padding-bottom: 5px;
41
+ padding-top: 2px;
42
+ }
43
+ a.select_video_type{
44
+ font-size: 12px;
45
+ margin: 10px 10px 10px 0
46
+ }
47
+
48
+ a.select_video_type.selected{
49
+ font-weight: bold;}
50
+
51
+
52
+ textarea.embed_tag{
53
+ height: 100px
54
+ }
55
+
56
+ span.short_info{
57
+ color: grey
58
+ }
59
+
60
+ div.add_remove_buttons{
61
+ margin-top: 10px
62
+ }
63
+
64
+ div#dialog_list{
65
+ width: 60%; float: left; min-height: 300px
66
+ }
67
+
68
+ div#dialog_list li.selected{
69
+ border: 4px solid #22A7F2
70
+ }
71
+
72
+ div#dialog_preview{
73
+ width:35%; float: right
74
+ }
75
+
76
+ div#preview_form{
77
+ width:35%; float: right
78
+ }
79
+
80
+ div#preview_form div.dimensions{
81
+ width:50%; float:left;
82
+ }
83
+
84
+ div#preview_form div.dimensions input{
85
+ width:70%;
86
+ }
87
+
88
+ div#preview_form div.options{
89
+ width:50%; float:right;
90
+ }
91
+
92
+ div#dialog_list #records{
93
+ width: 100%
94
+ }
95
+
@@ -0,0 +1,16 @@
1
+ module Refinery
2
+ module Videos
3
+ module Admin
4
+ class VideoFilesController < ::Refinery::AdminController
5
+
6
+ def destroy
7
+ @video_file = VideoFile.find(params[:id])
8
+ @video = @video_file.video
9
+ @video_file.destroy
10
+ redirect_to refinery.edit_videos_admin_video_path(@video), :notice => "#{@video_file.file_name} was successfully removed."
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,59 @@
1
+ module Refinery
2
+ module Videos
3
+ module Admin
4
+ class VideosController < ::Refinery::AdminController
5
+
6
+ crudify :'refinery/videos/video',
7
+ :title_attribute => 'title',
8
+ :xhr_paging => true,
9
+ :order => 'position ASC',
10
+ :sortable => true
11
+
12
+ before_filter :set_embedded, :only => [:new, :create]
13
+
14
+ def show
15
+ @video = Video.find(params[:id])
16
+ end
17
+
18
+ def new
19
+ @video = Video.new
20
+ @video.video_files.build
21
+ end
22
+
23
+ def insert
24
+ search_all_videos if searching?
25
+ find_all_videos
26
+ paginate_videos
27
+ end
28
+
29
+ def append_to_wym
30
+ @video = Video.find(params[:video_id])
31
+ params['video'].each do |key, value|
32
+ @video.config[key.to_sym] = value
33
+ end
34
+ @html_for_wym = @video.to_html
35
+ end
36
+
37
+ def dialog_preview
38
+ @video = Video.find(params[:id].delete('video_'))
39
+ w, h = @video.config[:width], @video.config[:height]
40
+ @video.config[:width], @video.config[:height] = 300, 200
41
+ @preview_html = @video.to_html
42
+ @video.config[:width], @video.config[:height] = w, h
43
+ @embedded = true if @video.use_shared
44
+ end
45
+
46
+ private
47
+
48
+ def paginate_videos
49
+ @videos = @videos.paginate(:page => params[:page], :per_page => Video.per_page(true))
50
+ end
51
+
52
+ def set_embedded
53
+ @embedded = true if params['embedded']
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,119 @@
1
+ require 'dragonfly'
2
+
3
+ module Refinery
4
+ module Videos
5
+ class Video < Refinery::Core::BaseModel
6
+
7
+ self.table_name = 'refinery_videos'
8
+ acts_as_indexed :fields => [:title]
9
+
10
+ validates :title, :presence => true
11
+ validate :one_source
12
+
13
+ has_many :video_files, :dependent => :destroy
14
+ accepts_nested_attributes_for :video_files
15
+
16
+ belongs_to :poster, :class_name => '::Refinery::Image'
17
+ accepts_nested_attributes_for :poster
18
+
19
+ ################## Video config options
20
+ serialize :config, Hash
21
+ CONFIG_OPTIONS = {
22
+ :autoplay => "false", :width => "400", :height => "300",
23
+ :controls => "true", :preload => "true", :loop => "true"
24
+ }
25
+
26
+ attr_accessible :title, :poster_id, :video_files_attributes,
27
+ :position, :config, :embed_tag, :use_shared,
28
+ *CONFIG_OPTIONS.keys
29
+
30
+ # Create getters and setters
31
+ CONFIG_OPTIONS.keys.each do |option|
32
+ define_method option do
33
+ self.config[option]
34
+ end
35
+ define_method "#{option}=" do |value|
36
+ self.config[option] = value
37
+ end
38
+ end
39
+ #######################################
40
+
41
+ ########################### Callbacks
42
+ after_initialize :set_default_config
43
+ #####################################
44
+
45
+ def to_html
46
+ if use_shared
47
+ update_from_config
48
+ return embed_tag.html_safe
49
+ end
50
+
51
+ data_setup = []
52
+ CONFIG_OPTIONS.keys.each do |option|
53
+ if option && (option != :width && option != :height)
54
+ data_setup << "\"#{option}\": #{config[option] || '\"auto\"'}"
55
+ end
56
+ end
57
+
58
+ data_setup << "\"poster\": \"#{poster.url}\"" if poster
59
+ sources = []
60
+ video_files.each do |file|
61
+ if file.use_external
62
+ sources << ["<source src='#{file.external_url}' type='#{file.file_mime_type}'/>"]
63
+ else
64
+ sources << ["<source src='#{file.url}' type='#{file.file_mime_type}'/>"]
65
+ end if file.exist?
66
+ end
67
+ html = %Q{<video id="video_#{self.id}" class="video-js vjs-default-skin" width="#{config[:width]}" height="#{config[:height]}" data-setup=' {#{data_setup.join(',')}}'>#{sources.join}</video>}
68
+
69
+ html.html_safe
70
+ end
71
+
72
+
73
+ def short_info
74
+ return [['.shared_source', embed_tag.scan(/src=".+?"/).first]] if use_shared
75
+ info = []
76
+ video_files.each do |file|
77
+ info << file.short_info
78
+ end
79
+
80
+ info
81
+ end
82
+
83
+ ####################################class methods
84
+ class << self
85
+ def per_page(dialog = false)
86
+ dialog ? Videos.pages_per_dialog : Videos.pages_per_admin_index
87
+ end
88
+ end
89
+ #################################################
90
+
91
+ private
92
+
93
+ def set_default_config
94
+ if new_record? && config.empty?
95
+ CONFIG_OPTIONS.each do |option, value|
96
+ self.send("#{option}=", value)
97
+ end
98
+ end
99
+ end
100
+
101
+ def update_from_config
102
+ embed_tag.gsub!(/width="(\d*)?"/, "width=\"#{config[:width]}\"")
103
+ embed_tag.gsub!(/height="(\d*)?"/, "height=\"#{config[:height]}\"")
104
+ #fix iframe overlay
105
+ if embed_tag.include? 'iframe'
106
+ embed_tag =~ /src="(\S+)"/
107
+ embed_tag.gsub!(/src="\S+"/, "src=\"#{$1}?wmode=transparent\"")
108
+ end
109
+ end
110
+
111
+ def one_source
112
+ errors.add(:embed_tag, 'Please embed video') if use_shared && embed_tag.nil?
113
+ errors.add(:video_files, 'Please select at least one source') if !use_shared && video_files.empty?
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,63 @@
1
+ require 'dragonfly'
2
+
3
+ module Refinery
4
+ module Videos
5
+ class VideoFile < Refinery::Core::BaseModel
6
+
7
+ self.table_name = 'refinery_video_files'
8
+ acts_as_indexed :fields => [:file_name, :file_ext]
9
+ attr_accessible :file, :file_mime_type, :position, :use_external, :external_url
10
+ belongs_to :video
11
+
12
+ MIME_TYPES = {'.mp4' => 'mp4', '.flv' => 'flv', '.webm' => 'webm', '.ogg' => 'ogg', '.ogv' => 'ogg'}
13
+
14
+ ############################ Dragonfly
15
+ ::Refinery::Videos::Dragonfly.setup!
16
+ video_accessor :file
17
+
18
+ delegate :ext, :size, :mime_type, :url,
19
+ :to => :file,
20
+ :allow_nil => true
21
+
22
+ #######################################
23
+
24
+ ########################### Validations
25
+ validates :file, :presence => true, :unless => :use_external?
26
+ validates :mime_type, :inclusion => { :in => Refinery::Videos.config[:whitelisted_mime_types],
27
+ :message => "Wrong file mime_type" }, :if => :file_name?
28
+ validates :external_url, :presence => true, :if => :use_external?
29
+ #######################################
30
+
31
+ before_save :set_mime_type
32
+ before_update :set_mime_type
33
+
34
+ def exist?
35
+ use_external ? external_url.present? : file.present?
36
+ end
37
+
38
+ def short_info
39
+ if use_external
40
+ ['.link', external_url]
41
+ else
42
+ ['.file', file_name]
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def set_mime_type
49
+ if use_external
50
+ type = external_url.scan(/\.\w+$/)
51
+ if type.present? && MIME_TYPES.has_key?(type.first)
52
+ self.file_mime_type = "video/#{MIME_TYPES[type.first]}"
53
+ else
54
+ self.file_mime_type = 'video/mp4'
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,4 @@
1
+ <li>
2
+ <%= link_to t('.create_new'), refinery.new_videos_admin_video_path,
3
+ :class => "add_icon" %>
4
+ </li>
@@ -0,0 +1,23 @@
1
+ <ul>
2
+ <li>
3
+ <%= render '/refinery/admin/search', :url => refinery.videos_admin_videos_path %>
4
+ </li>
5
+ <li>
6
+ <%= link_to t('.create_new'), refinery.new_videos_admin_video_path,
7
+ :class => "add_icon" %>
8
+ </li>
9
+ <% if !searching? && ::Refinery::Videos::Admin::VideosController.sortable? && ::Refinery::Videos::Video.any? %>
10
+ <li>
11
+ <%= link_to t('.reorder', :what => "Videos"),
12
+ refinery.videos_admin_videos_path,
13
+ :id => "reorder_action",
14
+ :class => "reorder_icon" %>
15
+
16
+ <%= link_to t('.reorder_done', :what => "Videos"),
17
+ refinery.videos_admin_videos_path,
18
+ :id => "reorder_action_done",
19
+ :style => "display: none;",
20
+ :class => "reorder_icon" %>
21
+ </li>
22
+ <% end %>
23
+ </ul>
@@ -0,0 +1,45 @@
1
+ <div class='field'>
2
+ <%= f.label t('.copy_embed_tag_here') %>
3
+ <%= f.text_area :embed_tag, :class => 'embed_tag', :required => true %>
4
+ </div>
5
+ <%= f.hidden_field :use_shared, :value => true %>
6
+
7
+ <script type="text/javascript">
8
+ $(function(){
9
+ $('textarea.embed_tag').on('input', function(e){
10
+ set_width_and_height($(this))
11
+ });
12
+ $('#video_width').on('input', function(){
13
+ set_in_text_area_width('width', $(this));
14
+ });
15
+ $('#video_height').on('input', function(){
16
+ set_in_text_area_width('height', $(this));
17
+ });
18
+
19
+
20
+ });
21
+
22
+ function set_width_and_height(text_area){
23
+ var val = text_area.val();
24
+ var width = val.match(/width="(\d+)"/);
25
+ if (width) {
26
+ $('#video_width').val(width[1]);
27
+ }
28
+ var height = val.match(/height="(\d+)"/);
29
+ if (height){
30
+ $('#video_height').val(height[1]);
31
+ }
32
+ }
33
+
34
+ function set_in_text_area_width(what, input){
35
+ var val = input.val();
36
+ var text = $('textarea.embed_tag').val();
37
+ var new_text = ''
38
+ if (what == 'width'){
39
+ new_text = text.replace(/width="(\d*|\0)"/, 'width="' + val + '"');
40
+ } else if (what == 'height') {
41
+ new_text = text.replace(/height="(\d*|\0)"/, 'height="' + val + '"');
42
+ }
43
+ $('textarea.embed_tag').val(new_text);
44
+ }
45
+ </script>
@@ -0,0 +1,94 @@
1
+ <label><%= t('.files') %></label>
2
+ <div class='tips'><%= t('.file_tip') %></div>
3
+ <div id='file_fields'>
4
+ <%= f.fields_for :video_files do |v| %>
5
+ <div class="parent">
6
+ <label class="inline">
7
+ <%= v.radio_button :use_external, false, {:class => "use_file"}.merge(v.object.use_external ? {} : {:checked => true}) %>
8
+ <span><%= t('.use_file') %></span>
9
+ </label>
10
+ <label class="inline">
11
+ <%= v.radio_button :use_external, true, {:class => "use_external"}.merge(v.object.use_external ? {:checked => true} : {}) %>
12
+ <span><%= t('.use_external_source') %></span>
13
+ </label>
14
+
15
+ <div class='field'>
16
+ <div class="use_file" <%= "style='display: none;'" if v.object.use_external %>>
17
+ <% if v.object.file.present? %>
18
+ <% if v.object.url %>
19
+ <%= link_to(t('.download_current'), v.object.url,
20
+ :title => v.object.file_name) %>
21
+ <em><%= t('.or') %> </em><%= t('.replace') %>
22
+ <% else %>
23
+ <span><%= t('.add_file') %></span>
24
+ <% end %>
25
+ <%= v.file_field :file %>
26
+ <% else %>
27
+ <span><%= t('.add_file') %></span>
28
+ <%= v.file_field :file, {}.merge(v.object.use_external ? {} : {:required => true}) %>
29
+ <% end %>
30
+ </div>
31
+ <div class="use_external" <%= "style='display: none;'" unless v.object.use_external %>>
32
+ <span><%= t('.link_to_source') %></span>
33
+ <%= v.text_field :external_url, {}.merge(v.object.use_external ? {:required => true} : {}) %>
34
+ </div>
35
+ </div>
36
+ <div class='add_remove_buttons'>
37
+ <% if f.object.video_files.count > 1 %>
38
+ <% if f.object.persisted? %>
39
+ <%= link_to(refinery.videos_admin_video_file_path(v.object),
40
+ :class => "cancel confirm-delete",
41
+ :title => t('.delete'),
42
+ :confirm => t('message', :scope => 'refinery.admin.delete', :title => 'file'),
43
+ :method => :delete) do %>
44
+ <%= refinery_icon_tag("delete.png") %>
45
+ <div class="inline"><%= t('.delete_source') %></div>
46
+ <% end %>
47
+ <% else %>
48
+ <a href='#' onclick="remove_field($(this)); return false" class="remove_field" style='display: none'><%= refinery_icon_tag("delete.png")%>
49
+ <div class="inline"><%= t('.delete_source') %></div>
50
+ </a>
51
+ <% end %>
52
+ <% end %>
53
+ <a href='#' onclick="add_field($(this)); return false" class="add_field" style='display: none'><%= refinery_icon_tag("add.png") %>
54
+ <div class="inline"><%= t('.add_source') %></div>
55
+ </a>
56
+ </div>
57
+ </div>
58
+
59
+ <% end %>
60
+ </div>
61
+
62
+ <% @video.video_files.build %>
63
+ <%= render 'new_file_field', :f => f %>
64
+
65
+ <div class='field' id='maximum_file_size'>
66
+ <label>
67
+ <%= t('.maximum_file_size', :bytes => number_to_human_size(Refinery::Videos.max_file_size)) %>
68
+ </label>
69
+ </div>
70
+
71
+ <script type="text/javascript">
72
+ function radio_control(){
73
+ $('input.use_external').on('change', function(){
74
+ if ($(this).is(':checked')) {
75
+ var $parent = $(this).parents('div.parent');
76
+ $parent.find('div.use_external').show();
77
+ $parent.find('div.use_file').hide();
78
+ $parent.find('.use_file input').removeAttr('required');
79
+ $parent.find('.use_external input').attr('required', 'required');
80
+ }
81
+ });
82
+ $('input.use_file').on('change', function(){
83
+ if ($(this).is(':checked')) {
84
+ var $parent = $(this).parents('div.parent');
85
+ $parent.find('div.use_external').hide();
86
+ $parent.find('div.use_file').show();
87
+ $parent.find('.use_file input').attr('required', 'required');
88
+ $parent.find('.use_external input').removeAttr('required');
89
+ }
90
+ });
91
+ }
92
+
93
+
94
+ </script>
@@ -0,0 +1,44 @@
1
+ <% @embedded = true if @video.use_shared %>
2
+ <%= form_for [refinery, :videos_admin, @video] do |f| %>
3
+ <%= hidden_field_tag(:embedded, true) if @embedded %>
4
+ <%= render '/refinery/admin/error_messages',
5
+ :object => @video,
6
+ :include_object_name => true %>
7
+
8
+ <div class='field'>
9
+ <%= f.label t('.title') %>
10
+ <%= f.text_field :title, :required => true %>
11
+ </div>
12
+
13
+ <% if @embedded %>
14
+ <%= render 'embed_video_fields', :f => f %>
15
+ <% else %>
16
+ <div class='field'>
17
+ <%= f.label t('.poster') %>
18
+ <%= render '/refinery/admin/image_picker',
19
+ :f => f,
20
+ :field => :poster_id,
21
+ :image => @video.poster,
22
+ :toggle_image_display => false %>
23
+
24
+ </div>
25
+ <%= render 'file_fields', :f => f %>
26
+ <% end %>
27
+
28
+ <div class='field'>
29
+ <%= f.label t('.width') %>
30
+ <%= f.text_field :width %>
31
+ </div>
32
+ <div class='field'>
33
+ <%= f.label t('.height') %>
34
+ <%= f.text_field :height %>
35
+ </div>
36
+
37
+ <%= render('form_option_fields', :f => f) unless @embedded %>
38
+
39
+ <%= render '/refinery/admin/form_actions',
40
+ :f => f,
41
+ :continue_editing => false,
42
+ :delete_title => t('delete', :scope => 'refinery.videos.admin.videos.video'),
43
+ :delete_confirmation => t('message', :scope => 'refinery.admin.delete', :title => @video.title) %>
44
+ <% end %>
@@ -0,0 +1,17 @@
1
+ <label><%= t('.options') %></label>
2
+ <div class='field'>
3
+ <%= f.check_box :autoplay, { }, "true", "false" %>
4
+ <%= f.label :autoplay, t('.autoplay'), :class => 'input_label' %>
5
+ </div>
6
+ <div class='field'>
7
+ <%= f.check_box :controls, { }, "true", "false" %>
8
+ <%= f.label :controls, t('.show_ontrols'), :class => 'input_label' %>
9
+ </div>
10
+ <div class='field'>
11
+ <%= f.check_box :preload, { }, "true", "false" %>
12
+ <%= f.label :preload, t('.preload_video'), :class => 'input_label' %>
13
+ </div>
14
+ <div class='field'>
15
+ <%= f.check_box :loop, { }, "true", "false" %>
16
+ <%= f.label :loop, t('.loop_video'), :class => 'input_label' %>
17
+ </div>
@@ -0,0 +1,75 @@
1
+ <%= f.fields_for :video_files, @video.video_files.last do |v| %>
2
+ <div class="new_field" style="display: none">
3
+ <label class="inline">
4
+ <%= v.radio_button :use_external, false, :class => "use_file", :checked => true %>
5
+ <span><%= t('.use_file') %></span>
6
+ </label>
7
+ <label class="inline">
8
+ <%= v.radio_button :use_external, true, :class => "use_external" %>
9
+ <span><%= t('.use_external_source') %></span>
10
+ </label>
11
+ <div class='field'>
12
+ <div class="use_file">
13
+ <span><%= t('.add_file') %></span>
14
+ <%= v.file_field :file, :id => "new_file_field", :required => true %>
15
+ </div>
16
+ <div class="use_external" style='display: none'>
17
+ <span><%= t('.link_to_source') %></span>
18
+ <%= v.text_field :external_url, :id => "new_external_url_field" %>
19
+ </div>
20
+ </div>
21
+ <div class='add_remove_buttons'>
22
+ <a href='#' onclick="remove_field($(this)); return false" class="remove_field"><%= refinery_icon_tag("delete.png")%>
23
+ <div class="inline"><%= t('.delete_source') %></div>
24
+ </a>
25
+ <a href='#' onclick="add_field($(this)); return false" class="add_field"><%= refinery_icon_tag("add.png") %>
26
+ <div class="inline"><%= t('.add_source') %></div>
27
+ </a>
28
+ </div>
29
+ </div>
30
+ <% end %>
31
+
32
+ <script type="text/javascript">
33
+ function add_field(plus){
34
+ plus.parents('div.parent').find('a.add_field').hide();
35
+ plus.parents('div.parent').find('a.remove_field').show();
36
+ prepare_new_field();
37
+ $div = window.new_field.clone();
38
+ $div.addClass('parent');
39
+ $div.removeClass('new_field');
40
+ $('#file_fields').append($div.show());
41
+ radio_control();
42
+ }
43
+
44
+ function remove_field(minus){
45
+ minus.parents('div.parent').remove();
46
+ $('div.parent').last().find('a.add_field').show();
47
+ if ($('div.parent').length > 1) {
48
+ $('div.parent').last().find('a.remove_field').show();
49
+ } else {
50
+ $('div.parent').find('a.remove_field').hide();
51
+ }
52
+ }
53
+
54
+ $(function(){
55
+ radio_control();
56
+ $('div.parent').last().find('a.add_field').show();
57
+ $without_first = $('div.parent').not($('div.parent').first());
58
+ if ($('div.parent').length > 1) {
59
+ $('div.parent').find('a.remove_field').show();
60
+ }
61
+ window.new_field = $('div.new_field').remove();
62
+ $('input[checked="checked"]').attr('checked', 'checked');
63
+ });
64
+
65
+ function prepare_new_field(){
66
+ var $inputs = window.new_field.find('input');
67
+ var date = Number(new Date);
68
+ $.each($inputs, function(){
69
+ var new_name = $(this).attr('name').replace(/\[\d+\]/,'['+date+']');
70
+ $(this).attr('name', new_name);
71
+ var new_id = $(this).attr('id') + date
72
+ $(this).attr('id', new_id);
73
+ });
74
+ }
75
+ </script>