diff options
| author | Tristan Zur <tzur@web.web.ccwn.org> | 2014-03-27 22:27:47 +0100 |
|---|---|---|
| committer | Tristan Zur <tzur@web.web.ccwn.org> | 2014-03-27 22:27:47 +0100 |
| commit | b62676ca5d3d6f6ba3f019ea3f99722e165a98d8 (patch) | |
| tree | 86722cb80f07d4569f90088eeaea2fc2f6e2ef94 /js/dojo/dojox/form/uploader | |
Diffstat (limited to 'js/dojo/dojox/form/uploader')
| -rw-r--r-- | js/dojo/dojox/form/uploader/Base.js | 126 | ||||
| -rw-r--r-- | js/dojo/dojox/form/uploader/FileList.js | 202 | ||||
| -rw-r--r-- | js/dojo/dojox/form/uploader/plugins/Flash.js | 307 | ||||
| -rw-r--r-- | js/dojo/dojox/form/uploader/plugins/HTML5.js | 241 | ||||
| -rw-r--r-- | js/dojo/dojox/form/uploader/plugins/IFrame.js | 79 |
5 files changed, 955 insertions, 0 deletions
diff --git a/js/dojo/dojox/form/uploader/Base.js b/js/dojo/dojox/form/uploader/Base.js new file mode 100644 index 0000000..4587c76 --- /dev/null +++ b/js/dojo/dojox/form/uploader/Base.js @@ -0,0 +1,126 @@ +//>>built +define("dojox/form/uploader/Base", [ + "dojo/dom-form", + "dojo/dom-style", + "dojo/dom-construct", + "dojo/dom-attr", + "dojo/has", + "dojo/_base/declare", + "dojo/_base/event", + "dijit/_Widget", + "dijit/_TemplatedMixin", + "dijit/_WidgetsInTemplateMixin" +],function(domForm, domStyle, domConstruct, domAttr, has, declare, event, Widget, TemplatedMixin, WidgetsInTemplateMixin){ + +has.add('FormData', function(){return !!window.FormData;}); +has.add("xhr-sendAsBinary", function(){var xhr=window.XMLHttpRequest && new window.XMLHttpRequest(); return xhr && !!xhr.sendAsBinary;}); +has.add("file-multiple", function(){return !!({'true':1,'false':1}[domAttr.get(document.createElement('input',{type:"file"}), 'multiple')]);}); + + /*===== + Widget = dijit._Widget; + TemplatedMixin = dijit._TemplatedMixin; + WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin; + =====*/ +return declare("dojox.form.uploader.Base", [Widget, TemplatedMixin, WidgetsInTemplateMixin], { + // + // Version: 1.6 + // + // summary: + // The Base class used for dojox.form.Uploader and dojox.form.uploader.FileList. + // + // description: + // Should not be used as a standalone. To be mixed in with other classes. + // + + getForm: function(){ + // summary: + // Finds the parent form of the Uploader, if it exists. + // + if(!this.form){ + var n = this.domNode; + while(n && n.tagName && n !== document.body){ + if(n.tagName.toLowerCase() == "form"){ + this.form = n; + break; + } + n = n.parentNode; + } + } + return this.form // Node; + }, + + getUrl: function(){ + // summary: + // Finds the URL to upload to, whether it be the action in the parent form, this.url or + // this.uploadUrl + // + if(this.uploadUrl) this.url = this.uploadUrl; + if(this.url) return this.url; + if(this.getForm()) this.url = this.form.action; + return this.url; // String + }, + + + connectForm: function(){ + // summary: + // Internal. Connects to form if there is one. + // + this.url = this.getUrl(); + if(!this._fcon && !!this.getForm()){ + this._fcon = true; + this.connect(this.form, "onsubmit", function(evt){ + event.stop(evt); + this.submit(this.form); + }); + } + }, + + supports: function(what){ + // summary: + // Does feature testing for uploader capabilities. (No browser sniffing - yay) + // + switch(what){ + case "multiple": + if(this.force == "flash" || this.force == "iframe") return false; + return has("file-multiple"); + case "FormData": + return has(what); + case "sendAsBinary": + return has("xhr-sendAsBinary"); + } + return false; // Boolean + }, + getMimeType: function(){ + // summary: + // Returns the mime type that should be used in an HTML5 upload form. Return result + // may change as the current use is very generic. + // + return "application/octet-stream"; //image/gif + }, + getFileType: function(/* String */name){ + // summary: + // Gets the extension of a file + return name.substring(name.lastIndexOf(".")+1).toUpperCase(); // String + }, + convertBytes: function(bytes){ + // summary: + // Converts bytes. Returns an object with all conversions. The "value" property is + // considered the most likely desired result. + // + var kb = Math.round(bytes/1024*100000)/100000; + var mb = Math.round(bytes/1048576*100000)/100000; + var gb = Math.round(bytes/1073741824*100000)/100000; + var value = bytes; + if(kb>1) value = kb.toFixed(1)+" kb"; + if(mb>1) value = mb.toFixed(1)+" mb"; + if(gb>1) value = gb.toFixed(1)+" gb"; + return { + kb:kb, + mb:mb, + gb:gb, + bytes:bytes, + value: value + }; // Object + } +}); +}); diff --git a/js/dojo/dojox/form/uploader/FileList.js b/js/dojo/dojox/form/uploader/FileList.js new file mode 100644 index 0000000..ed17c33 --- /dev/null +++ b/js/dojo/dojox/form/uploader/FileList.js @@ -0,0 +1,202 @@ +//>>built +define("dojox/form/uploader/FileList", [ + "dojo/_base/fx", + "dojo/dom-style", + "dojo/dom-class", + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/array", + "dijit/_base/manager", + "dojox/form/uploader/Base" +],function(fx, domStyle, domClass, declare, lang, array, manager, formUploaderBase){ + + /*===== + formUploaderBase = dojox.form.uploader.Base; + =====*/ +return declare("dojox.form.uploader.FileList", [formUploaderBase], { + // + // Version: 1.6 + // + // summary: + // A simple widget that provides a list of the files currently selected by + // dojox.form.Uploader + // + // description: + // There is a required CSS file: resources/UploaderFileList.css. + // This is a very simple widget, and not beautifully styled. It is here mainly for test + // cases, but could very easily be used, extended, modified, or copied. + // + // uploaderId: String + // The id of the dojox.form.Uploader to connect to. + uploaderId:"", + // uploader: dojox.form.Uploader + // The dojox.form.Uploader to connect to. Use either this property of unploaderId. This + // property is populated if uploaderId is used. + // + uploader:null, + // headerIndex: String + // The label for the index column. + // + headerIndex:"#", + // headerType: String + // The label for the file type column. + // + headerType:"Type", + // headerFilename: String + // The label for the file name column. + // + headerFilename:"File Name", + // headerFilesize: String + // The label for the file size column. + // + headerFilesize:"Size", + + _upCheckCnt:0, + rowAmt:0, + + templateString: '<div class="dojoxUploaderFileList">' + + '<div dojoAttachPoint="progressNode" class="dojoxUploaderFileListProgress"><div dojoAttachPoint="percentBarNode" class="dojoxUploaderFileListProgressBar"></div><div dojoAttachPoint="percentTextNode" class="dojoxUploaderFileListPercentText">0%</div></div>' + + '<table class="dojoxUploaderFileListTable">'+ + '<thead><tr class="dojoxUploaderFileListHeader"><th class="dojoxUploaderIndex">${headerIndex}</th><th class="dojoxUploaderIcon">${headerType}</th><th class="dojoxUploaderFileName">${headerFilename}</th><th class="dojoxUploaderFileSize" dojoAttachPoint="sizeHeader">${headerFilesize}</th></tr></thead>'+ + '<tbody class="dojoxUploaderFileListContent" dojoAttachPoint="listNode">'+ + '</tbody>'+ + '</table>'+ + '<div>' + , + + postCreate: function(){ + this.setUploader(); + this.hideProgress(); + }, + + reset: function(){ + // summary: + // Clears all rows of items. Happens automatically if Uploader is reset, but you + // could call this directly. + // + for(var i=0;i<this.rowAmt;i++){ + this.listNode.deleteRow(0); + } + this.rowAmt = 0; + }, + + setUploader: function(){ + // summary: + // Connects to the Uploader based on the uploader or the uploaderId properties. + // + if(!this.uploaderId && !this.uploader){ + console.warn("uploaderId not passed to UploaderFileList"); + }else if(this.uploaderId && !this.uploader){ + this.uploader = manager.byId(this.uploaderId); + }else if(this._upCheckCnt>4){ + console.warn("uploader not found for ID ", this.uploaderId); + return; + } + if(this.uploader){ + this.connect(this.uploader, "onChange", "_onUploaderChange"); + this.connect(this.uploader, "reset", "reset"); + this.connect(this.uploader, "onBegin", function(){ + this.showProgress(true); + }); + this.connect(this.uploader, "onProgress", "_progress"); + this.connect(this.uploader, "onComplete", function(){ + setTimeout(lang.hitch(this, function(){ + this.hideProgress(true); + }), 1250); + }); + if(!(this._fileSizeAvail = {'html5':1,'flash':1}[this.uploader.uploadType])){ + //if uploadType is neither html5 nor flash, file size is not available + //hide the size header + this.sizeHeader.style.display="none"; + } + }else{ + this._upCheckCnt++; + setTimeout(lang.hitch(this, "setUploader"), 250); + } + }, + + hideProgress: function(/* Boolean */animate){ + var o = animate ? { + ani:true, + endDisp:"none", + beg:15, + end:0 + } : { + endDisp:"none", + ani:false + }; + this._hideShowProgress(o); + }, + + showProgress: function(/* Boolean */animate){ + var o = animate ? { + ani:true, + endDisp:"block", + beg:0, + end:15 + } : { + endDisp:"block", + ani:false + }; + this._hideShowProgress(o); + }, + + _progress: function(/* Object */ customEvent){ + this.percentTextNode.innerHTML = customEvent.percent; + domStyle.set(this.percentBarNode, "width", customEvent.percent); + }, + + _hideShowProgress: function(o){ + var node = this.progressNode; + var onEnd = function(){ + domStyle.set(node, "display", o.endDisp); + } + if(o.ani){ + domStyle.set(node, "display", "block"); + fx.animateProperty({ + node: node, + properties:{ + height:{ + start:o.beg, + end:o.end, + units:"px" + } + }, + onEnd:onEnd + }).play(); + }else{ + onEnd(); + } + }, + + _onUploaderChange: function(fileArray){ + this.reset(); + array.forEach(fileArray, function(f, i){ + this._addRow(i+1, this.getFileType(f.name), f.name, f.size); + }, this) + }, + + _addRow: function(index, type, name, size){ + + var c, r = this.listNode.insertRow(-1); + c = r.insertCell(-1); + domClass.add(c, "dojoxUploaderIndex"); + c.innerHTML = index; + + c = r.insertCell(-1); + domClass.add(c, "dojoxUploaderIcon"); + c.innerHTML = type; + + c = r.insertCell(-1); + domClass.add(c, "dojoxUploaderFileName"); + c.innerHTML = name; + if(this._fileSizeAvail){ + c = r.insertCell(-1); + domClass.add(c, "dojoxUploaderSize"); + c.innerHTML = this.convertBytes(size).value; + } + + this.rowAmt++; + } +}); +}); diff --git a/js/dojo/dojox/form/uploader/plugins/Flash.js b/js/dojo/dojox/form/uploader/plugins/Flash.js new file mode 100644 index 0000000..473410b --- /dev/null +++ b/js/dojo/dojox/form/uploader/plugins/Flash.js @@ -0,0 +1,307 @@ +//>>built +define("dojox/form/uploader/plugins/Flash", [ + "dojo/dom-form", + "dojo/dom-style", + "dojo/dom-construct", + "dojo/dom-attr", + "dojo/_base/declare", + "dojo/_base/config", + "dojo/_base/connect", + "dojo/_base/lang", + "dojo/_base/array", + "dojox/form/uploader/plugins/HTML5", + "dojox/embed/Flash" +],function(domForm, domStyle, domConstruct, domAttr, declare, config, connect, lang, array, formUploaderPluginsHTML5, embedFlash){ + + +var pluginsFlash = declare("dojox.form.uploader.plugins.Flash", [], { + // + // Version: 1.6 + // + // summary: + // A plugin for dojox.form.Uploader that utilizes a Flash SWF for handling to upload in IE. + // All other browsers will use the HTML5 plugin, unless force="flash" is used, then Flash + // will be used in all browsers. force="flash" is provided because Flash has some features + // that HTML5 does not yet have. But it is still not recommended because of the many problems + // that Firefox and Webkit have with the Flash plugin. + // + // description: + // Inherits all properties from dojox.form.Uploader and formUploaderPluginsHTML5. + // All properties and methods listed here are specific to the Flash plugin only. + // + // swfPath:String + // Path to SWF. Can be overwritten or provided in djConfig. + swfPath:config.uploaderPath || require.toUrl("dojox/form/resources/uploader.swf"), + // + // skipServerCheck: Boolean + // If true, will not verify that the server was sent the correct format. + // This can be safely set to true. The purpose of the server side check + // is mainly to show the dev if they've implemented the different returns + // correctly. + skipServerCheck:true, + // + // serverTimeout:Number (milliseconds) + // The amount of time given to the uploaded file + // to wait for a server response. After this amount + // of time, the onComplete is fired but with a 'server timeout' + // error in the returned item. + serverTimeout: 2000, + // + // isDebug: Boolean + // If true, outputs traces from the SWF to console. What exactly gets passed + // is very relative, and depends upon what traces have been left in the DEFT SWF. + isDebug:false, + // + // devMode: Boolean. + // Re-implemented. devMode increases the logging, adding style tracing from the SWF. + devMode:false, + // + // deferredUploading: Number (1 - X) + // (Flash only) throttles the upload to a certain amount of files at a time. + // By default, Flash uploads file one at a time to the server, but in parallel. + // Firefox will try to queue all files at once, leading to problems. Set this + // to the amount to upload in parallel at a time. + // Generally, 1 should work fine, but you can experiment with queuing more than + // one at a time. + // This is of course ignored if selectMultipleFiles equals false. + deferredUploading:0, + // + // force: String + // Use "flash" to always use Flash (and hopefully force the user to download the plugin + // if they don't have it). + force:"", + + postMixInProperties: function(){ + if(!this.supports("multiple")){ + // Flash will only be used in IE6-8 unless force="flash" + this.uploadType = "flash"; + this._files = []; + this._fileMap = {}; + this._createInput = this._createFlashUploader; + this.getFileList = this.getFlashFileList; + this.reset = this.flashReset; + this.upload = this.uploadFlash; + this.fieldname = "flashUploadFiles"; ///////////////////// this.name + } + this.inherited(arguments); + }, + + /************************* + * Public Events * + *************************/ + + onReady: function(/* dojox.form.FileUploader */ uploader){ + // summary: + // Stub - Fired when embedFlash has created the + // Flash object, but it has not necessarilly finished + // downloading, and is ready to be communicated with. + }, + + onLoad: function(/* dojox.form.FileUploader */ uploader){ + // summary: + // Stub - SWF has been downloaded 100%. + }, + + onFileChange: function(fileArray){ + // summary: + // Stub - Flash-specific event. Fires on each selection of files + // and only provides the files selected on that event - not all files + // selected, as with HTML5 + }, + + onFileProgress: function(fileArray){ + // summary: + // Stub - Flash-specific event. Fires on progress of upload + // and only provides a file-specific event + }, + + + /************************* + * Public Methods * + *************************/ + + getFlashFileList: function(){ + // summary: + // Returns list of currently selected files + return this._files; // Array + }, + + flashReset: function(){ + this.flashMovie.reset(); + this._files = []; + }, + + /************************* + * Private Methods * + *************************/ + + uploadFlash: function(/*Object ? */formData){ + // summary: + // Uploads selected files. Alias "upload()" should be used instead. + // tags: + // private + this.onBegin(this.getFileList()); + this.flashMovie.doUpload(formData); + }, + + _change: function(fileArray){ + this._files = this._files.concat(fileArray); + array.forEach(fileArray, function(f){ + f.bytesLoaded = 0; + f.bytesTotal = f.size; + this._fileMap[f.name+"_"+f.size] = f; + }, this); + this.onChange(this._files); + this.onFileChange(fileArray); + }, + _complete: function(fileArray){ + var o = this._getCustomEvent(); + o.type = "load"; + this.onComplete(fileArray); + }, + _progress: function(f){ + this._fileMap[f.name+"_"+f.bytesTotal].bytesLoaded = f.bytesLoaded; + var o = this._getCustomEvent(); + this.onFileProgress(f); + this.onProgress(o); + }, + _error: function(err){ + this.onError(err); + }, + _onFlashBlur: function(fileArray){ + //console.log("UploaderFlash._onFlashBlur"); + }, + + _getCustomEvent: function(){ + var o = { + bytesLoaded:0, + bytesTotal:0, + type:"progress", + timeStamp:new Date().getTime() + }; + + + for(var nm in this._fileMap){ + o.bytesTotal += this._fileMap[nm].bytesTotal; + o.bytesLoaded += this._fileMap[nm].bytesLoaded; + } + o.decimal = o.bytesLoaded / o.bytesTotal; + o.percent = Math.ceil((o.bytesLoaded / o.bytesTotal)*100)+"%"; + return o; // Object + }, + + _connectFlash: function(){ + // summary: + // Subscribing to published topics coming from the + // Flash uploader. + // description: + // Sacrificing some readbilty for compactness. this.id + // will be on the beginning of the topic, so more than + // one uploader can be on a page and can have unique calls. + // + + this._subs = []; + this._cons = []; + + var doSub = lang.hitch(this, function(s, funcStr){ + this._subs.push(connect.subscribe(this.id + s, this, funcStr)); + }); + + doSub("/filesSelected", "_change"); + doSub("/filesUploaded", "_complete"); + doSub("/filesProgress", "_progress"); + doSub("/filesError", "_error"); + doSub("/filesCanceled", "onCancel"); + doSub("/stageBlur", "_onFlashBlur"); + + this.connect(this.domNode, "focus", function(){ + // TODO: some kind of indicator that the Flash button + // is in focus + this.flashMovie.focus(); + this.flashMovie.doFocus(); + }); + if(this.tabIndex>=0){ + domAttr.set(this.domNode, "tabIndex", this.tabIndex); + } + }, + _createFlashUploader: function(){ + // summary: + // Internal. Creates Flash Uploader + // + var url = this.getUrl(); + if(url){ + if(url.toLowerCase().indexOf("http")<0 && url.indexOf("/")!=0){ + // Appears to be a relative path. Attempt to + // convert it to absolute, so it will better + //target the SWF. + // + var loc = window.location.href.split("/"); + loc.pop(); + loc = loc.join("/")+"/"; + url = loc+url; + } + }else{ + console.warn("Warning: no uploadUrl provided."); + } + + this.inputNode = domConstruct.create("div", {className:"dojoxFlashNode"}, this.domNode, "first"); + domStyle.set(this.inputNode, { + position:"absolute", + top:"-2px", + width:this.btnSize.w+"px", + height:this.btnSize.h+"px", + opacity:0 + }); + + var w = this.btnSize.w; + var h = this.btnSize.h; + + var args = { + expressInstall:true, + path: (this.swfPath.uri || this.swfPath) + "?cb_" + (new Date().getTime()), + width: w, + height: h, + allowScriptAccess:"always", + allowNetworking:"all", + vars: { + uploadDataFieldName: this.flashFieldName || this.name+"Flash", + uploadUrl: url, + uploadOnSelect: this.uploadOnSelect, + deferredUploading:this.deferredUploading || 0, + selectMultipleFiles: this.multiple, + id: this.id, + isDebug: this.isDebug, + noReturnCheck: this.skipServerCheck, + serverTimeout:this.serverTimeout + }, + params: { + scale:"noscale", + wmode:"transparent", + wmode:"opaque", + allowScriptAccess:"always", + allowNetworking:"all" + } + + }; + + this.flashObject = new embedFlash(args, this.inputNode); + this.flashObject.onError = lang.hitch(function(msg){ + console.error("Flash Error: " + msg); + }); + this.flashObject.onReady = lang.hitch(this, function(){ + this.onReady(this); + }); + this.flashObject.onLoad = lang.hitch(this, function(mov){ + this.flashMovie = mov; + this.flashReady = true; + + this.onLoad(this); + }); + this._connectFlash(); + } +}); +dojox.form.addUploaderPlugin(pluginsFlash); + + +return pluginsFlash; +}); diff --git a/js/dojo/dojox/form/uploader/plugins/HTML5.js b/js/dojo/dojox/form/uploader/plugins/HTML5.js new file mode 100644 index 0000000..cf16ccc --- /dev/null +++ b/js/dojo/dojox/form/uploader/plugins/HTML5.js @@ -0,0 +1,241 @@ +//>>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; +}); diff --git a/js/dojo/dojox/form/uploader/plugins/IFrame.js b/js/dojo/dojox/form/uploader/plugins/IFrame.js new file mode 100644 index 0000000..93f5e7e --- /dev/null +++ b/js/dojo/dojox/form/uploader/plugins/IFrame.js @@ -0,0 +1,79 @@ +//>>built +define("dojox/form/uploader/plugins/IFrame", [ + "dojo/dom-construct", + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/array", + "dojo/io/iframe", + "dojox/form/uploader/plugins/HTML5" +],function(domConstruct, declare, lang, array, ioIframe, formUploaderPluginsHTML5){ + + +var pluginsIFrame = declare("dojox.form.uploader.plugins.IFrame", [], { + // + // Version: 1.6 + // + // summary: + // A plugin for dojox.form.Uploader that adds Ajax upload capabilities. + // + // description: + // Only supported by IE, due to the specifc iFrame hack used. The + // formUploaderPluginsHTML5 plugin should be used along with this to add HTML5 + // capabilities to browsers that support them. Progress events are not supported. + // Inherits all properties from dojox.form.Uploader and formUploaderPluginsHTML5. + // + + force:"", + + postMixInProperties: function(){ + this.inherited(arguments); + if(!this.supports("multiple") || this.force =="iframe"){ + this.uploadType = "iframe"; + this.upload = this.uploadIFrame; + } + }, + + uploadIFrame: function(data){ + // summary: + // Internal. You could use this, but you should use upload() or submit(); + // which can also handle the post data. + // + var form, destroyAfter = false; + if(!this.getForm()){ + //enctype can't be changed once a form element is created + form = domConstruct.place('<form enctype="multipart/form-data" method="post"></form>', this.domNode); + array.forEach(this._inputs, function(n, i){ + if(n.value) form.appendChild(n); + }, this); + destroyAfter = true; + }else{ + form = this.form; + } + + var url = this.getUrl(); + + var dfd = ioIframe.send({ + url: url, + form: form, + handleAs: "json", + content: data, + error: lang.hitch(this, function(err){ + if(destroyAfter){ domConstruct.destroy(form); } + this.onError(err); + }), + load: lang.hitch(this, function(data, ioArgs, widgetRef){ + if(destroyAfter){ domConstruct.destroy(form); } + if(data["ERROR"] || data["error"]){ + this.onError(data); + }else{ + this.onComplete(data); + } + }) + }); + } +}); + +dojox.form.addUploaderPlugin(pluginsIFrame); + +return pluginsIFrame; +}); |
