effective_assets 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +228 -0
  3. data/Rakefile +23 -0
  4. data/app/assets/images/effective_assets/icon_close.png +0 -0
  5. data/app/assets/images/effective_assets/s3_down_button.gif +0 -0
  6. data/app/assets/images/effective_assets/s3_over_button.gif +0 -0
  7. data/app/assets/images/effective_assets/s3_up_button.gif +0 -0
  8. data/app/assets/images/effective_assets/s3_upload.swf +0 -0
  9. data/app/assets/images/effective_assets/spinner.gif +0 -0
  10. data/app/assets/images/mime-types/excel.jpg +0 -0
  11. data/app/assets/images/mime-types/file.png +0 -0
  12. data/app/assets/images/mime-types/mp3.png +0 -0
  13. data/app/assets/images/mime-types/pdf.png +0 -0
  14. data/app/assets/images/mime-types/video.png +0 -0
  15. data/app/assets/images/mime-types/word.jpg +0 -0
  16. data/app/assets/images/mime-types/zip.png +0 -0
  17. data/app/assets/javascripts/effective_assets.js +1 -0
  18. data/app/assets/javascripts/effective_assets/asset_box_input.js.coffee +71 -0
  19. data/app/assets/javascripts/effective_assets/asset_box_uploader.js +122 -0
  20. data/app/assets/javascripts/effective_assets/asset_box_uploader_customization.js +166 -0
  21. data/app/assets/javascripts/effective_assets/jquery_ui_sortable.js +2106 -0
  22. data/app/assets/stylesheets/effective_assets.css.scss +1 -0
  23. data/app/assets/stylesheets/effective_assets/_asset_box_input.scss +206 -0
  24. data/app/controllers/effective/attachments_controller.rb +14 -0
  25. data/app/controllers/effective/s3_uploads_controller.rb +98 -0
  26. data/app/helpers/effective_assets_helper.rb +55 -0
  27. data/app/models/concerns/acts_as_asset_box.rb +97 -0
  28. data/app/models/effective/asset.rb +224 -0
  29. data/app/models/effective/attachment.rb +25 -0
  30. data/app/models/effective/delayed_job.rb +99 -0
  31. data/app/models/inputs/asset_box_input.rb +87 -0
  32. data/app/models/validators/asset_box_length_validator.rb +11 -0
  33. data/app/models/validators/asset_box_presence_validator.rb +6 -0
  34. data/app/uploaders/asset_uploader.rb +26 -0
  35. data/app/uploaders/effective_assets_uploader.rb +63 -0
  36. data/app/views/active_admin/effective_assets/_edit.html.haml +35 -0
  37. data/app/views/active_admin/effective_assets/_form.html.haml +4 -0
  38. data/app/views/active_admin/effective_assets/_new.html.haml +3 -0
  39. data/app/views/asset_box_input/_attachment_fields.html.haml +14 -0
  40. data/app/views/asset_box_input/_uploader.html.haml +119 -0
  41. data/app/views/assets/_video.html.erb +4 -0
  42. data/config/routes.rb +6 -0
  43. data/db/migrate/01_create_effective_assets.rb.erb +42 -0
  44. data/lib/effective_assets.rb +31 -0
  45. data/lib/effective_assets/engine.rb +38 -0
  46. data/lib/effective_assets/version.rb +3 -0
  47. data/lib/generators/effective_assets/install_generator.rb +41 -0
  48. data/lib/generators/templates/README +1 -0
  49. data/lib/generators/templates/asset_uploader.rb +25 -0
  50. data/lib/generators/templates/effective_assets.rb +19 -0
  51. data/lib/tasks/effective_assets_tasks.rake +4 -0
  52. data/spec/dummy/README.rdoc +261 -0
  53. data/spec/dummy/Rakefile +7 -0
  54. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  55. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  56. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  57. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  58. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  59. data/spec/dummy/config.ru +4 -0
  60. data/spec/dummy/config/application.rb +65 -0
  61. data/spec/dummy/config/boot.rb +10 -0
  62. data/spec/dummy/config/database.yml +25 -0
  63. data/spec/dummy/config/environment.rb +5 -0
  64. data/spec/dummy/config/environments/development.rb +37 -0
  65. data/spec/dummy/config/environments/production.rb +67 -0
  66. data/spec/dummy/config/environments/test.rb +37 -0
  67. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  68. data/spec/dummy/config/initializers/inflections.rb +15 -0
  69. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  70. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  71. data/spec/dummy/config/initializers/session_store.rb +8 -0
  72. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  73. data/spec/dummy/config/locales/en.yml +5 -0
  74. data/spec/dummy/config/routes.rb +58 -0
  75. data/spec/dummy/db/development.sqlite3 +0 -0
  76. data/spec/dummy/db/schema.rb +16 -0
  77. data/spec/dummy/db/test.sqlite3 +0 -0
  78. data/spec/dummy/log/development.log +71 -0
  79. data/spec/dummy/log/test.log +33 -0
  80. data/spec/dummy/public/404.html +26 -0
  81. data/spec/dummy/public/422.html +26 -0
  82. data/spec/dummy/public/500.html +25 -0
  83. data/spec/dummy/public/favicon.ico +0 -0
  84. data/spec/dummy/script/rails +6 -0
  85. data/spec/dummy/spec_link +3 -0
  86. data/spec/models/asset_spec.rb +46 -0
  87. data/spec/spec_helper.rb +34 -0
  88. data/spec/support/factories.rb +28 -0
  89. metadata +431 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 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/README.md ADDED
@@ -0,0 +1,228 @@
1
+ # Effective Assets
2
+
3
+ A full solution for managing assets (images, files, videos, etc).
4
+
5
+ Attach one or more assets to any model with validations.
6
+
7
+ Includes an upload direct to Amazon S3 implementation based on s3_swf_upload and image processing in the background with CarrierWave and DelayedJob
8
+
9
+ Formtastic input for displaying, organizing, and uploading assets direct to s3.
10
+
11
+ Includes (optional but recommended) integration with ActiveAdmin
12
+
13
+ ## Getting Started
14
+
15
+ Add to your Gemfile:
16
+
17
+ ```ruby
18
+ gem 'effective_assets'
19
+ ```
20
+
21
+ Run the bundle command to install it:
22
+
23
+ ```console
24
+ bundle install
25
+ ```
26
+
27
+ Then run the generator:
28
+
29
+ ```ruby
30
+ rails generate effective_assets:install
31
+ ```
32
+
33
+ The generator will install an initializer which describes all configuration options and creates two database migrations, one for EffectiveAssets the other for DelayedJob.
34
+
35
+ If you want to tweak the table name (to use something other than the default 'assets' and 'attachments'), manually adjust both the configuration file and the migration now.
36
+
37
+ Then migrate the database:
38
+
39
+ ```ruby
40
+ rake db:migrate
41
+ ```
42
+
43
+ If you intend to use the form helper method to display and upload assets, require the javascript in your application.js
44
+
45
+ ```ruby
46
+ //= require effective_addresses
47
+ ```
48
+
49
+ If you intend to use ActiveAdmin (optional, but highly recommended)
50
+
51
+ Add to your ActiveAdmin.js file:
52
+
53
+ ```ruby
54
+ //= require effective_assets
55
+
56
+ ```
57
+
58
+ And to your ActiveAdmin stylesheet
59
+
60
+ ```ruby
61
+ body.active_admin {
62
+ @import "effective_assets";
63
+ }
64
+ ```
65
+
66
+ If ActiveAdmin is installed, there will automatically be an 'Effective Assets' page.
67
+
68
+ ## Usage
69
+
70
+ ### Model
71
+
72
+ When including the acts_as_asset_box mixin, the idea of 'boxes' is presented. A box is just a category, which can have any name.
73
+
74
+ If the box is declared as a singular, 'photo', then it will be a singular asset. When defined as a plural, 'photos', it will be a set of photos.
75
+
76
+ The following will create 3 separate sets of assets:
77
+
78
+ ```ruby
79
+ class User
80
+ acts_as_asset_box :fav_icon, :pictures, :logos
81
+ end
82
+ ```
83
+
84
+ Calling @user.fav_icon will return a single Effective::Asset. Calling @user.pictures will return an array (relation) of Effective::Assets
85
+
86
+ To use with validations:
87
+
88
+ ```ruby
89
+ class User
90
+ acts_as_asset_box :fav_icon => true, :pictures => false, :videos => 2, :images => 5..10
91
+ end
92
+ ```
93
+
94
+ The user in this example is only valid if exists a fav_icon, 2 videos, and 5..10 images.
95
+
96
+ ### Uploading & Attaching
97
+
98
+ Use the custom formtastic input for uploading (direct to S3) and attaching assets to the 'pictures' box.
99
+
100
+ ```ruby
101
+ = f.input :pictures, :as => :asset_box, :uploader => true
102
+ = f.input :videos, :as => :asset_box, :limit => 2, :file_types => [:jpg, :gif, :png]
103
+ = f.input :logo, :as => :asset_box, :uploader => true, :uploader_visible => true # Show the uploader right away
104
+ ```
105
+
106
+ Note: Passing :limit => 2 will have no effect on a singular asset_box, which by definition has a limit of 1.
107
+
108
+ We use the s3_swf_upload gem for direct-to-s3 uploading. The process is as follows:
109
+
110
+ - User sees the form and clicks Browse. Selects 1 or more files, then clicks Start Uploading
111
+ - The s3_uploader reads configuration options from effective_assets.rb initializer, and connects to S3
112
+ - The file is uploaded directly to its 'final' resting place.
113
+ - A post is then made back to the effective#s3_uploads_controller which creates the Asset object and sets up a task in DelayedJob to process the asset (for image resizing)
114
+ - An attachment is created, which joins the Asset to the parent Object (User in our example) in the appropriate position.
115
+ - The DelayedJob task should be running and will handle any image resizing as defined by the AssetUploader
116
+ - The asset will appear in the form, and the user may click&drag the asset around to set the position.
117
+
118
+ ### Authorization
119
+
120
+ All authorization checks are handled via the config.authorization_method found in the effective_assets.rb initializer.
121
+
122
+ It is intended for flow through to CanCan, but that is not required.
123
+
124
+ The authorization method can be defined as:
125
+
126
+ ```ruby
127
+ EffectiveAssets.setup do |config|
128
+ config.authorization_method = Proc.new { |controller, action, resource| can?(action, resource) }
129
+ end
130
+ ```
131
+
132
+ or as a method:
133
+
134
+ ```ruby
135
+ EffectiveAssets.setup do |config|
136
+ config.authorization_method = :authorize_effective_assets
137
+ end
138
+ ```
139
+
140
+ and then in your application_controller.rb:
141
+
142
+ ```ruby
143
+ def authorize_effective_assets(action, resource)
144
+ can?(action, resource)
145
+ end
146
+ ```
147
+
148
+ The action will be one of :read, :create, :update, :destroy, :manage
149
+ The resource will generally be the @asset, but in the case of :manage, it is Effective::Asset class.
150
+
151
+ If the method or proc returns false (user is not authorized) an ActiveResource::UnauthorizedAccess exception will be raised
152
+
153
+ You can rescue from this exception by adding the following to your application_controller.rb
154
+
155
+ ```ruby
156
+ rescue_from ActiveResource::UnauthorizedAccess do |exception|
157
+ respond_to do |format|
158
+ format.html { render 'static_pages/access_denied', :status => 403 }
159
+ format.any { render :text => 'Access Denied', :status => 403 }
160
+ end
161
+ end
162
+ ```
163
+
164
+ ### Image Processing and Resizing
165
+
166
+ CarrierWave is used under the covers to do all the image resizing.
167
+ The installer created an uploaders/asset_uploader.rb which you can use to set up versions.
168
+
169
+ Some additional processing goes on to record final image dimensions and file sizes.
170
+
171
+
172
+ ### Helpers
173
+
174
+ To just get the URL of an asset
175
+
176
+ ```ruby
177
+ @asset = @user.fav_icon
178
+ @asset.url
179
+ => "http://aws_bucket.s3.amazonaws.com/assets/1/my_favorite_icon.png
180
+ ```
181
+
182
+ To display the asset as a link with an image (if its an image, or a mime-type appropriate icon if its not an image):
183
+
184
+ ```ruby
185
+ # Asset is the @user.fav_icon
186
+ # version is anything you set up in your uploaders/asset_uploader.rb as versions. :thumb
187
+ # Options are passed through to a call to rails image_tag helper
188
+ effective_asset_image_tag(asset, version = nil, options = {})
189
+ ```
190
+
191
+ To display the asset as a link with no image
192
+
193
+ ```ruby
194
+ # Options are passed through to rails link_to helper
195
+ effective_asset_link_to(asset, version = nil, options = {})
196
+ ```
197
+
198
+ ### Integration
199
+
200
+ The 'Insert Asset' functionality from this gem is used in effective_mercury and effective_rte
201
+
202
+
203
+ ## License
204
+
205
+ MIT License. Copyright Code and Effect Inc. http://www.codeandeffect.com
206
+
207
+ You are not granted rights or licenses to the trademarks of Code and Effect
208
+
209
+ ## Credits
210
+
211
+ This gem heavily relies on:
212
+
213
+ CarrierWave (https://github.com/carrierwaveuploader/carrierwave)
214
+
215
+ DelayedJob (https://github.com/collectiveidea/delayed_job)
216
+
217
+ swf_s3_upload (https://github.com/nathancolgate/s3-swf-upload-plugin)
218
+
219
+
220
+ ### Testing
221
+
222
+ The test suite for this gem is unfortunately not yet complete.
223
+
224
+ Run tests by:
225
+
226
+ ```ruby
227
+ rake spec
228
+ ```
data/Rakefile ADDED
@@ -0,0 +1,23 @@
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
+
8
+ # Our tasks
9
+ load 'lib/tasks/effective_assets_tasks.rake'
10
+
11
+ # Testing tasks
12
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
13
+ load 'rails/tasks/engine.rake'
14
+
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ require 'rspec/core'
18
+ require 'rspec/core/rake_task'
19
+
20
+ desc "Run all specs in spec directory (excluding plugin specs)"
21
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
22
+
23
+ task :default => :spec
@@ -0,0 +1 @@
1
+ //= require_tree ./effective_assets
@@ -0,0 +1,71 @@
1
+ $ ->
2
+ $(document).on 'click', 'a.asset-box-remove', (event) ->
3
+ event.preventDefault()
4
+ attachment_div = $(event.target).closest('div.asset-box-attachment')
5
+ attachment_div.find('input.asset-box-remove').first().val(1)
6
+ attachment_div.hide()
7
+
8
+ # Show the first 'limit' attachments, hide the rest
9
+ asset_box_input = attachment_div.closest('div.asset_box_input')
10
+ limit = asset_box_input.data('limit')
11
+
12
+ asset_box_input.find("input.asset-box-remove[value!='1']:gt(#{limit})").each -> $(this).closest('div.asset-box-attachment').hide()
13
+ asset_box_input.find("input.asset-box-remove[value!='1']:lt(#{limit})").each -> $(this).closest('div.asset-box-attachment').show()
14
+
15
+ $(document).on 'click', 'a.asset-box-upload', (event) ->
16
+ event.preventDefault()
17
+ uploader = $(event.target).closest('div.asset_box_input').find('div.asset_box_uploader').first()
18
+
19
+ if uploader.is(':visible')
20
+ uploader.slideUp('slow', -> $(this).hide())
21
+ else
22
+ uploader.slideDown('slow', -> $(this).show())
23
+
24
+ # This is the 'admin' insert assets screen
25
+ $(document).on 'click', 'a.asset-box-dialog', (event) ->
26
+ event.preventDefault()
27
+ dialog_frame = $(
28
+ "<div title='Insert Asset'>" +
29
+ "<iframe id='wym_insert_asset_iframe' src='/admin/assets' width='100%' height='100%' marginWidth='0' marginHeight='0' frameBorder='0' scrolling='auto' title='Insert Asset'></iframe>" +
30
+ "</div>"
31
+ )
32
+
33
+ dialog_frame.dialog({
34
+ modal: true,
35
+ height: $(window).height() * 0.85,
36
+ width: "85%",
37
+ close: (event, ui) -> $(this).remove()
38
+ buttons: { Close: -> $(this).dialog("close") }
39
+ })
40
+
41
+ asset_box = $(event.target).closest('div.asset_box_input')
42
+
43
+ single_mode = (asset_box.data('limit') == 1)
44
+ attachable_id = asset_box.data('attachable-id')
45
+ attachable_type = asset_box.data('attachable-type')
46
+ attachable_swf = asset_box.data('swf')
47
+ attachable_box = asset_box.data('box')
48
+ authenticity_token = asset_box.closest('form').find("input[name='authenticity_token']").first().val()
49
+
50
+ $('#wym_insert_asset_iframe', dialog_frame).on 'load', ->
51
+ $(this).contents().find('a.asset-insertable').on 'click', (event) ->
52
+ event.preventDefault()
53
+
54
+ # Initialize a new Attachment and get the HTML for it.
55
+ $.ajax({
56
+ url: '/s3_uploads',
57
+ beforeSend: (jqXHR, settings) -> s3_showAttachmentLoading(attachable_swf, '...'),
58
+ complete: (jqXHR, textStatus) -> s3_loadAttachmentHtml(attachable_swf, jqXHR.responseText),
59
+ global: false,
60
+ type: 'POST',
61
+ dataType: 'script',
62
+ data: {
63
+ 'authenticity_token' : authenticity_token,
64
+ 'box' : attachable_box,
65
+ 'attachable_type' : attachable_type,
66
+ 'attachable_id' : attachable_id,
67
+ 'asset_id' : $(this).data('asset-id')
68
+ }
69
+ })
70
+
71
+ if single_mode then dialog_frame.dialog("close")
@@ -0,0 +1,122 @@
1
+ /* SWFObject v2.2 <http://code.google.com/p/swfobject/>
2
+ is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
3
+ */
4
+ var s3_upload_swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
5
+
6
+ /* S3_Upload V0.1
7
+ Copyright (c) 2008 Elctech,
8
+ This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
9
+ */
10
+ /* S3_Upload V0.2
11
+ Copyright (c) 2010 Nathan Colgate,
12
+ This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
13
+ */
14
+ var s3_swf;
15
+ function s3_swf_init(id, options)
16
+ {
17
+ var buttonWidth = (options.buttonWidth != undefined) ? options.buttonWidth : 50;
18
+ var buttonHeight = (options.buttonHeight != undefined) ? options.buttonHeight : 50;
19
+ var flashVersion = (options.flashVersion != undefined) ? options.flashVersion : '9.0.0';
20
+ var queueSizeLimit = (options.queueSizeLimit != undefined) ? options.queueSizeLimit : 10;
21
+ var fileSizeLimit = (options.fileSizeLimit != undefined) ? options.fileSizeLimit : 524288000;
22
+ var fileTypes = (options.fileTypes != undefined) ? options.fileTypes : "*.*";
23
+ var fileTypeDescs = (options.fileTypeDescs != undefined) ? options.fileTypeDescs : "All Files";
24
+ var selectMultipleFiles = (options.selectMultipleFiles != undefined) ? options.selectMultipleFiles : true;
25
+ var keyPrefix = (options.keyPrefix != undefined) ? options.keyPrefix : "";
26
+ var signaturePath = (options.signaturePath != undefined) ? options.signaturePath : "s3_uploads.xml";
27
+ var swfFilePath = (options.swfFilePath != undefined) ? options.swfFilePath : "/flash/s3_upload.swf";
28
+ var buttonUpPath = (options.buttonUpPath != undefined) ? options.buttonUpPath : "";
29
+ var buttonOverPath = (options.buttonOverPath != undefined) ? options.buttonOverPath : "";
30
+ var buttonDownPath = (options.buttonDownPath != undefined) ? options.buttonDownPath : "";
31
+
32
+ var onFileAdd = (options.onFileAdd != undefined) ? options.onFileAdd : function(file){};
33
+ var onFileRemove = (options.onFileRemove != undefined) ? options.onFileRemove : function(file){};
34
+ var onFileSizeLimitReached = (options.onFileSizeLimitReached != undefined) ? options.onFileSizeLimitReached : function(file){};
35
+ var onFileNotInQueue = (options.onFileNotInQueue != undefined) ? options.onFileNotInQueue : function(file){};
36
+
37
+ var onQueueChange = (options.onQueueChange != undefined) ? options.onQueueChange : function(queue){};
38
+ var onQueueClear = (options.onQueueClear != undefined) ? options.onQueueClear : function(queue){};
39
+ var onQueueSizeLimitReached = (options.onQueueSizeLimitReached != undefined) ? options.onQueueSizeLimitReached : function(queue){};
40
+ var onQueueEmpty = (options.onQueueEmpty != undefined) ? options.onQueueEmpty : function(queue){};
41
+
42
+ var onUploadingStop = (options.onUploadingStop != undefined) ? options.onUploadingStop : function(){};
43
+ var onUploadingStart = (options.onUploadingStart != undefined) ? options.onUploadingStart : function(){};
44
+ var onUploadingFinish = (options.onUploadingFinish != undefined) ? options.onUploadingFinish : function(){};
45
+
46
+ var onSignatureOpen = (options.onSignatureOpen != undefined) ? options.onSignatureOpen : function(file,event){};
47
+ var onSignatureProgress = (options.onSignatureProgress != undefined) ? options.onSignatureProgress : function(file,progress_event){};
48
+ var onSignatureHttpStatus = (options.onSignatureHttpStatus != undefined) ? options.onSignatureHttpStatus : function(file,http_status_event){};
49
+ var onSignatureComplete = (options.onSignatureComplete != undefined) ? options.onSignatureComplete : function(file,event){};
50
+ var onSignatureSecurityError = (options.onSignatureSecurityError != undefined) ? options.onSignatureSecurityError : function(file,security_error_event){};
51
+ var onSignatureIOError = (options.onSignatureIOError != undefined) ? options.onSignatureIOError : function(file,io_error_event){};
52
+ var onSignatureXMLError = (options.onSignatureXMLError != undefined) ? options.onSignatureXMLError : function(file,error_message){};
53
+
54
+ var onUploadOpen = (options.onUploadOpen != undefined) ? options.onUploadOpen : function(upload_options,event){};
55
+ var onUploadProgress = (options.onUploadProgress != undefined) ? options.onUploadProgress : function(upload_options,progress_event){};
56
+ var onUploadHttpStatus = (options.onUploadHttpStatus != undefined) ? options.onUploadHttpStatus : function(upload_options,http_status_event){};
57
+ var onUploadComplete = (options.onUploadComplete != undefined) ? options.onUploadComplete : function(upload_options,event){};
58
+ var onUploadIOError = (options.onUploadIOError != undefined) ? options.onUploadIOError : function(upload_options,io_error_event){};
59
+ var onUploadSecurityError = (options.onUploadSecurityError != undefined) ? options.onUploadSecurityError : function(upload_options,security_error_event){};
60
+ var onUploadError = (options.onUploadError != undefined) ? options.onUploadError : function(upload_options,error){};
61
+
62
+ var flashvars = {"s3_swf_obj": (options.swfVarObj != undefined ? options.swfVarObj : 's3_swf')}; //fallback to the global var incase script is used outside of view helper
63
+ var params = {};
64
+ var attributes = {};
65
+ params.wmode = "transparent";
66
+ params.menu = "false";
67
+ params.quality = "low";
68
+
69
+ s3_upload_swfobject.embedSWF(swfFilePath+"?t=" + new Date().getTime(), id, buttonWidth, buttonHeight, flashVersion, false, flashvars, params, attributes);
70
+
71
+ var signatureUrl = window.location.protocol + '//' + window.location.host + signaturePath;
72
+ var buttonUpUrl = window.location.protocol + '//' + window.location.host + buttonUpPath;
73
+ var buttonDownUrl = window.location.protocol + '//' + window.location.host + buttonDownPath;
74
+ var buttonOverUrl = window.location.protocol + '//' + window.location.host + buttonOverPath;
75
+
76
+ s3_swf = {
77
+ obj: function() { return document[id]; },
78
+
79
+ init: function() { this.obj().init(signatureUrl, keyPrefix, fileSizeLimit, queueSizeLimit, fileTypes, fileTypeDescs, selectMultipleFiles,buttonWidth,buttonHeight,buttonUpUrl,buttonDownUrl,buttonOverUrl); },
80
+ clearQueue: function() { this.obj().clearQueue();},
81
+ startUploading: function() { this.obj().startUploading();},
82
+ stopUploading: function() { this.obj().stopUploading(); s3_queueClearHandler("");},
83
+ removeFileFromQueue: function(file_name) {
84
+ console.log("remove file from queue");
85
+ var one_file = $("#file_todo_list li[data-name='" + file_name + "']");
86
+ this.obj().removeFileFromQueue(one_file.index());
87
+ },
88
+
89
+ onFileAdd: onFileAdd,
90
+ onFileRemove: onFileRemove,
91
+ onFileSizeLimitReached: onFileSizeLimitReached,
92
+ onFileNotInQueue: onFileNotInQueue,
93
+
94
+ onQueueChange: onQueueChange,
95
+ onQueueClear: onQueueClear,
96
+ onQueueSizeLimitReached: onQueueSizeLimitReached,
97
+ onQueueEmpty: onQueueEmpty,
98
+
99
+ onUploadingStop: onUploadingStop,
100
+ onUploadingStart: onUploadingStart,
101
+ onUploadingFinish: onUploadingFinish,
102
+
103
+ onSignatureOpen: onSignatureOpen,
104
+ onSignatureProgress: onSignatureProgress,
105
+ onSignatureHttpStatus: onSignatureHttpStatus,
106
+ onSignatureComplete: onSignatureComplete,
107
+ onSignatureSecurityError: onSignatureSecurityError,
108
+ onSignatureIOError: onSignatureIOError,
109
+ onSignatureXMLError: onSignatureXMLError,
110
+
111
+ onUploadOpen: onUploadOpen,
112
+ onUploadProgress: onUploadProgress,
113
+ onUploadHttpStatus: onUploadHttpStatus,
114
+ onUploadComplete: onUploadComplete,
115
+ onUploadIOError: onUploadIOError,
116
+ onUploadSecurityError: onUploadSecurityError,
117
+ onUploadError: onUploadError
118
+
119
+ }
120
+
121
+ return(s3_swf);
122
+ }