[76] | 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); |
---|