Multi.html 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-slider-Multi'>/**
  19. </span> * Slider which supports vertical or horizontal orientation, keyboard adjustments, configurable snapping, axis clicking
  20. * and animation. Can be added as an item to any container.
  21. *
  22. * Sliders can be created with more than one thumb handle by passing an array of values instead of a single one:
  23. *
  24. * @example
  25. * Ext.create('Ext.slider.Multi', {
  26. * width: 200,
  27. * values: [25, 50, 75],
  28. * increment: 5,
  29. * minValue: 0,
  30. * maxValue: 100,
  31. *
  32. * // this defaults to true, setting to false allows the thumbs to pass each other
  33. * constrainThumbs: false,
  34. * renderTo: Ext.getBody()
  35. * });
  36. */
  37. Ext.define('Ext.slider.Multi', {
  38. extend: 'Ext.form.field.Base',
  39. alias: 'widget.multislider',
  40. alternateClassName: 'Ext.slider.MultiSlider',
  41. requires: [
  42. 'Ext.slider.Thumb',
  43. 'Ext.slider.Tip',
  44. 'Ext.Number',
  45. 'Ext.util.Format',
  46. 'Ext.Template',
  47. 'Ext.layout.component.field.Slider'
  48. ],
  49. childEls: [
  50. 'endEl', 'innerEl'
  51. ],
  52. // note: {id} here is really {inputId}, but {cmpId} is available
  53. fieldSubTpl: [
  54. '&lt;div id=&quot;{id}&quot; class=&quot;' + Ext.baseCSSPrefix + 'slider {fieldCls} {vertical}&quot; aria-valuemin=&quot;{minValue}&quot; aria-valuemax=&quot;{maxValue}&quot; aria-valuenow=&quot;{value}&quot; aria-valuetext=&quot;{value}&quot;&gt;',
  55. '&lt;div id=&quot;{cmpId}-endEl&quot; class=&quot;' + Ext.baseCSSPrefix + 'slider-end&quot; role=&quot;presentation&quot;&gt;',
  56. '&lt;div id=&quot;{cmpId}-innerEl&quot; class=&quot;' + Ext.baseCSSPrefix + 'slider-inner&quot; role=&quot;presentation&quot;&gt;',
  57. '{%this.renderThumbs(out, values)%}',
  58. '&lt;/div&gt;',
  59. '&lt;/div&gt;',
  60. '&lt;/div&gt;',
  61. {
  62. renderThumbs: function(out, values) {
  63. var me = values.$comp,
  64. i = 0,
  65. thumbs = me.thumbs,
  66. len = thumbs.length,
  67. thumb,
  68. thumbConfig;
  69. for (; i &lt; len; i++) {
  70. thumb = thumbs[i];
  71. thumbConfig = thumb.getElConfig();
  72. thumbConfig.id = me.id + '-thumb-' + i;
  73. Ext.DomHelper.generateMarkup(thumbConfig, out);
  74. }
  75. },
  76. disableFormats: true
  77. }
  78. ],
  79. <span id='Ext-slider-Multi-cfg-value'> /**
  80. </span> * @cfg {Number} value
  81. * A value with which to initialize the slider. Setting this will only result in the creation
  82. * of a single slider thumb; if you want multiple thumbs then use the {@link #values} config instead.
  83. *
  84. * Defaults to #minValue.
  85. */
  86. <span id='Ext-slider-Multi-cfg-values'> /**
  87. </span> * @cfg {Number[]} values
  88. * Array of Number values with which to initalize the slider. A separate slider thumb will be created for each value
  89. * in this array. This will take precedence over the single {@link #value} config.
  90. */
  91. <span id='Ext-slider-Multi-cfg-vertical'> /**
  92. </span> * @cfg {Boolean} vertical
  93. * Orient the Slider vertically rather than horizontally.
  94. */
  95. vertical: false,
  96. <span id='Ext-slider-Multi-cfg-minValue'> /**
  97. </span> * @cfg {Number} minValue
  98. * The minimum value for the Slider.
  99. */
  100. minValue: 0,
  101. <span id='Ext-slider-Multi-cfg-maxValue'> /**
  102. </span> * @cfg {Number} maxValue
  103. * The maximum value for the Slider.
  104. */
  105. maxValue: 100,
  106. <span id='Ext-slider-Multi-cfg-decimalPrecision'> /**
  107. </span> * @cfg {Number/Boolean} decimalPrecision The number of decimal places to which to round the Slider's value.
  108. *
  109. * To disable rounding, configure as **false**.
  110. */
  111. decimalPrecision: 0,
  112. <span id='Ext-slider-Multi-cfg-keyIncrement'> /**
  113. </span> * @cfg {Number} keyIncrement
  114. * How many units to change the Slider when adjusting with keyboard navigation. If the increment
  115. * config is larger, it will be used instead.
  116. */
  117. keyIncrement: 1,
  118. <span id='Ext-slider-Multi-cfg-increment'> /**
  119. </span> * @cfg {Number} increment
  120. * How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
  121. */
  122. increment: 0,
  123. <span id='Ext-slider-Multi-cfg-zeroBasedSnapping'> /**
  124. </span> * @cfg {Boolean} [zeroBasedSnapping=false]
  125. * Set to `true` to calculate snap points based on {@link #increment}s from zero as opposed to
  126. * from this Slider's {@link #minValue}.
  127. *
  128. * By Default, valid snap points are calculated starting {@link #increment}s from the {@link #minValue}
  129. */
  130. <span id='Ext-slider-Multi-property-clickRange'> /**
  131. </span> * @private
  132. * @property {Number[]} clickRange
  133. * Determines whether or not a click to the slider component is considered to be a user request to change the value. Specified as an array of [top, bottom],
  134. * the click event's 'top' property is compared to these numbers and the click only considered a change request if it falls within them. e.g. if the 'top'
  135. * value of the click event is 4 or 16, the click is not considered a change request as it falls outside of the [5, 15] range
  136. */
  137. clickRange: [5,15],
  138. <span id='Ext-slider-Multi-cfg-clickToChange'> /**
  139. </span> * @cfg {Boolean} clickToChange
  140. * Determines whether or not clicking on the Slider axis will change the slider.
  141. */
  142. clickToChange : true,
  143. <span id='Ext-slider-Multi-cfg-animate'> /**
  144. </span> * @cfg {Boolean} animate
  145. * Turn on or off animation.
  146. */
  147. animate: true,
  148. <span id='Ext-slider-Multi-property-dragging'> /**
  149. </span> * @property {Boolean} dragging
  150. * True while the thumb is in a drag operation
  151. */
  152. dragging: false,
  153. <span id='Ext-slider-Multi-cfg-constrainThumbs'> /**
  154. </span> * @cfg {Boolean} constrainThumbs
  155. * True to disallow thumbs from overlapping one another.
  156. */
  157. constrainThumbs: true,
  158. componentLayout: 'sliderfield',
  159. <span id='Ext-slider-Multi-cfg-useTips'> /**
  160. </span> * @cfg {Object/Boolean} useTips
  161. * True to use an {@link Ext.slider.Tip} to display tips for the value. This option may also
  162. * provide a configuration object for an {@link Ext.slider.Tip}.
  163. */
  164. useTips : true,
  165. <span id='Ext-slider-Multi-cfg-tipText'> /**
  166. </span> * @cfg {Function} [tipText=undefined]
  167. * A function used to display custom text for the slider tip.
  168. *
  169. * Defaults to null, which will use the default on the plugin.
  170. *
  171. * @cfg {Ext.slider.Thumb} tipText.thumb The Thumb that the Tip is attached to
  172. * @cfg {String} tipText.return The text to display in the tip
  173. */
  174. tipText : null,
  175. ariaRole: 'slider',
  176. // private override
  177. initValue: function() {
  178. var me = this,
  179. extValue = Ext.value,
  180. // Fallback for initial values: values config -&gt; value config -&gt; minValue config -&gt; 0
  181. values = extValue(me.values, [extValue(me.value, extValue(me.minValue, 0))]),
  182. i = 0,
  183. len = values.length;
  184. // Store for use in dirty check
  185. me.originalValue = values;
  186. // Add a thumb for each value
  187. for (; i &lt; len; i++) {
  188. me.addThumb(values[i]);
  189. }
  190. },
  191. // private override
  192. initComponent : function() {
  193. var me = this,
  194. tipPlug,
  195. hasTip,
  196. p, pLen, plugins;
  197. <span id='Ext-slider-Multi-property-thumbs'> /**
  198. </span> * @property {Array} thumbs
  199. * Array containing references to each thumb
  200. */
  201. me.thumbs = [];
  202. me.keyIncrement = Math.max(me.increment, me.keyIncrement);
  203. me.addEvents(
  204. <span id='Ext-slider-Multi-event-beforechange'> /**
  205. </span> * @event beforechange
  206. * Fires before the slider value is changed. By returning false from an event handler, you can cancel the
  207. * event and prevent the slider from changing.
  208. * @param {Ext.slider.Multi} slider The slider
  209. * @param {Number} newValue The new value which the slider is being changed to.
  210. * @param {Number} oldValue The old value which the slider was previously.
  211. */
  212. 'beforechange',
  213. <span id='Ext-slider-Multi-event-change'> /**
  214. </span> * @event change
  215. * Fires when the slider value is changed.
  216. * @param {Ext.slider.Multi} slider The slider
  217. * @param {Number} newValue The new value which the slider has been changed to.
  218. * @param {Ext.slider.Thumb} thumb The thumb that was changed
  219. */
  220. 'change',
  221. <span id='Ext-slider-Multi-event-changecomplete'> /**
  222. </span> * @event changecomplete
  223. * Fires when the slider value is changed by the user and any drag operations have completed.
  224. * @param {Ext.slider.Multi} slider The slider
  225. * @param {Number} newValue The new value which the slider has been changed to.
  226. * @param {Ext.slider.Thumb} thumb The thumb that was changed
  227. */
  228. 'changecomplete',
  229. <span id='Ext-slider-Multi-event-dragstart'> /**
  230. </span> * @event dragstart
  231. * Fires after a drag operation has started.
  232. * @param {Ext.slider.Multi} slider The slider
  233. * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  234. */
  235. 'dragstart',
  236. <span id='Ext-slider-Multi-event-drag'> /**
  237. </span> * @event drag
  238. * Fires continuously during the drag operation while the mouse is moving.
  239. * @param {Ext.slider.Multi} slider The slider
  240. * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  241. */
  242. 'drag',
  243. <span id='Ext-slider-Multi-event-dragend'> /**
  244. </span> * @event dragend
  245. * Fires after the drag operation has completed.
  246. * @param {Ext.slider.Multi} slider The slider
  247. * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
  248. */
  249. 'dragend'
  250. );
  251. // Ensure that the maxValue is a snap point, and that the initial value is snapped.
  252. if (me.increment) {
  253. me.maxValue = Ext.Number.snapInRange(me.maxValue, me.increment, me.minValue);
  254. me.value = me.normalizeValue(me.value);
  255. }
  256. me.callParent();
  257. // only can use it if it exists.
  258. if (me.useTips) {
  259. if (Ext.isObject(me.useTips)) {
  260. tipPlug = Ext.apply({}, me.useTips);
  261. } else {
  262. tipPlug = me.tipText ? {getText: me.tipText} : {};
  263. }
  264. plugins = me.plugins = me.plugins || [];
  265. pLen = plugins.length;
  266. for (p = 0; p &lt; pLen; p++) {
  267. if (plugins[p].isSliderTip) {
  268. hasTip = true;
  269. break;
  270. }
  271. }
  272. if (!hasTip) {
  273. me.plugins.push(new Ext.slider.Tip(tipPlug));
  274. }
  275. }
  276. },
  277. <span id='Ext-slider-Multi-method-addThumb'> /**
  278. </span> * Creates a new thumb and adds it to the slider
  279. * @param {Number} [value=0] The initial value to set on the thumb.
  280. * @return {Ext.slider.Thumb} The thumb
  281. */
  282. addThumb: function(value) {
  283. var me = this,
  284. thumb = new Ext.slider.Thumb({
  285. ownerCt : me,
  286. ownerLayout : me.getComponentLayout(),
  287. value : value,
  288. slider : me,
  289. index : me.thumbs.length,
  290. constrain : me.constrainThumbs,
  291. disabled : !!me.readOnly
  292. });
  293. me.thumbs.push(thumb);
  294. //render the thumb now if needed
  295. if (me.rendered) {
  296. thumb.render();
  297. }
  298. return thumb;
  299. },
  300. <span id='Ext-slider-Multi-method-promoteThumb'> /**
  301. </span> * @private
  302. * Moves the given thumb above all other by increasing its z-index. This is called when as drag
  303. * any thumb, so that the thumb that was just dragged is always at the highest z-index. This is
  304. * required when the thumbs are stacked on top of each other at one of the ends of the slider's
  305. * range, which can result in the user not being able to move any of them.
  306. * @param {Ext.slider.Thumb} topThumb The thumb to move to the top
  307. */
  308. promoteThumb: function(topThumb) {
  309. var thumbs = this.thumbs,
  310. ln = thumbs.length,
  311. zIndex, thumb, i;
  312. for (i = 0; i &lt; ln; i++) {
  313. thumb = thumbs[i];
  314. if (thumb == topThumb) {
  315. thumb.bringToFront();
  316. } else {
  317. thumb.sendToBack();
  318. }
  319. }
  320. },
  321. // private override
  322. getSubTplData : function() {
  323. var me = this;
  324. return Ext.apply(me.callParent(), {
  325. $comp: me,
  326. vertical: me.vertical ? Ext.baseCSSPrefix + 'slider-vert' : Ext.baseCSSPrefix + 'slider-horz',
  327. minValue: me.minValue,
  328. maxValue: me.maxValue,
  329. value: me.value
  330. });
  331. },
  332. onRender : function() {
  333. var me = this,
  334. thumbs = me.thumbs,
  335. len = thumbs.length,
  336. i = 0,
  337. thumb;
  338. me.callParent(arguments);
  339. for (i = 0; i &lt; len; i++) {
  340. thumb = thumbs[i];
  341. thumb.el = me.el.getById(me.id + '-thumb-' + i);
  342. thumb.onRender();
  343. }
  344. },
  345. <span id='Ext-slider-Multi-method-initEvents'> /**
  346. </span> * @private
  347. * Adds keyboard and mouse listeners on this.el. Ignores click events on the internal focus element.
  348. */
  349. initEvents : function() {
  350. var me = this;
  351. me.mon(me.el, {
  352. scope : me,
  353. mousedown: me.onMouseDown,
  354. keydown : me.onKeyDown
  355. });
  356. },
  357. <span id='Ext-slider-Multi-method-getTrackpoint'> /**
  358. </span> * @private
  359. * Given an `[x, y]` position within the slider's track (Points outside the slider's track are coerced to either the minimum or maximum value),
  360. * calculate how many pixels **from the slider origin** (left for horizontal Sliders and bottom for vertical Sliders) that point is.
  361. *
  362. * If the point is outside the range of the Slider's track, the return value is `undefined`
  363. * @param {Number[]} xy The point to calculate the track point for
  364. */
  365. getTrackpoint : function(xy) {
  366. var me = this,
  367. result,
  368. positionProperty,
  369. sliderTrack = me.innerEl,
  370. trackLength;
  371. if (me.vertical) {
  372. positionProperty = 'top';
  373. trackLength = sliderTrack.getHeight();
  374. } else {
  375. positionProperty = 'left';
  376. trackLength = sliderTrack.getWidth();
  377. }
  378. result = Ext.Number.constrain(sliderTrack.translatePoints(xy)[positionProperty], 0, trackLength);
  379. return me.vertical ? trackLength - result : result;
  380. },
  381. <span id='Ext-slider-Multi-method-onMouseDown'> /**
  382. </span> * @private
  383. * Mousedown handler for the slider. If the clickToChange is enabled and the click was not on the draggable 'thumb',
  384. * this calculates the new value of the slider and tells the implementation (Horizontal or Vertical) to move the thumb
  385. * @param {Ext.EventObject} e The click event
  386. */
  387. onMouseDown : function(e) {
  388. var me = this,
  389. thumbClicked = false,
  390. i = 0,
  391. thumbs = me.thumbs,
  392. len = thumbs.length,
  393. trackPoint;
  394. if (me.disabled) {
  395. return;
  396. }
  397. //see if the click was on any of the thumbs
  398. for (; i &lt; len; i++) {
  399. thumbClicked = thumbClicked || e.target == thumbs[i].el.dom;
  400. }
  401. if (me.clickToChange &amp;&amp; !thumbClicked) {
  402. trackPoint = me.getTrackpoint(e.getXY());
  403. if (trackPoint !== undefined) {
  404. me.onClickChange(trackPoint);
  405. }
  406. }
  407. me.focus();
  408. },
  409. <span id='Ext-slider-Multi-method-onClickChange'> /**
  410. </span> * @private
  411. * Moves the thumb to the indicated position.
  412. * Only changes the value if the click was within this.clickRange.
  413. * @param {Number} trackPoint local pixel offset **from the origin** (left for horizontal and bottom for vertical) along the Slider's axis at which the click event occured.
  414. */
  415. onClickChange : function(trackPoint) {
  416. var me = this,
  417. thumb, index;
  418. // How far along the track *from the origin* was the click.
  419. // If vertical, the origin is the bottom of the slider track.
  420. //find the nearest thumb to the click event
  421. thumb = me.getNearest(trackPoint);
  422. if (!thumb.disabled) {
  423. index = thumb.index;
  424. me.setValue(index, Ext.util.Format.round(me.reversePixelValue(trackPoint), me.decimalPrecision), undefined, true);
  425. }
  426. },
  427. <span id='Ext-slider-Multi-method-getNearest'> /**
  428. </span> * @private
  429. * Returns the nearest thumb to a click event, along with its distance
  430. * @param {Number} trackPoint local pixel position along the Slider's axis to find the Thumb for
  431. * @return {Object} The closest thumb object and its distance from the click event
  432. */
  433. getNearest: function(trackPoint) {
  434. var me = this,
  435. clickValue = me.reversePixelValue(trackPoint),
  436. nearestDistance = (me.maxValue - me.minValue) + 5, //add a small fudge for the end of the slider
  437. nearest = null,
  438. thumbs = me.thumbs,
  439. i = 0,
  440. len = thumbs.length,
  441. thumb,
  442. value,
  443. dist;
  444. for (; i &lt; len; i++) {
  445. thumb = me.thumbs[i];
  446. value = thumb.value;
  447. dist = Math.abs(value - clickValue);
  448. if (Math.abs(dist &lt;= nearestDistance)) {
  449. nearest = thumb;
  450. nearestDistance = dist;
  451. }
  452. }
  453. return nearest;
  454. },
  455. <span id='Ext-slider-Multi-method-onKeyDown'> /**
  456. </span> * @private
  457. * Handler for any keypresses captured by the slider. If the key is UP or RIGHT, the thumb is moved along to the right
  458. * by this.keyIncrement. If DOWN or LEFT it is moved left. Pressing CTRL moves the slider to the end in either direction
  459. * @param {Ext.EventObject} e The Event object
  460. */
  461. onKeyDown : function(e) {
  462. /*
  463. * The behaviour for keyboard handling with multiple thumbs is currently undefined.
  464. * There's no real sane default for it, so leave it like this until we come up
  465. * with a better way of doing it.
  466. */
  467. var me = this,
  468. k,
  469. val;
  470. if(me.disabled || me.thumbs.length !== 1) {
  471. e.preventDefault();
  472. return;
  473. }
  474. k = e.getKey();
  475. switch(k) {
  476. case e.UP:
  477. case e.RIGHT:
  478. e.stopEvent();
  479. val = e.ctrlKey ? me.maxValue : me.getValue(0) + me.keyIncrement;
  480. me.setValue(0, val, undefined, true);
  481. break;
  482. case e.DOWN:
  483. case e.LEFT:
  484. e.stopEvent();
  485. val = e.ctrlKey ? me.minValue : me.getValue(0) - me.keyIncrement;
  486. me.setValue(0, val, undefined, true);
  487. break;
  488. default:
  489. e.preventDefault();
  490. }
  491. },
  492. <span id='Ext-slider-Multi-method-normalizeValue'> /**
  493. </span> * @private
  494. * Returns a snapped, constrained value when given a desired value
  495. * @param {Number} value Raw number value
  496. * @return {Number} The raw value rounded to the correct d.p. and constrained within the set max and min values
  497. */
  498. normalizeValue : function(v) {
  499. var me = this,
  500. Num = Ext.Number,
  501. snapFn = Num[me.zeroBasedSnapping ? 'snap' : 'snapInRange'];
  502. v = snapFn.call(Num, v, me.increment, me.minValue, me.maxValue);
  503. v = Ext.util.Format.round(v, me.decimalPrecision);
  504. v = Ext.Number.constrain(v, me.minValue, me.maxValue);
  505. return v;
  506. },
  507. <span id='Ext-slider-Multi-method-setMinValue'> /**
  508. </span> * Sets the minimum value for the slider instance. If the current value is less than the minimum value, the current
  509. * value will be changed.
  510. * @param {Number} val The new minimum value
  511. */
  512. setMinValue : function(val) {
  513. var me = this,
  514. i = 0,
  515. thumbs = me.thumbs,
  516. len = thumbs.length,
  517. t;
  518. me.minValue = val;
  519. if (me.rendered) {
  520. me.inputEl.dom.setAttribute('aria-valuemin', val);
  521. }
  522. for (; i &lt; len; ++i) {
  523. t = thumbs[i];
  524. t.value = t.value &lt; val ? val : t.value;
  525. }
  526. me.syncThumbs();
  527. },
  528. <span id='Ext-slider-Multi-method-setMaxValue'> /**
  529. </span> * Sets the maximum value for the slider instance. If the current value is more than the maximum value, the current
  530. * value will be changed.
  531. * @param {Number} val The new maximum value
  532. */
  533. setMaxValue : function(val) {
  534. var me = this,
  535. i = 0,
  536. thumbs = me.thumbs,
  537. len = thumbs.length,
  538. t;
  539. me.maxValue = val;
  540. if (me.rendered) {
  541. me.inputEl.dom.setAttribute('aria-valuemax', val);
  542. }
  543. for (; i &lt; len; ++i) {
  544. t = thumbs[i];
  545. t.value = t.value &gt; val ? val : t.value;
  546. }
  547. me.syncThumbs();
  548. },
  549. <span id='Ext-slider-Multi-method-setValue'> /**
  550. </span> * Programmatically sets the value of the Slider. Ensures that the value is constrained within the minValue and
  551. * maxValue.
  552. * @param {Number} index Index of the thumb to move
  553. * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
  554. * @param {Boolean} [animate=true] Turn on or off animation
  555. */
  556. setValue : function(index, value, animate, changeComplete) {
  557. var me = this,
  558. thumb = me.thumbs[index];
  559. // ensures value is contstrained and snapped
  560. value = me.normalizeValue(value);
  561. if (value !== thumb.value &amp;&amp; me.fireEvent('beforechange', me, value, thumb.value, thumb) !== false) {
  562. thumb.value = value;
  563. if (me.rendered) {
  564. // TODO this only handles a single value; need a solution for exposing multiple values to aria.
  565. // Perhaps this should go on each thumb element rather than the outer element.
  566. me.inputEl.set({
  567. 'aria-valuenow': value,
  568. 'aria-valuetext': value
  569. });
  570. thumb.move(me.calculateThumbPosition(value), Ext.isDefined(animate) ? animate !== false : me.animate);
  571. me.fireEvent('change', me, value, thumb);
  572. me.checkDirty();
  573. if (changeComplete) {
  574. me.fireEvent('changecomplete', me, value, thumb);
  575. }
  576. }
  577. }
  578. },
  579. <span id='Ext-slider-Multi-method-calculateThumbPosition'> /**
  580. </span> * @private
  581. * Given a value within this Slider's range, calculates a Thumb's percentage CSS position to map that value.
  582. */
  583. calculateThumbPosition : function(v) {
  584. return (v - this.minValue) / (this.maxValue - this.minValue) * 100;
  585. },
  586. <span id='Ext-slider-Multi-method-getRatio'> /**
  587. </span> * @private
  588. * Returns the ratio of pixels to mapped values. e.g. if the slider is 200px wide and maxValue - minValue is 100,
  589. * the ratio is 2
  590. * @return {Number} The ratio of pixels to mapped values
  591. */
  592. getRatio : function() {
  593. var me = this,
  594. trackLength = this.vertical ? this.innerEl.getHeight() : this.innerEl.getWidth(),
  595. valueRange = this.maxValue - this.minValue;
  596. return valueRange === 0 ? trackLength : (trackLength / valueRange);
  597. },
  598. <span id='Ext-slider-Multi-method-reversePixelValue'> /**
  599. </span> * @private
  600. * Given a pixel location along the slider, returns the mapped slider value for that pixel.
  601. * E.g. if we have a slider 200px wide with minValue = 100 and maxValue = 500, reversePixelValue(50)
  602. * returns 200
  603. * @param {Number} pos The position along the slider to return a mapped value for
  604. * @return {Number} The mapped value for the given position
  605. */
  606. reversePixelValue : function(pos) {
  607. return this.minValue + (pos / this.getRatio());
  608. },
  609. <span id='Ext-slider-Multi-method-reversePercentageValue'> /**
  610. </span> * @private
  611. * Given a Thumb's percentage position along the slider, returns the mapped slider value for that pixel.
  612. * E.g. if we have a slider 200px wide with minValue = 100 and maxValue = 500, reversePercentageValue(25)
  613. * returns 200
  614. * @param {Number} pos The percentage along the slider track to return a mapped value for
  615. * @return {Number} The mapped value for the given position
  616. */
  617. reversePercentageValue : function(pos) {
  618. return this.minValue + (this.maxValue - this.minValue) * (pos / 100);
  619. },
  620. //private
  621. onDisable: function() {
  622. var me = this,
  623. i = 0,
  624. thumbs = me.thumbs,
  625. len = thumbs.length,
  626. thumb,
  627. el,
  628. xy;
  629. me.callParent();
  630. for (; i &lt; len; i++) {
  631. thumb = thumbs[i];
  632. el = thumb.el;
  633. thumb.disable();
  634. if(Ext.isIE) {
  635. //IE breaks when using overflow visible and opacity other than 1.
  636. //Create a place holder for the thumb and display it.
  637. xy = el.getXY();
  638. el.hide();
  639. me.innerEl.addCls(me.disabledCls).dom.disabled = true;
  640. if (!me.thumbHolder) {
  641. me.thumbHolder = me.endEl.createChild({cls: Ext.baseCSSPrefix + 'slider-thumb ' + me.disabledCls});
  642. }
  643. me.thumbHolder.show().setXY(xy);
  644. }
  645. }
  646. },
  647. //private
  648. onEnable: function() {
  649. var me = this,
  650. i = 0,
  651. thumbs = me.thumbs,
  652. len = thumbs.length,
  653. thumb,
  654. el;
  655. this.callParent();
  656. for (; i &lt; len; i++) {
  657. thumb = thumbs[i];
  658. el = thumb.el;
  659. thumb.enable();
  660. if (Ext.isIE) {
  661. me.innerEl.removeCls(me.disabledCls).dom.disabled = false;
  662. if (me.thumbHolder) {
  663. me.thumbHolder.hide();
  664. }
  665. el.show();
  666. me.syncThumbs();
  667. }
  668. }
  669. },
  670. <span id='Ext-slider-Multi-method-syncThumbs'> /**
  671. </span> * Synchronizes thumbs position to the proper proportion of the total component width based on the current slider
  672. * {@link #value}. This will be called automatically when the Slider is resized by a layout, but if it is rendered
  673. * auto width, this method can be called from another resize handler to sync the Slider if necessary.
  674. */
  675. syncThumbs : function() {
  676. if (this.rendered) {
  677. var thumbs = this.thumbs,
  678. length = thumbs.length,
  679. i = 0;
  680. for (; i &lt; length; i++) {
  681. thumbs[i].move(this.calculateThumbPosition(thumbs[i].value));
  682. }
  683. }
  684. },
  685. <span id='Ext-slider-Multi-method-getValue'> /**
  686. </span> * Returns the current value of the slider
  687. * @param {Number} index The index of the thumb to return a value for
  688. * @return {Number/Number[]} The current value of the slider at the given index, or an array of all thumb values if
  689. * no index is given.
  690. */
  691. getValue : function(index) {
  692. return Ext.isNumber(index) ? this.thumbs[index].value : this.getValues();
  693. },
  694. <span id='Ext-slider-Multi-method-getValues'> /**
  695. </span> * Returns an array of values - one for the location of each thumb
  696. * @return {Number[]} The set of thumb values
  697. */
  698. getValues: function() {
  699. var values = [],
  700. i = 0,
  701. thumbs = this.thumbs,
  702. len = thumbs.length;
  703. for (; i &lt; len; i++) {
  704. values.push(thumbs[i].value);
  705. }
  706. return values;
  707. },
  708. getSubmitValue: function() {
  709. var me = this;
  710. return (me.disabled || !me.submitValue) ? null : me.getValue();
  711. },
  712. reset: function() {
  713. var me = this,
  714. arr = [].concat(me.originalValue),
  715. a = 0,
  716. aLen = arr.length,
  717. val;
  718. for (; a &lt; aLen; a++) {
  719. val = arr[a];
  720. me.setValue(a, val);
  721. }
  722. me.clearInvalid();
  723. // delete here so we reset back to the original state
  724. delete me.wasValid;
  725. },
  726. setReadOnly: function(readOnly){
  727. var me = this,
  728. thumbs = me.thumbs,
  729. len = thumbs.length,
  730. i = 0;
  731. me.callParent(arguments);
  732. readOnly = me.readOnly;
  733. for (; i &lt; len; ++i) {
  734. if (readOnly) {
  735. thumbs[i].disable();
  736. } else {
  737. thumbs[i].enable();
  738. }
  739. }
  740. },
  741. // private
  742. beforeDestroy : function() {
  743. var me = this,
  744. thumbs = me.thumbs,
  745. t = 0,
  746. tLen = thumbs.length,
  747. thumb;
  748. Ext.destroy(me.innerEl, me.endEl, me.focusEl);
  749. for (; t &lt; tLen; t++) {
  750. thumb = thumbs[t];
  751. Ext.destroy(thumb);
  752. }
  753. me.callParent();
  754. }
  755. });
  756. </pre>
  757. </body>
  758. </html>