242 lines
6.2 KiB
JavaScript
242 lines
6.2 KiB
JavaScript
//>>built
|
|
define("dojox/form/uploader/plugins/HTML5", [
|
|
"dojo/_base/declare",
|
|
"dojo/_base/lang",
|
|
"dojo/_base/array",
|
|
"dojo"
|
|
],function(declare, lang, array, dojo){
|
|
|
|
var pluginsHTML5 = declare("dojox.form.uploader.plugins.HTML5", [], {
|
|
//
|
|
// Version: 1.6
|
|
//
|
|
// summary:
|
|
// A plugin for dojox.form.Uploader that adds HTML5 multiple-file upload capabilities and
|
|
// progress events.
|
|
//
|
|
// description:
|
|
// Add this plugin to have HTML5 capabilities in the Uploader. Note that it does not add
|
|
// these capabilities to browsers that don't support them. For IE or older browsers, add
|
|
// additional plugins: IFrame or Flash.
|
|
//
|
|
errMsg:"Error uploading files. Try checking permissions",
|
|
|
|
// Overwrites "form" and could possibly be overwritten again by iframe or flash plugin.
|
|
uploadType:"html5",
|
|
|
|
postCreate: function(){
|
|
this.connectForm();
|
|
this.inherited(arguments);
|
|
if(this.uploadOnSelect){
|
|
this.connect(this, "onChange", function(data){
|
|
this.upload(data[0]);
|
|
});
|
|
}
|
|
},
|
|
|
|
_drop: function(e){
|
|
dojo.stopEvent(e);
|
|
var dt = e.dataTransfer;
|
|
this._files = dt.files;
|
|
this.onChange(this.getFileList());
|
|
},
|
|
/*************************
|
|
* Public Methods *
|
|
*************************/
|
|
|
|
upload: function(/*Object ? */formData){
|
|
// summary:
|
|
// See: dojox.form.Uploader.upload
|
|
//
|
|
this.onBegin(this.getFileList());
|
|
if(this.supports("FormData")){
|
|
this.uploadWithFormData(formData);
|
|
}else if(this.supports("sendAsBinary")){
|
|
this.sendAsBinary(formData);
|
|
}
|
|
},
|
|
|
|
addDropTarget: function(node, /*Boolean?*/onlyConnectDrop){
|
|
// summary:
|
|
// Add a dom node which will act as the drop target area so user
|
|
// can drop files to this node.
|
|
// description:
|
|
// If onlyConnectDrop is true, dragenter/dragover/dragleave events
|
|
// won't be connected to dojo.stopEvent, and they need to be
|
|
// canceled by user code to allow DnD files to happen.
|
|
// This API is only available in HTML5 plugin (only HTML5 allows
|
|
// DnD files).
|
|
if(!onlyConnectDrop){
|
|
this.connect(node, 'dragenter', dojo.stopEvent);
|
|
this.connect(node, 'dragover', dojo.stopEvent);
|
|
this.connect(node, 'dragleave', dojo.stopEvent);
|
|
}
|
|
this.connect(node, 'drop', '_drop');
|
|
},
|
|
|
|
sendAsBinary: function(/* Object */data){
|
|
// summary:
|
|
// Used primarily in FF < 4.0. Sends files and form object as binary data, written to
|
|
// still enable use of $_FILES in PHP (or equivalent).
|
|
// tags:
|
|
// private
|
|
//
|
|
if(!this.getUrl()){
|
|
console.error("No upload url found.", this); return;
|
|
}
|
|
|
|
// The date/number doesn't matter but amount of dashes do. The actual boundary
|
|
// will have two more dashes than this one which is used in the header.
|
|
var boundary = "---------------------------" + (new Date).getTime();
|
|
var xhr = this.createXhr();
|
|
|
|
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
|
|
|
|
// finally send the request as binary data
|
|
// still accessed as $_FILES
|
|
var msg = this._buildRequestBody(data, boundary);
|
|
if(!msg){
|
|
this.onError(this.errMsg);
|
|
}else{
|
|
console.log("msg:", msg)
|
|
console.log("xhr:", xhr)
|
|
|
|
xhr.sendAsBinary(msg);
|
|
}
|
|
},
|
|
uploadWithFormData: function(/* Object */data){
|
|
// summary
|
|
// Used with WebKit and Firefox 4+
|
|
// Upload files using the much friendlier FormData browser object.
|
|
// tags:
|
|
// private
|
|
//
|
|
if(!this.getUrl()){
|
|
console.error("No upload url found.", this); return;
|
|
}
|
|
var fd = new FormData();
|
|
array.forEach(this._files, function(f, i){
|
|
fd.append(this.name+"s[]", f);
|
|
}, this);
|
|
|
|
if(data){
|
|
for(var nm in data){
|
|
fd.append(nm, data[nm]);
|
|
}
|
|
}
|
|
|
|
var xhr = this.createXhr();
|
|
xhr.send(fd);
|
|
},
|
|
|
|
_xhrProgress: function(evt){
|
|
if(evt.lengthComputable){
|
|
var o = {
|
|
bytesLoaded:evt.loaded,
|
|
bytesTotal:evt.total,
|
|
type:evt.type,
|
|
timeStamp:evt.timeStamp
|
|
};
|
|
if(evt.type == "load"){
|
|
// 100%
|
|
o.percent = "100%",
|
|
o.decimal = 1;
|
|
}else{
|
|
o.decimal = evt.loaded / evt.total;
|
|
o.percent = Math.ceil((evt.loaded / evt.total)*100)+"%";
|
|
}
|
|
this.onProgress(o);
|
|
}
|
|
},
|
|
|
|
createXhr: function(){
|
|
var xhr = new XMLHttpRequest();
|
|
var timer;
|
|
xhr.upload.addEventListener("progress", lang.hitch(this, "_xhrProgress"), false);
|
|
xhr.addEventListener("load", lang.hitch(this, "_xhrProgress"), false);
|
|
xhr.addEventListener("error", lang.hitch(this, function(evt){
|
|
this.onError(evt);
|
|
clearInterval(timer);
|
|
}), false);
|
|
xhr.addEventListener("abort", lang.hitch(this, function(evt){
|
|
this.onAbort(evt);
|
|
clearInterval(timer);
|
|
}), false);
|
|
xhr.onreadystatechange = lang.hitch(this, function(){
|
|
if(xhr.readyState === 4){
|
|
// console.info("COMPLETE")
|
|
clearInterval(timer);
|
|
this.onComplete(JSON.parse(xhr.responseText.replace(/^\{\}&&/,'')));
|
|
}
|
|
});
|
|
xhr.open("POST", this.getUrl());
|
|
|
|
timer = setInterval(lang.hitch(this, function(){
|
|
try{
|
|
if(typeof(xhr.statusText)){} // accessing this error throws an error. Awesomeness.
|
|
}catch(e){
|
|
//this.onError("Error uploading file."); // not always an error.
|
|
clearInterval(timer);
|
|
}
|
|
}),250);
|
|
|
|
return xhr;
|
|
},
|
|
|
|
_buildRequestBody : function(data, boundary){
|
|
var EOL = "\r\n";
|
|
var part = "";
|
|
boundary = "--" + boundary;
|
|
|
|
var filesInError = [], files = this._files;
|
|
array.forEach(files, function(f, i){
|
|
var fieldName = this.name+"s[]";//+i;
|
|
var fileName = f.fileName;
|
|
var binary;
|
|
|
|
try{
|
|
binary = f.getAsBinary() + EOL;
|
|
part += boundary + EOL;
|
|
part += 'Content-Disposition: form-data; ';
|
|
part += 'name="' + fieldName + '"; ';
|
|
part += 'filename="'+ fileName + '"' + EOL;
|
|
part += "Content-Type: " + this.getMimeType() + EOL + EOL;
|
|
part += binary;
|
|
}catch(e){
|
|
filesInError.push({index:i, name:fileName});
|
|
}
|
|
}, this);
|
|
|
|
if(filesInError.length){
|
|
if(filesInError.length >= files.length){
|
|
// all files were bad. Nothing to upload.
|
|
this.onError({
|
|
message:this.errMsg,
|
|
filesInError:filesInError
|
|
});
|
|
part = false;
|
|
}
|
|
}
|
|
|
|
if(!part) return false;
|
|
|
|
if(data){
|
|
for(var nm in data){
|
|
part += boundary + EOL;
|
|
part += 'Content-Disposition: form-data; ';
|
|
part += 'name="' + nm + '"' + EOL + EOL;
|
|
part += data[nm] + EOL;
|
|
}
|
|
}
|
|
|
|
|
|
part += boundary + "--" + EOL;
|
|
return part;
|
|
}
|
|
|
|
});
|
|
dojox.form.addUploaderPlugin(pluginsHTML5);
|
|
|
|
return pluginsHTML5;
|
|
});
|