HorizontalSlider.js.uncompressed.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. require({cache:{
  2. 'url:dijit/form/templates/HorizontalSlider.html':"<table class=\"dijit dijitReset dijitSlider dijitSliderH\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\" data-dojo-attach-event=\"onkeypress:_onKeyPress,onkeyup:_onKeyUp\"\n\trole=\"presentation\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td data-dojo-attach-point=\"topDecoration\" class=\"dijitReset dijitSliderDecoration dijitSliderDecorationT dijitSliderDecorationH\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\n\t\t\t><div class=\"dijitSliderDecrementIconH\" style=\"display:none\" data-dojo-attach-point=\"decrementButton\"><span class=\"dijitSliderButtonInner\">-</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper\" data-dojo-attach-event=\"press:_onClkDecBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><input data-dojo-attach-point=\"valueNode\" type=\"hidden\" ${!nameAttrSetting}\n\t\t\t/><div class=\"dijitReset dijitSliderBarContainerH\" role=\"presentation\" data-dojo-attach-point=\"sliderBarContainer\"\n\t\t\t\t><div role=\"presentation\" data-dojo-attach-point=\"progressBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH\" data-dojo-attach-event=\"press:_onBarClick\"\n\t\t\t\t\t><div class=\"dijitSliderMoveable dijitSliderMoveableH\"\n\t\t\t\t\t\t><div data-dojo-attach-point=\"sliderHandle,focusNode\" class=\"dijitSliderImageHandle dijitSliderImageHandleH\" data-dojo-attach-event=\"press:_onHandleClick\" role=\"slider\"></div\n\t\t\t\t\t></div\n\t\t\t\t></div\n\t\t\t\t><div role=\"presentation\" data-dojo-attach-point=\"remainingBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH\" data-dojo-attach-event=\"press:_onBarClick\"></div\n\t\t\t></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper\" data-dojo-attach-event=\"press:_onClkIncBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\n\t\t\t><div class=\"dijitSliderIncrementIconH\" style=\"display:none\" data-dojo-attach-point=\"incrementButton\"><span class=\"dijitSliderButtonInner\">+</span></div\n\t\t></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td data-dojo-attach-point=\"containerNode,bottomDecoration\" class=\"dijitReset dijitSliderDecoration dijitSliderDecorationB dijitSliderDecorationH\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n></table>\n"}});
  3. define("dijit/form/HorizontalSlider", [
  4. "dojo/_base/array", // array.forEach
  5. "dojo/_base/declare", // declare
  6. "dojo/dnd/move",
  7. "dojo/_base/event", // event.stop
  8. "dojo/_base/fx", // fx.animateProperty
  9. "dojo/dom-geometry", // domGeometry.position
  10. "dojo/dom-style", // domStyle.getComputedStyle
  11. "dojo/keys", // keys.DOWN_ARROW keys.END keys.HOME keys.LEFT_ARROW keys.PAGE_DOWN keys.PAGE_UP keys.RIGHT_ARROW keys.UP_ARROW
  12. "dojo/_base/lang", // lang.hitch
  13. "dojo/sniff", // has("ie") has("mozilla")
  14. "dojo/dnd/Moveable", // Moveable
  15. "dojo/dnd/Mover", // Mover Mover.prototype.destroy.apply
  16. "dojo/query", // query
  17. "dojo/mouse", // mouse.wheel
  18. "../registry", // registry.findWidgets
  19. "../focus", // focus.focus()
  20. "../typematic",
  21. "./Button",
  22. "./_FormValueWidget",
  23. "../_Container",
  24. "dojo/text!./templates/HorizontalSlider.html"
  25. ], function(array, declare, move, event, fx, domGeometry, domStyle, keys, lang, has, Moveable, Mover, query, mouse,
  26. registry, focus, typematic, Button, _FormValueWidget, _Container, template){
  27. // module:
  28. // dijit/form/HorizontalSlider
  29. var _SliderMover = declare("dijit.form._SliderMover", Mover, {
  30. onMouseMove: function(e){
  31. var widget = this.widget;
  32. var abspos = widget._abspos;
  33. if(!abspos){
  34. abspos = widget._abspos = domGeometry.position(widget.sliderBarContainer, true);
  35. widget._setPixelValue_ = lang.hitch(widget, "_setPixelValue");
  36. widget._isReversed_ = widget._isReversed();
  37. }
  38. var pixelValue = e[widget._mousePixelCoord] - abspos[widget._startingPixelCoord];
  39. widget._setPixelValue_(widget._isReversed_ ? (abspos[widget._pixelCount]-pixelValue) : pixelValue, abspos[widget._pixelCount], false);
  40. },
  41. destroy: function(e){
  42. Mover.prototype.destroy.apply(this, arguments);
  43. var widget = this.widget;
  44. widget._abspos = null;
  45. widget._setValueAttr(widget.value, true);
  46. }
  47. });
  48. var HorizontalSlider = declare("dijit.form.HorizontalSlider", [_FormValueWidget, _Container], {
  49. // summary:
  50. // A form widget that allows one to select a value with a horizontally draggable handle
  51. templateString: template,
  52. // Overrides FormValueWidget.value to indicate numeric value
  53. value: 0,
  54. // showButtons: [const] Boolean
  55. // Show increment/decrement buttons at the ends of the slider?
  56. showButtons: true,
  57. // minimum: [const] Integer
  58. // The minimum value the slider can be set to.
  59. minimum: 0,
  60. // maximum: [const] Integer
  61. // The maximum value the slider can be set to.
  62. maximum: 100,
  63. // discreteValues: Integer
  64. // If specified, indicates that the slider handle has only 'discreteValues' possible positions,
  65. // and that after dragging the handle, it will snap to the nearest possible position.
  66. // Thus, the slider has only 'discreteValues' possible values.
  67. //
  68. // For example, if minimum=10, maxiumum=30, and discreteValues=3, then the slider handle has
  69. // three possible positions, representing values 10, 20, or 30.
  70. //
  71. // If discreteValues is not specified or if it's value is higher than the number of pixels
  72. // in the slider bar, then the slider handle can be moved freely, and the slider's value will be
  73. // computed/reported based on pixel position (in this case it will likely be fractional,
  74. // such as 123.456789).
  75. discreteValues: Infinity,
  76. // pageIncrement: Integer
  77. // If discreteValues is also specified, this indicates the amount of clicks (ie, snap positions)
  78. // that the slider handle is moved via pageup/pagedown keys.
  79. // If discreteValues is not specified, it indicates the number of pixels.
  80. pageIncrement: 2,
  81. // clickSelect: Boolean
  82. // If clicking the slider bar changes the value or not
  83. clickSelect: true,
  84. // slideDuration: Number
  85. // The time in ms to take to animate the slider handle from 0% to 100%,
  86. // when clicking the slider bar to make the handle move.
  87. slideDuration: registry.defaultDuration,
  88. // Map widget attributes to DOMNode attributes.
  89. _setIdAttr: "", // Override _FormWidget which sends id to focusNode
  90. baseClass: "dijitSlider",
  91. // Apply CSS classes to up/down arrows and handle per mouse state
  92. cssStateNodes: {
  93. incrementButton: "dijitSliderIncrementButton",
  94. decrementButton: "dijitSliderDecrementButton",
  95. focusNode: "dijitSliderThumb"
  96. },
  97. _mousePixelCoord: "pageX",
  98. _pixelCount: "w",
  99. _startingPixelCoord: "x",
  100. _handleOffsetCoord: "left",
  101. _progressPixelSize: "width",
  102. _onKeyUp: function(/*Event*/ e){
  103. if(this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey){ return; }
  104. this._setValueAttr(this.value, true);
  105. },
  106. _onKeyPress: function(/*Event*/ e){
  107. if(this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey){ return; }
  108. switch(e.charOrCode){
  109. case keys.HOME:
  110. this._setValueAttr(this.minimum, false);
  111. break;
  112. case keys.END:
  113. this._setValueAttr(this.maximum, false);
  114. break;
  115. // this._descending === false: if ascending vertical (min on top)
  116. // (this._descending || this.isLeftToRight()): if left-to-right horizontal or descending vertical
  117. case ((this._descending || this.isLeftToRight()) ? keys.RIGHT_ARROW : keys.LEFT_ARROW):
  118. case (this._descending === false ? keys.DOWN_ARROW : keys.UP_ARROW):
  119. case (this._descending === false ? keys.PAGE_DOWN : keys.PAGE_UP):
  120. this.increment(e);
  121. break;
  122. case ((this._descending || this.isLeftToRight()) ? keys.LEFT_ARROW : keys.RIGHT_ARROW):
  123. case (this._descending === false ? keys.UP_ARROW : keys.DOWN_ARROW):
  124. case (this._descending === false ? keys.PAGE_UP : keys.PAGE_DOWN):
  125. this.decrement(e);
  126. break;
  127. default:
  128. return;
  129. }
  130. event.stop(e);
  131. },
  132. _onHandleClick: function(e){
  133. if(this.disabled || this.readOnly){ return; }
  134. if(!has("ie")){
  135. // make sure you get focus when dragging the handle
  136. // (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
  137. focus.focus(this.sliderHandle);
  138. }
  139. event.stop(e);
  140. },
  141. _isReversed: function(){
  142. // summary:
  143. // Returns true if direction is from right to left
  144. // tags:
  145. // protected extension
  146. return !this.isLeftToRight();
  147. },
  148. _onBarClick: function(e){
  149. if(this.disabled || this.readOnly || !this.clickSelect){ return; }
  150. focus.focus(this.sliderHandle);
  151. event.stop(e);
  152. var abspos = domGeometry.position(this.sliderBarContainer, true);
  153. var pixelValue = e[this._mousePixelCoord] - abspos[this._startingPixelCoord];
  154. this._setPixelValue(this._isReversed() ? (abspos[this._pixelCount] - pixelValue) : pixelValue, abspos[this._pixelCount], true);
  155. this._movable.onMouseDown(e);
  156. },
  157. _setPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels, /*Boolean?*/ priorityChange){
  158. if(this.disabled || this.readOnly){ return; }
  159. var count = this.discreteValues;
  160. if(count <= 1 || count == Infinity){ count = maxPixels; }
  161. count--;
  162. var pixelsPerValue = maxPixels / count;
  163. var wholeIncrements = Math.round(pixelValue / pixelsPerValue);
  164. this._setValueAttr(Math.max(Math.min((this.maximum-this.minimum)*wholeIncrements/count + this.minimum, this.maximum), this.minimum), priorityChange);
  165. },
  166. _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){
  167. // summary:
  168. // Hook so set('value', value) works.
  169. this._set("value", value);
  170. this.valueNode.value = value;
  171. this.focusNode.setAttribute("aria-valuenow", value);
  172. this.inherited(arguments);
  173. var percent = (value - this.minimum) / (this.maximum - this.minimum);
  174. var progressBar = (this._descending === false) ? this.remainingBar : this.progressBar;
  175. var remainingBar = (this._descending === false) ? this.progressBar : this.remainingBar;
  176. if(this._inProgressAnim && this._inProgressAnim.status != "stopped"){
  177. this._inProgressAnim.stop(true);
  178. }
  179. if(priorityChange && this.slideDuration > 0 && progressBar.style[this._progressPixelSize]){
  180. // animate the slider
  181. var _this = this;
  182. var props = {};
  183. var start = parseFloat(progressBar.style[this._progressPixelSize]);
  184. var duration = this.slideDuration * (percent-start/100);
  185. if(duration == 0){ return; }
  186. if(duration < 0){ duration = 0 - duration; }
  187. props[this._progressPixelSize] = { start: start, end: percent*100, units:"%" };
  188. this._inProgressAnim = fx.animateProperty({ node: progressBar, duration: duration,
  189. onAnimate: function(v){
  190. remainingBar.style[_this._progressPixelSize] = (100 - parseFloat(v[_this._progressPixelSize])) + "%";
  191. },
  192. onEnd: function(){
  193. delete _this._inProgressAnim;
  194. },
  195. properties: props
  196. });
  197. this._inProgressAnim.play();
  198. }else{
  199. progressBar.style[this._progressPixelSize] = (percent*100) + "%";
  200. remainingBar.style[this._progressPixelSize] = ((1-percent)*100) + "%";
  201. }
  202. },
  203. _bumpValue: function(signedChange, /*Boolean?*/ priorityChange){
  204. if(this.disabled || this.readOnly){ return; }
  205. var s = domStyle.getComputedStyle(this.sliderBarContainer);
  206. var c = domGeometry.getContentBox(this.sliderBarContainer, s);
  207. var count = this.discreteValues;
  208. if(count <= 1 || count == Infinity){ count = c[this._pixelCount]; }
  209. count--;
  210. var value = (this.value - this.minimum) * count / (this.maximum - this.minimum) + signedChange;
  211. if(value < 0){ value = 0; }
  212. if(value > count){ value = count; }
  213. value = value * (this.maximum - this.minimum) / count + this.minimum;
  214. this._setValueAttr(value, priorityChange);
  215. },
  216. _onClkBumper: function(val){
  217. if(this.disabled || this.readOnly || !this.clickSelect){ return; }
  218. this._setValueAttr(val, true);
  219. },
  220. _onClkIncBumper: function(){
  221. this._onClkBumper(this._descending === false ? this.minimum : this.maximum);
  222. },
  223. _onClkDecBumper: function(){
  224. this._onClkBumper(this._descending === false ? this.maximum : this.minimum);
  225. },
  226. decrement: function(/*Event*/ e){
  227. // summary:
  228. // Decrement slider
  229. // tags:
  230. // private
  231. this._bumpValue(e.charOrCode == keys.PAGE_DOWN ? -this.pageIncrement : -1);
  232. },
  233. increment: function(/*Event*/ e){
  234. // summary:
  235. // Increment slider
  236. // tags:
  237. // private
  238. this._bumpValue(e.charOrCode == keys.PAGE_UP ? this.pageIncrement : 1);
  239. },
  240. _mouseWheeled: function(/*Event*/ evt){
  241. // summary:
  242. // Event handler for mousewheel where supported
  243. event.stop(evt);
  244. this._bumpValue(evt.wheelDelta < 0 ? -1 : 1, true); // negative scroll acts like a decrement
  245. },
  246. startup: function(){
  247. if(this._started){ return; }
  248. array.forEach(this.getChildren(), function(child){
  249. if(this[child.container] != this.containerNode){
  250. this[child.container].appendChild(child.domNode);
  251. }
  252. }, this);
  253. this.inherited(arguments);
  254. },
  255. _typematicCallback: function(/*Number*/ count, /*Object*/ button, /*Event*/ e){
  256. if(count == -1){
  257. this._setValueAttr(this.value, true);
  258. }else{
  259. this[(button == (this._descending? this.incrementButton : this.decrementButton)) ? "decrement" : "increment"](e);
  260. }
  261. },
  262. buildRendering: function(){
  263. this.inherited(arguments);
  264. if(this.showButtons){
  265. this.incrementButton.style.display="";
  266. this.decrementButton.style.display="";
  267. }
  268. // find any associated label element and add to slider focusnode.
  269. var label = query('label[for="'+this.id+'"]');
  270. if(label.length){
  271. if(!label[0].id){ label[0].id = this.id + "_label"; }
  272. this.focusNode.setAttribute("aria-labelledby", label[0].id);
  273. }
  274. this.focusNode.setAttribute("aria-valuemin", this.minimum);
  275. this.focusNode.setAttribute("aria-valuemax", this.maximum);
  276. },
  277. postCreate: function(){
  278. this.inherited(arguments);
  279. if(this.showButtons){
  280. this.own(
  281. typematic.addMouseListener(this.decrementButton, this, "_typematicCallback", 25, 500),
  282. typematic.addMouseListener(this.incrementButton, this, "_typematicCallback", 25, 500)
  283. );
  284. }
  285. this.connect(this.domNode, mouse.wheel, "_mouseWheeled");
  286. // define a custom constructor for a SliderMover that points back to me
  287. var mover = declare(_SliderMover, {
  288. widget: this
  289. });
  290. this._movable = new Moveable(this.sliderHandle, {mover: mover});
  291. this._layoutHackIE7();
  292. },
  293. destroy: function(){
  294. this._movable.destroy();
  295. if(this._inProgressAnim && this._inProgressAnim.status != "stopped"){
  296. this._inProgressAnim.stop(true);
  297. }
  298. this.inherited(arguments);
  299. }
  300. });
  301. HorizontalSlider._Mover = _SliderMover; // for monkey patching
  302. return HorizontalSlider;
  303. });