ultimix

- Main Page
- Data Structures
- Files
- Examples

- File List
- Globals

swfupload.js
Go to the documentation of this file.
1
15 /* ******************* */
16 /* Constructor & Init */
17 /* ******************* */
18 var SWFUpload;
19
20 if (SWFUpload == undefined) {
21 SWFUpload = function (settings) {
22 this.initSWFUpload(settings);
23 };
24 }
25
26 SWFUpload.prototype.initSWFUpload = function (settings) {
27 try {
28 this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
29 this.settings = settings;
30 this.eventQueue = [];
31 this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
32 this.movieElement = null;
33
34
35 // Setup global control tracking
36 SWFUpload.instances[this.movieName] = this;
37
38 // Load the settings. Load the Flash movie.
39 this.initSettings();
40 this.loadFlash();
41 this.displayDebugInfo();
42 } catch (ex) {
43 delete SWFUpload.instances[this.movieName];
44 throw ex;
45 }
46 };
47
48 /* *************** */
49 /* Static Members */
50 /* *************** */
51 SWFUpload.instances = {};
52 SWFUpload.movieCount = 0;
53 SWFUpload.version = "2.2.0 2009-03-25";
54 SWFUpload.QUEUE_ERROR = {
55 QUEUE_LIMIT_EXCEEDED : -100,
56 FILE_EXCEEDS_SIZE_LIMIT : -110,
57 ZERO_BYTE_FILE : -120,
58 INVALID_FILETYPE : -130
59 };
60 SWFUpload.UPLOAD_ERROR = {
61 HTTP_ERROR : -200,
62 MISSING_UPLOAD_URL : -210,
63 IO_ERROR : -220,
64 SECURITY_ERROR : -230,
65 UPLOAD_LIMIT_EXCEEDED : -240,
66 UPLOAD_FAILED : -250,
67 SPECIFIED_FILE_ID_NOT_FOUND : -260,
68 FILE_VALIDATION_FAILED : -270,
69 FILE_CANCELLED : -280,
70 UPLOAD_STOPPED : -290
71 };
72 SWFUpload.FILE_STATUS = {
73 QUEUED : -1,
74 IN_PROGRESS : -2,
75 ERROR : -3,
76 COMPLETE : -4,
77 CANCELLED : -5
78 };
79 SWFUpload.BUTTON_ACTION = {
80 SELECT_FILE : -100,
81 SELECT_FILES : -110,
82 START_UPLOAD : -120
83 };
84 SWFUpload.CURSOR = {
85 ARROW : -1,
86 HAND : -2
87 };
88 SWFUpload.WINDOW_MODE = {
89 WINDOW : "window",
90 TRANSPARENT : "transparent",
91 OPAQUE : "opaque"
92 };
93
94 // Private: takes a URL, determines if it is relative and converts to an absolute URL
95 // using the current site. Only processes the URL if it can, otherwise returns the URL untouched
96 SWFUpload.completeURL = function(url) {
97 if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) {
98 return url;
99 }
100
101 var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "");
102
103 var indexSlash = window.location.pathname.lastIndexOf("/");
104 if (indexSlash <= 0) {
105 path = "/";
106 } else {
107 path = window.location.pathname.substr(0, indexSlash) + "/";
108 }
109
110 return /*currentURL +*/ path + url;
111
112 };
113
114
115 /* ******************** */
116 /* Instance Members */
117 /* ******************** */
118
119 // Private: initSettings ensures that all the
120 // settings are set, getting a default value if one was not assigned.
121 SWFUpload.prototype.initSettings = function () {
122 this.ensureDefault = function (settingName, defaultValue) {
123 this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
124 };
125
126 // Upload backend settings
127 this.ensureDefault("upload_url", "");
128 this.ensureDefault("preserve_relative_urls", false);
129 this.ensureDefault("file_post_name", "Filedata");
130 this.ensureDefault("post_params", {});
131 this.ensureDefault("use_query_string", false);
132 this.ensureDefault("requeue_on_error", false);
133 this.ensureDefault("http_success", []);
134 this.ensureDefault("assume_success_timeout", 0);
135
136 // File Settings
137 this.ensureDefault("file_types", "*.*");
138 this.ensureDefault("file_types_description", "All Files");
139 this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited"
140 this.ensureDefault("file_upload_limit", 0);
141 this.ensureDefault("file_queue_limit", 0);
142
143 // Flash Settings
144 this.ensureDefault("flash_url", "swfupload.swf");
145 this.ensureDefault("prevent_swf_caching", true);
146
147 // Button Settings
148 this.ensureDefault("button_image_url", "");
149 this.ensureDefault("button_width", 1);
150 this.ensureDefault("button_height", 1);
151 this.ensureDefault("button_text", "");
152 this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
153 this.ensureDefault("button_text_top_padding", 0);
154 this.ensureDefault("button_text_left_padding", 0);
155 this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
156 this.ensureDefault("button_disabled", false);
157 this.ensureDefault("button_placeholder_id", "");
158 this.ensureDefault("button_placeholder", null);
159 this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
160 this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);
161
162 // Debug Settings
163 this.ensureDefault("debug", false);
164 this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API
165
166 // Event Handlers
167 this.settings.return_upload_start_handler = this.returnUploadStart;
168 this.ensureDefault("swfupload_loaded_handler", null);
169 this.ensureDefault("file_dialog_start_handler", null);
170 this.ensureDefault("file_queued_handler", null);
171 this.ensureDefault("file_queue_error_handler", null);
172 this.ensureDefault("file_dialog_complete_handler", null);
173
174 this.ensureDefault("upload_start_handler", null);
175 this.ensureDefault("upload_progress_handler", null);
176 this.ensureDefault("upload_error_handler", null);
177 this.ensureDefault("upload_success_handler", null);
178 this.ensureDefault("upload_complete_handler", null);
179
180 this.ensureDefault("debug_handler", this.debugMessage);
181
182 this.ensureDefault("custom_settings", {});
183
184 // Other settings
185 this.customSettings = this.settings.custom_settings;
186
187 // Update the flash url if needed
188 if (!!this.settings.prevent_swf_caching) {
189 this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime();
190 }
191
192 if (!this.settings.preserve_relative_urls) {
193 //this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url); // Don't need to do this one since flash doesn't look at it
194 this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url);
195 this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url);
196 }
197
198 delete this.ensureDefault;
199 };
200
201 // Private: loadFlash replaces the button_placeholder element with the flash movie.
202 SWFUpload.prototype.loadFlash = function () {
203 var targetElement, tempParent;
204
205 // Make sure an element with the ID we are going to use doesn't already exist
206 if (document.getElementById(this.movieName) !== null) {
207 throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
208 }
209
210 // Get the element where we will be placing the flash movie
211 targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder;
212
213 if (targetElement == undefined) {
214 throw "Could not find the placeholder element: " + this.settings.button_placeholder_id;
215 }
216
217 // Append the container and load the flash
218 tempParent = document.createElement("div");
219 tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
220 targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);
221
222 // Fix IE Flash/Form bug
223 if (window[this.movieName] == undefined) {
224 window[this.movieName] = this.getMovieElement();
225 }
226
227 };
228
229 // Private: getFlashHTML generates the object tag needed to embed the flash in to the document
230 SWFUpload.prototype.getFlashHTML = function () {
231 // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
232 return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
233 '<param name="wmode" value="', this.settings.button_window_mode, '" />',
234 '<param name="movie" value="', this.settings.flash_url, '" />',
235 '<param name="quality" value="high" />',
236 '<param name="menu" value="false" />',
237 '<param name="allowScriptAccess" value="always" />',
238 '<param name="flashvars" value="' + this.getFlashVars() + '" />',
239 '</object>'].join("");
240 };
241
242 // Private: getFlashVars builds the parameter string that will be passed
243 // to flash in the flashvars param.
244 SWFUpload.prototype.getFlashVars = function () {
245 // Build a string from the post param object
246 var paramString = this.buildParamString();
247 var httpSuccessString = this.settings.http_success.join(",");
248
249 // Build the parameter string
250 return ["movieName=", encodeURIComponent(this.movieName),
251 "&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
252 "&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
253 "&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
254 "&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
255 "&amp;assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout),
256 "&amp;params=", encodeURIComponent(paramString),
257 "&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
258 "&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
259 "&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
260 "&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
261 "&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
262 "&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
263 "&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
264 "&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
265 "&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
266 "&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
267 "&amp;buttonText=", encodeURIComponent(this.settings.button_text),
268 "&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
269 "&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
270 "&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
271 "&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
272 "&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
273 "&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
274 ].join("");
275 };
276
277 // Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload
278 // The element is cached after the first lookup
279 SWFUpload.prototype.getMovieElement = function () {
280 if (this.movieElement == undefined) {
281 this.movieElement = document.getElementById(this.movieName);
282 }
283
284 if (this.movieElement === null) {
285 throw "Could not find Flash element";
286 }
287
288 return this.movieElement;
289 };
290
291 // Private: buildParamString takes the name/value pairs in the post_params setting object
292 // and joins them up in to a string formatted "name=value&amp;name=value"
293 SWFUpload.prototype.buildParamString = function () {
294 var postParams = this.settings.post_params;
295 var paramStringPairs = [];
296
297 if (typeof(postParams) === "object") {
298 for (var name in postParams) {
299 if (postParams.hasOwnProperty(name)) {
300 paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
301 }
302 }
303 }
304
305 return paramStringPairs.join("&amp;");
306 };
307
308 // Public: Used to remove a SWFUpload instance from the page. This method strives to remove
309 // all references to the SWF, and other objects so memory is properly freed.
310 // Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
311 // Credits: Major improvements provided by steffen
312 SWFUpload.prototype.destroy = function () {
313 try {
314 // Make sure Flash is done before we try to remove it
315 this.cancelUpload(null, false);
316
317
318 // Remove the SWFUpload DOM nodes
319 var movieElement = null;
320 movieElement = this.getMovieElement();
321
322 if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
323 // Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround)
324 for (var i in movieElement) {
325 try {
326 if (typeof(movieElement[i]) === "function") {
327 movieElement[i] = null;
328 }
329 } catch (ex1) {}
330 }
331
332 // Remove the Movie Element from the page
333 try {
334 movieElement.parentNode.removeChild(movieElement);
335 } catch (ex) {}
336 }
337
338 // Remove IE form fix reference
339 window[this.movieName] = null;
340
341 // Destroy other references
342 SWFUpload.instances[this.movieName] = null;
343 delete SWFUpload.instances[this.movieName];
344
345 this.movieElement = null;
346 this.settings = null;
347 this.customSettings = null;
348 this.eventQueue = null;
349 this.movieName = null;
350
351
352 return true;
353 } catch (ex2) {
354 return false;
355 }
356 };
357
358
359 // Public: displayDebugInfo prints out settings and configuration
360 // information about this SWFUpload instance.
361 // This function (and any references to it) can be deleted when placing
362 // SWFUpload in production.
363 SWFUpload.prototype.displayDebugInfo = function () {
364 this.debug(
365 [
366 "---SWFUpload Instance Info---\n",
367 "Version: ", SWFUpload.version, "\n",
368 "Movie Name: ", this.movieName, "\n",
369 "Settings:\n",
370 "\t", "upload_url: ", this.settings.upload_url, "\n",
371 "\t", "flash_url: ", this.settings.flash_url, "\n",
372 "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n",
373 "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n",
374 "\t", "http_success: ", this.settings.http_success.join(", "), "\n",
375 "\t", "assume_success_timeout: ", this.settings.assume_success_timeout, "\n",
376 "\t", "file_post_name: ", this.settings.file_post_name, "\n",
377 "\t", "post_params: ", this.settings.post_params.toString(), "\n",
378 "\t", "file_types: ", this.settings.file_types, "\n",
379 "\t", "file_types_description: ", this.settings.file_types_description, "\n",
380 "\t", "file_size_limit: ", this.settings.file_size_limit, "\n",
381 "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n",
382 "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n",
383 "\t", "debug: ", this.settings.debug.toString(), "\n",
384
385 "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n",
386
387 "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n",
388 "\t", "button_placeholder: ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n",
389 "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n",
390 "\t", "button_width: ", this.settings.button_width.toString(), "\n",
391 "\t", "button_height: ", this.settings.button_height.toString(), "\n",
392 "\t", "button_text: ", this.settings.button_text.toString(), "\n",
393 "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n",
394 "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n",
395 "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
396 "\t", "button_action: ", this.settings.button_action.toString(), "\n",
397 "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n",
398
399 "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n",
400 "Event Handlers:\n",
401 "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
402 "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
403 "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
404 "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
405 "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
406 "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
407 "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
408 "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
409 "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
410 "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n"
411 ].join("")
412 );
413 };
414
415 /* Note: addSetting and getSetting are no longer used by SWFUpload but are included
416 the maintain v2 API compatibility
417 */
418 // Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
419 SWFUpload.prototype.addSetting = function (name, value, default_value) {
420 if (value == undefined) {
421 return (this.settings[name] = default_value);
422 } else {
423 return (this.settings[name] = value);
424 }
425 };
426
427 // Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
428 SWFUpload.prototype.getSetting = function (name) {
429 if (this.settings[name] != undefined) {
430 return this.settings[name];
431 }
432
433 return "";
434 };
435
436
437
438 // Private: callFlash handles function calls made to the Flash element.
439 // Calls are made with a setTimeout for some functions to work around
440 // bugs in the ExternalInterface library.
441 SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
442 argumentArray = argumentArray || [];
443
444 var movieElement = this.getMovieElement();
445 var returnValue, returnString;
446
447 // Flash's method if calling ExternalInterface methods (code adapted from MooTools).
448 try {
449 returnString = movieElement.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');
450 returnValue = eval(returnString);
451 } catch (ex) {
452 throw "Call to " + functionName + " failed";
453 }
454
455 // Unescape file post param values
456 if (returnValue != undefined && typeof returnValue.post === "object") {
457 returnValue = this.unescapeFilePostParams(returnValue);
458 }
459
460 return returnValue;
461 };
462
463 /* *****************************
464 -- Flash control methods --
465 Your UI should use these
466 to operate SWFUpload
467 ***************************** */
468
469 // WARNING: this function does not work in Flash Player 10
470 // Public: selectFile causes a File Selection Dialog window to appear. This
471 // dialog only allows 1 file to be selected.
472 SWFUpload.prototype.selectFile = function () {
473 this.callFlash("SelectFile");
474 };
475
476 // WARNING: this function does not work in Flash Player 10
477 // Public: selectFiles causes a File Selection Dialog window to appear/ This
478 // dialog allows the user to select any number of files
479 // Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
480 // If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around
481 // for this bug.
482 SWFUpload.prototype.selectFiles = function () {
483 this.callFlash("SelectFiles");
484 };
485
486
487 // Public: startUpload starts uploading the first file in the queue unless
488 // the optional parameter 'fileID' specifies the ID
489 SWFUpload.prototype.startUpload = function (fileID) {
490 this.callFlash("StartUpload", [fileID]);
491 };
492
493 // Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index.
494 // If you do not specify a fileID the current uploading file or first file in the queue is cancelled.
495 // If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.
496 SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {
497 if (triggerErrorEvent !== false) {
498 triggerErrorEvent = true;
499 }
500 this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
501 };
502
503 // Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
504 // If nothing is currently uploading then nothing happens.
505 SWFUpload.prototype.stopUpload = function () {
506 this.callFlash("StopUpload");
507 };
508
509 /* ************************
510 * Settings methods
511 * These methods change the SWFUpload settings.
512 * SWFUpload settings should not be changed directly on the settings object
513 * since many of the settings need to be passed to Flash in order to take
514 * effect.
515 * *********************** */
516
517 // Public: getStats gets the file statistics object.
518 SWFUpload.prototype.getStats = function () {
519 return this.callFlash("GetStats");
520 };
521
522 // Public: setStats changes the SWFUpload statistics. You shouldn't need to
523 // change the statistics but you can. Changing the statistics does not
524 // affect SWFUpload accept for the successful_uploads count which is used
525 // by the upload_limit setting to determine how many files the user may upload.
526 SWFUpload.prototype.setStats = function (statsObject) {
527 this.callFlash("SetStats", [statsObject]);
528 };
529
530 // Public: getFile retrieves a File object by ID or Index. If the file is
531 // not found then 'null' is returned.
532 SWFUpload.prototype.getFile = function (fileID) {
533 if (typeof(fileID) === "number") {
534 return this.callFlash("GetFileByIndex", [fileID]);
535 } else {
536 return this.callFlash("GetFile", [fileID]);
537 }
538 };
539
540 // Public: addFileParam sets a name/value pair that will be posted with the
541 // file specified by the Files ID. If the name already exists then the
542 // exiting value will be overwritten.
543 SWFUpload.prototype.addFileParam = function (fileID, name, value) {
544 return this.callFlash("AddFileParam", [fileID, name, value]);
545 };
546
547 // Public: removeFileParam removes a previously set (by addFileParam) name/value
548 // pair from the specified file.
549 SWFUpload.prototype.removeFileParam = function (fileID, name) {
550 this.callFlash("RemoveFileParam", [fileID, name]);
551 };
552
553 // Public: setUploadUrl changes the upload_url setting.
554 SWFUpload.prototype.setUploadURL = function (url) {
555 this.settings.upload_url = url.toString();
556 this.callFlash("SetUploadURL", [url]);
557 };
558
559 // Public: setPostParams changes the post_params setting
560 SWFUpload.prototype.setPostParams = function (paramsObject) {
561 this.settings.post_params = paramsObject;
562 this.callFlash("SetPostParams", [paramsObject]);
563 };
564
565 // Public: addPostParam adds post name/value pair. Each name can have only one value.
566 SWFUpload.prototype.addPostParam = function (name, value) {
567 this.settings.post_params[name] = value;
568 this.callFlash("SetPostParams", [this.settings.post_params]);
569 };
570
571 // Public: removePostParam deletes post name/value pair.
572 SWFUpload.prototype.removePostParam = function (name) {
573 delete this.settings.post_params[name];
574 this.callFlash("SetPostParams", [this.settings.post_params]);
575 };
576
577 // Public: setFileTypes changes the file_types setting and the file_types_description setting
578 SWFUpload.prototype.setFileTypes = function (types, description) {
579 this.settings.file_types = types;
580 this.settings.file_types_description = description;
581 this.callFlash("SetFileTypes", [types, description]);
582 };
583
584 // Public: setFileSizeLimit changes the file_size_limit setting
585 SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {
586 this.settings.file_size_limit = fileSizeLimit;
587 this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
588 };
589
590 // Public: setFileUploadLimit changes the file_upload_limit setting
591 SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {
592 this.settings.file_upload_limit = fileUploadLimit;
593 this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
594 };
595
596 // Public: setFileQueueLimit changes the file_queue_limit setting
597 SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {
598 this.settings.file_queue_limit = fileQueueLimit;
599 this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
600 };
601
602 // Public: setFilePostName changes the file_post_name setting
603 SWFUpload.prototype.setFilePostName = function (filePostName) {
604 this.settings.file_post_name = filePostName;
605 this.callFlash("SetFilePostName", [filePostName]);
606 };
607
608 // Public: setUseQueryString changes the use_query_string setting
609 SWFUpload.prototype.setUseQueryString = function (useQueryString) {
610 this.settings.use_query_string = useQueryString;
611 this.callFlash("SetUseQueryString", [useQueryString]);
612 };
613
614 // Public: setRequeueOnError changes the requeue_on_error setting
615 SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {
616 this.settings.requeue_on_error = requeueOnError;
617 this.callFlash("SetRequeueOnError", [requeueOnError]);
618 };
619
620 // Public: setHTTPSuccess changes the http_success setting
621 SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
622 if (typeof http_status_codes === "string") {
623 http_status_codes = http_status_codes.replace(" ", "").split(",");
624 }
625
626 this.settings.http_success = http_status_codes;
627 this.callFlash("SetHTTPSuccess", [http_status_codes]);
628 };
629
630 // Public: setHTTPSuccess changes the http_success setting
631 SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) {
632 this.settings.assume_success_timeout = timeout_seconds;
633 this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]);
634 };
635
636 // Public: setDebugEnabled changes the debug_enabled setting
637 SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
638 this.settings.debug_enabled = debugEnabled;
639 this.callFlash("SetDebugEnabled", [debugEnabled]);
640 };
641
642 // Public: setButtonImageURL loads a button image sprite
643 SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {
644 if (buttonImageURL == undefined) {
645 buttonImageURL = "";
646 }
647
648 this.settings.button_image_url = buttonImageURL;
649 this.callFlash("SetButtonImageURL", [buttonImageURL]);
650 };
651
652 // Public: setButtonDimensions resizes the Flash Movie and button
653 SWFUpload.prototype.setButtonDimensions = function (width, height) {
654 this.settings.button_width = width;
655 this.settings.button_height = height;
656
657 var movie = this.getMovieElement();
658 if (movie != undefined) {
659 movie.style.width = width + "px";
660 movie.style.height = height + "px";
661 }
662
663 this.callFlash("SetButtonDimensions", [width, height]);
664 };
665 // Public: setButtonText Changes the text overlaid on the button
666 SWFUpload.prototype.setButtonText = function (html) {
667 this.settings.button_text = html;
668 this.callFlash("SetButtonText", [html]);
669 };
670 // Public: setButtonTextPadding changes the top and left padding of the text overlay
671 SWFUpload.prototype.setButtonTextPadding = function (left, top) {
672 this.settings.button_text_top_padding = top;
673 this.settings.button_text_left_padding = left;
674 this.callFlash("SetButtonTextPadding", [left, top]);
675 };
676
677 // Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
678 SWFUpload.prototype.setButtonTextStyle = function (css) {
679 this.settings.button_text_style = css;
680 this.callFlash("SetButtonTextStyle", [css]);
681 };
682 // Public: setButtonDisabled disables/enables the button
683 SWFUpload.prototype.setButtonDisabled = function (isDisabled) {
684 this.settings.button_disabled = isDisabled;
685 this.callFlash("SetButtonDisabled", [isDisabled]);
686 };
687 // Public: setButtonAction sets the action that occurs when the button is clicked
688 SWFUpload.prototype.setButtonAction = function (buttonAction) {
689 this.settings.button_action = buttonAction;
690 this.callFlash("SetButtonAction", [buttonAction]);
691 };
692
693 // Public: setButtonCursor changes the mouse cursor displayed when hovering over the button
694 SWFUpload.prototype.setButtonCursor = function (cursor) {
695 this.settings.button_cursor = cursor;
696 this.callFlash("SetButtonCursor", [cursor]);
697 };
698
699 /* *******************************
700 Flash Event Interfaces
701 These functions are used by Flash to trigger the various
702 events.
703
704 All these functions a Private.
705
706 Because the ExternalInterface library is buggy the event calls
707 are added to a queue and the queue then executed by a setTimeout.
708 This ensures that events are executed in a determinate order and that
709 the ExternalInterface bugs are avoided.
710 ******************************* */
711
712 SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {
713 // Warning: Don't call this.debug inside here or you'll create an infinite loop
714
715 if (argumentArray == undefined) {
716 argumentArray = [];
717 } else if (!(argumentArray instanceof Array)) {
718 argumentArray = [argumentArray];
719 }
720
721 var self = this;
722 if (typeof this.settings[handlerName] === "function") {
723 // Queue the event
724 this.eventQueue.push(function () {
725 this.settings[handlerName].apply(this, argumentArray);
726 });
727
728 // Execute the next queued event
729 setTimeout(function () {
730 self.executeNextEvent();
731 }, 0);
732
733 } else if (this.settings[handlerName] !== null) {
734 throw "Event handler " + handlerName + " is unknown or is not a function";
735 }
736 };
737
738 // Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout
739 // we must queue them in order to garentee that they are executed in order.
740 SWFUpload.prototype.executeNextEvent = function () {
741 // Warning: Don't call this.debug inside here or you'll create an infinite loop
742
743 var f = this.eventQueue ? this.eventQueue.shift() : null;
744 if (typeof(f) === "function") {
745 f.apply(this);
746 }
747 };
748
749 // Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
750 // properties that contain characters that are not valid for JavaScript identifiers. To work around this
751 // the Flash Component escapes the parameter names and we must unescape again before passing them along.
752 SWFUpload.prototype.unescapeFilePostParams = function (file) {
753 var reg = /[$]([0-9a-f]{4})/i;
754 var unescapedPost = {};
755 var uk;
756
757 if (file != undefined) {
758 for (var k in file.post) {
759 if (file.post.hasOwnProperty(k)) {
760 uk = k;
761 var match;
762 while ((match = reg.exec(uk)) !== null) {
763 uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
764 }
765 unescapedPost[uk] = file.post[k];
766 }
767 }
768
769 file.post = unescapedPost;
770 }
771
772 return file;
773 };
774
775 // Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working)
776 SWFUpload.prototype.testExternalInterface = function () {
777 try {
778 return this.callFlash("TestExternalInterface");
779 } catch (ex) {
780 return false;
781 }
782 };
783
784 // Private: This event is called by Flash when it has finished loading. Don't modify this.
785 // Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded.
786 SWFUpload.prototype.flashReady = function () {
787 // Check that the movie element is loaded correctly with its ExternalInterface methods defined
788 var movieElement = this.getMovieElement();
789
790 if (!movieElement) {
791 this.debug("Flash called back ready but the flash movie can't be found.");
792 return;
793 }
794
795 this.cleanUp(movieElement);
796
797 this.queueEvent("swfupload_loaded_handler");
798 };
799
800 // Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE.
801 // This function is called by Flash each time the ExternalInterface functions are created.
802 SWFUpload.prototype.cleanUp = function (movieElement) {
803 // Pro-actively unhook all the Flash functions
804 try {
805 if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
806 this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
807 for (var key in movieElement) {
808 try {
809 if (typeof(movieElement[key]) === "function") {
810 movieElement[key] = null;
811 }
812 } catch (ex) {
813 }
814 }
815 }
816 } catch (ex1) {
817
818 }
819
820 // Fix Flashes own cleanup code so if the SWFMovie was removed from the page
821 // it doesn't display errors.
822 window["__flash__removeCallback"] = function (instance, name) {
823 try {
824 if (instance) {
825 instance[name] = null;
826 }
827 } catch (flashEx) {
828
829 }
830 };
831
832 };
833
834
835 /* This is a chance to do something before the browse window opens */
836 SWFUpload.prototype.fileDialogStart = function () {
837 this.queueEvent("file_dialog_start_handler");
838 };
839
840
841 /* Called when a file is successfully added to the queue. */
842 SWFUpload.prototype.fileQueued = function (file) {
843 file = this.unescapeFilePostParams(file);
844 this.queueEvent("file_queued_handler", file);
845 };
846
847
848 /* Handle errors that occur when an attempt to queue a file fails. */
849 SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
850 file = this.unescapeFilePostParams(file);
851 this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
852 };
853
854 /* Called after the file dialog has closed and the selected files have been queued.
855 You could call startUpload here if you want the queued files to begin uploading immediately. */
856 SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) {
857 this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]);
858 };
859
860 SWFUpload.prototype.uploadStart = function (file) {
861 file = this.unescapeFilePostParams(file);
862 this.queueEvent("return_upload_start_handler", file);
863 };
864
865 SWFUpload.prototype.returnUploadStart = function (file) {
866 var returnValue;
867 if (typeof this.settings.upload_start_handler === "function") {
868 file = this.unescapeFilePostParams(file);
869 returnValue = this.settings.upload_start_handler.call(this, file);
870 } else if (this.settings.upload_start_handler != undefined) {
871 throw "upload_start_handler must be a function";
872 }
873
874 // Convert undefined to true so if nothing is returned from the upload_start_handler it is
875 // interpretted as 'true'.
876 if (returnValue === undefined) {
877 returnValue = true;
878 }
879
880 returnValue = !!returnValue;
881
882 this.callFlash("ReturnUploadStart", [returnValue]);
883 };
884
885
886
887 SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
888 file = this.unescapeFilePostParams(file);
889 this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
890 };
891
892 SWFUpload.prototype.uploadError = function (file, errorCode, message) {
893 file = this.unescapeFilePostParams(file);
894 this.queueEvent("upload_error_handler", [file, errorCode, message]);
895 };
896
897 SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) {
898 file = this.unescapeFilePostParams(file);
899 this.queueEvent("upload_success_handler", [file, serverData, responseReceived]);
900 };
901
902 SWFUpload.prototype.uploadComplete = function (file) {
903 file = this.unescapeFilePostParams(file);
904 this.queueEvent("upload_complete_handler", file);
905 };
906
907 /* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
908 internal debug console. You can override this event and have messages written where you want. */
909 SWFUpload.prototype.debug = function (message) {
910 this.queueEvent("debug_handler", message);
911 };
912
913
914 /* **********************************
915 Debug Console
916 The debug console is a self contained, in page location
917 for debug message to be sent. The Debug Console adds
918 itself to the body if necessary.
919
920 The console is automatically scrolled as messages appear.
921
922 If you are using your own debug handler or when you deploy to production and
923 have debug disabled you can remove these functions to reduce the file size
924 and complexity.
925 ********************************** */
926
927 // Private: debugMessage is the default debug_handler. If you want to print debug messages
928 // call the debug() function. When overriding the function your own function should
929 // check to see if the debug setting is true before outputting debug information.
930 SWFUpload.prototype.debugMessage = function (message) {
931 if (this.settings.debug) {
932 var exceptionMessage, exceptionValues = [];
933
934 // Check for an exception object and print it nicely
935 if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
936 for (var key in message) {
937 if (message.hasOwnProperty(key)) {
938 exceptionValues.push(key + ": " + message[key]);
939 }
940 }
941 exceptionMessage = exceptionValues.join("\n") || "";
942 exceptionValues = exceptionMessage.split("\n");
943 exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
944 SWFUpload.Console.writeLine(exceptionMessage);
945 } else {
946 SWFUpload.Console.writeLine(message);
947 }
948 }
949 };
950
951 SWFUpload.Console = {};
952 SWFUpload.Console.writeLine = function (message) {
953 var console, documentForm;
954
955 try {
956 console = document.getElementById("SWFUpload_Console");
957
958 if (!console) {
959 documentForm = document.createElement("form");
960 document.getElementsByTagName("body")[0].appendChild(documentForm);
961
962 console = document.createElement("textarea");
963 console.id = "SWFUpload_Console";
964 console.style.fontFamily = "monospace";
965 console.setAttribute("wrap", "off");
966 console.wrap = "off";
967 console.style.overflow = "auto";
968 console.style.width = "700px";
969 console.style.height = "350px";
970 console.style.margin = "5px";
971 documentForm.appendChild(console);
972 }
973
974 console.value += message + "\n";
975
976 console.scrollTop = console.scrollHeight - console.clientHeight;
977 } catch (ex) {
978 alert("Exception: " + ex.name + " Message: " + ex.message);
979 }
980 };