ui.slider_handle.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /**
  2. * DevExtreme (ui/slider/ui.slider_handle.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var $ = require("../../core/renderer");
  11. var Widget = require("../widget/ui.widget");
  12. var Tooltip = require("../tooltip");
  13. var translator = require("../../animation/translator");
  14. var positionUtils = require("../../animation/position");
  15. var mathUtils = require("../../core/utils/math");
  16. var typeUtils = require("../../core/utils/type");
  17. var extend = require("../../core/utils/extend").extend;
  18. var numberLocalization = require("../../localization/number");
  19. var SLIDER_CLASS = "dx-slider";
  20. var SLIDER_HANDLE_CLASS = "dx-slider-handle";
  21. var POSITION_ALIASES = {
  22. top: {
  23. my: "bottom center",
  24. at: "top center",
  25. collision: "none"
  26. },
  27. bottom: {
  28. my: "top center",
  29. at: "bottom center",
  30. collision: "none"
  31. },
  32. right: {
  33. my: "left center",
  34. at: "right center",
  35. collision: "none"
  36. },
  37. left: {
  38. my: "right center",
  39. at: "left center",
  40. collision: "none"
  41. }
  42. };
  43. var SliderHandle = Widget.inherit({
  44. _getDefaultOptions: function() {
  45. return extend(this.callBase(), {
  46. hoverStateEnabled: false,
  47. value: 0,
  48. tooltipEnabled: false,
  49. tooltipFormat: function(v) {
  50. return v
  51. },
  52. tooltipPosition: "top",
  53. tooltipShowMode: "onHover",
  54. tooltipFitIn: null
  55. })
  56. },
  57. _initMarkup: function() {
  58. this.callBase();
  59. this.$element().addClass(SLIDER_HANDLE_CLASS);
  60. this.setAria({
  61. role: "slider",
  62. valuenow: this.option("value")
  63. })
  64. },
  65. _render: function() {
  66. this._renderTooltip();
  67. this.callBase()
  68. },
  69. _renderTooltip: function() {
  70. if (this.option("tooltipEnabled")) {
  71. if (!this._$tooltip) {
  72. this._$tooltip = $("<div>").appendTo(this.$element())
  73. }
  74. this._$slider = this.$element().closest("." + SLIDER_CLASS);
  75. this._updateTooltip()
  76. } else {
  77. this._removeTooltip()
  78. }
  79. },
  80. _createTooltip: function() {
  81. if (this._tooltip) {
  82. return false
  83. }
  84. this._tooltip = this._createComponent(this._$tooltip, Tooltip, {
  85. visible: true,
  86. target: this.$element(),
  87. closeOnOutsideClick: false,
  88. container: this.$element(),
  89. closeOnBackButton: false,
  90. closeOnTargetScroll: false,
  91. onPositioned: function(args) {
  92. this._saveTooltipElements(args.component);
  93. this._saveTooltipLocation();
  94. this._centeredTooltipPosition()
  95. }.bind(this),
  96. animation: null,
  97. arrowPosition: null,
  98. templatesRenderAsynchronously: false
  99. });
  100. return true
  101. },
  102. _removeTooltip: function() {
  103. if (!this._$tooltip) {
  104. return
  105. }
  106. this._$tooltip.remove();
  107. delete this._$tooltip;
  108. delete this._tooltip
  109. },
  110. _renderTooltipPosition: function() {
  111. if (!this._tooltip) {
  112. return
  113. }
  114. var position = this.option("tooltipPosition");
  115. this._saveTooltipElements();
  116. this._resetTooltipPosition();
  117. if ("string" === typeUtils.type(position)) {
  118. position = extend({
  119. boundary: this._$slider,
  120. boundaryOffset: {
  121. h: 1,
  122. v: 1
  123. }
  124. }, POSITION_ALIASES[position])
  125. }
  126. this._tooltip.option("position", position);
  127. this._saveTooltipLocation()
  128. },
  129. _saveTooltipElements: function(tooltip) {
  130. tooltip = this._tooltip || tooltip;
  131. this._$tooltipContent = tooltip.$content().parent();
  132. this._$tooltipArrow = this._$tooltipContent.find(".dx-popover-arrow")
  133. },
  134. _resetTooltipPosition: function() {
  135. translator.resetPosition(this._$tooltipContent);
  136. translator.resetPosition(this._$tooltipArrow)
  137. },
  138. _saveTooltipLocation: function() {
  139. this._contentLocate = translator.locate(this._$tooltipContent)
  140. },
  141. _centeredTooltipPosition: function() {
  142. if (!this._tooltip) {
  143. return
  144. }
  145. this._$tooltipContent.outerWidth("auto");
  146. var outerWidthWithoutRounding = this._$tooltipContent.get(0).getBoundingClientRect().width;
  147. var tooltipOuterWidth = Math.ceil(outerWidthWithoutRounding);
  148. var roundedTooltipOuterWidth = tooltipOuterWidth % 2 + tooltipOuterWidth;
  149. this._$tooltipContent.outerWidth(roundedTooltipOuterWidth);
  150. var tooltipCenter = (roundedTooltipOuterWidth - this.$element().width()) / 2;
  151. this._contentLocate.left = -tooltipCenter;
  152. this._$tooltipArrow.css({
  153. marginLeft: -this._$tooltipArrow.outerWidth() / 2,
  154. left: "50%"
  155. });
  156. this._fitTooltip()
  157. },
  158. _fitTooltip: function() {
  159. if (!this._tooltip) {
  160. return
  161. }
  162. var position = this.option("tooltipPosition");
  163. if ("string" === typeUtils.type(position)) {
  164. position = extend({
  165. of: this.$element(),
  166. boundary: this._$slider,
  167. boundaryOffset: {
  168. h: 2,
  169. v: 1
  170. }
  171. }, POSITION_ALIASES[position], {
  172. collision: "fit none"
  173. })
  174. }
  175. var calculatePosition = positionUtils.calculate(this._$tooltipContent, position);
  176. var isLeftSide = "left" === calculatePosition.h.collisionSide;
  177. var arrowLeft = (isLeftSide ? -1 : 1) * calculatePosition.h.oversize;
  178. var arrowMinLeft = this._contentLocate.left;
  179. var arrowMaxRight = this._contentLocate.left + this._$tooltipContent.outerWidth() - this._$tooltipArrow.outerWidth();
  180. translator.move(this._$tooltipContent, {
  181. left: this._contentLocate.left + (isLeftSide ? 1 : -1) * calculatePosition.h.oversize
  182. });
  183. translator.move(this._$tooltipArrow, {
  184. left: mathUtils.fitIntoRange(arrowLeft, arrowMinLeft, arrowMaxRight)
  185. })
  186. },
  187. _getFormattedValue: function(value) {
  188. return numberLocalization.format(value, this.option("tooltipFormat"))
  189. },
  190. _renderValue: function() {
  191. if (!this._tooltip) {
  192. return
  193. }
  194. var value = this.option("value");
  195. this._tooltip.$content().html(this._getFormattedValue(value));
  196. this._fitTooltip()
  197. },
  198. _updateTooltip: function() {
  199. var hoverMode = /^onhover$/i.test(this.option("tooltipShowMode"));
  200. if (!hoverMode) {
  201. this._createTooltip()
  202. }
  203. this.$element().toggleClass("dx-slider-tooltip-on-hover", hoverMode);
  204. this._renderTooltipPosition();
  205. this._renderValue();
  206. this._centeredTooltipPosition()
  207. },
  208. _clean: function() {
  209. this.callBase();
  210. delete this._$tooltip;
  211. delete this._tooltip
  212. },
  213. _ensureTooltipIsCentered: function(value, previousValue) {
  214. if (typeUtils.isDefined(value) && typeUtils.isDefined(previousValue) && value.toString().length !== previousValue.toString().length) {
  215. this._centeredTooltipPosition()
  216. }
  217. },
  218. _optionChanged: function(args) {
  219. switch (args.name) {
  220. case "tooltipFormat":
  221. this._renderValue();
  222. break;
  223. case "value":
  224. this._renderValue();
  225. var value = this._getFormattedValue(args.value);
  226. var previousValue = this._getFormattedValue(args.previousValue);
  227. this._ensureTooltipIsCentered(value, previousValue);
  228. this.setAria("valuenow", args.value);
  229. break;
  230. case "tooltipEnabled":
  231. this._renderTooltip();
  232. break;
  233. case "tooltipPosition":
  234. this._renderTooltipPosition();
  235. this._centeredTooltipPosition();
  236. break;
  237. case "tooltipShowMode":
  238. this._updateTooltip();
  239. break;
  240. case "tooltipFitIn":
  241. this._fitTooltip();
  242. break;
  243. default:
  244. this.callBase(args)
  245. }
  246. },
  247. fitTooltipPosition: function() {
  248. this._fitTooltip()
  249. },
  250. updateTooltip: function() {
  251. if (!this._createTooltip()) {
  252. return
  253. }
  254. this._renderTooltipPosition();
  255. this._renderValue();
  256. this._centeredTooltipPosition()
  257. },
  258. repaint: function() {
  259. this._renderTooltipPosition();
  260. this._centeredTooltipPosition();
  261. if (this._tooltip) {
  262. this._tooltip._visibilityChanged(true)
  263. }
  264. }
  265. });
  266. module.exports = SliderHandle;