FileInputAuto.js 7.5 KB

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