Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / src / widgets / ProgressBar.js
index dc2a9dd..7e44081 100644 (file)
 /*!
- * Ext JS Library 3.0.0
- * Copyright(c) 2006-2009 Ext JS, LLC
+ * Ext JS Library 3.2.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
  * licensing@extjs.com
  * http://www.extjs.com/license
  */
-/**\r
- * @class Ext.ProgressBar\r
- * @extends Ext.BoxComponent\r
- * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>\r
- * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the\r
- * progress bar as needed from your own code.  This method is most appropriate when you want to show progress\r
- * throughout an operation that has predictable points of interest at which you can update the control.</p>\r
- * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it\r
- * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time\r
- * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in\r
- * which you have no need for indicating intermediate progress.</p>\r
- * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
- * @cfg {String} text The progress bar text (defaults to '')\r
- * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress\r
- * bar's internal text element)\r
- * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)\r
- * @xtype progress\r
- */\r
-Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {\r
-   /**\r
-    * @cfg {String} baseCls\r
-    * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')\r
-    */\r
-    baseCls : 'x-progress',\r
-    \r
-    /**\r
-    * @cfg {Boolean} animate\r
-    * True to animate the progress bar during transitions (defaults to false)\r
-    */\r
-    animate : false,\r
-\r
-    // private\r
-    waitTimer : null,\r
-\r
-    // private\r
-    initComponent : function(){\r
-        Ext.ProgressBar.superclass.initComponent.call(this);\r
-        this.addEvents(\r
-            /**\r
-             * @event update\r
-             * Fires after each update interval\r
-             * @param {Ext.ProgressBar} this\r
-             * @param {Number} The current progress value\r
-             * @param {String} The current progress text\r
-             */\r
-            "update"\r
-        );\r
-    },\r
-\r
-    // private\r
-    onRender : function(ct, position){\r
-        var tpl = new Ext.Template(\r
-            '<div class="{cls}-wrap">',\r
-                '<div class="{cls}-inner">',\r
-                    '<div class="{cls}-bar">',\r
-                        '<div class="{cls}-text">',\r
-                            '<div>&#160;</div>',\r
-                        '</div>',\r
-                    '</div>',\r
-                    '<div class="{cls}-text {cls}-text-back">',\r
-                        '<div>&#160;</div>',\r
-                    '</div>',\r
-                '</div>',\r
-            '</div>'\r
-        );\r
-\r
-        this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)\r
-               : tpl.append(ct, {cls: this.baseCls}, true);\r
-                       \r
-        if(this.id){\r
-            this.el.dom.id = this.id;\r
-        }\r
-        var inner = this.el.dom.firstChild;\r
-        this.progressBar = Ext.get(inner.firstChild);\r
-\r
-        if(this.textEl){\r
-            //use an external text el\r
-            this.textEl = Ext.get(this.textEl);\r
-            delete this.textTopEl;\r
-        }else{\r
-            //setup our internal layered text els\r
-            this.textTopEl = Ext.get(this.progressBar.dom.firstChild);\r
-            var textBackEl = Ext.get(inner.childNodes[1]);\r
-            this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');\r
-            this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);\r
-            this.textEl.setWidth(inner.offsetWidth);\r
-        }\r
-        this.progressBar.setHeight(inner.offsetHeight);\r
-    },\r
-    \r
-    // private\r
-    afterRender : function(){\r
-        Ext.ProgressBar.superclass.afterRender.call(this);\r
-        if(this.value){\r
-            this.updateProgress(this.value, this.text);\r
-        }else{\r
-            this.updateText(this.text);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Updates the progress bar value, and optionally its text.  If the text argument is not specified,\r
-     * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even\r
-     * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for\r
-     * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.\r
-     * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
-     * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
-     * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is\r
-     * not specified, the default for the class is used (default to false)\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    updateProgress : function(value, text, animate){\r
-        this.value = value || 0;\r
-        if(text){\r
-            this.updateText(text);\r
-        }\r
-        if(this.rendered){\r
-            var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);\r
-            this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));\r
-            if(this.textTopEl){\r
-                //textTopEl should be the same width as the bar so overflow will clip as the bar moves\r
-                this.textTopEl.removeClass('x-hidden').setWidth(w);\r
-            }\r
-        }\r
-        this.fireEvent('update', this, value, text);\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress\r
-     * bar will automatically reset after a fixed amount of time and optionally call a callback function\r
-     * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must\r
-     * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with\r
-     * the following properties:\r
-     * <pre>\r
-Property   Type          Description\r
----------- ------------  ----------------------------------------------------------------------\r
-duration   Number        The length of time in milliseconds that the progress bar should\r
-                         run before resetting itself (defaults to undefined, in which case it\r
-                         will run indefinitely until reset is called)\r
-interval   Number        The length of time in milliseconds between each progress update\r
-                         (defaults to 1000 ms)\r
-animate    Boolean       Whether to animate the transition of the progress bar. If this value is\r
-                         not specified, the default for the class is used.                                                   \r
-increment  Number        The number of progress update segments to display within the progress\r
-                         bar (defaults to 10).  If the bar reaches the end and is still\r
-                         updating, it will automatically wrap back to the beginning.\r
-text       String        Optional text to display in the progress bar element (defaults to '').\r
-fn         Function      A callback function to execute after the progress bar finishes auto-\r
-                         updating.  The function will be called with no arguments.  This function\r
-                         will be ignored if duration is not specified since in that case the\r
-                         progress bar can only be stopped programmatically, so any required function\r
-                         should be called by the same code after it resets the progress bar.\r
-scope      Object        The scope that is passed to the callback function (only applies when\r
-                         duration and fn are both passed).\r
-</pre>\r
-         *\r
-         * Example usage:\r
-         * <pre><code>\r
-var p = new Ext.ProgressBar({\r
-   renderTo: 'my-el'\r
-});\r
-\r
-//Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r
-p.wait({\r
-   interval: 100, //bar will move fast!\r
-   duration: 5000,\r
-   increment: 15,\r
-   text: 'Updating...',\r
-   scope: this,\r
-   fn: function(){\r
-      Ext.fly('status').update('Done!');\r
-   }\r
-});\r
-\r
-//Or update indefinitely until some async action completes, then reset manually\r
-p.wait();\r
-myAction.on('complete', function(){\r
-    p.reset();\r
-    Ext.fly('status').update('Done!');\r
-});\r
-</code></pre>\r
-     * @param {Object} config (optional) Configuration options\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    wait : function(o){\r
-        if(!this.waitTimer){\r
-            var scope = this;\r
-            o = o || {};\r
-            this.updateText(o.text);\r
-            this.waitTimer = Ext.TaskMgr.start({\r
-                run: function(i){\r
-                    var inc = o.increment || 10;\r
-                    this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);\r
-                },\r
-                interval: o.interval || 1000,\r
-                duration: o.duration,\r
-                onStop: function(){\r
-                    if(o.fn){\r
-                        o.fn.apply(o.scope || this);\r
-                    }\r
-                    this.reset();\r
-                },\r
-                scope: scope\r
-            });\r
-        }\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Returns true if the progress bar is currently in a {@link #wait} operation\r
-     * @return {Boolean} True if waiting, else false\r
-     */\r
-    isWaiting : function(){\r
-        return this.waitTimer !== null;\r
-    },\r
-\r
-    /**\r
-     * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress\r
-     * bar itself will display the updated text.\r
-     * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    updateText : function(text){\r
-        this.text = text || '&#160;';\r
-        if(this.rendered){\r
-            this.textEl.update(this.text);\r
-        }\r
-        return this;\r
-    },\r
-    \r
-    /**\r
-     * Synchronizes the inner bar width to the proper proportion of the total componet width based\r
-     * on the current progress {@link #value}.  This will be called automatically when the ProgressBar\r
-     * is resized by a layout, but if it is rendered auto width, this method can be called from\r
-     * another resize handler to sync the ProgressBar if necessary.\r
-     */\r
-    syncProgressBar : function(){\r
-        if(this.value){\r
-            this.updateProgress(this.value, this.text);\r
-        }\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Sets the size of the progress bar.\r
-     * @param {Number} width The new width in pixels\r
-     * @param {Number} height The new height in pixels\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    setSize : function(w, h){\r
-        Ext.ProgressBar.superclass.setSize.call(this, w, h);\r
-        if(this.textTopEl){\r
-            var inner = this.el.dom.firstChild;\r
-            this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);\r
-        }\r
-        this.syncProgressBar();\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress\r
-     * bar will also be hidden (using the {@link #hideMode} property internally).\r
-     * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    reset : function(hide){\r
-        this.updateProgress(0);\r
-        if(this.textTopEl){\r
-            this.textTopEl.addClass('x-hidden');\r
-        }\r
-        if(this.waitTimer){\r
-            this.waitTimer.onStop = null; //prevent recursion\r
-            Ext.TaskMgr.stop(this.waitTimer);\r
-            this.waitTimer = null;\r
-        }\r
-        if(hide === true){\r
-            this.hide();\r
-        }\r
-        return this;\r
-    }\r
-});\r
+/**
+ * @class Ext.ProgressBar
+ * @extends Ext.BoxComponent
+ * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>
+ * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
+ * progress bar as needed from your own code.  This method is most appropriate when you want to show progress
+ * throughout an operation that has predictable points of interest at which you can update the control.</p>
+ * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
+ * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time
+ * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in
+ * which you have no need for indicating intermediate progress.</p>
+ * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
+ * @cfg {String} text The progress bar text (defaults to '')
+ * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
+ * bar's internal text element)
+ * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
+ * @xtype progress
+ */
+Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
+   /**
+    * @cfg {String} baseCls
+    * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
+    */
+    baseCls : 'x-progress',
+    
+    /**
+    * @cfg {Boolean} animate
+    * True to animate the progress bar during transitions (defaults to false)
+    */
+    animate : false,
+
+    // private
+    waitTimer : null,
+
+    // private
+    initComponent : function(){
+        Ext.ProgressBar.superclass.initComponent.call(this);
+        this.addEvents(
+            /**
+             * @event update
+             * Fires after each update interval
+             * @param {Ext.ProgressBar} this
+             * @param {Number} The current progress value
+             * @param {String} The current progress text
+             */
+            "update"
+        );
+    },
+
+    // private
+    onRender : function(ct, position){
+        var tpl = new Ext.Template(
+            '<div class="{cls}-wrap">',
+                '<div class="{cls}-inner">',
+                    '<div class="{cls}-bar">',
+                        '<div class="{cls}-text">',
+                            '<div>&#160;</div>',
+                        '</div>',
+                    '</div>',
+                    '<div class="{cls}-text {cls}-text-back">',
+                        '<div>&#160;</div>',
+                    '</div>',
+                '</div>',
+            '</div>'
+        );
+
+        this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
+            : tpl.append(ct, {cls: this.baseCls}, true);
+                
+        if(this.id){
+            this.el.dom.id = this.id;
+        }
+        var inner = this.el.dom.firstChild;
+        this.progressBar = Ext.get(inner.firstChild);
+
+        if(this.textEl){
+            //use an external text el
+            this.textEl = Ext.get(this.textEl);
+            delete this.textTopEl;
+        }else{
+            //setup our internal layered text els
+            this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
+            var textBackEl = Ext.get(inner.childNodes[1]);
+            this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
+            this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
+            this.textEl.setWidth(inner.offsetWidth);
+        }
+        this.progressBar.setHeight(inner.offsetHeight);
+    },
+    
+    // private
+    afterRender : function(){
+        Ext.ProgressBar.superclass.afterRender.call(this);
+        if(this.value){
+            this.updateProgress(this.value, this.text);
+        }else{
+            this.updateText(this.text);
+        }
+    },
+
+    /**
+     * Updates the progress bar value, and optionally its text.  If the text argument is not specified,
+     * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even
+     * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
+     * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
+     * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
+     * @param {String} text (optional) The string to display in the progress text element (defaults to '')
+     * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
+     * not specified, the default for the class is used (default to false)
+     * @return {Ext.ProgressBar} this
+     */
+    updateProgress : function(value, text, animate){
+        this.value = value || 0;
+        if(text){
+            this.updateText(text);
+        }
+        if(this.rendered && !this.isDestroyed){
+            var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
+            this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
+            if(this.textTopEl){
+                //textTopEl should be the same width as the bar so overflow will clip as the bar moves
+                this.textTopEl.removeClass('x-hidden').setWidth(w);
+            }
+        }
+        this.fireEvent('update', this, value, text);
+        return this;
+    },
+
+    /**
+     * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress
+     * bar will automatically reset after a fixed amount of time and optionally call a callback function
+     * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must
+     * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with
+     * the following properties:
+     * <pre>
+Property   Type          Description
+---------- ------------  ----------------------------------------------------------------------
+duration   Number        The length of time in milliseconds that the progress bar should
+                         run before resetting itself (defaults to undefined, in which case it
+                         will run indefinitely until reset is called)
+interval   Number        The length of time in milliseconds between each progress update
+                         (defaults to 1000 ms)
+animate    Boolean       Whether to animate the transition of the progress bar. If this value is
+                         not specified, the default for the class is used.                                                   
+increment  Number        The number of progress update segments to display within the progress
+                         bar (defaults to 10).  If the bar reaches the end and is still
+                         updating, it will automatically wrap back to the beginning.
+text       String        Optional text to display in the progress bar element (defaults to '').
+fn         Function      A callback function to execute after the progress bar finishes auto-
+                         updating.  The function will be called with no arguments.  This function
+                         will be ignored if duration is not specified since in that case the
+                         progress bar can only be stopped programmatically, so any required function
+                         should be called by the same code after it resets the progress bar.
+scope      Object        The scope that is passed to the callback function (only applies when
+                         duration and fn are both passed).
+</pre>
+         *
+         * Example usage:
+         * <pre><code>
+var p = new Ext.ProgressBar({
+   renderTo: 'my-el'
+});
+
+//Wait for 5 seconds, then update the status el (progress bar will auto-reset)
+p.wait({
+   interval: 100, //bar will move fast!
+   duration: 5000,
+   increment: 15,
+   text: 'Updating...',
+   scope: this,
+   fn: function(){
+      Ext.fly('status').update('Done!');
+   }
+});
+
+//Or update indefinitely until some async action completes, then reset manually
+p.wait();
+myAction.on('complete', function(){
+    p.reset();
+    Ext.fly('status').update('Done!');
+});
+</code></pre>
+     * @param {Object} config (optional) Configuration options
+     * @return {Ext.ProgressBar} this
+     */
+    wait : function(o){
+        if(!this.waitTimer){
+            var scope = this;
+            o = o || {};
+            this.updateText(o.text);
+            this.waitTimer = Ext.TaskMgr.start({
+                run: function(i){
+                    var inc = o.increment || 10;
+                    i -= 1;
+                    this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
+                },
+                interval: o.interval || 1000,
+                duration: o.duration,
+                onStop: function(){
+                    if(o.fn){
+                        o.fn.apply(o.scope || this);
+                    }
+                    this.reset();
+                },
+                scope: scope
+            });
+        }
+        return this;
+    },
+
+    /**
+     * Returns true if the progress bar is currently in a {@link #wait} operation
+     * @return {Boolean} True if waiting, else false
+     */
+    isWaiting : function(){
+        return this.waitTimer !== null;
+    },
+
+    /**
+     * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress
+     * bar itself will display the updated text.
+     * @param {String} text (optional) The string to display in the progress text element (defaults to '')
+     * @return {Ext.ProgressBar} this
+     */
+    updateText : function(text){
+        this.text = text || '&#160;';
+        if(this.rendered){
+            this.textEl.update(this.text);
+        }
+        return this;
+    },
+    
+    /**
+     * Synchronizes the inner bar width to the proper proportion of the total componet width based
+     * on the current progress {@link #value}.  This will be called automatically when the ProgressBar
+     * is resized by a layout, but if it is rendered auto width, this method can be called from
+     * another resize handler to sync the ProgressBar if necessary.
+     */
+    syncProgressBar : function(){
+        if(this.value){
+            this.updateProgress(this.value, this.text);
+        }
+        return this;
+    },
+
+    /**
+     * Sets the size of the progress bar.
+     * @param {Number} width The new width in pixels
+     * @param {Number} height The new height in pixels
+     * @return {Ext.ProgressBar} this
+     */
+    setSize : function(w, h){
+        Ext.ProgressBar.superclass.setSize.call(this, w, h);
+        if(this.textTopEl){
+            var inner = this.el.dom.firstChild;
+            this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
+        }
+        this.syncProgressBar();
+        return this;
+    },
+
+    /**
+     * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress
+     * bar will also be hidden (using the {@link #hideMode} property internally).
+     * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
+     * @return {Ext.ProgressBar} this
+     */
+    reset : function(hide){
+        this.updateProgress(0);
+        if(this.textTopEl){
+            this.textTopEl.addClass('x-hidden');
+        }
+        this.clearTimer();
+        if(hide === true){
+            this.hide();
+        }
+        return this;
+    },
+    
+    // private
+    clearTimer : function(){
+        if(this.waitTimer){
+            this.waitTimer.onStop = null; //prevent recursion
+            Ext.TaskMgr.stop(this.waitTimer);
+            this.waitTimer = null;
+        }
+    },
+    
+    onDestroy: function(){
+        this.clearTimer();
+        if(this.rendered){
+            if(this.textEl.isComposite){
+                this.textEl.clear();
+            }
+            Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
+        }
+        Ext.ProgressBar.superclass.onDestroy.call(this);
+    }
+});
 Ext.reg('progress', Ext.ProgressBar);
\ No newline at end of file