FileInputAuto.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. require({cache:{
  2. 'url:dojox/form/resources/FileInputAuto.html':"<div class=\"dijitFileInput\">\n\t<input id=\"${id}\" name=\"${name}\" class=\"dijitFileInputReal\" type=\"file\" dojoAttachPoint=\"fileInput\" />\n\t<div class=\"dijitFakeInput\" dojoAttachPoint=\"fakeNodeHolder\">\n\t\t<input class=\"dijitFileInputVisible\" type=\"text\" dojoAttachPoint=\"focusNode, inputNode\" />\n\t\t<div class=\"dijitInline dijitFileInputText\" dojoAttachPoint=\"titleNode\">${label}</div>\n\t\t<div class=\"dijitInline dijitFileInputButton\" dojoAttachPoint=\"cancelNode\" dojoAttachEvent=\"onclick:reset\">${cancelText}</div>\n\t</div>\n\t<div class=\"dijitProgressOverlay\" dojoAttachPoint=\"overlay\">&nbsp;</div>\n</div>\n"}});
  3. define("dojox/form/FileInputAuto", [
  4. "dojo/_base/declare",
  5. "dojo/_base/lang",
  6. "dojo/_base/fx",
  7. "dojo/_base/window",
  8. "dojo/dom-style",
  9. "dojo/_base/sniff",
  10. "dojo/text!./resources/FileInputAuto.html",
  11. "dojox/form/FileInput",
  12. "dojo/io/iframe"
  13. ],
  14. function(declare, lang, fx, win, domStyle, has, template, FileInput, ioIframe){
  15. /*=====
  16. FileInput = dojox.form.FileInput;
  17. =====*/
  18. var FileInputAuto = declare("dojox.form.FileInputAuto", FileInput,
  19. {
  20. // summary: An extension on FileInput providing background upload progress
  21. //
  22. // description: An extended version of FileInput - when the user focuses away from the input
  23. // the selected file is posted via ioIframe to the url. example implementation
  24. // comes with PHP solution for handling upload, and returning required data.
  25. //
  26. // notes: the return data from the io.iframe is used to populate the input element with
  27. // data regarding the results. it will be a JSON object, like:
  28. //
  29. // results = { size: "1024", filename: "file.txt" }
  30. //
  31. // all the parameters allowed to FileInput apply
  32. // url: String
  33. // the URL where our background FileUpload will be sent
  34. url: "",
  35. // blurDelay: Integer
  36. // time in ms before an un-focused widget will wait before uploading the file to the url="" specified
  37. // default: 2 seconds
  38. blurDelay: 2000,
  39. // duration: Integer
  40. // The time in ms to use as the generic timing mechanism for the animations
  41. // set to 1 or 0 for "immediate respose"
  42. duration: 500,
  43. // uploadMessage: String
  44. //
  45. // FIXME: i18n somehow?
  46. uploadMessage: "Uploading ...",
  47. // triggerEvent: String
  48. // Event which triggers the upload. Defaults to onblur, sending the file selected
  49. // 'blurDelay' milliseconds after losing focus. Set to "onchange" with a low blurDelay
  50. // to send files immediately after uploading.
  51. triggerEvent: "onblur",
  52. _sent: false,
  53. // small template changes, new attachpoint: overlay
  54. templateString: template,
  55. onBeforeSend: function(){
  56. // summary: Called immediately before a FileInput sends it's file via io.iframe.send.
  57. // The return of this function is passed as the `content` member in the io.iframe IOArgs
  58. // object.
  59. return {};
  60. },
  61. startup: function(){
  62. // summary: add our extra blur listeners
  63. this._blurListener = this.connect(this.fileInput, this.triggerEvent, "_onBlur");
  64. this._focusListener = this.connect(this.fileInput, "onfocus", "_onFocus");
  65. this.inherited(arguments);
  66. },
  67. _onFocus: function(){
  68. // summary: clear the upload timer
  69. if(this._blurTimer){ clearTimeout(this._blurTimer); }
  70. },
  71. _onBlur: function(){
  72. // summary: start the upload timer
  73. if(this._blurTimer){ clearTimeout(this._blurTimer); }
  74. if(!this._sent){
  75. this._blurTimer = setTimeout(lang.hitch(this,"_sendFile"),this.blurDelay);
  76. }
  77. },
  78. setMessage: function(/*String*/title){
  79. // summary: set the text of the progressbar
  80. // innerHTML throws errors in IE! so use DOM manipulation instead
  81. //this.overlay.innerHTML = title;
  82. this.overlay.removeChild(this.overlay.firstChild);
  83. this.overlay.appendChild(document.createTextNode(title));
  84. },
  85. _sendFile: function(/* Event */e){
  86. // summary: triggers the chain of events needed to upload a file in the background.
  87. if(this._sent || this._sending || !this.fileInput.value){ return; }
  88. this._sending = true;
  89. domStyle.set(this.fakeNodeHolder,"display","none");
  90. domStyle.set(this.overlay,{
  91. opacity:0,
  92. display:"block"
  93. });
  94. this.setMessage(this.uploadMessage);
  95. fx.fadeIn({ node: this.overlay, duration:this.duration }).play();
  96. var _newForm;
  97. if(has("ie") < 9 || (has("ie") && has("quirks"))){
  98. // just to reiterate, IE is a steaming pile of code.
  99. _newForm = document.createElement('<form enctype="multipart/form-data" method="post">');
  100. _newForm.encoding = "multipart/form-data";
  101. }else{
  102. // this is how all other sane browsers do it
  103. _newForm = document.createElement('form');
  104. _newForm.setAttribute("enctype","multipart/form-data");
  105. _newForm.setAttribute("method","post");
  106. }
  107. _newForm.appendChild(this.fileInput);
  108. win.body().appendChild(_newForm);
  109. ioIframe.send({
  110. url: this.url,
  111. form: _newForm,
  112. handleAs: "json",
  113. handle: lang.hitch(this,"_handleSend"),
  114. content: this.onBeforeSend()
  115. });
  116. },
  117. _handleSend: function(data,ioArgs){
  118. // summary: The callback to toggle the progressbar, and fire the user-defined callback
  119. // innerHTML throws errors in IE! so use DOM manipulation instead
  120. this.overlay.removeChild(this.overlay.firstChild);
  121. this._sent = true;
  122. this._sending = false;
  123. domStyle.set(this.overlay,{
  124. opacity:0,
  125. border:"none",
  126. background:"none"
  127. });
  128. this.overlay.style.backgroundImage = "none";
  129. this.fileInput.style.display = "none";
  130. this.fakeNodeHolder.style.display = "none";
  131. fx.fadeIn({ node:this.overlay, duration:this.duration }).play(250);
  132. this.disconnect(this._blurListener);
  133. this.disconnect(this._focusListener);
  134. //remove the form used to send the request
  135. win.body().removeChild(ioArgs.args.form);
  136. this.fileInput = null;
  137. this.onComplete(data,ioArgs,this);
  138. },
  139. reset: function(e){
  140. // summary: accomodate our extra focusListeners
  141. if(this._blurTimer){ clearTimeout(this._blurTimer); }
  142. this.disconnect(this._blurListener);
  143. this.disconnect(this._focusListener);
  144. this.overlay.style.display = "none";
  145. this.fakeNodeHolder.style.display = "";
  146. this.inherited(arguments);
  147. this._sent = false;
  148. this._sending = false;
  149. this._blurListener = this.connect(this.fileInput, this.triggerEvent,"_onBlur");
  150. this._focusListener = this.connect(this.fileInput,"onfocus","_onFocus");
  151. },
  152. onComplete: function(data,ioArgs,widgetRef){
  153. // summary: stub function fired when an upload has finished.
  154. // data: the raw data found in the first [TEXTAREA] tag of the post url
  155. // ioArgs: the Deferred data being passed from the handle: callback
  156. // widgetRef: this widget pointer, so you can set this.overlay to a completed/error message easily
  157. }
  158. });
  159. declare("dojox.form.FileInputBlind", FileInputAuto,
  160. {
  161. // summary: An extended version of dojox.form.FileInputAuto
  162. // that does not display an input node, but rather only a button
  163. // and otherwise behaves just like FileInputAuto
  164. startup: function(){
  165. // summary: hide our fileInput input field
  166. this.inherited(arguments);
  167. this._off = domStyle.get(this.inputNode,"width");
  168. this.inputNode.style.display = "none";
  169. this._fixPosition();
  170. },
  171. _fixPosition: function(){
  172. // summary: in this case, set the button under where the visible button is
  173. if(has("ie")){
  174. domStyle.set(this.fileInput,"width","1px");
  175. }else{
  176. domStyle.set(this.fileInput,"left","-"+(this._off)+"px");
  177. }
  178. },
  179. reset: function(e){
  180. // summary: onclick, we need to reposition our newly created input type="file"
  181. this.inherited(arguments);
  182. this._fixPosition();
  183. }
  184. });
  185. return FileInputAuto;
  186. });