MINOR Removed cms/thirdparty/swfupload, moved to sapphire/thirdparty

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92852 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2009-11-21 03:21:16 +00:00
parent 2c7e4c1dd4
commit 394e0c0b38
32 changed files with 3 additions and 4347 deletions

View File

@ -74,7 +74,7 @@ class AssetAdmin extends LeftAndMain {
Requirements::javascript(CMS_DIR . "/javascript/AssetAdmin.js");
Requirements::javascript(CMS_DIR . "/javascript/CMSMain_upload.js");
Requirements::javascript(CMS_DIR . "/javascript/Upload.js");
Requirements::javascript(CMS_DIR . "/thirdparty/swfupload/swfupload.js");
Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/swfupload/swfupload/swfupload.js");
Requirements::css(CMS_DIR . "/css/AssetAdmin.css");

View File

@ -276,7 +276,7 @@ class LeftAndMain extends Controller {
'cms/javascript/LeftAndMain.js',
'sapphire/javascript/tree/tree.js',
'cms/javascript/TinyMCEImageEnhancement.js',
'cms/thirdparty/swfupload/swfupload.js',
'sapphire/thirdparty/swfupload/swfupload/swfupload.js',
'cms/javascript/Upload.js',
'cms/javascript/TinyMCEImageEnhancement.js',
'sapphire/javascript/TreeSelectorField.js',

View File

@ -74,7 +74,7 @@ Upload.prototype = {
button_window_mode : "transparent",
button_width : this.buttonWidth,
button_height : this.buttonHeight,
flash_url : 'sapphire/thirdparty/swfupload/swfupload.swf', // Relative to this file
flash_url : 'sapphire/thirdparty/swfupload/swfupload/swfupload.swf', // Relative to this file
swfupload_loaded_handler: this.buildUI.bind(this),
debug: false,
preserve_relative_urls: true

View File

@ -1,8 +0,0 @@
---
format: 1
handler:
piston:remote-revision: 854
piston:uuid: 46bd1c57-1c41-0410-9cc9-652e43039c97
lock: false
repository_url: http://swfupload.googlecode.com/svn/swfupload/tags/swfupload_v2.0.1/FlashDevelop
repository_class: Piston::Svn::Repository

View File

@ -1,193 +0,0 @@
* SWFUpload v2.0 by Jacob Roberts, Nov 2007, www.swfupload.org, linebyline.blogspot.com
* --------- Version 2.0.1 -----------
* = Fixed a bug where zero-byte files would stop file the queuing process.
* = Finished updating Features Demo
* + Added GetFileByIndex(i) that gets a JavaScript File Object. The index never changes. Finished files continue to be available.
* The JavaScript GetFile function will accept a file_id or an index.
* + Added CheckFileSize constants to replace the magic numbers
* + Added some code in an attempt to fix "Script is running slowly" error messages
* = Better cleanup of FileReference objects
* --------- Version 2.0 -----------
* + Re-created SWFUpload in Actionscript v2 for Flash 8 compatibility. Flash 8 loses POST and Server Data features. The two versions are otherwise fully compatible.
* Flash 8 uses URL to pass post_params/file_params.
* = Changed uploadStart event so it's part of the setTimeout/eventQueue workaround. This allows Flash functions to be called from uploadStart.
* = Renamed uploadComplete to uploadSuccess and fileComplete to uploadComplete. All started uploads call uploadComplete (even if cancelled or stopped).
* = Changed startUpload validation failure behavior. Rather than cancelling the upload the file is now requeued. Devs can cancel
* or do whatever the need to in uploadError to handle the problem.
* = Fixed fileQueueLimit/fileUploadLimit logic so it works correctly.
* = Moved the upload request building to a later point so that the post params and file params can be updated in uploadStart.
* - Removed the last of the UI stuff (ui_container, degraded_container).
* + Started development on Plug-ins. Graceful Degradation, v1.0.2, Cookies, Queue Handling
* = Fixed missing file_status field in FileItem.
* + Added modificationDate to FileItem (file object)
* + Added setStats function that lets you change the file upload count, etc. This will give more power over the queue limits. Not well tested.
* = Renamed compeleted_uploads to successful_uploads in getStats object
* + Added in_progress to getStats object
* --------- Revision 7.0 beta 3 -----------
* + Added an "event queue". Events are added to an array and executeEvent is called on a setTimeout. This prevents out of order issues that occur
* in the Safari browser.
* + Added a check for the UPLOAD_COMPLETE_DATA event constant which only became available in Flash Player 9.0.28. This
* fixes the Flash Version detection (Flash Object Detection) which was accepting Flash Player 9 versions before 9.0.28.
* - Removed old code block that was missed when moving from a Flash Timer to the JavaScript timeout (caused certain cancel events to be called twice)
* = Change ShowUI to the swfUploadLoaded event which will hopefully make it more clear that this is an overrideable event
* = Changed flashReady to behave like the other events (uses setTimeout and the Event Queue).
* --------- Revision 7.0 beta 2 -----------
* = Changed ERROR_CODE_FILE_NOT_FOUND to ERROR_CODE_FILE_ID_NOT_FOUND
* + Grouped the error code constants in objects for queue errors and upload errors.
* + Added an UPLOAD_STOPPED error code.
* = Changed Event calling method (using Timer) in Flash. Timer is no longer called
* instead setTimeout is called in JavaScript. This includes a change to the
* JavaSCript design so the Event methods are not directly overridden but stored
* internally and called if defined (with a setTimeout). This is an effort
* be more compatible with the current Flash Player on Linux
* = Changed the parameter order for the fileQueueError and uploadError events so the fileObj is first, like other events.
* + Added an empty JavaScript object (customSettings) where users can store settings associated with the instance.
* + Worked around an escaping bug in the ExternalInterface library by escaping all backslashes in out-going strings.
* = Updated all the demos.
* --------- Revision 7.0 beta 1 -----------
* = Redesigned the Event Chain
* - Removed much of the queue concepts
* - Removed the fileValidation events. This can be done in the new uploadStart event
* - Removed beginUploadOnQueue feature. This can be done in the new dialogComplete event.
* - Removed use_server_data. This is now always on.
* + Added functions for retrieving queue stats (number of files uploaded, queued, errors, etc)
* + Added a file status property to the FileObject. This indicates, uploaded, error, waiting.
* + Added a single file browser (user cannot select multiple files)
* + Fixed bug (hopefully) caused if Flash call to JavaScript and in the callback JavaSCript calls to Flash
* This only place this does not apply is to uploadStart. If you call in to Flash from uploadStart use a setTimeout to do it.
* --------- Revision 6.2 -----------
* + Added API calls for changing all the changeable settings dynamically
* = Fixed a bug in FileComplete event handler (in the SWF) that caused an error in Debug Players
* and prevent the event from being called
* + Added a setting (use_server_data_event) to indicate whether FileComplete or ServerData should be called.
* The SWFUpload architecture requires that only one file upload success event can be called.
* = Updated all the Demos, especially the Features Demo and the Forms Demo
* --------- Revision 6 -----------
* - Removed the call to setUploadSettings in flashReady. This was a left over call that is unnecessary.
* + Finished the parsing of post params during the init stage. This ommision was hidden by the call to setUploadSettings.
* - Removed the flash_target_id setting. The Flash file should only ever be added to the body tag.
* + Fixed (hopefully for good) another SWF race condition. IE executes the SWF very very early. The this.movieElement value should never be referenced.
* The movie Element should always be retrieved using this.getMovieElement().
* --------- Revision 6 -----------
* + Ported to ActionScript 3. Revision 6 requires Flash Player 9.
* = Fixed bug caused when cancelling single files. Would break any function that searched for a file_id.
* - Removed the automatic cookie sending setting. Devs should just pass the value they want to send in the post_params
* - Removed the query params settings (global and file specific). All params should be sent in the post_params
* + Added post_params which adds post values to the file upload post.
* + Added validate_files setting flag which causes the fileValidation event to be called before each file is uploaded.
* + Added fileValidation event. Return false if validation fails and true if validation is successful.
* + Added server_data parameter to the fileComplete event which returns any text that the upload script returns.
* = Updated all demos to work with Revision 6
* + Added in-code file extension validation. Before a file is queued the extension is checked against the valid extensions.
* Files the have invalid extensions cause the error event to be raised.
* + Added 'file_post_name' setting that allows the post variable name containing the file data to be named something other than 'Filedata'
* = Fixed a race condition in loadFlash where a cached flash movie would execute before this.movieElement could be assigned and loading would fail.
* --------- Revision 5.2 -----------
* = A little more code cleaning and variable renaming
* + Changed from an array queue to a FIFO queue. This eliminates the "current_index" and
* should reduce some memory usage.
* + Added out of order file uploading. Call StartUpload(/file_id/).
* + Added custom query_string parameters in addition to the cookies
* + Added the ability to modify the URL, cookies, params and send to flash
* + Added per file query_string params
* + Added files queued limit. Sometimes you may want the user to only queue one file at a time (or something)
* + Fixed limits so a zero(0) value means unlimited.
* --------- Revision 5 -------------
* = More code cleaning. Ported SWF to FlashDevelop. (Since my Flash Studio trial expired)
* The port to FlashDevelop is a big deal. It significantly changes the code structure
* and could introduce bugs. Also there have been reported issues with the FlashDevelop
* version from swfupload.mammon.se: Doesn't start when reloading in IE. Doesn't start
* in Firefox if the SWF file is visible because of a page scroll.
* + I fixed the Firefox issue by removing the wmode attribute from the embed object.
* + I cannot reproduce the IE issue on my local machine (although I can reproduce it at swfupload.mammon.se)
* + Event Handlers are now attached to the SWFUpload javascript object. The SWF file
* now calls the handlers in the context of the SWFUpload object which means the "this"
* object inside the handler refers to the proper SWFUpload instance.
* + Tested and Fixed upload target cookie attachment
* = Cleaned up / renamed everything for clarity and consistancy
* + File queuing is now subject to the upload limit. If the user attempts to queue more files
* than allowed an error is returned and the files are not queued.
* + Fixed misc bugs and text encodings.
* + Added more debug info for the SWF file.
* + SWF file now obeys the debug setting.
* + Added SetUploadTargetURL function that allows you to "dynamically" change the upload target
* + Added error code for zero byte file uploads which always return an IO error. The files are now rejected
* instead of being uploaded.
* --------- Revision 4 -------------
* = Cleaned up code. Added comments. Reorganized. Added more try..catches. Removed old unused methods.
* - Removed the 'create_ui' setting. The UI is now completely up to the developer.
* + Added upload_backend_cookies setting. Can set a string, or array of cookie names. These values will be
* passed as part of the upload_backend url
*
* = Changed QueueComplete event to only fire if at least one file has been successfully uploaded.
* + Added "Stop Upload" feature.
* = Revised the FLA file to clean things up, better handle errors, etc.
* = Fixed a bug where cancelling the first upload would cause the remaining uploads to fire before calling
* "startUpload". This change is in the FLA.
*
* + Fixed a bug in the upload.swf that prevented further file processing after an error is returned.
* + Added uploadLimit variable. Only complete uploads are counted. Once the limit is reached the flash
* movie will not upload any more files. (The ability to select or queue many files is not affected
* by the upload limit)
* + Added cancelQueue and cancelUpload methods.
* + Added ID property to the FileObj in the upload.swf
* + Added Upload and Queue settings
* + Added methods for generating the flash HTML and inserting it into the DOM.
* - Removed SWFObject
* + Updated the upload.swf and added the "flashReady" event. This will only call back
* for Flash 8 and above. With this we don't need a flash version detect script.
* The script initializes the Flash then waits for the Callback to init the UI.
* + Added seperate ui_target, degraded_target, create_ui settings. This allows fine control
* over what parts of the GUI the script displays and hides
*
* + Changed from a Static Class to an Instance (changed code/class structure)
* + Added "flash_version" setting. When set to zero the version check is skipped
* + Added Debug Console. The Instance class can't do document.write.
* = De-obfuscated SWFObject a bit
* - Removed standalone mode.
* + Added "ui_target" setting. When non-blank the link is added.
* + Added "flash_target" setting. When blank the flash is appended to the <body> tag
* = This fixes ASP.Net not allowing the flash to be added to the Form
* + Added error checking to the callSWF method
*
* -------- -------- -------- -------- -------- -------- -------- --------
* SWFUpload 0.7: Flash upload dialog - http://profandesign.se/swfupload/
* SWFUpload is (c) 2006 Lars Huring and Mammon Media and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
* -------- -------- -------- -------- -------- -------- -------- --------
* SWFUpload 0.7: Flash upload dialog - http://profandesign.se/swfupload/
*
* VERSION HISTORY
* 0.5 - First release
*
* 0.6 - 2006-11-24
* - Got rid of flash overlay
* - SWF size reduced to 840b
* - CSS-only styling of button
* - Add upload to links etc.
*
* 0.7 - 2006-11-27
* - Added filesize param and check in SWF
*
* 0.7.1 - 2006-12-01
* - Added link_mode param for standalone links
* if set to "standalone", createElement("a") won't run.
* - Added link_text param if css isn't needed.
* - Renamed cssClass to css_class for consistency
*
*/

View File

@ -1,8 +0,0 @@
class Delegate
{
static function create(obj:Object, func:Function):Function
{
return function() { return func.apply(obj, arguments); };
}
}

View File

@ -1,115 +0,0 @@
import flash.external.ExternalInterface;
class ExternalCall
{
/*public function ExternalCall()
{
}
*/
public static function Simple(callback:String):Void {
ExternalInterface.call(callback);
}
public static function FileQueued(callback:String, file_object:Object):Void {
ExternalInterface.call(callback, EscapeMessage(file_object));
}
public static function FileQueueError(callback:String, error_code:Number, file_object:Object, message:String):Void {
ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(error_code), EscapeMessage(message));
}
public static function FileDialogComplete(callback:String, num_files_selected:Number):Void {
ExternalInterface.call(callback, EscapeMessage(num_files_selected));
}
public static function UploadStart(callback:String, file_object:Object):Void {
ExternalInterface.call(callback, EscapeMessage(file_object));
}
public static function UploadProgress(callback:String, file_object:Object, bytes_loaded:Number, bytes_total:Number):Void {
ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(bytes_loaded), EscapeMessage(bytes_total));
}
public static function UploadSuccess(callback:String, file_object:Object):Void {
ExternalInterface.call(callback, EscapeMessage(file_object));
}
public static function UploadError(callback:String, error_code:Number, file_object:Object, message:String):Void {
ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(error_code), EscapeMessage(message));
}
public static function UploadComplete(callback:String, file_object:Object):Void {
ExternalInterface.call(callback, EscapeMessage(file_object));
}
public static function Debug(callback:String, message:String):Void {
ExternalInterface.call(callback, EscapeMessage(message));
}
/* Escapes all the backslashes which are not translated correctly in the Flash -> JavaScript Interface
*
* These functions had to be developed because the ExternalInterface has a bug that simply places the
* value a string in quotes (except for a " which is escaped) in a JavaScript string literal which
* is executed by the browser. These often results in improperly escaped string literals if your
* input string has any backslash characters. For example the string:
* "c:\Program Files\uploadtools\"
* is placed in a string literal (with quotes escaped) and becomes:
* var __flash__temp = "\"c:\Program Files\uploadtools\\"";
* This statement will cause errors when executed by the JavaScript interpreter:
* 1) The first \" is succesfully transformed to a "
* 2) \P is translated to P and the \ is lost
* 3) \u is interpreted as a unicode character and causes an error in IE
* 4) \\ is translated to \
* 5) leaving an unescaped " which causes an error
*
* I fixed this by escaping \ characters in all outgoing strings. The above escaped string becomes:
* var __flash__temp = "\"c:\\Program Files\\uploadtools\\\"";
* which contains the correct string literal.
*
* Note: The "var __flash__temp = " portion of the example is part of the ExternalInterface not part of
* my escaping routine.
*/
private static function EscapeMessage(message) {
if (typeof message == "string") {
message = EscapeString(message);
}
else if (typeof message == "array") {
message = EscapeArray(message);
}
else if (typeof message == "object") {
message = EscapeObject(message);
}
return message;
}
private static function EscapeString(message:String):String {
//var replacePattern:RegExp = /\\/g; //new RegExp("/\\/", "g");
return message.split("\\").join("\\\\").split("\n").join("\\n").split("\r").join("\\r").split("\f").join("\\f").split("\b").join("\\b");
}
private static function EscapeArray(message_array:Array):Array {
var length:Number = message_array.length;
var i:Number = 0;
for (i=0; i < length; i++) {
message_array[i] = EscapeMessage(message_array[i]);
}
return message_array;
}
private static function EscapeObject(message_obj:Object):Object {
for (var name:String in message_obj) {
message_obj[name] = EscapeMessage(message_obj[name]);
}
return message_obj;
}
}

View File

@ -1,65 +0,0 @@
import flash.net.FileReference;
class FileItem
{
private static var file_id_sequence:Number = 0; // tracks the file id sequence
private var postObject:Object;
public var file_reference:FileReference;
public var id:String;
public var index:Number = -1;
public var file_status:Number = 0;
private var js_object:Object;
public static var FILE_STATUS_QUEUED:Number = -1;
public static var FILE_STATUS_IN_PROGRESS:Number = -2;
public static var FILE_STATUS_ERROR:Number = -3;
public static var FILE_STATUS_SUCCESS:Number = -4;
public static var FILE_STATUS_CANCELLED:Number = -5;
public static var FILE_STATUS_NEW:Number = -6; // This file status should never be sent to JavaScript
public function FileItem(file_reference:FileReference, control_id:String)
{
this.postObject = {};
this.file_reference = file_reference;
this.id = control_id + "_" + (FileItem.file_id_sequence++);
this.file_status = FileItem.FILE_STATUS_QUEUED;
this.js_object = {
id: this.id,
index: this.index,
name: this.file_reference.name,
size: this.file_reference.size,
type: this.file_reference.type,
creationdate: this.file_reference.creationDate,
modificationdate: this.file_reference.modificationDate,
filestatus: this.file_status,
post: this.GetPostObject()
};
}
public function AddParam(name:String, value:String):Void {
this.postObject[name] = value;
}
public function RemoveParam(name:String):Void {
delete this.postObject[name];
}
public function GetPostObject():Object {
return this.postObject;
}
// Update the js_object and return it.
public function ToJavaScriptObject():Object {
this.js_object.filestatus = this.file_status;
this.js_object.post = this.GetPostObject();
return this.js_object;
}
public function toString():String {
return "FileItem - ID: " + this.id;
}
}

View File

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<project>
<!-- Output SWF options -->
<output>
<movie disabled="False" />
<movie input="" />
<movie path="swfupload_f8.swf" />
<movie fps="1" />
<movie width="1" />
<movie height="1" />
<movie version="8" />
<movie background="#FFFFFF" />
</output>
<!-- Other classes to be compiled into your SWF -->
<classpaths>
<class path="." />
</classpaths>
<!-- Build options -->
<build>
<option verbose="False" />
<option strict="False" />
<option infer="False" />
<option useMain="True" />
<option useMX="False" />
<option warnUnusedImports="False" />
<option traceMode="FlashConnect" />
<option traceFunction="" />
<option libraryPrefix="" />
<option excludeFile="" />
<option groupClasses="False" />
<option frame="1" />
<option keep="True" />
</build>
<!-- Class files to compile (other referenced classes will automatically be included) -->
<compileTargets>
<compile path="SWFUpload.as" />
</compileTargets>
<!-- Assets to embed into the output SWF -->
<library>
<!-- example: <asset path="..." id="..." update="..." glyphs="..." mode="..." place="..." sharepoint="..." /> -->
</library>
<!-- Paths to exclude from the Project Explorer tree -->
<hiddenPaths>
<!-- example: <hidden path="..." /> -->
</hiddenPaths>
<!-- Executed before build -->
<preBuildCommand />
<!-- Executed after build -->
<postBuildCommand alwaysRun="False">deploy.bat</postBuildCommand>
<!-- Other project options -->
<options>
<option showHiddenPaths="False" />
<option testMovie="Default" />
</options>
</project>

View File

@ -1,914 +0,0 @@
/*
* Todo:
* In SWFUpload v3 the file_queue and file_index should be merged. This probably means we'll remove FileItem.id and just
* use indexes everywhere.
* */
import flash.net.FileReferenceList;
import flash.net.FileReference;
import flash.external.ExternalInterface;
import FileItem;
import ExternalCall;
import Delegate;
class SWFUpload {
// Cause SWFUpload to start as soon as the movie starts
public static function main():Void
{
// Code to attempt to fix "flash script running slowly" error messages
var counter:Number = 0;
_root.onEnterFrame = function () {
if (++counter > 100) counter = 0;
};
// Start SWFUpload
var SWFUpload:SWFUpload = new SWFUpload();
}
private var build_number:String = "SWFUPLOAD 2.0.1 FP8 2007-12-05 0001";
// State tracking variables
private var fileBrowserMany:FileReferenceList = new FileReferenceList();
private var fileBrowserOne:FileReference = null; // This isn't set because it can't be reused like the FileReferenceList. It gets setup in the SelectFile method
private var file_queue:Array = new Array(); // holds a list of all items that are to be uploaded.
private var current_file_item:FileItem = null; // the item that is currently being uploaded.
private var file_index:Array = new Array();
private var successful_uploads:Number = 0; // Tracks the uploads that have been completed
private var queue_errors:Number = 0; // Tracks files rejected during queueing
private var upload_errors:Number = 0; // Tracks files that fail upload
private var upload_cancelled:Number = 0; // Tracks number of cancelled files
private var queued_uploads:Number = 0; // Tracks the FileItems that are waiting to be uploaded.
private var valid_file_extensions:Array = new Array();// Holds the parsed valid extensions.
private var file_reference_listener:Object;
// Callbacks
private var flashReady_Callback:String;
private var fileDialogStart_Callback:String;
private var fileQueued_Callback:String;
private var fileQueueError_Callback:String;
private var fileDialogComplete_Callback:String;
private var uploadStart_Callback:String;
private var uploadProgress_Callback:String;
private var uploadError_Callback:String;
private var uploadSuccess_Callback:String;
private var uploadComplete_Callback:String;
private var debug_Callback:String;
// Values passed in from the HTML
private var movieName:String;
private var uploadURL:String;
private var filePostName:String;
private var uploadPostObject:Object;
private var fileTypes:String;
private var fileTypesDescription:String;
private var fileSizeLimit:Number;
private var fileUploadLimit:Number = 0;
private var fileQueueLimit:Number = 0;
private var debugEnabled:Boolean;
// Error code "constants"
// Size check constants
private var SIZE_TOO_BIG:Number = 1;
private var SIZE_ZERO_BYTE:Number = -1;
private var SIZE_OK:Number = 0;
// Queue errors
private var ERROR_CODE_QUEUE_LIMIT_EXCEEDED:Number = -100;
private var ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT:Number = -110;
private var ERROR_CODE_ZERO_BYTE_FILE:Number = -120;
private var ERROR_CODE_INVALID_FILETYPE:Number = -130;
// Upload Errors
private var ERROR_CODE_HTTP_ERROR:Number = -200;
private var ERROR_CODE_MISSING_UPLOAD_URL:Number = -210;
private var ERROR_CODE_IO_ERROR:Number = -220;
private var ERROR_CODE_SECURITY_ERROR:Number = -230;
private var ERROR_CODE_UPLOAD_LIMIT_EXCEEDED:Number = -240;
private var ERROR_CODE_UPLOAD_FAILED:Number = -250;
private var ERROR_CODE_SPECIFIED_FILE_ID_NOT_FOUND:Number = -260;
private var ERROR_CODE_FILE_VALIDATION_FAILED:Number = -270;
private var ERROR_CODE_FILE_CANCELLED:Number = -280;
private var ERROR_CODE_UPLOAD_STOPPED:Number = -290;
public function SWFUpload() {
System.security.allowDomain("*"); // Allow uploading to any domain
// Setup file FileReferenceList events
var fbmListener:Object = {
onSelect : Delegate.create(this, this.Select_Many_Handler),
onCancel : Delegate.create(this, this.DialogCancelled_Handler)
}
this.fileBrowserMany.addListener(fbmListener);
// Setup the events listner
this.file_reference_listener = {
onProgress : Delegate.create(this, this.FileProgress_Handler),
onIOError : Delegate.create(this, this.IOError_Handler),
onSecurityError : Delegate.create(this, this.SecurityError_Handler),
onHTTPError : Delegate.create(this, this.HTTPError_Handler),
onComplete : Delegate.create(this, this.FileComplete_Handler)
};
// Get the move name
this.movieName = _root.movieName;
// **Configure the callbacks**
// The JavaScript tracks all the instances of SWFUpload on a page. We can access the instance
// associated with this SWF file using the movieName. Each callback is accessible by making
// a call directly to it on our instance. There is no error handling for undefined callback functions.
// A developer would have to deliberately remove the default functions,set the variable to null, or remove
// it from the init function.
this.flashReady_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].flashReady";
this.fileDialogStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogStart";
this.fileQueued_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueued";
this.fileQueueError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueueError";
this.fileDialogComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogComplete";
this.uploadStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadStart";
this.uploadProgress_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadProgress";
this.uploadError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadError";
this.uploadSuccess_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadSuccess";
this.uploadComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadComplete";
this.debug_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].debug";
// Get the Flash Vars
this.uploadURL = _root.uploadURL;
this.filePostName = _root.filePostName;
this.fileTypes = _root.fileTypes;
this.fileTypesDescription = _root.fileTypesDescription + " (" + this.fileTypes + ")";
this.loadPostParams(_root.params);
if (!this.filePostName) {
this.filePostName = "Filedata";
}
if (!this.fileTypes) {
this.fileTypes = "*.*";
}
if (!this.fileTypesDescription) {
this.fileTypesDescription = "All Files";
}
this.LoadFileExensions(this.fileTypes);
try {
this.debugEnabled = _root.debugEnabled == "true" ? true : false;
} catch (ex:Object) {
this.debugEnabled = false;
}
try {
this.fileSizeLimit = Number(_root.fileSizeLimit);
if (this.fileSizeLimit < 0) this.fileSizeLimit = 0;
} catch (ex:Object) {
this.fileSizeLimit = 0;
}
try {
this.fileUploadLimit = Number(_root.fileUploadLimit);
if (this.fileUploadLimit < 0) this.fileUploadLimit = 0;
} catch (ex:Object) {
this.fileUploadLimit = 0;
}
try {
this.fileQueueLimit = Number(_root.fileQueueLimit);
if (this.fileQueueLimit < 0) this.fileQueueLimit = 0;
} catch (ex:Object) {
this.fileQueueLimit = 0;
}
// Set the queue limit to match the upload limit when the queue limit is bigger than the upload limit
if (this.fileQueueLimit > this.fileUploadLimit && this.fileUploadLimit != 0) this.fileQueueLimit = this.fileUploadLimit;
// The the queue limit is unlimited and the upload limit is not then set the queue limit to the upload limit
if (this.fileQueueLimit == 0 && this.fileUploadLimit != 0) this.fileQueueLimit = this.fileUploadLimit;
try {
ExternalInterface.addCallback("SelectFile", this, this.SelectFile);
ExternalInterface.addCallback("SelectFiles", this, this.SelectFiles);
ExternalInterface.addCallback("StartUpload", this, this.StartUpload);
ExternalInterface.addCallback("ReturnUploadStart", this, this.ReturnUploadStart);
ExternalInterface.addCallback("StopUpload", this, this.StopUpload);
ExternalInterface.addCallback("CancelUpload", this, this.CancelUpload);
ExternalInterface.addCallback("GetStats", this, this.GetStats);
ExternalInterface.addCallback("SetStats", this, this.SetStats);
ExternalInterface.addCallback("GetFile", this, this.GetFile);
ExternalInterface.addCallback("GetFileByIndex", this, this.GetFileByIndex);
ExternalInterface.addCallback("AddFileParam", this, this.AddFileParam);
ExternalInterface.addCallback("RemoveFileParam", this, this.RemoveFileParam);
ExternalInterface.addCallback("SetUploadURL", this, this.SetUploadURL);
ExternalInterface.addCallback("SetPostParams", this, this.SetPostParams);
ExternalInterface.addCallback("SetFileTypes", this, this.SetFileTypes);
ExternalInterface.addCallback("SetFileSizeLimit", this, this.SetFileSizeLimit);
ExternalInterface.addCallback("SetFileUploadLimit", this, this.SetFileUploadLimit);
ExternalInterface.addCallback("SetFileQueueLimit", this, this.SetFileQueueLimit);
ExternalInterface.addCallback("SetFilePostName", this, this.SetFilePostName);
ExternalInterface.addCallback("SetDebugEnabled", this, this.SetDebugEnabled);
} catch (ex:Error) {
this.Debug("Callbacks where not set.");
}
this.Debug("SWFUpload Init Complete");
this.PrintDebugInfo();
// Do some feature detection
if (flash.net.FileReferenceList && flash.net.FileReference && flash.external.ExternalInterface && flash.external.ExternalInterface.available) {
ExternalCall.Simple(this.flashReady_Callback);
} else {
this.Debug("Feature Detection Failed");
}
}
/* *****************************************
* FileReference Event Handlers
* *************************************** */
private function DialogCancelled_Handler():Void {
this.Debug("Event: fileDialogComplete: File Dialog window cancelled.");
ExternalCall.FileDialogComplete(this.fileDialogComplete_Callback, 0);
}
private function FileProgress_Handler(file:FileReference, bytesLoaded:Number, bytesTotal:Number):Void {
this.Debug("Event: uploadProgress: File ID: " + this.current_file_item.id + ". Bytes: " + bytesLoaded + ". Total: " + bytesTotal);
ExternalCall.UploadProgress(this.uploadProgress_Callback, this.current_file_item.ToJavaScriptObject(), bytesLoaded, bytesTotal);
}
private function FileComplete_Handler():Void {
this.successful_uploads++;
this.current_file_item.file_status = FileItem.FILE_STATUS_SUCCESS;
this.Debug("Event: uploadSuccess: File ID: " + this.current_file_item.id + " Data: n/a");
ExternalCall.UploadSuccess(this.uploadSuccess_Callback, this.current_file_item.ToJavaScriptObject());
this.UploadComplete();
}
private function HTTPError_Handler(file:FileReference, httpError:Number):Void {
this.upload_errors++;
this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR;
this.Debug("Event: uploadError: HTTP ERROR : File ID: " + this.current_file_item.id + ". HTTP Status: " + httpError + ".");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_HTTP_ERROR, this.current_file_item.ToJavaScriptObject(), httpError.toString());
this.UploadComplete();
}
// Note: Flash Player does not support Uploads that require authentication. Attempting this will trigger an
// IO Error or it will prompt for a username and password and the crash the browser (FireFox/Opera)
private function IOError_Handler(file:FileReference):Void {
this.upload_errors++;
this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR;
if(!this.uploadURL.length) {
this.Debug("Event: uploadError : IO Error : File ID: " + this.current_file_item.id + ". Upload URL string is empty.");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_MISSING_UPLOAD_URL, this.current_file_item.ToJavaScriptObject(), "IO Error");
} else {
this.Debug("Event: uploadError : IO Error : File ID: " + this.current_file_item.id + ". IO Error.");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_IO_ERROR, this.current_file_item.ToJavaScriptObject(), "IO Error");
}
this.UploadComplete();
}
private function SecurityError_Handler(file:FileReference, errorString:String):Void {
this.upload_errors++;
this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR;
this.Debug("Event: uploadError : Security Error : File Number: " + this.current_file_item.id + ". Error:" + errorString);
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_SECURITY_ERROR, this.current_file_item.ToJavaScriptObject(), errorString);
this.UploadComplete();
}
private function Select_Many_Handler(frl:FileReferenceList):Void {
this.Select_Handler(frl.fileList);
}
private function Select_One_Handler(file:FileReference):Void {
var fileArray:Array = new Array(1);
fileArray[0] = file;
this.Select_Handler(fileArray);
}
private function Select_Handler(file_reference_list:Array):Void {
this.Debug("Select Handler: Files Selected from Dialog. Processing file list");
this.Debug("Type: " + typeof(this.fileQueueLimit) + " Value:" + this.fileQueueLimit);
// Determine how many queue slots are remaining (check the unlimited (0) settings, successful uploads and queued uploads)
var queue_slots_remaining:Number = 0;
if (this.fileUploadLimit == 0) {
queue_slots_remaining = (this.fileQueueLimit == 0) ? file_reference_list.length : (this.fileQueueLimit - this.queued_uploads); // If unlimited queue make the allowed size match however many files were selected.
} else {
var remaining_uploads:Number = this.fileUploadLimit - this.successful_uploads - this.queued_uploads;
if (remaining_uploads < 0) remaining_uploads = 0;
if (this.fileQueueLimit == 0 || this.fileQueueLimit >= remaining_uploads) {
queue_slots_remaining = remaining_uploads;
} else if (this.fileQueueLimit < remaining_uploads) {
queue_slots_remaining = this.fileQueueLimit;
}
}
// Check if the number of files selected is greater than the number allowed to queue up.
if (queue_slots_remaining < file_reference_list.length) {
this.Debug("Event: fileQueueError : Selected Files (" + file_reference_list.length + ") exceeds remaining Queue size (" + queue_slots_remaining + ").");
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_QUEUE_LIMIT_EXCEEDED, null, queue_slots_remaining.toString());
} else {
// Process each selected file
for (var i:Number = 0; i < file_reference_list.length; i++) {
var file_item:FileItem = new FileItem(file_reference_list[i], this.movieName);
// Add the file to the index
file_item.index = this.file_index.length;
this.file_index[file_item.index] = file_item;
// The the file to see if it is acceptable
var size_result:Number = this.CheckFileSize(file_item);
var is_valid_filetype:Boolean = this.CheckFileType(file_item);
if(size_result == this.SIZE_OK && is_valid_filetype) {
this.Debug("Event: fileQueued : File ID: " + file_item.id);
this.file_queue.push(file_item);
this.queued_uploads++;
ExternalCall.FileQueued(this.fileQueued_Callback, file_item.ToJavaScriptObject());
}
else if (!is_valid_filetype) {
file_item.file_reference = null; // Cleanup the object
this.Debug("Event: fileQueueError : File not of a valid type.");
this.queue_errors++;
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_INVALID_FILETYPE, file_item.ToJavaScriptObject(), "File is not an allowed file type.");
}
else if (size_result == this.SIZE_TOO_BIG) {
file_item.file_reference = null; // Cleanup the object
this.Debug("Event: fileQueueError : File exceeds size limit.");
this.queue_errors++;
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT, file_item.ToJavaScriptObject(), "File size exceeds allowed limit.");
}
else if (size_result == this.SIZE_ZERO_BYTE) {
file_item.file_reference = null; // Cleanup the object
this.Debug("Event: fileQueueError : File is zero bytes.");
this.queue_errors++;
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_ZERO_BYTE_FILE, file_item.ToJavaScriptObject(), "File is zero bytes and cannot be uploaded.");
}
else {
file_item.file_reference = null; // Cleanup the object
this.Debug("Entered an unexpected state checking the file in Select_Handler");
}
}
}
this.Debug("Event: fileDialogComplete : Finished adding files");
ExternalCall.FileDialogComplete(this.fileDialogComplete_Callback, file_reference_list.length);
}
/* ****************************************************************
Externally exposed functions
****************************************************************** */
// Opens a file browser dialog that allows one file to be selected.
private function SelectFile():Void {
this.fileBrowserOne = new FileReference();
var fbo_listener:Object = {
onSelect : Delegate.create(this, this.Select_One_Handler),
onCancel : Delegate.create(this, this.DialogCancelled_Handler)
}
this.fileBrowserOne.addListener(fbo_listener);
// Default file type settings
var allowed_file_types:String = "*.*";
var allowed_file_types_description:String = "All Files";
// Get the instance settings
if (this.fileTypes.length > 0) allowed_file_types = this.fileTypes;
if (this.fileTypesDescription.length > 0) allowed_file_types_description = this.fileTypesDescription;
this.Debug("Event: fileDialogStart : Browsing files. Single Select. Allowed file types: " + allowed_file_types);
ExternalCall.Simple(this.fileDialogStart_Callback);
this.fileBrowserOne.browse([{ description : allowed_file_types_description, extension : allowed_file_types }]);
}
// Opens a file browser dialog that allows multiple files to be selected.
private function SelectFiles():Void {
var allowed_file_types:String = "*.*";
var allowed_file_types_description:String = "All Files";
if (this.fileTypes.length > 0) allowed_file_types = this.fileTypes;
if (this.fileTypesDescription.length > 0) allowed_file_types_description = this.fileTypesDescription;
this.Debug("Event: fileDialogStart : Browsing files. Multi Select. Allowed file types: " + allowed_file_types);
ExternalCall.Simple(this.fileDialogStart_Callback);
this.fileBrowserMany.browse([{ description : allowed_file_types_description, extension : allowed_file_types }]);
}
// Starts uploading. Checks to see if a file is currently uploading and, if not, starts the upload.
private function StartUpload(file_id:String):Void {
if (file_id == undefined) file_id = "";
if (this.current_file_item == null) {
this.Debug("StartUpload(): Starting Upload: " + (file_id ? "File ID:" + file_id : "First file in queue"));
this.StartFile(file_id);
} else {
this.Debug("StartUpload(): Upload run already in progress");
}
}
// Cancel the current upload and stops. Doesn't advance the upload pointer. The current file is requeued at the beginning.
private function StopUpload():Void {
if (this.current_file_item != null) {
// Cancel the upload and re-queue the FileItem
this.current_file_item.file_reference.cancel();
this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED;
// Remove the event handlers
this.current_file_item.file_reference.removeListener(this.file_reference_listener);
this.file_queue.unshift(this.current_file_item);
var js_object:Object = this.current_file_item.ToJavaScriptObject();
this.current_file_item = null;
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_STOPPED, js_object, "Upload Stopped");
ExternalCall.UploadComplete(this.uploadComplete_Callback, js_object);
this.Debug("StopUpload(): upload stopped.");
} else {
this.Debug("StopUpload(): Upload run not in progress");
}
}
/* Cancels the upload specified by file_id
* If the file is currently uploading it is cancelled and the uploadComplete
* event gets called.
* If the file is not currently uploading then only the uploadCancelled event is fired.
* */
private function CancelUpload(file_id:String):Void {
var file_item:FileItem = null;
if (file_id == undefined) file_id = "";
// Check the current file item
if (this.current_file_item != null && (this.current_file_item.id == file_id || !file_id)) {
this.current_file_item.file_reference.cancel();
this.current_file_item.file_status = FileItem.FILE_STATUS_CANCELLED;
this.upload_cancelled++;
this.Debug("Event: fileCancelled: File ID: " + this.current_file_item.id + ". Cancelling current upload");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, this.current_file_item.ToJavaScriptObject(), "File Upload Cancelled.");
this.UploadComplete(); // <-- this advanced the upload to the next file
} else if (file_id) {
// Find the file in the queue
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
// Remove the file from the queue
file_item = FileItem(this.file_queue[file_index]);
file_item.file_status = FileItem.FILE_STATUS_CANCELLED;
this.file_queue[file_index] = null;
this.queued_uploads--;
this.upload_cancelled++;
// Cancel the file (just for good measure) and make the callback
file_item.file_reference.cancel();
file_item.file_reference.removeListener(this.file_reference_listener);
file_item.file_reference = null;
this.Debug("Event: uploadError : " + file_item.id + ". Cancelling queued upload");
this.Debug("Event: uploadError : " + file_item.id + ". Cancelling queued upload");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, file_item.ToJavaScriptObject(), "File Cancelled");
// Get rid of the file object
file_item = null;
}
} else {
// Get the first file and cancel it
while (this.file_queue.length > 0 && file_item == null) {
// Check that File Reference is valid (if not make sure it's deleted and get the next one on the next loop)
file_item = FileItem(this.file_queue.shift()); // Cast back to a FileItem
if (typeof(file_item) == "undefined") {
file_item = null;
continue;
}
}
if (file_item != null) {
file_item.file_status = FileItem.FILE_STATUS_CANCELLED;
this.queued_uploads--;
this.upload_cancelled++;
// Cancel the file (just for good measure) and make the callback
file_item.file_reference.cancel();
file_item.file_reference.removeListener(this.file_reference_listener);
file_item.file_reference = null;
this.Debug("Event: uploadError : " + file_item.id + ". Cancelling queued upload");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, file_item.ToJavaScriptObject(), "File Cancelled");
// Get rid of the file object
file_item = null;
}
}
}
private function GetStats():Object {
return {
in_progress : this.current_file_item == null ? 0 : 1,
files_queued : this.queued_uploads,
successful_uploads : this.successful_uploads,
upload_errors : this.upload_errors,
upload_cancelled : this.upload_cancelled,
queue_errors : this.queue_errors
};
}
private function SetStats(stats:Object):Void {
this.successful_uploads = (typeof(stats["successful_uploads"]) === "Number") ? stats["successful_uploads"] : this.successful_uploads;
this.upload_errors = (typeof(stats["upload_errors"]) === "Number") ? stats["upload_errors"] : this.upload_errors;
this.upload_cancelled = (typeof(stats["upload_cancelled"]) === "Number") ? stats["upload_cancelled"] : this.upload_cancelled;
this.queue_errors = (typeof(stats["queue_errors"]) === "Number") ? stats["queue_errors"] : this.queue_errors;
}
private function GetFile(file_id:String):Object {
var file:FileItem = null;
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
file = this.file_queue[file_index];
} else {
if (this.current_file_item != null) {
file = this.current_file_item;
} else {
for (var i:Number = 0; i < this.file_queue.length; i++) {
file = this.file_queue[i];
if (file != null) break;
}
}
}
if (file == null) {
return null;
} else {
return file.ToJavaScriptObject();
}
}
private function GetFileByIndex(index:Number):Object {
if (index < 0 || index > this.file_index.length - 1) {
return null;
} else {
return this.file_index[index].ToJavaScriptObject();
}
}
private function AddFileParam(file_id:String, name:String, value:String):Boolean {
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
var file_item:FileItem = FileItem(this.file_queue[file_index]);
file_item.AddParam(name, value);
return true;
} else {
return false;
}
}
private function RemoveFileParam(file_id:String, name:String):Boolean {
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
var file_item:FileItem = FileItem(this.file_queue[file_index]);
file_item.RemoveParam(name);
return true;
} else {
return false;
}
}
private function SetUploadURL(url:String):Void {
if (typeof(url) !== "undefined" && url !== "") {
this.uploadURL = url;
}
}
private function SetPostParams(post_object:Object):Void {
if (typeof(post_object) !== "undefined" && post_object !== null) {
this.uploadPostObject = post_object;
}
}
private function SetFileTypes(types:String, description:String):Void {
this.fileTypes = types;
this.fileTypesDescription = description;
this.LoadFileExensions(this.fileTypes);
}
private function SetFileSizeLimit(bytes:Number):Void {
if (bytes < 0) bytes = 0;
this.fileSizeLimit = bytes;
}
private function SetFileUploadLimit(file_upload_limit:Number):Void {
if (file_upload_limit < 0) file_upload_limit = 0;
this.fileUploadLimit = file_upload_limit;
}
private function SetFileQueueLimit(file_queue_limit:Number):Void {
if (file_queue_limit < 0) file_queue_limit = 0;
this.fileQueueLimit = file_queue_limit;
}
private function SetFilePostName(file_post_name:String):Void {
if (file_post_name != "") {
this.filePostName = file_post_name;
}
}
private function SetDebugEnabled(debug_enabled:Boolean):Void {
this.debugEnabled = debug_enabled;
}
/* *************************************************************
File processing and handling functions
*************************************************************** */
//
private function StartFile(file_id:String):Void {
if (file_id == undefined) file_id = "";
// Only upload a file uploads are being processed.
// startFile could be called by a file cancellation even when we aren't currently uploading
if (this.current_file_item != null) {
this.Debug("StartFile(): Upload already in progress. Not starting another upload.");
}
this.Debug("StartFile: " + (file_id ? "File ID: " + file_id : "First file in queue"));
// Check the upload limit
if (this.successful_uploads >= this.fileUploadLimit && this.fileUploadLimit != 0) {
this.Debug("Event: uploadError : Upload limit reached. No more files can be uploaded.");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_LIMIT_EXCEEDED, null, "The upload limit has been reached.");
this.current_file_item = null;
return;
}
// Get the next file to upload
if (!file_id) {
while (this.file_queue.length > 0 && this.current_file_item == null) {
// Check that File Reference is valid (if not make sure it's deleted and get the next one on the next loop)
this.current_file_item = FileItem(this.file_queue.shift()); // Cast back to a FileItem
if (typeof(this.current_file_item) == "undefined") {
this.current_file_item = null;
continue;
}
}
} else {
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
// Set the file as the current upload and remove it from the queue
this.current_file_item = FileItem(this.file_queue[file_index]);
this.file_queue[file_index] = null;
} else {
this.Debug("Event: uploadError : File ID not found in queue: " + file_id);
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_SPECIFIED_FILE_ID_NOT_FOUND, null, "File ID not queued.");
}
}
// Start the upload if we found an item to upload
if (this.current_file_item != null) {
// Begin the upload
this.Debug("Event: uploadStart : File ID: " + this.current_file_item.id);
ExternalCall.UploadStart(this.uploadStart_Callback, this.current_file_item.ToJavaScriptObject());
}
// Otherwise we've would have looped through all the FileItems. This means the queue is empty)
else {
this.Debug("startFile(): No File Reference found. There are no files left to upload.\nstartFile(): Ending upload run.");
}
}
// This starts the upload when the user returns TRUE from the uploadStart event. Rather than just have the value returned from
// the function we do a return function call so we can use the setTimeout work-around for Flash/JS circular calls.
private function ReturnUploadStart(start_upload:Boolean):Void {
if (this.current_file_item == null) {
this.Debug("ReturnUploadStart called but file was no longer queued. This is okay if the file was stopped or cancelled.");
return;
}
if (start_upload) {
try {
// Set the event handlers
this.current_file_item.file_reference.addListener(this.file_reference_listener);
// Upload the file
var url:String = this.BuildRequest();
this.Debug("startFile(): File Reference found. File accepted by startUpload event. Starting upload to " + this.uploadURL + " for File ID: " + this.current_file_item.id);
this.current_file_item.file_reference.upload(url, this.filePostName, false);
} catch (ex:Error) {
this.upload_errors++;
this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR;
var message:String = ex.name + "\n" + ex.message;
this.Debug("Event: uploadError(): Unhandled exception: " + message);
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_FAILED, this.current_file_item.ToJavaScriptObject(), message);
this.UploadComplete();
}
this.current_file_item.file_status = FileItem.FILE_STATUS_IN_PROGRESS;
} else {
this.Debug("Event: uploadError : Call to uploadStart returned false. Not uploading file.");
// Remove the event handlers
this.current_file_item.file_reference.removeListener(this.file_reference_listener);
// Re-queue the FileItem
this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED;
var js_object:Object = this.current_file_item.ToJavaScriptObject();
this.file_queue.unshift(this.current_file_item);
this.current_file_item = null;
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_VALIDATION_FAILED, js_object, "Call to uploadStart return false. Not uploading file.");
ExternalCall.UploadComplete(this.uploadComplete_Callback, js_object);
this.Debug("startFile(): upload rejected by startUpload event. File re-queued.");
}
}
// Completes the file upload by deleting it's reference, advancing the pointer.
// Once this event files a new upload can be started.
private function UploadComplete():Void {
var jsFileObj:Object = this.current_file_item.ToJavaScriptObject();
this.current_file_item.file_reference.removeListener(this.file_reference_listener);
this.current_file_item.file_reference = null;
this.current_file_item = null;
this.queued_uploads--;
this.Debug("Event: uploadComplete : Upload cycle complete.");
ExternalCall.UploadComplete(this.uploadComplete_Callback, jsFileObj);
}
/* *************************************************************
Utility Functions
*************************************************************** */
// Check the size of the file against the allowed file size.
private function CheckFileSize(file_item:FileItem):Number {
if (file_item.file_reference.size == 0) {
return this.SIZE_ZERO_BYTE;
} else if (this.fileSizeLimit != 0 && file_item.file_reference.size > (this.fileSizeLimit * 1000)) {
return this.SIZE_TOO_BIG;
} else {
return this.SIZE_OK;
}
}
private function CheckFileType(file_item:FileItem):Boolean {
// If no extensions are defined then a *.* was passed and the check is unnecessary
if (this.valid_file_extensions.length == 0) {
return true;
}
var fileRef:FileReference = file_item.file_reference;
var last_dot_index:Number = fileRef.name.lastIndexOf(".");
var extension:String = "";
if (last_dot_index >= 0) {
extension = fileRef.name.substr(last_dot_index + 1).toLowerCase();
}
var is_valid_filetype:Boolean = false;
for (var i:Number=0; i < this.valid_file_extensions.length; i++) {
if (String(this.valid_file_extensions[i]) == extension) {
is_valid_filetype = true;
break;
}
}
return is_valid_filetype;
}
private function BuildRequest():String {
// Create the request object
var file_post:Object = this.current_file_item.GetPostObject();
var key:String;
var url:String = this.uploadURL;
var pairs:Array = new Array();
for (key in this.uploadPostObject) {
this.Debug("Global URL Item: " + key + "=" + this.uploadPostObject[key]);
if (this.uploadPostObject.hasOwnProperty(key)) {
pairs.push(key + "=" + this.uploadPostObject[key]);
}
}
for (key in file_post) {
this.Debug("File Post Item: " + key + "=" + this.uploadPostObject[key]);
if (file_post.hasOwnProperty(key)) {
pairs.push(escape(key) + "=" + escape(file_post[key]));
}
}
url = this.uploadURL + (this.uploadURL.indexOf("?") > -1 ? "&" : "?") + pairs.join("&");
return url;
}
private function Debug(msg:String):Void {
if (this.debugEnabled) {
var lines:Array = msg.split("\n");
for (var i:Number=0; i < lines.length; i++) {
lines[i] = "SWF DEBUG: " + lines[i];
}
try {
ExternalCall.Debug(this.debug_Callback, lines.join("\n"));
} catch (ex:Error) {
// pretend nothing happened
}
}
}
private function PrintDebugInfo():Void {
var debug_info:String = "\n----- SWF DEBUG OUTPUT ----\n"
+ "Build Number: " + this.build_number + "\n"
+ "movieName: " + this.movieName + "\n"
+ "Upload URL: " + this.uploadURL + "\n"
+ "File Types String: " + this.fileTypes + "\n"
+ "Parsed File Types: " + this.valid_file_extensions.toString() + "\n"
+ "File Types Description: " + this.fileTypesDescription + "\n"
+ "File Size Limit: " + this.fileSizeLimit + "\n"
+ "File Upload Limit: " + this.fileUploadLimit + "\n"
+ "File Queue Limit: " + this.fileQueueLimit + "\n"
+ "Post Params:\n";
for (var key:String in this.uploadPostObject) {
debug_info += " " + key + "=" + this.uploadPostObject[key] + "\n";
}
debug_info += "----- END SWF DEBUG OUTPUT ----\n";
this.Debug(debug_info);
}
private function FindIndexInFileQueue(file_id:String):Number {
for (var i:Number = 0; i<this.file_queue.length; i++) {
var item:FileItem = this.file_queue[i];
if (item != null && item.id == file_id) return i;
}
return -1;
}
// Parse the file extensions in to an array so we can validate them agains
// the files selected later.
private function LoadFileExensions(filetypes:String):Void {
var extensions:Array = filetypes.split(";");
this.valid_file_extensions = new Array();
for (var i:Number=0; i < extensions.length; i++) {
var extension:String = String(extensions[i]);
var dot_index:Number = extension.lastIndexOf(".");
if (dot_index >= 0) {
extension = extension.substr(dot_index + 1).toLowerCase();
} else {
extension = extension.toLowerCase();
}
// If one of the extensions is * then we allow all files
if (extension == "*") {
this.valid_file_extensions = new Array();
break;
}
this.valid_file_extensions.push(extension);
}
}
private function loadPostParams(param_string:String):Void {
var post_object:Object = {};
if (param_string != null) {
var name_value_pairs:Array = param_string.split("&");
for (var i:Number = 0; i < name_value_pairs.length; i++) {
var name_value:String = String(name_value_pairs[i]);
var index_of_equals:Number = name_value.indexOf("=");
if (index_of_equals > 0) {
post_object[unescape(name_value.substring(0, index_of_equals))] = unescape(name_value.substr(index_of_equals + 1));
}
}
}
this.uploadPostObject = post_object;
}
}

View File

@ -1,3 +0,0 @@
@echo off
copy ..\swfupload.js ..\..\demos\swfupload
copy swfupload_f8.swf ..\..\demos\swfupload

Binary file not shown.

View File

@ -1,117 +0,0 @@
package {
import flash.external.ExternalInterface;
internal class ExternalCall
{
/*public function ExternalCall()
{
}
*/
public static function Simple(callback:String):void {
ExternalInterface.call(callback);
}
public static function FileQueued(callback:String, file_object:Object):void {
ExternalInterface.call(callback, EscapeMessage(file_object));
}
public static function FileQueueError(callback:String, error_code:Number, file_object:Object, message:String):void {
ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(error_code), EscapeMessage(message));
}
public static function FileDialogComplete(callback:String, num_files_selected:Number):void {
ExternalInterface.call(callback, EscapeMessage(num_files_selected));
}
public static function UploadStart(callback:String, file_object:Object):void {
ExternalInterface.call(callback, EscapeMessage(file_object));
}
public static function UploadProgress(callback:String, file_object:Object, bytes_loaded:uint, bytes_total:uint):void {
ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(bytes_loaded), EscapeMessage(bytes_total));
}
public static function UploadSuccess(callback:String, file_object:Object, server_data:String):void {
ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(server_data));
}
public static function UploadError(callback:String, error_code:Number, file_object:Object, message:String):void {
ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(error_code), EscapeMessage(message));
}
public static function UploadComplete(callback:String, file_object:Object):void {
ExternalInterface.call(callback, EscapeMessage(file_object));
}
public static function Debug(callback:String, message:String):void {
ExternalInterface.call(callback, EscapeMessage(message));
}
/* Escapes all the backslashes which are not translated correctly in the Flash -> JavaScript Interface
*
* These functions had to be developed because the ExternalInterface has a bug that simply places the
* value a string in quotes (except for a " which is escaped) in a JavaScript string literal which
* is executed by the browser. These often results in improperly escaped string literals if your
* input string has any backslash characters. For example the string:
* "c:\Program Files\uploadtools\"
* is placed in a string literal (with quotes escaped) and becomes:
* var __flash__temp = "\"c:\Program Files\uploadtools\\"";
* This statement will cause errors when executed by the JavaScript interpreter:
* 1) The first \" is succesfully transformed to a "
* 2) \P is translated to P and the \ is lost
* 3) \u is interpreted as a unicode character and causes an error in IE
* 4) \\ is translated to \
* 5) leaving an unescaped " which causes an error
*
* I fixed this by escaping \ characters in all outgoing strings. The above escaped string becomes:
* var __flash__temp = "\"c:\\Program Files\\uploadtools\\\"";
* which contains the correct string literal.
*
* Note: The "var __flash__temp = " portion of the example is part of the ExternalInterface not part of
* my escaping routine.
*/
private static function EscapeMessage(message:*):* {
if (message is String) {
message = EscapeString(message);
}
else if (message is Array) {
message = EscapeArray(message);
}
else if (message is Object) {
message = EscapeObject(message);
}
return message;
}
private static function EscapeString(message:String):String {
var replacePattern:RegExp = /\\/g; //new RegExp("/\\/", "g");
return message.replace(replacePattern, "$&$&");
}
private static function EscapeArray(message_array:Array):Array {
var length:uint = message_array.length;
var i:uint = 0;
for (i; i < length; i++) {
message_array[i] = EscapeMessage(message_array[i]);
}
return message_array;
}
private static function EscapeObject(message_obj:Object):Object {
for (var name:String in message_obj) {
message_obj[name] = EscapeMessage(message_obj[name]);
}
return message_obj;
}
}
}

View File

@ -1,74 +0,0 @@
package {
import flash.net.FileReference;
internal class FileItem
{
private static var file_id_sequence:Number = 0; // tracks the file id sequence
private var postObject:Object;
public var file_reference:FileReference;
public var id:String;
public var index:Number = -1;
public var file_status:int = 0;
private var js_object:Object;
public static var FILE_STATUS_QUEUED:int = -1;
public static var FILE_STATUS_IN_PROGRESS:int = -2;
public static var FILE_STATUS_ERROR:int = -3;
public static var FILE_STATUS_SUCCESS:int = -4;
public static var FILE_STATUS_CANCELLED:int = -5;
public static var FILE_STATUS_NEW:int = -6; // This file status should never be sent to JavaScript
public function FileItem(file_reference:FileReference, control_id:String)
{
this.postObject = {};
this.file_reference = file_reference;
this.id = control_id + "_" + (FileItem.file_id_sequence++);
this.file_status = FileItem.FILE_STATUS_NEW;
this.js_object = {
id: this.id,
index: this.index,
post: this.GetPostObject()
};
// Cleanly attempt to retrieve the FileReference info
// this can fail and so is wrapped in try..catch
try {
this.js_object.name = this.file_reference.name;
this.js_object.size = this.file_reference.size;
this.js_object.type = this.file_reference.type;
this.js_object.creationdate = this.file_reference.creationDate;
this.js_object.modificationdate = this.file_reference.modificationDate;
} catch (ex:Error) {
this.file_status = FileItem.FILE_STATUS_ERROR;
}
this.js_object.filestatus = this.file_status;
}
public function AddParam(name:String, value:String):void {
this.postObject[name] = value;
}
public function RemoveParam(name:String):void {
delete this.postObject[name];
}
public function GetPostObject():Object {
return this.postObject;
}
// Create the simply file object that is passed to the browser
public function ToJavaScriptObject():Object {
this.js_object.file_status = this.file_status;
this.js_object.post = this.GetPostObject();
return this.js_object;
}
public function toString():String {
return "FileItem - ID: " + this.id;
}
}
}

View File

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<project>
<!-- Output SWF options -->
<output>
<movie disabled="False" />
<movie input="" />
<movie path="swfupload_f9.swf" />
<movie fps="1" />
<movie width="1" />
<movie height="1" />
<movie version="9" />
<movie background="#FFFFFF" />
</output>
<!-- Other classes to be compiled into your SWF -->
<classpaths>
<class path="." />
</classpaths>
<!-- Build options -->
<build>
<option accessible="False" />
<option allowSourcePathOverlap="False" />
<option benchmark="False" />
<option es="False" />
<option loadConfig="" />
<option optimize="True" />
<option showActionScriptWarnings="True" />
<option showBindingWarnings="True" />
<option showDeprecationWarnings="True" />
<option showUnusedTypeSelectorWarnings="True" />
<option strict="True" />
<option useNetwork="True" />
<option useResourceBundleMetadata="True" />
<option warnings="True" />
<option verboseStackTraces="False" />
<option additional="" />
<option customSDK="" />
</build>
<!-- SWC Include Libraries -->
<includeLibraries>
<!-- example: <element path="..." /> -->
</includeLibraries>
<!-- SWC Libraries -->
<libraryPaths>
<!-- example: <element path="..." /> -->
</libraryPaths>
<!-- External Libraries -->
<externalLibraryPaths>
<!-- example: <element path="..." /> -->
</externalLibraryPaths>
<!-- Runtime Shared Libraries -->
<rslPaths>
<!-- example: <element path="..." /> -->
</rslPaths>
<!-- Assets to embed into the output SWF -->
<library>
<!-- example: <asset path="..." id="..." update="..." glyphs="..." mode="..." place="..." sharepoint="..." /> -->
</library>
<!-- Class files to compile (other referenced classes will automatically be included) -->
<compileTargets>
<compile path="SWFUpload.as" />
</compileTargets>
<!-- Paths to exclude from the Project Explorer tree -->
<hiddenPaths>
<!-- example: <hidden path="..." /> -->
</hiddenPaths>
<!-- Executed before build -->
<preBuildCommand />
<!-- Executed after build -->
<postBuildCommand alwaysRun="True">deploy.bat</postBuildCommand>
<!-- Other project options -->
<options>
<option showHiddenPaths="False" />
<option testMovie="NewWindow" />
</options>
</project>

View File

@ -1,920 +0,0 @@
package {
/*
* Todo:
* I should look in to using array.splice to remove cancelled files from the array.
* Add GetFile(file_id) function that returns the FileItem js object for any file (defaults to current or first in queue).
* */
import flash.display.Stage;
import flash.display.Sprite;
import flash.net.FileReferenceList;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
import flash.events.*;
import flash.external.ExternalInterface;
import flash.system.Security;
import FileItem;
import ExternalCall;
public class SWFUpload extends Sprite {
// Cause SWFUpload to start as soon as the movie starts
public static function main():void
{
var SWFUpload:SWFUpload = new SWFUpload();
}
private const build_number:String = "SWFUPLOAD 2.0.1 FP9 2007-12-05 0001";
// State tracking variables
private var fileBrowserMany:FileReferenceList = new FileReferenceList();
private var fileBrowserOne:FileReference = null; // This isn't set because it can't be reused like the FileReferenceList. It gets setup in the SelectFile method
private var file_queue:Array = new Array(); // holds a list of all items that are to be uploaded.
private var current_file_item:FileItem = null; // the item that is currently being uploaded.
private var file_index:Array = new Array();
private var successful_uploads:Number = 0; // Tracks the uploads that have been completed
private var queue_errors:Number = 0; // Tracks files rejected during queueing
private var upload_errors:Number = 0; // Tracks files that fail upload
private var upload_cancelled:Number = 0; // Tracks number of cancelled files
private var queued_uploads:Number = 0; // Tracks the FileItems that are waiting to be uploaded.
private var valid_file_extensions:Array = new Array();// Holds the parsed valid extensions.
// Callbacks
private var flashReady_Callback:String;
private var fileDialogStart_Callback:String;
private var fileQueued_Callback:String;
private var fileQueueError_Callback:String;
private var fileDialogComplete_Callback:String;
private var uploadStart_Callback:String;
private var uploadProgress_Callback:String;
private var uploadError_Callback:String;
private var uploadSuccess_Callback:String;
private var uploadComplete_Callback:String;
private var debug_Callback:String;
// Values passed in from the HTML
private var movieName:String;
private var uploadURL:String;
private var filePostName:String;
private var uploadPostObject:Object;
private var fileTypes:String;
private var fileTypesDescription:String;
private var fileSizeLimit:Number;
private var fileUploadLimit:Number = 0;
private var fileQueueLimit:Number = 0;
private var debugEnabled:Boolean;
// Error code "constants"
// Size check constants
private var SIZE_TOO_BIG:Number = 1;
private var SIZE_ZERO_BYTE:Number = -1;
private var SIZE_OK:Number = 0;
// Queue errors
private var ERROR_CODE_QUEUE_LIMIT_EXCEEDED:Number = -100;
private var ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT:Number = -110;
private var ERROR_CODE_ZERO_BYTE_FILE:Number = -120;
private var ERROR_CODE_INVALID_FILETYPE:Number = -130;
// Upload Errors
private var ERROR_CODE_HTTP_ERROR:Number = -200;
private var ERROR_CODE_MISSING_UPLOAD_URL:Number = -210;
private var ERROR_CODE_IO_ERROR:Number = -220;
private var ERROR_CODE_SECURITY_ERROR:Number = -230;
private var ERROR_CODE_UPLOAD_LIMIT_EXCEEDED:Number = -240;
private var ERROR_CODE_UPLOAD_FAILED:Number = -250;
private var ERROR_CODE_SPECIFIED_FILE_ID_NOT_FOUND:Number = -260;
private var ERROR_CODE_FILE_VALIDATION_FAILED:Number = -270;
private var ERROR_CODE_FILE_CANCELLED:Number = -280;
private var ERROR_CODE_UPLOAD_STOPPED:Number = -290;
public function SWFUpload() {
Security.allowDomain("*"); // Allow uploading to any domain
// Keep Flash Player busy so it doesn't show the "flash script is running slowly" error
var counter:Number = 0;
root.addEventListener(Event.ENTER_FRAME, function ():void { if (++counter > 100) counter = 100; });
// Setup file FileReferenceList events
this.fileBrowserMany.addEventListener(Event.SELECT, this.Select_Many_Handler);
this.fileBrowserMany.addEventListener(Event.CANCEL, this.DialogCancelled_Handler);
// Get the move name
this.movieName = root.loaderInfo.parameters.movieName;
// **Configure the callbacks**
// The JavaScript tracks all the instances of SWFUpload on a page. We can access the instance
// associated with this SWF file using the movieName. Each callback is accessible by making
// a call directly to it on our instance. There is no error handling for undefined callback functions.
// A developer would have to deliberately remove the default functions,set the variable to null, or remove
// it from the init function.
this.flashReady_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].flashReady";
this.fileDialogStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogStart";
this.fileQueued_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueued";
this.fileQueueError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueueError";
this.fileDialogComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogComplete";
this.uploadStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadStart";
this.uploadProgress_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadProgress";
this.uploadError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadError";
this.uploadSuccess_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadSuccess";
this.uploadComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadComplete";
this.debug_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].debug";
// Get the Flash Vars
this.uploadURL = root.loaderInfo.parameters.uploadURL;
this.filePostName = root.loaderInfo.parameters.filePostName;
this.fileTypes = root.loaderInfo.parameters.fileTypes;
this.fileTypesDescription = root.loaderInfo.parameters.fileTypesDescription + " (" + this.fileTypes + ")";
this.loadPostParams(root.loaderInfo.parameters.params);
if (!this.filePostName) {
this.filePostName = "Filedata";
}
if (!this.fileTypes) {
this.fileTypes = "*.*";
}
if (!this.fileTypesDescription) {
this.fileTypesDescription = "All Files";
}
this.LoadFileExensions(this.fileTypes);
try {
this.debugEnabled = root.loaderInfo.parameters.debugEnabled == "true" ? true : false;
} catch (ex:Object) {
this.debugEnabled = false;
}
try {
this.fileSizeLimit = Number(root.loaderInfo.parameters.fileSizeLimit);
if (this.fileSizeLimit < 0) this.fileSizeLimit = 0;
} catch (ex:Object) {
this.fileSizeLimit = 0;
}
try {
this.fileUploadLimit = Number(root.loaderInfo.parameters.fileUploadLimit);
if (this.fileUploadLimit < 0) this.fileUploadLimit = 0;
} catch (ex:Object) {
this.fileUploadLimit = 0;
}
try {
this.fileQueueLimit = Number(root.loaderInfo.parameters.fileQueueLimit);
if (this.fileQueueLimit < 0) this.fileQueueLimit = 0;
} catch (ex:Object) {
this.fileQueueLimit = 0;
}
// Set the queue limit to match the upload limit when the queue limit is bigger than the upload limit
if (this.fileQueueLimit > this.fileUploadLimit && this.fileUploadLimit != 0) this.fileQueueLimit = this.fileUploadLimit;
// The the queue limit is unlimited and the upload limit is not then set the queue limit to the upload limit
if (this.fileQueueLimit == 0 && this.fileUploadLimit != 0) this.fileQueueLimit = this.fileUploadLimit;
try {
ExternalInterface.addCallback("SelectFile", this.SelectFile);
ExternalInterface.addCallback("SelectFiles", this.SelectFiles);
ExternalInterface.addCallback("StartUpload", this.StartUpload);
ExternalInterface.addCallback("ReturnUploadStart", this.ReturnUploadStart);
ExternalInterface.addCallback("StopUpload", this.StopUpload);
ExternalInterface.addCallback("CancelUpload", this.CancelUpload);
ExternalInterface.addCallback("GetStats", this.GetStats);
ExternalInterface.addCallback("SetStats", this.SetStats);
ExternalInterface.addCallback("GetFile", this.GetFile);
ExternalInterface.addCallback("GetFileByIndex", this.GetFileByIndex);
ExternalInterface.addCallback("AddFileParam", this.AddFileParam);
ExternalInterface.addCallback("RemoveFileParam", this.RemoveFileParam);
ExternalInterface.addCallback("SetUploadURL", this.SetUploadURL);
ExternalInterface.addCallback("SetPostParams", this.SetPostParams);
ExternalInterface.addCallback("SetFileTypes", this.SetFileTypes);
ExternalInterface.addCallback("SetFileSizeLimit", this.SetFileSizeLimit);
ExternalInterface.addCallback("SetFileUploadLimit", this.SetFileUploadLimit);
ExternalInterface.addCallback("SetFileQueueLimit", this.SetFileQueueLimit);
ExternalInterface.addCallback("SetFilePostName", this.SetFilePostName);
ExternalInterface.addCallback("SetDebugEnabled", this.SetDebugEnabled);
} catch (ex:Error) {
this.Debug("Callbacks where not set.");
}
this.Debug("SWFUpload Init Complete");
this.PrintDebugInfo();
// Do some feature detection
if (flash.net.FileReferenceList && flash.net.FileReference && flash.net.URLRequest && flash.external.ExternalInterface && flash.external.ExternalInterface.available && DataEvent.UPLOAD_COMPLETE_DATA) {
ExternalCall.Simple(this.flashReady_Callback);
} else {
this.Debug("Feature Detection Failed");
}
}
/* *****************************************
* FileReference Event Handlers
* *************************************** */
private function DialogCancelled_Handler(event:Event):void {
this.Debug("Event: fileDialogComplete: File Dialog window cancelled.");
ExternalCall.FileDialogComplete(this.fileDialogComplete_Callback, 0);
}
private function FileProgress_Handler(event:ProgressEvent):void {
this.Debug("Event: uploadProgress: File ID: " + this.current_file_item.id + ". Bytes: " + event.bytesLoaded + ". Total: " + event.bytesTotal);
ExternalCall.UploadProgress(this.uploadProgress_Callback, this.current_file_item.ToJavaScriptObject(), event.bytesLoaded, event.bytesTotal);
}
private function ServerData_Handler(event:DataEvent):void {
this.successful_uploads++;
this.current_file_item.file_status = FileItem.FILE_STATUS_SUCCESS;
this.Debug("Event: uploadSuccess: File ID: " + this.current_file_item.id + " Data: " + event.data);
ExternalCall.UploadSuccess(this.uploadSuccess_Callback, this.current_file_item.ToJavaScriptObject(), event.data);
this.UploadComplete();
}
private function HTTPError_Handler(event:HTTPStatusEvent):void {
this.upload_errors++;
this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR;
this.Debug("Event: uploadError: HTTP ERROR : File ID: " + this.current_file_item.id + ". HTTP Status: " + event.status + ".");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_HTTP_ERROR, this.current_file_item.ToJavaScriptObject(), event.status.toString());
this.UploadComplete();
}
// Note: Flash Player does not support Uploads that require authentication. Attempting this will trigger an
// IO Error or it will prompt for a username and password and the crash the browser (FireFox/Opera)
private function IOError_Handler(event:IOErrorEvent):void {
this.upload_errors++;
this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR;
if(!this.uploadURL.length) {
this.Debug("Event: uploadError : IO Error : File ID: " + this.current_file_item.id + ". Upload URL string is empty.");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_MISSING_UPLOAD_URL, this.current_file_item.ToJavaScriptObject(), event.text);
} else {
this.Debug("Event: uploadError : IO Error : File ID: " + this.current_file_item.id + ". IO Error.");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_IO_ERROR, this.current_file_item.ToJavaScriptObject(), event.text);
}
this.UploadComplete();
}
private function SecurityError_Handler(event:SecurityErrorEvent):void {
this.upload_errors++;
this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR;
this.Debug("Event: uploadError : Security Error : File Number: " + this.current_file_item.id + ". Error:" + event.text);
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_SECURITY_ERROR, this.current_file_item.ToJavaScriptObject(), event.text);
this.UploadComplete();
}
private function Select_Many_Handler(event:Event):void {
this.Select_Handler(this.fileBrowserMany.fileList);
}
private function Select_One_Handler(event:Event):void {
var fileArray:Array = new Array(1);
fileArray[0] = this.fileBrowserOne;
this.Select_Handler(fileArray);
}
private function Select_Handler(file_reference_list:Array):void {
this.Debug("Select Handler: Files Selected from Dialog. Processing file list");
// Determine how many queue slots are remaining (check the unlimited (0) settings, successful uploads and queued uploads)
var queue_slots_remaining:Number = 0;
if (this.fileUploadLimit == 0) {
queue_slots_remaining = this.fileQueueLimit == 0 ? file_reference_list.length : (this.fileQueueLimit - this.queued_uploads); // If unlimited queue make the allowed size match however many files were selected.
} else {
var remaining_uploads:Number = this.fileUploadLimit - this.successful_uploads - this.queued_uploads;
if (remaining_uploads < 0) remaining_uploads = 0;
if (this.fileQueueLimit == 0 || this.fileQueueLimit >= remaining_uploads) {
queue_slots_remaining = remaining_uploads;
} else if (this.fileQueueLimit < remaining_uploads) {
queue_slots_remaining = this.fileQueueLimit;
}
}
// Check if the number of files selected is greater than the number allowed to queue up.
if (queue_slots_remaining < file_reference_list.length) {
this.Debug("Event: fileQueueError : Selected Files (" + file_reference_list.length + ") exceeds remaining Queue size (" + queue_slots_remaining + ").");
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_QUEUE_LIMIT_EXCEEDED, null, queue_slots_remaining.toString());
} else {
// Process each selected file
for (var i:Number = 0; i < file_reference_list.length; i++) {
var file_item:FileItem = new FileItem(file_reference_list[i], this.movieName);
// Add the file to the index
file_item.index = this.file_index.length;
this.file_index[file_item.index] = file_item;
// Verify that the file is accessible. Zero byte files and possibly other conditions can cause a file to be inaccessible.
var jsFileObj:Object = file_item.ToJavaScriptObject();
var is_valid_file_reference:Boolean = (jsFileObj.filestatus !== FileItem.FILE_STATUS_ERROR);
if (is_valid_file_reference) {
// Check the size, if it's within the limit add it to the upload list.
var size_result:Number = this.CheckFileSize(file_item);
var is_valid_filetype:Boolean = this.CheckFileType(file_item);
if(size_result == this.SIZE_OK && is_valid_filetype) {
this.Debug("Event: fileQueued : File ID: " + file_item.id);
file_item.file_status = FileItem.FILE_STATUS_QUEUED;
this.file_queue.push(file_item);
this.queued_uploads++;
ExternalCall.FileQueued(this.fileQueued_Callback, file_item.ToJavaScriptObject());
}
else if (!is_valid_filetype) {
file_item.file_reference = null; // Cleanup the object
this.Debug("Event: fileQueueError : File not of a valid type.");
this.queue_errors++;
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_INVALID_FILETYPE, file_item.ToJavaScriptObject(), "File is not an allowed file type.");
}
else if (size_result == this.SIZE_TOO_BIG) {
file_item.file_reference = null; // Cleanup the object
this.Debug("Event: fileQueueError : File exceeds size limit.");
this.queue_errors++;
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT, file_item.ToJavaScriptObject(), "File size exceeds allowed limit.");
} else if (size_result == this.SIZE_ZERO_BYTE) {
file_item.file_reference = null; // Cleanup the object
this.Debug("Event: fileQueueError : File is zero bytes.");
this.queue_errors++;
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_ZERO_BYTE_FILE, file_item.ToJavaScriptObject(), "File is zero bytes and cannot be uploaded.");
}
} else {
file_item.file_reference = null; // Cleanup the object
this.Debug("Event: fileQueueError : File is zero bytes or FileReference is invalid.");
this.queue_errors++;
ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_ZERO_BYTE_FILE, file_item.ToJavaScriptObject(), "File is zero bytes or cannot be accessed and cannot be uploaded.");
}
}
}
this.Debug("Event: fileDialogComplete : Finished adding files");
ExternalCall.FileDialogComplete(this.fileDialogComplete_Callback, file_reference_list.length);
}
/* ****************************************************************
Externally exposed functions
****************************************************************** */
// Opens a file browser dialog that allows one file to be selected.
private function SelectFile():void {
this.fileBrowserOne = new FileReference();
this.fileBrowserOne.addEventListener(Event.SELECT, this.Select_One_Handler);
this.fileBrowserOne.addEventListener(Event.CANCEL, this.DialogCancelled_Handler);
// Default file type settings
var allowed_file_types:String = "*.*";
var allowed_file_types_description:String = "All Files";
// Get the instance settings
if (this.fileTypes.length > 0) allowed_file_types = this.fileTypes;
if (this.fileTypesDescription.length > 0) allowed_file_types_description = this.fileTypesDescription;
this.Debug("Event: fileDialogStart : Browsing files. Single Select. Allowed file types: " + allowed_file_types);
ExternalCall.Simple(this.fileDialogStart_Callback);
this.fileBrowserOne.browse([new FileFilter(allowed_file_types_description, allowed_file_types)]);
}
// Opens a file browser dialog that allows multiple files to be selected.
private function SelectFiles():void {
var allowed_file_types:String = "*.*";
var allowed_file_types_description:String = "All Files";
if (this.fileTypes.length > 0) allowed_file_types = this.fileTypes;
if (this.fileTypesDescription.length > 0) allowed_file_types_description = this.fileTypesDescription;
this.Debug("Event: fileDialogStart : Browsing files. Multi Select. Allowed file types: " + allowed_file_types);
ExternalCall.Simple(this.fileDialogStart_Callback);
this.fileBrowserMany.browse([new FileFilter(allowed_file_types_description, allowed_file_types)]);
}
// Starts uploading. Checks to see if a file is currently uploading and, if not, starts the upload.
private function StartUpload(file_id:String = ""):void {
if (this.current_file_item == null) {
this.Debug("StartUpload(): Starting Upload: " + (file_id ? "File ID:" + file_id : "First file in queue"));
this.StartFile(file_id);
} else {
this.Debug("StartUpload(): Upload run already in progress");
}
}
// Cancel the current upload and stops. Doesn't advance the upload pointer. The current file is requeued at the beginning.
private function StopUpload():void {
if (this.current_file_item != null) {
// Cancel the upload and re-queue the FileItem
this.current_file_item.file_reference.cancel();
this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED;
// Remove the event handlers
this.removeFileReferenceEventListeners(this.current_file_item);
this.file_queue.unshift(this.current_file_item);
var js_object:Object = this.current_file_item.ToJavaScriptObject();
this.current_file_item = null;
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_STOPPED, js_object, "Upload Stopped");
ExternalCall.UploadComplete(this.uploadComplete_Callback, js_object);
this.Debug("StopUpload(): upload stopped.");
} else {
this.Debug("StopUpload(): Upload run not in progress");
}
}
/* Cancels the upload specified by file_id
* If the file is currently uploading it is cancelled and the uploadComplete
* event gets called.
* If the file is not currently uploading then only the uploadCancelled event is fired.
* */
private function CancelUpload(file_id:String):void {
var file_item:FileItem = null;
// Check the current file item
if (this.current_file_item != null && (this.current_file_item.id == file_id || !file_id)) {
this.current_file_item.file_reference.cancel();
this.current_file_item.file_status = FileItem.FILE_STATUS_CANCELLED;
this.upload_cancelled++;
this.Debug("Event: fileCancelled: File ID: " + this.current_file_item.id + ". Cancelling current upload");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, this.current_file_item.ToJavaScriptObject(), "File Upload Cancelled.");
this.UploadComplete(); // <-- this advanced the upload to the next file
} else if (file_id) {
// Find the file in the queue
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
// Remove the file from the queue
file_item = FileItem(this.file_queue[file_index]);
file_item.file_status = FileItem.FILE_STATUS_CANCELLED;
this.file_queue[file_index] = null;
this.queued_uploads--;
this.upload_cancelled++;
// Cancel the file (just for good measure) and make the callback
file_item.file_reference.cancel();
this.removeFileReferenceEventListeners(file_item);
file_item.file_reference = null;
this.Debug("Event: uploadError : " + file_item.id + ". Cancelling queued upload");
this.Debug("Event: uploadError : " + file_item.id + ". Cancelling queued upload");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, file_item.ToJavaScriptObject(), "File Cancelled");
// Get rid of the file object
file_item = null;
}
} else {
// Get the first file and cancel it
while (this.file_queue.length > 0 && file_item == null) {
// Check that File Reference is valid (if not make sure it's deleted and get the next one on the next loop)
file_item = FileItem(this.file_queue.shift()); // Cast back to a FileItem
if (typeof(file_item) == "undefined") {
file_item = null;
continue;
}
}
if (file_item != null) {
file_item.file_status = FileItem.FILE_STATUS_CANCELLED;
this.queued_uploads--;
this.upload_cancelled++;
// Cancel the file (just for good measure) and make the callback
file_item.file_reference.cancel();
this.removeFileReferenceEventListeners(file_item);
file_item.file_reference = null;
this.Debug("Event: uploadError : " + file_item.id + ". Cancelling queued upload");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, file_item.ToJavaScriptObject(), "File Cancelled");
// Get rid of the file object
file_item = null;
}
}
}
private function GetStats():Object {
return {
in_progress : this.current_file_item == null ? 0 : 1,
files_queued : this.queued_uploads,
successful_uploads : this.successful_uploads,
upload_errors : this.upload_errors,
upload_cancelled : this.upload_cancelled,
queue_errors : this.queue_errors
};
}
private function SetStats(stats:Object):void {
this.successful_uploads = typeof(stats["successful_uploads"]) === "Number" ? stats["successful_uploads"] : this.successful_uploads;
this.upload_errors = typeof(stats["upload_errors"]) === "Number" ? stats["upload_errors"] : this.upload_errors;
this.upload_cancelled = typeof(stats["upload_cancelled"]) === "Number" ? stats["upload_cancelled"] : this.upload_cancelled;
this.queue_errors = typeof(stats["queue_errors"]) === "Number" ? stats["queue_errors"] : this.queue_errors;
}
private function GetFile(file_id:String):Object {
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
var file:FileItem = this.file_queue[file_index];
} else {
if (this.current_file_item != null) {
file = this.current_file_item;
} else {
for (var i:Number = 0; i < this.file_queue.length; i++) {
file = this.file_queue[i];
if (file != null) break;
}
}
}
if (file == null) {
return null;
} else {
return file.ToJavaScriptObject();
}
}
private function GetFileByIndex(index:Number):Object {
if (index < 0 || index > this.file_index.length - 1) {
return null;
} else {
return this.file_index[index].ToJavaScriptObject();
}
}
private function AddFileParam(file_id:String, name:String, value:String):Boolean {
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
var file_item:FileItem = FileItem(this.file_queue[file_index]);
file_item.AddParam(name, value);
return true;
} else {
return false;
}
}
private function RemoveFileParam(file_id:String, name:String):Boolean {
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
var file_item:FileItem = FileItem(this.file_queue[file_index]);
file_item.RemoveParam(name);
return true;
} else {
return false;
}
}
private function SetUploadURL(url:String):void {
if (typeof(url) !== "undefined" && url !== "") {
this.uploadURL = url;
}
}
private function SetPostParams(post_object:Object):void {
if (typeof(post_object) !== "undefined" && post_object !== null) {
this.uploadPostObject = post_object;
}
}
private function SetFileTypes(types:String, description:String):void {
this.fileTypes = types;
this.fileTypesDescription = description;
this.LoadFileExensions(this.fileTypes);
}
private function SetFileSizeLimit(bytes:Number):void {
if (bytes < 0) bytes = 0;
this.fileSizeLimit = bytes;
}
private function SetFileUploadLimit(file_upload_limit:Number):void {
if (file_upload_limit < 0) file_upload_limit = 0;
this.fileUploadLimit = file_upload_limit;
}
private function SetFileQueueLimit(file_queue_limit:Number):void {
if (file_queue_limit < 0) file_queue_limit = 0;
this.fileQueueLimit = file_queue_limit;
}
private function SetFilePostName(file_post_name:String):void {
if (file_post_name != "") {
this.filePostName = file_post_name;
}
}
private function SetDebugEnabled(debug_enabled:Boolean):void {
this.debugEnabled = debug_enabled;
}
/* *************************************************************
File processing and handling functions
*************************************************************** */
//
private function StartFile(file_id:String = ""):void {
// Only upload a file uploads are being processed.
// startFile could be called by a file cancellation even when we aren't currently uploading
if (this.current_file_item != null) {
this.Debug("StartFile(): Upload already in progress. Not starting another upload.");
}
this.Debug("StartFile: " + (file_id ? "File ID: " + file_id : "First file in queue"));
// Check the upload limit
if (this.successful_uploads >= this.fileUploadLimit && this.fileUploadLimit != 0) {
this.Debug("Event: uploadError : Upload limit reached. No more files can be uploaded.");
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_LIMIT_EXCEEDED, null, "The upload limit has been reached.");
this.current_file_item = null;
return;
}
// Get the next file to upload
if (!file_id) {
while (this.file_queue.length > 0 && this.current_file_item == null) {
// Check that File Reference is valid (if not make sure it's deleted and get the next one on the next loop)
this.current_file_item = FileItem(this.file_queue.shift()); // Cast back to a FileItem
if (typeof(this.current_file_item) == "undefined") {
this.current_file_item = null;
continue;
}
}
} else {
var file_index:Number = this.FindIndexInFileQueue(file_id);
if (file_index >= 0) {
// Set the file as the current upload and remove it from the queue
this.current_file_item = FileItem(this.file_queue[file_index]);
this.file_queue[file_index] = null;
} else {
this.Debug("Event: uploadError : File ID not found in queue: " + file_id);
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_SPECIFIED_FILE_ID_NOT_FOUND, null, "File ID not queued.");
}
}
// Start the upload if we found an item to upload
if (this.current_file_item != null) {
// Begin the upload
this.Debug("Event: uploadStart : File ID: " + this.current_file_item.id);
ExternalCall.UploadStart(this.uploadStart_Callback, this.current_file_item.ToJavaScriptObject());
}
// Otherwise we've would have looped through all the FileItems. This means the queue is empty)
else {
this.Debug("startFile(): No File Reference found. There are no files left to upload.\nstartFile(): Ending upload run.");
}
}
// This starts the upload when the user returns TRUE from the uploadStart event. Rather than just have the value returned from
// the function we do a return function call so we can use the setTimeout work-around for Flash/JS circular calls.
private function ReturnUploadStart(start_upload:Boolean):void {
if (this.current_file_item == null) {
this.Debug("ReturnUploadStart called but file was no longer queued. This is okay if the file was stopped or cancelled.");
return;
}
if (start_upload) {
try {
// Set the event handlers
this.current_file_item.file_reference.addEventListener(ProgressEvent.PROGRESS, this.FileProgress_Handler);
this.current_file_item.file_reference.addEventListener(IOErrorEvent.IO_ERROR, this.IOError_Handler);
this.current_file_item.file_reference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.SecurityError_Handler);
this.current_file_item.file_reference.addEventListener(HTTPStatusEvent.HTTP_STATUS, this.HTTPError_Handler);
this.current_file_item.file_reference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, this.ServerData_Handler);
// Upload the file
var request:URLRequest = this.BuildRequest();
this.Debug("startFile(): File Reference found. File accepted by startUpload event. Starting upload to " + request.url + " for File ID: " + this.current_file_item.id);
this.current_file_item.file_reference.upload(request, this.filePostName, false);
} catch (ex:Error) {
this.upload_errors++;
this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR;
var message:String = ex.errorID + "\n" + ex.name + "\n" + ex.message + "\n" + ex.getStackTrace();
this.Debug("Event: uploadError(): Unhandled exception: " + message);
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_FAILED, this.current_file_item.ToJavaScriptObject(), message);
this.UploadComplete();
}
this.current_file_item.file_status = FileItem.FILE_STATUS_IN_PROGRESS;
} else {
this.Debug("Event: uploadError : Call to uploadStart returned false. Not uploading file.");
// Remove the event handlers
this.removeFileReferenceEventListeners(this.current_file_item);
// Re-queue the FileItem
this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED;
var js_object:Object = this.current_file_item.ToJavaScriptObject();
this.file_queue.unshift(this.current_file_item);
this.current_file_item = null;
ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_VALIDATION_FAILED, js_object, "Call to uploadStart return false. Not uploading file.");
ExternalCall.UploadComplete(this.uploadComplete_Callback, js_object);
this.Debug("startFile(): upload rejected by startUpload event. File re-queued.");
}
}
// Completes the file upload by deleting it's reference, advancing the pointer.
// Once this event files a new upload can be started.
private function UploadComplete():void {
var jsFileObj:Object = this.current_file_item.ToJavaScriptObject();
this.removeFileReferenceEventListeners(this.current_file_item);
this.current_file_item.file_reference = null;
this.current_file_item = null;
this.queued_uploads--;
this.Debug("Event: uploadComplete : Upload cycle complete.");
ExternalCall.UploadComplete(this.uploadComplete_Callback, jsFileObj);
}
/* *************************************************************
Utility Functions
*************************************************************** */
// Check the size of the file against the allowed file size. If it is less the return TRUE. If it is too large return FALSE
private function CheckFileSize(file_item:FileItem):Number {
if (file_item.file_reference.size == 0) {
return this.SIZE_ZERO_BYTE;
} else if (this.fileSizeLimit != 0 && file_item.file_reference.size > (this.fileSizeLimit * 1000)) {
return this.SIZE_TOO_BIG;
} else {
return this.SIZE_OK;
}
}
private function CheckFileType(file_item:FileItem):Boolean {
// If no extensions are defined then a *.* was passed and the check is unnecessary
if (this.valid_file_extensions.length == 0) {
return true;
}
var fileRef:FileReference = file_item.file_reference;
var last_dot_index:Number = fileRef.name.lastIndexOf(".");
var extension:String = "";
if (last_dot_index >= 0) {
extension = fileRef.name.substr(last_dot_index + 1).toLowerCase();
}
var is_valid_filetype:Boolean = false;
for (var i:Number=0; i < this.valid_file_extensions.length; i++) {
if (String(this.valid_file_extensions[i]) == extension) {
is_valid_filetype = true;
break;
}
}
return is_valid_filetype;
}
private function BuildRequest():URLRequest {
// Create the request object
var request:URLRequest = new URLRequest();
request.method = URLRequestMethod.POST;
request.url = this.uploadURL;
var file_post:Object = this.current_file_item.GetPostObject();
var key:String;
var post:URLVariables = new URLVariables();
for (key in this.uploadPostObject) {
this.Debug("Global Post Item: " + key + "=" + this.uploadPostObject[key]);
if (this.uploadPostObject.hasOwnProperty(key)) {
post[key] = this.uploadPostObject[key];
}
}
for (key in file_post) {
this.Debug("File Post Item: " + key + "=" + this.uploadPostObject[key]);
if (file_post.hasOwnProperty(key)) {
post[key] = file_post[key];
}
}
request.data = post;
return request;
}
private function Debug(msg:String):void {
if (this.debugEnabled) {
var lines:Array = msg.split("\n");
for (var i:Number=0; i < lines.length; i++) {
lines[i] = "SWF DEBUG: " + lines[i];
}
try {
ExternalCall.Debug(this.debug_Callback, lines.join("\n"));
} catch (ex:Error) {
// pretend nothing happened
}
}
}
private function PrintDebugInfo():void {
var debug_info:String = "\n----- SWF DEBUG OUTPUT ----\n";
debug_info += "Build Number: " + this.build_number + "\n";
debug_info += "movieName: " + this.movieName + "\n";
debug_info += "Upload URL: " + this.uploadURL + "\n";
debug_info += "File Types String: " + this.fileTypes + "\n";
debug_info += "Parsed File Types: " + this.valid_file_extensions.toString() + "\n";
debug_info += "File Types Description: " + this.fileTypesDescription + "\n";
debug_info += "File Size Limit: " + this.fileSizeLimit + "\n";
debug_info += "File Upload Limit: " + this.fileUploadLimit + "\n";
debug_info += "File Queue Limit: " + this.fileQueueLimit + "\n";
debug_info += "Post Params:\n";
for (var key:String in this.uploadPostObject) {
debug_info += " " + key + "=" + this.uploadPostObject[key] + "\n";
}
debug_info += "----- END SWF DEBUG OUTPUT ----\n";
this.Debug(debug_info);
}
private function FindIndexInFileQueue(file_id:String):Number {
for (var i:Number = 0; i<this.file_queue.length; i++) {
var item:FileItem = this.file_queue[i];
if (item != null && item.id == file_id) return i;
}
return -1;
}
// Parse the file extensions in to an array so we can validate them agains
// the files selected later.
private function LoadFileExensions(filetypes:String):void {
var extensions:Array = filetypes.split(";");
this.valid_file_extensions = new Array();
for (var i:Number=0; i < extensions.length; i++) {
var extension:String = String(extensions[i]);
var dot_index:Number = extension.lastIndexOf(".");
if (dot_index >= 0) {
extension = extension.substr(dot_index + 1).toLowerCase();
} else {
extension = extension.toLowerCase();
}
// If one of the extensions is * then we allow all files
if (extension == "*") {
this.valid_file_extensions = new Array();
break;
}
this.valid_file_extensions.push(extension);
}
}
private function loadPostParams(param_string:String):void {
var post_object:Object = {};
if (param_string != null) {
var name_value_pairs:Array = param_string.split("&");
for (var i:Number = 0; i < name_value_pairs.length; i++) {
var name_value:String = String(name_value_pairs[i]);
var index_of_equals:Number = name_value.indexOf("=");
if (index_of_equals > 0) {
post_object[decodeURIComponent(name_value.substring(0, index_of_equals))] = decodeURIComponent(name_value.substr(index_of_equals + 1));
}
}
}
this.uploadPostObject = post_object;
}
private function removeFileReferenceEventListeners(file_item:FileItem):void {
if (file_item != null && file_item.file_reference != null) {
file_item.file_reference.removeEventListener(ProgressEvent.PROGRESS, this.FileProgress_Handler);
file_item.file_reference.removeEventListener(IOErrorEvent.IO_ERROR, this.IOError_Handler);
file_item.file_reference.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.SecurityError_Handler);
file_item.file_reference.removeEventListener(HTTPStatusEvent.HTTP_STATUS, this.HTTPError_Handler);
file_item.file_reference.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, this.ServerData_Handler);
}
}
}
}

View File

@ -1,3 +0,0 @@
@echo off
copy ..\swfupload.js ..\..\demos\swfupload
copy swfupload_f9.swf ..\..\demos\swfupload

Binary file not shown.

View File

@ -1,11 +0,0 @@
/**
* mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/
*
* SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*
* SWFUpload Revision 7.0 is (c) 2007 Jake Roberts and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*/

View File

@ -1,50 +0,0 @@
/*
Cookie Plug-in
This plug in automatically gets all the cookies for this site and adds them to the post_params.
Cookies are loaded only on initialization. The refreshCookies function can be called to update the post_params.
The cookies will override any other post params with the same name.
*/
var SWFUpload;
if (typeof(SWFUpload) === "function") {
SWFUpload.prototype.initSettings = function (old_initSettings) {
return function (init_settings) {
if (typeof(old_initSettings) === "function") {
old_initSettings.call(this, init_settings);
}
this.refreshCookies(false); // The false parameter must be sent since SWFUpload has not initialzed at this point
};
}(SWFUpload.prototype.initSettings);
// refreshes the post_params and updates SWFUpload. The send_to_flash parameters is optional and defaults to True
SWFUpload.prototype.refreshCookies = function (send_to_flash) {
if (send_to_flash !== false) send_to_flash = true;
// Get the post_params object
var post_params = this.getSetting("post_params");
// Get the cookies
var i, cookie_array = document.cookie.split(';'), ca_length = cookie_array.length, c, eq_index, name, value;
for(i = 0; i < ca_length; i++) {
c = cookie_array[i];
// Left Trim spaces
while (c.charAt(0) == " ") {
c = c.substring(1, c.length);
}
eq_index = c.indexOf("=");
if (eq_index > 0) {
name = c.substring(0, eq_index);
value = c.substring(eq_index+1);
post_params[name] = value;
}
}
if (send_to_flash) {
this.setPostParams(post_params);
}
};
}

View File

@ -1,102 +0,0 @@
/*
DocumentReady Plug-in
This plugin loads SWFUpload as soon as the document is ready. You should not load SWFUpload inside window.onload using this plugin.
You can also chain other functions by calling SWFUpload.DocumentReady(your function).
Warning: Embedded Ads or other scripts that overwrite window.onload or use their own document ready functions may interfer with this plugin. You
should not set window.onload when using this plugin.
Usage Example:
var swfu = new SWFUpload(your settings object);
SWFUpload.DocumentReady(function () { alert('Document Ready!'; });
*/
var SWFUpload;
if (typeof(SWFUpload) === "function") {
// Override iniSWFUpload so SWFUpload gets inited when the document is ready rather than immediately
SWFUpload.prototype.initSWFUpload = function (old_initSWFUpload) {
return function (init_settings) {
var self = this;
if (typeof(old_initSWFUpload) === "function") {
SWFUpload.DocumentReady(function () {
old_initSWFUpload.call(self, init_settings);
});
}
}
}(SWFUpload.prototype.initSWFUpload);
// The DocumentReady function adds the passed in function to
// the functions that will be executed when the document is ready/loaded
SWFUpload.DocumentReady = function (fn) {
// Add the function to the chain
SWFUpload.DocumentReady.InternalOnloadChain = function (previous_link_fn) {
return function () {
if (typeof(previous_link_fn) === "function") {
previous_link_fn();
}
fn();
};
}(SWFUpload.DocumentReady.InternalOnloadChain);
};
SWFUpload.DocumentReady.InternalOnloadChain = null;
SWFUpload.DocumentReady.Onload = function () {
// Execute the onload function chain
if (typeof(SWFUpload.DocumentReady.InternalOnloadChain) === "function") {
SWFUpload.DocumentReady.InternalOnloadChain();
}
};
SWFUpload.DocumentReady.SetupComplete = false;
/* ********************************************
This portion of the code gets executed as soon it is loaded.
It binds the proper event for executing JavaScript is
early as possible. This is a per browser function and so
some browser sniffing is used.
This solution still has the "exposed" issue (See the Global Delegation section at http://peter.michaux.ca/article/553 )
Base solution from http://dean.edwards.name/weblog/2006/06/again/ and http://dean.edwards.name/weblog/2005/09/busted/
******************************************** */
if (!SWFUpload.DocumentReady.SetupComplete) {
// for Internet Explorer (using conditional comments)
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
SWFUpload.DocumentReady.Onload(); // call the onload handler
}
};
SWFUpload.DocumentReady.SetupComplete = true;
/*@end @*/
}
if (!SWFUpload.DocumentReady.SetupComplete && /WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
clearInterval(_timer);
SWFUpload.DocumentReady.Onload(); // call the onload handler
}
}, 10);
SWFUpload.DocumentReady.SetupComplete = true;
}
/* for Mozilla */
if (!SWFUpload.DocumentReady.SetupComplete && document.addEventListener) {
document.addEventListener("DOMContentLoaded", SWFUpload.DocumentReady.Onload, false);
SWFUpload.DocumentReady.SetupComplete = true;
}
/* for other browsers */
if (!SWFUpload.DocumentReady.SetupComplete) {
window.onload = SWFUpload.DocumentReady.Onload;
SWFUpload.DocumentReady.SetupComplete = true;
}
}

View File

@ -1,63 +0,0 @@
/*
SWFUpload Graceful Degradation Plug-in
This plugin allows SWFUpload to display only if it is loaded successfully. Otherwise a default form is left displayed.
Usage:
To use this plugin create two HTML containers. Each should have an ID defined. One container should hold the SWFUpload UI. The other should hold the degraded UI.
The SWFUpload container should have its CSS "display" property set to "none".
If SWFUpload loads successfully the SWFUpload container will be displayed ("display" set to "block") and the
degraded container will be hidden ("display" set to "none").
Use the settings "swfupload_element_id" and "degraded_element_id" to indicate your container IDs. The default values are "swfupload_container" and "degraded_container".
*/
var SWFUpload;
if (typeof(SWFUpload) === "function") {
SWFUpload.gracefulDegradation = {};
SWFUpload.prototype.initSettings = function (old_initSettings) {
return function (init_settings) {
if (typeof(old_initSettings) === "function") {
old_initSettings.call(this, init_settings);
}
this.addSetting("swfupload_element_id", init_settings.swfupload_element_id, "swfupload_container");
this.addSetting("degraded_element_id", init_settings.degraded_element_id, "degraded_container");
this.addSetting("user_swfUploadLoaded_handler", init_settings.swfupload_loaded_handler, SWFUpload.swfUploadLoaded);
this.swfUploadLoaded_handler = SWFUpload.gracefulDegradation.swfUploadLoaded;
};
}(SWFUpload.prototype.initSettings);
SWFUpload.gracefulDegradation.swfUploadLoaded = function () {
var swfupload_container_id, swfupload_container, degraded_container_id, degraded_container, user_swfUploadLoaded_handler;
try {
swfupload_element_id = this.getSetting("swfupload_element_id");
degraded_element_id = this.getSetting("degraded_element_id");
// Show the UI container
swfupload_container = document.getElementById(swfupload_element_id);
if (swfupload_container !== null) {
swfupload_container.style.display = "block";
// Now take care of hiding the degraded UI
degraded_container = document.getElementById(degraded_element_id);
if (degraded_container !== null) {
degraded_container.style.display = "none";
}
}
} catch (ex) {
this.debug(ex);
}
user_swfUploadLoaded_handler = this.getSetting("user_swfUploadLoaded_handler");
if (typeof(user_swfUploadLoaded_handler) === "function") {
user_swfUploadLoaded_handler.apply(this);
}
};
}

View File

@ -1,58 +0,0 @@
/*
Queue Plug-in
Features:
cancelQueue method for cancelling the entire queue.
All queued files are uploaded when startUpload() is called.
If false is returned from uploadComplete then the queue upload is stopped. If false is not returned (strict comparison) then the queue upload is continued.
*/
var SWFUpload;
if (typeof(SWFUpload) === "function") {
SWFUpload.queue = {};
SWFUpload.prototype.initSettings = function (old_initSettings) {
return function (init_settings) {
if (typeof(old_initSettings) === "function") {
old_initSettings.call(this, init_settings);
}
this.customSettings.queue_cancelled_flag = false;
this.addSetting("user_upload_complete_handler", init_settings.upload_complete_handler, SWFUpload.uploadComplete);
this.uploadComplete_handler = SWFUpload.queue.uploadComplete;
};
}(SWFUpload.prototype.initSettings);
SWFUpload.prototype.cancelQueue = function () {
var stats = this.getStats();
this.customSettings.queue_cancelled_flag = false;
if (stats.in_progress > 0) {
this.customSettings.queue_cancelled_flag = true;
}
while(stats.files_queued > 0) {
this.cancelUpload();
stats = this.getStats();
}
};
SWFUpload.queue.uploadComplete = function (file) {
var user_upload_complete_handler = this.getSetting("user_upload_complete_handler");
var continue_upload = true;
if (typeof(user_upload_complete_handler) === "function") {
continue_upload = (user_upload_complete_handler.call(this, file) === false) ? false : true;
}
if (continue_upload) {
var stats = this.getStats();
if (stats.files_queued > 0 && this.customSettings.queue_cancelled_flag === false) {
this.startUpload();
} else {
this.customSettings.queue_cancelled_flag = false;
}
}
};
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

View File

@ -1,73 +0,0 @@
function fileQueued(file, queuelength) {
var listingfiles = document.getElementById("SWFUploadFileListingFiles");
if(!listingfiles.getElementsByTagName("ul")[0]) {
var info = document.createElement("h4");
info.appendChild(document.createTextNode("File queue"));
listingfiles.appendChild(info);
var ul = document.createElement("ul")
listingfiles.appendChild(ul);
}
listingfiles = listingfiles.getElementsByTagName("ul")[0];
var li = document.createElement("li");
li.id = file.id;
li.className = "SWFUploadFileItem";
li.innerHTML = file.name + " <span class='progressBar' id='" + file.id + "progress'></span><a id='" + file.id + "deletebtn' class='cancelbtn' href='javascript:swfu.cancelFile(\"" + file.id + "\");'><!-- IE --></a>";
listingfiles.appendChild(li);
var queueinfo = document.getElementById("queueinfo");
queueinfo.innerHTML = queuelength + " files queued";
document.getElementById(swfu.movieName + "UploadBtn").style.display = "block";
document.getElementById("cancelqueuebtn").style.display = "block";
}
function uploadFileCancelled(file, queuelength) {
var li = document.getElementById(file.id);
li.innerHTML = file.name + " - cancelled";
li.className = "SWFUploadFileItem uploadCancelled";
var queueinfo = document.getElementById("queueinfo");
queueinfo.innerHTML = queuelength + " files queued";
}
function uploadFileStart(file, position, queuelength) {
var div = document.getElementById("queueinfo");
div.innerHTML = "Uploading file " + position + " of " + queuelength;
var li = document.getElementById(file.id);
li.className += " fileUploading";
}
function uploadProgress(file, bytesLoaded) {
var progress = document.getElementById(file.id + "progress");
var percent = Math.ceil((bytesLoaded / file.size) * 200)
progress.style.background = "#f0f0f0 url(swfupload.v102.progressbar.png) no-repeat -" + (200 - percent) + "px 0";
}
function uploadError(errno) {
// SWFUpload.debug(errno);
}
function uploadFileComplete(file) {
var li = document.getElementById(file.id);
li.className = "SWFUploadFileItem uploadCompleted";
}
function cancelQueue() {
swfu.cancelQueue();
document.getElementById(swfu.movieName + "UploadBtn").style.display = "none";
document.getElementById("cancelqueuebtn").style.display = "none";
}
function uploadQueueComplete(file) {
var div = document.getElementById("queueinfo");
//div.innerHTML = "All files uploaded..."
document.getElementById("cancelqueuebtn").style.display = "none";
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 587 B

View File

@ -1,332 +0,0 @@
/*
SWFUpload v1.0.2 Plug-in
This plug in creates API compatibility with SWFUpload v1.0.2. Many SWFUpload v1.0.2 behaviors are emulated as well.
*/
var SWFUpload;
if (typeof(SWFUpload) === "function") {
SWFUpload.v102 = {};
SWFUpload.prototype.initSWFUpload = function (init_settings) {
try {
this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
this.settings = {};
this.eventQueue = [];
this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
this.movieElement = null;
// Setup global control tracking
SWFUpload.instances[this.movieName] = this;
// Load the settings. Load the Flash movie.
this.initSettings(init_settings);
this.loadFlash();
this.displayDebugInfo();
} catch (ex2) {
this.debug(ex2);
}
};
SWFUpload.prototype.initSettings = function (init_settings) {
// Store v1.0.2 settings
this.customSettings["target"] = this.retrieveSetting(init_settings["target"], "");
this.customSettings["create_ui"] = this.retrieveSetting(init_settings["create_ui"], false);
this.customSettings["browse_link_class"] = this.retrieveSetting(init_settings["browse_link_class"], "SWFBrowseLink");
this.customSettings["upload_link_class"] = this.retrieveSetting(init_settings["upload_link_class"], "SWFUploadLink");
this.customSettings["browse_link_innerhtml"] = this.retrieveSetting(init_settings["browse_link_innerhtml"], "<span>Browse...</span>");
this.customSettings["upload_link_innerhtml"] = this.retrieveSetting(init_settings["upload_link_innerhtml"], "<span>Upload</span>");
this.customSettings["auto_upload"] = this.retrieveSetting(init_settings["auto_upload"], false);
// Store v1.0.2 events
this.customSettings["upload_file_queued_callback"] = this.retrieveSetting(init_settings["upload_file_queued_callback"], null);
this.customSettings["upload_file_start_callback"] = this.retrieveSetting(init_settings["upload_file_start_callback"], null);
this.customSettings["upload_file_complete_callback"] = this.retrieveSetting(init_settings["upload_file_complete_callback"], null);
this.customSettings["upload_queue_complete_callback"] = this.retrieveSetting(init_settings["upload_queue_complete_callback"], null);
this.customSettings["upload_progress_callback"] = this.retrieveSetting(init_settings["upload_progress_callback"], null);
this.customSettings["upload_dialog_cancel_callback"] = this.retrieveSetting(init_settings["upload_dialog_cancel_callback"], null);
this.customSettings["upload_file_error_callback"] = this.retrieveSetting(init_settings["upload_file_error_callback"], null);
this.customSettings["upload_file_cancel_callback"] = this.retrieveSetting(init_settings["upload_file_cancel_callback"], null);
this.customSettings["upload_queue_cancel_callback"] = this.retrieveSetting(init_settings["upload_queue_cancel_callback"], null);
this.customSettings["queue_cancelled_flag"] = false;
// Upload backend settings
this.addSetting("upload_url", init_settings["upload_script"], "");
this.addSetting("file_post_name", "Filedata");
this.addSetting("post_params", {});
// File Settings
this.addSetting("file_types", init_settings["allowed_filetypes"], "*.*");
this.addSetting("file_types_description", init_settings["allowed_filetypes_description"], "All Files");
this.addSetting("file_size_limit", init_settings["allowed_filesize"], "1024");
this.addSetting("file_upload_limit", "0");
this.addSetting("file_queue_limit", "0");
// Flash Settings
this.addSetting("flash_url", init_settings["flash_path"], "swfupload.swf");
this.addSetting("flash_width", init_settings["flash_width"], "1px");
this.addSetting("flash_height", init_settings["flash_height"], "1px");
this.addSetting("flash_color", init_settings["flash_color"], "#000000");
// Debug Settings
this.addSetting("debug_enabled", init_settings.debug, false);
// Event Handlers
this.flashReady_handler = SWFUpload.flashReady; // This is a non-overrideable event handler
this.swfUploadLoaded_handler = SWFUpload.v102.swfUploadLoaded;
this.fileDialogStart_handler = SWFUpload.fileDialogStart;
this.fileQueued_handler = SWFUpload.v102.fileQueued;
this.fileQueueError_handler = SWFUpload.v102.uploadError;
this.fileDialogComplete_handler = SWFUpload.v102.fileDialogComplete;
this.uploadStart_handler = SWFUpload.v102.uploadStart;
this.uploadProgress_handler = SWFUpload.v102.uploadProgress;
this.uploadError_handler = SWFUpload.v102.uploadError;
this.uploadSuccess_handler = SWFUpload.v102.uploadSuccess;
this.uploadComplete_handler = SWFUpload.v102.uploadComplete;
this.debug_handler = SWFUpload.v102.debug;
// Hook up the v1.0.2 methods
this.browse = SWFUpload.v102.browse;
this.upload = SWFUpload.v102.upload;
this.cancelFile = SWFUpload.v102.cancelFile;
this.cancelQueue = SWFUpload.v102.cancelQueue;
this.debugSettings = SWFUpload.v102.debugSettings;
}
// Emulate the v1.0.2 events
SWFUpload.v102.swfUploadLoaded = function() {
try {
var target_id = this.customSettings["target"];
if(target_id !== "" && target_id !== "fileinputs") {
var self = this;
var target = document.getElementById(target_id);
if (target != null) {
// Create the link for uploading
var browselink = document.createElement("a");
browselink.className = this.customSettings["browse_link_class"];
browselink.id = this.movieName + "BrowseBtn";
browselink.href = "javascript:void(0);";
browselink.onclick = function() { self.browse(); return false; }
browselink.innerHTML = this.customSettings["browse_link_innerhtml"];
target.innerHTML = "";
target.appendChild(browselink);
// Add upload btn if auto upload not used
if(this.customSettings["auto_upload"] === false) {
// Create the link for uploading
var uploadlink = document.createElement("a");
uploadlink.className = this.customSettings["upload_link_class"];
uploadlink.id = this.movieName + "UploadBtn";
uploadlink.href = "#";
uploadlink.onclick = function() { self.upload(); return false; }
uploadlink.innerHTML = this.customSettings["upload_link_innerhtml"];
target.appendChild(uploadlink);
}
}
}
}
catch (ex) {
this.debug("Exception in swfUploadLoaded");
this.debug(ex);
}
}
SWFUpload.v102.fileQueued = function(file) {
var stats = this.getStats();
var total_files = stats.successful_uploads + stats.upload_errors + stats.files_queued;
var v102fileQueued = this.customSettings["upload_file_queued_callback"];
if (typeof(v102fileQueued) === "function") {
v102fileQueued.call(this, file, total_files);
}
}
SWFUpload.v102.fileDialogComplete = function(num_selected) {
if (!!this.customSettings["auto_upload"]) {
this.startUpload();
}
};
SWFUpload.v102.uploadStart = function (file) {
var callback = this.customSettings["upload_file_start_callback"];
var stats = this.getStats();
var current_file_number = stats.successful_uploads + stats.upload_errors + 1;
var total_files = stats.successful_uploads + stats.upload_errors + stats.files_queued;
if (typeof(callback) === "function") {
callback.call(this, file, current_file_number, total_files);
}
return true;
};
SWFUpload.v102.uploadProgress = function (file, bytes_complete, bytes_total) {
var callback = this.customSettings["upload_progress_callback"];
if (typeof(callback) === "function") {
callback.call(this, file, bytes_complete, bytes_total);
}
};
SWFUpload.v102.uploadSuccess = function (file, server_data) {
var callback = this.customSettings["upload_file_complete_callback"];
if (typeof(callback) === "function") {
callback.call(this, file, server_data);
}
};
SWFUpload.v102.uploadComplete = function (file) {
var stats = this.getStats();
if (stats.files_queued > 0 && !this.customSettings["queue_cancelled_flag"]) {
// Automatically start the next upload (if the queue wasn't cancelled)
this.startUpload();
} else if (stats.files_queued === 0 && !this.customSettings["queue_cancelled_flag"]) {
// Call Queue Complete if there are no more files queued and the queue wasn't cancelled
var callback = this.customSettings["upload_queue_complete_callback"];
if (typeof(callback) === "function") {
callback.call(this, file);
}
} else {
// Don't do anything. Remove the queue cancelled flag (if the queue was cancelled it will be set again)
this.customSettings["queue_cancelled_flag"] = false;
}
}
SWFUpload.v102.uploadError = function (file, error_code, msg) {
var translated_error_code = SWFUpload.v102.translateErrorCode(error_code);
switch (error_code) {
case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
var stats = this.getStats();
var total_files = stats.successful_uploads + stats.upload_errors + stats.files_queued;
var callback = this.customSettings["upload_file_cancel_callback"];
if (typeof(callback) === "function") {
callback.call(this, file, total_files);
}
break;
defaut:
var error_callback = this.customSettings["upload_file_error_callback"];
if (error_callback === null || typeof(error_callback) !== "function") {
SWFUpload.v102.defaultHandleErrors.call(this, translated_error_code, file, msg);
} else {
error_callback.call(this, translated_error_code, file, msg);
}
}
};
SWFUpload.v102.translateErrorCode = function (error_code) {
var translated_error_code = 0;
switch (error_code) {
case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:
translated_error_code = -40;
break;
case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
translated_error_code = -50;
break;
case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
translated_error_code = -30;
break;
case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
translated_error_code = -30;
break;
case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
translated_error_code = -10;
break;
case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
translated_error_code = -20;
break;
case SWFUpload.UPLOAD_ERROR.IO_ERROR:
translated_error_code = -30;
break;
case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
translated_error_code = -40;
break;
case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
translated_error_code = -30;
break;
case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
translated_error_code = -30;
break;
case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
translated_error_code = -10;
// FIX ME - call the upload_cancelled_callback
break;
case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
translated_error_code = -30;
break;
}
return translated_error_code;
}
// Default error handling.
SWFUpload.v102.defaultHandleErrors = function(errcode, file, msg) {
switch(errcode) {
case -10: // HTTP error
alert("Error Code: HTTP Error, File name: " + file.name + ", Message: " + msg);
break;
case -20: // No upload script specified
alert("Error Code: No upload script, File name: " + file.name + ", Message: " + msg);
break;
case -30: // IOError
alert("Error Code: IO Error, File name: " + file.name + ", Message: " + msg);
break;
case -40: // Security error
alert("Error Code: Security Error, File name: " + file.name + ", Message: " + msg);
break;
case -50: // Filesize too big
alert("Error Code: Filesize exceeds limit, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
break;
default:
alert("Error Code: " + errcode + ". File name: " + file.name + ", Message: " + msg);
}
};
SWFUpload.v102.debug = function (message) {
if (this.getSetting("debug_enabled")) {
if (window.console) {
window.console.log(message);
} else {
alert(message);
}
}
};
// Emulate the v1.0.2 function calls
SWFUpload.v102.browse = function() {
this.selectFiles();
};
SWFUpload.v102.upload = function () {
this.startUpload();
};
SWFUpload.v102.cancelFile = function (file_id) {
this.cancelUpload(file_id);
};
SWFUpload.v102.cancelQueue = function () {
var stats = this.getStats();
while (stats["files_queued"] > 0) {
this.customSettings["queue_cancelled_flag"] = true;
this.cancelUpload();
stats = this.getStats();
}
if (status.in_progress === 0) {
this.customSettings["queue_cancelled_flag"] = false;
}
};
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 972 B

View File

@ -1,73 +0,0 @@
.clr {
clear:both;
}
/* SWFUpload CSS */
.swfuploadbtn {
display: block;
width: 100px;
padding: 0 0 0 20px;
line-height: 16px;
}
.browsebtn {
background: url(swfupload.v102.add.png) no-repeat 0 0px;
}
.uploadbtn {
display: none;
background: url(swfupload.v102.accept.png) no-repeat 0 0px;
}
.cancelbtn {
display: block;
width: 16px;
height: 16px;
float: right;
background: url(swfupload.v102.cancel.png) no-repeat;
}
#cancelqueuebtn {
display: none;
background-image: url(swfupload.v102.cancel.png);
background-repeat: no-repeat;
background-position: 0px 0px;
background-attachment: scroll;
margin: 10px 0;
line-height: 16px;
}
#SWFUploadFileListingFiles ul {
margin: 0;
padding: 0;
list-style: none;
}
.SWFUploadFileItem {
display: block;
width: 230px;
height: 70px;
float: left;
background: #eaefea;
margin: 0 10px 10px 0;
padding: 5px;
}
.fileUploading { background: #fee727; }
.uploadCompleted { background: #d2fa7c; }
.uploadCancelled { background: #f77c7c; }
.uploadCompleted .cancelbtn, .uploadCancelled .cancelbtn {
display: none;
}
span.progressBar {
width: 200px;
display: block;
font-size: 10px;
height: 4px;
margin-top: 2px;
margin-bottom: 10px;
background-color: #CCC;
}

View File

@ -1,1032 +0,0 @@
/**
* SWFUpload v2.0 by Jacob Roberts, Nov 2007, http://www.swfupload.org, http://linebyline.blogspot.com
* -------- -------- -------- -------- -------- -------- -------- --------
* SWFUpload is (c) 2006 Lars Huring and Mammon Media and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* See Changelog.txt for version history
*
* Development Notes:
* * This version of SWFUpload requires Flash Player 9.0.28 and should autodetect the correct flash version.
* * In Linux Flash Player 9 setting the post file variable name does not work. It is always set to "Filedata".
* * There is a lot of repeated code that could be refactored to single functions. Feel free.
* * It's dangerous to do "circular calls" between Flash and JavaScript. I've taken steps to try to work around issues
* by having the event calls pipe through setTimeout. However you should still avoid calling in to Flash from
* within the event handler methods. Especially the "startUpload" event since it cannot use the setTimeout hack.
*/
/* *********** */
/* Constructor */
/* *********** */
var SWFUpload = function (init_settings) {
this.initSWFUpload(init_settings);
};
SWFUpload.prototype.initSWFUpload = function (init_settings) {
// Remove background flicker in IE (read this: http://misterpixel.blogspot.com/2006/09/forensic-analysis-of-ie6.html)
// This doesn't have anything to do with SWFUpload but can help your UI behave better in IE.
try {
document.execCommand('BackgroundImageCache', false, true);
} catch (ex1) {
}
try {
this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
this.settings = {};
this.eventQueue = [];
this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
this.movieElement = null;
// Setup global control tracking
SWFUpload.instances[this.movieName] = this;
// Load the settings. Load the Flash movie.
this.initSettings(init_settings);
this.loadFlash();
this.displayDebugInfo();
} catch (ex2) {
this.debug(ex2);
}
}
/* *************** */
/* Static thingies */
/* *************** */
SWFUpload.instances = {};
SWFUpload.movieCount = 0;
SWFUpload.QUEUE_ERROR = {
QUEUE_LIMIT_EXCEEDED : -100,
FILE_EXCEEDS_SIZE_LIMIT : -110,
ZERO_BYTE_FILE : -120,
INVALID_FILETYPE : -130
};
SWFUpload.UPLOAD_ERROR = {
HTTP_ERROR : -200,
MISSING_UPLOAD_URL : -210,
IO_ERROR : -220,
SECURITY_ERROR : -230,
UPLOAD_LIMIT_EXCEEDED : -240,
UPLOAD_FAILED : -250,
SPECIFIED_FILE_ID_NOT_FOUND : -260,
FILE_VALIDATION_FAILED : -270,
FILE_CANCELLED : -280,
UPLOAD_STOPPED : -290
};
SWFUpload.FILE_STATUS = {
QUEUED : -1,
IN_PROGRESS : -2,
ERROR : -3,
COMPLETE : -4,
CANCELLED : -5
};
/* ***************** */
/* Instance Thingies */
/* ***************** */
// init is a private method that ensures that all the object settings are set, getting a default value if one was not assigned.
SWFUpload.prototype.initSettings = function (init_settings) {
// Upload backend settings
this.addSetting("upload_url", init_settings.upload_url, "");
this.addSetting("file_post_name", init_settings.file_post_name, "Filedata");
this.addSetting("post_params", init_settings.post_params, {});
// File Settings
this.addSetting("file_types", init_settings.file_types, "*.*");
this.addSetting("file_types_description", init_settings.file_types_description, "All Files");
this.addSetting("file_size_limit", init_settings.file_size_limit, "1024");
this.addSetting("file_upload_limit", init_settings.file_upload_limit, "0");
this.addSetting("file_queue_limit", init_settings.file_queue_limit, "0");
// Flash Settings
this.addSetting("flash_url", init_settings.flash_url, "swfupload.swf");
this.addSetting("flash_width", init_settings.flash_width, "1px");
this.addSetting("flash_height", init_settings.flash_height, "1px");
this.addSetting("flash_color", init_settings.flash_color, "#FFFFFF");
// Debug Settings
this.addSetting("debug_enabled", init_settings.debug, false);
// Event Handlers
this.flashReady_handler = SWFUpload.flashReady; // This is a non-overrideable event handler
this.swfUploadLoaded_handler = this.retrieveSetting(init_settings.swfupload_loaded_handler, SWFUpload.swfUploadLoaded);
this.fileDialogStart_handler = this.retrieveSetting(init_settings.file_dialog_start_handler, SWFUpload.fileDialogStart);
this.fileQueued_handler = this.retrieveSetting(init_settings.file_queued_handler, SWFUpload.fileQueued);
this.fileQueueError_handler = this.retrieveSetting(init_settings.file_queue_error_handler, SWFUpload.fileQueueError);
this.fileDialogComplete_handler = this.retrieveSetting(init_settings.file_dialog_complete_handler, SWFUpload.fileDialogComplete);
this.uploadStart_handler = this.retrieveSetting(init_settings.upload_start_handler, SWFUpload.uploadStart);
this.uploadProgress_handler = this.retrieveSetting(init_settings.upload_progress_handler, SWFUpload.uploadProgress);
this.uploadError_handler = this.retrieveSetting(init_settings.upload_error_handler, SWFUpload.uploadError);
this.uploadSuccess_handler = this.retrieveSetting(init_settings.upload_success_handler, SWFUpload.uploadSuccess);
this.uploadComplete_handler = this.retrieveSetting(init_settings.upload_complete_handler, SWFUpload.uploadComplete);
this.debug_handler = this.retrieveSetting(init_settings.debug_handler, SWFUpload.debug);
// Other settings
this.customSettings = this.retrieveSetting(init_settings.custom_settings, {});
};
// loadFlash is a private method that generates the HTML tag for the Flash
// It then adds the flash to the "target" or to the body and stores a
// reference to the flash element in "movieElement".
SWFUpload.prototype.loadFlash = function () {
var html, target_element, container;
// Make sure an element with the ID we are going to use doesn't already exist
if (document.getElementById(this.movieName) !== null) {
return false;
}
// Get the body tag where we will be adding the flash movie
try {
target_element = document.getElementsByTagName("body")[0];
if (typeof(target_element) === "undefined" || target_element === null) {
this.debug('Could not find the BODY element. SWFUpload failed to load.');
return false;
}
} catch (ex) {
return false;
}
// Append the container and load the flash
container = document.createElement("div");
container.style.width = this.getSetting("flash_width");
container.style.height = this.getSetting("flash_height");
target_element.appendChild(container);
container.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
};
// Generates the embed/object tags needed to embed the flash in to the document
SWFUpload.prototype.getFlashHTML = function () {
var html = "";
// Create Mozilla Embed HTML
if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {
// Build the basic embed html
html = '<embed type="application/x-shockwave-flash" src="' + this.getSetting("flash_url") + '" width="' + this.getSetting("flash_width") + '" height="' + this.getSetting("flash_height") + '"';
html += ' id="' + this.movieName + '" name="' + this.movieName + '" ';
html += 'bgcolor="' + this.getSetting("flash_color") + '" quality="high" menu="false" flashvars="';
html += this.getFlashVars();
html += '" />';
// Create IE Object HTML
} else {
// Build the basic Object tag
html = '<object id="' + this.movieName + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + this.getSetting("flash_width") + '" height="' + this.getSetting("flash_height") + '">';
html += '<param name="movie" value="' + this.getSetting("flash_url") + '">';
html += '<param name="bgcolor" value="' + this.getSetting("flash_color") + '" />';
html += '<param name="quality" value="high" />';
html += '<param name="menu" value="false" />';
html += '<param name="flashvars" value="' + this.getFlashVars() + '" />';
html += '</object>';
}
return html;
};
// This private method builds the parameter string that will be passed
// to flash.
SWFUpload.prototype.getFlashVars = function () {
// Build a string from the post param object
var param_string = this.buildParamString();
// Build the parameter string
var html = "";
html += "movieName=" + encodeURIComponent(this.movieName);
html += "&uploadURL=" + encodeURIComponent(this.getSetting("upload_url"));
html += "&params=" + encodeURIComponent(param_string);
html += "&filePostName=" + encodeURIComponent(this.getSetting("file_post_name"));
html += "&fileTypes=" + encodeURIComponent(this.getSetting("file_types"));
html += "&fileTypesDescription=" + encodeURIComponent(this.getSetting("file_types_description"));
html += "&fileSizeLimit=" + encodeURIComponent(this.getSetting("file_size_limit"));
html += "&fileUploadLimit=" + encodeURIComponent(this.getSetting("file_upload_limit"));
html += "&fileQueueLimit=" + encodeURIComponent(this.getSetting("file_queue_limit"));
html += "&debugEnabled=" + encodeURIComponent(this.getSetting("debug_enabled"));
return html;
};
SWFUpload.prototype.getMovieElement = function () {
if (typeof(this.movieElement) === "undefined" || this.movieElement === null) {
this.movieElement = document.getElementById(this.movieName);
// 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)
// Removed because Revision 6 always adds the flash to the body (inside a containing div)
// 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
// and run this code to make the form's ID available from the window object so Flash and JavaScript can communicate.
//if (typeof(window[this.movieName]) === "undefined" || window[this.moveName] !== this.movieElement) {
// window[this.movieName] = this.movieElement;
//}
}
return this.movieElement;
};
SWFUpload.prototype.buildParamString = function () {
var post_params = this.getSetting("post_params");
var param_string_pairs = [];
var i, value, name;
// Retrieve the user defined parameters
if (typeof(post_params) === "object") {
for (name in post_params) {
if (post_params.hasOwnProperty(name)) {
if (typeof(post_params[name]) === "string") {
param_string_pairs.push(encodeURIComponent(name) + "=" + encodeURIComponent(post_params[name]));
}
}
}
}
return param_string_pairs.join("&");
};
// Saves a setting. If the value given is undefined or null then the default_value is used.
SWFUpload.prototype.addSetting = function (name, value, default_value) {
if (typeof(value) === "undefined" || value === null) {
this.settings[name] = default_value;
} else {
this.settings[name] = value;
}
return this.settings[name];
};
// Gets a setting. Returns empty string if not found.
SWFUpload.prototype.getSetting = function (name) {
if (typeof(this.settings[name]) === "undefined") {
return "";
} else {
return this.settings[name];
}
};
// Gets a setting, if the setting is undefined then return the default value
// This does not affect or use the interal setting object.
SWFUpload.prototype.retrieveSetting = function (value, default_value) {
if (typeof(value) === "undefined" || value === null) {
return default_value;
} else {
return value;
}
};
// It loops through all the settings and displays
// them in the debug Console.
SWFUpload.prototype.displayDebugInfo = function () {
var key, debug_message = "";
debug_message += "----- SWFUPLOAD SETTINGS ----\nID: " + this.moveName + "\n";
debug_message += this.outputObject(this.settings);
debug_message += "----- SWFUPLOAD SETTINGS END ----\n";
debug_message += "\n";
this.debug(debug_message);
};
SWFUpload.prototype.outputObject = function (object, prefix) {
var output = "", key;
if (typeof(prefix) !== "string") {
prefix = "";
}
if (typeof(object) !== "object") {
return "";
}
for (key in object) {
if (object.hasOwnProperty(key)) {
if (typeof(object[key]) === "object") {
output += (prefix + key + ": { \n" + this.outputObject(object[key], "\t" + prefix) + prefix + "}" + "\n");
} else {
output += (prefix + key + ": " + object[key] + "\n");
}
}
}
return output;
};
/* *****************************
-- Flash control methods --
Your UI should use these
to operate SWFUpload
***************************** */
SWFUpload.prototype.selectFile = function () {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SelectFile) === "function") {
try {
movie_element.SelectFile();
}
catch (ex) {
this.debug("Could not call SelectFile: " + ex);
}
} else {
this.debug("Could not find Flash element");
}
};
SWFUpload.prototype.selectFiles = function () {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SelectFiles) === "function") {
try {
movie_element.SelectFiles();
}
catch (ex) {
this.debug("Could not call SelectFiles: " + ex);
}
} else {
this.debug("Could not find Flash element");
}
};
/* Start the upload. If a file_id is specified that file is uploaded. Otherwise the first
* file in the queue is uploaded. If no files are in the queue then nothing happens.
* This call uses setTimeout since Flash will be calling back in to JavaScript
*/
SWFUpload.prototype.startUpload = function (file_id) {
var self = this;
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.StartUpload) === "function") {
setTimeout(
function () {
try {
movie_element.StartUpload(file_id);
}
catch (ex) {
self.debug("Could not call StartUpload: " + ex);
}
}, 0
);
} else {
this.debug("Could not find Flash element");
}
};
/* Cancels a the file upload. You must specify a file_id */
SWFUpload.prototype.cancelUpload = function (file_id) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.CancelUpload) === "function") {
try {
movie_element.CancelUpload(file_id);
}
catch (ex) {
this.debug("Could not call CancelUpload: " + ex);
}
} else {
this.debug("Could not find Flash element");
}
};
// Stops the current upload. The file is re-queued. If nothing is currently uploading then nothing happens.
SWFUpload.prototype.stopUpload = function () {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.StopUpload) === "function") {
try {
movie_element.StopUpload();
}
catch (ex) {
this.debug("Could not call StopUpload: " + ex);
}
} else {
this.debug("Could not find Flash element");
}
};
/* ************************
* Settings methods
* These methods change the settings inside SWFUpload
* They shouldn't need to be called in a setTimeout since they
* should not call back from Flash to JavaScript (except perhaps in a Debug call)
* and some need to return data so setTimeout won't work.
*/
/* Gets the file statistics object. It looks like this (where n = number):
{
files_queued: n,
complete_uploads: n,
upload_errors: n,
uploads_cancelled: n,
queue_errors: n
}
*/
SWFUpload.prototype.getStats = function () {
var self = this;
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.GetStats) === "function") {
try {
return movie_element.GetStats();
}
catch (ex) {
self.debug("Could not call GetStats");
}
} else {
this.debug("Could not find Flash element");
}
};
SWFUpload.prototype.setStats = function (stats_object) {
var self = this;
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetStats) === "function") {
try {
movie_element.SetStats(stats_object);
}
catch (ex) {
self.debug("Could not call SetStats");
}
} else {
this.debug("Could not find Flash element");
}
};
SWFUpload.prototype.getFile = function (file_id) {
var self = this;
var movie_element = this.getMovieElement();
if (typeof(file_id) === "number") {
if (movie_element !== null && typeof(movie_element.GetFileByIndex) === "function") {
try {
return movie_element.GetFileByIndex(file_id);
}
catch (ex) {
self.debug("Could not call GetFileByIndex");
}
} else {
this.debug("Could not find Flash element");
}
} else {
if (movie_element !== null && typeof(movie_element.GetFile) === "function") {
try {
return movie_element.GetFile(file_id);
}
catch (ex) {
self.debug("Could not call GetFile");
}
} else {
this.debug("Could not find Flash element");
}
}
};
SWFUpload.prototype.addFileParam = function (file_id, name, value) {
var self = this;
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.AddFileParam) === "function") {
try {
return movie_element.AddFileParam(file_id, name, value);
}
catch (ex) {
self.debug("Could not call AddFileParam");
}
} else {
this.debug("Could not find Flash element");
}
};
SWFUpload.prototype.removeFileParam = function (file_id, name) {
var self = this;
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.RemoveFileParam) === "function") {
try {
return movie_element.RemoveFileParam(file_id, name);
}
catch (ex) {
self.debug("Could not call AddFileParam");
}
} else {
this.debug("Could not find Flash element");
}
};
SWFUpload.prototype.setUploadURL = function (url) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetUploadURL) === "function") {
try {
this.addSetting("upload_url", url);
movie_element.SetUploadURL(this.getSetting("upload_url"));
}
catch (ex) {
this.debug("Could not call SetUploadURL");
}
} else {
this.debug("Could not find Flash element in setUploadURL");
}
};
SWFUpload.prototype.setPostParams = function (param_object) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetPostParams) === "function") {
try {
this.addSetting("post_params", param_object);
movie_element.SetPostParams(this.getSetting("post_params"));
}
catch (ex) {
this.debug("Could not call SetPostParams");
}
} else {
this.debug("Could not find Flash element in SetPostParams");
}
};
SWFUpload.prototype.setFileTypes = function (types, description) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetFileTypes) === "function") {
try {
this.addSetting("file_types", types);
this.addSetting("file_types_description", description);
movie_element.SetFileTypes(this.getSetting("file_types"), this.getSetting("file_types_description"));
}
catch (ex) {
this.debug("Could not call SetFileTypes");
}
} else {
this.debug("Could not find Flash element in SetFileTypes");
}
};
SWFUpload.prototype.setFileSizeLimit = function (file_size_limit) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetFileSizeLimit) === "function") {
try {
this.addSetting("file_size_limit", file_size_limit);
movie_element.SetFileSizeLimit(this.getSetting("file_size_limit"));
}
catch (ex) {
this.debug("Could not call SetFileSizeLimit");
}
} else {
this.debug("Could not find Flash element in SetFileSizeLimit");
}
};
SWFUpload.prototype.setFileUploadLimit = function (file_upload_limit) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetFileUploadLimit) === "function") {
try {
this.addSetting("file_upload_limit", file_upload_limit);
movie_element.SetFileUploadLimit(this.getSetting("file_upload_limit"));
}
catch (ex) {
this.debug("Could not call SetFileUploadLimit");
}
} else {
this.debug("Could not find Flash element in SetFileUploadLimit");
}
};
SWFUpload.prototype.setFileQueueLimit = function (file_queue_limit) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetFileQueueLimit) === "function") {
try {
this.addSetting("file_queue_limit", file_queue_limit);
movie_element.SetFileQueueLimit(this.getSetting("file_queue_limit"));
}
catch (ex) {
this.debug("Could not call SetFileQueueLimit");
}
} else {
this.debug("Could not find Flash element in SetFileQueueLimit");
}
};
SWFUpload.prototype.setFilePostName = function (file_post_name) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetFilePostName) === "function") {
try {
this.addSetting("file_post_name", file_post_name);
movie_element.SetFilePostName(this.getSetting("file_post_name"));
}
catch (ex) {
this.debug("Could not call SetFilePostName");
}
} else {
this.debug("Could not find Flash element in SetFilePostName");
}
};
SWFUpload.prototype.setDebugEnabled = function (debug_enabled) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SetDebugEnabled) === "function") {
try {
this.addSetting("debug_enabled", debug_enabled);
movie_element.SetDebugEnabled(this.getSetting("debug_enabled"));
}
catch (ex) {
this.debug("Could not call SetDebugEnabled");
}
} else {
this.debug("Could not find Flash element in SetDebugEnabled");
}
};
/* *******************************
Internal Event Callers
Don't override these! These event callers ensure that your custom event handlers
are called safely and in order.
******************************* */
/* This is the callback method that the Flash movie will call when it has been loaded and is ready to go.
Calling this or showUI() "manually" will bypass the Flash Detection built in to SWFUpload.
Use a ui_function setting if you want to control the UI loading after the flash has loaded.
*/
SWFUpload.prototype.flashReady = function () {
var self = this;
if (typeof(self.fileDialogStart_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.flashReady_handler(); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("fileDialogStart event not defined");
}
};
/*
Event Queue. Rather can call events directly from Flash they events are
are placed in a queue and then executed. This ensures that each event is
executed in the order it was called which is not guarenteed when calling
setTimeout. Out of order events was especially problematic in Safari.
*/
SWFUpload.prototype.executeNextEvent = function () {
var f = this.eventQueue.shift();
if (typeof(f) === "function") {
f();
}
}
/* This is a chance to do something before the browse window opens */
SWFUpload.prototype.fileDialogStart = function () {
var self = this;
if (typeof(self.fileDialogStart_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.fileDialogStart_handler(); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("fileDialogStart event not defined");
}
};
/* Called when a file is successfully added to the queue. */
SWFUpload.prototype.fileQueued = function (file) {
var self = this;
if (typeof(self.fileQueued_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.fileQueued_handler(file); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("fileQueued event not defined");
}
};
/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.prototype.fileQueueError = function (file, error_code, message) {
var self = this;
if (typeof(self.fileQueueError_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.fileQueueError_handler(file, error_code, message); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("fileQueueError event not defined");
}
};
/* Called after the file dialog has closed and the selected files have been queued.
You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.prototype.fileDialogComplete = function (num_files_selected) {
var self = this;
if (typeof(self.fileDialogComplete_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.fileDialogComplete_handler(num_files_selected); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("fileDialogComplete event not defined");
}
};
/* Gets called when a file upload is about to be started. Return true to continue the upload. Return false to stop the upload.
If you return false then uploadError and uploadComplete are called (like normal).
This is a good place to do any file validation you need.
*/
SWFUpload.prototype.uploadStart = function (file) {
var self = this;
if (typeof(self.fileDialogComplete_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.returnUploadStart(self.uploadStart_handler(file)); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("uploadStart event not defined");
}
};
/* Note: Internal use only. This function returns the result of uploadStart to
flash. Since returning values in the normal way can result in Flash/JS circular
call issues we split up the call in a Timeout. This is transparent from the API
point of view.
*/
SWFUpload.prototype.returnUploadStart = function (return_value) {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.ReturnUploadStart) === "function") {
try {
movie_element.ReturnUploadStart(return_value);
}
catch (ex) {
this.debug("Could not call ReturnUploadStart");
}
} else {
this.debug("Could not find Flash element in returnUploadStart");
}
};
/* Called during upload as the file progresses. Use this event to update your UI. */
SWFUpload.prototype.uploadProgress = function (file, bytes_complete, bytes_total) {
var self = this;
if (typeof(self.uploadProgress_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.uploadProgress_handler(file, bytes_complete, bytes_total); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("uploadProgress event not defined");
}
};
/* Called when an error occurs during an upload. Use error_code and the SWFUpload.UPLOAD_ERROR constants to determine
which error occurred. The uploadComplete event is called after an error code indicating that the next file is
ready for upload. For files cancelled out of order the uploadComplete event will not be called. */
SWFUpload.prototype.uploadError = function (file, error_code, message) {
var self = this;
if (typeof(this.uploadError_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.uploadError_handler(file, error_code, message); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("uploadError event not defined");
}
};
/* This gets called when a file finishes uploading and the server-side upload script has completed and returned a 200
status code. Any text returned by the server is available in server_data.
**NOTE: The upload script MUST return some text or the uploadSuccess and uploadComplete events will not fire and the
upload will become 'stuck'. */
SWFUpload.prototype.uploadSuccess = function (file, server_data) {
var self = this;
if (typeof(self.uploadSuccess_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.uploadSuccess_handler(file, server_data); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("uploadSuccess event not defined");
}
};
/* uploadComplete is called when the file is uploaded or an error occurred and SWFUpload is ready to make the next upload.
If you want the next upload to start to automatically you can call startUpload() from this event. */
SWFUpload.prototype.uploadComplete = function (file) {
var self = this;
if (typeof(self.uploadComplete_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.uploadComplete_handler(file); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.debug("uploadComplete event not defined");
}
};
/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
internal debug console. You can override this event and have messages written where you want. */
SWFUpload.prototype.debug = function (message) {
var self = this;
if (typeof(self.debug_handler) === "function") {
this.eventQueue[this.eventQueue.length] = function() { self.debug_handler(message); };
setTimeout(function () { self.executeNextEvent();}, 0);
} else {
this.eventQueue[this.eventQueue.length] = function() { self.debugMessage(message); };
setTimeout(function () { self.executeNextEvent();}, 0);
}
};
/* **********************************
Default Event Handlers.
These event handlers are used by default if an overriding handler is
not defined in the SWFUpload settings object.
JS Note: even though these are defined on the SWFUpload object (rather than the prototype) they
are attached (read: copied) to a SWFUpload instance and 'this' is given the proper context.
********************************** */
/* This is a special event handler that has no override in the settings. Flash calls this when it has
been loaded by the browser and is ready for interaction. You should not override it. If you need
to do something with SWFUpload has loaded then use the swfupload_loaded_handler setting.
*/
SWFUpload.flashReady = function () {
try {
this.debug("Flash called back and is ready.");
if (typeof(this.swfUploadLoaded_handler) === "function") {
this.swfUploadLoaded_handler();
}
} catch (ex) {
this.debug(ex);
}
};
/* This is a chance to something immediately after SWFUpload has loaded.
Like, hide the default/degraded upload form and display the SWFUpload form. */
SWFUpload.swfUploadLoaded = function () {
};
/* This is a chance to do something before the browse window opens */
SWFUpload.fileDialogStart = function () {
};
/* Called when a file is successfully added to the queue. */
SWFUpload.fileQueued = function (file) {
};
/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.fileQueueError = function (file, error_code, message) {
try {
switch (error_code) {
case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
this.debug("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
break;
case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
this.debug("Error Code: Zero Byte File, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
break;
case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:
this.debug("Error Code: Upload limit reached, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
break;
case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
this.debug("Error Code: File extension is not allowed, Message: " + message);
break;
default:
this.debug("Error Code: Unhandled error occured. Errorcode: " + error_code);
}
} catch (ex) {
this.debug(ex);
}
};
/* Called after the file dialog has closed and the selected files have been queued.
You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.fileDialogComplete = function (num_files_selected) {
};
/* Gets called when a file upload is about to be started. Return true to continue the upload. Return false to stop the upload.
If you return false then the uploadError callback is called and then uploadComplete (like normal).
This is a good place to do any file validation you need.
This is the only function that cannot be called on a setTimeout because it must return a value to Flash.
You SHOULD NOT make any calls in to Flash (e.i, changing settings, getting stats, etc). Flash Player bugs prevent
calls in to Flash from working reliably.
*/
SWFUpload.uploadStart = function (file) {
return true;
};
// Called during upload as the file progresses
SWFUpload.uploadProgress = function (file, bytes_complete, bytes_total) {
this.debug("File Progress: " + file.id + ", Bytes: " + bytes_complete + ". Total: " + bytes_total);
};
/* 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
server is available in server_data. The upload script must return some text or uploadSuccess will not fire (neither will uploadComplete). */
SWFUpload.uploadSuccess = function (file, server_data) {
};
/* This is called last. The file is uploaded or an error occurred and SWFUpload is ready to make the next upload.
If you want to automatically start the next file just call startUpload from here.
*/
SWFUpload.uploadComplete = function (file) {
};
// Called by SWFUpload JavaScript and Flash functions when debug is enabled.
// Override this method in your settings to call your own debug message handler
SWFUpload.debug = function (message) {
if (this.getSetting("debug_enabled")) {
this.debugMessage(message);
}
};
/* Called when an upload occurs during upload. For HTTP errors 'message' will contain the HTTP STATUS CODE */
SWFUpload.uploadError = function (file, error_code, message) {
try {
switch (errcode) {
case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
this.debug("Error Code: File ID specified for upload was not found, Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
this.debug("Error Code: HTTP Error, File name: " + file.name + ", Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
this.debug("Error Code: No backend file, File name: " + file.name + ", Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.IO_ERROR:
this.debug("Error Code: IO Error, File name: " + file.name + ", Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
this.debug("Error Code: Security Error, File name: " + file.name + ", Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
this.debug("Error Code: Upload limit reached, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
this.debug("Error Code: Upload Initialization exception, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
this.debug("Error Code: uploadStart callback returned false, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
this.debug("Error Code: The file upload was cancelled, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
break;
case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
this.debug("Error Code: The file upload was stopped, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
break;
default:
this.debug("Error Code: Unhandled error occured. Errorcode: " + errcode);
}
} catch (ex) {
this.debug(ex);
}
};
/* **********************************
Debug Console
The debug console is a self contained, in page location
for debug message to be sent. The Debug Console adds
itself to the body if necessary.
The console is automatically scrolled as messages appear.
You can override this console (to use FireBug's console for instance) by setting the debug event method to your own function
that handles the debug message
********************************** */
SWFUpload.prototype.debugMessage = function (message) {
var exception_message, exception_values;
if (typeof(message) === "object" && typeof(message.name) === "string" && typeof(message.message) === "string") {
exception_message = "";
exception_values = [];
for (var key in message) {
exception_values.push(key + ": " + message[key]);
}
exception_message = exception_values.join("\n");
exception_values = exception_message.split("\n");
exception_message = "EXCEPTION: " + exception_values.join("\nEXCEPTION: ");
SWFUpload.Console.writeLine(exception_message);
} else {
SWFUpload.Console.writeLine(message);
}
};
SWFUpload.Console = {};
SWFUpload.Console.writeLine = function (message) {
var console, documentForm;
try {
console = document.getElementById("SWFUpload_Console");
if (!console) {
documentForm = document.createElement("form");
document.getElementsByTagName("body")[0].appendChild(documentForm);
console = document.createElement("textarea");
console.id = "SWFUpload_Console";
console.style.fontFamily = "monospace";
console.setAttribute("wrap", "off");
console.wrap = "off";
console.style.overflow = "auto";
console.style.width = "700px";
console.style.height = "350px";
console.style.margin = "5px";
documentForm.appendChild(console);
}
console.value += message + "\n";
console.scrollTop = console.scrollHeight - console.clientHeight;
} catch (ex) {
alert("Exception: " + ex.name + " Message: " + ex.message);
}
};