PageRenderTime 76ms CodeModel.GetById 24ms app.highlight 19ms RepoModel.GetById 23ms app.codeStats 0ms

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