flash_s3_rails 0.0.1.beta1
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.
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +156 -0
- data/README.md +92 -0
- data/Rakefile +46 -0
- data/app/assets/images/vendor/flash_s3/start_button.png +0 -0
- data/app/assets/images/vendor/flash_s3/swfupload.swf +0 -0
- data/app/assets/images/vendor/flash_s3/upload_button.png +0 -0
- data/app/assets/javascripts/jquery.flashS3.js +128 -0
- data/app/assets/javascripts/vendor/flash_s3/swfupload.fileprogress.js +151 -0
- data/app/assets/javascripts/vendor/flash_s3/swfupload.handlers.js +199 -0
- data/app/assets/javascripts/vendor/flash_s3/swfupload.js +980 -0
- data/app/assets/javascripts/vendor/flash_s3/swfupload.queue.js +98 -0
- data/app/assets/javascripts/vendor/flash_s3/swfupload.swfobject.js +111 -0
- data/app/assets/stylesheets/jquery.flashS3.css +53 -0
- data/app/helpers/flash_s3_helper.rb +45 -0
- data/app/views/flash_s3/_flash_s3_uploader.html.erb +5 -0
- data/app/views/layouts/_flash_s3.html.erb +6 -0
- data/config/routes.rb +5 -0
- data/flash_s3.gemspec +34 -0
- data/lib/flash_s3.rb +66 -0
- data/lib/flash_s3/attachment.rb +28 -0
- data/lib/flash_s3/attachment_definition.rb +39 -0
- data/lib/flash_s3/engine.rb +13 -0
- data/lib/flash_s3/s3_post_params.rb +80 -0
- data/lib/flash_s3/version.rb +3 -0
- data/spec/models/upload_spec.rb +72 -0
- data/spec/rails_spec_helper.rb +32 -0
- data/spec/requests/new_upload_spec.rb +12 -0
- data/spec/spec_helper.rb +18 -0
- metadata +204 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
/*
|
2
|
+
Queue Plug-in
|
3
|
+
|
4
|
+
Features:
|
5
|
+
*Adds a cancelQueue() method for cancelling the entire queue.
|
6
|
+
*All queued files are uploaded when startUpload() is called.
|
7
|
+
*If false is returned from uploadComplete then the queue upload is stopped.
|
8
|
+
If false is not returned (strict comparison) then the queue upload is continued.
|
9
|
+
*Adds a QueueComplete event that is fired when all the queued files have finished uploading.
|
10
|
+
Set the event handler with the queue_complete_handler setting.
|
11
|
+
|
12
|
+
*/
|
13
|
+
|
14
|
+
var SWFUpload;
|
15
|
+
if (typeof(SWFUpload) === "function") {
|
16
|
+
SWFUpload.queue = {};
|
17
|
+
|
18
|
+
SWFUpload.prototype.initSettings = (function (oldInitSettings) {
|
19
|
+
return function () {
|
20
|
+
if (typeof(oldInitSettings) === "function") {
|
21
|
+
oldInitSettings.call(this);
|
22
|
+
}
|
23
|
+
|
24
|
+
this.queueSettings = {};
|
25
|
+
|
26
|
+
this.queueSettings.queue_cancelled_flag = false;
|
27
|
+
this.queueSettings.queue_upload_count = 0;
|
28
|
+
|
29
|
+
this.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler;
|
30
|
+
this.queueSettings.user_upload_start_handler = this.settings.upload_start_handler;
|
31
|
+
this.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler;
|
32
|
+
this.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler;
|
33
|
+
|
34
|
+
this.settings.queue_complete_handler = this.settings.queue_complete_handler || null;
|
35
|
+
};
|
36
|
+
})(SWFUpload.prototype.initSettings);
|
37
|
+
|
38
|
+
SWFUpload.prototype.startUpload = function (fileID) {
|
39
|
+
this.queueSettings.queue_cancelled_flag = false;
|
40
|
+
this.callFlash("StartUpload", [fileID]);
|
41
|
+
};
|
42
|
+
|
43
|
+
SWFUpload.prototype.cancelQueue = function () {
|
44
|
+
this.queueSettings.queue_cancelled_flag = true;
|
45
|
+
this.stopUpload();
|
46
|
+
|
47
|
+
var stats = this.getStats();
|
48
|
+
while (stats.files_queued > 0) {
|
49
|
+
this.cancelUpload();
|
50
|
+
stats = this.getStats();
|
51
|
+
}
|
52
|
+
};
|
53
|
+
|
54
|
+
SWFUpload.queue.uploadStartHandler = function (file) {
|
55
|
+
var returnValue;
|
56
|
+
if (typeof(this.queueSettings.user_upload_start_handler) === "function") {
|
57
|
+
returnValue = this.queueSettings.user_upload_start_handler.call(this, file);
|
58
|
+
}
|
59
|
+
|
60
|
+
// To prevent upload a real "FALSE" value must be returned, otherwise default to a real "TRUE" value.
|
61
|
+
returnValue = (returnValue === false) ? false : true;
|
62
|
+
|
63
|
+
this.queueSettings.queue_cancelled_flag = !returnValue;
|
64
|
+
|
65
|
+
return returnValue;
|
66
|
+
};
|
67
|
+
|
68
|
+
SWFUpload.queue.uploadCompleteHandler = function (file) {
|
69
|
+
var user_upload_complete_handler = this.queueSettings.user_upload_complete_handler;
|
70
|
+
var continueUpload;
|
71
|
+
|
72
|
+
if (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) {
|
73
|
+
this.queueSettings.queue_upload_count++;
|
74
|
+
}
|
75
|
+
|
76
|
+
if (typeof(user_upload_complete_handler) === "function") {
|
77
|
+
continueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true;
|
78
|
+
} else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) {
|
79
|
+
// If the file was stopped and re-queued don't restart the upload
|
80
|
+
continueUpload = false;
|
81
|
+
} else {
|
82
|
+
continueUpload = true;
|
83
|
+
}
|
84
|
+
|
85
|
+
if (continueUpload) {
|
86
|
+
var stats = this.getStats();
|
87
|
+
if (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) {
|
88
|
+
this.startUpload();
|
89
|
+
} else if (this.queueSettings.queue_cancelled_flag === false) {
|
90
|
+
this.queueEvent("queue_complete_handler", [this.queueSettings.queue_upload_count]);
|
91
|
+
this.queueSettings.queue_upload_count = 0;
|
92
|
+
} else {
|
93
|
+
this.queueSettings.queue_cancelled_flag = false;
|
94
|
+
this.queueSettings.queue_upload_count = 0;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
};
|
98
|
+
}
|
@@ -0,0 +1,111 @@
|
|
1
|
+
/*
|
2
|
+
SWFUpload.SWFObject Plugin
|
3
|
+
|
4
|
+
Summary:
|
5
|
+
This plugin uses SWFObject to embed SWFUpload dynamically in the page. SWFObject provides accurate Flash Player detection and DOM Ready loading.
|
6
|
+
This plugin replaces the Graceful Degradation plugin.
|
7
|
+
|
8
|
+
Features:
|
9
|
+
* swfupload_load_failed_hander event
|
10
|
+
* swfupload_pre_load_handler event
|
11
|
+
* minimum_flash_version setting (default: "9.0.28")
|
12
|
+
* SWFUpload.onload event for early loading
|
13
|
+
|
14
|
+
Usage:
|
15
|
+
Provide handlers and settings as needed. When using the SWFUpload.SWFObject plugin you should initialize SWFUploading
|
16
|
+
in SWFUpload.onload rather than in window.onload. When initialized this way SWFUpload can load earlier preventing the UI flicker
|
17
|
+
that was seen using the Graceful Degradation plugin.
|
18
|
+
|
19
|
+
<script type="text/javascript">
|
20
|
+
var swfu;
|
21
|
+
SWFUpload.onload = function () {
|
22
|
+
swfu = new SWFUpload({
|
23
|
+
minimum_flash_version: "9.0.28",
|
24
|
+
swfupload_pre_load_handler: swfuploadPreLoad,
|
25
|
+
swfupload_load_failed_handler: swfuploadLoadFailed
|
26
|
+
});
|
27
|
+
};
|
28
|
+
</script>
|
29
|
+
|
30
|
+
Notes:
|
31
|
+
You must provide set minimum_flash_version setting to "8" if you are using SWFUpload for Flash Player 8.
|
32
|
+
The swfuploadLoadFailed event is only fired if the minimum version of Flash Player is not met. Other issues such as missing SWF files, browser bugs
|
33
|
+
or corrupt Flash Player installations will not trigger this event.
|
34
|
+
The swfuploadPreLoad event is fired as soon as the minimum version of Flash Player is found. It does not wait for SWFUpload to load and can
|
35
|
+
be used to prepare the SWFUploadUI and hide alternate content.
|
36
|
+
swfobject's onDomReady event is cross-browser safe but will default to the window.onload event when DOMReady is not supported by the browser.
|
37
|
+
Early DOM Loading is supported in major modern browsers but cannot be guaranteed for every browser ever made.
|
38
|
+
*/
|
39
|
+
|
40
|
+
|
41
|
+
/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
|
42
|
+
Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
|
43
|
+
This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
|
44
|
+
*/
|
45
|
+
var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in swfobject){swfobject[q]=null}swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
var SWFUpload;
|
50
|
+
if (typeof(SWFUpload) === "function") {
|
51
|
+
SWFUpload.onload = function () {};
|
52
|
+
|
53
|
+
swfobject.addDomLoadEvent(function () {
|
54
|
+
if (typeof(SWFUpload.onload) === "function") {
|
55
|
+
SWFUpload.onload.call(window);
|
56
|
+
}
|
57
|
+
});
|
58
|
+
|
59
|
+
SWFUpload.prototype.initSettings = (function (oldInitSettings) {
|
60
|
+
return function () {
|
61
|
+
if (typeof(oldInitSettings) === "function") {
|
62
|
+
oldInitSettings.call(this);
|
63
|
+
}
|
64
|
+
|
65
|
+
this.ensureDefault = function (settingName, defaultValue) {
|
66
|
+
this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
|
67
|
+
};
|
68
|
+
|
69
|
+
this.ensureDefault("minimum_flash_version", "9.0.28");
|
70
|
+
this.ensureDefault("swfupload_pre_load_handler", null);
|
71
|
+
this.ensureDefault("swfupload_load_failed_handler", null);
|
72
|
+
|
73
|
+
delete this.ensureDefault;
|
74
|
+
|
75
|
+
};
|
76
|
+
})(SWFUpload.prototype.initSettings);
|
77
|
+
|
78
|
+
|
79
|
+
SWFUpload.prototype.loadFlash = function (oldLoadFlash) {
|
80
|
+
return function () {
|
81
|
+
var hasFlash = swfobject.hasFlashPlayerVersion(this.settings.minimum_flash_version);
|
82
|
+
|
83
|
+
if (hasFlash) {
|
84
|
+
this.queueEvent("swfupload_pre_load_handler");
|
85
|
+
if (typeof(oldLoadFlash) === "function") {
|
86
|
+
oldLoadFlash.call(this);
|
87
|
+
}
|
88
|
+
} else {
|
89
|
+
this.queueEvent("swfupload_load_failed_handler");
|
90
|
+
}
|
91
|
+
};
|
92
|
+
|
93
|
+
}(SWFUpload.prototype.loadFlash);
|
94
|
+
|
95
|
+
SWFUpload.prototype.displayDebugInfo = function (oldDisplayDebugInfo) {
|
96
|
+
return function () {
|
97
|
+
if (typeof(oldDisplayDebugInfo) === "function") {
|
98
|
+
oldDisplayDebugInfo.call(this);
|
99
|
+
}
|
100
|
+
|
101
|
+
this.debug(
|
102
|
+
[
|
103
|
+
"SWFUpload.SWFObject Plugin settings:", "\n",
|
104
|
+
"\t", "minimum_flash_version: ", this.settings.minimum_flash_version, "\n",
|
105
|
+
"\t", "swfupload_pre_load_handler assigned: ", (typeof(this.settings.swfupload_pre_load_handler) === "function").toString(), "\n",
|
106
|
+
"\t", "swfupload_load_failed_handler assigned: ", (typeof(this.settings.swfupload_load_failed_handler) === "function").toString(), "\n",
|
107
|
+
].join("")
|
108
|
+
);
|
109
|
+
};
|
110
|
+
}(SWFUpload.prototype.displayDebugInfo);
|
111
|
+
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
.flash_s3-wrapper {
|
2
|
+
width:25em;
|
3
|
+
height:12em;
|
4
|
+
background:#99FFCC;
|
5
|
+
padding:1em;
|
6
|
+
display:table-cell;
|
7
|
+
vertical-align:bottom;
|
8
|
+
position:relative;
|
9
|
+
}
|
10
|
+
|
11
|
+
.flash_s3-wrapper ol.flash_s3-file_transfers {
|
12
|
+
padding:0;
|
13
|
+
margin:0;
|
14
|
+
position:absolute;
|
15
|
+
width:23em;
|
16
|
+
top:1em;
|
17
|
+
left:1em;
|
18
|
+
height:9em;
|
19
|
+
overflow:auto;
|
20
|
+
}
|
21
|
+
|
22
|
+
.flash_s3-wrapper li.flash_s3-file {
|
23
|
+
list-style:none;
|
24
|
+
padding:3px 0;
|
25
|
+
position:relative;
|
26
|
+
}
|
27
|
+
|
28
|
+
.flash_s3-wrapper li.flash_s3-file .ui-icon-close {
|
29
|
+
position:absolute;
|
30
|
+
right:-2px;
|
31
|
+
top:20px;
|
32
|
+
}
|
33
|
+
|
34
|
+
.flash_s3-start_button_wrapper {
|
35
|
+
display:inline-block;
|
36
|
+
zoom:1;
|
37
|
+
*display:inline;
|
38
|
+
}
|
39
|
+
|
40
|
+
.flash_s3-start_button {
|
41
|
+
display:block;
|
42
|
+
width:60px;
|
43
|
+
height:28px;
|
44
|
+
background:url('/assets/vendor/flash_s3/start_button.png') 0 0 no-repeat;
|
45
|
+
}
|
46
|
+
|
47
|
+
.flash_s3-start_button:hover { background-position:0 -28px; }
|
48
|
+
.flash_s3-start_button:active { background-position:0 -56px; }
|
49
|
+
|
50
|
+
.flash_s3-progress_bar.ui-progressbar {
|
51
|
+
height: 12px;
|
52
|
+
margin-right:10px;
|
53
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module FlashS3Helper
|
2
|
+
def flash_s3_uploader(record, attachment, create_url, options = {})
|
3
|
+
render :partial => 'flash_s3/flash_s3_uploader', :formats => [:html], :locals => {
|
4
|
+
:id => uploader_id(record, attachment),
|
5
|
+
:button_id => uploader_button_id(record, attachment),
|
6
|
+
:swf_upload_options_as_json => swf_upload_options_as_json(record, attachment, create_url, options)
|
7
|
+
}, :layout => 'layouts/flash_s3'
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def swf_upload_options_as_json(record, attachment, create_url, options)
|
13
|
+
s3_post_params = FlashS3::S3PostParams.new(record, attachment)
|
14
|
+
|
15
|
+
attachment_defintion = record.send(attachment).attachment_definition
|
16
|
+
|
17
|
+
{
|
18
|
+
:upload_url => "http://#{attachment_defintion.bucket}.s3.amazonaws.com/",
|
19
|
+
:flash_url => "/assets/vendor/flash_s3/swfupload.swf",
|
20
|
+
:post_params => s3_post_params.params,
|
21
|
+
:button_placeholder_id => uploader_button_id(record, attachment),
|
22
|
+
:button_width => 60,
|
23
|
+
:button_height => 28,
|
24
|
+
:button_image_url => "/assets/vendor/flash_s3/upload_button.png",
|
25
|
+
:button_cursor => -2,
|
26
|
+
:http_success => [ 200, 201, 204 ],
|
27
|
+
:file_post_name => "file",
|
28
|
+
:custom_settings => {
|
29
|
+
:record_class_name => record.class.name.underscore.downcase,
|
30
|
+
:attachment_name => attachment.to_s,
|
31
|
+
:renderers => {
|
32
|
+
# :file_upload_list_item_renderer => 'methods.fileUplaodListItemRenderer'
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}.deep_merge(options.deep_merge(:custom_settings => {:create_s3_attachment_url => create_url})).to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
def uploader_id(record, attachment)
|
39
|
+
"#{record.class.name.underscore.downcase}_#{attachment}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def uploader_button_id(record, attachment)
|
43
|
+
"#{uploader_id(record, attachment)}-flash_s3-button"
|
44
|
+
end
|
45
|
+
end
|
data/config/routes.rb
ADDED
data/flash_s3.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "flash_s3/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "flash_s3_rails"
|
7
|
+
s.version = FlashS3::VERSION
|
8
|
+
s.authors = ["Sam Woodard"]
|
9
|
+
s.email = ["sam.h.woodard@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Direct multi-file uploader to s3}
|
12
|
+
s.description = %q{Direct multi-file uploader to s3}
|
13
|
+
|
14
|
+
s.rubyforge_project = "flash_s3"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n") - Dir['lib/flash_s3_test/**/*']
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
s.add_development_dependency "thin"
|
24
|
+
s.add_development_dependency "capybara"
|
25
|
+
s.add_development_dependency "mongrel", '~> 1.2.0.pre2'
|
26
|
+
s.add_development_dependency "database_cleaner"
|
27
|
+
s.add_development_dependency "rspec-rails"
|
28
|
+
s.add_development_dependency "rails"
|
29
|
+
s.add_development_dependency "sqlite3"
|
30
|
+
s.add_development_dependency "jquery-rails"
|
31
|
+
|
32
|
+
s.add_runtime_dependency "activesupport"
|
33
|
+
s.add_runtime_dependency "jquery-ui-rails"
|
34
|
+
end
|
data/lib/flash_s3.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "flash_s3/version"
|
3
|
+
require "flash_s3/engine"
|
4
|
+
|
5
|
+
module FlashS3
|
6
|
+
extend ActiveSupport::Autoload
|
7
|
+
|
8
|
+
autoload :AttachmentDefinition
|
9
|
+
autoload :Attachment
|
10
|
+
autoload :S3PostParams
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def configure
|
14
|
+
yield(configuration)
|
15
|
+
end
|
16
|
+
|
17
|
+
def configuration
|
18
|
+
::Rails.application.railties.engines.find {|engine| engine.is_a? FlashS3::Engine }.config.flash_s3
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def configuration=(config)
|
23
|
+
configuration.clear
|
24
|
+
config.each {|k,v| configuration.send(:"#{k}=", v)}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module Rails
|
29
|
+
module ActiveRecord
|
30
|
+
extend ActiveSupport::Concern
|
31
|
+
|
32
|
+
module ClassMethods
|
33
|
+
def has_attached_s3_file(name, &blk)
|
34
|
+
name = name.to_sym
|
35
|
+
attachment_definition = AttachmentDefinition.new(name)
|
36
|
+
|
37
|
+
if block_given?
|
38
|
+
attachment_definition.configure(&blk)
|
39
|
+
end
|
40
|
+
|
41
|
+
unless respond_to?(:s3_file_attachment_definitions)
|
42
|
+
cattr_accessor :s3_file_attachment_definitions
|
43
|
+
self.s3_file_attachment_definitions = {}
|
44
|
+
end
|
45
|
+
|
46
|
+
s3_file_attachment_definitions[name] = attachment_definition
|
47
|
+
|
48
|
+
define_method :"#{name}=" do |options|
|
49
|
+
options.symbolize_keys.assert_valid_keys(:s3_key)
|
50
|
+
send(:"#{name}_s3_key=", options[:s3_key])
|
51
|
+
end
|
52
|
+
|
53
|
+
define_method :"#{name}" do
|
54
|
+
Attachment.new(name, self.class.s3_file_attachment_definitions[name], self)
|
55
|
+
end
|
56
|
+
|
57
|
+
define_method(:"before_#{name}_save") {}
|
58
|
+
define_method(:"after_#{name}_save") {}
|
59
|
+
|
60
|
+
before_save :"before_#{name}_save"
|
61
|
+
after_save :"after_#{name}_save"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module FlashS3
|
2
|
+
class Attachment
|
3
|
+
attr_accessor :s3_key
|
4
|
+
|
5
|
+
delegate :bucket, :to => :@definition
|
6
|
+
|
7
|
+
def initialize(name, definition, record)
|
8
|
+
@name, @definition, @record = name, definition, record
|
9
|
+
self.s3_key = record.send(:"#{name}_s3_key")
|
10
|
+
end
|
11
|
+
|
12
|
+
def update(options)
|
13
|
+
options.assert_valid_keys(:s3_key)
|
14
|
+
options.each do |k,v|
|
15
|
+
send(:"#{k}=", v)
|
16
|
+
@record.send(:"#{@name}_s3_key=", s3_key)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def attachment_definition
|
21
|
+
@definition
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid?
|
25
|
+
@definition.valid? && !@record.send(:"#{@name}_s3_key").nil?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|