penguin/AstroJS

Javascript framework for my blog

botanjs/src/Astro/Blog/AstroEdit/Uploader.js

raw ยท 6139 bytes

(function(  ){
	var ns = __namespace( "Astro.Blog.AstroEdit" );

	/** @type {System.Cycle} */
	var Cycle                                   = __import( "System.Cycle" );
	/** @type {System.Debug} */
	var debug                                   = __import( "System.Debug" );
	/** @type {typeof System.utils.EventKey} */
	var EventKey                                = __import( "System.utils.EventKey" );
	/** @type {typeof Components.Mouse.ContextMenu} */
	var ContextMenu                             = __import( "Components.Mouse.ContextMenu" );
	/** @type {typeof Components.MessageBox} */
	var MessageBox                              = __import( "Components.MessageBox" );
	/** @type {typeof Dandelion} */
	var Dand                                    = __import( "Dandelion" );
	/** @type {typeof Dandelion.IDOMObject} */
	var IDOMObject                              = __import( "Dandelion.IDOMObject" );
	/** @type {Astro.Blog.Config} */
	var Conf                                    = __import( "Astro.Blog.Config" );
	/** @type {System.utils.Perf} */
	var Perf                                    = __import( "System.utils.Perf" );

	var postFile                                = __import( "System.Net.postFile" );


	var Uploader = function ( set_file_uri )
	{
		/** @type {_AstConf_.SiteFile} */
		var config = Conf.get( "SiteFile" );

		// linkage
		var  busy = false
			, placedFiles = []
			, currentFile


			// Prepare structure for dockpanel
			, ptext = Dand.id( "asl_ptext" )
			, pbar = Dand.id( "asl_pbar_fill" )
			, ppreview = Dand.id( "asl_preview" )
			, pfileName = Dand.id( "asl_fileName" )
			, instruction = Dand.id( "asl_instruction" )
			, p_status = Dand.id( "asl_u_head" )

			, fileList = Dand.id( "asl_fileList" )
			, stage = Dand.id( "asl_uploader" )


			, uploadProgress = function(e)
			{
				var done = e.position || e.loaded
					, total = e.totalSize || e.total
					, percentage = String( Math.floor( done / total * 1000 )/10 ) + "%";

				// Set progress
				ptext.innetText
					= ptext.textContent
					= pbar.style.width
					= percentage;
			}

		, uploadComplete = function ( response )
		{
			try
			{
				var obj = JSON.parse( response );
				if(obj.status)
				{
					currentFile.setStatus( "ok", config.f_host + obj.destination );
				}
				else
				{
					currentFile.setStatus( "error", obj.message );
				}
				new ContextMenu( currentFile.stage, currentFile.menuKeys, "LMB", stage );
			}
			catch ( ex )
			{
				currentFile.setStatus( "error", ex.message );
				debug.Error( ex );
			}
			beginUpload();
		}

		, beginUpload = function()
		{
			busy = true;
			if( placedFiles.length )
			{
				currentFile = placedFiles.pop();
				if( currentFile )
				{
					var file = currentFile.file;

					pfileName.textContent = pfileName.innetText = file.name;

					var fd = new FormData();
					fd.append( "uploadFile", file );
					postFile( set_file_uri, fd, { progress: uploadProgress, complete: uploadComplete } );

					currentFile.setStatus("active");
					instruction.style.marginTop = "-80px";
				}
				else
				{
					// deleted file, skip it
					beginUpload();
				}
			}
			else
			{
				busy = false;
				instruction.style.marginTop = "";
			}
		}

		, clearFileList = function ()
		{
			while( fileList.hasChildNodes() )
			{
				fileList.removeChild( fileList.firstChild );
			}
		}

		, retryUpload = function ()
		{
			this.setStatus("pending");
			placedFiles[placedFiles.length] = this;
			new ContextMenu( this.stage, this.menuKeys, "RMB", stage );
			if( !busy ) beginUpload();
		}

		, removeItem = function ()
		{
			this.stage.style.marginTop = "-2em";
			this.stage.style.opacity = "0";

			if( placedFiles.indexOf(this) != -1 )
			{
				delete placedFiles[placedFiles.indexOf(this)];
			}

			Cycle.delay(function () {
				fileList.removeChild(this);
			}.bind(this.stage), 250);
		}
		;

		fileList.style.paddingTop = String(p_status.clientHeight) + "px";


		var docDom = new IDOMObject( document );
		// Drag/drop handlers
		docDom.addEventListener( "DragOver", function ( e )
		{
			e.preventDefault();
			this.className = "dragged_over";
		} );
		docDom.addEventListener( "DragEnd", function () { this.className = ""; } );
		docDom.addEventListener( "Drop", function ( e )
		{
			e.preventDefault();
			this.className = "";

			// Push files
			var list = e.dataTransfer.files;
			for(var i in list)
			{
				if(list[i].type != undefined)
				{
					var fileItem = new ASLFileItem(list[i], {clear: clearFileList, remove: removeItem, retry: retryUpload});
					placedFiles[placedFiles.length] = fileItem;

					fileList.appendChild(fileItem.stage);
					new ContextMenu(fileItem.stage, fileItem.menuKeys, "LMB", stage);
				}
			}

			if(!busy) beginUpload();

			return false;
		} );
	};

	var ASLFileItem = function (file, callbacks)
	{
		var statusblob = Dand.wrap("span", null, "asl_uItemStat", "\u25CF")
			, msg
			, _items = [
				new EventKey("Remove this item", callbacks.remove.bind(this)) // Reserved for remove item
				, null // Reserved for retry/ Open link
				, null // Reserved for get Error message
				, new EventKey("Clear all", callbacks.clear)
			]

			, popMessage = function ()
			{
				new MessageBox("Upload error", msg).show();
			}

			, getFileLink = function ()
			{
				return msg;
			}
		;

		this.stage = Dand.wrap( null, "asl_item" + Perf.uuid, "asl_uItem", [ statusblob, Dand.textNode(file.name) ] );
		this.file = file;
		this.menuKeys = _items;

		this.setStatus = function (st, message)
		{
			msg = message;
			switch(st)
			{
				case "active":
					statusblob.style.color = "cornflowerblue";
					break;
				case "error":
					statusblob.style.color = "red";

					_items[1] = new EventKey( "Retry", callbacks.retry.bind(this) );
					_items[2] = new EventKey( "Whats wrong ?", popMessage );

					break;
				case "ok":
					statusblob.style.color = "greenyellow";

					_items[1] = new EventKey( "Copy file link", getFileLink );

					break;
				default:// pending
					delete _items[1];
					delete _items[2];
					statusblob.style.color = "";
			}

		}
	};

	ns[ NS_EXPORT ]( EX_CLASS, "Uploader", Uploader );

})();