]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/swfupload/swfupload.js
Wordpress 2.5.1-scripts
[autoinstalls/wordpress.git] / wp-includes / js / swfupload / swfupload.js
1 /**
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
6  *
7  * See Changelog.txt for version history
8  *
9  * Development Notes:
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.
16  */
17
18
19 /* *********** */
20 /* Constructor */
21 /* *********** */
22
23 var SWFUpload = function (init_settings) {
24         this.initSWFUpload(init_settings);
25 };
26
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.
30         try {
31                 document.execCommand('BackgroundImageCache', false, true);
32         } catch (ex1) {
33         }
34
35
36         try {
37                 this.customSettings = {};       // A container where developers can place their own settings associated with this instance.
38                 this.settings = {};
39                 this.eventQueue = [];
40                 this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
41                 this.movieElement = null;
42
43                 // Setup global control tracking
44                 SWFUpload.instances[this.movieName] = this;
45
46                 // Load the settings.  Load the Flash movie.
47                 this.initSettings(init_settings);
48                 this.loadFlash();
49
50                 this.displayDebugInfo();
51
52         } catch (ex2) {
53                 this.debug(ex2);
54         }
55 }
56
57 /* *************** */
58 /* Static thingies */
59 /* *************** */
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
67 };
68 SWFUpload.UPLOAD_ERROR = {
69         HTTP_ERROR                                              : -200,
70         MISSING_UPLOAD_URL                      : -210,
71         IO_ERROR                                                : -220,
72         SECURITY_ERROR                                  : -230,
73         UPLOAD_LIMIT_EXCEEDED                   : -240,
74         UPLOAD_FAILED                                   : -250,
75         SPECIFIED_FILE_ID_NOT_FOUND             : -260,
76         FILE_VALIDATION_FAILED                  : -270,
77         FILE_CANCELLED                                  : -280,
78         UPLOAD_STOPPED                                  : -290
79 };
80 SWFUpload.FILE_STATUS = {
81         QUEUED           : -1,
82         IN_PROGRESS      : -2,
83         ERROR            : -3,
84         COMPLETE         : -4,
85         CANCELLED        : -5
86 };
87
88
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.
93
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,                              {});
99
100         // File Settings
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");
106
107         // Flash Settings
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");
112
113         // Debug Settings
114         this.addSetting("debug_enabled", init_settings.debug,  false);
115
116         // Event Handlers
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);
119         
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);
124         
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);
130
131         this.debug_handler                              = this.retrieveSetting(init_settings.debug_handler,                                     SWFUpload.debug);
132
133         // Other settings
134         this.customSettings = this.retrieveSetting(init_settings.custom_settings, {});
135 };
136
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;
142
143         // Make sure an element with the ID we are going to use doesn't already exist
144         if (document.getElementById(this.movieName) !== null) {
145                 return false;
146         }
147
148         // Get the body tag where we will be adding the flash movie
149         try {
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.');
153                         return false;
154                 }
155         } catch (ex) {
156                 return false;
157         }
158
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");
163
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)
166 };
167
168 // Generates the embed/object tags needed to embed the flash in to the document
169 SWFUpload.prototype.getFlashHTML = function () {
170         var html = "";
171
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="';
178
179                 html += this.getFlashVars();
180
181                 html += '" />';
182
183                 // Create IE Object HTML
184         } else {
185
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") + '">';
189
190                 html += '<param name="bgcolor" value="' + this.getSetting("flash_color") + '" />';
191                 html += '<param name="quality" value="high" />';
192                 html += '<param name="menu" value="false" />';
193
194                 html += '<param name="flashvars" value="' + this.getFlashVars() + '" />';
195                 html += '</object>';
196         }
197
198         return html;
199 };
200
201 // This private method builds the parameter string that will be passed
202 // to flash.
203 SWFUpload.prototype.getFlashVars = function () {
204         // Build a string from the post param object
205         var param_string = this.buildParamString();
206
207         // Build the parameter string
208         var html = "";
209         html += "movieName=" + encodeURIComponent(this.movieName);
210         html += "&uploadURL=" + encodeURIComponent(this.getSetting("upload_url"));
211         html += "&params=" + 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"));
219
220         return html;
221 };
222
223 SWFUpload.prototype.getMovieElement = function () {
224         if (typeof(this.movieElement) === "undefined" || this.movieElement === null) {
225                 this.movieElement = document.getElementById(this.movieName);
226
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;
233                 //}
234         }
235
236         return this.movieElement;
237 };
238
239 SWFUpload.prototype.buildParamString = function () {
240         var post_params = this.getSetting("post_params");
241         var param_string_pairs = [];
242         var i, value, name;
243
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]));
250                                 }
251                         }
252                 }
253         }
254
255         return param_string_pairs.join("&");
256 };
257
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;
262         } else {
263                 this.settings[name] = value;
264         }
265
266         return this.settings[name];
267 };
268
269 // Gets a setting.      Returns empty string if not found.
270 SWFUpload.prototype.getSetting = function (name) {
271         if (typeof(this.settings[name]) === "undefined") {
272                 return "";
273         } else {
274                 return this.settings[name];
275         }
276 };
277
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;
283         } else {
284                 return value;
285         }
286 };
287
288
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 = "";
293
294         debug_message += "----- SWFUPLOAD SETTINGS     ----\nID: " + this.moveName + "\n";
295
296         debug_message += this.outputObject(this.settings);
297
298         debug_message += "----- SWFUPLOAD SETTINGS END ----\n";
299         debug_message += "\n";
300
301         this.debug(debug_message);
302 };
303 SWFUpload.prototype.outputObject = function (object, prefix) {
304         var output = "", key;
305
306         if (typeof(prefix) !== "string") {
307                 prefix = "";
308         }
309         if (typeof(object) !== "object") {
310                 return "";
311         }
312
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");
317                         } else {
318                                 output += (prefix + key + ": " + object[key] + "\n");
319                         }
320                 }
321         }
322
323         return output;
324 };
325
326 /* *****************************
327         -- Flash control methods --
328         Your UI should use these
329         to operate SWFUpload
330    ***************************** */
331
332 SWFUpload.prototype.selectFile = function () {
333         var movie_element = this.getMovieElement();
334         if (movie_element !== null && typeof(movie_element.SelectFile) === "function") {
335                 try {
336                         movie_element.SelectFile();
337                 }
338                 catch (ex) {
339                         this.debug("Could not call SelectFile: " + ex);
340                 }
341         } else {
342                 this.debug("Could not find Flash element");
343         }
344
345 };
346
347 SWFUpload.prototype.selectFiles = function () {
348         var movie_element = this.getMovieElement();
349         if (movie_element !== null && typeof(movie_element.SelectFiles) === "function") {
350                 try {
351                         movie_element.SelectFiles();
352                 }
353                 catch (ex) {
354                         this.debug("Could not call SelectFiles: " + ex);
355                 }
356         } else {
357                 this.debug("Could not find Flash element");
358         }
359
360 };
361
362
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
366  */
367 SWFUpload.prototype.startUpload = function (file_id) {
368         var self = this;
369         var movie_element = this.getMovieElement();
370         if (movie_element !== null && typeof(movie_element.StartUpload) === "function") {
371                 setTimeout(
372                         function () {
373                                 try {
374                                         movie_element.StartUpload(file_id);
375                                 }
376                                 catch (ex) {
377                                         self.debug("Could not call StartUpload: " + ex);
378                                 }
379                         }, 0
380                 );
381         } else {
382                 this.debug("Could not find Flash element");
383         }
384
385 };
386
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") {
391                 try {
392                         movie_element.CancelUpload(file_id);
393                 }
394                 catch (ex) {
395                         this.debug("Could not call CancelUpload: " + ex);
396                 }
397         } else {
398                 this.debug("Could not find Flash element");
399         }
400
401 };
402
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") {
407                 try {
408                         movie_element.StopUpload();
409                 }
410                 catch (ex) {
411                         this.debug("Could not call StopUpload: " + ex);
412                 }
413         } else {
414                 this.debug("Could not find Flash element");
415         }
416
417 };
418
419 /* ************************
420  * Settings methods
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.
425  */
426
427 /* Gets the file statistics object.      It looks like this (where n = number):
428         {
429                 files_queued: n,
430                 complete_uploads: n,
431                 upload_errors: n,
432                 uploads_cancelled: n,
433                 queue_errors: n
434         }
435 */
436 SWFUpload.prototype.getStats = function () {
437         var movie_element = this.getMovieElement();
438         if (movie_element !== null && typeof(movie_element.GetStats) === "function") {
439                 try {
440                         return movie_element.GetStats();
441                 }
442                 catch (ex) {
443                         this.debug("Could not call GetStats");
444                 }
445         } else {
446                 this.debug("Could not find Flash element");
447         }
448 };
449 SWFUpload.prototype.setStats = function (stats_object) {
450         var movie_element = this.getMovieElement();
451         if (movie_element !== null && typeof(movie_element.SetStats) === "function") {
452                 try {
453                         movie_element.SetStats(stats_object);
454                 }
455                 catch (ex) {
456                         this.debug("Could not call SetStats");
457                 }
458         } else {
459                 this.debug("Could not find Flash element");
460         }
461 };
462
463 SWFUpload.prototype.setCredentials = function(name, password) {
464         var movie_element = this.getMovieElement();
465         if (movie_element !== null && typeof(movie_element.SetCredentials) === "function") {
466                 try {
467                         return movie_element.SetCredentials(name, password);
468                 }
469                 catch (ex) {
470                         this.debug("Could not call SetCredentials");
471                 }
472         } else {
473                 this.debug("Could not find Flash element");
474         }
475 };
476
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") {
481                                         try {
482                                                 return movie_element.GetFileByIndex(file_id);
483                                         }
484                                         catch (ex) {
485                                                 this.debug("Could not call GetFileByIndex");
486                                         }
487                                 } else {
488                                         this.debug("Could not find Flash element");
489                                 }
490                         } else {
491                                 if (movie_element !== null && typeof(movie_element.GetFile) === "function") {
492                                         try {
493                                                 return movie_element.GetFile(file_id);
494                                         }
495                                         catch (ex) {
496                                                 this.debug("Could not call GetFile");
497                                         }
498                                 } else {
499                                         this.debug("Could not find Flash element");
500                                 }
501                         }
502 };
503
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") {
507                 try {
508                         return movie_element.AddFileParam(file_id, name, value);
509                 }
510                 catch (ex) {
511                         this.debug("Could not call AddFileParam");
512                 }
513         } else {
514                 this.debug("Could not find Flash element");
515         }
516 };
517
518 SWFUpload.prototype.removeFileParam = function (file_id, name) {
519         var movie_element = this.getMovieElement();
520         if (movie_element !== null && typeof(movie_element.RemoveFileParam) === "function") {
521                 try {
522                         return movie_element.RemoveFileParam(file_id, name);
523                 }
524                 catch (ex) {
525                         this.debug("Could not call AddFileParam");
526                 }
527         } else {
528                 this.debug("Could not find Flash element");
529         }
530
531 };
532
533 SWFUpload.prototype.setUploadURL = function (url) {
534         var movie_element = this.getMovieElement();
535         if (movie_element !== null && typeof(movie_element.SetUploadURL) === "function") {
536                 try {
537                         this.addSetting("upload_url", url);
538                         movie_element.SetUploadURL(this.getSetting("upload_url"));
539                 }
540                 catch (ex) {
541                         this.debug("Could not call SetUploadURL");
542                 }
543         } else {
544                 this.debug("Could not find Flash element in setUploadURL");
545         }
546 };
547
548 SWFUpload.prototype.setPostParams = function (param_object) {
549         var movie_element = this.getMovieElement();
550         if (movie_element !== null && typeof(movie_element.SetPostParams) === "function") {
551                 try {
552                         this.addSetting("post_params", param_object);
553                         movie_element.SetPostParams(this.getSetting("post_params"));
554                 }
555                 catch (ex) {
556                         this.debug("Could not call SetPostParams");
557                 }
558         } else {
559                 this.debug("Could not find Flash element in SetPostParams");
560         }
561 };
562
563 SWFUpload.prototype.setFileTypes = function (types, description) {
564         var movie_element = this.getMovieElement();
565         if (movie_element !== null && typeof(movie_element.SetFileTypes) === "function") {
566                 try {
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"));
570                 }
571                 catch (ex) {
572                         this.debug("Could not call SetFileTypes");
573                 }
574         } else {
575                 this.debug("Could not find Flash element in SetFileTypes");
576         }
577 };
578
579 SWFUpload.prototype.setFileSizeLimit = function (file_size_limit) {
580         var movie_element = this.getMovieElement();
581         if (movie_element !== null && typeof(movie_element.SetFileSizeLimit) === "function") {
582                 try {
583                         this.addSetting("file_size_limit", file_size_limit);
584                         movie_element.SetFileSizeLimit(this.getSetting("file_size_limit"));
585                 }
586                 catch (ex) {
587                         this.debug("Could not call SetFileSizeLimit");
588                 }
589         } else {
590                 this.debug("Could not find Flash element in SetFileSizeLimit");
591         }
592 };
593
594 SWFUpload.prototype.setFileUploadLimit = function (file_upload_limit) {
595         var movie_element = this.getMovieElement();
596         if (movie_element !== null && typeof(movie_element.SetFileUploadLimit) === "function") {
597                 try {
598                         this.addSetting("file_upload_limit", file_upload_limit);
599                         movie_element.SetFileUploadLimit(this.getSetting("file_upload_limit"));
600                 }
601                 catch (ex) {
602                         this.debug("Could not call SetFileUploadLimit");
603                 }
604         } else {
605                 this.debug("Could not find Flash element in SetFileUploadLimit");
606         }
607 };
608
609 SWFUpload.prototype.setFileQueueLimit = function (file_queue_limit) {
610         var movie_element = this.getMovieElement();
611         if (movie_element !== null && typeof(movie_element.SetFileQueueLimit) === "function") {
612                 try {
613                         this.addSetting("file_queue_limit", file_queue_limit);
614                         movie_element.SetFileQueueLimit(this.getSetting("file_queue_limit"));
615                 }
616                 catch (ex) {
617                         this.debug("Could not call SetFileQueueLimit");
618                 }
619         } else {
620                 this.debug("Could not find Flash element in SetFileQueueLimit");
621         }
622 };
623
624 SWFUpload.prototype.setFilePostName = function (file_post_name) {
625         var movie_element = this.getMovieElement();
626         if (movie_element !== null && typeof(movie_element.SetFilePostName) === "function") {
627                 try {
628                         this.addSetting("file_post_name", file_post_name);
629                         movie_element.SetFilePostName(this.getSetting("file_post_name"));
630                 }
631                 catch (ex) {
632                         this.debug("Could not call SetFilePostName");
633                 }
634         } else {
635                 this.debug("Could not find Flash element in SetFilePostName");
636         }
637 };
638
639 SWFUpload.prototype.setDebugEnabled = function (debug_enabled) {
640         var movie_element = this.getMovieElement();
641         if (movie_element !== null && typeof(movie_element.SetDebugEnabled) === "function") {
642                 try {
643                         this.addSetting("debug_enabled", debug_enabled);
644                         movie_element.SetDebugEnabled(this.getSetting("debug_enabled"));
645                 }
646                 catch (ex) {
647                         this.debug("Could not call SetDebugEnabled");
648                 }
649         } else {
650                 this.debug("Could not find Flash element in SetDebugEnabled");
651         }
652 };
653
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 ******************************* */
659
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.
663 */
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.");
669                 return;
670         }
671         
672         var self = this;
673         if (typeof(self.flashReady_handler) === "function") {
674                 this.eventQueue[this.eventQueue.length] = function() { self.flashReady_handler(); };
675                 setTimeout(function () { self.executeNextEvent();}, 0);
676         } else {
677                 this.debug("flashReady_handler event not defined");
678         }
679 };
680
681 /*
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.
686 */
687 SWFUpload.prototype.executeNextEvent = function () {
688         var  f = this.eventQueue.shift();
689         if (typeof(f) === "function") {
690                 f();
691         }
692 }
693
694 /* This is a chance to do something before the browse window opens */
695 SWFUpload.prototype.fileDialogStart = function () {
696         var self = this;
697         if (typeof(self.fileDialogStart_handler) === "function") {
698                 this.eventQueue[this.eventQueue.length] = function() { self.fileDialogStart_handler(); };
699                 setTimeout(function () { self.executeNextEvent();}, 0);
700         } else {
701                 this.debug("fileDialogStart event not defined");
702         }
703 };
704
705
706 /* Called when a file is successfully added to the queue. */
707 SWFUpload.prototype.fileQueued = function (file) {
708         var self = this;
709         if (typeof(self.fileQueued_handler) === "function") {
710                 this.eventQueue[this.eventQueue.length] = function() { self.fileQueued_handler(file); };
711                 setTimeout(function () { self.executeNextEvent();}, 0);
712         } else {
713                 this.debug("fileQueued event not defined");
714         }
715 };
716
717
718 /* Handle errors that occur when an attempt to queue a file fails. */
719 SWFUpload.prototype.fileQueueError = function (file, error_code, message) {
720         var self = this;
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);
724         } else {
725                 this.debug("fileQueueError event not defined");
726         }
727 };
728
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) {
732         var self = this;
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);
736         } else {
737                 this.debug("fileDialogComplete event not defined");
738         }
739 };
740
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).
743         
744         This is a good place to do any file validation you need.
745         */
746 SWFUpload.prototype.uploadStart = function (file) {
747         var self = this;
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);
751         } else {
752                 this.debug("uploadStart event not defined");
753         }
754 };
755
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
759         point of view.
760 */
761 SWFUpload.prototype.returnUploadStart = function (return_value) {
762         var movie_element = this.getMovieElement();
763         if (movie_element !== null && typeof(movie_element.ReturnUploadStart) === "function") {
764                 try {
765                         movie_element.ReturnUploadStart(return_value);
766                 }
767                 catch (ex) {
768                         this.debug("Could not call ReturnUploadStart");
769                 }
770         } else {
771                 this.debug("Could not find Flash element in returnUploadStart");
772         }
773 };
774
775
776
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) {
779         var self = this;
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);
783         } else {
784                 this.debug("uploadProgress event not defined");
785         }
786 };
787
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) {
792         var self = this;
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);
796         } else {
797                 this.debug("uploadError event not defined");
798         }
799 };
800
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) {
806         var self = this;
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);
810         } else {
811                 this.debug("uploadSuccess event not defined");
812         }
813 };
814
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) {
818         var self = this;
819         if (typeof(self.uploadComplete_handler) === "function") {
820                 this.eventQueue[this.eventQueue.length] = function() { self.uploadComplete_handler(file); };
821                 setTimeout(function () { self.executeNextEvent();}, 0);
822         } else {
823                 this.debug("uploadComplete event not defined");
824         }
825 };
826
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) {
830         var self = this;
831         if (typeof(self.debug_handler) === "function") {
832                 this.eventQueue[this.eventQueue.length] = function() { self.debug_handler(message); };
833                 setTimeout(function () { self.executeNextEvent();}, 0);
834         } else {
835                 this.eventQueue[this.eventQueue.length] = function() { self.debugMessage(message); };
836                 setTimeout(function () { self.executeNextEvent();}, 0);
837         }
838 };
839
840
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.
845         
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    ********************************** */
849
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.
853 */
854 SWFUpload.flashReady = function () {
855         try {
856                 this.debug("Flash called back and is ready.");
857
858                 if (typeof(this.swfUploadLoaded_handler) === "function") {
859                         this.swfUploadLoaded_handler();
860                 }
861         } catch (ex) {
862                 this.debug(ex);
863         }
864 };
865
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 () {
869 };
870
871 /* This is a chance to do something before the browse window opens */
872 SWFUpload.fileDialogStart = function () {
873 };
874
875
876 /* Called when a file is successfully added to the queue. */
877 SWFUpload.fileQueued = function (file) {
878 };
879
880
881 /* Handle errors that occur when an attempt to queue a file fails. */
882 SWFUpload.fileQueueError = function (file, error_code, message) {
883         try {
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);
887                         break;
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);
890                         break;
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);
893                         break;
894                 case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
895                         this.debug("Error Code: File extension is not allowed, Message: " + message);
896                         break;
897                 default:
898                         this.debug("Error Code: Unhandled error occured. Errorcode: " + error_code);
899                 }
900         } catch (ex) {
901                 this.debug(ex);
902         }
903 };
904
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) {
908 };
909
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).
912         
913         This is a good place to do any file validation you need.
914         
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.
918 */
919 SWFUpload.uploadStart = function (file) {
920         return true;
921 };
922
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);
926 };
927
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);
932 };
933
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.
936 */
937 SWFUpload.uploadComplete = function (file) {
938         this.debug("Upload Complete: " + file.id);
939 };
940
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);
946         }
947 };
948
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) {
951         try {
952                 switch (errcode) {
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);
955                         break;
956                 case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
957                         this.debug("Error Code: HTTP Error, File name: " + file.name + ", Message: " + msg);
958                         break;
959                 case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
960                         this.debug("Error Code: No backend file, File name: " + file.name + ", Message: " + msg);
961                         break;
962                 case SWFUpload.UPLOAD_ERROR.IO_ERROR:
963                         this.debug("Error Code: IO Error, File name: " + file.name + ", Message: " + msg);
964                         break;
965                 case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
966                         this.debug("Error Code: Security Error, File name: " + file.name + ", Message: " + msg);
967                         break;
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);
970                         break;
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);
973                         break;
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);
976                         break;
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);
979                         break;
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);
982                         break;
983                 default:
984                         this.debug("Error Code: Unhandled error occured. Errorcode: " + errcode);
985                 }
986         } catch (ex) {
987                 this.debug(ex);
988         }
989 };
990
991
992
993 /* **********************************
994         Debug Console
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.
998
999         The console is automatically scrolled as messages appear.
1000         
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;
1006
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]);
1012                 }
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);
1017         } else {
1018                 SWFUpload.Console.writeLine(message);
1019         }
1020 };
1021
1022 SWFUpload.Console = {};
1023 SWFUpload.Console.writeLine = function (message) {
1024         var console, documentForm;
1025
1026         try {
1027                 console = document.getElementById("SWFUpload_Console");
1028
1029                 if (!console) {
1030                         documentForm = document.createElement("form");
1031                         document.getElementsByTagName("body")[0].appendChild(documentForm);
1032
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);
1043                 }
1044
1045                 console.value += message + "\n";
1046
1047                 console.scrollTop = console.scrollHeight - console.clientHeight;
1048         } catch (ex) {
1049                 alert("Exception: " + ex.name + " Message: " + ex.message);
1050         }
1051 };