ui.date_view.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /**
  2. * DevExtreme (ui/date_box/ui.date_view.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 Editor = require("../editor/editor");
  12. var DateViewRoller = require("./ui.date_view_roller");
  13. var dateUtils = require("../../core/utils/date");
  14. var each = require("../../core/utils/iterator").each;
  15. var extend = require("../../core/utils/extend").extend;
  16. var uiDateUtils = require("./ui.date_utils");
  17. var registerComponent = require("../../core/component_registrator");
  18. var dateLocalization = require("../../localization/date");
  19. var DATEVIEW_CLASS = "dx-dateview";
  20. var DATEVIEW_COMPACT_CLASS = "dx-dateview-compact";
  21. var DATEVIEW_WRAPPER_CLASS = "dx-dateview-wrapper";
  22. var DATEVIEW_ROLLER_CONTAINER_CLASS = "dx-dateview-rollers";
  23. var DATEVIEW_ROLLER_CLASS = "dx-dateviewroller";
  24. var TYPE = {
  25. date: "date",
  26. datetime: "datetime",
  27. time: "time"
  28. };
  29. var ROLLER_TYPE = {
  30. year: "year",
  31. month: "month",
  32. day: "day",
  33. hours: "hours"
  34. };
  35. var DateView = Editor.inherit({
  36. _valueOption: function() {
  37. var value = this.option("value");
  38. var date = new Date(value);
  39. return !value || isNaN(date) ? this._getDefaultDate() : date
  40. },
  41. _getDefaultDate: function() {
  42. var date = new Date;
  43. if (this.option("type") === TYPE.date) {
  44. return new Date(date.getFullYear(), date.getMonth(), date.getDate())
  45. }
  46. return date
  47. },
  48. _getDefaultOptions: function() {
  49. return extend(this.callBase(), {
  50. minDate: uiDateUtils.MIN_DATEVIEW_DEFAULT_DATE,
  51. maxDate: uiDateUtils.MAX_DATEVIEW_DEFAULT_DATE,
  52. type: TYPE.date,
  53. value: new Date,
  54. showNames: false,
  55. applyCompactClass: false
  56. })
  57. },
  58. _defaultOptionsRules: function() {
  59. return this.callBase().concat([{
  60. device: function(_device) {
  61. return "win" === _device.platform && _device.version && 8 === _device.version[0]
  62. },
  63. options: {
  64. showNames: true
  65. }
  66. }, {
  67. device: function(_device2) {
  68. return "desktop" !== _device2.deviceType
  69. },
  70. options: {
  71. applyCompactClass: true
  72. }
  73. }])
  74. },
  75. _render: function() {
  76. this.callBase();
  77. this.$element().addClass(DATEVIEW_CLASS);
  78. this._toggleFormatClasses(this.option("type"));
  79. this._toggleCompactClass()
  80. },
  81. _toggleFormatClasses: function(currentFormat, previousFormat) {
  82. this.$element().addClass(DATEVIEW_CLASS + "-" + currentFormat);
  83. previousFormat && this.$element().removeClass(DATEVIEW_CLASS + "-" + previousFormat)
  84. },
  85. _toggleCompactClass: function() {
  86. this.$element().toggleClass(DATEVIEW_COMPACT_CLASS, this.option("applyCompactClass"))
  87. },
  88. _wrapper: function() {
  89. return this._$wrapper
  90. },
  91. _renderContentImpl: function() {
  92. this._$wrapper = $("<div>").addClass(DATEVIEW_WRAPPER_CLASS);
  93. this._renderRollers();
  94. this._$wrapper.appendTo(this.$element())
  95. },
  96. _renderRollers: function() {
  97. if (!this._$rollersContainer) {
  98. this._$rollersContainer = $("<div>").addClass(DATEVIEW_ROLLER_CONTAINER_CLASS)
  99. }
  100. this._$rollersContainer.empty();
  101. this._createRollerConfigs();
  102. this._rollers = {};
  103. var that = this;
  104. each(that._rollerConfigs, function(name) {
  105. var $roller = $("<div>").appendTo(that._$rollersContainer).addClass(DATEVIEW_ROLLER_CLASS + "-" + that._rollerConfigs[name].type);
  106. that._rollers[that._rollerConfigs[name].type] = that._createComponent($roller, DateViewRoller, {
  107. items: that._rollerConfigs[name].displayItems,
  108. selectedIndex: that._rollerConfigs[name].selectedIndex,
  109. showScrollbar: false,
  110. onStart: function(e) {
  111. var roller = e.component;
  112. roller._toggleActive(true);
  113. that._setActiveRoller(that._rollerConfigs[name], roller.option("selectedIndex"))
  114. },
  115. onEnd: function(e) {
  116. var roller = e.component;
  117. roller._toggleActive(false)
  118. },
  119. onClick: function(e) {
  120. var roller = e.component;
  121. roller._toggleActive(true);
  122. that._setActiveRoller(that._rollerConfigs[name], roller.option("selectedIndex"));
  123. that._setRollerState(that._rollerConfigs[name], roller.option("selectedIndex"));
  124. roller._toggleActive(false)
  125. },
  126. onSelectedIndexChanged: function(e) {
  127. var roller = e.component;
  128. that._setRollerState(that._rollerConfigs[name], roller.option("selectedIndex"))
  129. }
  130. })
  131. });
  132. that._$rollersContainer.appendTo(that._wrapper())
  133. },
  134. _createRollerConfigs: function(type) {
  135. var that = this;
  136. type = type || that.option("type");
  137. that._rollerConfigs = {};
  138. dateLocalization.getFormatParts(uiDateUtils.FORMATS_MAP[type]).forEach(function(partName) {
  139. that._createRollerConfig(partName)
  140. })
  141. },
  142. _createRollerConfig: function(componentName) {
  143. var componentInfo = uiDateUtils.DATE_COMPONENTS_INFO[componentName];
  144. var valueRange = this._calculateRollerConfigValueRange(componentName);
  145. var startValue = valueRange.startValue;
  146. var endValue = valueRange.endValue;
  147. var formatter = componentInfo.formatter;
  148. var showNames = this.option("showNames");
  149. var curDate = this._getCurrentDate();
  150. var config = {
  151. type: componentName,
  152. setValue: componentInfo.setter,
  153. valueItems: [],
  154. displayItems: [],
  155. getIndex: function(value) {
  156. return value[componentInfo.getter]() - startValue
  157. }
  158. };
  159. for (var i = startValue; i <= endValue; i++) {
  160. config.valueItems.push(i);
  161. config.displayItems.push(formatter(i, showNames, curDate))
  162. }
  163. config.selectedIndex = config.getIndex(curDate);
  164. this._rollerConfigs[componentName] = config
  165. },
  166. _setActiveRoller: function(currentRoller) {
  167. var activeRoller = currentRoller && this._rollers[currentRoller.type];
  168. each(this._rollers, function() {
  169. this.toggleActiveState(this === activeRoller)
  170. })
  171. },
  172. _updateRollersPosition: function() {
  173. var that = this;
  174. each(this._rollers, function(type) {
  175. var correctIndex = that._rollerConfigs[type].getIndex(that._getCurrentDate());
  176. this.option("selectedIndex", correctIndex)
  177. })
  178. },
  179. _setRollerState: function(roller, selectedIndex) {
  180. if (selectedIndex !== roller.selectedIndex) {
  181. var rollerValue = roller.valueItems[selectedIndex];
  182. var setValue = roller.setValue;
  183. var currentValue = new Date(this._getCurrentDate());
  184. var currentDate = currentValue.getDate();
  185. var minDate = this.option("minDate");
  186. var maxDate = this.option("maxDate");
  187. if (roller.type === ROLLER_TYPE.month) {
  188. currentDate = Math.min(currentDate, uiDateUtils.getMaxMonthDay(currentValue.getFullYear(), rollerValue))
  189. } else {
  190. if (roller.type === ROLLER_TYPE.year) {
  191. currentDate = Math.min(currentDate, uiDateUtils.getMaxMonthDay(rollerValue, currentValue.getMonth()))
  192. }
  193. }
  194. currentValue.setDate(currentDate);
  195. currentValue[setValue](rollerValue);
  196. var normalizedDate = dateUtils.normalizeDate(currentValue, minDate, maxDate);
  197. currentValue = uiDateUtils.mergeDates(normalizedDate, currentValue, "time");
  198. currentValue = dateUtils.normalizeDate(currentValue, minDate, maxDate);
  199. this.option("value", currentValue);
  200. roller.selectedIndex = selectedIndex
  201. }
  202. if (roller.type === ROLLER_TYPE.year) {
  203. this._refreshRollers()
  204. }
  205. if (roller.type === ROLLER_TYPE.month) {
  206. this._refreshRoller(ROLLER_TYPE.day);
  207. this._refreshRoller(ROLLER_TYPE.hours)
  208. }
  209. },
  210. _refreshRoller: function(rollerType) {
  211. var roller = this._rollers[rollerType];
  212. if (roller) {
  213. this._createRollerConfig(rollerType);
  214. var rollerConfig = this._rollerConfigs[rollerType];
  215. if (rollerType === ROLLER_TYPE.day || rollerConfig.displayItems.toString() !== roller.option("items").toString()) {
  216. roller.option({
  217. items: rollerConfig.displayItems,
  218. selectedIndex: rollerConfig.selectedIndex
  219. })
  220. }
  221. }
  222. },
  223. _getCurrentDate: function() {
  224. var curDate = this._valueOption();
  225. var minDate = this.option("minDate");
  226. var maxDate = this.option("maxDate");
  227. return dateUtils.normalizeDate(curDate, minDate, maxDate)
  228. },
  229. _calculateRollerConfigValueRange: function(componentName) {
  230. var curDate = this._getCurrentDate();
  231. var minDate = this.option("minDate");
  232. var maxDate = this.option("maxDate");
  233. var minYear = dateUtils.sameYear(curDate, minDate);
  234. var minMonth = minYear && curDate.getMonth() === minDate.getMonth();
  235. var maxYear = dateUtils.sameYear(curDate, maxDate);
  236. var maxMonth = maxYear && curDate.getMonth() === maxDate.getMonth();
  237. var minHour = minMonth && curDate.getDate() === minDate.getDate();
  238. var maxHour = maxMonth && curDate.getDate() === maxDate.getDate();
  239. var componentInfo = uiDateUtils.DATE_COMPONENTS_INFO[componentName];
  240. var startValue = componentInfo.startValue;
  241. var endValue = componentInfo.endValue;
  242. if (componentName === ROLLER_TYPE.year) {
  243. startValue = minDate.getFullYear();
  244. endValue = maxDate.getFullYear()
  245. }
  246. if (componentName === ROLLER_TYPE.month) {
  247. if (minYear) {
  248. startValue = minDate.getMonth()
  249. }
  250. if (maxYear) {
  251. endValue = maxDate.getMonth()
  252. }
  253. }
  254. if (componentName === ROLLER_TYPE.day) {
  255. endValue = uiDateUtils.getMaxMonthDay(curDate.getFullYear(), curDate.getMonth());
  256. if (minYear && minMonth) {
  257. startValue = minDate.getDate()
  258. }
  259. if (maxYear && maxMonth) {
  260. endValue = maxDate.getDate()
  261. }
  262. }
  263. if (componentName === ROLLER_TYPE.hours) {
  264. startValue = minHour ? minDate.getHours() : startValue;
  265. endValue = maxHour ? maxDate.getHours() : endValue
  266. }
  267. return {
  268. startValue: startValue,
  269. endValue: endValue
  270. }
  271. },
  272. _refreshRollers: function() {
  273. this._refreshRoller(ROLLER_TYPE.month);
  274. this._refreshRoller(ROLLER_TYPE.day);
  275. this._refreshRoller(ROLLER_TYPE.hours)
  276. },
  277. _optionChanged: function(args) {
  278. switch (args.name) {
  279. case "showNames":
  280. case "minDate":
  281. case "maxDate":
  282. case "type":
  283. this._renderRollers();
  284. this._toggleFormatClasses(args.value, args.previousValue);
  285. break;
  286. case "visible":
  287. this.callBase(args);
  288. if (args.value) {
  289. this._renderRollers()
  290. }
  291. break;
  292. case "value":
  293. this.option("value", this._valueOption());
  294. this._refreshRollers();
  295. this._updateRollersPosition();
  296. break;
  297. default:
  298. this.callBase(args)
  299. }
  300. },
  301. _clean: function() {
  302. this.callBase();
  303. delete this._$rollersContainer
  304. },
  305. _dispose: function() {
  306. clearTimeout(this._deferredRenderDayTimeout);
  307. clearTimeout(this._deferredRenderMonthTimeout);
  308. this.callBase()
  309. }
  310. });
  311. registerComponent("dxDateView", DateView);
  312. module.exports = DateView;