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