We left off last time with our user interface filled out nicely with pictures from both the local filesystem and the "My Photos" folder on Xdrive. Today, we'll add some drag/drop interaction using Ext to facilitate the uploading of local pictures to Xdrive.
The task of uploading files using a pure AJAX solution can be a little tricky. We can't just auto-fill a value in a file input control as this is a read-only property. For this particular implementation, we'll be using a mix of Ext JS to drag/drop the images from the local environment to the Xdrive environment, AIR to perform the file upload, and ColdFusion to host a local proxy for sending data to Xdrive. Let's start with the drag/drop functionality.
Incorporating Drag/Drop
Remember last time, as part of the success handler in doLogin(), the thumbnails for both the local and remote environments were constructed using Ext DataViews. Tack on the following code in this success handler, after the DataViews are constructed:
// get the local pictures, attach DD proxies var nl = Ext.select( "div[class='thumb'] img" ); // define a drop zone var dz = new Ext.dd.DropZone( pnl_center.getEl().id, { ddGroup: "local" } ); Ext.override( Ext.dd.DDProxy, { onDragOver: function( e, targetId ) { this.target = Ext.get( targetId ); }, endDrag: function() { if( this.target.id == pnl_center.getEl().id ){ var draggedImage = Ext.get( this.getEl() ); ds_xdrive.add( new Ext.data.Record( { "name": draggedImage.dom.title, "path": draggedImage.dom.src } ) ); var f_remove = function( r, i ) { if( r.get( "name" ) == draggedImage.dom.title ) { return true; } } // remove the reference in the local store ds_local.remove( ds_local.getAt( ds_local.findBy( f_remove ) ) ); // create a destination folder object "My Photos" var obj_destFolder = { "destFolder": { "type": "FileObject", "id": "xdr:XFS-1706469105" } }; // make key information available to AIR AirBrowser.XDRIVE_URL = XDRIVE_URL; AirBrowser.jsessionid = jsessionid; AirBrowser.recoveryToken = recoveryToken; AirBrowser.xdriveData = Ext.util.JSON.encode( obj_destFolder ); // upload the picture to the proxy parentSandboxBridge.uploadPicture( draggedImage.dom.src ); } } } ); for( var i = 0; i < nl.elements.length; i++ ) { var tmp = new Ext.dd.DDProxy( nl.elements[i].id, "local" ); }
This code starts off by getting element references to all the image elements in the local environment panel. After defining the Xdrive (remote) panel as a drop zone for the drag/drop group named 'local', an override block is used to define custom actions for the onDragOver and endDrag events. The onDragOver event saves a reference to the current target so it can be used in the endDrag event. The endDrag definition checks to ensure the image ended up over the Xdrive drop zone. If it did, then the image is added to the data store tied to the Xdrive environment's Ext.DataView which we used in part 3 to render the thumbnails. Next, the index position of the dragged image is queried for in the local data store so it can be removed. The final tasks are to set some properties on the AirBrowser object which is used as the bridge between the browser sandbox and the AIR sandbox. The uploadPicture function which is defined in the AIR sandbox is fired, using the path to the dragged image as its lone argument.
AIR File Uploads
Now that we've moved images from the local environment to the remote environment (at least their representation held in Ext data stores), we can shift focus to the uploading of the physical file on disk. This is a much lighter task compared to the drag/drop functionality just demonstrated. The following code is defined in root.js on the AirApp object:
uploadPicture: function( imgPath ) {
// create the request
var r = new air.URLRequest( "http://localhost:8501/xdriveProxy.cfm" );
r.method = air.URLRequestMethod.POST;
var variables = new air.URLVariables();
variables.jsessionid = AirBrowser.jsessionid;
variables.recoveryToken = AirBrowser.recoveryToken;
variables.XDRIVE_URL = AirBrowser.XDRIVE_URL;
variables.xdriveData = AirBrowser.xdriveData;
r.data = variables;
// create a File object, upload it to the proxy
var pictureFile = new air.File( imgPath );
pictureFile.upload( r );
}
To upload a file object in AIR, it's a matter of defining a request, creating a File, then calling the upload method of the File object using the request. AIR handles much of the legwork for a task that normally would be tricky at best. All you need is to implement a server-side proxy to pick the file up and pass it along to Xdrive. For this implementation, I chose ColdFusion:
<!--- upload the file ---> <cffile action = "upload" fileField = "fileData" destination = "#ExpandPath( form.filename )#" /> <!--- upload to Xdrive ---> <cfhttp url="#form.XDRIVE_URL#io.formupload;jsessionid=#form.jsessionid#" method="post"> <cfhttpparam type="url" name="data" value="#form.xdriveData#" /> <cfhttpparam type="file" name="#ExpandPath( form.filename )#" file="#ExpandPath( form.filename )#" /> </cfhttp>
The proxy's job is a matter of getting the file, then uploading it to Xdrive using the data POSTed to the proxy. While this example uses ColdFusion, it's important to understand that any server-side technology could be used to perform the proxy duties.
We're almost there, Friday we finish up by downloading files from Xdrive to the local environment.
