1 | /*! |
---|
2 | * Ext JS Library 3.4.0 |
---|
3 | * Copyright(c) 2006-2011 Sencha Inc. |
---|
4 | * licensing@sencha.com |
---|
5 | * http://www.sencha.com/license |
---|
6 | */ |
---|
7 | /** |
---|
8 | * @class Ext.ProgressBar |
---|
9 | * @extends Ext.BoxComponent |
---|
10 | * <p>An updateable progress bar component. The progress bar supports two different modes: manual and automatic.</p> |
---|
11 | * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the |
---|
12 | * progress bar as needed from your own code. This method is most appropriate when you want to show progress |
---|
13 | * throughout an operation that has predictable points of interest at which you can update the control.</p> |
---|
14 | * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it |
---|
15 | * once the operation is complete. You can optionally have the progress bar wait for a specific amount of time |
---|
16 | * and then clear itself. Automatic mode is most appropriate for timed operations or asynchronous operations in |
---|
17 | * which you have no need for indicating intermediate progress.</p> |
---|
18 | * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0) |
---|
19 | * @cfg {String} text The progress bar text (defaults to '') |
---|
20 | * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress |
---|
21 | * bar's internal text element) |
---|
22 | * @cfg {String} id The progress bar element's id (defaults to an auto-generated id) |
---|
23 | * @xtype progress |
---|
24 | */ |
---|
25 | Ext.ProgressBar = Ext.extend(Ext.BoxComponent, { |
---|
26 | /** |
---|
27 | * @cfg {String} baseCls |
---|
28 | * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress') |
---|
29 | */ |
---|
30 | baseCls : 'x-progress', |
---|
31 | |
---|
32 | /** |
---|
33 | * @cfg {Boolean} animate |
---|
34 | * True to animate the progress bar during transitions (defaults to false) |
---|
35 | */ |
---|
36 | animate : false, |
---|
37 | |
---|
38 | // private |
---|
39 | waitTimer : null, |
---|
40 | |
---|
41 | // private |
---|
42 | initComponent : function(){ |
---|
43 | Ext.ProgressBar.superclass.initComponent.call(this); |
---|
44 | this.addEvents( |
---|
45 | /** |
---|
46 | * @event update |
---|
47 | * Fires after each update interval |
---|
48 | * @param {Ext.ProgressBar} this |
---|
49 | * @param {Number} The current progress value |
---|
50 | * @param {String} The current progress text |
---|
51 | */ |
---|
52 | "update" |
---|
53 | ); |
---|
54 | }, |
---|
55 | |
---|
56 | // private |
---|
57 | onRender : function(ct, position){ |
---|
58 | var tpl = new Ext.Template( |
---|
59 | '<div class="{cls}-wrap">', |
---|
60 | '<div class="{cls}-inner">', |
---|
61 | '<div class="{cls}-bar">', |
---|
62 | '<div class="{cls}-text">', |
---|
63 | '<div> </div>', |
---|
64 | '</div>', |
---|
65 | '</div>', |
---|
66 | '<div class="{cls}-text {cls}-text-back">', |
---|
67 | '<div> </div>', |
---|
68 | '</div>', |
---|
69 | '</div>', |
---|
70 | '</div>' |
---|
71 | ); |
---|
72 | |
---|
73 | this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true) |
---|
74 | : tpl.append(ct, {cls: this.baseCls}, true); |
---|
75 | |
---|
76 | if(this.id){ |
---|
77 | this.el.dom.id = this.id; |
---|
78 | } |
---|
79 | var inner = this.el.dom.firstChild; |
---|
80 | this.progressBar = Ext.get(inner.firstChild); |
---|
81 | |
---|
82 | if(this.textEl){ |
---|
83 | //use an external text el |
---|
84 | this.textEl = Ext.get(this.textEl); |
---|
85 | delete this.textTopEl; |
---|
86 | }else{ |
---|
87 | //setup our internal layered text els |
---|
88 | this.textTopEl = Ext.get(this.progressBar.dom.firstChild); |
---|
89 | var textBackEl = Ext.get(inner.childNodes[1]); |
---|
90 | this.textTopEl.setStyle("z-index", 99).addClass('x-hidden'); |
---|
91 | this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]); |
---|
92 | this.textEl.setWidth(inner.offsetWidth); |
---|
93 | } |
---|
94 | this.progressBar.setHeight(inner.offsetHeight); |
---|
95 | }, |
---|
96 | |
---|
97 | // private |
---|
98 | afterRender : function(){ |
---|
99 | Ext.ProgressBar.superclass.afterRender.call(this); |
---|
100 | if(this.value){ |
---|
101 | this.updateProgress(this.value, this.text); |
---|
102 | }else{ |
---|
103 | this.updateText(this.text); |
---|
104 | } |
---|
105 | }, |
---|
106 | |
---|
107 | /** |
---|
108 | * Updates the progress bar value, and optionally its text. If the text argument is not specified, |
---|
109 | * any existing text value will be unchanged. To blank out existing text, pass ''. Note that even |
---|
110 | * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for |
---|
111 | * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control. |
---|
112 | * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0) |
---|
113 | * @param {String} text (optional) The string to display in the progress text element (defaults to '') |
---|
114 | * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is |
---|
115 | * not specified, the default for the class is used (default to false) |
---|
116 | * @return {Ext.ProgressBar} this |
---|
117 | */ |
---|
118 | updateProgress : function(value, text, animate){ |
---|
119 | this.value = value || 0; |
---|
120 | if(text){ |
---|
121 | this.updateText(text); |
---|
122 | } |
---|
123 | if(this.rendered && !this.isDestroyed){ |
---|
124 | var w = Math.floor(value*this.el.dom.firstChild.offsetWidth); |
---|
125 | this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate)); |
---|
126 | if(this.textTopEl){ |
---|
127 | //textTopEl should be the same width as the bar so overflow will clip as the bar moves |
---|
128 | this.textTopEl.removeClass('x-hidden').setWidth(w); |
---|
129 | } |
---|
130 | } |
---|
131 | this.fireEvent('update', this, value, text); |
---|
132 | return this; |
---|
133 | }, |
---|
134 | |
---|
135 | /** |
---|
136 | * Initiates an auto-updating progress bar. A duration can be specified, in which case the progress |
---|
137 | * bar will automatically reset after a fixed amount of time and optionally call a callback function |
---|
138 | * if specified. If no duration is passed in, then the progress bar will run indefinitely and must |
---|
139 | * be manually cleared by calling {@link #reset}. The wait method accepts a config object with |
---|
140 | * the following properties: |
---|
141 | * <pre> |
---|
142 | Property Type Description |
---|
143 | ---------- ------------ ---------------------------------------------------------------------- |
---|
144 | duration Number The length of time in milliseconds that the progress bar should |
---|
145 | run before resetting itself (defaults to undefined, in which case it |
---|
146 | will run indefinitely until reset is called) |
---|
147 | interval Number The length of time in milliseconds between each progress update |
---|
148 | (defaults to 1000 ms) |
---|
149 | animate Boolean Whether to animate the transition of the progress bar. If this value is |
---|
150 | not specified, the default for the class is used. |
---|
151 | increment Number The number of progress update segments to display within the progress |
---|
152 | bar (defaults to 10). If the bar reaches the end and is still |
---|
153 | updating, it will automatically wrap back to the beginning. |
---|
154 | text String Optional text to display in the progress bar element (defaults to ''). |
---|
155 | fn Function A callback function to execute after the progress bar finishes auto- |
---|
156 | updating. The function will be called with no arguments. This function |
---|
157 | will be ignored if duration is not specified since in that case the |
---|
158 | progress bar can only be stopped programmatically, so any required function |
---|
159 | should be called by the same code after it resets the progress bar. |
---|
160 | scope Object The scope that is passed to the callback function (only applies when |
---|
161 | duration and fn are both passed). |
---|
162 | </pre> |
---|
163 | * |
---|
164 | * Example usage: |
---|
165 | * <pre><code> |
---|
166 | var p = new Ext.ProgressBar({ |
---|
167 | renderTo: 'my-el' |
---|
168 | }); |
---|
169 | |
---|
170 | //Wait for 5 seconds, then update the status el (progress bar will auto-reset) |
---|
171 | p.wait({ |
---|
172 | interval: 100, //bar will move fast! |
---|
173 | duration: 5000, |
---|
174 | increment: 15, |
---|
175 | text: 'Updating...', |
---|
176 | scope: this, |
---|
177 | fn: function(){ |
---|
178 | Ext.fly('status').update('Done!'); |
---|
179 | } |
---|
180 | }); |
---|
181 | |
---|
182 | //Or update indefinitely until some async action completes, then reset manually |
---|
183 | p.wait(); |
---|
184 | myAction.on('complete', function(){ |
---|
185 | p.reset(); |
---|
186 | Ext.fly('status').update('Done!'); |
---|
187 | }); |
---|
188 | </code></pre> |
---|
189 | * @param {Object} config (optional) Configuration options |
---|
190 | * @return {Ext.ProgressBar} this |
---|
191 | */ |
---|
192 | wait : function(o){ |
---|
193 | if(!this.waitTimer){ |
---|
194 | var scope = this; |
---|
195 | o = o || {}; |
---|
196 | this.updateText(o.text); |
---|
197 | this.waitTimer = Ext.TaskMgr.start({ |
---|
198 | run: function(i){ |
---|
199 | var inc = o.increment || 10; |
---|
200 | i -= 1; |
---|
201 | this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate); |
---|
202 | }, |
---|
203 | interval: o.interval || 1000, |
---|
204 | duration: o.duration, |
---|
205 | onStop: function(){ |
---|
206 | if(o.fn){ |
---|
207 | o.fn.apply(o.scope || this); |
---|
208 | } |
---|
209 | this.reset(); |
---|
210 | }, |
---|
211 | scope: scope |
---|
212 | }); |
---|
213 | } |
---|
214 | return this; |
---|
215 | }, |
---|
216 | |
---|
217 | /** |
---|
218 | * Returns true if the progress bar is currently in a {@link #wait} operation |
---|
219 | * @return {Boolean} True if waiting, else false |
---|
220 | */ |
---|
221 | isWaiting : function(){ |
---|
222 | return this.waitTimer !== null; |
---|
223 | }, |
---|
224 | |
---|
225 | /** |
---|
226 | * Updates the progress bar text. If specified, textEl will be updated, otherwise the progress |
---|
227 | * bar itself will display the updated text. |
---|
228 | * @param {String} text (optional) The string to display in the progress text element (defaults to '') |
---|
229 | * @return {Ext.ProgressBar} this |
---|
230 | */ |
---|
231 | updateText : function(text){ |
---|
232 | this.text = text || ' '; |
---|
233 | if(this.rendered){ |
---|
234 | this.textEl.update(this.text); |
---|
235 | } |
---|
236 | return this; |
---|
237 | }, |
---|
238 | |
---|
239 | /** |
---|
240 | * Synchronizes the inner bar width to the proper proportion of the total componet width based |
---|
241 | * on the current progress {@link #value}. This will be called automatically when the ProgressBar |
---|
242 | * is resized by a layout, but if it is rendered auto width, this method can be called from |
---|
243 | * another resize handler to sync the ProgressBar if necessary. |
---|
244 | */ |
---|
245 | syncProgressBar : function(){ |
---|
246 | if(this.value){ |
---|
247 | this.updateProgress(this.value, this.text); |
---|
248 | } |
---|
249 | return this; |
---|
250 | }, |
---|
251 | |
---|
252 | /** |
---|
253 | * Sets the size of the progress bar. |
---|
254 | * @param {Number} width The new width in pixels |
---|
255 | * @param {Number} height The new height in pixels |
---|
256 | * @return {Ext.ProgressBar} this |
---|
257 | */ |
---|
258 | setSize : function(w, h){ |
---|
259 | Ext.ProgressBar.superclass.setSize.call(this, w, h); |
---|
260 | if(this.textTopEl){ |
---|
261 | var inner = this.el.dom.firstChild; |
---|
262 | this.textEl.setSize(inner.offsetWidth, inner.offsetHeight); |
---|
263 | } |
---|
264 | this.syncProgressBar(); |
---|
265 | return this; |
---|
266 | }, |
---|
267 | |
---|
268 | /** |
---|
269 | * Resets the progress bar value to 0 and text to empty string. If hide = true, the progress |
---|
270 | * bar will also be hidden (using the {@link #hideMode} property internally). |
---|
271 | * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false) |
---|
272 | * @return {Ext.ProgressBar} this |
---|
273 | */ |
---|
274 | reset : function(hide){ |
---|
275 | this.updateProgress(0); |
---|
276 | if(this.textTopEl){ |
---|
277 | this.textTopEl.addClass('x-hidden'); |
---|
278 | } |
---|
279 | this.clearTimer(); |
---|
280 | if(hide === true){ |
---|
281 | this.hide(); |
---|
282 | } |
---|
283 | return this; |
---|
284 | }, |
---|
285 | |
---|
286 | // private |
---|
287 | clearTimer : function(){ |
---|
288 | if(this.waitTimer){ |
---|
289 | this.waitTimer.onStop = null; //prevent recursion |
---|
290 | Ext.TaskMgr.stop(this.waitTimer); |
---|
291 | this.waitTimer = null; |
---|
292 | } |
---|
293 | }, |
---|
294 | |
---|
295 | onDestroy: function(){ |
---|
296 | this.clearTimer(); |
---|
297 | if(this.rendered){ |
---|
298 | if(this.textEl.isComposite){ |
---|
299 | this.textEl.clear(); |
---|
300 | } |
---|
301 | Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl'); |
---|
302 | } |
---|
303 | Ext.ProgressBar.superclass.onDestroy.call(this); |
---|
304 | } |
---|
305 | }); |
---|
306 | Ext.reg('progress', Ext.ProgressBar); |
---|