/src/js/jquery.s3upload.js

http://github.com/slaskis/s3upload · JavaScript · 227 lines · 181 code · 22 blank · 24 comment · 45 complexity · f96487e8902a9d09cd125e639f7b5293 MD5 · raw file

  1. (function($){
  2. $.fn.s3upload = function( settings ) {
  3. var config = {
  4. text: null, // Defaults to the previous value of content of the element
  5. path: "/s3upload.swf",
  6. prefix: "",
  7. element: "<input type='text' />",
  8. signature_url: "/s3upload",
  9. required: false,
  10. submit_on_all_complete: true,
  11. error_class: "s3_error",
  12. file_types: []
  13. };
  14. if( settings ) $.extend( config , settings );
  15. // TODO Define settings for the default visuals (like progress percentage or bar)
  16. // if any element is a form find all :file inputs inside instead.
  17. var elements = this.map( function() {
  18. if( $(this).is("form") )
  19. return $(this).find(":file").toArray();
  20. return $(this);
  21. } );
  22. $.fn.s3upload.instances = $.fn.s3upload.instances || [];
  23. var started = 0;
  24. var completed = 0;
  25. return elements.each( function() {
  26. var form = $(this).closest("form");
  27. var id = $(this).attr("id") || "s3upload_" + $.fn.s3upload.instances.length;
  28. var name = $(this).attr("name");
  29. // Ignore already created instances
  30. if( $.inArray( id , $.fn.s3upload.instances ) != -1 )
  31. return;
  32. // replace the file input
  33. var el = $(config.element);
  34. el.attr( {
  35. id: id,
  36. "class": $(this).attr("class")
  37. });
  38. $(this).replaceWith(el);
  39. // Find the value of the original to use (useful for when a previous "upload" exists)
  40. var val = config.text;
  41. if( !val ) {
  42. if( $(this).is(":file") )
  43. val = $(this).attr("defaultValue");
  44. else if( $(this).is("input") )
  45. val = $(this).val();
  46. else
  47. val = $(this).html();
  48. }
  49. // A helper method to set the value, even if it's an input element
  50. var setValue = function(v) {
  51. if( el.is("input") )
  52. el.val(v);
  53. else
  54. el.html(v);
  55. }
  56. // create a div for the transparent flash button and absolute position it above the created element.
  57. var flash_div = $( "<div id='s3upload_"+id+"'><div id='flash_"+id+"'></div></div>" ).appendTo( "body" );
  58. // "Serialize" the filters
  59. var filters = $.map( config.file_types , function(f,i) { return f.join("#"); }).join("|");
  60. // Instantiate a swfobject in that div with js callbacks for selected, start, cancel, progress, error and complete
  61. var fv = {
  62. id: "flash_"+id,
  63. prefix: config.prefix,
  64. signatureURL: config.signature_url,
  65. filters: filters
  66. };
  67. var params = { wmode: "transparent" , menu: false };
  68. swfobject.embedSWF(config.path, fv.id, "100%", "100%", "9.0.0" , false, fv, params, false, function(e){
  69. if( e.success ) {
  70. var swf = e.ref;
  71. // Now that the flash has been initialized, show the initial text
  72. setValue(val);
  73. // Position the swf on top of the element (and keep it positioned)
  74. swf.update_interval = setInterval( function(){
  75. var pos = el.offset();
  76. flash_div.css({
  77. width: el.outerWidth(),
  78. height: el.outerHeight(),
  79. position: "absolute",
  80. top: pos.top,
  81. left: pos.left
  82. });
  83. } , 100 );
  84. // add a submit listener to the elements form which starts the upload in the flash instances.
  85. var formSubmit = function(e){
  86. if( config.required && !swf.info )
  87. swf.onerror( "Error: No file selected." );
  88. else if( swf.info )
  89. swf.upload();
  90. return false;
  91. }
  92. // Create SWF-JS callbacks
  93. swf.onenabled = function() {
  94. if( $.isFunction( config.onenabled ) )
  95. config.onenabled.call(el);
  96. if( !$.isFunction( swf.upload ) ) {
  97. swf.onerror( "S3UploadError: Callbacks could not be initialized. Try enabling the browser cache." );
  98. $(swf).parent().remove();
  99. }
  100. }
  101. swf.ondisabled = function() {
  102. if( $.isFunction( config.ondisabled ) )
  103. config.ondisabled.call(el);
  104. form.unbind("submit",formSubmit);
  105. }
  106. swf.onmouseevent = function(type,x,y) {
  107. var def = true;
  108. if( $.isFunction( config["on"+type] ) )
  109. def = config["on"+type].call(el,x,y);
  110. if( def ) {
  111. // Do default stuff: Run the regular dom events on "el"?
  112. el.trigger(type);
  113. }
  114. }
  115. swf.onselect = function(name,size,type) {
  116. swf.info = {name: name, size: size, type: type};
  117. var def = true;
  118. if( $.isFunction( config.onselect ) )
  119. def = config.onselect.call(el,swf.info);
  120. if( def ) {
  121. // Do default stuff: Replace the text of the div with the filename?
  122. setValue(config.prefix + name);
  123. }
  124. form.data("s3_selected",(form.data("s3_selected")||0) + 1 );
  125. form.submit(formSubmit);
  126. }
  127. swf.oncancel = function() {
  128. var def = true;
  129. if( $.isFunction( config.oncancel ) )
  130. def = config.oncancel.call(el,swf.info);
  131. if( def ) {
  132. // Do default stuff: Show a message? Go back to "Select file..." text?
  133. setValue(val);
  134. }
  135. swf.info = null;
  136. }
  137. swf.onstart = function() {
  138. var def = true;
  139. if( $.isFunction( config.onstart ) )
  140. def = config.onstart.call(el,swf.info);
  141. if( def ) {
  142. // Do default stuff: Replace the text of the div?
  143. }
  144. if( $.isFunction( swf.disable ) )
  145. swf.disable();
  146. }
  147. swf.onprogress = function(p) {
  148. var def = true;
  149. if( $.isFunction( config.onprogress ) )
  150. def = config.onprogress.call(el,p,swf.info);
  151. if( def ) {
  152. // Do default stuff: Fill the background of the div?
  153. setValue( Math.ceil( p * 100 ) + "%" );
  154. }
  155. }
  156. swf.onerror = function(msg) {
  157. var def = true;
  158. if( $.isFunction( config.onerror ) )
  159. def = config.onerror.call(el,msg,swf.info);
  160. if( def ) {
  161. // Do default stuff: Replace the text with the error message?
  162. if( !el.is("input") )
  163. setValue( "<span class='"+config.error_class+"'>" + msg + "</span>" );
  164. else
  165. setValue( msg );
  166. }
  167. if( $.isFunction( swf.enable ) )
  168. swf.enable();
  169. }
  170. swf.oncomplete = function(key) {
  171. // Add the key to the info object
  172. swf.info.key = key;
  173. var def = true;
  174. if( $.isFunction( config.oncomplete ) )
  175. def = config.oncomplete.call(el,swf.info);
  176. if( def ) {
  177. // Do default stuff...
  178. }
  179. // Create/Update the hidden inputs
  180. if( el.nextAll("input[name^="+name+"]").length == 0 )
  181. for( var k in swf.info )
  182. el.after( "<input type='hidden' name='"+name+"["+k+"]' value='"+swf.info[k]+"' />" );
  183. else
  184. for( var k in swf.info )
  185. el.siblings( "input[name="+name+"["+k+"]]" ).val( swf.info[k] );
  186. // Add to the total upload complete counter, and if it matches the number of uploads we submit the form.
  187. form.data("s3_completed",(form.data("s3_completed")||0) + 1 );
  188. var done = form.data("s3_completed") / form.data("s3_selected");
  189. // All Done! Do a regular form submit or just re-enable the flash.
  190. if( done == 1 ) {
  191. if( !config.submit_on_all_complete ) {
  192. if( $.isFunction( swf.enable ) )
  193. swf.enable();
  194. } else {
  195. form.unbind();
  196. form.submit();
  197. }
  198. }
  199. }
  200. }
  201. });
  202. $.fn.s3upload.instances.push( id );
  203. } );
  204. };
  205. })(jQuery);