Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

slider-value-range.js 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*
  2. Copyright (c) 2010, Yahoo! Inc. All rights reserved.
  3. Code licensed under the BSD License:
  4. http://developer.yahoo.com/yui/license.html
  5. version: 3.4.0
  6. build: nightly
  7. */
  8. YUI.add('slider-value-range', function(Y) {
  9. /**
  10. * Adds value support for Slider as a range of integers between a configured
  11. * minimum and maximum value. For use with <code>Y.Base.build(..)</code> to
  12. * add the plumbing to <code>Y.SliderBase</code>.
  13. *
  14. * @module slider
  15. * @submodule slider-value-range
  16. */
  17. // Constants for compression or performance
  18. var MIN = 'min',
  19. MAX = 'max',
  20. VALUE = 'value',
  21. round = Math.round;
  22. /**
  23. * One class of value algorithm that can be built onto SliderBase. By default,
  24. * values range between 0 and 100, but you can configure these on the
  25. * built Slider class by setting the <code>min</code> and <code>max</code>
  26. * configurations. Set the initial value (will cause the thumb to move to the
  27. * appropriate location on the rail) in configuration as well if appropriate.
  28. *
  29. * @class SliderValueRange
  30. */
  31. function SliderValueRange() {
  32. this._initSliderValueRange();
  33. }
  34. Y.SliderValueRange = Y.mix( SliderValueRange, {
  35. // Prototype properties and methods that will be added onto host class
  36. prototype: {
  37. /**
  38. * Factor used to translate value -&gt; position -&gt; value.
  39. *
  40. * @property _factor
  41. * @type {Number}
  42. * @protected
  43. */
  44. _factor: 1,
  45. /**
  46. * Stub for construction logic. Override if extending this class and
  47. * you need to set something up during the initializer phase.
  48. *
  49. * @method _initSliderValueRange
  50. * @protected
  51. */
  52. _initSliderValueRange: function () {},
  53. /**
  54. * Override of stub method in SliderBase that is called at the end of
  55. * its bindUI stage of render(). Subscribes to internal events to
  56. * trigger UI and related state updates.
  57. *
  58. * @method _bindValueLogic
  59. * @protected
  60. */
  61. _bindValueLogic: function () {
  62. this.after( {
  63. minChange : this._afterMinChange,
  64. maxChange : this._afterMaxChange,
  65. valueChange: this._afterValueChange
  66. } );
  67. },
  68. /**
  69. * Move the thumb to appropriate position if necessary. Also resets
  70. * the cached offsets and recalculates the conversion factor to
  71. * translate position to value.
  72. *
  73. * @method _syncThumbPosition
  74. * @protected
  75. */
  76. _syncThumbPosition: function () {
  77. this._calculateFactor();
  78. this._setPosition( this.get( VALUE ) );
  79. },
  80. /**
  81. * Calculates and caches
  82. * (range between max and min) / (rail length)
  83. * for fast runtime calculation of position -&gt; value.
  84. *
  85. * @method _calculateFactor
  86. * @protected
  87. */
  88. _calculateFactor: function () {
  89. var length = this.get( 'length' ),
  90. thumbSize = this.thumb.getStyle( this._key.dim ),
  91. min = this.get( MIN ),
  92. max = this.get( MAX );
  93. // The default thumb width is based on Sam skin's thumb dimension.
  94. // This attempts to allow for rendering off-DOM, then attaching
  95. // without the need to call syncUI(). It is still recommended
  96. // to call syncUI() in these cases though, just to be sure.
  97. length = parseFloat( length ) || 150;
  98. thumbSize = parseFloat( thumbSize ) || 15;
  99. this._factor = ( max - min ) / ( length - thumbSize );
  100. },
  101. /**
  102. * Dispatch the new position of the thumb into the value setting
  103. * operations.
  104. *
  105. * @method _defThumbMoveFn
  106. * @param e { EventFacade } The host's thumbMove event
  107. * @protected
  108. */
  109. _defThumbMoveFn: function ( e ) {
  110. var previous = this.get( VALUE ),
  111. value = this._offsetToValue( e.offset );
  112. // This test avoids duplication of this.set(..) if the origin
  113. // of this thumbMove is from slider.set('value',x);
  114. // slider.set() -> afterValueChange -> uiMoveThumb ->
  115. // fire(thumbMove) -> _defThumbMoveFn -> this.set()
  116. if ( previous !== value ) {
  117. this.set( VALUE, value, { positioned: true } );
  118. }
  119. },
  120. /**
  121. * <p>Converts a pixel position into a value. Calculates current
  122. * thumb offset from the leading edge of the rail multiplied by the
  123. * ratio of <code>(max - min) / (constraining dim)</code>.</p>
  124. *
  125. * <p>Override this if you want to use a different value mapping
  126. * algorithm.</p>
  127. *
  128. * @method _offsetToValue
  129. * @param offset { Number } X or Y pixel offset
  130. * @return { mixed } Value corresponding to the provided pixel offset
  131. * @protected
  132. */
  133. _offsetToValue: function ( offset ) {
  134. var value = round( offset * this._factor ) + this.get( MIN );
  135. return round( this._nearestValue( value ) );
  136. },
  137. /**
  138. * Converts a value into a pixel offset for use in positioning
  139. * the thumb according to the reverse of the
  140. * <code>_offsetToValue( xy )</code> operation.
  141. *
  142. * @method _valueToOffset
  143. * @param val { Number } The value to map to pixel X or Y position
  144. * @return { Number } The pixel offset
  145. * @protected
  146. */
  147. _valueToOffset: function ( value ) {
  148. var offset = round( ( value - this.get( MIN ) ) / this._factor );
  149. return offset;
  150. },
  151. /**
  152. * Returns the current value. Override this if you want to introduce
  153. * output formatting. Otherwise equivalent to slider.get( "value" );
  154. *
  155. * @method getValue
  156. * @return {Number}
  157. */
  158. getValue: function () {
  159. return this.get( VALUE );
  160. },
  161. /**
  162. * Updates the current value. Override this if you want to introduce
  163. * input value parsing or preprocessing. Otherwise equivalent to
  164. * slider.set( "value", v );
  165. *
  166. * @method setValue
  167. * @param val {Number} The new value
  168. * @return {Slider}
  169. * @chainable
  170. */
  171. setValue: function ( val ) {
  172. return this.set( VALUE, val );
  173. },
  174. /**
  175. * Update position according to new min value. If the new min results
  176. * in the current value being out of range, the value is set to the
  177. * closer of min or max.
  178. *
  179. * @method _afterMinChange
  180. * @param e { EventFacade } The <code>min</code> attribute change event.
  181. * @protected
  182. */
  183. _afterMinChange: function ( e ) {
  184. this._verifyValue();
  185. this._syncThumbPosition();
  186. },
  187. /**
  188. * Update position according to new max value. If the new max results
  189. * in the current value being out of range, the value is set to the
  190. * closer of min or max.
  191. *
  192. * @method _afterMaxChange
  193. * @param e { EventFacade } The <code>max</code> attribute change event.
  194. * @protected
  195. */
  196. _afterMaxChange: function ( e ) {
  197. this._verifyValue();
  198. this._syncThumbPosition();
  199. },
  200. /**
  201. * Verifies that the current value is within the min - max range. If
  202. * not, value is set to either min or max, depending on which is
  203. * closer.
  204. *
  205. * @method _verifyValue
  206. * @protected
  207. */
  208. _verifyValue: function () {
  209. var value = this.get( VALUE ),
  210. nearest = this._nearestValue( value );
  211. if ( value !== nearest ) {
  212. // @TODO Can/should valueChange, minChange, etc be queued
  213. // events? To make dd.set( 'min', n ); execute after minChange
  214. // subscribers before on/after valueChange subscribers.
  215. this.set( VALUE, nearest );
  216. }
  217. },
  218. /**
  219. * Propagate change to the thumb position unless the change originated
  220. * from the thumbMove event.
  221. *
  222. * @method _afterValueChange
  223. * @param e { EventFacade } The <code>valueChange</code> event.
  224. * @protected
  225. */
  226. _afterValueChange: function ( e ) {
  227. if ( !e.positioned ) {
  228. this._setPosition( e.newVal );
  229. }
  230. },
  231. /**
  232. * Positions the thumb in accordance with the translated value.
  233. *
  234. * @method _setPosition
  235. * @protected
  236. */
  237. _setPosition: function ( value ) {
  238. this._uiMoveThumb( this._valueToOffset( value ) );
  239. },
  240. /**
  241. * Validates new values assigned to <code>min</code> attribute. Numbers
  242. * are acceptable. Override this to enforce different rules.
  243. *
  244. * @method _validateNewMin
  245. * @param value { mixed } Value assigned to <code>min</code> attribute.
  246. * @return { Boolean } True for numbers. False otherwise.
  247. * @protected
  248. */
  249. _validateNewMin: function ( value ) {
  250. return Y.Lang.isNumber( value );
  251. },
  252. /**
  253. * Validates new values assigned to <code>max</code> attribute. Numbers
  254. * are acceptable. Override this to enforce different rules.
  255. *
  256. * @method _validateNewMax
  257. * @param value { mixed } Value assigned to <code>max</code> attribute.
  258. * @return { Boolean } True for numbers. False otherwise.
  259. * @protected
  260. */
  261. _validateNewMax: function ( value ) {
  262. return Y.Lang.isNumber( value );
  263. },
  264. /**
  265. * Restricts new values assigned to <code>value</code> attribute to be
  266. * between the configured <code>min</code> and <code>max</code>.
  267. * Rounds to nearest integer value.
  268. *
  269. * @method _setNewValue
  270. * @param value { Number } Value assigned to <code>value</code> attribute
  271. * @return { Number } Normalized and constrained value
  272. * @protected
  273. */
  274. _setNewValue: function ( value ) {
  275. return round( this._nearestValue( value ) );
  276. },
  277. /**
  278. * Returns the nearest valid value to the value input. If the provided
  279. * value is outside the min - max range, accounting for min > max
  280. * scenarios, the nearest of either min or max is returned. Otherwise,
  281. * the provided value is returned.
  282. *
  283. * @method _nearestValue
  284. * @param value { mixed } Value to test against current min - max range
  285. * @return { Number } Current min, max, or value if within range
  286. * @protected
  287. */
  288. _nearestValue: function ( value ) {
  289. var min = this.get( MIN ),
  290. max = this.get( MAX ),
  291. tmp;
  292. // Account for reverse value range (min > max)
  293. tmp = ( max > min ) ? max : min;
  294. min = ( max > min ) ? min : max;
  295. max = tmp;
  296. return ( value < min ) ?
  297. min :
  298. ( value > max ) ?
  299. max :
  300. value;
  301. }
  302. },
  303. /**
  304. * Attributes that will be added onto host class.
  305. *
  306. * @property ATTRS
  307. * @type {Object}
  308. * @static
  309. * @protected
  310. */
  311. ATTRS: {
  312. /**
  313. * The value associated with the farthest top, left position of the
  314. * rail. Can be greater than the configured <code>max</code> if you
  315. * want values to increase from right-to-left or bottom-to-top.
  316. *
  317. * @attribute min
  318. * @type { Number }
  319. * @default 0
  320. */
  321. min: {
  322. value : 0,
  323. validator: '_validateNewMin'
  324. },
  325. /**
  326. * The value associated with the farthest bottom, right position of
  327. * the rail. Can be less than the configured <code>min</code> if
  328. * you want values to increase from right-to-left or bottom-to-top.
  329. *
  330. * @attribute max
  331. * @type { Number }
  332. * @default 100
  333. */
  334. max: {
  335. value : 100,
  336. validator: '_validateNewMax'
  337. },
  338. /**
  339. * The value associated with the thumb's current position on the
  340. * rail. Defaults to the value inferred from the thumb's current
  341. * position. Specifying value in the constructor will move the
  342. * thumb to the position that corresponds to the supplied value.
  343. *
  344. * @attribute value
  345. * @type { Number }
  346. * @default (inferred from current thumb position)
  347. */
  348. value: {
  349. value : 0,
  350. setter: '_setNewValue'
  351. }
  352. }
  353. }, true );
  354. }, '3.4.0' ,{requires:['slider-base']});