2 * SWFUpload v2.0 by Jacob Roberts, Nov 2007, http://www.swfupload.org, http://linebyline.blogspot.com
3 * -------- -------- -------- -------- -------- -------- -------- --------
4 * SWFUpload is (c) 2006 Lars Huring and Mammon Media and is released under the MIT License:
5 * http://www.opensource.org/licenses/mit-license.php
7 * See Changelog.txt for version history
10 * * This version of SWFUpload requires Flash Player 9.0.28 and should autodetect the correct flash version.
11 * * In Linux Flash Player 9 setting the post file variable name does not work. It is always set to "Filedata".
12 * * There is a lot of repeated code that could be refactored to single functions. Feel free.
13 * * It's dangerous to do "circular calls" between Flash and JavaScript. I've taken steps to try to work around issues
14 * by having the event calls pipe through setTimeout. However you should still avoid calling in to Flash from
15 * within the event handler methods. Especially the "startUpload" event since it cannot use the setTimeout hack.
23 var SWFUpload = function (init_settings) {
24 this.initSWFUpload(init_settings);
27 SWFUpload.prototype.initSWFUpload = function (init_settings) {
28 // Remove background flicker in IE (read this: http://misterpixel.blogspot.com/2006/09/forensic-analysis-of-ie6.html)
29 // This doesn't have anything to do with SWFUpload but can help your UI behave better in IE.
31 document.execCommand('BackgroundImageCache', false, true);
37 this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
40 this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
41 this.movieElement = null;
43 // Setup global control tracking
44 SWFUpload.instances[this.movieName] = this;
46 // Load the settings. Load the Flash movie.
47 this.initSettings(init_settings);
50 this.displayDebugInfo();
60 SWFUpload.instances = {};
61 SWFUpload.movieCount = 0;
62 SWFUpload.QUEUE_ERROR = {
63 QUEUE_LIMIT_EXCEEDED : -100,
64 FILE_EXCEEDS_SIZE_LIMIT : -110,
65 ZERO_BYTE_FILE : -120,
66 INVALID_FILETYPE : -130
68 SWFUpload.UPLOAD_ERROR = {
70 MISSING_UPLOAD_URL : -210,
72 SECURITY_ERROR : -230,
73 UPLOAD_LIMIT_EXCEEDED : -240,
75 SPECIFIED_FILE_ID_NOT_FOUND : -260,
76 FILE_VALIDATION_FAILED : -270,
77 FILE_CANCELLED : -280,
80 SWFUpload.FILE_STATUS = {
89 /* ***************** */
90 /* Instance Thingies */
91 /* ***************** */
92 // init is a private method that ensures that all the object settings are set, getting a default value if one was not assigned.
94 SWFUpload.prototype.initSettings = function (init_settings) {
95 // Upload backend settings
96 this.addSetting("upload_url", init_settings.upload_url, "");
97 this.addSetting("file_post_name", init_settings.file_post_name, "Filedata");
98 this.addSetting("post_params", init_settings.post_params, {});
101 this.addSetting("file_types", init_settings.file_types, "*.*");
102 this.addSetting("file_types_description", init_settings.file_types_description, "All Files");
103 this.addSetting("file_size_limit", init_settings.file_size_limit, "1024");
104 this.addSetting("file_upload_limit", init_settings.file_upload_limit, "0");
105 this.addSetting("file_queue_limit", init_settings.file_queue_limit, "0");
108 this.addSetting("flash_url", init_settings.flash_url, "swfupload.swf");
109 this.addSetting("flash_width", init_settings.flash_width, "1px");
110 this.addSetting("flash_height", init_settings.flash_height, "1px");
111 this.addSetting("flash_color", init_settings.flash_color, "#FFFFFF");
114 this.addSetting("debug_enabled", init_settings.debug, false);
117 this.flashReady_handler = SWFUpload.flashReady; // This is a non-overrideable event handler
118 this.swfUploadLoaded_handler = this.retrieveSetting(init_settings.swfupload_loaded_handler, SWFUpload.swfUploadLoaded);
120 this.fileDialogStart_handler = this.retrieveSetting(init_settings.file_dialog_start_handler, SWFUpload.fileDialogStart);
121 this.fileQueued_handler = this.retrieveSetting(init_settings.file_queued_handler, SWFUpload.fileQueued);
122 this.fileQueueError_handler = this.retrieveSetting(init_settings.file_queue_error_handler, SWFUpload.fileQueueError);
123 this.fileDialogComplete_handler = this.retrieveSetting(init_settings.file_dialog_complete_handler, SWFUpload.fileDialogComplete);
125 this.uploadStart_handler = this.retrieveSetting(init_settings.upload_start_handler, SWFUpload.uploadStart);
126 this.uploadProgress_handler = this.retrieveSetting(init_settings.upload_progress_handler, SWFUpload.uploadProgress);
127 this.uploadError_handler = this.retrieveSetting(init_settings.upload_error_handler, SWFUpload.uploadError);
128 this.uploadSuccess_handler = this.retrieveSetting(init_settings.upload_success_handler, SWFUpload.uploadSuccess);
129 this.uploadComplete_handler = this.retrieveSetting(init_settings.upload_complete_handler, SWFUpload.uploadComplete);
131 this.debug_handler = this.retrieveSetting(init_settings.debug_handler, SWFUpload.debug);
134 this.customSettings = this.retrieveSetting(init_settings.custom_settings, {});
137 // loadFlash is a private method that generates the HTML tag for the Flash
138 // It then adds the flash to the "target" or to the body and stores a
139 // reference to the flash element in "movieElement".
140 SWFUpload.prototype.loadFlash = function () {
141 var html, target_element, container;
143 // Make sure an element with the ID we are going to use doesn't already exist
144 if (document.getElementById(this.movieName) !== null) {
148 // Get the body tag where we will be adding the flash movie
150 target_element = document.getElementsByTagName("body")[0];
151 if (typeof(target_element) === "undefined" || target_element === null) {
152 this.debug('Could not find the BODY element. SWFUpload failed to load.');
159 // Append the container and load the flash
160 container = document.createElement("div");
161 container.style.width = this.getSetting("flash_width");
162 container.style.height = this.getSetting("flash_height");
164 target_element.appendChild(container);
165 container.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
168 // Generates the embed/object tags needed to embed the flash in to the document
169 SWFUpload.prototype.getFlashHTML = function () {
172 // Create Mozilla Embed HTML
173 if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {
174 // Build the basic embed html
175 html = '<embed type="application/x-shockwave-flash" src="' + this.getSetting("flash_url") + '" width="' + this.getSetting("flash_width") + '" height="' + this.getSetting("flash_height") + '"';
176 html += ' id="' + this.movieName + '" name="' + this.movieName + '" ';
177 html += 'bgcolor="' + this.getSetting("flash_color") + '" quality="high" menu="false" flashvars="';
179 html += this.getFlashVars();
183 // Create IE Object HTML
186 // Build the basic Object tag
187 html = '<object id="' + this.movieName + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + this.getSetting("flash_width") + '" height="' + this.getSetting("flash_height") + '">';
188 html += '<param name="movie" value="' + this.getSetting("flash_url") + '">';
190 html += '<param name="bgcolor" value="' + this.getSetting("flash_color") + '" />';
191 html += '<param name="quality" value="high" />';
192 html += '<param name="menu" value="false" />';
194 html += '<param name="flashvars" value="' + this.getFlashVars() + '" />';
201 // This private method builds the parameter string that will be passed
203 SWFUpload.prototype.getFlashVars = function () {
204 // Build a string from the post param object
205 var param_string = this.buildParamString();
207 // Build the parameter string
209 html += "movieName=" + encodeURIComponent(this.movieName);
210 html += "&uploadURL=" + encodeURIComponent(this.getSetting("upload_url"));
211 html += "¶ms=" + encodeURIComponent(param_string);
212 html += "&filePostName=" + encodeURIComponent(this.getSetting("file_post_name"));
213 html += "&fileTypes=" + encodeURIComponent(this.getSetting("file_types"));
214 html += "&fileTypesDescription=" + encodeURIComponent(this.getSetting("file_types_description"));
215 html += "&fileSizeLimit=" + encodeURIComponent(this.getSetting("file_size_limit"));
216 html += "&fileUploadLimit=" + encodeURIComponent(this.getSetting("file_upload_limit"));
217 html += "&fileQueueLimit=" + encodeURIComponent(this.getSetting("file_queue_limit"));
218 html += "&debugEnabled=" + encodeURIComponent(this.getSetting("debug_enabled"));
223 SWFUpload.prototype.getMovieElement = function () {
224 if (typeof(this.movieElement) === "undefined" || this.movieElement === null) {
225 this.movieElement = document.getElementById(this.movieName);
227 // Fix IEs "Flash can't callback when in a form" issue (http://www.extremefx.com.ar/blog/fixing-flash-external-interface-inside-form-on-internet-explorer)
228 // Removed because Revision 6 always adds the flash to the body (inside a containing div)
229 // If you insist on adding the Flash file inside a Form then in IE you have to make you wait until the DOM is ready
230 // and run this code to make the form's ID available from the window object so Flash and JavaScript can communicate.
231 //if (typeof(window[this.movieName]) === "undefined" || window[this.moveName] !== this.movieElement) {
232 // window[this.movieName] = this.movieElement;
236 return this.movieElement;
239 SWFUpload.prototype.buildParamString = function () {
240 var post_params = this.getSetting("post_params");
241 var param_string_pairs = [];
244 // Retrieve the user defined parameters
245 if (typeof(post_params) === "object") {
246 for (name in post_params) {
247 if (post_params.hasOwnProperty(name)) {
248 if (typeof(post_params[name]) === "string") {
249 param_string_pairs.push(encodeURIComponent(name) + "=" + encodeURIComponent(post_params[name]));
255 return param_string_pairs.join("&");
258 // Saves a setting. If the value given is undefined or null then the default_value is used.
259 SWFUpload.prototype.addSetting = function (name, value, default_value) {
260 if (typeof(value) === "undefined" || value === null) {
261 this.settings[name] = default_value;
263 this.settings[name] = value;
266 return this.settings[name];
269 // Gets a setting. Returns empty string if not found.
270 SWFUpload.prototype.getSetting = function (name) {
271 if (typeof(this.settings[name]) === "undefined") {
274 return this.settings[name];
278 // Gets a setting, if the setting is undefined then return the default value
279 // This does not affect or use the interal setting object.
280 SWFUpload.prototype.retrieveSetting = function (value, default_value) {
281 if (typeof(value) === "undefined" || value === null) {
282 return default_value;
289 // It loops through all the settings and displays
290 // them in the debug Console.
291 SWFUpload.prototype.displayDebugInfo = function () {
292 var key, debug_message = "";
294 debug_message += "----- SWFUPLOAD SETTINGS ----\nID: " + this.moveName + "\n";
296 debug_message += this.outputObject(this.settings);
298 debug_message += "----- SWFUPLOAD SETTINGS END ----\n";
299 debug_message += "\n";
301 this.debug(debug_message);
303 SWFUpload.prototype.outputObject = function (object, prefix) {
304 var output = "", key;
306 if (typeof(prefix) !== "string") {
309 if (typeof(object) !== "object") {
313 for (key in object) {
314 if (object.hasOwnProperty(key)) {
315 if (typeof(object[key]) === "object") {
316 output += (prefix + key + ": { \n" + this.outputObject(object[key], "\t" + prefix) + prefix + "}" + "\n");
318 output += (prefix + key + ": " + object[key] + "\n");
326 /* *****************************
327 -- Flash control methods --
328 Your UI should use these
330 ***************************** */
332 SWFUpload.prototype.selectFile = function () {
333 var movie_element = this.getMovieElement();
334 if (movie_element !== null && typeof(movie_element.SelectFile) === "function") {
336 movie_element.SelectFile();
339 this.debug("Could not call SelectFile: " + ex);
342 this.debug("Could not find Flash element");
347 SWFUpload.prototype.selectFiles = function () {
348 var movie_element = this.getMovieElement();
349 if (movie_element !== null && typeof(movie_element.SelectFiles) === "function") {
351 movie_element.SelectFiles();
354 this.debug("Could not call SelectFiles: " + ex);
357 this.debug("Could not find Flash element");
363 /* Start the upload. If a file_id is specified that file is uploaded. Otherwise the first
364 * file in the queue is uploaded. If no files are in the queue then nothing happens.
365 * This call uses setTimeout since Flash will be calling back in to JavaScript
367 SWFUpload.prototype.startUpload = function (file_id) {
369 var movie_element = this.getMovieElement();
370 if (movie_element !== null && typeof(movie_element.StartUpload) === "function") {
374 movie_element.StartUpload(file_id);
377 self.debug("Could not call StartUpload: " + ex);
382 this.debug("Could not find Flash element");
387 /* Cancels a the file upload. You must specify a file_id */
388 SWFUpload.prototype.cancelUpload = function (file_id) {
389 var movie_element = this.getMovieElement();
390 if (movie_element !== null && typeof(movie_element.CancelUpload) === "function") {
392 movie_element.CancelUpload(file_id);
395 this.debug("Could not call CancelUpload: " + ex);
398 this.debug("Could not find Flash element");
403 // Stops the current upload. The file is re-queued. If nothing is currently uploading then nothing happens.
404 SWFUpload.prototype.stopUpload = function () {
405 var movie_element = this.getMovieElement();
406 if (movie_element !== null && typeof(movie_element.StopUpload) === "function") {
408 movie_element.StopUpload();
411 this.debug("Could not call StopUpload: " + ex);
414 this.debug("Could not find Flash element");
419 /* ************************
421 * These methods change the settings inside SWFUpload
422 * They shouldn't need to be called in a setTimeout since they
423 * should not call back from Flash to JavaScript (except perhaps in a Debug call)
424 * and some need to return data so setTimeout won't work.
427 /* Gets the file statistics object. It looks like this (where n = number):
432 uploads_cancelled: n,
436 SWFUpload.prototype.getStats = function () {
437 var movie_element = this.getMovieElement();
438 if (movie_element !== null && typeof(movie_element.GetStats) === "function") {
440 return movie_element.GetStats();
443 this.debug("Could not call GetStats");
446 this.debug("Could not find Flash element");
449 SWFUpload.prototype.setStats = function (stats_object) {
450 var movie_element = this.getMovieElement();
451 if (movie_element !== null && typeof(movie_element.SetStats) === "function") {
453 movie_element.SetStats(stats_object);
456 this.debug("Could not call SetStats");
459 this.debug("Could not find Flash element");
463 SWFUpload.prototype.setCredentials = function(name, password) {
464 var movie_element = this.getMovieElement();
465 if (movie_element !== null && typeof(movie_element.SetCredentials) === "function") {
467 return movie_element.SetCredentials(name, password);
470 this.debug("Could not call SetCredentials");
473 this.debug("Could not find Flash element");
477 SWFUpload.prototype.getFile = function (file_id) {
478 var movie_element = this.getMovieElement();
479 if (typeof(file_id) === "number") {
480 if (movie_element !== null && typeof(movie_element.GetFileByIndex) === "function") {
482 return movie_element.GetFileByIndex(file_id);
485 this.debug("Could not call GetFileByIndex");
488 this.debug("Could not find Flash element");
491 if (movie_element !== null && typeof(movie_element.GetFile) === "function") {
493 return movie_element.GetFile(file_id);
496 this.debug("Could not call GetFile");
499 this.debug("Could not find Flash element");
504 SWFUpload.prototype.addFileParam = function (file_id, name, value) {
505 var movie_element = this.getMovieElement();
506 if (movie_element !== null && typeof(movie_element.AddFileParam) === "function") {
508 return movie_element.AddFileParam(file_id, name, value);
511 this.debug("Could not call AddFileParam");
514 this.debug("Could not find Flash element");
518 SWFUpload.prototype.removeFileParam = function (file_id, name) {
519 var movie_element = this.getMovieElement();
520 if (movie_element !== null && typeof(movie_element.RemoveFileParam) === "function") {
522 return movie_element.RemoveFileParam(file_id, name);
525 this.debug("Could not call AddFileParam");
528 this.debug("Could not find Flash element");
533 SWFUpload.prototype.setUploadURL = function (url) {
534 var movie_element = this.getMovieElement();
535 if (movie_element !== null && typeof(movie_element.SetUploadURL) === "function") {
537 this.addSetting("upload_url", url);
538 movie_element.SetUploadURL(this.getSetting("upload_url"));
541 this.debug("Could not call SetUploadURL");
544 this.debug("Could not find Flash element in setUploadURL");
548 SWFUpload.prototype.setPostParams = function (param_object) {
549 var movie_element = this.getMovieElement();
550 if (movie_element !== null && typeof(movie_element.SetPostParams) === "function") {
552 this.addSetting("post_params", param_object);
553 movie_element.SetPostParams(this.getSetting("post_params"));
556 this.debug("Could not call SetPostParams");
559 this.debug("Could not find Flash element in SetPostParams");
563 SWFUpload.prototype.setFileTypes = function (types, description) {
564 var movie_element = this.getMovieElement();
565 if (movie_element !== null && typeof(movie_element.SetFileTypes) === "function") {
567 this.addSetting("file_types", types);
568 this.addSetting("file_types_description", description);
569 movie_element.SetFileTypes(this.getSetting("file_types"), this.getSetting("file_types_description"));
572 this.debug("Could not call SetFileTypes");
575 this.debug("Could not find Flash element in SetFileTypes");
579 SWFUpload.prototype.setFileSizeLimit = function (file_size_limit) {
580 var movie_element = this.getMovieElement();
581 if (movie_element !== null && typeof(movie_element.SetFileSizeLimit) === "function") {
583 this.addSetting("file_size_limit", file_size_limit);
584 movie_element.SetFileSizeLimit(this.getSetting("file_size_limit"));
587 this.debug("Could not call SetFileSizeLimit");
590 this.debug("Could not find Flash element in SetFileSizeLimit");
594 SWFUpload.prototype.setFileUploadLimit = function (file_upload_limit) {
595 var movie_element = this.getMovieElement();
596 if (movie_element !== null && typeof(movie_element.SetFileUploadLimit) === "function") {
598 this.addSetting("file_upload_limit", file_upload_limit);
599 movie_element.SetFileUploadLimit(this.getSetting("file_upload_limit"));
602 this.debug("Could not call SetFileUploadLimit");
605 this.debug("Could not find Flash element in SetFileUploadLimit");
609 SWFUpload.prototype.setFileQueueLimit = function (file_queue_limit) {
610 var movie_element = this.getMovieElement();
611 if (movie_element !== null && typeof(movie_element.SetFileQueueLimit) === "function") {
613 this.addSetting("file_queue_limit", file_queue_limit);
614 movie_element.SetFileQueueLimit(this.getSetting("file_queue_limit"));
617 this.debug("Could not call SetFileQueueLimit");
620 this.debug("Could not find Flash element in SetFileQueueLimit");
624 SWFUpload.prototype.setFilePostName = function (file_post_name) {
625 var movie_element = this.getMovieElement();
626 if (movie_element !== null && typeof(movie_element.SetFilePostName) === "function") {
628 this.addSetting("file_post_name", file_post_name);
629 movie_element.SetFilePostName(this.getSetting("file_post_name"));
632 this.debug("Could not call SetFilePostName");
635 this.debug("Could not find Flash element in SetFilePostName");
639 SWFUpload.prototype.setDebugEnabled = function (debug_enabled) {
640 var movie_element = this.getMovieElement();
641 if (movie_element !== null && typeof(movie_element.SetDebugEnabled) === "function") {
643 this.addSetting("debug_enabled", debug_enabled);
644 movie_element.SetDebugEnabled(this.getSetting("debug_enabled"));
647 this.debug("Could not call SetDebugEnabled");
650 this.debug("Could not find Flash element in SetDebugEnabled");
654 /* *******************************
655 Internal Event Callers
656 Don't override these! These event callers ensure that your custom event handlers
657 are called safely and in order.
658 ******************************* */
660 /* This is the callback method that the Flash movie will call when it has been loaded and is ready to go.
661 Calling this or showUI() "manually" will bypass the Flash Detection built in to SWFUpload.
662 Use a ui_function setting if you want to control the UI loading after the flash has loaded.
664 SWFUpload.prototype.flashReady = function () {
665 // Check that the movie element is loaded correctly with its ExternalInterface methods defined
666 var movie_element = this.getMovieElement();
667 if (movie_element === null || typeof(movie_element.StartUpload) !== "function") {
668 this.debug("ExternalInterface methods failed to initialize.");
673 if (typeof(self.flashReady_handler) === "function") {
674 this.eventQueue[this.eventQueue.length] = function() { self.flashReady_handler(); };
675 setTimeout(function () { self.executeNextEvent();}, 0);
677 this.debug("flashReady_handler event not defined");
682 Event Queue. Rather can call events directly from Flash they events are
683 are placed in a queue and then executed. This ensures that each event is
684 executed in the order it was called which is not guarenteed when calling
685 setTimeout. Out of order events was especially problematic in Safari.
687 SWFUpload.prototype.executeNextEvent = function () {
688 var f = this.eventQueue.shift();
689 if (typeof(f) === "function") {
694 /* This is a chance to do something before the browse window opens */
695 SWFUpload.prototype.fileDialogStart = function () {
697 if (typeof(self.fileDialogStart_handler) === "function") {
698 this.eventQueue[this.eventQueue.length] = function() { self.fileDialogStart_handler(); };
699 setTimeout(function () { self.executeNextEvent();}, 0);
701 this.debug("fileDialogStart event not defined");
706 /* Called when a file is successfully added to the queue. */
707 SWFUpload.prototype.fileQueued = function (file) {
709 if (typeof(self.fileQueued_handler) === "function") {
710 this.eventQueue[this.eventQueue.length] = function() { self.fileQueued_handler(file); };
711 setTimeout(function () { self.executeNextEvent();}, 0);
713 this.debug("fileQueued event not defined");
718 /* Handle errors that occur when an attempt to queue a file fails. */
719 SWFUpload.prototype.fileQueueError = function (file, error_code, message) {
721 if (typeof(self.fileQueueError_handler) === "function") {
722 this.eventQueue[this.eventQueue.length] = function() { self.fileQueueError_handler(file, error_code, message); };
723 setTimeout(function () { self.executeNextEvent();}, 0);
725 this.debug("fileQueueError event not defined");
729 /* Called after the file dialog has closed and the selected files have been queued.
730 You could call startUpload here if you want the queued files to begin uploading immediately. */
731 SWFUpload.prototype.fileDialogComplete = function (num_files_selected) {
733 if (typeof(self.fileDialogComplete_handler) === "function") {
734 this.eventQueue[this.eventQueue.length] = function() { self.fileDialogComplete_handler(num_files_selected); };
735 setTimeout(function () { self.executeNextEvent();}, 0);
737 this.debug("fileDialogComplete event not defined");
741 /* Gets called when a file upload is about to be started. Return true to continue the upload. Return false to stop the upload.
742 If you return false then uploadError and uploadComplete are called (like normal).
744 This is a good place to do any file validation you need.
746 SWFUpload.prototype.uploadStart = function (file) {
748 if (typeof(self.fileDialogComplete_handler) === "function") {
749 this.eventQueue[this.eventQueue.length] = function() { self.returnUploadStart(self.uploadStart_handler(file)); };
750 setTimeout(function () { self.executeNextEvent();}, 0);
752 this.debug("uploadStart event not defined");
756 /* Note: Internal use only. This function returns the result of uploadStart to
757 flash. Since returning values in the normal way can result in Flash/JS circular
758 call issues we split up the call in a Timeout. This is transparent from the API
761 SWFUpload.prototype.returnUploadStart = function (return_value) {
762 var movie_element = this.getMovieElement();
763 if (movie_element !== null && typeof(movie_element.ReturnUploadStart) === "function") {
765 movie_element.ReturnUploadStart(return_value);
768 this.debug("Could not call ReturnUploadStart");
771 this.debug("Could not find Flash element in returnUploadStart");
777 /* Called during upload as the file progresses. Use this event to update your UI. */
778 SWFUpload.prototype.uploadProgress = function (file, bytes_complete, bytes_total) {
780 if (typeof(self.uploadProgress_handler) === "function") {
781 this.eventQueue[this.eventQueue.length] = function() { self.uploadProgress_handler(file, bytes_complete, bytes_total); };
782 setTimeout(function () { self.executeNextEvent();}, 0);
784 this.debug("uploadProgress event not defined");
788 /* Called when an error occurs during an upload. Use error_code and the SWFUpload.UPLOAD_ERROR constants to determine
789 which error occurred. The uploadComplete event is called after an error code indicating that the next file is
790 ready for upload. For files cancelled out of order the uploadComplete event will not be called. */
791 SWFUpload.prototype.uploadError = function (file, error_code, message) {
793 if (typeof(this.uploadError_handler) === "function") {
794 this.eventQueue[this.eventQueue.length] = function() { self.uploadError_handler(file, error_code, message); };
795 setTimeout(function () { self.executeNextEvent();}, 0);
797 this.debug("uploadError event not defined");
801 /* This gets called when a file finishes uploading and the server-side upload script has completed and returned a 200
802 status code. Any text returned by the server is available in server_data.
803 **NOTE: The upload script MUST return some text or the uploadSuccess and uploadComplete events will not fire and the
804 upload will become 'stuck'. */
805 SWFUpload.prototype.uploadSuccess = function (file, server_data) {
807 if (typeof(self.uploadSuccess_handler) === "function") {
808 this.eventQueue[this.eventQueue.length] = function() { self.uploadSuccess_handler(file, server_data); };
809 setTimeout(function () { self.executeNextEvent();}, 0);
811 this.debug("uploadSuccess event not defined");
815 /* uploadComplete is called when the file is uploaded or an error occurred and SWFUpload is ready to make the next upload.
816 If you want the next upload to start to automatically you can call startUpload() from this event. */
817 SWFUpload.prototype.uploadComplete = function (file) {
819 if (typeof(self.uploadComplete_handler) === "function") {
820 this.eventQueue[this.eventQueue.length] = function() { self.uploadComplete_handler(file); };
821 setTimeout(function () { self.executeNextEvent();}, 0);
823 this.debug("uploadComplete event not defined");
827 /* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
828 internal debug console. You can override this event and have messages written where you want. */
829 SWFUpload.prototype.debug = function (message) {
831 if (typeof(self.debug_handler) === "function") {
832 this.eventQueue[this.eventQueue.length] = function() { self.debug_handler(message); };
833 setTimeout(function () { self.executeNextEvent();}, 0);
835 this.eventQueue[this.eventQueue.length] = function() { self.debugMessage(message); };
836 setTimeout(function () { self.executeNextEvent();}, 0);
841 /* **********************************
842 Default Event Handlers.
843 These event handlers are used by default if an overriding handler is
844 not defined in the SWFUpload settings object.
846 JS Note: even though these are defined on the SWFUpload object (rather than the prototype) they
847 are attached (read: copied) to a SWFUpload instance and 'this' is given the proper context.
848 ********************************** */
850 /* This is a special event handler that has no override in the settings. Flash calls this when it has
851 been loaded by the browser and is ready for interaction. You should not override it. If you need
852 to do something with SWFUpload has loaded then use the swfupload_loaded_handler setting.
854 SWFUpload.flashReady = function () {
856 this.debug("Flash called back and is ready.");
858 if (typeof(this.swfUploadLoaded_handler) === "function") {
859 this.swfUploadLoaded_handler();
866 /* This is a chance to something immediately after SWFUpload has loaded.
867 Like, hide the default/degraded upload form and display the SWFUpload form. */
868 SWFUpload.swfUploadLoaded = function () {
871 /* This is a chance to do something before the browse window opens */
872 SWFUpload.fileDialogStart = function () {
876 /* Called when a file is successfully added to the queue. */
877 SWFUpload.fileQueued = function (file) {
881 /* Handle errors that occur when an attempt to queue a file fails. */
882 SWFUpload.fileQueueError = function (file, error_code, message) {
884 switch (error_code) {
885 case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
886 this.debug("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
888 case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
889 this.debug("Error Code: Zero Byte File, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
891 case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:
892 this.debug("Error Code: Upload limit reached, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
894 case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
895 this.debug("Error Code: File extension is not allowed, Message: " + message);
898 this.debug("Error Code: Unhandled error occured. Errorcode: " + error_code);
905 /* Called after the file dialog has closed and the selected files have been queued.
906 You could call startUpload here if you want the queued files to begin uploading immediately. */
907 SWFUpload.fileDialogComplete = function (num_files_selected) {
910 /* Gets called when a file upload is about to be started. Return true to continue the upload. Return false to stop the upload.
911 If you return false then the uploadError callback is called and then uploadComplete (like normal).
913 This is a good place to do any file validation you need.
915 This is the only function that cannot be called on a setTimeout because it must return a value to Flash.
916 You SHOULD NOT make any calls in to Flash (e.i, changing settings, getting stats, etc). Flash Player bugs prevent
917 calls in to Flash from working reliably.
919 SWFUpload.uploadStart = function (file) {
923 // Called during upload as the file progresses
924 SWFUpload.uploadProgress = function (file, bytes_complete, bytes_total) {
925 this.debug("File Progress: " + file.id + ", Bytes: " + bytes_complete + ". Total: " + bytes_total);
928 /* This gets called when a file finishes uploading and the upload script has completed and returned a 200 status code. Any text returned by the
929 server is available in server_data. The upload script must return some text or uploadSuccess will not fire (neither will uploadComplete). */
930 SWFUpload.uploadSuccess = function (file, server_data) {
931 this.debug("Upload Success: " + file.id + ", Server: " + server_data);
934 /* This is called last. The file is uploaded or an error occurred and SWFUpload is ready to make the next upload.
935 If you want to automatically start the next file just call startUpload from here.
937 SWFUpload.uploadComplete = function (file) {
938 this.debug("Upload Complete: " + file.id);
941 // Called by SWFUpload JavaScript and Flash functions when debug is enabled.
942 // Override this method in your settings to call your own debug message handler
943 SWFUpload.debug = function (message) {
944 if (this.getSetting("debug_enabled")) {
945 this.debugMessage(message);
949 /* Called when an upload occurs during upload. For HTTP errors 'message' will contain the HTTP STATUS CODE */
950 SWFUpload.uploadError = function (file, errcode, msg) {
953 case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
954 this.debug("Error Code: File ID specified for upload was not found, Message: " + msg);
956 case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
957 this.debug("Error Code: HTTP Error, File name: " + file.name + ", Message: " + msg);
959 case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
960 this.debug("Error Code: No backend file, File name: " + file.name + ", Message: " + msg);
962 case SWFUpload.UPLOAD_ERROR.IO_ERROR:
963 this.debug("Error Code: IO Error, File name: " + file.name + ", Message: " + msg);
965 case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
966 this.debug("Error Code: Security Error, File name: " + file.name + ", Message: " + msg);
968 case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
969 this.debug("Error Code: Upload limit reached, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
971 case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
972 this.debug("Error Code: Upload Initialization exception, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
974 case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
975 this.debug("Error Code: uploadStart callback returned false, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
977 case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
978 this.debug("Error Code: The file upload was cancelled, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
980 case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
981 this.debug("Error Code: The file upload was stopped, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
984 this.debug("Error Code: Unhandled error occured. Errorcode: " + errcode);
993 /* **********************************
995 The debug console is a self contained, in page location
996 for debug message to be sent. The Debug Console adds
997 itself to the body if necessary.
999 The console is automatically scrolled as messages appear.
1001 You can override this console (to use FireBug's console for instance) by setting the debug event method to your own function
1002 that handles the debug message
1003 ********************************** */
1004 SWFUpload.prototype.debugMessage = function (message) {
1005 var exception_message, exception_values;
1007 if (typeof(message) === "object" && typeof(message.name) === "string" && typeof(message.message) === "string") {
1008 exception_message = "";
1009 exception_values = [];
1010 for (var key in message) {
1011 exception_values.push(key + ": " + message[key]);
1013 exception_message = exception_values.join("\n");
1014 exception_values = exception_message.split("\n");
1015 exception_message = "EXCEPTION: " + exception_values.join("\nEXCEPTION: ");
1016 SWFUpload.Console.writeLine(exception_message);
1018 SWFUpload.Console.writeLine(message);
1022 SWFUpload.Console = {};
1023 SWFUpload.Console.writeLine = function (message) {
1024 var console, documentForm;
1027 console = document.getElementById("SWFUpload_Console");
1030 documentForm = document.createElement("form");
1031 document.getElementsByTagName("body")[0].appendChild(documentForm);
1033 console = document.createElement("textarea");
1034 console.id = "SWFUpload_Console";
1035 console.style.fontFamily = "monospace";
1036 console.setAttribute("wrap", "off");
1037 console.wrap = "off";
1038 console.style.overflow = "auto";
1039 console.style.width = "700px";
1040 console.style.height = "350px";
1041 console.style.margin = "5px";
1042 documentForm.appendChild(console);
1045 console.value += message + "\n";
1047 console.scrollTop = console.scrollHeight - console.clientHeight;
1049 alert("Exception: " + ex.name + " Message: " + ex.message);