cmp-foundation-debug.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:422k
源码类别:

中间件编程

开发平台:

JavaScript

  1.         if(!this.disabled){
  2.             var delta = e.getWheelDelta();
  3.             if(delta > 0){
  4.                 this.showPrevMonth();
  5.             } else if(delta < 0){
  6.                 this.showNextMonth();
  7.             }
  8.         }
  9.     },
  10.     // private
  11.     handleDateClick : function(e, t){
  12.         e.stopEvent();
  13.         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
  14.             this.setValue(new Date(t.dateValue));
  15.             this.fireEvent('select', this, this.value);
  16.         }
  17.     },
  18.     // private
  19.     selectToday : function(){
  20.         if(this.todayBtn && !this.todayBtn.disabled){
  21.             this.setValue(new Date().clearTime());
  22.             this.fireEvent('select', this, this.value);
  23.         }
  24.     },
  25.     // private
  26.     update : function(date, forceRefresh){
  27.         var vd = this.activeDate, vis = this.isVisible();
  28.         this.activeDate = date;
  29.         if(!forceRefresh && vd && this.el){
  30.             var t = date.getTime();
  31.             if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
  32.                 this.cells.removeClass('x-date-selected');
  33.                 this.cells.each(function(c){
  34.                    if(c.dom.firstChild.dateValue == t){
  35.                        c.addClass('x-date-selected');
  36.                        if(vis){
  37.                            Ext.fly(c.dom.firstChild).focus(50);
  38.                        }
  39.                        return false;
  40.                    }
  41.                 });
  42.                 return;
  43.             }
  44.         }
  45.         var days = date.getDaysInMonth();
  46.         var firstOfMonth = date.getFirstDateOfMonth();
  47.         var startingPos = firstOfMonth.getDay()-this.startDay;
  48.         if(startingPos <= this.startDay){
  49.             startingPos += 7;
  50.         }
  51.         var pm = date.add('mo', -1);
  52.         var prevStart = pm.getDaysInMonth()-startingPos;
  53.         var cells = this.cells.elements;
  54.         var textEls = this.textNodes;
  55.         days += startingPos;
  56.         // convert everything to numbers so it's fast
  57.         var day = 86400000;
  58.         var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
  59.         var today = new Date().clearTime().getTime();
  60.         var sel = date.clearTime().getTime();
  61.         var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
  62.         var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
  63.         var ddMatch = this.disabledDatesRE;
  64.         var ddText = this.disabledDatesText;
  65.         var ddays = this.disabledDays ? this.disabledDays.join('') : false;
  66.         var ddaysText = this.disabledDaysText;
  67.         var format = this.format;
  68.         if(this.showToday){
  69.             var td = new Date().clearTime();
  70.             var disable = (td < min || td > max ||
  71.                 (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
  72.                 (ddays && ddays.indexOf(td.getDay()) != -1));
  73.             if(!this.disabled){
  74.                 this.todayBtn.setDisabled(disable);
  75.                 this.todayKeyListener[disable ? 'disable' : 'enable']();
  76.             }
  77.         }
  78.         var setCellClass = function(cal, cell){
  79.             cell.title = '';
  80.             var t = d.getTime();
  81.             cell.firstChild.dateValue = t;
  82.             if(t == today){
  83.                 cell.className += ' x-date-today';
  84.                 cell.title = cal.todayText;
  85.             }
  86.             if(t == sel){
  87.                 cell.className += ' x-date-selected';
  88.                 if(vis){
  89.                     Ext.fly(cell.firstChild).focus(50);
  90.                 }
  91.             }
  92.             // disabling
  93.             if(t < min) {
  94.                 cell.className = ' x-date-disabled';
  95.                 cell.title = cal.minText;
  96.                 return;
  97.             }
  98.             if(t > max) {
  99.                 cell.className = ' x-date-disabled';
  100.                 cell.title = cal.maxText;
  101.                 return;
  102.             }
  103.             if(ddays){
  104.                 if(ddays.indexOf(d.getDay()) != -1){
  105.                     cell.title = ddaysText;
  106.                     cell.className = ' x-date-disabled';
  107.                 }
  108.             }
  109.             if(ddMatch && format){
  110.                 var fvalue = d.dateFormat(format);
  111.                 if(ddMatch.test(fvalue)){
  112.                     cell.title = ddText.replace('%0', fvalue);
  113.                     cell.className = ' x-date-disabled';
  114.                 }
  115.             }
  116.         };
  117.         var i = 0;
  118.         for(; i < startingPos; i++) {
  119.             textEls[i].innerHTML = (++prevStart);
  120.             d.setDate(d.getDate()+1);
  121.             cells[i].className = 'x-date-prevday';
  122.             setCellClass(this, cells[i]);
  123.         }
  124.         for(; i < days; i++){
  125.             var intDay = i - startingPos + 1;
  126.             textEls[i].innerHTML = (intDay);
  127.             d.setDate(d.getDate()+1);
  128.             cells[i].className = 'x-date-active';
  129.             setCellClass(this, cells[i]);
  130.         }
  131.         var extraDays = 0;
  132.         for(; i < 42; i++) {
  133.              textEls[i].innerHTML = (++extraDays);
  134.              d.setDate(d.getDate()+1);
  135.              cells[i].className = 'x-date-nextday';
  136.              setCellClass(this, cells[i]);
  137.         }
  138.         this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
  139.         if(!this.internalRender){
  140.             var main = this.el.dom.firstChild;
  141.             var w = main.offsetWidth;
  142.             this.el.setWidth(w + this.el.getBorderWidth('lr'));
  143.             Ext.fly(main).setWidth(w);
  144.             this.internalRender = true;
  145.             // opera does not respect the auto grow header center column
  146.             // then, after it gets a width opera refuses to recalculate
  147.             // without a second pass
  148.             if(Ext.isOpera && !this.secondPass){
  149.                 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
  150.                 this.secondPass = true;
  151.                 this.update.defer(10, this, [date]);
  152.             }
  153.         }
  154.     },
  155.     // private
  156.     beforeDestroy : function() {
  157.         if(this.rendered){
  158.             this.keyNav.disable();
  159.             this.keyNav = null;
  160.             Ext.destroy(
  161.                 this.leftClickRpt,
  162.                 this.rightClickRpt,
  163.                 this.monthPicker,
  164.                 this.eventEl,
  165.                 this.mbtn,
  166.                 this.todayBtn
  167.             );
  168.         }
  169.     }
  170.     /**
  171.      * @cfg {String} autoEl @hide
  172.      */
  173. });
  174. Ext.reg('datepicker', Ext.DatePicker);
  175. /**  * @class Ext.LoadMask  * A simple utility class for generically masking elements while loading data.  If the {@link #store}  * config option is specified, the masking will be automatically synchronized with the store's loading  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the  * element's Updater load indicator and will be destroyed after the initial load.  * <p>Example usage:</p>  *<pre><code> // Basic mask: var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."}); myMask.show(); </code></pre>  * @constructor  * Create a new LoadMask  * @param {Mixed} el The element or DOM node, or its id  * @param {Object} config The config object  */ Ext.LoadMask = function(el, config){     this.el = Ext.get(el);     Ext.apply(this, config);     if(this.store){         this.store.on('beforeload', this.onBeforeLoad, this);         this.store.on('load', this.onLoad, this);         this.store.on('exception', this.onLoad, this);         this.removeMask = Ext.value(this.removeMask, false);     }else{         var um = this.el.getUpdater();         um.showLoadIndicator = false; // disable the default indicator         um.on('beforeupdate', this.onBeforeLoad, this);         um.on('update', this.onLoad, this);         um.on('failure', this.onLoad, this);         this.removeMask = Ext.value(this.removeMask, true);     } }; Ext.LoadMask.prototype = {     /**      * @cfg {Ext.data.Store} store      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and      * hidden on either load sucess, or load fail.      */     /**      * @cfg {Boolean} removeMask      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.      */     /**      * @cfg {String} msg      * The text to display in a centered loading message box (defaults to 'Loading...')      */     msg : 'Loading...',     /**      * @cfg {String} msgCls      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")      */     msgCls : 'x-mask-loading',     /**      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)      * @type Boolean      */     disabled: false,     /**      * Disables the mask to prevent it from being displayed      */     disable : function(){        this.disabled = true;     },     /**      * Enables the mask so that it can be displayed      */     enable : function(){         this.disabled = false;     },     // private     onLoad : function(){         this.el.unmask(this.removeMask);     },     // private     onBeforeLoad : function(){         if(!this.disabled){             this.el.mask(this.msg, this.msgCls);         }     },     /**      * Show this LoadMask over the configured Element.      */     show: function(){         this.onBeforeLoad();     },     /**      * Hide this LoadMask.      */     hide: function(){         this.onLoad();     },     // private     destroy : function(){         if(this.store){             this.store.un('beforeload', this.onBeforeLoad, this);             this.store.un('load', this.onLoad, this);             this.store.un('exception', this.onLoad, this);         }else{             var um = this.el.getUpdater();             um.un('beforeupdate', this.onBeforeLoad, this);             um.un('update', this.onLoad, this);             um.un('failure', this.onLoad, this);         }     } };/**
  176.  * @class Ext.Slider
  177.  * @extends Ext.BoxComponent
  178.  * Slider which supports vertical or horizontal orientation, keyboard adjustments,
  179.  * configurable snapping, axis clicking and animation. Can be added as an item to
  180.  * any container. Example usage:
  181. <pre><code>
  182. new Ext.Slider({
  183.     renderTo: Ext.getBody(),
  184.     width: 200,
  185.     value: 50,
  186.     increment: 10,
  187.     minValue: 0,
  188.     maxValue: 100
  189. });
  190. </code></pre>
  191.  */
  192. Ext.Slider = Ext.extend(Ext.BoxComponent, {
  193. /**
  194.  * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
  195.  */
  196. /**
  197.  * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
  198.  */
  199.     vertical: false,
  200. /**
  201.  * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
  202.  */
  203.     minValue: 0,
  204. /**
  205.  * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
  206.  */
  207.     maxValue: 100,
  208.     /**
  209.      * @cfg {Number/Boolean} decimalPrecision.
  210.      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
  211.      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
  212.      */
  213.     decimalPrecision: 0,
  214. /**
  215.  * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.
  216.  */
  217.     keyIncrement: 1,
  218. /**
  219.  * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
  220.  */
  221.     increment: 0,
  222. // private
  223.     clickRange: [5,15],
  224. /**
  225.  * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
  226.  */
  227.     clickToChange : true,
  228. /**
  229.  * @cfg {Boolean} animate Turn on or off animation. Defaults to true
  230.  */
  231.     animate: true,
  232.     /**
  233.      * True while the thumb is in a drag operation
  234.      * @type boolean
  235.      */
  236.     dragging: false,
  237.     // private override
  238.     initComponent : function(){
  239.         if(!Ext.isDefined(this.value)){
  240.             this.value = this.minValue;
  241.         }
  242.         Ext.Slider.superclass.initComponent.call(this);
  243.         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
  244.         this.addEvents(
  245.             /**
  246.              * @event beforechange
  247.              * Fires before the slider value is changed. By returning false from an event handler,
  248.              * you can cancel the event and prevent the slider from changing.
  249.  * @param {Ext.Slider} slider The slider
  250.  * @param {Number} newValue The new value which the slider is being changed to.
  251.  * @param {Number} oldValue The old value which the slider was previously.
  252.              */
  253. 'beforechange',
  254. /**
  255.  * @event change
  256.  * Fires when the slider value is changed.
  257.  * @param {Ext.Slider} slider The slider
  258.  * @param {Number} newValue The new value which the slider has been changed to.
  259.  */
  260. 'change',
  261. /**
  262.  * @event changecomplete
  263.  * Fires when the slider value is changed by the user and any drag operations have completed.
  264.  * @param {Ext.Slider} slider The slider
  265.  * @param {Number} newValue The new value which the slider has been changed to.
  266.  */
  267. 'changecomplete',
  268. /**
  269.  * @event dragstart
  270.              * Fires after a drag operation has started.
  271.  * @param {Ext.Slider} slider The slider
  272.  * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  273.  */
  274. 'dragstart',
  275. /**
  276.  * @event drag
  277.              * Fires continuously during the drag operation while the mouse is moving.
  278.  * @param {Ext.Slider} slider The slider
  279.  * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  280.  */
  281. 'drag',
  282. /**
  283.  * @event dragend
  284.              * Fires after the drag operation has completed.
  285.  * @param {Ext.Slider} slider The slider
  286.  * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  287.  */
  288. 'dragend'
  289. );
  290.         if(this.vertical){
  291.             Ext.apply(this, Ext.Slider.Vertical);
  292.         }
  293.     },
  294. // private override
  295.     onRender : function(){
  296.         this.autoEl = {
  297.             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
  298.             cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}
  299.         };
  300.         Ext.Slider.superclass.onRender.apply(this, arguments);
  301.         this.endEl = this.el.first();
  302.         this.innerEl = this.endEl.first();
  303.         this.thumb = this.innerEl.first();
  304.         this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;
  305.         this.focusEl = this.thumb.next();
  306.         this.initEvents();
  307.     },
  308. // private override
  309.     initEvents : function(){
  310.         this.thumb.addClassOnOver('x-slider-thumb-over');
  311.         this.mon(this.el, {
  312.             scope: this,
  313.             mousedown: this.onMouseDown,
  314.             keydown: this.onKeyDown
  315.         });
  316.         this.focusEl.swallowEvent("click", true);
  317.         this.tracker = new Ext.dd.DragTracker({
  318.             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
  319.             onStart: this.onDragStart.createDelegate(this),
  320.             onDrag: this.onDrag.createDelegate(this),
  321.             onEnd: this.onDragEnd.createDelegate(this),
  322.             tolerance: 3,
  323.             autoStart: 300
  324.         });
  325.         this.tracker.initEl(this.thumb);
  326.         this.on('beforedestroy', this.tracker.destroy, this.tracker);
  327.     },
  328. // private override
  329.     onMouseDown : function(e){
  330.         if(this.disabled) {return;}
  331.         if(this.clickToChange && e.target != this.thumb.dom){
  332.             var local = this.innerEl.translatePoints(e.getXY());
  333.             this.onClickChange(local);
  334.         }
  335.         this.focus();
  336.     },
  337. // private
  338.     onClickChange : function(local){
  339.         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){
  340.             this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
  341.         }
  342.     },
  343. // private
  344.     onKeyDown : function(e){
  345.         if(this.disabled){e.preventDefault();return;}
  346.         var k = e.getKey();
  347.         switch(k){
  348.             case e.UP:
  349.             case e.RIGHT:
  350.                 e.stopEvent();
  351.                 if(e.ctrlKey){
  352.                     this.setValue(this.maxValue, undefined, true);
  353.                 }else{
  354.                     this.setValue(this.value+this.keyIncrement, undefined, true);
  355.                 }
  356.             break;
  357.             case e.DOWN:
  358.             case e.LEFT:
  359.                 e.stopEvent();
  360.                 if(e.ctrlKey){
  361.                     this.setValue(this.minValue, undefined, true);
  362.                 }else{
  363.                     this.setValue(this.value-this.keyIncrement, undefined, true);
  364.                 }
  365.             break;
  366.             default:
  367.                 e.preventDefault();
  368.         }
  369.     },
  370. // private
  371.     doSnap : function(value){
  372.         if(!this.increment || this.increment == 1 || !value) {
  373.             return value;
  374.         }
  375.         var newValue = value, inc = this.increment;
  376.         var m = value % inc;
  377.         if(m != 0){
  378.             newValue -= m;
  379.             if(m * 2 > inc){
  380.                 newValue += inc;
  381.             }else if(m * 2 < -inc){
  382.                 newValue -= inc;
  383.             }
  384.         }
  385.         return newValue.constrain(this.minValue,  this.maxValue);
  386.     },
  387. // private
  388.     afterRender : function(){
  389.         Ext.Slider.superclass.afterRender.apply(this, arguments);
  390.         if(this.value !== undefined){
  391.             var v = this.normalizeValue(this.value);
  392.             if(v !== this.value){
  393.                 delete this.value;
  394.                 this.setValue(v, false);
  395.             }else{
  396.                 this.moveThumb(this.translateValue(v), false);
  397.             }
  398.         }
  399.     },
  400. // private
  401.     getRatio : function(){
  402.         var w = this.innerEl.getWidth();
  403.         var v = this.maxValue - this.minValue;
  404.         return v == 0 ? w : (w/v);
  405.     },
  406. // private
  407.     normalizeValue : function(v){
  408.         v = this.doSnap(v);
  409.         v = Ext.util.Format.round(v, this.decimalPrecision);
  410.         v = v.constrain(this.minValue, this.maxValue);
  411.         return v;
  412.     },
  413. /**
  414.  * Programmatically sets the value of the Slider. Ensures that the value is constrained within
  415.  * the minValue and maxValue.
  416.  * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
  417.  * @param {Boolean} animate Turn on or off animation, defaults to true
  418.  */
  419.     setValue : function(v, animate, changeComplete){
  420.         v = this.normalizeValue(v);
  421.         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){
  422.             this.value = v;
  423.             this.moveThumb(this.translateValue(v), animate !== false);
  424.             this.fireEvent('change', this, v);
  425.             if(changeComplete){
  426.                 this.fireEvent('changecomplete', this, v);
  427.             }
  428.         }
  429.     },
  430. // private
  431.     translateValue : function(v){
  432.         var ratio = this.getRatio();
  433.         return (v * ratio)-(this.minValue * ratio)-this.halfThumb;
  434.     },
  435. reverseValue : function(pos){
  436.         var ratio = this.getRatio();
  437.         return (pos+this.halfThumb+(this.minValue * ratio))/ratio;
  438.     },
  439. // private
  440.     moveThumb: function(v, animate){
  441.         if(!animate || this.animate === false){
  442.             this.thumb.setLeft(v);
  443.         }else{
  444.             this.thumb.shift({left: v, stopFx: true, duration:.35});
  445.         }
  446.     },
  447. // private
  448.     focus : function(){
  449.         this.focusEl.focus(10);
  450.     },
  451. // private
  452.     onBeforeDragStart : function(e){
  453.         return !this.disabled;
  454.     },
  455. // private
  456.     onDragStart: function(e){
  457.         this.thumb.addClass('x-slider-thumb-drag');
  458.         this.dragging = true;
  459.         this.dragStartValue = this.value;
  460.         this.fireEvent('dragstart', this, e);
  461.     },
  462. // private
  463.     onDrag: function(e){
  464.         var pos = this.innerEl.translatePoints(this.tracker.getXY());
  465.         this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);
  466.         this.fireEvent('drag', this, e);
  467.     },
  468. // private
  469.     onDragEnd: function(e){
  470.         this.thumb.removeClass('x-slider-thumb-drag');
  471.         this.dragging = false;
  472.         this.fireEvent('dragend', this, e);
  473.         if(this.dragStartValue != this.value){
  474.             this.fireEvent('changecomplete', this, this.value);
  475.         }
  476.     },
  477. // private
  478.     onResize : function(w, h){
  479.         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
  480.         this.syncThumb();
  481.     },
  482.     
  483.     //private
  484.     onDisable: function(){
  485.         Ext.Slider.superclass.onDisable.call(this);
  486.         this.thumb.addClass(this.disabledClass);
  487.         if(Ext.isIE){
  488.             //IE breaks when using overflow visible and opacity other than 1.
  489.             //Create a place holder for the thumb and display it.
  490.             var xy = this.thumb.getXY();
  491.             this.thumb.hide();
  492.             this.innerEl.addClass(this.disabledClass).dom.disabled = true;
  493.             if (!this.thumbHolder){
  494.                 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    
  495.             }
  496.             this.thumbHolder.show().setXY(xy);
  497.         }
  498.     },
  499.     
  500.     //private
  501.     onEnable: function(){
  502.         Ext.Slider.superclass.onEnable.call(this);
  503.         this.thumb.removeClass(this.disabledClass);
  504.         if(Ext.isIE){
  505.             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
  506.             if (this.thumbHolder){
  507.                 this.thumbHolder.hide();
  508.             }
  509.             this.thumb.show();
  510.             this.syncThumb();
  511.         }
  512.     },
  513.     
  514.     /**
  515.      * Synchronizes the thumb position to the proper proportion of the total component width based
  516.      * on the current slider {@link #value}.  This will be called automatically when the Slider
  517.      * is resized by a layout, but if it is rendered auto width, this method can be called from
  518.      * another resize handler to sync the Slider if necessary.
  519.      */
  520.     syncThumb : function(){
  521.         if(this.rendered){
  522.             this.moveThumb(this.translateValue(this.value));
  523.         }
  524.     },
  525. /**
  526.  * Returns the current value of the slider
  527.  * @return {Number} The current value of the slider
  528.  */
  529.     getValue : function(){
  530.         return this.value;
  531.     }
  532. });
  533. Ext.reg('slider', Ext.Slider);
  534. // private class to support vertical sliders
  535. Ext.Slider.Vertical = {
  536.     onResize : function(w, h){
  537.         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
  538.         this.syncThumb();
  539.     },
  540.     getRatio : function(){
  541.         var h = this.innerEl.getHeight();
  542.         var v = this.maxValue - this.minValue;
  543.         return h/v;
  544.     },
  545.     moveThumb: function(v, animate){
  546.         if(!animate || this.animate === false){
  547.             this.thumb.setBottom(v);
  548.         }else{
  549.             this.thumb.shift({bottom: v, stopFx: true, duration:.35});
  550.         }
  551.     },
  552.     onDrag: function(e){
  553.         var pos = this.innerEl.translatePoints(this.tracker.getXY());
  554.         var bottom = this.innerEl.getHeight()-pos.top;
  555.         this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);
  556.         this.fireEvent('drag', this, e);
  557.     },
  558.     onClickChange : function(local){
  559.         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){
  560.             var bottom = this.innerEl.getHeight()-local.top;
  561.             this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);
  562.         }
  563.     }
  564. };/**
  565.  * @class Ext.ProgressBar
  566.  * @extends Ext.BoxComponent
  567.  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>
  568.  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
  569.  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress
  570.  * throughout an operation that has predictable points of interest at which you can update the control.</p>
  571.  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
  572.  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time
  573.  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in
  574.  * which you have no need for indicating intermediate progress.</p>
  575.  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
  576.  * @cfg {String} text The progress bar text (defaults to '')
  577.  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
  578.  * bar's internal text element)
  579.  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
  580.  * @xtype progress
  581.  */
  582. Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
  583.    /**
  584.     * @cfg {String} baseCls
  585.     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
  586.     */
  587.     baseCls : 'x-progress',
  588.     
  589.     /**
  590.     * @cfg {Boolean} animate
  591.     * True to animate the progress bar during transitions (defaults to false)
  592.     */
  593.     animate : false,
  594.     // private
  595.     waitTimer : null,
  596.     // private
  597.     initComponent : function(){
  598.         Ext.ProgressBar.superclass.initComponent.call(this);
  599.         this.addEvents(
  600.             /**
  601.              * @event update
  602.              * Fires after each update interval
  603.              * @param {Ext.ProgressBar} this
  604.              * @param {Number} The current progress value
  605.              * @param {String} The current progress text
  606.              */
  607.             "update"
  608.         );
  609.     },
  610.     // private
  611.     onRender : function(ct, position){
  612.         var tpl = new Ext.Template(
  613.             '<div class="{cls}-wrap">',
  614.                 '<div class="{cls}-inner">',
  615.                     '<div class="{cls}-bar">',
  616.                         '<div class="{cls}-text">',
  617.                             '<div>&#160;</div>',
  618.                         '</div>',
  619.                     '</div>',
  620.                     '<div class="{cls}-text {cls}-text-back">',
  621.                         '<div>&#160;</div>',
  622.                     '</div>',
  623.                 '</div>',
  624.             '</div>'
  625.         );
  626.         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
  627.          : tpl.append(ct, {cls: this.baseCls}, true);
  628.         
  629.         if(this.id){
  630.             this.el.dom.id = this.id;
  631.         }
  632.         var inner = this.el.dom.firstChild;
  633.         this.progressBar = Ext.get(inner.firstChild);
  634.         if(this.textEl){
  635.             //use an external text el
  636.             this.textEl = Ext.get(this.textEl);
  637.             delete this.textTopEl;
  638.         }else{
  639.             //setup our internal layered text els
  640.             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
  641.             var textBackEl = Ext.get(inner.childNodes[1]);
  642.             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
  643.             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
  644.             this.textEl.setWidth(inner.offsetWidth);
  645.         }
  646.         this.progressBar.setHeight(inner.offsetHeight);
  647.     },
  648.     
  649.     // private
  650.     afterRender : function(){
  651.         Ext.ProgressBar.superclass.afterRender.call(this);
  652.         if(this.value){
  653.             this.updateProgress(this.value, this.text);
  654.         }else{
  655.             this.updateText(this.text);
  656.         }
  657.     },
  658.     /**
  659.      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,
  660.      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even
  661.      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
  662.      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
  663.      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
  664.      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
  665.      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
  666.      * not specified, the default for the class is used (default to false)
  667.      * @return {Ext.ProgressBar} this
  668.      */
  669.     updateProgress : function(value, text, animate){
  670.         this.value = value || 0;
  671.         if(text){
  672.             this.updateText(text);
  673.         }
  674.         if(this.rendered){
  675.             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
  676.             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
  677.             if(this.textTopEl){
  678.                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves
  679.                 this.textTopEl.removeClass('x-hidden').setWidth(w);
  680.             }
  681.         }
  682.         this.fireEvent('update', this, value, text);
  683.         return this;
  684.     },
  685.     /**
  686.      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress
  687.      * bar will automatically reset after a fixed amount of time and optionally call a callback function
  688.      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must
  689.      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with
  690.      * the following properties:
  691.      * <pre>
  692. Property   Type          Description
  693. ---------- ------------  ----------------------------------------------------------------------
  694. duration   Number        The length of time in milliseconds that the progress bar should
  695.                          run before resetting itself (defaults to undefined, in which case it
  696.                          will run indefinitely until reset is called)
  697. interval   Number        The length of time in milliseconds between each progress update
  698.                          (defaults to 1000 ms)
  699. animate    Boolean       Whether to animate the transition of the progress bar. If this value is
  700.                          not specified, the default for the class is used.                                                   
  701. increment  Number        The number of progress update segments to display within the progress
  702.                          bar (defaults to 10).  If the bar reaches the end and is still
  703.                          updating, it will automatically wrap back to the beginning.
  704. text       String        Optional text to display in the progress bar element (defaults to '').
  705. fn         Function      A callback function to execute after the progress bar finishes auto-
  706.                          updating.  The function will be called with no arguments.  This function
  707.                          will be ignored if duration is not specified since in that case the
  708.                          progress bar can only be stopped programmatically, so any required function
  709.                          should be called by the same code after it resets the progress bar.
  710. scope      Object        The scope that is passed to the callback function (only applies when
  711.                          duration and fn are both passed).
  712. </pre>
  713.          *
  714.          * Example usage:
  715.          * <pre><code>
  716. var p = new Ext.ProgressBar({
  717.    renderTo: 'my-el'
  718. });
  719. //Wait for 5 seconds, then update the status el (progress bar will auto-reset)
  720. p.wait({
  721.    interval: 100, //bar will move fast!
  722.    duration: 5000,
  723.    increment: 15,
  724.    text: 'Updating...',
  725.    scope: this,
  726.    fn: function(){
  727.       Ext.fly('status').update('Done!');
  728.    }
  729. });
  730. //Or update indefinitely until some async action completes, then reset manually
  731. p.wait();
  732. myAction.on('complete', function(){
  733.     p.reset();
  734.     Ext.fly('status').update('Done!');
  735. });
  736. </code></pre>
  737.      * @param {Object} config (optional) Configuration options
  738.      * @return {Ext.ProgressBar} this
  739.      */
  740.     wait : function(o){
  741.         if(!this.waitTimer){
  742.             var scope = this;
  743.             o = o || {};
  744.             this.updateText(o.text);
  745.             this.waitTimer = Ext.TaskMgr.start({
  746.                 run: function(i){
  747.                     var inc = o.increment || 10;
  748.                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
  749.                 },
  750.                 interval: o.interval || 1000,
  751.                 duration: o.duration,
  752.                 onStop: function(){
  753.                     if(o.fn){
  754.                         o.fn.apply(o.scope || this);
  755.                     }
  756.                     this.reset();
  757.                 },
  758.                 scope: scope
  759.             });
  760.         }
  761.         return this;
  762.     },
  763.     /**
  764.      * Returns true if the progress bar is currently in a {@link #wait} operation
  765.      * @return {Boolean} True if waiting, else false
  766.      */
  767.     isWaiting : function(){
  768.         return this.waitTimer !== null;
  769.     },
  770.     /**
  771.      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress
  772.      * bar itself will display the updated text.
  773.      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
  774.      * @return {Ext.ProgressBar} this
  775.      */
  776.     updateText : function(text){
  777.         this.text = text || '&#160;';
  778.         if(this.rendered){
  779.             this.textEl.update(this.text);
  780.         }
  781.         return this;
  782.     },
  783.     
  784.     /**
  785.      * Synchronizes the inner bar width to the proper proportion of the total componet width based
  786.      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar
  787.      * is resized by a layout, but if it is rendered auto width, this method can be called from
  788.      * another resize handler to sync the ProgressBar if necessary.
  789.      */
  790.     syncProgressBar : function(){
  791.         if(this.value){
  792.             this.updateProgress(this.value, this.text);
  793.         }
  794.         return this;
  795.     },
  796.     /**
  797.      * Sets the size of the progress bar.
  798.      * @param {Number} width The new width in pixels
  799.      * @param {Number} height The new height in pixels
  800.      * @return {Ext.ProgressBar} this
  801.      */
  802.     setSize : function(w, h){
  803.         Ext.ProgressBar.superclass.setSize.call(this, w, h);
  804.         if(this.textTopEl){
  805.             var inner = this.el.dom.firstChild;
  806.             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
  807.         }
  808.         this.syncProgressBar();
  809.         return this;
  810.     },
  811.     /**
  812.      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress
  813.      * bar will also be hidden (using the {@link #hideMode} property internally).
  814.      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
  815.      * @return {Ext.ProgressBar} this
  816.      */
  817.     reset : function(hide){
  818.         this.updateProgress(0);
  819.         if(this.textTopEl){
  820.             this.textTopEl.addClass('x-hidden');
  821.         }
  822.         if(this.waitTimer){
  823.             this.waitTimer.onStop = null; //prevent recursion
  824.             Ext.TaskMgr.stop(this.waitTimer);
  825.             this.waitTimer = null;
  826.         }
  827.         if(hide === true){
  828.             this.hide();
  829.         }
  830.         return this;
  831.     }
  832. });
  833. Ext.reg('progress', Ext.ProgressBar);