ProgressBar.js 11 KB

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