]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | /**\r |
2 | * An updateable progress bar component. The progress bar supports two different modes: manual and automatic.\r | |
3 | *\r | |
4 | * In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the progress bar\r | |
5 | * as needed from your own code. This method is most appropriate when you want to show progress throughout an operation\r | |
6 | * that has predictable points of interest at which you can update the control.\r | |
7 | *\r | |
8 | * In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it once the\r | |
9 | * operation is complete. You can optionally have the progress bar wait for a specific amount of time and then clear\r | |
10 | * itself. Automatic mode is most appropriate for timed operations or asynchronous operations in which you have no need\r | |
11 | * for indicating intermediate progress.\r | |
12 | *\r | |
13 | * @example\r | |
14 | * var p = Ext.create('Ext.ProgressBar', {\r | |
15 | * renderTo: Ext.getBody(),\r | |
16 | * width: 300\r | |
17 | * });\r | |
18 | *\r | |
19 | * // Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r | |
20 | * p.wait({\r | |
21 | * interval: 500, //bar will move fast!\r | |
22 | * duration: 50000,\r | |
23 | * increment: 15,\r | |
24 | * text: 'Updating...',\r | |
25 | * scope: this,\r | |
26 | * fn: function(){\r | |
27 | * p.updateText('Done!');\r | |
28 | * }\r | |
29 | * });\r | |
30 | */\r | |
31 | Ext.define('Ext.ProgressBar', {\r | |
32 | extend: 'Ext.Component',\r | |
33 | xtype: 'progressbar',\r | |
34 | mixins: [\r | |
35 | 'Ext.ProgressBase'\r | |
36 | ],\r | |
37 | \r | |
38 | requires: [\r | |
39 | 'Ext.Template',\r | |
40 | 'Ext.CompositeElement',\r | |
41 | 'Ext.TaskManager',\r | |
42 | 'Ext.layout.component.ProgressBar'\r | |
43 | ],\r | |
44 | \r | |
45 | uses: ['Ext.fx.Anim'],\r | |
46 | \r | |
47 | /**\r | |
48 | * @cfg {String/HTMLElement/Ext.dom.Element} textEl\r | |
49 | * The element to render the progress text to (defaults to the progress bar's internal text element)\r | |
50 | */\r | |
51 | \r | |
52 | /**\r | |
53 | * @cfg {String} id\r | |
54 | * The progress bar element's id (defaults to an auto-generated id)\r | |
55 | */\r | |
56 | \r | |
57 | /**\r | |
58 | * @cfg {String} [baseCls='x-progress']\r | |
59 | * The base CSS class to apply to the progress bar's wrapper element.\r | |
60 | */\r | |
61 | baseCls: Ext.baseCSSPrefix + 'progress',\r | |
62 | \r | |
63 | /**\r | |
64 | * @cfg {Boolean/Object} animate\r | |
65 | * True to animate the progress bar during transitions, or an animation configuration\r | |
66 | * (see the {@link #method-animate} method for details).\r | |
67 | */\r | |
68 | animate: false,\r | |
69 | \r | |
70 | /**\r | |
71 | * @cfg {String} text\r | |
72 | * The text shown in the progress bar.\r | |
73 | */\r | |
74 | text: '',\r | |
75 | \r | |
76 | /**\r | |
77 | * @private\r | |
78 | */\r | |
79 | waitTimer: null,\r | |
80 | \r | |
81 | childEls: [\r | |
82 | 'bar'\r | |
83 | ],\r | |
84 | \r | |
85 | defaultBindProperty: 'value',\r | |
86 | \r | |
87 | renderTpl: [\r | |
88 | '<tpl if="internalText">',\r | |
89 | '<div class="{baseCls}-text {baseCls}-text-back">{text}</div>',\r | |
90 | '</tpl>',\r | |
91 | '<div id="{id}-bar" data-ref="bar" class="{baseCls}-bar {baseCls}-bar-{ui}" role="presentation" style="width:{percentage}%">',\r | |
92 | '<tpl if="internalText">',\r | |
93 | '<div class="{baseCls}-text">',\r | |
94 | '<div>{text}</div>',\r | |
95 | '</div>',\r | |
96 | '</tpl>',\r | |
97 | '</div>'\r | |
98 | ],\r | |
99 | \r | |
100 | componentLayout: 'progressbar',\r | |
101 | \r | |
102 | ariaRole: 'progressbar',\r | |
103 | \r | |
104 | /**\r | |
105 | * @event update\r | |
106 | * Fires after each update interval\r | |
107 | * @param {Ext.ProgressBar} this\r | |
108 | * @param {Number} value The current progress value\r | |
109 | * @param {String} text The current progress text\r | |
110 | */\r | |
111 | \r | |
112 | initRenderData: function() {\r | |
113 | var me = this,\r | |
114 | value = me.value || 0;\r | |
115 | \r | |
116 | return Ext.apply(me.callParent(), {\r | |
117 | internalText : !me.hasOwnProperty('textEl'),\r | |
118 | text : me.text || ' ',\r | |
119 | percentage : value * 100\r | |
120 | });\r | |
121 | },\r | |
122 | \r | |
123 | onRender : function() {\r | |
124 | var me = this;\r | |
125 | \r | |
126 | me.callParent(arguments);\r | |
127 | \r | |
128 | // External text display\r | |
129 | if (me.textEl) {\r | |
130 | me.textEl = Ext.get(me.textEl);\r | |
131 | me.updateText(me.text);\r | |
132 | }\r | |
133 | // Inline text display\r | |
134 | else {\r | |
135 | // This produces a composite w/2 el's (which is why we cannot use childEls or\r | |
136 | // renderSelectors):\r | |
137 | me.textEl = me.el.select('.' + me.baseCls + '-text');\r | |
138 | }\r | |
139 | },\r | |
140 | \r | |
141 | updateValue: function(value) {\r | |
142 | this.updateProgress(value, Math.round(value * 100) + '%');\r | |
143 | },\r | |
144 | \r | |
145 | /**\r | |
146 | * Updates the progress bar value, and optionally its text.\r | |
147 | * \r | |
148 | * If the text argument is not specified, then the {@link #textTpl} will be used to generate the text.\r | |
149 | * If there is no `textTpl`, any existing text value will be unchanged. To blank out existing text, pass `""`.\r | |
150 | *\r | |
151 | * Note that even if the progress bar value exceeds 1, it will never automatically reset --\r | |
152 | * you are responsible for determining when the progress is complete and\r | |
153 | * calling {@link #reset} to clear and/or hide the control.\r | |
154 | * @param {Number} [value=0] A floating point value between 0 and 1 (e.g., .5)\r | |
155 | * @param {String} [text=''] The string to display in the progress text element\r | |
156 | * @param {Boolean} [animate=false] Whether to animate the transition of the progress bar. If this value is not\r | |
157 | * specified, the default for the class is used\r | |
158 | * @return {Ext.ProgressBar} this\r | |
159 | */\r | |
160 | updateProgress: function(value, text, animate) {\r | |
161 | value = value || 0;\r | |
162 | \r | |
163 | var me = this,\r | |
164 | oldValue = me.value,\r | |
165 | textTpl = me.getTextTpl();\r | |
166 | \r | |
167 | // Ensure value is not undefined.\r | |
168 | me.value = value || (value = 0);\r | |
169 | \r | |
170 | // Empty string (falsy) must blank out the text as per docs.\r | |
171 | if (text != null) {\r | |
172 | me.updateText(text);\r | |
173 | }\r | |
174 | // Generate text using template and progress values.\r | |
175 | else if (textTpl) {\r | |
176 | me.updateText(textTpl.apply({\r | |
177 | value: value,\r | |
178 | percent: value * 100\r | |
179 | }));\r | |
180 | }\r | |
181 | if (me.rendered && !me.destroyed) {\r | |
182 | if (animate === true || (animate !== false && me.animate)) {\r | |
183 | me.bar.stopAnimation();\r | |
184 | me.bar.animate(Ext.apply({\r | |
185 | from: {\r | |
186 | width: (oldValue * 100) + '%'\r | |
187 | },\r | |
188 | to: {\r | |
189 | width: (value * 100) + '%'\r | |
190 | }\r | |
191 | }, me.animate));\r | |
192 | } else {\r | |
193 | me.bar.setStyle('width', (value * 100) + '%');\r | |
194 | }\r | |
195 | }\r | |
196 | me.fireEvent('update', me, value, text);\r | |
197 | return me;\r | |
198 | },\r | |
199 | \r | |
200 | /**\r | |
201 | * Updates the progress bar text. If specified, textEl will be updated, otherwise the progress bar itself will\r | |
202 | * display the updated text.\r | |
203 | * @param {String} [text=''] The string to display in the progress text element\r | |
204 | * @return {Ext.ProgressBar} this\r | |
205 | */\r | |
206 | updateText: function(text) {\r | |
207 | var me = this;\r | |
208 | \r | |
209 | me.text = text;\r | |
210 | if (me.rendered) {\r | |
211 | me.textEl.setHtml(me.text);\r | |
212 | }\r | |
213 | return me;\r | |
214 | },\r | |
215 | \r | |
216 | applyText : function(text) {\r | |
217 | this.updateText(text);\r | |
218 | },\r | |
219 | \r | |
220 | getText: function(){\r | |
221 | return this.text; \r | |
222 | },\r | |
223 | \r | |
224 | /**\r | |
225 | * Initiates an auto-updating progress bar. A duration can be specified, in which case the progress bar will\r | |
226 | * automatically reset after a fixed amount of time and optionally call a callback function if specified. If no\r | |
227 | * duration is passed in, then the progress bar will run indefinitely and must be manually cleared by calling\r | |
228 | * {@link #reset}.\r | |
229 | *\r | |
230 | * Example usage:\r | |
231 | *\r | |
232 | * var p = new Ext.ProgressBar({\r | |
233 | * renderTo: 'my-el'\r | |
234 | * });\r | |
235 | *\r | |
236 | * //Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r | |
237 | * var p = Ext.create('Ext.ProgressBar', {\r | |
238 | * renderTo: Ext.getBody(),\r | |
239 | * width: 300\r | |
240 | * });\r | |
241 | *\r | |
242 | * //Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r | |
243 | * p.wait({\r | |
244 | * interval: 500, //bar will move fast!\r | |
245 | * duration: 50000,\r | |
246 | * increment: 15,\r | |
247 | * text: 'Updating...',\r | |
248 | * scope: this,\r | |
249 | * fn: function(){\r | |
250 | * p.updateText('Done!');\r | |
251 | * }\r | |
252 | * });\r | |
253 | *\r | |
254 | * //Or update indefinitely until some async action completes, then reset manually\r | |
255 | * p.wait();\r | |
256 | * myAction.on('complete', function(){\r | |
257 | * p.reset();\r | |
258 | * p.updateText('Done!');\r | |
259 | * });\r | |
260 | *\r | |
261 | * @param {Object} config (optional) Configuration options\r | |
262 | * @param {Number} config.duration The length of time in milliseconds that the progress bar should\r | |
263 | * run before resetting itself (defaults to undefined, in which case it will run indefinitely\r | |
264 | * until reset is called)\r | |
265 | * @param {Number} config.interval The length of time in milliseconds between each progress update\r | |
266 | * (defaults to 1000 ms)\r | |
267 | * @param {Boolean} config.animate Whether to animate the transition of the progress bar. If this\r | |
268 | * value is not specified, the default for the class is used.\r | |
269 | * @param {Number} config.increment The number of progress update segments to display within the\r | |
270 | * progress bar (defaults to 10). If the bar reaches the end and is still updating, it will\r | |
271 | * automatically wrap back to the beginning.\r | |
272 | * @param {String} config.text Optional text to display in the progress bar element (defaults to '').\r | |
273 | * @param {Function} config.fn A callback function to execute after the progress bar finishes auto-\r | |
274 | * updating. The function will be called with no arguments. This function will be ignored if\r | |
275 | * duration is not specified since in that case the progress bar can only be stopped programmatically,\r | |
276 | * so any required function should be called by the same code after it resets the progress bar.\r | |
277 | * @param {Object} config.scope The scope that is passed to the callback function (only applies when\r | |
278 | * duration and fn are both passed).\r | |
279 | * @return {Ext.ProgressBar} this\r | |
280 | */\r | |
281 | wait: function(o) {\r | |
282 | var me = this, scope;\r | |
283 | \r | |
284 | if (!me.waitTimer) {\r | |
285 | scope = me;\r | |
286 | o = o || {};\r | |
287 | me.updateText(o.text);\r | |
288 | me.waitTimer = Ext.TaskManager.start({\r | |
289 | run: function(i){\r | |
290 | var inc = o.increment || 10;\r | |
291 | i -= 1;\r | |
292 | me.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);\r | |
293 | },\r | |
294 | interval: o.interval || 1000,\r | |
295 | duration: o.duration,\r | |
296 | onStop: function(){\r | |
297 | if (o.fn) {\r | |
298 | o.fn.apply(o.scope || me);\r | |
299 | }\r | |
300 | me.reset();\r | |
301 | },\r | |
302 | scope: scope\r | |
303 | });\r | |
304 | }\r | |
305 | return me;\r | |
306 | },\r | |
307 | \r | |
308 | /**\r | |
309 | * Returns true if the progress bar is currently in a {@link #wait} operation\r | |
310 | * @return {Boolean} True if waiting, else false\r | |
311 | */\r | |
312 | isWaiting: function(){\r | |
313 | return this.waitTimer !== null;\r | |
314 | },\r | |
315 | \r | |
316 | /**\r | |
317 | * Resets the progress bar value to 0 and text to empty string. If hide = true, the progress bar will also be hidden\r | |
318 | * (using the {@link #hideMode} property internally).\r | |
319 | * @param {Boolean} [hide=false] True to hide the progress bar.\r | |
320 | * @return {Ext.ProgressBar} this\r | |
321 | */\r | |
322 | reset: function(hide){\r | |
323 | var me = this;\r | |
324 | \r | |
325 | me.updateProgress(0);\r | |
326 | me.clearTimer();\r | |
327 | if (hide === true) {\r | |
328 | me.hide();\r | |
329 | }\r | |
330 | return me;\r | |
331 | },\r | |
332 | \r | |
333 | /**\r | |
334 | * @private\r | |
335 | */\r | |
336 | clearTimer: function(){\r | |
337 | var me = this;\r | |
338 | \r | |
339 | if (me.waitTimer) {\r | |
340 | me.waitTimer.onStop = null; //prevent recursion\r | |
341 | Ext.TaskManager.stop(me.waitTimer);\r | |
342 | me.waitTimer = null;\r | |
343 | }\r | |
344 | },\r | |
345 | \r | |
346 | onDestroy: function(){\r | |
347 | var me = this,\r | |
348 | bar = me.bar;\r | |
349 | \r | |
350 | me.clearTimer();\r | |
351 | if (me.rendered) {\r | |
352 | if (me.textEl.isComposite) {\r | |
353 | me.textEl.clear();\r | |
354 | }\r | |
355 | Ext.destroyMembers(me, 'textEl', 'progressBar');\r | |
356 | if (bar && me.animate) {\r | |
357 | bar.stopAnimation();\r | |
358 | }\r | |
359 | }\r | |
360 | me.callParent();\r | |
361 | }\r | |
362 | });\r |