文件上传与管理的UI部分

作者:root
注:与filehtml5及队列模块协同使用

oakupfiles = function(o={}) {
    for(var i in o){
	    if (o.hasOwnProperty(i))
			if(oakupfiles.ATTRS.hasOwnProperty(i))oakupfiles.ATTRS[i]=o[i];
	}
}
oakupfiles.prototype = {
    body:null,
    foot:null,
    _fileInputField: null,
    _buttonBinding: null,
    queue: null,
    fileList:[],
    HTML5FILEFIELD_TEMPLATE: "<input id='oakupfile' type='file' style='visibility:hidden; width:0px; height: 0px;'>",
	IMGHTML_TM : "<div style='float:left;border:1px solid #CCCCCC;'><img /><div><button style='float: left;' name='__del'>删除"+
				"</button><button name='__insert' style='float: right;'>插入</button></div></div>",
    oInit : {
			method: "POST",
  			credentials: "include",
  			headers: {"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"},
  			body: '',
  			cache: "no-cache"   
  	},
      
    each: function(a,f){for(var i=0;i< a.length;i++)f(a[i]);},
    fire:function(e,o={},canBubble=false,cancelable=false){
		var evt = document.createEvent("HTMLEvents");
		evt.initEvent(e, canBubble, cancelable);
		Object.assign(evt,o);
	//	for(i in o)evt[i]=o[i];
		document.dispatchEvent(evt);
	},
    get:function(s){
		if(oakupfiles.ATTRS.hasOwnProperty(s))return oakupfiles.ATTRS[s];
	},
	set:function(s,o){
		if(oakupfiles.ATTRS.hasOwnProperty(s))return oakupfiles.ATTRS[s]=o;
	},
    _footFn:function(e){
        var t=e.target.getAttribute('name');
		try{ 
			if(t && typeof(this[t])=="function"){ 
 				this[t](e);
			}else{ } 
		}catch(e){ } 
    },
    updata:function(){
		var o,n;
		this.body.innerHTML = '';
		this.oInit.body = this._postSTR();
		fetch(this.get('listURL'),this.oInit).then((response) => {return response.json();}).then((o) => {
			this.body.appendChild(this._Refresh(o.url,o.files,o.path));	
    	});  
    },
	__del:function(e){
		this.oInit.body = this._postSTR()+'filename='+e.target.getAttribute('data-fname');
		fetch(this.get('delURL'),this.oInit).then((response) => {return response.text();}).then((text) => {
			if(text == 1) e.target.parentNode.parentNode.remove(true);
    	});         
    },
	__insert:function(e){
		var mime,n = e.target,s,t;
		mime = n.getAttribute('data-mime');
        t = this.get('downURL')+'?type=resizes&'+this._postSTR()+'filename='+n.getAttribute('data-fname');
        if (mime.indexOf('image')!= -1){s='<img  src="'+t+'"/>';			    
        }else if(mime.indexOf('audio')!= -1){s='<audio src="'+t+'" controls="controls"></audio>';
		}else if(mime.indexOf('video')!= -1){s='<video src="'+t+'" controls="controls"></video>';
		}else{s='<a href="'+t+'">'+n.getAttribute('data-fname')+'</a>'}
        this.get('exec')('inserthtml',s+'<br>');
    },
    _postSTR:function(){
		var o = this.get("postVars"),s='';
        for(i in o){s+=i+'='+o[i]+'&';}		   	
		return s;
    },
    renderUI:function(){
        this._fileInputField = this.creatNode(this.HTML5FILEFIELD_TEMPLATE);
        this._fileInputField.setAttribute("multiple", "multiple");
		this.body=this.get('bodyNode');
		this.foot=this.get('footNode');
		document.body.appendChild(this._fileInputField);
    },
    bindUI:function(){   
        this._bindSelectButton();
        this._setFileFilters();       
       	this._fileInputField.addEventListener("change", this._updateFileList.bind(this));
        this._fileInputField.addEventListener("click", function(event) {event.stopPropagation();});
        document.addEventListener("fileselect",this._upView.bind(this));
		this.body.addEventListener('click',this._footFn.bind(this));
		this.foot.addEventListener('click',this._footFn.bind(this));
        // document.addEventListener("uploadstart", this._uploadEventHandler.bind(this));
        document.addEventListener("uploadprogress", this._uploadprogress.bind(this));
        document.addEventListener("totaluploadprogress", this._uploadEventHandler.bind(this));
        document.addEventListener("uploadcomplete", this._uploadcomplete.bind(this));
        document.addEventListener("alluploadscomplete", this._uploadEventHandler.bind(this));
        document.addEventListener("uploadcancel", this._uploadEventHandler.bind(this));
        document.addEventListener("uploaderror", this._uploadEventHandler.bind(this));   
    },
    syncUI : function() {
		if(this.get('editor'))this.editor=this.get('editor');            			
    },
    _upView : function(e){			
        var perFileVars = [];
        this.each(e.fileList, (function (file,i) {
			var n = this.creatNode('<progress  id="'+ file.id + '"  max="100" style="width: 200px;" ></progress>');
            this.body.appendChild(n);
			perFileVars[file.id] = Object.assign(this.get("postVars"),{filename: file.name});
       	}).bind(this));
		this.set("postVarsPerFile",Object.assign(this.get("postVarsPerFile"), perFileVars));
       	this.uploadAll();
    },       
    _uploadprogress:function(e){
		this.body.querySelector('#'+e.file.id).setAttribute("value", e.originEvent.percentLoaded);
	},


    _uploadcomplete: function(e){
		var t = this.body.querySelector("#"+e.file.id),o=JSON.parse(e.originEvent.data);
        t.parentNode.replaceChild(this._Refresh(o.url,o.files,o.path),t);
	},
    _Refresh: function(url,files,path=''){
		var t,n,nl,nb,ns=document.createElement('tt');
		for(f in files){
			n = this.creatNode(this.IMGHTML_TM);
			if (files[f].indexOf('image')!= -1){
				p= this.get('downURL')+'?type=thumbs&'+this._postSTR()+'filename='+f;
				n.querySelector('img').src = p;
			}else{
				t = this.creatNode('<span><img src= "'+path+'/upload/img/file.png"/><div style="width:120px;">'+ f +'</div></span>');
				nb=n.querySelector('img');
                nb.parentNode.replaceChild(t,nb);
			}
			nl = n.querySelectorAll('button');
            for(var i=0;i<nl.length;i++){nl[i].setAttribute('data-fname',f);
                nl[i].setAttribute('data-path',path);
                nl[i].setAttribute('data-mime',files[f]);
            }
			ns.appendChild(n);
		}
		return ns;
	},
	_rebindFileField : function () {
        this._fileInputField.remove(true);
        this._fileInputField = this.creatNode(this.HTML5FILEFIELD_TEMPLATE);
        this._fileInputField.setAttribute("multiple", "multiple");
        document.body.appendChild(this._fileInputField);
        this._fileInputField.addEventListener("change", this._updateFileList.bind(this));
        this._setFileFilters();
    },
    _bindSelectButton : function () {
		this._buttonBinding = this.get('selectnode').addEventListener("click", this.openFileSelectDialog.bind(this));
    },
    _setFileFilters : function () {
        if (this.get("fileFilters").length > 0) {
            this._fileInputField.setAttribute("accept", this.get("fileFilters").join(","));
        }
        else {
            this._fileInputField.setAttribute("accept", "");
        }
    },
    openFileSelectDialog : function () {
        if (this._fileInputField.click) {
            this._fileInputField.click();
        }
    },	
    _updateFileList : function (ev) {      
        var newfiles = ev.target.files,
            parsedFiles = [],
            filterFunc = this.get("fileFilterFunction"),
            oldfiles;
        if (filterFunc) {
            this.each(newfiles, function (value) {
                var newfile = new oakFileHTML5(value);
                if (filterFunc(newfile)) {
                    parsedFiles.push(newfile);
                }
            });
        }
        else {
            this.each(newfiles, function (value) {
                parsedFiles.push(new oakFileHTML5(value));
            });
        }
        if (parsedFiles.length > 0) {
            oldfiles = this.fileList;


            this.fileList = this.get("appendNewFiles") ? oldfiles.concat(parsedFiles) : parsedFiles ;


            this.fire("fileselect", {fileList: parsedFiles});
        }
        this._rebindFileField();
    },
    uploadAll : function (url, postvars) {       
        this.uploadThese(this.fileList, url, postvars);
    },
    uploadThese : function (files, url, postvars) {
        if (!this.queue) {
            var uploadURL = url || this.get("uploadURL"),
                postVars = postvars || this.get("postVarsPerFile");
                this.queue = new UploaderQueue({
                simUploads: this.get("simLimit"),
                fileFieldName: this.get("fileFieldName"),
                fileList: files,
                uploadURL: uploadURL,
                perFileParameters: postVars,
                retryCount: this.get("retryCount"),
                uploadHeaders: this.get("uploadHeaders"),
                withCredentials: this.get("withCredentials")
            });
               
            this.queue.startUpload();
            this.fire("uploadstart");
        }
        else if (this.queue._currentState === UploaderQueue.UPLOADING) {
            this.queue.set("perFileParameters", this.get("postVarsPerFile"));
            this.each(files, (function (file) {
                this.queue.addToQueueBottom(file);
            }).bind(this));
        }
    },
    _uploadEventHandler : function (event) {
        switch (event.type) {                
            case "alluploadscomplete":
                this.queue = null;
                //  this.fire("alluploadscomplete", event);
                break;
        }
    },
	render: function(parentNode) {
        this.renderUI();
        this.bindUI();       
        this.syncUI();
        this.fire('render', {parentNode: (parentNode) ? Node.one(parentNode) : null});
	    this.updata();
        return this;
    },
    creatNode:function (s) { 
   	var o = document.createElement("div"); 
   	o.innerHTML = s; 
   	return o.childNodes[0]; 
	}
};
oakupfiles.ATTRS = {
	exec:null,
	bodyNode:null,
	footNode:null,
	selectnode:null,	
    uploadURL:"./upload/upload.php/write",
    delURL:"./upload/upload.php/del",
    listURL:"./upload/upload.php/list",
    downURL:"./upload/getfile.php",               
    simLimit : 5,       
    height:"400px",                
    width:"640px",                                 
    fileFilters:  ['php','pl'],                            
    fileFilterFunction: null,                            
    fileFieldName:"Filedata",                           
    appendNewFiles :  false,                            
    uploadHeaders:{},                            
    /* 额外的数据 */
    postVarsPerFile:{},                            
	postVars:{},
    withCredentials: true,                                 
    retryCount: 3,                            
}