[Dojo-checkins] mwilcox - r20770 - in deft/trunk/deft: common/events form shapes

dojo-checkins-admin at dojotoolkit.org dojo-checkins-admin at dojotoolkit.org
Wed Nov 11 12:36:25 EST 2009


Author: mwilcox
Date: Wed Nov 11 09:36:13 2009
New Revision: 20770

Added:
   deft/trunk/deft/form/File.as   (contents, props changed)
Modified:
   deft/trunk/deft/common/events/Topic.as
   deft/trunk/deft/form/IUpload.as
   deft/trunk/deft/form/UploadFile.as
   deft/trunk/deft/form/UploadList.as
   deft/trunk/deft/form/Uploader.as
   deft/trunk/deft/shapes/HtmlShape.as
   deft/trunk/deft/shapes/HtmlText.as
Log:
Fixes #10216, #10215 - Refactored code so its much prettier. Changes include better memory mamangement - not attaching listeners until actual upload and detaching them when done. Deferred uploading is required now to enforce sending only ne (or more) files at a time but not all. onProgree fires onComplete now which fixes the problem of it never firing when uploading small files.

Modified: deft/trunk/deft/common/events/Topic.as
==============================================================================
--- deft/trunk/deft/common/events/Topic.as	(original)
+++ deft/trunk/deft/common/events/Topic.as	Wed Nov 11 09:36:13 2009
@@ -1 +1 @@
-package deft.common.events {
	import deft.common.debugging.console;
	import flash.events.EventDispatcher;
	import deft.common.events.TopicEvent;
	import flash.external.ExternalInterface;
	import deft.common.MovieIdentity;
	public class Topic {
		
		public static var ACTION:String = "action";
		public static var METHOD:String = "method";
		
		public static var FILES_SELECTED:String = "filesSelected";
		public static var FILES_CANCELED:String = "filesCanceled";
		public static var FILES_UPLOADED:String = "filesUploaded";
		public static var FILES_PROGRESS:String = "filesProgress";
		public static var FILES_ALL_LOADED:String = "filesAllLoaded";
		public static var FILES_ERROR:String = "filesError";
		public static var MEDIA_ERROR:String = "mediaError";
		public static var MEDIA_META:String = "mediaMeta";
		public static var MEDIA_POSITION:String = "mediaPosition";
		public static var MEDIA_STATII:String = "mediaStatus";
		public static var MEDIA_START:String = "mediaStart";
 		public static var MEDIA_END:String = "mediaEnd";
		public static var MEDIA_CUEPOINT:String = "mediaCuepoint";
		public static var STAGE_SIZED:String = "stageSized";
		public static var STAGE_CLICK:String = "stageClick";
		public static var STAGE_BLUR:String = "stageBlur";
		
		private static var d:EventDispatcher = new EventDispatcher();
		
		public function Topic():void{ }
		
		public static function publish(event:TopicEvent):void{
			var args:Array = [
				"dojo.publish",
				MovieIdentity.identity+"/"+event.type,
				[event.argObject, event.scope]
			];
			
			console.log("Topic args:", args);
			
			/*if(event.type=="filesCanceled"){
				console.log("---------dispatchEvent args:", args);
				console.log("---------dispatchEvent event type:", event.type);
				console.log("---------dispatchEvent event args:", event.argObject);
				console.log("---------dispatchEvent event scope:", event.scope);
				console.log("---------dispatchEvent event:", event);
				//console.log("--
 -------hasEventListener:", d.hasEventListener(event.type) );
				//console.log("---------willTrigger:", d.willTrigger(event.type) );
			}*/
			
			
			ExternalInterface.call.apply(null, args);
			//console.log("---------EI DISPATCHED.");
			if(d.hasEventListener(event.type)){
				d.dispatchEvent(event);
			}
			console.log("Topic Publish:", event.type);
			//console.log("---------EVENT DISPATCHED.");
		}
		
		public static function subscribe(type:String, method:Function):void{
			//console.log("subscribe: ", type)
			d.addEventListener(type, method);
		}
	}
	


}
\ No newline at end of file
+package deft.common.events {
	import deft.common.debugging.console;
	import flash.events.EventDispatcher;
	import deft.common.events.TopicEvent;
	import flash.external.ExternalInterface;
	import deft.common.MovieIdentity;
	public class Topic {
		
		public static var ACTION:String = "action";
		public static var METHOD:String = "method";
		
		public static var FILE_COMPLETE:String = "fileComplete";
		public static var FILES_SELECTED:String = "filesSelected";
		public static var FILES_CANCELED:String = "filesCanceled";
		public static var FILES_UPLOADED:String = "filesUploaded";
		public static var FILES_PROGRESS:String = "filesProgress";
		public static var FILES_ALL_LOADED:String = "filesAllLoaded";
		public static var FILES_ERROR:String = "filesError";
		public static var MEDIA_ERROR:String = "mediaError";
		public static var MEDIA_META:String = "mediaMeta";
		public static var MEDIA_POSITION:String = "mediaPosition";
		public static var MEDIA_STATII:String = "mediaStatu
 s";
		public static var MEDIA_START:String = "mediaStart";
		public static var MEDIA_END:String = "mediaEnd";
		public static var MEDIA_CUEPOINT:String = "mediaCuepoint";
		public static var STAGE_SIZED:String = "stageSized";
		public static var STAGE_CLICK:String = "stageClick";
		public static var STAGE_BLUR:String = "stageBlur";
		
		private static var d:EventDispatcher = new EventDispatcher();
		
		public function Topic():void{ }
		
		public static function publish(event:TopicEvent):void{
			var args:Array = [
				"dojo.publish",
				MovieIdentity.identity+"/"+event.type,
				[event.argObject, event.scope]
			];
			
			//console.log("Topic args:", args);
			
			/*if(event.type=="filesCanceled"){
				console.log("---------dispatchEvent args:", args);
				console.log("---------dispatchEvent event type:", event.type);
				console.log("---------dispatchEvent event args:", event.argObject);
				console.log("---------dispatchEvent event scope:", event.scope);
				console.log("
 ---------dispatchEvent event:", event);
				//console.log("---------hasEventListener:", d.hasEventListener(event.type) );
				//console.log("---------willTrigger:", d.willTrigger(event.type) );
			}*/
			
			
			ExternalInterface.call.apply(null, args);
			//console.log("---------EI DISPATCHED.");
			if(d.hasEventListener(event.type)){
				d.dispatchEvent(event);
			}
			//console.log("Topic Publish:", event.type);
			//console.log("---------EVENT DISPATCHED.");
		}
		
		public static function subscribe(type:String, method:Function):void{
			//console.log("subscribe: ", type)
			d.addEventListener(type, method);
		}
	}
	


}
\ No newline at end of file

Added: deft/trunk/deft/form/File.as
==============================================================================
--- (empty file)
+++ deft/trunk/deft/form/File.as	Wed Nov 11 09:36:13 2009
@@ -0,0 +1,249 @@
+/*********************************************************************
+ *	File.as
+ *
+ *	class to handle the individual files and their 
+ *	properties during uploads
+ *
+ *	version: 		1.4
+ *	revision date:	2009-11-04
+ *	authors:		Mike Wilcox
+ *********************************************************************/
+package deft.form{
+	import deft.common.debugging.console;
+    import flash.events.*;
+	import flash.net.FileReference;
+    import flash.net.URLRequest;
+	import deft.common.events.TopicEvent;
+	import deft.common.events.Topic;
+	import flash.utils.Timer;
+	import flash.utils.getTimer;
+	import flash.utils.setTimeout;
+	
+	public class File{
+		
+		public var additionalParams:Object = {};
+		public var Filename:String = "";
+		public var file:String = "";
+		public var name:String = "";
+		public var type:String = "";
+		public var error:String = "";
+		public var width:Number = 0;
+		public var height:Number = 0;
+		public var size:Number;
+		public var startUploadTime:Number = 0;
+		public var uploadTime:Number = 0;
+		public var lastUploadTime:Number = 0;
+		public var creationDate:Date;
+		public var modificationDate:Date;
+		public var creator:String;
+		
+		private var uploadOnSelect:Boolean;
+		private var testIllegalCharacters:Boolean;
+		
+		private var fileRef:FileReference;
+		private var serverTimer:Timer;
+		private var serverCheckIntv:Number = 1000;
+		private var currentServerTick:Number = 0;
+		private var failedServerTickAmount:Number = 3; 
+		
+		
+		
+		public function File(f:FileReference, event:Event, _t:Boolean, tout:Number):void{
+			// summary:
+			//		Constructor
+			//
+			fileRef = f;
+			testIllegalCharacters = _t;
+			failedServerTickAmount = tout/1000;
+			console.log("server timeout (seconds) : ", failedServerTickAmount);
+			try{
+			
+				name =				f.name;
+				type =				f.type;
+				size =				f.size;
+				creationDate =		f.creationDate;
+				modificationDate =	f.modificationDate;
+				creator =			f.creator;
+				
+			}catch(e:Event){ console.error(" file error:", e); }
+		}
+
+		public function getSelectedData():Object{
+			// summary:
+			//		Returns an object with certain properties
+			//		for pre-complete events
+			return {
+				name:name,
+				type:type,
+				size:size,
+				creationDate:creationDate,
+				modificationDate:modificationDate,
+				creator:creator
+			}
+		}
+		
+		public function doUpload(url:URLRequest, fieldName:String):void {
+			// summary:
+			//		Uploads file, sets timers, adds listeners
+			//
+			console.log(" * doUpload File ", name);
+			console.log("single file - do upload, fieldName", fieldName);
+			addListeners();
+			startUploadTime = getTimer();
+			pingServerResponse();
+			fileRef.upload(url, fieldName);
+		}
+		
+		private function onComplete(event:DataEvent):void{
+			// summary:
+			//		Fired on completion of upload. Fires 
+			//		a custom event that should be subscribed to.
+			//
+			
+			console.log("File-onComplete: event=" + event);
+			uploadTime = getTimer() - startUploadTime;
+			serverTimer.stop();
+			try{
+				var prog:Object = {
+					name:name,
+					bytesLoaded:size,
+					bytesTotal:size
+				};
+				Topic.publish(new TopicEvent(Topic.FILES_PROGRESS, this, prog));
+				
+				var r:RegExp = new RegExp(/\{|\}|<|>|"|'|\(|\)|;|,/g);
+				var r2:RegExp = new RegExp(/<html/i);
+				
+				var a:Array = event.data.split(",");
+				var parseError:Boolean = false;
+				
+				for(var i:uint=0;i<a.length;i++){
+					var keyValue:String = a[i];
+					if((testIllegalCharacters && r.test(keyValue)) || (!testIllegalCharacters && r2.test(keyValue))){
+						parseError = true;
+						break;
+					}
+					
+					var key:String = keyValue.split("=")[0];
+					var val:String = keyValue.split("=")[1];
+					
+					if(key == "width" || key == "height"){
+						this[key] = Number(val);
+					}else if(key == "Filename" || key == "file" || key == "type" || key == "error"){
+						this[key] = val;
+					}else{
+						additionalParams[key] = val;
+					}
+				}
+				
+				if(parseError){
+					// aborts upload
+					console.log("Reporting parse error");
+					var msg:Object = {msg:"Error: Illegal characters found in file data: "+event.data, type:"parseError"};
+					Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, msg));
+					return;
+				}
+				console.log(" -------------- fire file complete event...");
+				Topic.publish(new TopicEvent(Topic.FILE_COMPLETE, event, this));
+				
+			}catch(e:Event){ console.error("File.onComplete parse error:", e); }
+		}
+				
+        private function onProgress(event:ProgressEvent):void {
+			// summary:
+			//		Fires on progress event. Each file publishes this
+			//		individually where it is picked up by JavaScript
+			//		and assembled into an array.
+			//
+            var o:Object = {
+				name:name,
+				bytesLoaded:event.bytesLoaded,
+				bytesTotal:event.bytesTotal
+			}
+			console.log(" ** onProgress ** ", (event.bytesLoaded/event.bytesTotal));
+			currentServerTick = 0;
+			Topic.publish(new TopicEvent(Topic.FILES_PROGRESS, this, o));
+        }
+		
+		
+		public function pingServerResponse():void {
+			// summary:
+			//		Start timer check
+			//
+            serverTimer = new Timer(serverCheckIntv);
+            serverTimer.addEventListener("timer", timerHandler);
+            serverTimer.start();
+        }
+
+        public function timerHandler(event:TimerEvent):void {
+            // summary:
+			//		Periodically checks for an onComplete or an onProgress
+			//		If no response, this file is tagged with a "server timeout"
+			//		error an onComplete is triggered in hopes that subsequent
+			//		uploads will be successful.
+			//
+			// 		currentServerTick should be reset to zero onProgress
+			//		which indicates responsiveness
+			//
+			currentServerTick++;
+			if(currentServerTick >= failedServerTickAmount){
+				currentServerTick = 0;
+				
+				var prog:Object = {
+					name:name,
+					bytesLoaded:size,
+					bytesTotal:size
+				};
+				error = "server timeout";
+				
+				Topic.publish(new TopicEvent(Topic.FILES_PROGRESS, this, prog));
+				Topic.publish(new TopicEvent(Topic.FILE_COMPLETE, event, this));
+				console.warn("Server failed to respond");
+				return;
+			}
+			console.log("timerHandler: tick:", currentServerTick, " of: ", failedServerTickAmount);
+        }
+		
+		private function addListeners():void{
+			// summary:
+			//		Adds listeners. Natch.	
+			fileRef.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
+            fileRef.addEventListener(ProgressEvent.PROGRESS, onProgress);
+            fileRef.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onComplete);
+			fileRef.addEventListener(HTTPStatusEvent.HTTP_STATUS , httpErrorHandler);
+			fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
+		}
+		
+		public function removeListeners():void{
+			// summary:
+			//		Removes listeners. This is basically a "destroy". Nothing
+			//		else to do but remove the listeners. Should set object to 
+			//		null after.
+			//
+			fileRef.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
+			fileRef.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
+            fileRef.removeEventListener(ProgressEvent.PROGRESS, onProgress);
+            fileRef.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onComplete);
+			fileRef.removeEventListener(HTTPStatusEvent.HTTP_STATUS , httpErrorHandler);
+			fileRef.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
+			serverTimer.stop();
+			serverTimer.removeEventListener("timer", timerHandler);
+			console.log("file listeners removed.");
+		}
+		
+        private function httpErrorHandler(event:Event):void {
+			console.log("httpErrorHandler: name=" + name+ " event=" + event.toString());
+			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
+		}
+	 
+		private function ioErrorHandler(event:Event):void {
+			console.log("ioErrorHandler: name=" + name+ " event=" + event.toString());
+			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
+		}
+	 
+		private function securityErrorHandler(event:Event):void {
+			console.log("securityErrorHandler: name=" + name + " event=" + event.toString());
+			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
+		}
+    }
+}
\ No newline at end of file

Modified: deft/trunk/deft/form/IUpload.as
==============================================================================
--- deft/trunk/deft/form/IUpload.as	(original)
+++ deft/trunk/deft/form/IUpload.as	Wed Nov 11 09:36:13 2009
@@ -1 +1 @@
-/*********************************************************************
 *	IUpload.as
 *
 *	Interface defining file upload methods
 *
 *	version: 		1.0
 *	revision date:	2008-08-04
 *	authors:		Mike Wilcox
 *********************************************************************/

package deft.form {
	import deft.common.events.TopicEvent;
	import flash.net.URLRequest;
	public interface IUpload {
		function init(URI:URLRequest, fieldName:String, _uploadOnSelect:Boolean, _deferredUploading:Boolean):void;
		function doUpload(_newUrl:URLRequest=null):void;
		function removeFile(name:String):void;
		function doBrowse(typeFilter:Array):void;
	}
}
\ No newline at end of file
+/*********************************************************************
 *	IUpload.as
 *
 *	Interface defining file upload methods
 *
 *	version: 		1.0
 *	revision date:	2008-08-04
 *	authors:		Mike Wilcox
 *********************************************************************/

package deft.form {
	import deft.common.events.TopicEvent;
	import flash.net.URLRequest;
	public interface IUpload {
		function init(uploadOnSelect:Boolean, testIllegalCharacters:Boolean, serverTimeout:Number):void;
		function updateFunctionality(URI:URLRequest, fieldName:String, _deferredUploading:Number):void;
		function doUpload(_newUrl:URLRequest=null):void;
		function removeFile(name:String):void;
		function doBrowse(typeFilter:Array):void;
	}
}
\ No newline at end of file

Modified: deft/trunk/deft/form/UploadFile.as
==============================================================================
--- deft/trunk/deft/form/UploadFile.as	(original)
+++ deft/trunk/deft/form/UploadFile.as	Wed Nov 11 09:36:13 2009
@@ -1 +1 @@
-/*********************************************************************
 *	UploadFile.as
 *
 *	class to handle single-file uploads
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.form{
	import deft.common.debugging.console;
    import flash.events.*;
	import flash.net.FileReference;
    import flash.net.URLRequest;
	import deft.common.events.TopicEvent;
	import deft.common.events.Topic;
	import deft.form.IUpload;
	public class UploadFile extends FileReference implements IUpload{
		
		private var uploadURL:URLRequest;
		private var uploadOnSelect:Boolean;
		public var completeData:Array = [];
		private var fieldName:String;
		private var fileSelected:Boolean = false;
		
		public function UploadFile():void {
			//constructor
		};
		
		public function init(URI:URLRequest, _fieldName:String, _uploadOnSelect:Boolean, _deferredUploading:Boolean):void {
			this.uploadOn
 Select = _uploadOnSelect;
			uploadURL = URI;
            fieldName = _fieldName;
			addEventListener(Event.SELECT, onSelect);
            addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            addEventListener(ProgressEvent.PROGRESS, onProgress);
            addEventListener(Event.CANCEL, onCancel);
			addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onComplete);
			addEventListener(HTTPStatusEvent.HTTP_STATUS , httpErrorHandler);
			addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
        }
		
		public function doUpload(_newUrl:URLRequest=null):void {
			console.log(" * doUpload Single ", fileSelected);
			if(fileSelected){
				if(_newUrl){
					uploadURL = _newUrl;
				}
				console.log("single file - do upload, fieldName", fieldName);
				upload(uploadURL, fieldName);
			}
		}
		
		public function doBrowse(typeFilter:Array):void {
			browse(typeFilter);
		}
		
		private function onSelect(event:Event):void {
            console.log(
 "onSelect: name=" + name);
			var o:Object = {
				name:name,
				type:type,
				size:size,
				creationDate:creationDate,
				modificationDate:modificationDate,
				creator:creator
			};
			Topic.publish(new TopicEvent(Topic.FILES_SELECTED, this, [o]));
			fileSelected = true;
			
			if(this.uploadOnSelect){
				console.log("auto upload, fieldName", fieldName);
            	doUpload();
			}
        }
		public function removeFile(name:String):void{
			fileSelected = false;
		}
		private function onComplete(event:DataEvent):void{
			console.log("File-onComplete: event=" + event);
			fileSelected = false;
			var r:RegExp = new RegExp(/\{|\}|<|>|"|'|\(|\)|;|,/g);

			var o:Object = {
				name:name,
				type:type,
				size:size,
				creationDate:creationDate,
				modificationDate:modificationDate,
				creator:creator
			};
			var a:Array = event.data.split(",");
			var parseError:Boolean = false;
			for(var i:uint=0;i<a.length;i++){
				var keyValue:String = a[i];
				if(r.test(
 keyValue)){
					parseError = true;
					break;
				}
				o[keyValue.split("=")[0]] = keyValue.split("=")[1];
			}
			if(parseError){
				console.log("Reporting parse error");
				var msg:Object = {msg:"Error: Illegal characters found in file data: "+event.data, type:"parseError"};
				Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, msg));
				return;
			}
			console.log("File-Object created:", o);
			o.width = Number(o.width);
			o.height = Number(o.height);
			this.completeData = [o];
			
			Topic.publish(new TopicEvent(Topic.FILES_UPLOADED, this, this.completeData));
		}
		
      	private function onCancel(event:Event):void {
			var evt:TopicEvent = new TopicEvent(Topic.FILES_CANCELED);
			console.log(" 000 - onCancel...", evt)
			Topic.publish(evt);
		}
				
        private function onProgress(event:ProgressEvent):void {
            var o:Object = {
				name:name,
				bytesLoaded:event.bytesLoaded,
				bytesTotal:event.bytesTotal
			}
			Topic.publish(new TopicEven
 t(Topic.FILES_PROGRESS, this, o));
        }

        private function httpErrorHandler(event:Event):void {
			console.log("httpErrorHandler: name=" + name+ " event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	 
		private function ioErrorHandler(event:Event):void {
			console.log("ioErrorHandler: name=" + name+ " event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	 
		private function securityErrorHandler(event:Event):void {
			console.log("securityErrorHandler: name=" + name + " event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
    }
}
\ No newline at end of file
+/*********************************************************************
 *	UploadFile.as
 *
 *	class to handle single-file uploads
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.form{
	import deft.common.debugging.console;
    import flash.events.*;
	import flash.net.FileReference;
    import flash.net.URLRequest;
	import deft.common.events.TopicEvent;
	import deft.common.events.Topic;
	import deft.form.IUpload;
	import deft.form.File;
	
	public class UploadFile extends FileReference implements IUpload{
		
		private var uploadURL:URLRequest;
		private var uploadOnSelect:Boolean;
		public var completeData:Array = [];
		private var fieldName:String;
		private var fileSelected:Boolean = false;
		private var testIllegalCharacters:Boolean;
		private var uploadDeferred:Number = 1;
		private var file:deft.form.File;
		private var serverTimeout:Number = 3000;
		
		publi
 c function UploadFile():void{}
		
		public function init(_uploadOnSelect:Boolean, _testIllegalCharacters:Boolean, stout:Number):void {
			uploadOnSelect = _uploadOnSelect;
			serverTimeout = stout;
			testIllegalCharacters = _testIllegalCharacters;
			addEventListener(Event.SELECT, onSelect);
            addEventListener(Event.CANCEL, onCancel);
			Topic.subscribe(Topic.FILE_COMPLETE, onComplete);
		};
		
		public function updateFunctionality(URI:URLRequest, _fieldName:String, _def:Number):void {
			uploadURL = URI;
            fieldName = _fieldName;
			uploadDeferred = _def
        }
		
		public function doBrowse(typeFilter:Array):void {
			browse(typeFilter);
		}
		
		private function onSelect(event:Event):void {
            console.log("onSelect: name=" + name);
			file = new deft.form.File(this, event, testIllegalCharacters, serverTimeout);
			Topic.publish(new TopicEvent(Topic.FILES_SELECTED, this, [file]));
			fileSelected = true;
			
			if(this.uploadOnSelect){
				c
 onsole.log("auto upload, fieldName", fieldName);
            	doUpload();
			}
        }
		
		public function doUpload(_newUrl:URLRequest=null):void {
			console.log(" * doUpload Single ", fileSelected);
			if(fileSelected){
				uploadURL = _newUrl ? _newUrl : uploadURL;
				console.log("single file - do upload, fieldName", fieldName);
				file.doUpload(uploadURL, fieldName);
			}
		}
				
		public function removeFile(name:String):void{
			fileSelected = false;
		}
		
		private function onComplete(data:Object):void{
			console.log("File-onComplete: data=" + data);
			Topic.publish(new TopicEvent(Topic.FILES_UPLOADED, this, [file]));
			fileSelected = false;
			file.removeListeners();
			file = null;
		}
		
      	private function onCancel(event:Event):void {
			var evt:TopicEvent = new TopicEvent(Topic.FILES_CANCELED);
			console.log(" 000 - onCancel...", evt)
			Topic.publish(evt);
		}
				

        private function httpErrorHandler(event:Event):void {
			console.log("httpE
 rrorHandler: name=" + name+ " event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	 
		private function ioErrorHandler(event:Event):void {
			console.log("ioErrorHandler: name=" + name+ " event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	 
		private function securityErrorHandler(event:Event):void {
			console.log("securityErrorHandler: name=" + name + " event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
    }
}
\ No newline at end of file

Modified: deft/trunk/deft/form/UploadList.as
==============================================================================
--- deft/trunk/deft/form/UploadList.as	(original)
+++ deft/trunk/deft/form/UploadList.as	Wed Nov 11 09:36:13 2009
@@ -1 +1 @@
-/*********************************************************************
 *	UploadList.as
 *
 *	class to handle multi-file uploads
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.form {
	import deft.common.debugging.console;
	import deft.form.Uploader;
	import flash.events.*;
	import flash.net.FileReference;
	import flash.net.FileReferenceList;
	import deft.common.events.TopicEvent;
	import deft.common.events.Topic;
	import flash.net.URLRequest;
	import deft.form.IUpload;
	public class UploadList extends FileReferenceList implements IUpload{
		
		public var pendingFiles:Array = []; 
		public var completeData:Array = [];
		private var uploadURL:URLRequest;
		private var uploadOnSelect:Boolean;
		private var isDataComplete:Boolean = false;
		private var isUploadDeferred:Boolean = true;
		private var selectedFiles:Array = [];
		private var fieldName:String;
		public 
 function UploadList():void{ }
		
		public function init(URI:URLRequest, _fieldName:String, _uploadOnSelect:Boolean, _deferredUploading:Boolean):void {
			uploadOnSelect = _uploadOnSelect;
			isUploadDeferred = _deferredUploading;
			uploadURL = URI;
			fieldName = _fieldName;
			addEventListener(Event.SELECT, onSelect);
			addEventListener(Event.CANCEL, cancelHandler);
		}
		
		public function doBrowse(typeFilter:Array):void {
			browse(typeFilter);
		}
		
		private function onSelect(event:Event):void {
		   // fileList:
		   //	An array of FileReference objects.
		   console.log("onSelect: " + fileList.length + " files");
			
			var newFiles:Array = [];
			var file:FileReference;
			var i:uint
			for (i = 0; i < fileList.length; i++) {
				file = FileReference(fileList[i]);
				addPendingFile(file);
				
				var f:Object = {
					name:file.name,
					type:file.type,
					size:file.size,
					creationDate:file.creationDate,
					modificationDate:file.modificationDate,
					c
 reator:file.creator
				}
				selectedFiles.push(f);
				newFiles.push(f);
			};
			
			Topic.publish(new TopicEvent(Topic.FILES_SELECTED, this, newFiles));
			if(this.uploadOnSelect){
				console.log("multi auto upload, fieldName", fieldName);
				doUpload(uploadURL);
			}
		}
		
		private function addPendingFile(file:FileReference):void {
			console.log("addPendingFile: name=" + file.name);
			pendingFiles.push(file);
			file.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			file.addEventListener(ProgressEvent.PROGRESS, onProgress);
			file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			file.addEventListener(HTTPStatusEvent.HTTP_STATUS , httpErrorHandler);
			file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onComplete);
		}
		
		private function uploadNext():void{
			pendingFiles[0].upload(uploadURL, fieldName);
		}
		
		public function doUpload(_newUrl:URLRequest=null):void {
			// note: fieldname could be incremented
			//
		
 	// note: defer upload
			//
			
			try{
				console.log(" * doUpload Multi file amount:", pendingFiles.length, "isUploadDeferred:", isUploadDeferred);
				if(pendingFiles.length){
					if(_newUrl){
						uploadURL = _newUrl;
					}
					if(isUploadDeferred){
						uploadNext();					
					}else{
						
						for (var i:uint; i < this.pendingFiles.length; i++) {
							console.log("multi file - do upload name = ", this.pendingFiles[i].name);
							try{
								pendingFiles[i].upload(uploadURL, fieldName);
							}catch(e:Event){ console.error("Error uploading file: ", e); }
						};
					}
				}
			}catch(e:Event){ console.error("Error uploading all files: ", e);  }
		}
		
	 	
		private function onComplete(event:DataEvent):void {
			console.warn("Flash completed uploading a file....");
			
			var file:FileReference = FileReference(event.target);
			removePendingFile(file);
				
			//console.log("List-onComplete: event=" + event);
			var a:Array = event.data.split(",");
			va
 r o:Object = {};
			var i:uint;
			var r:RegExp = new RegExp(/\{|\}|<|>|"|'|\(|\)|;|,/g);
			var parseError:Boolean = false;
			for(i=0;i<a.length;i++){
				var keyValue:String = a[i];
				if(r.test(keyValue)){
					parseError = true;
					break;
				}
				o[keyValue.split("=")[0]] = keyValue.split("=")[1];
			}
			if(parseError){
				console.log("Reporting parse error");
				var msg:Object = {msg:"Error: Illegal characters found in file data: "+event.data, type:"parseError"};
				Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, msg));
				return;
			}
			
			console.log("List-Object created:", o);
			o.width = Number(o.width);
			o.height = Number(o.height);
			completeData.push(o);
			if(isDataComplete){
				selectedFiles.forEach(function(file:Object, index:uint, ar:Array):void{
					completeData.forEach(function(c:Object, index:uint, ar:Array):void{
						if(	c.name == file.name){
							c.type = file.type;
							c.size = file.size;
							c.creationDate = file.crea
 tionDate;
							c.modificationDate = file.modificationDate;
							c.creator = file.creator;
							//removeFile(c.name);
						}
					}, this);
				}, this);
				Topic.publish(new TopicEvent(Topic.FILES_UPLOADED, this, this.completeData));
				completeData = [];
				pendingFiles = [];
				selectedFiles = [];
				this.isDataComplete = false;
			}else if(isUploadDeferred){
				uploadNext();
			}
			
		}
		
		
		
	 
	 	public function removeFile(name:String):void{
			var i:uint;
			for (i=0;i<pendingFiles.length; i++) {
				if (pendingFiles[i].name == name) {
					pendingFiles.splice(i, 1);
					break;
				}
			}
			for (i=0;i<selectedFiles.length; i++) {
				if (selectedFiles[i].name == name) {
					selectedFiles.splice(i, 1);
					break;
				}
			}
		}
		
		private function removePendingFile(file:FileReference):void {
			var i:uint;
			for (i=0;i<pendingFiles.length; i++) {
				if (pendingFiles[i].name == file.name) {
					pendingFiles.splice(i, 1);
					if (pendingFiles.le
 ngth == 0) {
						this.isDataComplete = true;
					}
					return;
				}
			}
			for (i=0;i<selectedFiles.length; i++) {
				if (selectedFiles[i].name == file.name) {
					selectedFiles.splice(i, 1);
					break;
				}
			}
		}
		
		
		private function cancelHandler(event:Event):void {
			console.log("cancelHandler...")
			console.log("cancelHandler: event=" + event.target);
			console.log("cancelHandler: fileList array: " + this.fileList);
			var evt:TopicEvent = new TopicEvent(Topic.FILES_CANCELED);
			Topic.publish(evt);
		}
	 
		private function onProgress(event:ProgressEvent):void {
			try{
				var file:FileReference = FileReference(event.target);
				console.log("onProgress: name=" + file.name + " bytesLoaded=" + event.bytesLoaded + " bytesTotal=" + event.bytesTotal);
				var o:Object = {
					name:file.name,
					bytesLoaded:event.bytesLoaded,
					bytesTotal:event.bytesTotal
				}
				console.log("*SWF Progress: " + o.name, o.bytesLoaded, o.bytesTotal);
				Topic.publ
 ish(new TopicEvent(Topic.FILES_PROGRESS, this, o));
				
			} catch(e:Event){
				console.error("onProgress error", e);
				Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, e));
			}
		}
		
		private function httpErrorHandler(event:Event):void {
			console.error("httpErrorHandler: event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	 
		private function ioErrorHandler(event:Event):void {
			console.error("ioErrorHandler: event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	 
		private function securityErrorHandler(event:Event):void {
			console.error("securityErrorHandler: event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	}
}
\ No newline at end of file
+/*********************************************************************
 *	UploadList.as
 *
 *	class to handle multi-file uploads
 *
 *	version: 		1.4
 *	revision date:	2009-11-06
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.form {
	import deft.common.debugging.console;
	import deft.form.Uploader;
	import flash.utils.getTimer;
	import flash.utils.setTimeout;
	import flash.events.*;
	import flash.net.FileReference;
	import flash.net.FileReferenceList;
	import deft.common.events.TopicEvent;
	import deft.common.events.Topic;
	import flash.net.URLRequest;
	import deft.form.IUpload;
	import deft.form.File;
	
	public class UploadList extends FileReferenceList implements IUpload{
		
		private var completeData:Array = [];
		private var workingFiles:Array = [];
		private var files:Array = [];
		
		private var uploadURL:URLRequest;
		private var uploadOnSelect:Boolean;
		private var isLastFile:Boolean = false;
		privat
 e var uploadDeferred:Number = 1;
		private var fieldName:String;
		private var testIllegalCharacters:Boolean;
		private var startUploadTime:Number;
		private var lastUploadTime:Number;
		private var times:Object = {};
		private var serverTimeout:Number = 3000;
		
		public function UploadFile():void{}
		
		public function init(_uploadOnSelect:Boolean, _testIllegalCharacters:Boolean, stout:Number):void {
			// summary:
			// 		The pseudo constructor
			//
			serverTimeout = stout;
			uploadOnSelect = _uploadOnSelect;
			testIllegalCharacters = _testIllegalCharacters;
			addEventListener(Event.SELECT, onSelect);
			addEventListener(Event.CANCEL, cancelHandler);
			Topic.subscribe(Topic.FILE_COMPLETE, onComplete);
		};
		
		public function updateFunctionality(URI:URLRequest, _fieldName:String, _deferredUploading:Number):void {
			// summary:
			// 		When uploading, these are the props that can change
			//		(only partially implemented)
			uploadDeferred = _deferredUploading;
			
 uploadURL = URI;
			fieldName = _fieldName;
		}
		
		public function doBrowse(typeFilter:Array):void {
			// summary:
			// 		Opens the dialog box. Called from the Flash button.
			browse(typeFilter);
		}
		
		private function onSelect(event:Event):void {
			// summary:
			// 		Event fired when files are selected
			//
			// fileList:
			//		A FilereferenceList property; an array of FileReference objects.
		   console.log("onSelect: " + fileList.length + " files");
			
			var newFiles:Array = [];
			var file:deft.form.File;
			console.log("add selected files...");
			for (var i:uint = 0; i < fileList.length; i++) {
				file = new deft.form.File(fileList[i], event, testIllegalCharacters, serverTimeout);
				files.push(file);
				newFiles.push(file.getSelectedData());
			};
			console.log("added...")
			console.log("list:", newFiles);
			Topic.publish(new TopicEvent(Topic.FILES_SELECTED, this, newFiles));
			if(this.uploadOnSelect){
				console.log("multi auto upload, fieldNam
 e", fieldName);
				doUpload(uploadURL);
			}
		}
		
		
		
		public function doUpload(_newUrl:URLRequest=null):void {
			// summary:
			// 		Starts upload process. Called from JavaScript.
			//
			// TODO: fieldname could be incremented for server
			//
			try{
				
				console.log(" ********** doUpload Multi file amount:", files.length, "Deferred:", uploadDeferred);
				if(files.length){
					uploadURL = _newUrl ? _newUrl : uploadURL;
					var amt:Number = Math.min(files.length, uploadDeferred);
					console.log(" queing deferred files:", amt);
					for (var i:uint = 0; i < amt; i++) {
						uploadNext();					
					}
				}
				
			}catch(e:Event){ console.error("Error uploading all files: ", e);  }
		}
		
		private function uploadNext(uploadTime:Number = 0):void{
			// summary:
			//		Handles incremental upload. May be called 
			//		is sequence for parallel uploads or after
			//		the previous is complete - depending upon
			//		
			var file:deft.form.File = files.pop();
	
 		workingFiles.push(file);
			if (files.length == 0) {
				isLastFile = true;
			}
			file.lastUploadTime = uploadTime;
			file.doUpload(uploadURL, fieldName);			
		}
	 	
		private function onComplete(data:Object):void {
			// summary:
			//		Fires when a file completes. Checks if all files
			//		are complete and if so, fires a custom event
			//		for JavaScript. Otherwise triggers next upload.
			//
			// data.argObject is all public properties of deft.form.File
			//
			completeData.push(data.argObject);
			var f:deft.form.File = popWorkingFile(data.argObject.name);
			f.removeListeners();
			console.log("*****COMPLETE:", f);
			if(isLastFile){
				Topic.publish(new TopicEvent(Topic.FILES_UPLOADED, this, completeData));
				completeData = [];
				files = [];
				this.isLastFile = false;
			}else if(uploadDeferred){
				var self:Object = this;
				setTimeout(function():void{
					self.uploadNext(); 
				},30);
				
			}
			f = null;
		}
		private function popWorkingFile(na
 me:String):deft.form.File{
			// summary:
			//		Removes a File from the working list
			//		and returns it
			for (var i:uint = 0; i < workingFiles.length; i++) {
				if(workingFiles[i].name == name){
					var f:deft.form.File = workingFiles[i]
					workingFiles.splice(i, 1);
					return f;
				}
			}
			console.warn(" *** WARNING popWorkingFile - no file found", name);
			return null;
		}
		
		private function getFile(name:String):deft.form.File{
			// summary:
			//		Gets a file by name. If the same file
			//		has been loaded twice will simply get the first.
			//		If two files by the same name but from different
			//		folders are here, then you're in trouble.
			for (var i:uint = 0; i < files.length; i++) {
				if(files[i].name == name){
					return files[i];
				}
			}
			console.warn(" *** WARNING getSelectedFile - no file found", name);
			return null;
		}
	 
	 	public function removeFile(name:String):void{
			// summary:
			//		Removes a pending file from the list
 			//		Similar to getFile().
			//
			console.log(" * removeFile:", name);
			var i:uint;
			for (i=0;i<files.length; i++) {
				if (files[i].name == name) {
					files.splice(i, 1);
					break;
				}
			}
		}
		
		
		private function cancelHandler(event:Event):void {
			// summary
			//		triggered by close of the system dialog
			//
			var evt:TopicEvent = new TopicEvent(Topic.FILES_CANCELED);
			Topic.publish(evt);
		}
	 
		private function httpErrorHandler(event:Event):void {
			console.error("httpErrorHandler: event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	 
		private function ioErrorHandler(event:Event):void {
			console.error("ioErrorHandler: event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERROR, this, event));
		}
	 
		private function securityErrorHandler(event:Event):void {
			console.error("securityErrorHandler: event=" + event.toString());
			Topic.publish(new TopicEvent(Topic.FILES_ERRO
 R, this, event));
		}
	}
}
\ No newline at end of file

Modified: deft/trunk/deft/form/Uploader.as
==============================================================================
--- deft/trunk/deft/form/Uploader.as	(original)
+++ deft/trunk/deft/form/Uploader.as	Wed Nov 11 09:36:13 2009
@@ -1 +1 @@
-/*********************************************************************
 *	Uploader.as
 *
 *	main class, handles file uploads
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.form {

	import deft.common.debugging.console;
	import deft.common.debugging.Tracer;
	
	import flash.display.*;
	import flash.display.Stage
	import flash.display.StageAlign;
    import flash.display.StageScaleMode;
	
	import flash.system.Capabilities;
	import flash.utils.getQualifiedClassName;
    import flash.events.*;
    import flash.net.FileReference;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod
	import flash.net.URLVariables;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLLoader
	import flash.external.*;
	import flash.net.FileFilter;
	import flash.text.*;
	import flash.system.Security;
    
	import deft.form.UploadList;
	import deft.form.UploadFile;
 	
	
 	import deft.common.events.TopicEvent;
	import deft.common.events.Topic;
	import deft.form.IUpload;
	import deft.common.MovieIdentity;
	import deft.shapes.HtmlShape;
	import deft.shapes.HtmlText;
	import deft.shapes.Rect;
	import deft.common.events.Mouseable;
	import deft.common.events.Draggable
	import deft.common.flashvars;
	
	import flash.utils.Timer;
    import flash.events.TimerEvent;
	
    public class Uploader extends Sprite {
        
		public static var LIST_COMPLETE:String = "listComplete";
		public static var LIST_SELECT:String = "listSelect";
		public  var uploadUrl:String;
		private var uploadOnSelect:Boolean = true;
		private var fileRef:IUpload;
		private var htmlId:String;
		private var onSelectFilesCallback:String;
		private var onCompleteCallback:String;
		private var selectedFiles:Array = [];
		private var selectMultipleFiles:Boolean = true;
      	private var fileMask:Array = [];
		private var container:Sprite;
		private var buttonW:Number;
		private var 
 buttonH:Number;
		private var deferredUploading:Boolean = false;
		private var uploadDataFieldName:String = "Filedata";
		private var variables:URLVariables;
		private var postData:Object;
		private var params:Object;
		private var ideMode:Boolean = false;
		private var devMode:Boolean = false;
		private var request:URLRequest;
		public var flashVarKey:String = "flashButton";
		public var padding:Array=[0];
		
		private var logEnabled:Boolean = true;
		private var __count:Number = 0;
		
		private function log(...args):void{
			if(logEnabled){
				console.log.apply(console, args);
			}
		}
		private function count():void{
			__count++;
			log(__count);
		}
		
		public function Uploader(... args) {
			
			if(args.length==1){
				ideMode = true;
			}
			
			var obj:Object;
			if(ideMode){
				obj = {
					isDebug:true
				}
				devMode = true;
			}else{
				Security.allowDomain("*");
				obj = LoaderInfo(this.root.loaderInfo).parameters; 
			}
			
			var isDebug:Boolean = flash
 vars.getValue(obj.isDebug);
			logEnabled = isDebug;
			console.isDebug(isDebug);
			Tracer.init({prefix:"", both:isDebug});
			log("initializing flash...");
			
			try{
			
				uploadOnSelect 		= flashvars.getValue(obj.uploadOnSelect);
				selectMultipleFiles = flashvars.getValue(obj.selectMultipleFiles);
				uploadDataFieldName = flashvars.getValue(obj.uploadDataFieldName);
				deferredUploading 	= flashvars.getValue(obj.deferredUploading);
				htmlId 				= flashvars.getValue(obj.htmlId);
				uploadUrl 			= flashvars.getValue(obj.uploadUrl);
				buttonW 			= flashvars.getValue(obj.width);
				buttonH 			= flashvars.getValue(obj.height);
				devMode 			= flashvars.getValue(obj.devMode);
				
			}catch(e:Error){ console.error("error initializing vars:", e) }
			
			MovieIdentity.identity = obj.id || "default";
			
			if(obj.fileMask){
				try{
					var fm:Array = flashvars.deserialize(obj.fileMask);
					setFileMask(fm)
				}catch(e:Error){ console.error("error parsing fileM
 ask");}
			}
			
			if(!obj[flashVarKey]){
				console.warn("No button params passed in '"+flashVarKey+"'");
				stage.scaleMode = StageScaleMode.EXACT_FIT;
			}else{
				stage.align = StageAlign.TOP_LEFT;
				params = flashvars.deserialize(obj[flashVarKey]);		
			
			}
			//log("...............VARS:", obj);
			log(".............PARAMS:", params);
			
			Topic.subscribe(Topic.FILES_SELECTED, listSelectHandler);
			Topic.subscribe(Topic.FILES_UPLOADED, listCompleteHandler);
			
			provideCallback();
			// forcing this message regardless of isDebug
			var msg:Array = ["*SWF Loaded. isDebug: " + isDebug ];
			ExternalInterface.call.apply(null, ["console.log"].concat(msg));

			addButton();
		}

		
		private function openDialog():void {
			log("-----------open--------------");
			log("selectMultipleFiles:", selectMultipleFiles);
			
			if(!fileRef && selectMultipleFiles){
				log("* * * new UploadList()"); 
				fileRef = new UploadList();
			}else if(!fileRef){
				log("* * * ne
 w UploadFile()"); 
				fileRef = new UploadFile();
			}
			
			fileRef.init(buildUrl(), uploadDataFieldName, uploadOnSelect, deferredUploading);
			fileRef.doBrowse(fileMask);
		}
		
		private function doUpload(...args):void {
			if(!this.uploadOnSelect){
				if(args[0]){
					postData = args[0];
				}
				this.fileRef.doUpload(buildUrl());
			}
		}
		
		private function buildUrl():URLRequest{
			request = new URLRequest(uploadUrl);
			request.method = URLRequestMethod.POST;
			request.data = getPostData();
			
			//log(" * * *  buildUrl()", uploadUrl);
			//log(" * * *  PostData:", request.data)
			return request;
		}
		
		private function getPostData():URLVariables{
			var v:URLVariables = new URLVariables();
			if(postData){
				var n:String;
				for(n in postData){
					v[n] = postData[n];
				}
			}
			return v;
		}
		
		private function setFileMask(mask:Array):void{

			if(mask && getQualifiedClassName(mask)=="Array"){
				
				if(getQualifiedClassName(mask[0])=="Array
 "){
					for(var i:uint=0;i<mask.length;i++){
						fileMask.push(new FileFilter(mask[i][0], mask[i][1]));
					}
					
				}else if(mask.length){
					fileMask.push(new FileFilter(mask[0], mask[1]));
				}else{
					//default
					fileMask.push(new FileFilter("All Files", "*.*"));
				}
			}
		}
		
		
		
		private function listSelectHandler(event:Event):void {
            //log("listSelectHandler", event);
        }
		
		private function listCompleteHandler(event:Event):void {
            log(" * * * * files uploaded event listener");
			//fileRef = null;
        }
		
	   
	   
		/*public function getTypes():Array {
			var allTypes:Array = new Array();
			allTypes.push(getImageTypeFilter());
			allTypes.push(getTextTypeFilter());
			return allTypes;
		}
	 
		private function getImageTypeFilter():FileFilter {
			return new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg;*.jpeg;*.gif;*.png");
		}
	 
		private function getTextTypeFilter():FileFilter {
			return new F
 ileFilter("Text Files (*.txt, *.rtf)", "*.txt;*.rtf");
		}*/
		
		
		private function provideCallback():void{
			ExternalInterface.addCallback("openDialog",  openDialog);
			var self:Object = this;
			ExternalInterface.addCallback("doUpload", function(...args):void{
				log(" ---------------->  doUpload");
				self.doUpload.apply(self, args);
			}); 	 
			ExternalInterface.addCallback("removeFile", function(name:String):void{
				log(" * * * * removeFile:", name);
				if(self.fileRef){
					self.fileRef.removeFile(name);
				}
			});
			ExternalInterface.addCallback("testLoaded", function():Boolean{
				log(" * * * Uploader testLoaded true");
				return true;
			});
		}
		
		
		private function addButton():void{
			if(params){
				try{
					addVisibleButton()
				}catch(e:Error){ console.error("Error Building Flash Button", e);}
			}else{
				addInvisibleButton()
			}
		}
		private function addVisibleButton():void{
			if(!params.nr.m){
				params.nr.m = [0];
			}
			if(!para
 ms.nr.p){
				params.nr.p = [0];
			}
			params.tx = flashvars.mixin(params.nr, {});
			params.txo = flashvars.mixin(params.ov, {});
			params.txd = flashvars.mixin(params.dn, {});
			params.txds = flashvars.mixin(params.ds, {});
			
			params.ht = flashvars.mixin(params.nr, {});
			params.ht.a = .01;
			delete params.ht.bi;
			params.ht.bc = 0xff0000;
			params.tx.cn = params.cn
			params.dn.w = params.ov.w = params.ds.w = params.nr.w;
			params.dn.h = params.ov.h = params.ds.h = params.nr.h;
			padding = params.nr.p;
			
			log("norm shape...");
			try{
				var norm:HtmlShape = new HtmlShape(params.nr, this, "NORM");
				addChild(norm);
				norm.mouseEnabled = false;
				norm.tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlShape NORM");
			}
			
			try{
				var over:HtmlShape = new HtmlShape(params.ov, this, "OVER");
				addChild(over);
				over.mouseEnabled = false;
				over.tabEnabled = false;
				over.visible = false;
			}catch(e:Error){
		
 		console.error("Error Creating HtmlShape OVER");
			}
			
			try{
				var down:HtmlShape = new HtmlShape(params.dn, this, "DOWN");
				addChild(down);
				down.mouseEnabled = false;
				down.visible = false;
				down.tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlShape DOWN");
			}
			
			try{
				var dsbl:HtmlShape = new HtmlShape(params.ds, this, "DSBL");
				addChild(dsbl);
				dsbl.mouseEnabled = false;
				dsbl.visible = false;
				dsbl.tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlShape DSBL");
			}
			
			log("Build HtmlText:", params.tx);
			try{
				var txt:HtmlText = new HtmlText(params.tx, params.txo, params.txd, params.txds, this)
				addChild(txt);
				txt.tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlText");
			}
			
			try{
				var hitMC:HtmlShape = new HtmlShape(params.ht, this, "HIT");
				addChild(hitMC);
				hitMC.tabEnabled = false;
			}catch(e:Error){
				cons
 ole.error("Error Creating HtmlShape HIT");
			}
			
			var _onMouse:Function = function(evt:MouseEvent):void{
				norm.visible = evt.type=="mouseOut"||evt.type=="mouseUp" ? true : false;
				over.visible = evt.type=="mouseOver" ? true : false;
				down.visible = evt.type=="mouseDown" ? true : false;
				if(evt.type=="mouseUp"){
					onMouse("up");
				}
				txt.onMouse(evt.type);
			}
			hitMC.addEventListener(MouseEvent.MOUSE_DOWN, _onMouse);
			hitMC.addEventListener(MouseEvent.MOUSE_OVER, _onMouse);
			hitMC.addEventListener(MouseEvent.MOUSE_UP, _onMouse);
			hitMC.addEventListener(MouseEvent.MOUSE_OUT, _onMouse);
			hitMC.useHandCursor = true;
			hitMC.buttonMode = true;
			
			ExternalInterface.addCallback("doDisable", function(dis:Boolean):void{
				log(" * * * Flash Uploader Disable::", dis);
				if(dis){
					txt.onMouse("disabled");
					hitMC.visible = false;
					norm.visible = false;
					dsbl.visible = true;
				}else{
					txt.onMouse("enabled");
					hitMC.vis
 ible = true;
					norm.visible = true;
					dsbl.visible = false;
					
				}
			});
			
			
			ExternalInterface.addCallback("doFocus", function():void{
				// a11y TODO:
				//	doFocus is called when the HTML element is tabbed to.
				//	Detect the ENTER key and trigger browse.(this much works).
				//	Problem is we can't tab out. Look into checking for TAB
				//	key and calling js.doBlur or something which maybe call flashMov.blur()
				//	and then hopefully the key-up (tab) will be captured and next component
				//	will be tabbed to.
				log(" * * * Flash Uploader Focus");
			});
			log("stage:", stage.stageWidth, stage.stageHeight);
			function reportKeyDown(event:KeyboardEvent):void{
				log("Key Pressed: character code: ", event.charCode );
				if(event.charCode==13){
					onMouse("up");
				}
				if(event.charCode==9){
					event.stopImmediatePropagation();
					var evt:TopicEvent = new TopicEvent(Topic.STAGE_BLUR, this, [true]);
					Topic.publish(evt);
				}
				
 
			}
			stage.addEventListener(KeyboardEvent.KEY_DOWN, reportKeyDown);
			
		}
		private function addInvisibleButton():void{
			// deprecrated
			log("Creating invisible button");
			// In IE, if the embed container isn't showing yet, we get w:0, h:0
			// fall back on something that should be big enough.
			//	Yes. IE even messes up stuff here.
			var w:Number = stage.stageWidth || 300;
			var h:Number = stage.stageHeight || 100;
			var a:Number = devMode ? .3 : 0;
			var r:Rect = new Rect({w:w, h:h, lineThickness:0, alpha:a});
			var s:Sprite = new Sprite();
			addChild(s)
			s.addChild(r)
			var m:Mouseable = new deft.common.events.Mouseable(s, onMouse);
		}
		private function onMouse(type:String):void{
			var args:Array = [
				"dojo.publish",
				MovieIdentity.identity+"/"+type,
				[type]
			];
			ExternalInterface.call.apply(null, args);
			
			switch(type){
				case "up":
					openDialog();
				break;
				case "down":
					//log("DOWN");
				break;
				case "over":
 					//log("OVER");
				break;
				case "out":
					//log("OUT");
				break;
			}
		}
		
		
    }
}
 
\ No newline at end of file
+/*********************************************************************
 *	Uploader.as
 *
 *	main class, handles file uploads
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.form {

	import deft.common.debugging.console;
	import deft.form.UploadList;
	import deft.form.UploadFile;
	import deft.common.events.TopicEvent;
	import deft.common.events.Topic;
	import deft.form.IUpload;
	import deft.common.MovieIdentity;
	import deft.shapes.HtmlShape;
	import deft.shapes.HtmlText;
	import deft.shapes.Rect;
	import deft.common.events.Mouseable;
	import deft.common.flashvars;
	
	import flash.display.*;
	import flash.display.Stage
	import flash.display.StageAlign;
    import flash.display.StageScaleMode;
	import flash.system.Capabilities;
	import flash.utils.getQualifiedClassName;
    import flash.events.*;
    import flash.net.FileReference;
	import flash.net.URLRequest;
	i
 mport flash.net.URLRequestMethod
	import flash.net.URLVariables;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLLoader
	import flash.external.*;
	import flash.net.FileFilter;
	import flash.text.*;
	import flash.system.Security;
    import flash.utils.Timer;
    import flash.events.TimerEvent;
	
    public class Uploader extends Sprite {
        public var flashVarKey:String = "flashButton";
		public var padding:Array=[0];
		public static var LIST_COMPLETE:String = "listComplete";
		public static var LIST_SELECT:String = "listSelect";
		public  var uploadUrl:String;
		
		private var uploadOnSelect:Boolean = true;
		private var fileRef:IUpload;
		private var testIllegalCharacters:Boolean = true;
		private var htmlId:String;
		private var onSelectFilesCallback:String;
		private var onCompleteCallback:String;
		private var selectedFiles:Array = [];
		private var selectMultipleFiles:Boolean = true;
      	private var fileMask:Array = [];
		private var container:Sprit
 e;
		private var buttonW:Number;
		private var buttonH:Number;
		private var deferredUploading:Number = 1;
		private var uploadDataFieldName:String = "Filedata";
		private var variables:URLVariables;
		private var postData:Object;
		private var params:Object;
		private var ideMode:Boolean = false;
		private var devMode:Boolean = false;
		private var request:URLRequest;
		private var logEnabled:Boolean = true;
		private var __count:Number = 0;
		private var serverTimeout:Number = 3000;
		
		public function Uploader(... args) {
			// summary:
			//		Main cnstructor for Uploader SWF
			//
			
			// FlashVars - the data passed with teh query string -
			// are accessed here
			var obj:Object = LoaderInfo(this.root.loaderInfo).parameters; 
			var isDebug:Boolean = flashvars.getValue(obj.isDebug);
			
			isDebug = true;
			console.isDebug(true);
			logEnabled = isDebug;
			
			log("initializing flash...");
			Security.allowDomain("*");
			
			
			try{
			
				uploadOnSelect 		= fl
 ashvars.getValue(obj.uploadOnSelect);
				selectMultipleFiles = flashvars.getValue(obj.selectMultipleFiles);
				uploadDataFieldName = flashvars.getValue(obj.uploadDataFieldName);
				deferredUploading 	= flashvars.getValue(obj.deferredUploading);
				htmlId 				= flashvars.getValue(obj.htmlId);
				uploadUrl 			= flashvars.getValue(obj.uploadUrl);
				buttonW 			= flashvars.getValue(obj.width);
				buttonH 			= flashvars.getValue(obj.height);
				devMode 			= flashvars.getValue(obj.devMode);
				serverTimeout		= Math.max(1000, flashvars.getValue(obj.serverTimeout));
				var chk:* = flashvars.getValue(obj.noReturnCheck);
				if(chk){
					testIllegalCharacters = false;
				}
				if(typeof(deferredUploading) != "number" || !deferredUploading){
					deferredUploading = 1;
				}
			}catch(e:Error){ console.error("error initializing vars:", e) }
			
			log("serverTimeout:", serverTimeout);
			MovieIdentity.identity = obj.id || "default";
			
			if(obj.fileMask){
				try{
					va
 r fm:Array = flashvars.deserialize(obj.fileMask);
					setFileMask(fm)
				}catch(e:Error){ console.error("error parsing fileMask");}
			}
			
			// flashVarKey: the key that holds the FlashVar data
			if(!obj[flashVarKey]){
				console.warn("No button params passed in '"+flashVarKey+"'");
				stage.scaleMode = StageScaleMode.EXACT_FIT;
			}else{
				stage.align = StageAlign.TOP_LEFT;
				params = flashvars.deserialize(obj[flashVarKey]);		
			
			}
			
			//log("...............VARS:", obj);
			log(".............PARAMS:", params);
			
			provideCallback();
			addButton();
			
			// forcing this message regardless of isDebug
			ExternalInterface.call.apply(null, ["console.log"].concat(["*SWF Loaded. isDebug: " + isDebug + " devMode:" +devMode ]));

		}
		
		
		private function log(...args):void{
			// summary:
			//		Each class has it's own log method which passes
			//		through EI and to the browser console
			if(logEnabled){
				console.log.apply(console, args);
			}
		}
		
 		private function openDialog(...args):void {
			// summary:
			//		PUBLIC
			//		Method to open system dialog. This is also where
			//		iUpload is initialized
			//
			if(args[0]){
				if(args[0].fileMask){
					setFileMask(args[0].fileMask);
				}
			}
			
			log("selectMultipleFiles:", selectMultipleFiles);
			
			if(!fileRef && selectMultipleFiles){
				fileRef = new UploadList();
				fileRef.init(uploadOnSelect, testIllegalCharacters, serverTimeout);
			}else if(!fileRef){
				fileRef = new UploadFile();
				fileRef.init(uploadOnSelect, testIllegalCharacters, serverTimeout);
			}
			
			fileRef.updateFunctionality(buildUrl(), uploadDataFieldName, deferredUploading);
			
			fileRef.doBrowse(fileMask);
		}
		
		private function doUpload(...args):void {
			// summary:
			//		PUBLIC
			//		Method to start upload
			//
			if(!this.uploadOnSelect){
				if(args[0] !== undefined){
					postData = args[0];
				}
				if(args[1]){
					if(args[1].uploadDataFieldName){
						
				
 	}
					if(args[1].uploadUrl){
						
					}
					if(args[1].deferredUploading){
						
					}
				}
				console.log(" * doUpload - GO", buildUrl());
				this.fileRef.doUpload(buildUrl());
			}
		}
		
		private function buildUrl():URLRequest{
			// summary:
			//		Builds Flash-specific URL based on 
			//		the url passed in arguments
			request = new URLRequest(uploadUrl);
			request.method = URLRequestMethod.POST;
			request.data = getPostData();
			return request;
		}
		
		private function getPostData():URLVariables{
			// summary:
			//		Builds Flash-specific postData based on 
			//		the object passed in arguments
			var v:URLVariables = new URLVariables();
			if(postData){
				var n:String;
				for(n in postData){
					v[n] = postData[n];
				}
			}
			return v;
		}
		
		private function setFileMask(mask:Array):void{
			// summary:
			//		Builds the FileMask based on 
			//		the arguments
			//
			if(mask && getQualifiedClassName(mask)=="Array"){
				
				if(getQualifie
 dClassName(mask[0])=="Array"){
					for(var i:uint=0;i<mask.length;i++){
						fileMask.push(new FileFilter(mask[i][0], mask[i][1]));
					}
					
				}else if(mask.length){
					fileMask.push(new FileFilter(mask[0], mask[1]));
				}else{
					//default
					fileMask.push(new FileFilter("All Files", "*.*"));
				}
			}
		}
		
		private function addButton():void{
			// summary:
			//		Builds each state of the button based on params
			//
			if(!params.nr.m){
				params.nr.m = [0];
			}
			if(!params.nr.p){
				params.nr.p = [0];
			}
			params.tx = flashvars.mixin(params.nr, {});
			params.txo = flashvars.mixin(params.ov, {});
			params.txd = flashvars.mixin(params.dn, {});
			params.txds = flashvars.mixin(params.ds, {});
			
			params.ht = flashvars.mixin(params.nr, {});
			params.ht.a = .01;
			delete params.ht.bi;
			params.ht.bc = 0xff0000;
			params.tx.cn = params.cn
			params.dn.w = params.ov.w = params.ds.w = params.nr.w;
			params.dn.h = params.ov.h = params.ds.h = pa
 rams.nr.h;
			padding = params.nr.p;
			
			try{
				var norm:HtmlShape = new HtmlShape(params.nr, this, "NORM", devMode);
				addChild(norm);
				norm.mouseEnabled = false;
				norm.tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlShape NORM");
			}
			
			try{
				var over:HtmlShape = new HtmlShape(params.ov, this, "OVER", devMode);
				addChild(over);
				over.mouseEnabled = false;
				over.tabEnabled = false;
				over.visible = false;
			}catch(e:Error){
				console.error("Error Creating HtmlShape OVER");
			}
			
			try{
				var down:HtmlShape = new HtmlShape(params.dn, this, "DOWN", devMode);
				addChild(down);
				down.mouseEnabled = false;
				down.visible = false;
				down.tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlShape DOWN");
			}
			
			try{
				var dsbl:HtmlShape = new HtmlShape(params.ds, this, "DSBL", devMode);
				addChild(dsbl);
				dsbl.mouseEnabled = false;
				dsbl.visible = false;
				dsbl
 .tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlShape DSBL");
			}
			
			
			try{
				var txt:HtmlText = new HtmlText(params.tx, params.txo, params.txd, params.txds, this, devMode)
				addChild(txt);
				txt.tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlText");
			}
			
			try{
				var hitMC:HtmlShape = new HtmlShape(params.ht, this, "HIT");
				addChild(hitMC);
				hitMC.tabEnabled = false;
			}catch(e:Error){
				console.error("Error Creating HtmlShape HIT");
			}
			
			var _onMouse:Function = function(evt:MouseEvent):void{
				norm.visible = evt.type=="mouseOut"||evt.type=="mouseUp" ? true : false;
				over.visible = evt.type=="mouseOver" ? true : false;
				down.visible = evt.type=="mouseDown" ? true : false;
				if(evt.type=="mouseUp"){
					onMouse("up");
				}
				txt.onMouse(evt.type);
			}
			hitMC.addEventListener(MouseEvent.MOUSE_DOWN, _onMouse);
			hitMC.addEventListener(MouseEvent.MOUSE_OVER, _onMo
 use);
			hitMC.addEventListener(MouseEvent.MOUSE_UP, _onMouse);
			hitMC.addEventListener(MouseEvent.MOUSE_OUT, _onMouse);
			hitMC.useHandCursor = true;
			hitMC.buttonMode = true;
			
			ExternalInterface.addCallback("doDisable", function(dis:Boolean):void{
				log(" * Flash Uploader Toggle Disable::", dis);
				if(dis){
					txt.onMouse("disabled");
					hitMC.visible = false;
					norm.visible = false;
					dsbl.visible = true;
				}else{
					txt.onMouse("enabled");
					hitMC.visible = true;
					norm.visible = true;
					dsbl.visible = false;
					
				}
			});
			
			// Detect Tab-to. Problems. Doesn't work in HTML anyway
			// due to security
			ExternalInterface.addCallback("doFocus", function():void{
				// a11y TODO:
				//	doFocus is called when the HTML element is tabbed to.
				//	Detect the ENTER key and trigger browse.(this much works).
				//	Problem is we can't tab out. Look into checking for TAB
				//	key and calling js.doBlur or something which maybe ca
 ll flashMov.blur()
				//	and then hopefully the key-up (tab) will be captured and next component
				//	will be tabbed to.
				//log(" * Flash Uploader Focus");
			});
			
			// Detect ENTER key to trigger upload needs to work with onFocus)
			function reportKeyDown(event:KeyboardEvent):void{
				//log("Key Pressed: character code: ", event.charCode );
				if(event.charCode==13){
					onMouse("up");
				}
				if(event.charCode==9){
					event.stopImmediatePropagation();
					var evt:TopicEvent = new TopicEvent(Topic.STAGE_BLUR, this, [true]);
					Topic.publish(evt);
				}
				
			}
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, reportKeyDown);
			
		}
		
		private function onMouse(type:String):void{
			// summary:
			//		Handle Mouse events on button states
			//
			var args:Array = [
				"dojo.publish",
				MovieIdentity.identity+"/"+type,
				[type]
			];
			ExternalInterface.call.apply(null, args);
			
			switch(type){
				case "up":
					openDialog();
				break;
 
				case "down":
					//log("DOWN");
				break;
				case "over":
					//log("OVER");
				break;
				case "out":
					//log("OUT");
				break;
			}
		}
		
		private function provideCallback():void{
			// summary:
			//		Set up EI
			//
			ExternalInterface.addCallback("openDialog",  openDialog);
			var self:Object = this;
			ExternalInterface.addCallback("doUpload", function(...args):void{
				//log(" ---------------->  doUpload");
				self.doUpload.apply(self, args);
			}); 	 
			ExternalInterface.addCallback("removeFile", function(name:String):void{
				//log(" * * * * removeFile:", name);
				if(self.fileRef){
					self.fileRef.removeFile(name);
				}
			});
			ExternalInterface.addCallback("testLoaded", function():Boolean{
				log(" * * * Uploader testLoaded true");
				return true;
			});
		}
		
    }
}
 
\ No newline at end of file

Modified: deft/trunk/deft/shapes/HtmlShape.as
==============================================================================
--- deft/trunk/deft/shapes/HtmlShape.as	(original)
+++ deft/trunk/deft/shapes/HtmlShape.as	Wed Nov 11 09:36:13 2009
@@ -1 +1 @@
-/*********************************************************************
 *	HtmlShape.as
 *
 *	class to create rectangles based on HTML data
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.shapes {
	
	import flash.display.*;
	import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.*;
    import flash.net.URLRequest;
	import deft.common.debugging.console;
	
	public class HtmlShape extends Sprite {
		
		public var padding:Array=[0];
		private var image:Bitmap;
		private var imageWidth:Number;
		private var imageHeight:Number;
		private var url:String;
		private var logEnabled:Boolean = false;
		
		public function HtmlShape(style:Object, parent:Object, type:String):void{
			
			logEnabled = type=="DSBL";
			
			padding = style.p;
			log("HtmlShape:", type, style);
			t
 ry{
			draw(style, parent, new Sprite(), type);
			}catch(e:Error){ console.error("Flash.HtmlShape.error:", e); }
		}
		
		private function log(...args):void{
			if(logEnabled){
				console.log.apply(console, args);
			}
		}
		private function count(num:Number):void{
			//log(num);
		}
		private function draw(o:Object, parent:Object, container:Sprite, type:String):void{
			//graphics.clear();
		count(1);
			//if(o.bw[0]) graphics.lineStyle(o.bw[0], o.bc);

			var p:Array = [0]; //parent.padding && parent.padding.length ? parent.padding : [0];
			var x:Number = o.m ? o.m.length>1 ? o.m[3] : o.m[0] : 0;
			x = p.length>1 ? x+p[3] : x+p[0]; 
			var y:Number = o.m ? o.m[0] + p[0] : 0;
		count(2)
			var w:Number = o.w - x*2;
			var h:Number = o.h - y*2;
			var c:Number = o.bc; 
			
			var bmpx:Number = 0;
			var bmpy:Number = 0;
				
			if(image){
				
				w = imageWidth;
				h = imageHeight;
				
				var rx:String = o.bi.pos.split(" ")[0];
				var ry:String = o.bi.pos.split(" ")
 [1];
				log("IMAGE", type, w, h, " RX:", rx, "RY:", ry);
				var ny:Number;
				if(ry.indexOf("%")>-1){
					ny = parseInt(ry.replace("%", ""))*.01;
					y = ny*o.h - ny*imageHeight;
				}else{
					ny = parseInt(ry, 10);
					y = ny;
				}
				
				var nx:Number;
				if(rx.indexOf("%")>-1){
					nx = parseInt(rx.replace("%", ""))*.01;
					x = nx*o.h - nx*imageWidth;
				}else{
					nx = parseInt(rx, 10);
					x = nx;
				}
				
				if(o.bi.rp=="repeat-x"){
					x = 0;
					h = imageHeight;
					w = o.w - x*2;
					
				}else if(o.bi.rp=="repeat-y"){
					//TODO
					y = 0;
					w = imageWidth;
					h = o.h - y*2;
				}else if(o.bi.rp=="repeat"){
					//TODO
					x = 0;
					y = 0;
					w = o.w - x*2;
					h = o.h - y*2;
				}
				log("IMAGE:::", x,y,w,h,o.bi.url);
				
				//container.graphics.lineStyle(1, 0x000000);
					
				if(o.bi && o.bi.rp && (o.bi.rp=="repeat-x" || o.bi.rp=="repeat-y" || o.bi.rp=="repeat")){
					// position sprite, not bitmap
					container.graphi
 cs.beginBitmapFill(image.bitmapData, null, true, false); // 3rd is repeat, 4h is smooth
				}else{
					container.graphics.beginBitmapFill(image.bitmapData, null, true, false); // 3rd is repeat, 4h is smooth
					// position bitmap, not sprite
					//bmpx = x*-1;
					//bmpy = y*-1;
					//x = 0;
					//y = 0;
					
					log("BACKGROUND POSITION:", bmpx, bmpy);
				}
			}else{
				container.graphics.beginFill(c, o.a || 1);
			}
		count(4);
	log("draw:::", x, y, w, h, "("+bmpx+","+bmpy+")");
			container.graphics.drawRect(bmpx, bmpy, w, h);
			container.graphics.endFill();
		count(5)
			container.x = x;
			container.y = y;
			addChild(container);
		count(6)
			if(o.bi && !image){
				log("bk image", type);
				
				url = o.bi.url;
				url = url.replace(/\|\|/g,":").replace(/\^\^/g,".");
				log("   url:", url);
				var loader:Loader = new Loader();
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void{
					var loader:Loader = Loader(event.t
 arget.loader);
            		image = Bitmap(loader.content);
					imageWidth = loader.width;
					imageHeight = loader.height;
					log("LOADED ---> image size:", imageWidth, imageHeight);
					draw(o, parent, new Sprite(), type);
				});
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				var request:URLRequest = new URLRequest(url);
				loader.load(request);
			}
		}
		private function ioErrorHandler(event:IOErrorEvent):void {
            console.error("Unable to load image: " + url);
        }
	}
}
\ No newline at end of file
+/*********************************************************************
 *	HtmlShape.as
 *
 *	class to create rectangles based on HTML data
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.shapes {
	
	import flash.display.*;
	import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.*;
    import flash.net.URLRequest;
	import deft.common.debugging.console;
	
	public class HtmlShape extends Sprite {
		
		public var padding:Array=[0];
		private var image:Bitmap;
		private var imageWidth:Number;
		private var imageHeight:Number;
		private var url:String;
		private var logEnabled:Boolean = false;
		
		public function HtmlShape(style:Object, parent:Object, type:String, _log:Boolean=false):void{
			
			logEnabled = _log; //type=="DSBL";
			
			padding = style.p;
			log("Htm
 lShape:", type, style);
			try{
			draw(style, parent, new Sprite(), type);
			}catch(e:Error){ console.error("Flash.HtmlShape.error:", e); }
		}
		
		private function log(...args):void{
			if(logEnabled){
				console.log.apply(console, args);
			}
		}
		private function count(num:Number):void{
			//log(num);
		}
		private function draw(o:Object, parent:Object, container:Sprite, type:String):void{
			//graphics.clear();
		count(1);
			//if(o.bw[0]) graphics.lineStyle(o.bw[0], o.bc);

			var p:Array = [0]; //parent.padding && parent.padding.length ? parent.padding : [0];
			var x:Number = o.m ? o.m.length>1 ? o.m[3] : o.m[0] : 0;
			x = p.length>1 ? x+p[3] : x+p[0]; 
			var y:Number = o.m ? o.m[0] + p[0] : 0;
		count(2)
			var w:Number = o.w - x*2;
			var h:Number = o.h - y*2;
			var c:Number = o.bc; 
			
			var bmpx:Number = 0;
			var bmpy:Number = 0;
				
			if(image){
				
				w = imageWidth;
				h = imageHeight;
				
				var rx:String = o.bi.pos.split(" ")[0];
				var ry:
 String = o.bi.pos.split(" ")[1];
				log("IMAGE", type, w, h, " RX:", rx, "RY:", ry);
				var ny:Number;
				if(ry.indexOf("%")>-1){
					ny = parseInt(ry.replace("%", ""))*.01;
					y = ny*o.h - ny*imageHeight;
				}else{
					ny = parseInt(ry, 10);
					y = ny;
				}
				
				var nx:Number;
				if(rx.indexOf("%")>-1){
					nx = parseInt(rx.replace("%", ""))*.01;
					x = nx*o.h - nx*imageWidth;
				}else{
					nx = parseInt(rx, 10);
					x = nx;
				}
				
				if(o.bi.rp=="repeat-x"){
					x = 0;
					h = imageHeight;
					w = o.w - x*2;
					
				}else if(o.bi.rp=="repeat-y"){
					//TODO
					y = 0;
					w = imageWidth;
					h = o.h - y*2;
				}else if(o.bi.rp=="repeat"){
					//TODO
					x = 0;
					y = 0;
					w = o.w - x*2;
					h = o.h - y*2;
				}
				log("IMAGE:::", x,y,w,h,o.bi.url);
				
				//container.graphics.lineStyle(1, 0x000000);
					
				if(o.bi && o.bi.rp && (o.bi.rp=="repeat-x" || o.bi.rp=="repeat-y" || o.bi.rp=="repeat")){
					// position sprite, not 
 bitmap
					container.graphics.beginBitmapFill(image.bitmapData, null, true, false); // 3rd is repeat, 4h is smooth
				}else{
					container.graphics.beginBitmapFill(image.bitmapData, null, true, false); // 3rd is repeat, 4h is smooth
					// position bitmap, not sprite
					//bmpx = x*-1;
					//bmpy = y*-1;
					//x = 0;
					//y = 0;
					
					log("BACKGROUND POSITION:", bmpx, bmpy);
				}
			}else{
				container.graphics.beginFill(c, o.a || 1);
			}
		count(4);
	log("draw:::", x, y, w, h, "("+bmpx+","+bmpy+")");
			container.graphics.drawRect(bmpx, bmpy, w, h);
			container.graphics.endFill();
		count(5)
			container.x = x;
			container.y = y;
			addChild(container);
		count(6)
			if(o.bi && !image){
				log("bk image", type);
				
				url = o.bi.url;
				url = url.replace(/\|\|/g,":").replace(/\^\^/g,".");
				log("   url:", url);
				var loader:Loader = new Loader();
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void{
					var lo
 ader:Loader = Loader(event.target.loader);
            		image = Bitmap(loader.content);
					imageWidth = loader.width;
					imageHeight = loader.height;
					log("LOADED ---> image size:", imageWidth, imageHeight);
					draw(o, parent, new Sprite(), type);
				});
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				var request:URLRequest = new URLRequest(url);
				loader.load(request);
			}
		}
		private function ioErrorHandler(event:IOErrorEvent):void {
            console.error("Unable to load image: " + url);
        }
	}
}
\ No newline at end of file

Modified: deft/trunk/deft/shapes/HtmlText.as
==============================================================================
--- deft/trunk/deft/shapes/HtmlText.as	(original)
+++ deft/trunk/deft/shapes/HtmlText.as	Wed Nov 11 09:36:13 2009
@@ -1 +1 @@
-/*********************************************************************
 *	HtmlText.as
 *
 *	class to create text based on HTML data
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.shapes {
	
	import flash.display.*;
	import flash.text.*;
	
	import deft.common.debugging.console;
	
	public class HtmlText extends Sprite {
		
		public var padding:Array = [0];
		
		private var textElement:TextField;
		private var formatNorm:TextFormat;
		private var formatOver:TextFormat;
		private var formatDown:TextFormat;
		private var formatDisabled:TextFormat;
		
		public function HtmlText(style:Object, styleOver:Object, styleDown:Object, styleDisable:Object, container:Object):void{
			
			log("--------------------HtmlText:::", style.cn);
			
			try{
				formatNorm = createFormat(style);
				formatOver = createFormat(styleOver);
				formatDown = createFormat(styleDown);
				form
 atDisabled = createFormat(styleDisable);
				
			}catch(e:Error){ console.error("Flash.HtmlText - error creating text formats:", e); }
		
			try{
				textElement = draw(style, container);
			}catch(e:Error){ console.error("Flash.HtmlText.error:", e); }
		}
		
		public function onMouse(type:String):void{
			if(type=="mouseOut"||type=="mouseUp"||type=="enabled"){
				textElement.setTextFormat(formatNorm);
			}else if(type=="mouseOver"){
				textElement.setTextFormat(formatOver);
			}else if(type=="mouseDown"){
				textElement.setTextFormat(formatDown);
			}else if(type=="disabled"){
				textElement.setTextFormat(formatDisabled);
			}
		}
		private function createFormat(o:Object):TextFormat{
			var f:TextFormat = new TextFormat();
			f.color = o.fc;
			f.font = o.ff;
			f.size = o.fs;
			f.align = o.ta;
			f.bold = o.fw=="bold";
			f.italic = o.fi=="italic";
			return f;
		}
		
		private function log(...args):void{
			console.log.apply(console, args);
		}
		
		private function 
 draw(o:Object, container:Object):TextField{
			// to center text:
			//	set width and height first, then autoSize
			//	then multiline/wordWrap
			//	then format with align = center
			//
			var t:TextField = new TextField(); 
			
			//t.embedFonts = true;
			//t.blendMode = BlendMode.LAYER; // if we need opacity
			
			t.width = o.w;
			t.height = o.h;
			t.autoSize = o.ta;
			
			
			//	t.border = true;
			
			t.multiline = true;
			t.wordWrap = true;
				
			if(o.cn.indexOf("<")>-1){
				t.htmlText = o.cn;
			}else{
				t.text = o.cn;
			}
			
			
			var p:Array = container && container.padding && container.padding.length ? container.padding : [0];
			
			if(!o.p){
				o.p = [0,0,0,0];
			}else if(o.p.length==1){
				o.p=[o.p,o.p,o.p,o.p];
			}
			if(!o.m){
				o.m = [0,0,0,0];
			}else if(o.m.length==1){
				o.m = [o.m,o.m,o.m,o.m];
			}
			
			t.selectable = false;
			
			
			t.setTextFormat(formatNorm);
			
			
			if(o.va=="middle"){
				t.y = (o.h-t.height)/2;
			}els
 e if(o.va=="bottom"){
				t.y = o.h-t.height - o.p[2] - o.m[2];
				log("   bottom:", t.y, t.height, o.p[2], o.m[2]);
			}else{ // top
				t.y = o.m[0] + p[0];
			}
			log("................TEXT COLOR:", o.ta, o.fc, o.va);
			log("................Padding:", p, o.p);
			//log("text height:", t.y, t.height, o.h, o.h-t.height,(o.h-t.height)/2);  
			
			if(o.ta=="center"){
				t.x = (o.w - t.width)/2;
			}else if(o.ta == "right"){
				t.x = o.w - t.width - o.p[1] - o.m[1];
				log("   right:", t.x, o.w, t.width, o.p[1], o.m[1]);
			}else{ // left
				t.x = o.m.length>1 ? o.m[3] : o.m[0];
				t.x = p.length>1 ? t.x+p[3] : t.x+p[0]; 
			}
			
			addChild(t);
			return t;
		}
	}
}
\ No newline at end of file
+/*********************************************************************
 *	HtmlText.as
 *
 *	class to create text based on HTML data
 *
 *	version: 		1.4
 *	revision date:	2009-04-27
 *	authors:		Mike Wilcox
 *********************************************************************/
package deft.shapes {
	
	import flash.display.*;
	import flash.text.*;
	
	import deft.common.debugging.console;
	
	public class HtmlText extends Sprite {
		
		public var padding:Array = [0];
		
		private var textElement:TextField;
		private var formatNorm:TextFormat;
		private var formatOver:TextFormat;
		private var formatDown:TextFormat;
		private var formatDisabled:TextFormat;
		private var logEnabled:Boolean = false;
		
		public function HtmlText(style:Object, styleOver:Object, styleDown:Object, styleDisable:Object, container:Object, _log:Boolean=false):void{
			logEnabled = _log;
			log("--------------------HtmlText:::", style.cn);
			
			try{
				formatNorm = createFormat(style);
				formatOv
 er = createFormat(styleOver);
				formatDown = createFormat(styleDown);
				formatDisabled = createFormat(styleDisable);
				
			}catch(e:Error){ console.error("Flash.HtmlText - error creating text formats:", e); }
		
			try{
				textElement = draw(style, container);
			}catch(e:Error){ console.error("Flash.HtmlText.error:", e); }
		}
		
		private function log(...args):void{
			if(logEnabled){
				console.log.apply(console, args);
			}
		}
		
		public function onMouse(type:String):void{
			if(type=="mouseOut"||type=="mouseUp"||type=="enabled"){
				textElement.setTextFormat(formatNorm);
			}else if(type=="mouseOver"){
				textElement.setTextFormat(formatOver);
			}else if(type=="mouseDown"){
				textElement.setTextFormat(formatDown);
			}else if(type=="disabled"){
				textElement.setTextFormat(formatDisabled);
			}
		}
		private function createFormat(o:Object):TextFormat{
			var f:TextFormat = new TextFormat();
			f.color = o.fc;
			f.font = o.ff;
			f.size = o.fs;
			f.alig
 n = o.ta;
			f.bold = o.fw=="bold";
			f.italic = o.fi=="italic";
			log("Flash TextFormat Font:", f.font);
			log("Flash TextFormat size:", f.size);
			
			return f;
		}

		private function draw(o:Object, container:Object):TextField{
			// to center text:
			//	set width and height first, then autoSize
			//	then multiline/wordWrap
			//	then format with align = center
			//
			var t:TextField = new TextField(); 
			
			//t.embedFonts = true;
			//t.blendMode = BlendMode.LAYER; // if we need opacity
			
			t.width = o.w;
			t.height = o.h;
			t.autoSize = o.ta;
			
			
			//	t.border = true;
			
			t.multiline = true;
			t.wordWrap = true;
				
			if(o.cn.indexOf("<")>-1){
				t.htmlText = o.cn;
			}else{
				t.text = o.cn;
			}
			
			
			var p:Array = container && container.padding && container.padding.length ? container.padding : [0];
			
			if(!o.p){
				o.p = [0,0,0,0];
			}else if(o.p.length==1){
				o.p=[o.p,o.p,o.p,o.p];
			}
			if(!o.m){
				o.m = [0,0,0,0];
			}el
 se if(o.m.length==1){
				o.m = [o.m,o.m,o.m,o.m];
			}
			
			t.selectable = false;
			
			
			t.setTextFormat(formatNorm);
			
			
			if(o.va=="middle"){
				t.y = (o.h-t.height)/2;
			}else if(o.va=="bottom"){
				t.y = o.h-t.height - o.p[2] - o.m[2];
				log("   bottom:", t.y, t.height, o.p[2], o.m[2]);
			}else{ // top
				t.y = o.m[0] + p[0];
			}
			log("................TEXT COLOR:", o.ta, o.fc, o.va);
			log("................Padding:", p, o.p);
			//log("text height:", t.y, t.height, o.h, o.h-t.height,(o.h-t.height)/2);  
			
			if(o.ta=="center"){
				t.x = (o.w - t.width)/2;
			}else if(o.ta == "right"){
				t.x = o.w - t.width - o.p[1] - o.m[1];
				log("   right:", t.x, o.w, t.width, o.p[1], o.m[1]);
			}else{ // left
				t.x = o.m.length>1 ? o.m[3] : o.m[0];
				t.x = p.length>1 ? t.x+p[3] : t.x+p[0]; 
			}
			
			addChild(t);
			return t;
		}
	}
}
\ No newline at end of file


More information about the Dojo-checkins mailing list