define("dojox/form/uploader/_HTML5", [
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/_base/array",
"dojo"
],function(declare, lang, arrayUtil, dojo){
return declare("dojox.form.uploader._HTML5", [], {
// summary:
// A mixin for dojox/form/Uploader that adds HTML5 multiple-file upload capabilities and
// progress events.
//
// description:
// Note that this does not add these capabilities to browsers that don't support them.
// For IE8 or older browsers, _IFrame or _Flash mixins will be used.
//
// debug message:
errMsg:"Error uploading files. Try checking permissions",
// Overwrites "form" and could possibly be overwritten again by iframe or flash plugin.
uploadType:"html5",
postMixInProperties: function(){
this.inherited(arguments);
if(this.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());
this.uploadWithFormData(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');
},
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(), fieldName=this._getFileFieldName();
arrayUtil.forEach(this._files, function(f, i){
fd.append(fieldName, f);
}, this);
if(data){
data.uploadType = this.uploadType;
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);
try{
this.onComplete(JSON.parse(xhr.responseText.replace(/^\{\}&&/,'')));
}catch(e){
var msg = "Error parsing server result:";
console.error(msg, e);
console.error(xhr.responseText);
this.onError(msg, e);
}
}
});
xhr.open("POST", this.getUrl());
xhr.setRequestHeader("Accept","application/json");
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;
}
});
});