Changeset 1399
- Timestamp:
- 2009-12-11 16:55:18 (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/modules/kauri-forms/kauri-forms-framework/src/main/kauri/static-{build}.key/kauri.forms/upload.js
r1296 r1399 14 14 15 15 kf.fieldTypes.put("file", { 16 base: "composite", 17 members: { 18 "filelocation": { 19 type: "string" 20 }, 21 "mimetype": { 22 type: "string" 23 }, 24 "size": { 25 type: "integer" 26 }, 27 "filename": { 28 type: "string" 29 } 30 }, 16 base: "string", 31 17 control: "upload-control" 32 18 }); 33 19 34 $.inherit(UploadControl, kf. AbstractContainerControl);20 $.inherit(UploadControl, kf.Control); 35 21 36 22 /** … … 49 35 * Uri used for uploading the file to immediately after setting choosing the local file 50 36 */ 51 UploadControl.prototype.uploadUri = "/ tmp/?accept=text/plain";37 UploadControl.prototype.uploadUri = "/kauri/upload"; 52 38 53 39 UploadControl.prototype.elements = {}; 54 40 $.extend(UploadControl.prototype.elements, kf.AbstractContainerControl.prototype.elements); 55 41 $.extend(UploadControl.prototype.elements, { 56 "container": { 57 create: "<div/>" 58 }, 59 "layout": { 42 "input": { 60 43 create: "<div/>" 61 44 } 62 45 }); 63 46 47 48 var INIT_FRAME_URL = "about:blank"; 49 64 50 /** 65 51 * Initializes member types (filename, filelocation, size & mimetype) … … 68 54 */ 69 55 UploadControl.prototype.initElements = function(create){ 70 var container = this.getElement("container"); 71 container.hide(); 72 73 this._children = {}; 74 75 var type = this.getType(); 76 var memberTypes = type.getMemberTypes(); 77 78 for (var memberName in memberTypes) { 79 var memberType = memberTypes[memberName]; 80 var childControl = this.createChildControl(memberName, memberType); 81 this.putChild(memberName, childControl); 82 } 83 84 this._createUploadInput(); 85 86 var tmpFormContainer = $("<div/>").insertAfter(this._form.getRootElement()); 87 tmpFormContainer.hide(); 88 89 var uploadFrameId = this.getId() + "iFrame"; 90 91 // Create a fake form with target a hidden iframe, the form will be submitted the minute a file is chosen. When uploaded the iframe 92 // should contain the response from the upload 93 this.uploadForm = $("<form method='POST' enctype='multipart/form-data' action='" + this.uploadUri + "' target='" + uploadFrameId + "' />").appendTo(tmpFormContainer); 94 this.uploadIframe = $("<iframe src='about:blank' id='" + uploadFrameId + "' name='" + uploadFrameId + "'/>").appendTo(this.uploadForm); 95 96 // Used for showing loading messages and file information 97 this.uploadView = $("<div/>").insertAfter(container); 56 57 var me = this; 58 var $container = this.getElement("input"); 59 60 // a hidden container for the hidden form 61 var hiddenFormContainer = $("<div/>").insertAfter(this._form.getRootElement()).hide(); 62 // and a unique id to use 63 var uploadFrameId =( "iFrame" + this.getAbsoluteId() ).replace(/\//g,"_"); 64 65 66 // a hidden frame to send the upload-response to 67 this.uploadIframe = $("<iframe src='" + INIT_FRAME_URL + "' id='" + uploadFrameId + "' name='" + uploadFrameId + "'/>").hide().appendTo($container); 68 this.uploadIframe.unbind().load(function(){ 69 me.handleUploadResponse(this.contentWindow.document); 70 }); 71 72 73 // A hidden form targetted at the hidden iframe. 74 // This crafted form will be submitted the minute a file is chosen. It is distinct from the kauri-form holding this control. 75 // When uploaded the iframe should contain the response from the upload 76 this.uploadForm = $("<form method='POST' enctype='multipart/form-data' action='" + this.uploadUri + "?accept=text/plain' target='" + uploadFrameId + "' />").appendTo(hiddenFormContainer); 77 78 // an area for showing upload progress and status. 79 this.uploadView = $("<div/>").appendTo($container); 98 80 }; 99 81 100 UploadControl.prototype.initEventWiring = function(){ 101 var me = this; 102 this.uploadIframe.unbind().load(function(){ 103 // lets assume for now that it's always json 104 var idoc = this.contentWindow.document; 82 83 UploadControl.prototype.newUploadInput = function(me, $container) { 84 me = me || this; 85 $container = $container || this.getElement("input"); 86 87 if (this.uploadInput) 88 this.uploadInput.remove(); 89 90 // the visual input control the end user will see 91 this.uploadInput = $("<input type='file' name='file'/>").appendTo($container); 92 this.uploadInput.change(function(evt){ 93 me.performUpload(); 94 }); 95 } 96 97 UploadControl.prototype.performUpload = function() { 98 // remove any older input fields in the upload-form 99 $("input", this.uploadForm).remove(); 100 101 // clone the user-controlled file input and place the clone in the upload-form 102 var activeInput = this.uploadInput.clone().appendTo(this.uploadForm); 103 104 // replace the visible input control with a loading msg 105 this.uploadInput.remove(); 106 this.uploadView.html("<div class='upload-loading'/>"); 107 108 // start upload by submitting the upload-form 109 this.uploadForm.submit(); 110 } 111 112 UploadControl.prototype.handleUploadResponse = function(idoc) { 113 if (!idoc || INIT_FRAME_URL == idoc.URL) 114 return; // no data to be read, this is just starting up 115 116 try { 105 117 var ibody = $("body", idoc); 106 118 var responseText = ibody.text(); … … 109 121 var response = kp.JSON.parse(responseText); 110 122 if (response.length > 0) { 111 var pos = me.uploadUri.indexOf("?") > -1 ? me.uploadUri.lastIndexOf("?") : me.uploadUri.length;112 var baseurl = me.uploadUri.substring(0, pos);113 123 114 var value = { 115 filelocation: baseurl + response[0].id, 116 filename: response[0].filename, 117 size: response[0].size, 118 mimetype: response[0].type 119 }; 120 me.setWireValue(value); 124 var value = response[0]; //this control only uploads one file at a time. 125 this.setWireValue(value); 121 126 } 122 // after loading remove the cloned file input123 $("input", me.uploadForm).remove();124 127 } 128 } catch (e) { 129 // if loading failed: show some bad message 130 this.uploadView.html("<span class='message'>Upload Failed.</span>"); 131 132 // even if loading failed the control should go back to some decent view-state 133 this.updateView(); 134 } 135 } 136 137 UploadControl.prototype.dataRef = function(id){ 138 var uri = this.uploadUri; 139 var pos = uri.indexOf("?") > -1 ? uri.lastIndexOf("?") : uri.length; 140 var base = uri.substring(0, pos); 141 142 return base + id; 143 } 144 145 var ORDER_SIZES = [" Bytes", " KB", " MB"]; //higher order seems unlikely for uploads 146 UploadControl.prototype.humanSize = function(size, level) { 147 level = level || 0; 148 var nextOrder = Number(new Number(size) / 1024).toFixed(); 149 if (nextOrder != "0" && ORDER_SIZES.length > level +1) 150 return this.humanSize(nextOrder, level+1); 151 //else 152 return size + ORDER_SIZES[level]; 153 } 154 155 UploadControl.prototype.updateView = function () { 156 var me = this; 157 var value = this.getValue(); 158 159 160 if( value && value.id) { // there is data to show... 161 this.uploadView.empty(); 162 163 // remove the input and replace with file information 164 this.uploadInput.remove(); 165 166 // display file information 167 var size = value.size ? this.humanSize(value.size) : "N/A"; 168 var ref = this.dataRef(value.id); 169 var name = value.filename || "unnamed document"; 170 var mimetype = value.mimetype || "application/octet-stream"; 171 172 this.uploadView.html("<a target='_blank' href='" + ref + "'>" + name + "</a><span class='upload-info'> (type: " + mimetype + ", size: " + size + " ) </span> "); 173 var rmBtn = $("<a href='javascript:void(0)'>remove</a>").appendTo(this.uploadView); 174 rmBtn.click(function(evt){ 175 me.clearUploadedFile(value.id); 176 }); 177 178 this.startHeartBeat(); 179 } else { 180 this.uploadView.html(""); 181 this.newUploadInput(me); 182 } 183 } 184 185 UploadControl.prototype.clearUploadedFile = function (key) { 186 187 //stop keeping it life 188 this.endHeartBeat(key); 189 //then kill it off using a call to delete via AJAX 190 $.ajax({ 191 uri: this.dataRef(key) +"?method=DELETE", 192 method: "POST" 125 193 }); 126 }; 127 128 /** 129 * Create a file input with an onChange handler that submits the file to the server 130 */ 131 UploadControl.prototype._createUploadInput = function(){ 132 var container = this.getElement("container"); 133 this.uploadInput = $("<input type='file'/>").insertAfter(container); 134 var me = this; 135 136 this.uploadInput.change(function(evt){ 137 138 // clone the file input and put place the clone in the hidden form (since we want to fake an ajax upload) 139 var fileInput = me.uploadInput.clone().insertAfter(me.uploadIframe); 140 fileInput.attr("name", "file"); 141 // replace the input with a loading msg 142 me.uploadInput.remove(); 143 $("<div class='upload-loading'/>").appendTo(me.uploadView); 144 me.uploadForm.submit(); 145 }); 146 } 147 148 /** 149 * Sets the values for all of this controls children. The value is expected to be in wire format 150 * Also displays the file information 151 * @param {Array} value The values should be ordered in the same order as the children 152 */ 153 UploadControl.prototype.setWireValue = function (value) { 154 var me = this; 155 var container = this.uploadView; 156 container.empty(); 157 158 if(value){ 159 160 // remove the input and replace with file information 161 me.uploadInput.remove(); 162 163 // display file information 164 var kb = Number(new Number(value.size) / 1024).toFixed() + "KB"; 165 $("<a target='_blank' href='" + value.filelocation + "'>" + value.filename + "</a><span class='upload-info'>( " + value.mimetype + ", " + kb + " )</span>").appendTo(container); 166 var rmBtn = $("<a href='javascript:void(0)'>remove</a>").appendTo(container); 167 rmBtn.click(function(evt){ 168 container.empty(); 169 //TODO remove tmp resource 170 me._createUploadInput(); 171 172 }); 173 } 174 175 // set the child controls 176 return this.setValueLoop("setWireValue", value); 177 } 178 194 195 this.setValue(undefined); 196 } 197 198 UploadControl.prototype.startHeartBeat = function (key) { 199 //TODO 200 } 201 202 UploadControl.prototype.endHeartBeat = function (key) { 203 //TODO 204 } 205 206 UploadControl.prototype.setUserValue = function (value) { 207 // no such thing, we just use the event to update the visual 208 this.updateView(); 209 } 210 211 UploadControl.prototype.getUserValue = function () { 212 // no such thing 213 } 214 179 215 kf.controlTypes.put("upload-control", UploadControl); 180 216
Note: See TracChangeset
for help on using the changeset viewer.