tb_media 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +28 -0
  4. data/Readme.markdown +73 -0
  5. data/app/assets/images/spud/admin/files_thumbs/dat_thumb.png +0 -0
  6. data/app/assets/images/spud/admin/files_thumbs/doc_thumb.png +0 -0
  7. data/app/assets/images/spud/admin/files_thumbs/jpg_thumb.png +0 -0
  8. data/app/assets/images/spud/admin/files_thumbs/mp3_thumb.png +0 -0
  9. data/app/assets/images/spud/admin/files_thumbs/pdf_thumb.png +0 -0
  10. data/app/assets/images/spud/admin/files_thumbs/png_thumb.png +0 -0
  11. data/app/assets/images/spud/admin/files_thumbs/ppt_thumb.png +0 -0
  12. data/app/assets/images/spud/admin/files_thumbs/txt_thumb.png +0 -0
  13. data/app/assets/images/spud/admin/files_thumbs/xls_thumb.png +0 -0
  14. data/app/assets/images/spud/admin/files_thumbs/zip_thumb.png +0 -0
  15. data/app/assets/images/spud/admin/media/checkers.jpg +0 -0
  16. data/app/assets/images/spud/admin/media_thumb.png +0 -0
  17. data/app/assets/images/spud/admin/media_thumb@2x.png +0 -0
  18. data/app/assets/images/spud/admin/media_tiny.png +0 -0
  19. data/app/assets/javascripts/spud/admin/media/application.js +175 -0
  20. data/app/assets/javascripts/spud/admin/media/picker.js +219 -0
  21. data/app/assets/javascripts/spud/admin/media/plugin.js +99 -0
  22. data/app/assets/libs/jcrop/css/Jcrop.gif +0 -0
  23. data/app/assets/libs/jcrop/css/jquery.Jcrop.css +165 -0
  24. data/app/assets/libs/jcrop/css/jquery.Jcrop.min.css +29 -0
  25. data/app/assets/libs/jcrop/js/jquery.Jcrop.js +1694 -0
  26. data/app/assets/libs/jcrop/js/jquery.Jcrop.min.js +22 -0
  27. data/app/assets/libs/jcrop/js/jquery.color.js +661 -0
  28. data/app/assets/libs/jcrop/js/jquery.min.js +4 -0
  29. data/app/assets/libs/tiny_mce/plugins/spud_media/blank.htm +12 -0
  30. data/app/assets/libs/tiny_mce/plugins/spud_media/css/template.css +23 -0
  31. data/app/assets/libs/tiny_mce/plugins/spud_media/editor_plugin.js +1 -0
  32. data/app/assets/libs/tiny_mce/plugins/spud_media/editor_plugin_src.js +159 -0
  33. data/app/assets/libs/tiny_mce/plugins/spud_media/js/template.js +106 -0
  34. data/app/assets/libs/tiny_mce/plugins/spud_media/langs/en_dlg.js +1 -0
  35. data/app/assets/libs/tiny_mce/plugins/spud_media/template.htm +31 -0
  36. data/app/assets/stylesheets/spud/admin/media/application.css +103 -0
  37. data/app/assets/stylesheets/spud/admin/media/plugin.css +154 -0
  38. data/app/controllers/protected_media_controller.rb +26 -0
  39. data/app/controllers/spud/admin/media_controller.rb +73 -0
  40. data/app/controllers/spud/admin/media_picker_controller.rb +28 -0
  41. data/app/helpers/protected_media_helper.rb +3 -0
  42. data/app/helpers/spud/admin/users_helper.rb +2 -0
  43. data/app/helpers/spud/user_sessions_helper.rb +2 -0
  44. data/app/models/spud_media.rb +154 -0
  45. data/app/views/spud/admin/media/edit.html.erb +50 -0
  46. data/app/views/spud/admin/media/index.html.erb +37 -0
  47. data/app/views/spud/admin/media/new.html.erb +26 -0
  48. data/app/views/spud/admin/media_picker/_media.html.erb +19 -0
  49. data/app/views/spud/admin/media_picker/create.html.erb +1 -0
  50. data/app/views/spud/admin/media_picker/create.js.erb +1 -0
  51. data/app/views/spud/admin/media_picker/index.html.erb +103 -0
  52. data/config/routes.rb +13 -0
  53. data/db/migrate/20120101194256_create_spud_media.rb +11 -0
  54. data/db/migrate/20120501203325_add_protected_to_spud_media.rb +6 -0
  55. data/db/migrate/20120508132153_add_cropping_to_spud_media.rb +9 -0
  56. data/lib/spud_media/configuration.rb +11 -0
  57. data/lib/spud_media/engine.rb +16 -0
  58. data/lib/spud_media/version.rb +5 -0
  59. data/lib/tasks/spud_media_tasks.rake +15 -0
  60. data/lib/tb_media.rb +6 -0
  61. metadata +257 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTZjMTJmNTgwYzNkZWM0OWVmMzAwMGU5NGYwM2IxNjk2ZWIzYTRlOA==
5
+ data.tar.gz: !binary |-
6
+ N2Q1NTRmNjhmYTVkN2I3MWQ4M2RhNmEzZGY5MTNjNzM2NmRhYWE3YQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ OGNjYTE0MmU1OTU1NzRiZDMwY2IxZWUyZGJhYTliZDk5Y2ZhYmVjMzUwZTdl
10
+ YmRiNzFhMDhlM2I4MjgxMGVmNDVjMWNhNzEzZmY4ZTE0YmI5YmExMjUzNTZk
11
+ MTE2ZjcwOGRlOTFlNDVhYTU3ZDBhYmQ1ZjY1ZGEzNDc5ZmIzNjg=
12
+ data.tar.gz: !binary |-
13
+ OGNhOTM1ZWNmYzgzM2RhOTNkZjRmOGVjMTVhMjM4MTI1ZmU3YTk2MmNkMWIx
14
+ YmNmMmRmOTA3YjAzYWIxYjAxYzQwZTQxNzdiODJiODEzMjYxNGNkOGYwMWY3
15
+ YWJhYjMzMjM4N2I3YWMyOTdiYjc0ZDZiODg0MTU4ZTZjOTU0MDQ=
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'SpudMedia'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake'
data/Readme.markdown ADDED
@@ -0,0 +1,73 @@
1
+ # Spud Media
2
+
3
+ Spud Media is an engine for managing documents and other miscellaneous media files, designed for use with [Spud][1].
4
+
5
+ ## Installation/Usage
6
+
7
+ 1. In your Gemfile add the following
8
+
9
+ gem 'spud_media'
10
+
11
+ 2. Run bundle install
12
+ 3. Copy in database migrations to your new rails project
13
+
14
+ bundle exec rake railties:install:migrations
15
+ rake db:migrate
16
+
17
+ 4. Run a rails server instance and point your browser to /spud/admin
18
+
19
+ ## Configuration
20
+
21
+ Spud Photos accepts the following configuration options:
22
+
23
+ Spud::Media.configure do |config|
24
+
25
+ # s3 storage requires the 'aws-sdk' gem. defaults to filesystem
26
+ config.paperclip_storage = :s3
27
+ config.s3_credentials = "#{Rails.root}/config/s3.yml"
28
+
29
+ # see below for notes on 'storage_path_protected'
30
+ config.storage_path = "public/system/spud_media/:id/:style/:basename.:extension"
31
+ config.storage_path_protected = "public/system/spud_media_protected/:id/:style/:basename.:extension"
32
+ config.storage_url = "/system/spud_media/:id/:style/:basename.:extension"
33
+ end
34
+
35
+ ## File Protection
36
+
37
+ Spud Media allows for individual files to be marked as protected. How this is actually implemented depends on whether you are using the local file system or Amazon S3 for file storage.
38
+
39
+ ### Filesystem
40
+
41
+ Unprotected files are stored under `/public/system/spud_media` and are accessed directly by the web server. No further configuration is required, though you may customize the storage location if desired using `config.storage_path`.
42
+
43
+ Protected files are moved to `public/system/spud_media_protected`. Note that the public-facing download URL should __not__ reflect the `protected` storage path. Instead the user will hit the same URL as before, but this time their request will hit the `show` action of the `ProtectedMedia` controller.
44
+
45
+ __It is up to the individual developer to make sure that the protected storage path is not accessible by the public.__ You may choose to protect this folder via server configurations, or you can move the folder out of the document root using `config.storage_path_protected`.
46
+
47
+ ### Amazon S3
48
+
49
+ Files marked as unprotected will be uploaded to Amazon using the `public_read` ACL. These files are accessed directly - ie, calling `@media.attachment_url` will link directly to Amazon.
50
+
51
+ Files marked as protected are uploaded using the `private` ACL. In this case, calling `@media.attachment_url` will return a local URL that hits the show action of our `ProtectedMedia` controller. Once we have verified the user is logged in we generate a secure URL and redirect the user to it. The generated URL is good for 10 minutes.
52
+
53
+ [1]:https://github.com/davydotcom/spud_core_admin
54
+
55
+ Testing
56
+ -----------------
57
+
58
+ Spud uses RSpec for testing. Get the tests running with a few short commands:
59
+
60
+ 1. Create and migrate the databases:
61
+
62
+ rake db:create
63
+ rake db:migrate
64
+
65
+ 2. Load the schema in to the test database:
66
+
67
+ rake app:db:test:prepare
68
+
69
+ 3. Run the tests with RSpec
70
+
71
+ rspec spec
72
+
73
+ After the tests have completed the current code coverage stats is available by opening ```/coverage/index.html``` in a browser.
@@ -0,0 +1,175 @@
1
+ //= require jcrop/js/jquery.Jcrop
2
+ //= require spud/admin/media/plugin
3
+ //= require spud/admin/media/picker
4
+ //= require_self
5
+
6
+ spud.admin.media = new function(){
7
+
8
+ var self = this;
9
+ var cropimage;
10
+ var cropcontainer;
11
+ var croptarget;
12
+ var cropscale;
13
+ var maxcropscale;
14
+ var cropscaleincrement;
15
+ var originalWidth;
16
+ var originalHeight;
17
+ var cropartbox;
18
+ var jcrop;
19
+
20
+ this.edit = function(){
21
+ cropimage = $('#spud_media_cropper_image');
22
+ // IE8 isn't handling the image load event properly, so...
23
+ setTimeout(function(){
24
+ if(cropimage[0].complete){
25
+ self.initializeEditor();
26
+ }
27
+ else{
28
+ self.edit();
29
+ }
30
+ }, 50);
31
+ };
32
+
33
+ this.initializeEditor = function(){
34
+
35
+ // cache some selectors
36
+ cropcontainer = $('#spud_media_cropper_jcrop_container');
37
+ cropartbox = $('#spud_media_cropper');
38
+
39
+ // get the original dimensions before scaling the image down
40
+ originalWidth = cropimage.width();
41
+ originalHeight = cropimage.height();
42
+
43
+ // the max width is 900px (at least until the UI can handle more than that)
44
+ if(originalWidth > 900){
45
+ maxcropscale = Math.floor(900 / originalWidth * 100);
46
+ }
47
+ else{
48
+ maxcropscale = 100;
49
+ }
50
+ cropscaleincrement = Math.ceil(3.0 * (maxcropscale / 100));
51
+
52
+ // scale down the original if necessary
53
+ cropscale = parseInt($('#spud_media_crop_s').val(), 10);
54
+ if(cropscale > maxcropscale){
55
+ $('#spud_media_crop_s').val(maxcropscale);
56
+ cropscale = maxcropscale;
57
+ }
58
+
59
+ // if this is a new image, width and hight will be null. set some starter values.
60
+ if(!$('#spud_media_crop_w').val()){
61
+ $('#spud_media_crop_w').val(originalWidth * (maxcropscale / 100));
62
+ $('#spud_media_crop_h').val(originalHeight * (maxcropscale / 100));
63
+ }
64
+
65
+ // update height of artbox to match height of scaled image
66
+ cropartbox.height(originalHeight * (maxcropscale / 100));
67
+
68
+ self.resizeAndCenter(cropscale);
69
+
70
+ $('body').on('change', '#spud_media_crop_s', self.changedMediaCropScale);
71
+ $('body').on('click', '#spud_media_cropper_resize_up, #spud_media_cropper_resize_down', self.incrementMediaCropScale);
72
+ $('body').on('change', '#spud_media_crop_x, #spud_media_crop_y, #spud_media_crop_w, #spud_media_crop_h', self.changedMediaCropDimensions);
73
+ $('body').on('keypress', 'form input[type=text]', self.preventSubmitOnEnterKey);
74
+ };
75
+
76
+ this.resizeAndCenter = function(percent){
77
+
78
+ // destroy the jcrop object if it exists already
79
+ if(jcrop){
80
+ jcrop.destroy();
81
+ }
82
+
83
+ // initialize jcrop. snap to pre-existing selection if one exists.
84
+ var _width = Math.min(900, (originalWidth * (percent / 100)));
85
+ var _height = originalHeight * (_width / originalWidth);
86
+ cropimage.Jcrop({
87
+ boxWidth:_width,
88
+ boxHeight:_height,
89
+ onChange:self.updateCropCoordinates,
90
+ onSelect:self.updateCropCoordinates,
91
+ setSelect:self.getSelectFields()
92
+ },
93
+ function(){
94
+ jcrop = this;
95
+ }
96
+ );
97
+
98
+ // using the outer container, center the jcrop object in the artboard
99
+ var _left = (900 - _width) / 2;
100
+ var _top = (cropartbox.height() - _height) / 6;
101
+ cropcontainer.css({
102
+ left:_left,
103
+ top:_top
104
+ });
105
+ };
106
+
107
+ this.updateCropCoordinates = function(c){
108
+ $('#spud_media_crop_x').val(Math.floor(c.x * (cropscale / 100)));
109
+ $('#spud_media_crop_y').val(Math.floor(c.y * (cropscale / 100)));
110
+ $('#spud_media_crop_w').val(Math.floor(c.w * (cropscale / 100)));
111
+ $('#spud_media_crop_h').val(Math.floor(c.h * (cropscale / 100)));
112
+ };
113
+
114
+ this.changedMediaCropScale = function(e){
115
+ var val = $(this).val();
116
+ var percent = parseInt(val, 10);
117
+ if(!percent || percent > maxcropscale){
118
+ $(this).val(maxcropscale);
119
+ }
120
+ else{
121
+ $(this).val(percent);
122
+ cropscale = percent;
123
+ self.resizeAndCenter(percent);
124
+ }
125
+ };
126
+
127
+ this.incrementMediaCropScale = function(e){
128
+ var id = $(this).attr('id');
129
+ if(id == 'spud_media_cropper_resize_up'){
130
+ cropscale = Math.min(maxcropscale, cropscale+cropscaleincrement);
131
+ }
132
+ else{
133
+ cropscale = Math.max(0, cropscale-cropscaleincrement);
134
+ }
135
+ $('#spud_media_crop_s').val(cropscale);
136
+ self.resizeAndCenter(cropscale);
137
+ return false;
138
+ };
139
+
140
+ this.changedMediaCropDimensions = function(e){
141
+ var selection = self.getSelectFields();
142
+ if(selection){
143
+ jcrop.setSelect(selection);
144
+ }
145
+ };
146
+
147
+ this.getSelectFields = function(){
148
+ var x = parseInt($('#spud_media_crop_x').val(), 10);
149
+ var y = parseInt($('#spud_media_crop_y').val(), 10);
150
+ var w = parseInt($('#spud_media_crop_w').val(), 10);
151
+ var h = parseInt($('#spud_media_crop_h').val(), 10);
152
+ var x2 = x + w;
153
+ var y2 = y + h;
154
+ if(isNaN(x) || isNaN(w) || isNaN(x2) || isNaN(y2)){
155
+ return false;
156
+ }
157
+ else{
158
+ return [x * (100 / cropscale), y * (100 / cropscale), x2 * (100 / cropscale), y2 * (100 / cropscale)];
159
+ }
160
+ };
161
+
162
+ this.preventSubmitOnEnterKey = function(e){
163
+ if(e.keyCode == 13) {
164
+ e.preventDefault();
165
+ // need to prevent the form submit, but still fire the value change events
166
+ if($(this).attr('id') == 'spud_media_crop_s'){
167
+ self.changedMediaCropScale.apply(this, [e]);
168
+ }
169
+ else{
170
+ self.changedMediaCropDimensions(e);
171
+ }
172
+ return false;
173
+ }
174
+ };
175
+ };
@@ -0,0 +1,219 @@
1
+ spud.admin.mediapicker = new function(){
2
+
3
+ var self = this;
4
+ var supportsHtml5Upload = false;
5
+ var selectedFile = {};
6
+
7
+ self.init = function(){
8
+ if(typeof(FormData) != 'undefined'){
9
+ supportsHtml5Upload = true;
10
+ }
11
+ $('.spud_media_picker_tab').on('click', self.clickedTab);
12
+ $('.spud_media_picker_upload_form').on('submit', self.submittedUpload);
13
+ $('.spud_media_picker_list').on('click', '.spud_media_picker_item', self.clickedListItem);
14
+ $('.spud_media_picker_button_cancel').on('click', self.clickedCancel);
15
+ $('.spud_media_picker_button_use_selected').on('click', self.clickedUseSelected);
16
+ $('.spud_media_picker_button_insert').on('click', self.clickedInsert);
17
+ $('.spud_media_picker_item').first().click();
18
+ $('.spud_media_picker_tabs a').first().click();
19
+ $('.spud_media_picker_tab_advanced').on('spud_media_picker_tab_activated', self.activatedAdvancedTab);
20
+ $('.spud_media_picker_option_dimensions').on('blur', 'input', self.dimensionsChanged);
21
+ $('.spud_media_picker_option').on('keyup', 'input[type=text]', self.pickerOptionKeyDown);
22
+ };
23
+
24
+ self.clickedTab = function(e){
25
+ e.preventDefault();
26
+ self.goToTab($(this).attr('href'));
27
+ };
28
+
29
+ self.goToTab = function(tabName){
30
+ $('.spud_media_picker_tab_active').removeClass('spud_media_picker_tab_active');
31
+ $('a[href="'+tabName+'"]').addClass('spud_media_picker_tab_active');
32
+ var selector = tabName.replace('#', '.');
33
+ $('.spud_media_picker_tab_body').hide();
34
+ $(selector).show();
35
+ $(selector).trigger('spud_media_picker_tab_activated');
36
+ };
37
+
38
+ self.clickedListItem = function(){
39
+ $('.spud_media_picker_item_selected').removeClass('spud_media_picker_item_selected');
40
+ var element = $(this);
41
+ element.addClass('spud_media_picker_item_selected');
42
+ $('.spud_media_picker_details_thumb').attr('src', element.find('img').attr('src'));
43
+ $('.spud_media_picker_details_name').text(element.attr('data-name'));
44
+ $('.spud_media_picker_details_size').text(element.attr('data-size'));
45
+ $('.spud_media_picker_details_lastmod').text(element.attr('data-lastmod'));
46
+ $('.spud_media_picker_details_protected').text(element.attr('data-protected'));
47
+ $('.spud_media_picker_details').show();
48
+ };
49
+
50
+ self.clickedCancel = function(e){
51
+ e.preventDefault();
52
+ tinyMCEPopup.close();
53
+ };
54
+
55
+ self.clickedUseSelected = function(e){
56
+ e.preventDefault();
57
+ self.goToTab('#spud_media_picker_tab_advanced');
58
+ };
59
+
60
+ self.submittedUpload = function(e){
61
+ if(!$('#spud_media_attachment').val()){
62
+ window.alert("Please select a file.");
63
+ return false;
64
+ }
65
+
66
+ if(supportsHtml5Upload){
67
+ e.preventDefault();
68
+
69
+ // create html5 form object
70
+ var fd = new FormData();
71
+ var form = $(this);
72
+ var file = form.find('#spud_media_attachment')[0].files[0];
73
+ fd.append('_method', form.find('[name=_method]').val());
74
+ fd.append('authenticity_token', form.find('[name=authenticity_token]').val());
75
+ fd.append('spud_media[attachment]', file);
76
+
77
+ // upload via xhr
78
+ var xhr = new XMLHttpRequest();
79
+ xhr.upload.addEventListener('progress', self.onFileUploadProgress);
80
+ xhr.addEventListener('load', self.onFileUploadComplete);
81
+ xhr.addEventListener('error', self.onFileUploadError);
82
+ xhr.addEventListener('abort', self.onFileUploadAbort);
83
+ xhr.open('POST', form.attr('action'));
84
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
85
+ xhr.send(fd);
86
+
87
+ $('.spud_media_picker_upload_progress').show();
88
+ }
89
+ };
90
+
91
+ this.onFileUploadProgress = function(e){
92
+ var percent = Math.round(e.loaded * 100 / e.total);
93
+ var progress = $('.spud_media_picker_upload_progress');
94
+ progress.find('.bar').css({width: percent + '%'});
95
+ if(percent == 100){
96
+ progress.addClass('progress-success');
97
+ }
98
+ };
99
+
100
+ this.onFileUploadComplete = function(e){
101
+ var html = e.target.response;
102
+ self.onLegacyUploadComplete(html);
103
+ };
104
+
105
+ this.onFileUploadError = function(e){
106
+ window.alert('Whoops! Something has gone wrong.');
107
+ self.resetUploadForm();
108
+ };
109
+
110
+ this.onFileUploadAbort = function(e){
111
+ self.resetUploadForm();
112
+ };
113
+
114
+ // Non-html5 upload
115
+ this.onLegacyUploadComplete = function(html){
116
+ $('.spud_media_picker_list').prepend(html);
117
+ $('.spud_media_picker_item').first().click();
118
+ self.goToTab('#spud_media_picker_tab_choose');
119
+ self.resetUplaodForm();
120
+ };
121
+
122
+ this.resetUploadForm = function(){
123
+ // reset twitter bootstrap "loading" button state
124
+ $('.spud_media_picker_tab_upload_submit').button('reset');
125
+ $('#spud_media_attachment').val('');
126
+ $('.spud_media_picker_upload_progress').hide();
127
+ $('.spud_media_picker_upload_progress .bar').css({width:0});
128
+ };
129
+
130
+ this.activatedAdvancedTab = function(){
131
+ var selected = $('.spud_media_picker_item_selected');
132
+ selectedFile = {
133
+ id: selected.attr('data-id'),
134
+ type: selected.attr('data-type'),
135
+ url: selected.attr('data-url'),
136
+ name: selected.attr('data-name'),
137
+ size: selected.attr('data-size'),
138
+ lastmod: selected.attr('data-lastmod'),
139
+ isprotected: selected.attr('data-protected')
140
+ };
141
+ $('input[name="spud_media_picker_option_selected_file"]').val(selectedFile.name);
142
+ $('input[name="spud_media_picker_option_type"]').val(selectedFile.type == 'img' ? 'Image' : 'File');
143
+ if(selectedFile.type == 'img'){
144
+ $('.spud_media_picker_option_target').hide();
145
+ $('.spud_media_picker_option_text').hide();
146
+ $('.spud_media_picker_option_float').show();
147
+ $('.spud_media_picker_option_title').show();
148
+ $('.spud_media_picker_option_dimensions').show();
149
+ self.getOriginalImageDimensions(selectedFile.url);
150
+ }
151
+ else{
152
+ $('.spud_media_picker_option_target').show();
153
+ $('.spud_media_picker_option_text').show();
154
+ $('.spud_media_picker_option_text input').val(tinyMCEPopup.editor.selection.getContent());
155
+ $('.spud_media_picker_option_float').hide();
156
+ $('.spud_media_picker_option_title').hide();
157
+ $('.spud_media_picker_option_dimensions').hide();
158
+ }
159
+ };
160
+
161
+ var _originalWidth, _originalHeight;
162
+ self.getOriginalImageDimensions = function(url){
163
+ var img = new Image();
164
+ img.onload = function(){
165
+ _originalWidth = img.width;
166
+ _originalHeight = img.height;
167
+ };
168
+ img.src = url;
169
+ };
170
+
171
+ self.dimensionsChanged = function(e){
172
+ var element = $(this);
173
+ var val = parseInt(element.val(), 10);
174
+ if(isNaN(val)){
175
+ element.val('');
176
+ return;
177
+ }
178
+ var name = element.attr('name');
179
+ if(name == 'spud_media_picker_option_dimension_w'){
180
+ var height = Math.floor((_originalHeight/_originalWidth) * val);
181
+ $('input[name="spud_media_picker_option_dimension_h"]').val(height);
182
+ }
183
+ else{
184
+ var width = Math.ceil((_originalWidth/_originalHeight) * val);
185
+ $('input[name="spud_media_picker_option_dimension_w"]').val(width);
186
+ }
187
+ };
188
+
189
+ self.clickedInsert = function(e){
190
+ e.preventDefault();
191
+ if(selectedFile.type == 'img'){
192
+ selectedFile.title = $('input[name="spud_media_picker_option_title"]').val();
193
+ selectedFile.width = parseInt($('input[name="spud_media_picker_option_dimension_w"]').val(), 10);
194
+ selectedFile.height = parseInt($('input[name="spud_media_picker_option_dimension_h"]').val(), 10);
195
+ var float = $('select[name="spud_media_picker_option_float"]').val();
196
+ var style = "";
197
+ if(float){
198
+ style += "float:" + float + ";";
199
+ }
200
+ selectedFile.style = style;
201
+ }
202
+ else{
203
+ selectedFile.target = $('select[name="spud_media_picker_option_target"]').val();
204
+ selectedFile.text = $('input[name="spud_media_picker_option_text"]').val();
205
+ if(!selectedFile.text){
206
+ window.alert("Link Text is a required field.");
207
+ return;
208
+ }
209
+ }
210
+ tinyMCEPopup.editor.execCommand('spudMediaInsertSelected', false, selectedFile);
211
+ tinyMCEPopup.close();
212
+ };
213
+
214
+ self.pickerOptionKeyDown = function(e){
215
+ if(e.keyCode == 13){
216
+ self.clickedInsert(e);
217
+ }
218
+ };
219
+ };
@@ -0,0 +1,99 @@
1
+ /**
2
+ * editor_plugin_src.js
3
+ *
4
+ * Copyright 2009, Moxiecode Systems AB
5
+ * Released under LGPL License.
6
+ *
7
+ * License: http://tinymce.moxiecode.com/license
8
+ * Contributing: http://tinymce.moxiecode.com/contributing
9
+ */
10
+
11
+ (function() {
12
+
13
+ // Tell spud about our plugin and button
14
+ spud.admin.editor.registerPlugin('spud_media_picker');
15
+ spud.admin.editor.registerButton('spud_media_picker');
16
+
17
+ tinymce.create('tinymce.plugins.SpudMediaPicker', {
18
+ /**
19
+ * Initializes the plugin, this will be executed after the plugin has been created.
20
+ * This call is done before the editor instance has finished it's initialization so use the onInit event
21
+ * of the editor instance to intercept that event.
22
+ *
23
+ * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
24
+ * @param {string} url Absolute URL to where the plugin is located.
25
+ */
26
+ init : function(ed, url) {
27
+ // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample');
28
+ ed.addCommand('spudMediaShowPicker', function(){
29
+ ed.windowManager.open({
30
+ title: 'Spud Media Picker',
31
+ file: '/spud/admin/media_picker',
32
+ width: 450 + parseInt(ed.getLang('example.delta_width', 0), 10),
33
+ height: 300 + parseInt(ed.getLang('example.delta_height', 0), 10),
34
+ inline: 1,
35
+ resizable: false,
36
+ popup_css: false, // prevent tinymce from injecting some default css into our dialog box
37
+ close_previous: true, // close any previously opened dialogs
38
+ scrollbars: false
39
+ });
40
+ });
41
+
42
+ // Register picker button
43
+ ed.addButton('spud_media_picker', {
44
+ title: 'Insert Spud Media',
45
+ cmd: 'spudMediaShowPicker',
46
+ image: '/assets/spud/admin/media_tiny.png'
47
+ });
48
+
49
+ ed.addCommand('spudMediaInsertSelected', function(ui, data){
50
+ if(data.type == 'img'){
51
+ var img = ed.dom.createHTML('img', {
52
+ src: data.url,
53
+ title: data.title,
54
+ style: data.style,
55
+ width: data.width,
56
+ height: data.height
57
+ });
58
+ ed.execCommand('mceInsertContent', false, img);
59
+ }
60
+ else{
61
+ var link = ed.dom.createHTML('a', {
62
+ href: data.url,
63
+ target: data.target
64
+ }, data.text);
65
+ ed.execCommand('mceInsertContent', false, link);
66
+ }
67
+ });
68
+
69
+ /*
70
+ * Add a node change handler, selects the button in the UI when a image is selected
71
+ * @param {tinymce.Editor} ed Editor
72
+ * @param {tinymce.ControlManager} cm
73
+ * @param {node} n
74
+ */
75
+ // ed.onNodeChange.add(function(ed, cm, n) {
76
+ // cm.setActive('spud_media_picker', n.nodeName == 'IMG');
77
+ // });
78
+ },
79
+
80
+ /**
81
+ * Returns information about the plugin as a name/value array.
82
+ * The current keys are longname, author, authorurl, infourl and version.
83
+ *
84
+ * @return {Object} Name/value array containing information about the plugin.
85
+ */
86
+ getInfo: function(){
87
+ return {
88
+ longname : 'Spud Media',
89
+ author : 'Greg Woods',
90
+ authorurl : 'https://github.com/davydotcom/spud_media',
91
+ infourl : 'https://github.com/davydotcom/spud_media',
92
+ version : "1.0"
93
+ };
94
+ }
95
+ });
96
+
97
+ // Register plugin
98
+ tinymce.PluginManager.add('spud_media_picker', tinymce.plugins.SpudMediaPicker);
99
+ })();
Binary file