Slider.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:14k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.1.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**
  2.  * @class Ext.Slider
  3.  * @extends Ext.BoxComponent
  4.  * Slider which supports vertical or horizontal orientation, keyboard adjustments,
  5.  * configurable snapping, axis clicking and animation. Can be added as an item to
  6.  * any container. Example usage:
  7. <pre><code>
  8. new Ext.Slider({
  9.     renderTo: Ext.getBody(),
  10.     width: 200,
  11.     value: 50,
  12.     increment: 10,
  13.     minValue: 0,
  14.     maxValue: 100
  15. });
  16. </code></pre>
  17.  */
  18. Ext.Slider = Ext.extend(Ext.BoxComponent, {
  19. /**
  20.  * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
  21.  */
  22. /**
  23.  * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
  24.  */
  25.     vertical: false,
  26. /**
  27.  * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
  28.  */
  29.     minValue: 0,
  30. /**
  31.  * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
  32.  */
  33.     maxValue: 100,
  34.     /**
  35.      * @cfg {Number/Boolean} decimalPrecision.
  36.      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
  37.      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
  38.      */
  39.     decimalPrecision: 0,
  40. /**
  41.  * @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.
  42.  */
  43.     keyIncrement: 1,
  44. /**
  45.  * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
  46.  */
  47.     increment: 0,
  48. // private
  49.     clickRange: [5,15],
  50. /**
  51.  * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
  52.  */
  53.     clickToChange : true,
  54. /**
  55.  * @cfg {Boolean} animate Turn on or off animation. Defaults to true
  56.  */
  57.     animate: true,
  58.     /**
  59.      * True while the thumb is in a drag operation
  60.      * @type boolean
  61.      */
  62.     dragging: false,
  63.     // private override
  64.     initComponent : function(){
  65.         if(!Ext.isDefined(this.value)){
  66.             this.value = this.minValue;
  67.         }
  68.         Ext.Slider.superclass.initComponent.call(this);
  69.         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
  70.         this.addEvents(
  71.             /**
  72.              * @event beforechange
  73.              * Fires before the slider value is changed. By returning false from an event handler,
  74.              * you can cancel the event and prevent the slider from changing.
  75.  * @param {Ext.Slider} slider The slider
  76.  * @param {Number} newValue The new value which the slider is being changed to.
  77.  * @param {Number} oldValue The old value which the slider was previously.
  78.              */
  79. 'beforechange',
  80. /**
  81.  * @event change
  82.  * Fires when the slider value is changed.
  83.  * @param {Ext.Slider} slider The slider
  84.  * @param {Number} newValue The new value which the slider has been changed to.
  85.  */
  86. 'change',
  87. /**
  88.  * @event changecomplete
  89.  * Fires when the slider value is changed by the user and any drag operations have completed.
  90.  * @param {Ext.Slider} slider The slider
  91.  * @param {Number} newValue The new value which the slider has been changed to.
  92.  */
  93. 'changecomplete',
  94. /**
  95.  * @event dragstart
  96.              * Fires after a drag operation has started.
  97.  * @param {Ext.Slider} slider The slider
  98.  * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  99.  */
  100. 'dragstart',
  101. /**
  102.  * @event drag
  103.              * Fires continuously during the drag operation while the mouse is moving.
  104.  * @param {Ext.Slider} slider The slider
  105.  * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  106.  */
  107. 'drag',
  108. /**
  109.  * @event dragend
  110.              * Fires after the drag operation has completed.
  111.  * @param {Ext.Slider} slider The slider
  112.  * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  113.  */
  114. 'dragend'
  115. );
  116.         if(this.vertical){
  117.             Ext.apply(this, Ext.Slider.Vertical);
  118.         }
  119.     },
  120. // private override
  121.     onRender : function(){
  122.         this.autoEl = {
  123.             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
  124.             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'}]}}
  125.         };
  126.         Ext.Slider.superclass.onRender.apply(this, arguments);
  127.         this.endEl = this.el.first();
  128.         this.innerEl = this.endEl.first();
  129.         this.thumb = this.innerEl.first();
  130.         this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;
  131.         this.focusEl = this.thumb.next();
  132.         this.initEvents();
  133.     },
  134. // private override
  135.     initEvents : function(){
  136.         this.thumb.addClassOnOver('x-slider-thumb-over');
  137.         this.mon(this.el, {
  138.             scope: this,
  139.             mousedown: this.onMouseDown,
  140.             keydown: this.onKeyDown
  141.         });
  142.         this.focusEl.swallowEvent("click", true);
  143.         this.tracker = new Ext.dd.DragTracker({
  144.             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
  145.             onStart: this.onDragStart.createDelegate(this),
  146.             onDrag: this.onDrag.createDelegate(this),
  147.             onEnd: this.onDragEnd.createDelegate(this),
  148.             tolerance: 3,
  149.             autoStart: 300
  150.         });
  151.         this.tracker.initEl(this.thumb);
  152.     },
  153. // private override
  154.     onMouseDown : function(e){
  155.         if(this.disabled){
  156.             return;
  157.         }
  158.         if(this.clickToChange && e.target != this.thumb.dom){
  159.             var local = this.innerEl.translatePoints(e.getXY());
  160.             this.onClickChange(local);
  161.         }
  162.         this.focus();
  163.     },
  164. // private
  165.     onClickChange : function(local){
  166.         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){
  167.             this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
  168.         }
  169.     },
  170. // private
  171.     onKeyDown : function(e){
  172.         if(this.disabled){e.preventDefault();return;}
  173.         var k = e.getKey();
  174.         switch(k){
  175.             case e.UP:
  176.             case e.RIGHT:
  177.                 e.stopEvent();
  178.                 if(e.ctrlKey){
  179.                     this.setValue(this.maxValue, undefined, true);
  180.                 }else{
  181.                     this.setValue(this.value+this.keyIncrement, undefined, true);
  182.                 }
  183.             break;
  184.             case e.DOWN:
  185.             case e.LEFT:
  186.                 e.stopEvent();
  187.                 if(e.ctrlKey){
  188.                     this.setValue(this.minValue, undefined, true);
  189.                 }else{
  190.                     this.setValue(this.value-this.keyIncrement, undefined, true);
  191.                 }
  192.             break;
  193.             default:
  194.                 e.preventDefault();
  195.         }
  196.     },
  197. // private
  198.     doSnap : function(value){
  199.         if(!(this.increment && value)){
  200.             return value;
  201.         }
  202.         var newValue = value, 
  203.             inc = this.increment,
  204.             m = value % inc;
  205.         if(m != 0){
  206.             newValue -= m;
  207.             if(m * 2 > inc){
  208.                 newValue += inc;
  209.             }else if(m * 2 < -inc){
  210.                 newValue -= inc;
  211.             }
  212.         }
  213.         return newValue.constrain(this.minValue,  this.maxValue);
  214.     },
  215. // private
  216.     afterRender : function(){
  217.         Ext.Slider.superclass.afterRender.apply(this, arguments);
  218.         if(this.value !== undefined){
  219.             var v = this.normalizeValue(this.value);
  220.             if(v !== this.value){
  221.                 delete this.value;
  222.                 this.setValue(v, false);
  223.             }else{
  224.                 this.moveThumb(this.translateValue(v), false);
  225.             }
  226.         }
  227.     },
  228. // private
  229.     getRatio : function(){
  230.         var w = this.innerEl.getWidth(),
  231.             v = this.maxValue - this.minValue;
  232.         return v == 0 ? w : (w/v);
  233.     },
  234. // private
  235.     normalizeValue : function(v){
  236.         v = this.doSnap(v);
  237.         v = Ext.util.Format.round(v, this.decimalPrecision);
  238.         v = v.constrain(this.minValue, this.maxValue);
  239.         return v;
  240.     },
  241. /**
  242.  * Programmatically sets the value of the Slider. Ensures that the value is constrained within
  243.  * the minValue and maxValue.
  244.  * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
  245.  * @param {Boolean} animate Turn on or off animation, defaults to true
  246.  */
  247.     setValue : function(v, animate, changeComplete){
  248.         v = this.normalizeValue(v);
  249.         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){
  250.             this.value = v;
  251.             this.moveThumb(this.translateValue(v), animate !== false);
  252.             this.fireEvent('change', this, v);
  253.             if(changeComplete){
  254.                 this.fireEvent('changecomplete', this, v);
  255.             }
  256.         }
  257.     },
  258. // private
  259.     translateValue : function(v){
  260.         var ratio = this.getRatio();
  261.         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
  262.     },
  263. reverseValue : function(pos){
  264.         var ratio = this.getRatio();
  265.         return (pos + this.halfThumb + (this.minValue * ratio)) / ratio;
  266.     },
  267. // private
  268.     moveThumb: function(v, animate){
  269.         if(!animate || this.animate === false){
  270.             this.thumb.setLeft(v);
  271.         }else{
  272.             this.thumb.shift({left: v, stopFx: true, duration:.35});
  273.         }
  274.     },
  275. // private
  276.     focus : function(){
  277.         this.focusEl.focus(10);
  278.     },
  279. // private
  280.     onBeforeDragStart : function(e){
  281.         return !this.disabled;
  282.     },
  283. // private
  284.     onDragStart: function(e){
  285.         this.thumb.addClass('x-slider-thumb-drag');
  286.         this.dragging = true;
  287.         this.dragStartValue = this.value;
  288.         this.fireEvent('dragstart', this, e);
  289.     },
  290. // private
  291.     onDrag: function(e){
  292.         var pos = this.innerEl.translatePoints(this.tracker.getXY());
  293.         this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);
  294.         this.fireEvent('drag', this, e);
  295.     },
  296. // private
  297.     onDragEnd: function(e){
  298.         this.thumb.removeClass('x-slider-thumb-drag');
  299.         this.dragging = false;
  300.         this.fireEvent('dragend', this, e);
  301.         if(this.dragStartValue != this.value){
  302.             this.fireEvent('changecomplete', this, this.value);
  303.         }
  304.     },
  305. // private
  306.     onResize : function(w, h){
  307.         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
  308.         this.syncThumb();
  309.     },
  310.     
  311.     //private
  312.     onDisable: function(){
  313.         Ext.Slider.superclass.onDisable.call(this);
  314.         this.thumb.addClass(this.disabledClass);
  315.         if(Ext.isIE){
  316.             //IE breaks when using overflow visible and opacity other than 1.
  317.             //Create a place holder for the thumb and display it.
  318.             var xy = this.thumb.getXY();
  319.             this.thumb.hide();
  320.             this.innerEl.addClass(this.disabledClass).dom.disabled = true;
  321.             if (!this.thumbHolder){
  322.                 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    
  323.             }
  324.             this.thumbHolder.show().setXY(xy);
  325.         }
  326.     },
  327.     
  328.     //private
  329.     onEnable: function(){
  330.         Ext.Slider.superclass.onEnable.call(this);
  331.         this.thumb.removeClass(this.disabledClass);
  332.         if(Ext.isIE){
  333.             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
  334.             if(this.thumbHolder){
  335.                 this.thumbHolder.hide();
  336.             }
  337.             this.thumb.show();
  338.             this.syncThumb();
  339.         }
  340.     },
  341.     
  342.     /**
  343.      * Synchronizes the thumb position to the proper proportion of the total component width based
  344.      * on the current slider {@link #value}.  This will be called automatically when the Slider
  345.      * is resized by a layout, but if it is rendered auto width, this method can be called from
  346.      * another resize handler to sync the Slider if necessary.
  347.      */
  348.     syncThumb : function(){
  349.         if(this.rendered){
  350.             this.moveThumb(this.translateValue(this.value));
  351.         }
  352.     },
  353. /**
  354.  * Returns the current value of the slider
  355.  * @return {Number} The current value of the slider
  356.  */
  357.     getValue : function(){
  358.         return this.value;
  359.     },
  360.     
  361.     // private
  362.     beforeDestroy : function(){
  363.         Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');
  364.         Ext.Slider.superclass.beforeDestroy.call(this);
  365.     }
  366. });
  367. Ext.reg('slider', Ext.Slider);
  368. // private class to support vertical sliders
  369. Ext.Slider.Vertical = {
  370.     onResize : function(w, h){
  371.         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
  372.         this.syncThumb();
  373.     },
  374.     getRatio : function(){
  375.         var h = this.innerEl.getHeight(),
  376.             v = this.maxValue - this.minValue;
  377.         return h/v;
  378.     },
  379.     moveThumb: function(v, animate){
  380.         if(!animate || this.animate === false){
  381.             this.thumb.setBottom(v);
  382.         }else{
  383.             this.thumb.shift({bottom: v, stopFx: true, duration:.35});
  384.         }
  385.     },
  386.     onDrag: function(e){
  387.         var pos = this.innerEl.translatePoints(this.tracker.getXY()),
  388.             bottom = this.innerEl.getHeight()-pos.top;
  389.         this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);
  390.         this.fireEvent('drag', this, e);
  391.     },
  392.     onClickChange : function(local){
  393.         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){
  394.             var bottom = this.innerEl.getHeight() - local.top;
  395.             this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);
  396.         }
  397.     }
  398. };