evui 2.0.8 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/dist/{adac9fa4f723f9d2cb5b6640517114a9.png → 0b8d1200e71cae8d747dce4e69c4efb6.png} +0 -0
  2. package/dist/1.css +4 -0
  3. package/dist/1.css.map +1 -0
  4. package/dist/1.evui.min.js +2 -0
  5. package/dist/1.evui.min.js.map +1 -0
  6. package/dist/1ba679c05036b34bf359aa2e6c450faa.ttf +0 -0
  7. package/dist/2.css +4 -0
  8. package/dist/2.css.map +1 -0
  9. package/dist/2.evui.min.js +2 -0
  10. package/dist/2.evui.min.js.map +1 -0
  11. package/dist/{e8c322de9658cbeb8a774b6624167c2c.woff2 → 278156e41e0ad908cf7f841b17130502.woff2} +0 -0
  12. package/dist/3.evui.min.js +2 -0
  13. package/dist/3.evui.min.js.map +1 -0
  14. package/dist/32be89b11725274cd3e801192ba88361.ttf +0 -0
  15. package/dist/{0ab54153eeeca0ce03978cc463b257f7.woff2 → 38c6d8bab26db77d8c806813e1497763.woff2} +0 -0
  16. package/dist/4.evui.min.js +2 -0
  17. package/dist/4.evui.min.js.map +1 -0
  18. package/dist/{faff92145777a3cbaf8e7367b4807987.woff → 425399f81e4ce7cbd967685402ba0260.woff} +0 -0
  19. package/dist/4730076470a665bbc7b783c56d29a72e.svg +261 -0
  20. package/dist/52e9a7f6ff3af5ad261e5292d07ebdca.eot +0 -0
  21. package/dist/{ad97afd3337e8cda302d10ff5a4026b8.ttf → 5367103510b27b78482794590e1ce3b0.ttf} +0 -0
  22. package/dist/{65363c4d55617bbeb57d8ce6dcd46099.svg → 57e963e3d6dd0a9cf05150b40eebf69b.svg} +0 -0
  23. package/dist/{c5ebe0b32dc1b5cc449a76c4204d13bb.ttf → 65a2fb6d9aaa164b41a039302093995b.ttf} +0 -0
  24. package/dist/{cd6c777f1945164224dee082abaea03a.woff2 → 687a4990ea22bb1a49d469a5d9319790.woff2} +0 -0
  25. package/dist/{7583da5c07275cd5eb364507616f998f.ttf → 6c1d906bf5ba48676f65b2d65e935e1a.ttf} +0 -0
  26. package/dist/6dafca5a4f1e31f2bdf11939b24ff422.ttf +0 -0
  27. package/dist/{701ae6abd4719e9c2ada3535a497b341.eot → 752905fa5edf21fc52a10a0c1ca9c7a4.eot} +0 -0
  28. package/dist/76c05d80dda67cdc5d03f345b7bd063f.ttf +0 -0
  29. package/dist/{b551b554a67e86a840bc80cbb8066c30.svg → 7d62eb50e7bb05eedb2a4656f7fe8f3b.svg} +0 -0
  30. package/dist/{8e3c7f5520f5ae906c6cf6d7f3ddcd19.eot → a01e3f2d6c83dc3aee175e2482b3f777.eot} +0 -0
  31. package/dist/{448f2aaa315fa9dce7b2cf6ce31caed6.svg → b30fd8419d7e6d5918856c7531d33482.svg} +0 -0
  32. package/dist/c57dd55fa982e8940f69ca1d69a8a999.woff +0 -0
  33. package/dist/{b87b9ba532ace76ae9f6edfe9f72ded2.ttf → c656b8caa454ed19b9a2ef7f4f5b8fea.ttf} +0 -0
  34. package/dist/{a046592bac8f2fd96e994733faf3858c.woff → cac87dc00c87a5d74711d0276713808a.woff} +0 -0
  35. package/dist/{13db00b7a34fee4d819ab7f9838cc428.eot → d68fa3e67dbb653a13cec44b1bcabcfe.eot} +0 -0
  36. package/dist/{ef60a4f6c25ef7f39f2d25a748dbecfe.woff → ddae9b1ba9b0b42f58809904b0b21349.woff} +0 -0
  37. package/dist/evui.min.js +12 -59485
  38. package/dist/evui.min.js.gz +0 -0
  39. package/dist/evui.min.js.map +1 -1
  40. package/dist/main.css +85 -0
  41. package/dist/main.css.gz +0 -0
  42. package/dist/main.css.map +1 -0
  43. package/package.json +58 -89
  44. package/src/common/emitter.js +20 -0
  45. package/src/common/utils.debounce.js +223 -0
  46. package/src/common/utils.js +51 -17
  47. package/src/common/utils.throttle.js +83 -0
  48. package/src/common/utils.tree.js +18 -0
  49. package/src/components/button/button.vue +316 -241
  50. package/src/components/chart/chart.core.js +699 -0
  51. package/src/components/chart/chart.vue +200 -204
  52. package/src/components/chart/element/element.bar.js +311 -0
  53. package/src/components/chart/element/element.bar.time.js +115 -0
  54. package/src/components/chart/element/element.line.js +288 -0
  55. package/src/components/chart/element/element.pie.js +86 -0
  56. package/src/components/chart/element/element.scatter.js +83 -0
  57. package/src/components/chart/element/element.tip.js +356 -0
  58. package/src/components/chart/helpers/helpers.canvas.js +237 -0
  59. package/src/components/chart/helpers/helpers.constant.js +138 -0
  60. package/src/components/chart/helpers/helpers.util.js +154 -0
  61. package/src/components/chart/index.js +0 -1
  62. package/src/components/chart/model/index.js +4 -0
  63. package/src/components/chart/model/model.series.js +86 -0
  64. package/src/components/chart/model/model.store.js +559 -0
  65. package/src/components/chart/plugins/plugins.interaction.js +324 -0
  66. package/src/components/chart/plugins/plugins.legend.js +589 -0
  67. package/src/components/chart/plugins/plugins.pie.js +179 -0
  68. package/src/components/chart/plugins/plugins.title.js +56 -0
  69. package/src/components/chart/plugins/plugins.tooltip.js +384 -0
  70. package/src/components/chart/scale/scale.js +272 -0
  71. package/src/components/chart/scale/scale.linear.js +30 -0
  72. package/src/components/chart/scale/scale.logarithmic.js +120 -0
  73. package/src/components/chart/scale/scale.step.js +197 -0
  74. package/src/components/chart/scale/scale.time.category.js +204 -0
  75. package/src/components/chart/scale/scale.time.js +40 -0
  76. package/src/components/checkbox/checkbox-group.vue +31 -12
  77. package/src/components/checkbox/checkbox.vue +269 -19
  78. package/src/components/codeview/code.vue +42 -29
  79. package/src/components/contextmenu/contextmenu.child.vue +79 -0
  80. package/src/components/contextmenu/contextmenu.vue +276 -0
  81. package/src/components/contextmenu/contextmenu.wrap.vue +189 -0
  82. package/src/components/contextmenu/index.js +3 -0
  83. package/src/components/datepicker/calendar.core.js +604 -510
  84. package/src/components/datepicker/calendar.vue +0 -3
  85. package/src/components/datepicker/datepicker.vue +73 -14
  86. package/src/components/datepicker/index.js +5 -1
  87. package/src/components/grid/grid.filter.vue +290 -0
  88. package/src/components/grid/grid.filter.window.vue +411 -0
  89. package/src/components/grid/grid.render.vue +45 -0
  90. package/src/components/grid/grid.vue +1338 -0
  91. package/src/components/icon/icon.vue +22 -7
  92. package/src/components/input/input.number.vue +309 -277
  93. package/src/components/label/label.vue +2 -2
  94. package/src/components/loadingmask/loadingmask.vue +52 -63
  95. package/src/components/loginfield/index.js +3 -0
  96. package/src/components/loginfield/loginfield.vue +339 -0
  97. package/src/components/markdown/index.js +3 -0
  98. package/src/components/markdown/markdown.vue +1001 -0
  99. package/src/components/menu/index.js +1 -3
  100. package/src/components/menu/menu.nav.item.vue +115 -0
  101. package/src/components/menu/menu.nav.sub.vue +42 -0
  102. package/src/components/menu/menu.nav.vue +71 -98
  103. package/src/components/message/index.js +3 -0
  104. package/src/components/message/message.js +63 -0
  105. package/src/components/message/message.vue +191 -0
  106. package/src/components/message-box/index.js +3 -0
  107. package/src/components/message-box/message-box.js +31 -0
  108. package/src/components/message-box/message-box.vue +298 -0
  109. package/src/components/notification/index.js +3 -0
  110. package/src/components/notification/notification.js +75 -0
  111. package/src/components/notification/notification.vue +242 -0
  112. package/src/components/radio/radio-group.vue +12 -2
  113. package/src/components/radio/radio.vue +186 -25
  114. package/src/components/selectbox/dropdown.vue +96 -39
  115. package/src/components/selectbox/listbox.vue +68 -29
  116. package/src/components/selectbox/option.vue +1 -1
  117. package/src/components/selectbox/selectbox.vue +445 -245
  118. package/src/components/slider/slider-tooltip.vue +7 -7
  119. package/src/components/slider/slider.vue +20 -25
  120. package/src/components/splitter/index.js +3 -0
  121. package/src/components/splitter/splitter.vue +294 -0
  122. package/src/components/table/table.black.css +1 -1
  123. package/src/components/table/table.filter.lite.vue +8 -8
  124. package/src/components/table/table.filter.vue +1 -1
  125. package/src/components/table/table.grey.css +5 -6
  126. package/src/components/table/table.navy.css +1 -1
  127. package/src/components/table/table.vue +60 -55
  128. package/src/components/tabs/tab-panel.vue +19 -5
  129. package/src/components/tabs/tabs.vue +182 -87
  130. package/src/components/textfield/textfield.vue +140 -80
  131. package/src/components/timepicker/index.js +2 -2
  132. package/src/components/timepicker/spinner.vue +15 -17
  133. package/src/components/timepicker/timepicker.vue +98 -53
  134. package/src/components/toggle/toggle.vue +206 -158
  135. package/src/components/tree/index.js +2 -6
  136. package/src/components/tree/render.js +17 -0
  137. package/src/components/tree/tree-node.vue +214 -0
  138. package/src/components/tree/tree.vue +296 -0
  139. package/src/components/tree-table/index.js +7 -0
  140. package/src/components/{tree → tree-table}/tree.table.black.css +0 -0
  141. package/src/components/{tree → tree-table}/tree.table.grey.css +12 -12
  142. package/src/components/{tree → tree-table}/tree.table.vue +151 -95
  143. package/src/components/tree-table/tree.util.js +119 -0
  144. package/src/components/window/window.vue +238 -183
  145. package/src/index.js +29 -12
  146. package/src/styles/base/base.scss +50 -0
  147. package/src/styles/base/index.scss +1 -0
  148. package/src/styles/default.scss +5 -0
  149. package/src/styles/{codemirror.css → lib/codemirror.css} +0 -0
  150. package/src/styles/{all.css → lib/fontawesome.css} +1 -1
  151. package/src/styles/lib/icon.css +792 -0
  152. package/src/styles/themes/index.scss +2 -0
  153. package/src/styles/themes/mixin.scss +33 -0
  154. package/src/styles/themes/variables.scss +206 -0
  155. package/src/styles/utils/colors.scss +222 -0
  156. package/src/styles/utils/index.scss +2 -0
  157. package/src/styles/utils/mixins.scss +34 -0
  158. package/src/styles/utils/variables.scss +27 -0
  159. package/src/webfonts/EVUI.eot +0 -0
  160. package/src/webfonts/EVUI.svg +251 -173
  161. package/src/webfonts/EVUI.ttf +0 -0
  162. package/src/webfonts/EVUI.woff +0 -0
  163. package/src/webfonts/Roboto-Bold.ttf +0 -0
  164. package/src/webfonts/Roboto-Medium.ttf +0 -0
  165. package/src/webfonts/Roboto-Regular.ttf +0 -0
  166. package/dist/3c9453211570a4ede66a4b4954a32bbb.ttf +0 -0
  167. package/dist/8634884f932627fc43782e6963b64ccd.svg +0 -183
  168. package/dist/b9e64d9b5fa6b500eb5df6fa980d3e5b.eot +0 -0
  169. package/dist/f0ac0c8b3c9cd3ef9002749985ae546f.woff +0 -0
  170. package/src/components/chart/charts/chart.bar.js +0 -334
  171. package/src/components/chart/charts/chart.base.js +0 -1075
  172. package/src/components/chart/charts/chart.line.js +0 -262
  173. package/src/components/chart/charts/chart.pie.js +0 -383
  174. package/src/components/chart/charts/chart.scatter.js +0 -349
  175. package/src/components/chart/charts/chart.sunburst.js +0 -193
  176. package/src/components/chart/core/axis/axis.js +0 -217
  177. package/src/components/chart/core/axis/axis.scale.auto.js +0 -69
  178. package/src/components/chart/core/axis/axis.scale.fixed.js +0 -65
  179. package/src/components/chart/core/axis/axis.scale.steps.js +0 -149
  180. package/src/components/chart/core/core.constant.js +0 -91
  181. package/src/components/chart/core/core.legend.js +0 -473
  182. package/src/components/chart/core/core.util.js +0 -66
  183. package/src/components/chart/core/data/data.js +0 -412
  184. package/src/components/chart/core/data/data.pie.js +0 -70
  185. package/src/components/chart/core/data/data.stack.js +0 -222
  186. package/src/components/chart/core/data/data.sunburst.js +0 -172
  187. package/src/components/menu/menu.context.children.vue +0 -201
  188. package/src/components/menu/menu.context.vue +0 -144
  189. package/src/components/tabs/jun/tab.vue +0 -123
  190. package/src/components/tabs/jun/tabs.vue +0 -484
  191. package/src/components/tree/tree.util.js +0 -39
  192. package/src/styles/evui.css +0 -386
  193. package/src/styles/icon.css +0 -557
@@ -5,33 +5,64 @@
5
5
  consistent-return:
6
6
  ["error", { "treatUndefinedAsUnspecified": true }]
7
7
  */
8
- import _ from 'lodash';
8
+ import { merge, remove } from 'lodash-es';
9
9
 
10
10
  class Calendar {
11
11
  constructor(target, options) {
12
12
  const today = new Date();
13
13
  const obj = {
14
14
  // default width, height(onePage)
15
- width: 235,
16
- height: 220,
15
+ width: 224,
16
+ height: 222,
17
17
  // style
18
18
  colors: {
19
- background: '#fff',
20
- border: 'f0f0f0',
21
- thisMonthFont: '#202020',
22
- thisMonthFill: '#f5f5f5',
23
- prevNextMonthFont: '#ccc',
24
- prevNextMonthFill: '#fff',
25
- selectDayFill: 'rgba(0, 255, 0, 0.1)',
26
- mousemoveDayFill: 'rgba(255, 0, 0, 0.1)',
19
+ light: {
20
+ background: '#FFFFFF',
21
+ border: '#CFCFCF',
22
+ thisMonthFont: '#202020',
23
+ thisMonthFill: '#F5F5F5',
24
+ yearMonthColor: '#505050',
25
+ prevNextMonthFont: '#CCCCCC',
26
+ prevNextMonthFill: '#FFFFFF',
27
+ selectDayFill: 'rgba(0, 255, 0, 0.3)',
28
+ mousemoveDayFill: 'rgba(255, 0, 0, 0.3)',
29
+ triangle: '#B2B2B2',
30
+ weekColor: '#000000',
31
+ dayColor: '#000000',
32
+ timeLabelFont: '#989898',
33
+ timeLabelFill: '#E5E5E5',
34
+ timeLabelStroke: '#CFCFCF',
35
+ timeAreaFill: '#E5E5E5',
36
+ selectDay: '#FFFFFF',
37
+ },
38
+ dark: {
39
+ background: '#191919',
40
+ border: '#333333',
41
+ thisMonthFont: '#FFFFFF',
42
+ thisMonthFill: '#333333',
43
+ yearMonthColor: '#FFFFFF',
44
+ prevNextMonthFont: '#999999',
45
+ prevNextMonthFill: '#191919',
46
+ selectDayFill: 'rgba(0, 255, 0, 0.3)',
47
+ mousemoveDayFill: 'rgba(255, 0, 0, 0.3)',
48
+ triangle: '#666666',
49
+ weekColor: '#FFFFFF',
50
+ dayColor: '#FFFFFF',
51
+ timeLabelFont: '#666666',
52
+ timeLabelFill: '#262626',
53
+ timeLabelStroke: '#CFCFCF',
54
+ timeAreaFill: '#191919',
55
+ selectDay: '#000000',
56
+ },
27
57
  },
28
- font: 'bold 12px sans-serif',
58
+ font: 'bold 12px Roboto',
29
59
  padding: {
30
- top: 5,
31
- right: 5,
32
- bottom: 5,
33
- left: 5,
60
+ top: 1,
61
+ right: 1,
62
+ bottom: 1,
63
+ left: 1,
34
64
  },
65
+ theme: 'light',
35
66
 
36
67
  // 캔버스만 화면에 보여줄 경우 false (ref. datepicker-default.vue)
37
68
  // input text에 연계하여 드랍다운으로 보여줄 경우 true (ref. datepicker.vue)
@@ -56,8 +87,8 @@ class Calendar {
56
87
 
57
88
  // init parameter
58
89
  pickerArea: {
59
- triangleLength: 15,
60
- height: 25,
90
+ triangleLength: 10,
91
+ height: 35,
61
92
  },
62
93
  calendarArea: {
63
94
  },
@@ -72,7 +103,7 @@ class Calendar {
72
103
  // timeArea안에 hour, min, sec가 한 페이지에 몇 row * column으로 구성되는지
73
104
  columnCount: 6,
74
105
  rowCount: 2,
75
- triangleLength: 13,
106
+ triangleLength: 10,
76
107
  },
77
108
 
78
109
  // canvas context style
@@ -99,7 +130,7 @@ class Calendar {
99
130
  bottom: 0,
100
131
  left: 0,
101
132
  },
102
- font: '10px Roboto Condensed',
133
+ font: '12px Roboto',
103
134
  },
104
135
  // selectable: true, // 선택 가능 여부 (이번달 & 오늘 전까지)
105
136
 
@@ -121,9 +152,9 @@ class Calendar {
121
152
  timeTypeName: ['hour', 'minute', 'second'],
122
153
  titleType: {
123
154
  // 'fullName', 'numberName', 'abbrName' 중 선택
124
- month: 'fullName',
155
+ month: 'abbrName',
125
156
  // 'abbrUpperName', 'abbrLowerName' 중 선택
126
- dayOfTheWeek: 'abbrUpperName',
157
+ dayOfTheWeek: 'abbrLowerName',
127
158
  },
128
159
 
129
160
  // left : datepicker[default], right: timepicker - expand show?
@@ -134,12 +165,16 @@ class Calendar {
134
165
  };
135
166
 
136
167
  // parameter mapping
137
- this.options = _.merge({}, obj, options);
168
+ this.options = merge({}, obj, options);
138
169
 
139
170
  // create & init canvas
140
171
  this.dropdown = document.createElement('div');
141
172
  this.dropdown.setAttribute('class', 'ev-calendar-dropdown');
142
- this.dropdown.setAttribute('style', 'position: absolute; display: none; z-index: 1; background: #ffffff');
173
+ const bgColor = this.options.colors[this.options.theme].background;
174
+ this.dropdown.setAttribute('style', `position: absolute; display: none;
175
+ z-index: 850; background: ${bgColor}; border-radius: 4px;
176
+ box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.27); border: 0.5px solid #B2B2B2;
177
+ box-sizing: border-box;`);
143
178
  this.baseCanvas = document.createElement('canvas');
144
179
  this.baseCanvas.setAttribute('class', 'ev-calendar-canvas');
145
180
  this.context = this.baseCanvas.getContext('2d');
@@ -215,27 +250,12 @@ class Calendar {
215
250
  }
216
251
  }
217
252
 
218
- removeDropdown() {
219
- document.body.removeChild(this.dropdown);
220
- }
221
- showDropdown(e) {
222
- this.dropdown.style.display = 'block';
223
- let targetDivHeight = 0;
224
- if (e.currentTarget && e.currentTarget.clientHeight) {
225
- targetDivHeight = e.currentTarget.clientHeight;
226
- }
227
- this.dropdown.style.top = `${(e.pageY - e.layerY) + targetDivHeight}px`;
228
- this.dropdown.style.left = `${e.pageX - e.layerX}px`;
229
- }
230
- hideDropdown() {
231
- this.dropdown.style.display = 'none';
232
- }
233
-
234
253
  init() {
235
254
  this.initOptionsProperty();
236
255
  this.initCalendarProperty();
237
256
  this.initCanvasProperty();
238
257
  }
258
+
239
259
  initOptionsProperty() {
240
260
  if (this.options.initSelectDayFlag
241
261
  && this.options.selectDayType === 'day'
@@ -244,30 +264,30 @@ class Calendar {
244
264
  if (!this.options.timeExpand) {
245
265
  this.options.initSelectDay = this.options.initSelectDay.setHours(0, 0, 0, 0);
246
266
  } else {
247
- this.coordinate.timeArea.hour.select = this.options.initSelectDay.getHours();
248
- this.coordinate.timeArea.minute.select = this.options.initSelectDay.getMinutes();
249
- this.coordinate.timeArea.second.select = this.options.initSelectDay.getSeconds();
250
- this.coordinate.timeArea.hour.page
251
- = Math.floor(this.coordinate.timeArea.hour.select / 12) + 1;
252
- this.coordinate.timeArea.minute.page
253
- = Math.floor(this.coordinate.timeArea.minute.select / 12) + 1;
254
- this.coordinate.timeArea.second.page
255
- = Math.floor(this.coordinate.timeArea.second.select / 12) + 1;
267
+ const timeArea = this.coordinate.timeArea;
268
+ timeArea.hour.select = this.options.initSelectDay.getHours();
269
+ timeArea.minute.select = this.options.initSelectDay.getMinutes();
270
+ timeArea.second.select = this.options.initSelectDay.getSeconds();
271
+ timeArea.hour.page = Math.floor(timeArea.hour.select / 12) + 1;
272
+ timeArea.minute.page = Math.floor(timeArea.minute.select / 12) + 1;
273
+ timeArea.second.page = Math.floor(timeArea.second.select / 12) + 1;
256
274
  }
257
275
  const initSelectDay = new Date(this.options.initSelectDay);
276
+ const year = initSelectDay.getFullYear();
277
+ const month = initSelectDay.getMonth();
258
278
  const obj = {
259
- year: initSelectDay.getFullYear(),
260
- month: initSelectDay.getMonth() + 1,
279
+ year,
280
+ month: month + 1,
261
281
  day: initSelectDay.getDate(),
262
282
  };
263
283
  this.coordinate.calendarArea.selectDayArr.push(obj);
264
- this.options.currentYearMonth =
265
- new Date(initSelectDay.getFullYear(), initSelectDay.getMonth(), 1);
284
+ this.options.currentYearMonth = new Date(year, month, 1);
266
285
  }
267
286
  if (this.options.initLimitDay) {
268
287
  this.options.initLimitDay = this.options.initLimitDay.setHours(0, 0, 0, 0);
269
288
  }
270
289
  }
290
+
271
291
  initCanvasProperty() {
272
292
  // set total width, height 1
273
293
  if (this.options.width && this.options.height) {
@@ -295,9 +315,10 @@ class Calendar {
295
315
  startY: padding.top,
296
316
  height: pickerAreaHeight,
297
317
  };
318
+ const caPaddingLR = 10; // calendar area padding l/r
298
319
  this.coordinate.calendarArea.total = {
299
- startX: padding.left,
300
- width: commonAreaTotalWidth - 1,
320
+ startX: padding.left + caPaddingLR,
321
+ width: commonAreaTotalWidth - (caPaddingLR * 2) - 1,
301
322
  startY: +padding.top + +pickerAreaHeight,
302
323
  height: this.baseCanvas.height - pickerAreaHeight - padding.top - padding.bottom,
303
324
  };
@@ -335,13 +356,16 @@ class Calendar {
335
356
  });
336
357
  }
337
358
  }
359
+
338
360
  initCalendarProperty() {
339
361
  // 이번달 thisMonth월
340
362
  const thisMonth = this.options.currentYearMonth.getMonth() + 1;
363
+ // 이번 년도
364
+ const thisYear = this.options.currentYearMonth.getFullYear();
341
365
  // 저번달 마지막 날짜
342
- this.prevMonthLastDate = +this.getLastDayOfMonth(thisMonth - 1);
366
+ this.prevMonthLastDate = +this.getLastDayOfMonth(thisMonth - 1, thisYear);
343
367
  // 이번달 마지막 날짜
344
- this.thisMonthLastDate = +this.getLastDayOfMonth(thisMonth);
368
+ this.thisMonthLastDate = +this.getLastDayOfMonth(thisMonth, thisYear);
345
369
  // 이번달 첫번째 요일(sun : 0, sat : 6) & 해당 달력에서 선택된 달의 1일까지의 공백 before 일수
346
370
  this.thisMonthFirstDay = +this.options.currentYearMonth.getDay();
347
371
  // 이번달의 주 개수 (4주 ~ 6주)
@@ -350,132 +374,134 @@ class Calendar {
350
374
  }
351
375
 
352
376
  mouseInit() {
377
+ this.mousemove = this.onMousemove.bind(this);
378
+ this.mousedown = this.onMousedown.bind(this);
379
+ this.mouseleave = this.onMouseleave.bind(this);
380
+ this.mousewheel = this.onMousewheel.bind(this);
353
381
  this.initMouseclick();
354
382
  this.initMousemove();
355
383
  this.initMouseleave();
356
384
  this.initMousewheel();
357
385
  }
386
+
358
387
  initMousemove() {
359
- this.overCanvas.addEventListener('mousemove', (e) => {
360
- e.preventDefault();
361
- // init value
362
- const overCtx = this.overCtx;
363
- let mouseoverFlag = false;
364
-
365
- // mousemove on day box in calendar area
366
- // e.offsetX의 너비에 + this.options.timeArea.titleWidth를 하는 이유는 calendarArea에서 마우스가
367
- // 우측 title범위로 벗어나는 경우에 clear해주기 위함
368
- const calendarAreaTotal = this.coordinate.calendarArea.total;
369
- if (e.offsetX > calendarAreaTotal.startX
370
- && e.offsetX < calendarAreaTotal.startX + calendarAreaTotal.width
371
- + this.options.timeArea.titleWidth
372
- && e.offsetY > calendarAreaTotal.startY
373
- && e.offsetY < calendarAreaTotal.startY + calendarAreaTotal.height) {
374
- this.clearCanvas(overCtx,
375
- calendarAreaTotal.startX, calendarAreaTotal.startY,
376
- calendarAreaTotal.width, calendarAreaTotal.height,
377
- );
378
- this.mousemoveDate(e);
379
- mouseoverFlag = true;
380
- }
388
+ this.overCanvas.addEventListener('mousemove', this.mousemove);
389
+ }
381
390
 
382
- // mousemove on hour, minute, second box
383
- const timeTypeName = this.options.timeTypeName;
384
- const timeAreaTotal = this.coordinate.timeArea.total;
385
- const localeType = this.options.localeType;
386
- let condition = true;
387
- if (e.offsetX > timeAreaTotal.startX
388
- && e.offsetX < timeAreaTotal.startX + timeAreaTotal.width
389
- && e.offsetY > timeAreaTotal.startY
390
- && e.offsetY < timeAreaTotal.startY + timeAreaTotal.height
391
- ) {
392
- this.clearCanvas(overCtx,
393
- timeAreaTotal.startX, timeAreaTotal.startY,
394
- timeAreaTotal.width, timeAreaTotal.height,
395
- );
396
- timeTypeName.forEach((type) => {
397
- if (localeType === 'YYYY-MM-DD HH:mm:ss') {
398
- condition = type === 'hour' || type === 'minute' || type === 'second';
399
- } else if (localeType === 'YYYY-MM-DD HH:mm') {
400
- condition = type === 'hour' || type === 'minute';
401
- } else if (localeType === 'YYYY-MM-DD HH') {
402
- condition = type === 'hour';
403
- } else if (localeType === 'YYYY-MM-DD') {
404
- condition = false;
405
- }
406
- if (condition) {
407
- const timeAreaType = this.coordinate.timeArea[type];
408
- timeAreaType.data.forEach((v, idx) => {
409
- if (timeAreaType.page === v.page) {
410
- if (e.offsetY > v.startY && e.offsetY < v.startY + v.height
411
- && e.offsetX > v.startX && e.offsetX < v.startX + v.width) {
412
- this.dynamicDraw(
413
- overCtx, v.startX, v.startY,
414
- v.width, v.height,
415
- {
416
- fill: {
417
- show: true,
418
- color: this.options.colors.mousemoveDayFill,
419
- },
420
- },
421
- );
422
- mouseoverFlag = true;
423
- }
424
- if (timeAreaType.select === idx) {
425
- this.dynamicDraw(
426
- overCtx, v.startX, v.startY,
427
- v.width, v.height, {
428
- fill: {
429
- show: true,
430
- color: this.options.colors.selectDayFill,
431
- },
432
- },
433
- );
434
- }
391
+ onMousemove(e) {
392
+ e.preventDefault();
393
+ // init value
394
+ const overCtx = this.overCtx;
395
+ let mouseoverFlag = false;
396
+
397
+ // mousemove on day box in calendar area
398
+ // e.offsetX의 너비에 + this.options.timeArea.titleWidth를 하는 이유는 calendarArea에서 마우스가
399
+ // 우측 title범위로 벗어나는 경우에 clear해주기 위함
400
+ const calendarAreaTotal = this.coordinate.calendarArea.total;
401
+ if (e.offsetX > calendarAreaTotal.startX
402
+ && e.offsetX < calendarAreaTotal.startX + calendarAreaTotal.width
403
+ + this.options.timeArea.titleWidth
404
+ && e.offsetY > calendarAreaTotal.startY
405
+ && e.offsetY < calendarAreaTotal.startY + calendarAreaTotal.height) {
406
+ this.clearCanvas(overCtx,
407
+ calendarAreaTotal.startX, calendarAreaTotal.startY,
408
+ calendarAreaTotal.width, calendarAreaTotal.height,
409
+ );
410
+ this.mousemoveDate(e);
411
+ mouseoverFlag = true;
412
+ }
413
+
414
+ // mousemove on hour, minute, second box
415
+ const timeTypeName = this.options.timeTypeName;
416
+ const timeAreaTotal = this.coordinate.timeArea.total;
417
+ const localeType = this.options.localeType;
418
+ let condition = true;
419
+ if (e.offsetX > timeAreaTotal.startX
420
+ && e.offsetX < timeAreaTotal.startX + timeAreaTotal.width
421
+ && e.offsetY > timeAreaTotal.startY
422
+ && e.offsetY < timeAreaTotal.startY + timeAreaTotal.height
423
+ ) {
424
+ this.clearCanvas(overCtx,
425
+ timeAreaTotal.startX, timeAreaTotal.startY,
426
+ timeAreaTotal.width, timeAreaTotal.height,
427
+ );
428
+ timeTypeName.forEach((type) => {
429
+ if (localeType === 'YYYY-MM-DD HH:mm:ss') {
430
+ condition = type === 'hour' || type === 'minute' || type === 'second';
431
+ } else if (localeType === 'YYYY-MM-DD HH:mm') {
432
+ condition = type === 'hour' || type === 'minute';
433
+ } else if (localeType === 'YYYY-MM-DD HH') {
434
+ condition = type === 'hour';
435
+ } else if (localeType === 'YYYY-MM-DD') {
436
+ condition = false;
437
+ }
438
+ if (condition) {
439
+ const timeAreaType = this.coordinate.timeArea[type];
440
+ timeAreaType.data.forEach((v, idx) => {
441
+ if (timeAreaType.page === v.page) {
442
+ if (e.offsetY > v.startY && e.offsetY < v.startY + v.height
443
+ && e.offsetX > v.startX && e.offsetX < v.startX + v.width) {
444
+ overCtx.beginPath();
445
+ const cx = v.startX + (v.width / 2);
446
+ const cy = v.startY + (v.height / 2);
447
+ const r = (v.width < v.height) ? (v.width / 2) : (v.height / 2);
448
+ overCtx.arc(cx, cy, r, 0, Math.PI * 2, true);
449
+ overCtx.fillStyle = this.options.colors[this.options.theme].mousemoveDayFill;
450
+ overCtx.fill();
451
+ mouseoverFlag = true;
435
452
  }
436
- });
437
- } else {
438
- this.updateTimeArea(type);
439
- }
440
- });
453
+ if (timeAreaType.select === idx) {
454
+ overCtx.beginPath();
455
+ const cx = v.startX + (v.width / 2);
456
+ const cy = v.startY + (v.height / 2);
457
+ const r = (v.width < v.height) ? (v.width / 2) : (v.height / 2);
458
+ overCtx.arc(cx, cy, r, 0, Math.PI * 2, true);
459
+ overCtx.fillStyle = this.options.colors[this.options.theme].selectDayFill;
460
+ overCtx.fill();
461
+ }
462
+ }
463
+ });
464
+ } else {
465
+ this.updateTimeArea(type);
466
+ }
467
+ });
468
+ }
469
+
470
+ // mousemove on triangle in picker area (month)
471
+ const pickerAreaArrow = this.coordinate.pickerArea.arrow;
472
+ const pickerAreaOption = this.options.pickerArea;
473
+ let pickerAreaArrowOver = false;
474
+ pickerAreaArrow.forEach((v, idx) => {
475
+ pickerAreaArrowOver = this.existTriangle(
476
+ pickerAreaArrow[idx].centerX, pickerAreaArrow[idx].centerY,
477
+ v.direction, pickerAreaOption.triangleLength, e.offsetX, e.offsetY,
478
+ );
479
+ if (pickerAreaArrowOver) {
480
+ mouseoverFlag = true;
441
481
  }
482
+ });
442
483
 
443
- // mousemove on triangle in picker area (month)
444
- const pickerAreaArrow = this.coordinate.pickerArea.arrow;
445
- const pickerAreaOption = this.options.pickerArea;
446
- let pickerAreaArrowOver = false;
447
- pickerAreaArrow.forEach((v, idx) => {
448
- pickerAreaArrowOver = this.existTriangle(
449
- pickerAreaArrow[idx].centerX, pickerAreaArrow[idx].centerY,
450
- v.direction, pickerAreaOption.triangleLength, e.offsetX, e.offsetY,
484
+ // mousemove on triangle in time area (HMS)
485
+ const timeAreaOption = this.options.timeArea;
486
+ let timeAreaArrowOver = false;
487
+ this.options.timeTypeName.forEach((type) => {
488
+ const timeAreaTypeArrow = this.coordinate.timeArea[type].arrow;
489
+ timeAreaTypeArrow.forEach((v, idx) => {
490
+ timeAreaArrowOver = this.existTriangle(
491
+ timeAreaTypeArrow[idx].centerX, timeAreaTypeArrow[idx].centerY,
492
+ v.direction, timeAreaOption.triangleLength, e.offsetX, e.offsetY,
451
493
  );
452
- if (pickerAreaArrowOver) {
494
+ if (timeAreaArrowOver) {
453
495
  mouseoverFlag = true;
454
496
  }
455
497
  });
456
-
457
- // mousemove on triangle in time area (HMS)
458
- const timeAreaOption = this.options.timeArea;
459
- let timeAreaArrowOver = false;
460
- this.options.timeTypeName.forEach((type) => {
461
- const timeAreaTypeArrow = this.coordinate.timeArea[type].arrow;
462
- timeAreaTypeArrow.forEach((v, idx) => {
463
- timeAreaArrowOver = this.existTriangle(
464
- timeAreaTypeArrow[idx].centerX, timeAreaTypeArrow[idx].centerY,
465
- v.direction, timeAreaOption.triangleLength, e.offsetX, e.offsetY,
466
- );
467
- if (timeAreaArrowOver) {
468
- mouseoverFlag = true;
469
- }
470
- });
471
- });
472
-
473
- if (mouseoverFlag) {
474
- this.overCanvas.style.cursor = 'pointer';
475
- } else {
476
- this.overCanvas.style.cursor = 'default';
477
- }
478
498
  });
499
+
500
+ if (mouseoverFlag) {
501
+ this.overCanvas.style.cursor = 'pointer';
502
+ } else {
503
+ this.overCanvas.style.cursor = 'default';
504
+ }
479
505
  }
480
506
 
481
507
  mouseclickDate(e) {
@@ -495,24 +521,22 @@ class Calendar {
495
521
  && e.offsetY > v.startY
496
522
  && e.offsetY < v.startY + v.height) {
497
523
  // // 오늘 이후 비활성화 시 return false
498
- // if (this.options.limitToday) {
499
- // const mouseoverDay = new Date(v.date.year, v.date.month - 1, v.date.day);
500
- // const initLimitDay = new Date(this.options.initLimitDay);
501
- // // 선택된 날(default:오늘)의 요일 (일 : 0, 토 : 6)
502
- // const initSelectGetDay = initLimitDay.getDay();
503
- // // 선택된 날의 첫번째 일요일(선택된 날 기준 첫 날)
504
- // const initSelectSunday = new Date();
505
- // initSelectSunday.setDate(initLimitDay.getDate() - initSelectGetDay);
506
- // initSelectSunday.setHours(0, 0, 0, 0);
507
- // // 선택된 날(default:오늘)보다 크거나 선택된 날의 일요일 ~ 선택된 날 사이의 날짜인 경우 false
508
- // if (initLimitDay < mouseoverDay) {
509
- // return undefined;
510
- // } else if (initSelectSunday <= mouseoverDay && mouseoverDay <= initLimitDay) {
511
- // if (this.options.selectDayType === 'weekday') {
512
- // // 개발 필요
513
- // }
514
- // }
515
- // }
524
+ if (this.options.limitToday) {
525
+ if (this.options.selectDayType === 'day') {
526
+ const mouseoverDay = new Date(v.date.year, v.date.month - 1, v.date.day);
527
+ const initLimitDay = new Date(this.options.initLimitDay);
528
+ // 선택된 날(default:오늘)의 요일 (일 : 0, 토 : 6)
529
+ const initSelectGetDay = initLimitDay.getDay();
530
+ // 선택된 날의 첫번째 일요일(선택된 날 기준 첫 날)
531
+ const initSelectSunday = new Date();
532
+ initSelectSunday.setDate(initLimitDay.getDate() - initSelectGetDay);
533
+ initSelectSunday.setHours(0, 0, 0, 0);
534
+ // 선택된 날(default:오늘)보다 크거나 선택된 날의 일요일 ~ 선택된 날 사이의 날짜인 경우 false
535
+ if (initLimitDay < mouseoverDay) {
536
+ return undefined;
537
+ }
538
+ }
539
+ }
516
540
  // selectDayType에 따라 선택
517
541
  if (this.options.selectDayType === 'weekday') {
518
542
  // 1주평일(5일)
@@ -541,7 +565,7 @@ class Calendar {
541
565
  }
542
566
  }
543
567
  if (exist) {
544
- _.remove(selectDayArr, date);
568
+ remove(selectDayArr, date);
545
569
  } else {
546
570
  selectDayArr.push(date);
547
571
  }
@@ -567,7 +591,7 @@ class Calendar {
567
591
  }
568
592
  }
569
593
  if (exist) {
570
- _.remove(selectDayArr, date);
594
+ remove(selectDayArr, date);
571
595
  } else {
572
596
  selectDayArr.push(date);
573
597
  }
@@ -590,7 +614,7 @@ class Calendar {
590
614
  }
591
615
  }
592
616
  if (exist) {
593
- _.remove(selectDayArr, date);
617
+ remove(selectDayArr, date);
594
618
  } else {
595
619
  selectDayArr.push(date);
596
620
  }
@@ -625,16 +649,13 @@ class Calendar {
625
649
  timeAreaType.data.forEach((v, idx) => {
626
650
  if (timeAreaType.page === v.page
627
651
  && timeAreaType.select === idx) {
628
- this.dynamicDraw(
629
- overCtx, v.startX, v.startY,
630
- v.width, v.height,
631
- {
632
- fill: {
633
- show: true,
634
- color: this.options.colors.selectDayFill,
635
- },
636
- },
637
- );
652
+ overCtx.beginPath();
653
+ const cx = v.startX + (v.width / 2);
654
+ const cy = v.startY + (v.height / 2);
655
+ const r = (v.width < v.height) ? (v.width / 2) : (v.height / 2);
656
+ overCtx.arc(cx, cy, r, 0, Math.PI * 2, true);
657
+ overCtx.fillStyle = this.options.colors[this.options.theme].selectDayFill;
658
+ overCtx.fill();
638
659
  }
639
660
  });
640
661
  }
@@ -642,116 +663,121 @@ class Calendar {
642
663
  }
643
664
 
644
665
  initMouseclick() {
645
- this.overCanvas.addEventListener('mousedown', (e) => {
646
- e.preventDefault();
647
- const pickerAreaTotal = this.coordinate.pickerArea.total;
648
- const calendarAreaTotal = this.coordinate.calendarArea.total;
666
+ this.overCanvas.addEventListener('mousedown', this.mousedown);
667
+ }
649
668
 
650
- // CLICK triangle in picker area (LEFT, RIGHT)
651
- if (e.offsetX > pickerAreaTotal.startX
652
- && e.offsetX < pickerAreaTotal.startX + pickerAreaTotal.width
653
- && e.offsetY > pickerAreaTotal.startY
654
- && e.offsetY < pickerAreaTotal.startY + pickerAreaTotal.height) {
655
- const pickerAreaArrow = this.coordinate.pickerArea.arrow;
656
- const pickerAreaOption = this.options.pickerArea;
657
- const currDate = this.options.currentYearMonth;
669
+ onMousedown(e) {
670
+ e.preventDefault();
671
+ const pickerAreaTotal = this.coordinate.pickerArea.total;
672
+ const calendarAreaTotal = this.coordinate.calendarArea.total;
673
+
674
+ // CLICK triangle in picker area (LEFT, RIGHT)
675
+ if (e.offsetX > pickerAreaTotal.startX
676
+ && e.offsetX < pickerAreaTotal.startX + pickerAreaTotal.width
677
+ && e.offsetY > pickerAreaTotal.startY
678
+ && e.offsetY < pickerAreaTotal.startY + pickerAreaTotal.height) {
679
+ const pickerAreaArrow = this.coordinate.pickerArea.arrow;
680
+ const pickerAreaOption = this.options.pickerArea;
681
+ const currDate = this.options.currentYearMonth;
682
+ let exist = false;
683
+ pickerAreaArrow.forEach((v, idx) => {
684
+ exist = this.existTriangle(
685
+ pickerAreaArrow[idx].centerX, pickerAreaArrow[idx].centerY,
686
+ v.direction, pickerAreaOption.triangleLength, e.offsetX, e.offsetY,
687
+ );
688
+ if (exist) {
689
+ const year = currDate.getFullYear();
690
+ const month = currDate.getMonth();
691
+
692
+ if (v.direction === 'left') {
693
+ this.options.currentYearMonth = new Date(year, month - 1, 1);
694
+ } else if (v.direction === 'right') {
695
+ this.options.currentYearMonth = new Date(year, +month + +1, 1);
696
+ }
697
+ this.initCalendarProperty();
698
+ this.drawPickerArea();
699
+ this.drawCalendarDay();
700
+ this.clearCalendarArea();
701
+ this.mousemoveDate();
702
+ }
703
+ });
704
+ }
705
+
706
+ // CLICK Date logic
707
+ if (e.offsetX > calendarAreaTotal.startX
708
+ && e.offsetX < calendarAreaTotal.startX + calendarAreaTotal.width
709
+ && e.offsetY > calendarAreaTotal.startY
710
+ && e.offsetY < calendarAreaTotal.startY + calendarAreaTotal.height) {
711
+ this.mouseclickDate(e);
712
+ }
713
+
714
+ // CLICK triangle in time area (TOP, BOTTOM)
715
+ const timePageWidth = this.options.timeArea.pageWidth;
716
+ const timeAreaOption = this.options.timeArea;
717
+ const timeTypeName = this.options.timeTypeName;
718
+ timeTypeName.forEach((type) => {
719
+ const timeAreaType = this.coordinate.timeArea[type];
720
+ const timeAreaTypeTotal = timeAreaType.total;
721
+ if (e.offsetX > timeAreaTypeTotal.startX + timeAreaTypeTotal.width
722
+ && e.offsetX < (timeAreaTypeTotal.startX + timeAreaTypeTotal.width) + timePageWidth
723
+ && e.offsetY > timeAreaTypeTotal.startY
724
+ && e.offsetY < timeAreaTypeTotal.startY + timeAreaTypeTotal.height
725
+ ) {
658
726
  let exist = false;
659
- pickerAreaArrow.forEach((v, idx) => {
727
+ timeAreaType.arrow.forEach((v) => {
660
728
  exist = this.existTriangle(
661
- pickerAreaArrow[idx].centerX, pickerAreaArrow[idx].centerY,
662
- v.direction, pickerAreaOption.triangleLength, e.offsetX, e.offsetY,
729
+ v.centerX, v.centerY,
730
+ v.direction, timeAreaOption.triangleLength, e.offsetX, e.offsetY,
663
731
  );
664
732
  if (exist) {
665
- if (v.direction === 'left') {
666
- this.options.currentYearMonth =
667
- new Date(currDate.getFullYear(), currDate.getMonth() - 1, 1);
668
- } else if (v.direction === 'right') {
669
- this.options.currentYearMonth =
670
- new Date(currDate.getFullYear(), +currDate.getMonth() + +1, 1);
733
+ if (v.direction === 'top') {
734
+ if (timeAreaType.page > 1) {
735
+ this.coordinate.timeArea[type].page -= 1;
736
+ this.drawTimeAreaContent(type);
737
+ this.drawSplitLine();
738
+ this.updateTimeArea(type);
739
+ }
740
+ } else if (v.direction === 'bottom') {
741
+ if (timeAreaType.page < timeAreaType.maxPage) {
742
+ this.coordinate.timeArea[type].page += 1;
743
+ this.drawTimeAreaContent(type);
744
+ this.drawSplitLine();
745
+ this.updateTimeArea(type);
746
+ }
671
747
  }
672
- this.initCalendarProperty();
673
- this.drawPickerArea();
674
- this.drawCalendarDay();
675
- this.clearCalendarArea();
676
- this.mousemoveDate();
677
748
  }
678
749
  });
679
750
  }
751
+ });
680
752
 
681
- // CLICK Date logic
682
- if (e.offsetX > calendarAreaTotal.startX
683
- && e.offsetX < calendarAreaTotal.startX + calendarAreaTotal.width
684
- && e.offsetY > calendarAreaTotal.startY
685
- && e.offsetY < calendarAreaTotal.startY + calendarAreaTotal.height) {
686
- this.mouseclickDate(e);
753
+ // CLICK Time logic
754
+ const localeType = this.options.localeType;
755
+ let condition = true;
756
+ timeTypeName.forEach((type) => {
757
+ if (localeType === 'YYYY-MM-DD HH:mm:ss') {
758
+ condition = type === 'hour' || type === 'minute' || type === 'second';
759
+ } else if (localeType === 'YYYY-MM-DD HH:mm') {
760
+ condition = type === 'hour' || type === 'minute';
761
+ } else if (localeType === 'YYYY-MM-DD HH') {
762
+ condition = type === 'hour';
763
+ } else if (localeType === 'YYYY-MM-DD') {
764
+ condition = false;
687
765
  }
688
-
689
- // CLICK triangle in time area (TOP, BOTTOM)
690
- const timePageWidth = this.options.timeArea.pageWidth;
691
- const timeAreaOption = this.options.timeArea;
692
- const timeTypeName = this.options.timeTypeName;
693
- timeTypeName.forEach((type) => {
766
+ if (condition) {
694
767
  const timeAreaType = this.coordinate.timeArea[type];
695
- const timeAreaTypeTotal = timeAreaType.total;
696
- if (e.offsetX > timeAreaTypeTotal.startX + timeAreaTypeTotal.width
697
- && e.offsetX < (timeAreaTypeTotal.startX + timeAreaTypeTotal.width) + timePageWidth
698
- && e.offsetY > timeAreaTypeTotal.startY
699
- && e.offsetY < timeAreaTypeTotal.startY + timeAreaTypeTotal.height
700
- ) {
701
- let exist = false;
702
- timeAreaType.arrow.forEach((v) => {
703
- exist = this.existTriangle(
704
- v.centerX, v.centerY,
705
- v.direction, timeAreaOption.triangleLength, e.offsetX, e.offsetY,
706
- );
707
- if (exist) {
708
- if (v.direction === 'top') {
709
- if (timeAreaType.page > 1) {
710
- this.coordinate.timeArea[type].page -= 1;
711
- this.drawTimeAreaContent(type);
712
- this.updateTimeArea(type);
713
- }
714
- } else if (v.direction === 'bottom') {
715
- if (timeAreaType.page < timeAreaType.maxPage) {
716
- this.coordinate.timeArea[type].page += 1;
717
- this.drawTimeAreaContent(type);
718
- this.updateTimeArea(type);
719
- }
720
- }
768
+ const timeAreaTypeData = timeAreaType.data;
769
+ timeAreaTypeData.forEach((v, idx) => {
770
+ if (timeAreaType.page === v.page) {
771
+ if (e.offsetX > v.startX
772
+ && e.offsetX < v.startX + v.width
773
+ && e.offsetY > v.startY
774
+ && e.offsetY < v.startY + v.height) {
775
+ timeAreaType.select = idx;
776
+ this.updateTimeArea(type);
721
777
  }
722
- });
723
- }
724
- });
725
-
726
- // CLICK Time logic
727
- const localeType = this.options.localeType;
728
- let condition = true;
729
- timeTypeName.forEach((type) => {
730
- if (localeType === 'YYYY-MM-DD HH:mm:ss') {
731
- condition = type === 'hour' || type === 'minute' || type === 'second';
732
- } else if (localeType === 'YYYY-MM-DD HH:mm') {
733
- condition = type === 'hour' || type === 'minute';
734
- } else if (localeType === 'YYYY-MM-DD HH') {
735
- condition = type === 'hour';
736
- } else if (localeType === 'YYYY-MM-DD') {
737
- condition = false;
738
- }
739
- if (condition) {
740
- const timeAreaType = this.coordinate.timeArea[type];
741
- const timeAreaTypeData = timeAreaType.data;
742
- timeAreaTypeData.forEach((v, idx) => {
743
- if (timeAreaType.page === v.page) {
744
- if (e.offsetX > v.startX
745
- && e.offsetX < v.startX + v.width
746
- && e.offsetY > v.startY
747
- && e.offsetY < v.startY + v.height) {
748
- timeAreaType.select = idx;
749
- this.updateTimeArea(type);
750
- }
751
- }
752
- });
753
- }
754
- });
778
+ }
779
+ });
780
+ }
755
781
  });
756
782
  }
757
783
 
@@ -782,31 +808,25 @@ class Calendar {
782
808
  if (e.offsetX > v.startX && e.offsetX < v.startX + v.width
783
809
  && e.offsetY > v.startY && e.offsetY < v.startY + v.height
784
810
  ) {
785
- this.dynamicDraw(
786
- overCtx, v.startX, v.startY,
787
- v.width, v.height,
788
- {
789
- fill: {
790
- show: true,
791
- color: this.options.colors.mousemoveDayFill,
792
- },
793
- },
794
- );
811
+ overCtx.beginPath();
812
+ const cx = v.startX + (v.width / 2);
813
+ const cy = v.startY + (v.height / 2);
814
+ const r = (v.width < v.height) ? (v.width / 2) : (v.height / 2);
815
+ overCtx.arc(cx, cy, r, 0, Math.PI * 2, true);
816
+ overCtx.fillStyle = this.options.colors[this.options.theme].mousemoveDayFill;
817
+ overCtx.fill();
795
818
  }
796
819
  selectDayArr.forEach((s) => {
797
820
  if (v.date.year === s.year
798
821
  && v.date.month === s.month
799
822
  && v.date.day === s.day) {
800
- this.dynamicDraw(
801
- overCtx, v.startX, v.startY,
802
- v.width, v.height,
803
- {
804
- fill: {
805
- show: true,
806
- color: this.options.colors.selectDayFill,
807
- },
808
- },
809
- );
823
+ overCtx.beginPath();
824
+ const cx = v.startX + (v.width / 2);
825
+ const cy = v.startY + (v.height / 2);
826
+ const r = (v.width < v.height) ? (v.width / 2) : (v.height / 2);
827
+ overCtx.arc(cx, cy, r, 0, Math.PI * 2, true);
828
+ overCtx.fillStyle = this.options.colors[this.options.theme].selectDayFill;
829
+ overCtx.fill();
810
830
  }
811
831
  });
812
832
  });
@@ -817,16 +837,13 @@ class Calendar {
817
837
  if (v.date.year === s.year
818
838
  && v.date.month === s.month
819
839
  && v.date.day === s.day) {
820
- this.dynamicDraw(
821
- overCtx, v.startX, v.startY,
822
- v.width, v.height,
823
- {
824
- fill: {
825
- show: true,
826
- color: this.options.colors.selectDayFill,
827
- },
828
- },
829
- );
840
+ overCtx.beginPath();
841
+ const cx = v.startX + (v.width / 2);
842
+ const cy = v.startY + (v.height / 2);
843
+ const r = (v.width < v.height) ? (v.width / 2) : (v.height / 2);
844
+ overCtx.arc(cx, cy, r, 0, Math.PI * 2, true);
845
+ overCtx.fillStyle = this.options.colors[this.options.theme].selectDayFill;
846
+ overCtx.fill();
830
847
  }
831
848
  });
832
849
  });
@@ -834,135 +851,135 @@ class Calendar {
834
851
  }
835
852
 
836
853
  initMouseleave() {
837
- this.overCanvas.addEventListener('mouseleave', (e) => {
838
- e.preventDefault();
839
- const allDay = this.coordinate.calendarArea.allDay;
840
- const selectDayArr = this.coordinate.calendarArea.selectDayArr;
841
- const overCtx = this.overCtx;
842
- this.clearCanvas(overCtx, 0, 0, this.overCanvas.width, this.overCanvas.height);
843
- allDay.forEach((v) => {
844
- selectDayArr.forEach((s) => {
845
- if (v.date.year === s.year
846
- && v.date.month === s.month
847
- && v.date.day === s.day) {
848
- this.dynamicDraw(
849
- overCtx, v.startX, v.startY,
850
- v.width, v.height,
851
- {
852
- fill: {
853
- show: true,
854
- color: this.options.colors.selectDayFill,
855
- },
856
- },
857
- );
858
- }
859
- });
854
+ this.overCanvas.addEventListener('mouseleave', this.mouseleave);
855
+ }
856
+
857
+ onMouseleave(e) {
858
+ e.preventDefault();
859
+ const allDay = this.coordinate.calendarArea.allDay;
860
+ const selectDayArr = this.coordinate.calendarArea.selectDayArr;
861
+ const overCtx = this.overCtx;
862
+ this.clearCanvas(overCtx, 0, 0, this.overCanvas.width, this.overCanvas.height);
863
+ allDay.forEach((v) => {
864
+ selectDayArr.forEach((s) => {
865
+ if (v.date.year === s.year
866
+ && v.date.month === s.month
867
+ && v.date.day === s.day) {
868
+ overCtx.beginPath();
869
+ const cx = v.startX + (v.width / 2);
870
+ const cy = v.startY + (v.height / 2);
871
+ const r = (v.width < v.height) ? (v.width / 2) : (v.height / 2);
872
+ overCtx.arc(cx, cy, r, 0, Math.PI * 2, true);
873
+ overCtx.fillStyle = this.options.colors[this.options.theme].selectDayFill;
874
+ overCtx.fill();
875
+ }
860
876
  });
861
- const timeTypeName = this.options.timeTypeName;
862
- timeTypeName.forEach((type) => {
863
- const timeAreaType = this.coordinate.timeArea[type];
864
- timeAreaType.data.forEach((v, idx) => {
865
- if (timeAreaType.page === v.page
866
- && timeAreaType.select === idx) {
867
- this.dynamicDraw(
868
- overCtx, v.startX, v.startY,
869
- v.width, v.height, {
870
- fill: {
871
- show: true,
872
- color: this.options.colors.selectDayFill,
873
- },
874
- },
875
- );
876
- }
877
- });
877
+ });
878
+ const timeTypeName = this.options.timeTypeName;
879
+ timeTypeName.forEach((type) => {
880
+ const timeAreaType = this.coordinate.timeArea[type];
881
+ timeAreaType.data.forEach((v, idx) => {
882
+ if (timeAreaType.page === v.page
883
+ && timeAreaType.select === idx) {
884
+ overCtx.beginPath();
885
+ const cx = v.startX + (v.width / 2);
886
+ const cy = v.startY + (v.height / 2);
887
+ const r = (v.width < v.height) ? (v.width / 2) : (v.height / 2);
888
+ overCtx.arc(cx, cy, r, 0, Math.PI * 2, true);
889
+ overCtx.fillStyle = this.options.colors[this.options.theme].selectDayFill;
890
+ overCtx.fill();
891
+ }
878
892
  });
879
893
  });
880
894
  }
881
895
 
882
896
  initMousewheel() {
883
- this.overCanvas.addEventListener('mousewheel', (e) => {
884
- e.preventDefault();
885
- const pickerAreaTotal = this.coordinate.pickerArea.total;
886
- const calendarAreaTotal = this.coordinate.calendarArea.total;
887
- const timeAreaHourTotal = this.coordinate.timeArea.hour.total;
888
- const timeAreaMinuteTotal = this.coordinate.timeArea.minute.total;
889
- const timeAreaSecondTotal = this.coordinate.timeArea.second.total;
890
- const timeAreaPageWidth = this.options.timeArea.pageWidth;
891
-
892
- let areaType = '';
893
- if (e.offsetX > pickerAreaTotal.startX
894
- && e.offsetX < pickerAreaTotal.startX + pickerAreaTotal.width
895
- && e.offsetY > pickerAreaTotal.startY
896
- && e.offsetY < pickerAreaTotal.startY + pickerAreaTotal.height) {
897
- areaType = 'month';
898
- } else if (e.offsetX > calendarAreaTotal.startX
899
- && e.offsetX < calendarAreaTotal.startX + calendarAreaTotal.width
900
- && e.offsetY > calendarAreaTotal.startY
901
- && e.offsetY < calendarAreaTotal.startY + calendarAreaTotal.height) {
902
- areaType = 'month';
903
- } else if (e.offsetX > timeAreaHourTotal.startX
904
- && e.offsetX < timeAreaHourTotal.startX + timeAreaHourTotal.width + timeAreaPageWidth
905
- && e.offsetY > timeAreaHourTotal.startY
906
- && e.offsetY < timeAreaHourTotal.startY + timeAreaHourTotal.height) {
907
- areaType = 'hour';
908
- } else if (e.offsetX > timeAreaMinuteTotal.startX
909
- && e.offsetX < timeAreaMinuteTotal.startX + timeAreaMinuteTotal.width + timeAreaPageWidth
910
- && e.offsetY > timeAreaMinuteTotal.startY
911
- && e.offsetY < timeAreaMinuteTotal.startY + timeAreaMinuteTotal.height) {
912
- areaType = 'minute';
913
- } else if (e.offsetX > timeAreaSecondTotal.startX
914
- && e.offsetX < timeAreaSecondTotal.startX + timeAreaSecondTotal.width + timeAreaPageWidth
915
- && e.offsetY > timeAreaSecondTotal.startY
916
- && e.offsetY < timeAreaSecondTotal.startY + timeAreaSecondTotal.height) {
917
- areaType = 'second';
918
- }
897
+ this.overCanvas.addEventListener('mousewheel', this.mousewheel);
898
+ }
919
899
 
920
- if (areaType === 'month') {
921
- const currDate = this.options.currentYearMonth;
922
- if (e.deltaY < 0) {
923
- // wheel up
924
- this.options.currentYearMonth =
925
- new Date(currDate.getFullYear(), currDate.getMonth() - 1, 1);
926
- } else if (e.deltaY > 0) {
927
- // wheel down
928
- this.options.currentYearMonth =
929
- new Date(currDate.getFullYear(), +currDate.getMonth() + +1, 1);
900
+ onMousewheel(e) {
901
+ e.preventDefault();
902
+ const pickerAreaTotal = this.coordinate.pickerArea.total;
903
+ const calendarAreaTotal = this.coordinate.calendarArea.total;
904
+ const timeAreaHourTotal = this.coordinate.timeArea.hour.total;
905
+ const timeAreaMinuteTotal = this.coordinate.timeArea.minute.total;
906
+ const timeAreaSecondTotal = this.coordinate.timeArea.second.total;
907
+ const timeAreaPageWidth = this.options.timeArea.pageWidth;
908
+
909
+ let areaType = '';
910
+ if (e.offsetX > pickerAreaTotal.startX
911
+ && e.offsetX < pickerAreaTotal.startX + pickerAreaTotal.width
912
+ && e.offsetY > pickerAreaTotal.startY
913
+ && e.offsetY < pickerAreaTotal.startY + pickerAreaTotal.height) {
914
+ areaType = 'month';
915
+ } else if (e.offsetX > calendarAreaTotal.startX
916
+ && e.offsetX < calendarAreaTotal.startX + calendarAreaTotal.width
917
+ && e.offsetY > calendarAreaTotal.startY
918
+ && e.offsetY < calendarAreaTotal.startY + calendarAreaTotal.height) {
919
+ areaType = 'month';
920
+ } else if (e.offsetX > timeAreaHourTotal.startX
921
+ && e.offsetX < timeAreaHourTotal.startX + timeAreaHourTotal.width + timeAreaPageWidth
922
+ && e.offsetY > timeAreaHourTotal.startY
923
+ && e.offsetY < timeAreaHourTotal.startY + timeAreaHourTotal.height) {
924
+ areaType = 'hour';
925
+ } else if (e.offsetX > timeAreaMinuteTotal.startX
926
+ && e.offsetX < timeAreaMinuteTotal.startX + timeAreaMinuteTotal.width + timeAreaPageWidth
927
+ && e.offsetY > timeAreaMinuteTotal.startY
928
+ && e.offsetY < timeAreaMinuteTotal.startY + timeAreaMinuteTotal.height) {
929
+ areaType = 'minute';
930
+ } else if (e.offsetX > timeAreaSecondTotal.startX
931
+ && e.offsetX < timeAreaSecondTotal.startX + timeAreaSecondTotal.width + timeAreaPageWidth
932
+ && e.offsetY > timeAreaSecondTotal.startY
933
+ && e.offsetY < timeAreaSecondTotal.startY + timeAreaSecondTotal.height) {
934
+ areaType = 'second';
935
+ }
936
+
937
+ if (areaType === 'month') {
938
+ const currDate = this.options.currentYearMonth;
939
+ const year = currDate.getFullYear();
940
+ const month = currDate.getMonth();
941
+ if (e.deltaY < 0) {
942
+ // wheel up
943
+ this.options.currentYearMonth = new Date(year, month - 1, 1);
944
+ } else if (e.deltaY > 0) {
945
+ // wheel down
946
+ this.options.currentYearMonth = new Date(year, +month + +1, 1);
947
+ }
948
+ this.drawPickerArea();
949
+ this.initCalendarProperty();
950
+ this.drawCalendarDay();
951
+ this.clearCalendarArea();
952
+ this.mousemoveDate();
953
+ } else if (areaType === 'hour' || areaType === 'minute' || areaType === 'second') {
954
+ const timeAreaType = this.coordinate.timeArea[areaType];
955
+ if (e.deltaY < 0) {
956
+ // wheel up
957
+ if (timeAreaType.page > 1) {
958
+ timeAreaType.page -= 1;
959
+ this.drawTimeAreaContent(areaType);
960
+ this.drawSplitLine();
961
+ this.updateTimeArea(areaType);
930
962
  }
931
- this.drawPickerArea();
932
- this.initCalendarProperty();
933
- this.drawCalendarDay();
934
- this.clearCalendarArea();
935
- this.mousemoveDate();
936
- } else if (areaType === 'hour' || areaType === 'minute' || areaType === 'second') {
937
- const timeAreaType = this.coordinate.timeArea[areaType];
938
- if (e.deltaY < 0) {
939
- // wheel up
940
- if (timeAreaType.page > 1) {
941
- timeAreaType.page -= 1;
942
- this.drawTimeAreaContent(areaType);
943
- this.updateTimeArea(areaType);
944
- }
945
- } else if (e.deltaY > 0) {
946
- // wheel down
947
- if (timeAreaType.page < timeAreaType.maxPage) {
948
- timeAreaType.page += 1;
949
- this.drawTimeAreaContent(areaType);
950
- this.updateTimeArea(areaType);
951
- }
963
+ } else if (e.deltaY > 0) {
964
+ // wheel down
965
+ if (timeAreaType.page < timeAreaType.maxPage) {
966
+ timeAreaType.page += 1;
967
+ this.drawTimeAreaContent(areaType);
968
+ this.drawSplitLine();
969
+ this.updateTimeArea(areaType);
952
970
  }
953
971
  }
954
- });
972
+ }
955
973
  }
956
974
 
957
-
958
975
  drawCanvas() {
959
976
  this.drawTotalArea();
960
977
  this.drawPickerArea();
961
978
  this.drawCalendarArea();
962
979
  this.mousemoveDate();
963
980
  if (this.options.timeExpand) {
964
- this.drawSplitLine();
965
981
  this.drawTimeArea();
982
+ this.drawSplitLine();
966
983
  this.updateTimeArea();
967
984
  }
968
985
  }
@@ -970,11 +987,11 @@ class Calendar {
970
987
  drawTotalArea() {
971
988
  const ctx = this.context;
972
989
  const padding = this.options.padding;
973
- const style = {
974
- stroke: {
975
- show: true,
976
- },
977
- };
990
+ // const style = {
991
+ // stroke: {
992
+ // show: true,
993
+ // },
994
+ // };
978
995
  // total Area = picker area + calendar area + button area
979
996
  // linewidth이 1이므로 total area에 선을 그을 때, p+c+b area의 보더 +1로 지정
980
997
  const gap = 1;
@@ -985,14 +1002,14 @@ class Calendar {
985
1002
  ((this.baseCanvas.width - padding.left) - padding.right) + (gap * 2) + 2,
986
1003
  ((this.baseCanvas.height - padding.top) - padding.bottom) + (gap * 2) + 2,
987
1004
  );
988
- this.dynamicDraw(
989
- ctx,
990
- padding.left - gap,
991
- padding.top - gap,
992
- ((this.baseCanvas.width - padding.left) - padding.right) + (gap * 2),
993
- ((this.baseCanvas.height - padding.top) - padding.bottom) + (gap * 2),
994
- style,
995
- );
1005
+ // this.dynamicDraw(
1006
+ // ctx,
1007
+ // padding.left - gap,
1008
+ // padding.top - gap,
1009
+ // ((this.baseCanvas.width - padding.left) - padding.right) + (gap * 2),
1010
+ // ((this.baseCanvas.height - padding.top) - padding.bottom) + (gap * 2),
1011
+ // style,
1012
+ // );
996
1013
  }
997
1014
 
998
1015
  drawPickerArea() {
@@ -1005,17 +1022,22 @@ class Calendar {
1005
1022
  pickerAreaTotal.width, pickerAreaTotal.height,
1006
1023
  );
1007
1024
  // draw bottom line in picker area
1025
+ const yearUnderlinePaddingSide = 11;
1026
+ ctx.save();
1008
1027
  ctx.beginPath();
1009
1028
  ctx.moveTo(
1010
- pickerAreaTotal.startX,
1029
+ pickerAreaTotal.startX + yearUnderlinePaddingSide,
1011
1030
  +pickerAreaTotal.startY + +pickerAreaTotal.height,
1012
1031
  );
1013
1032
  ctx.lineTo(
1014
- +pickerAreaTotal.startX + +pickerAreaTotal.width,
1033
+ +pickerAreaTotal.startX + (+pickerAreaTotal.width - yearUnderlinePaddingSide),
1015
1034
  +pickerAreaTotal.startY + +pickerAreaTotal.height,
1016
1035
  );
1036
+ ctx.strokeStyle = '#CFCFCF';
1037
+ ctx.lineWidth = 1;
1017
1038
  ctx.stroke();
1018
1039
  ctx.closePath();
1040
+ ctx.restore();
1019
1041
 
1020
1042
  // draw triange in picker area
1021
1043
  let arrowObj = {};
@@ -1054,11 +1076,12 @@ class Calendar {
1054
1076
  fillText: {
1055
1077
  show: true,
1056
1078
  text: thisYear,
1079
+ color: this.options.colors[this.options.theme].yearMonthColor,
1057
1080
  },
1058
1081
  text: thisYear,
1059
1082
  align: 'center',
1060
- padding: { bottom: 8 },
1061
- font: '14px Roboto Condensed',
1083
+ padding: { bottom: 12 },
1084
+ font: 'bold 16px Roboto',
1062
1085
  },
1063
1086
  };
1064
1087
  this.dynamicDraw(
@@ -1080,10 +1103,11 @@ class Calendar {
1080
1103
  fillText: {
1081
1104
  show: true,
1082
1105
  text: thisMonthText,
1106
+ color: this.options.colors[this.options.theme].yearMonthColor,
1083
1107
  },
1084
1108
  align: 'center',
1085
- padding: { bottom: 8 },
1086
- font: '14px Roboto Condensed',
1109
+ padding: { bottom: 12 },
1110
+ font: 'bold 16px Roboto',
1087
1111
  },
1088
1112
  };
1089
1113
  this.dynamicDraw(
@@ -1112,13 +1136,14 @@ class Calendar {
1112
1136
  fillText: {
1113
1137
  show: true,
1114
1138
  text: this.options.dayOfTheWeekArr[this.options.titleType.dayOfTheWeek][idx],
1139
+ color: this.options.colors[this.options.theme].weekColor,
1115
1140
  },
1116
1141
  stroke: {
1117
1142
  show: false,
1118
1143
  },
1119
1144
  align: 'center',
1120
1145
  padding: { bottom: 8 },
1121
- font: '10px Roboto Condensed',
1146
+ font: '11px Roboto',
1122
1147
  },
1123
1148
  );
1124
1149
  });
@@ -1144,6 +1169,8 @@ class Calendar {
1144
1169
  const currentYear = this.options.currentYearMonth.getFullYear();
1145
1170
  // 현재 달력 월
1146
1171
  const currentMonth = +this.options.currentYearMonth.getMonth() + +1;
1172
+ // 일 숫자 텍스트 아래 패딩
1173
+ const daysPaddingBottom = 9;
1147
1174
 
1148
1175
  // draw DAY NUMBER
1149
1176
  for (let ix = 0, ixLen = this.thisMonthWeekCnt; ix < ixLen; ix++) {
@@ -1167,17 +1194,15 @@ class Calendar {
1167
1194
  style: {
1168
1195
  fillText: {
1169
1196
  show: true,
1170
- color: this.options.colors.prevNextMonthFont,
1197
+ color: this.options.colors[this.options.theme].prevNextMonthFont,
1171
1198
  text: ((this.prevMonthLastDate - firstWeekDayCnt) + jx) + 1,
1172
1199
  },
1173
1200
  fill: {
1174
1201
  show: false,
1175
1202
  },
1176
1203
  align: 'center',
1177
- padding: {
1178
- bottom: 8,
1179
- },
1180
- font: '10px Roboto Condensed',
1204
+ padding: { bottom: daysPaddingBottom },
1205
+ font: '12px Roboto',
1181
1206
  },
1182
1207
  selectable: false,
1183
1208
  date: {
@@ -1194,10 +1219,11 @@ class Calendar {
1194
1219
  let fillText = {
1195
1220
  show: true,
1196
1221
  text: 1,
1222
+ color: this.options.colors[this.options.theme].dayColor,
1197
1223
  };
1198
1224
  let fill = {
1199
1225
  show: true,
1200
- color: this.options.colors.thisMonthFill,
1226
+ color: this.options.colors[this.options.theme].thisMonthFill,
1201
1227
  };
1202
1228
  let selectableFlag = true;
1203
1229
  if (this.options.limitToday) {
@@ -1206,7 +1232,7 @@ class Calendar {
1206
1232
  if (initLimitDay < currentDate) {
1207
1233
  fillText = {
1208
1234
  show: true,
1209
- color: this.options.colors.prevNextMonthFont,
1235
+ color: this.options.colors[this.options.theme].prevNextMonthFont,
1210
1236
  text: 1,
1211
1237
  };
1212
1238
  fill = {
@@ -1224,8 +1250,8 @@ class Calendar {
1224
1250
  fillText,
1225
1251
  fill,
1226
1252
  align: 'center',
1227
- padding: { bottom: 8 },
1228
- font: '10px Roboto Condensed',
1253
+ padding: { bottom: daysPaddingBottom },
1254
+ font: '12px Roboto',
1229
1255
  },
1230
1256
  selectable: selectableFlag,
1231
1257
  date: {
@@ -1242,10 +1268,11 @@ class Calendar {
1242
1268
  let fillText = {
1243
1269
  show: true,
1244
1270
  text: this.monthDay,
1271
+ color: this.options.colors[this.options.theme].dayColor,
1245
1272
  };
1246
1273
  let fill = {
1247
1274
  show: true,
1248
- color: this.options.colors.thisMonthFill,
1275
+ color: this.options.colors[this.options.theme].thisMonthFill,
1249
1276
  };
1250
1277
  let selectableFlag = true;
1251
1278
  if (this.options.limitToday) {
@@ -1254,7 +1281,7 @@ class Calendar {
1254
1281
  if (initLimitDay < currentDate) {
1255
1282
  fillText = {
1256
1283
  show: true,
1257
- color: this.options.colors.prevNextMonthFont,
1284
+ color: this.options.colors[this.options.theme].prevNextMonthFont,
1258
1285
  text: this.monthDay,
1259
1286
  };
1260
1287
  fill = {
@@ -1272,8 +1299,8 @@ class Calendar {
1272
1299
  fillText,
1273
1300
  fill,
1274
1301
  align: 'center',
1275
- padding: { bottom: 8 },
1276
- font: '10px Roboto Condensed',
1302
+ padding: { bottom: daysPaddingBottom },
1303
+ font: '12px Roboto',
1277
1304
  },
1278
1305
  selectable: selectableFlag,
1279
1306
  date: {
@@ -1297,12 +1324,12 @@ class Calendar {
1297
1324
  style: {
1298
1325
  fillText: {
1299
1326
  show: true,
1300
- color: this.options.colors.prevNextMonthFont,
1327
+ color: this.options.colors[this.options.theme].prevNextMonthFont,
1301
1328
  text: this.monthDay - this.thisMonthLastDate,
1302
1329
  },
1303
1330
  align: 'center',
1304
- padding: { bottom: 8 },
1305
- font: '10px Roboto Condensed',
1331
+ padding: { bottom: daysPaddingBottom },
1332
+ font: '12px Roboto',
1306
1333
  },
1307
1334
  selectable: false,
1308
1335
  date: {
@@ -1321,10 +1348,11 @@ class Calendar {
1321
1348
  let fillText = {
1322
1349
  show: true,
1323
1350
  text: 1,
1351
+ color: this.options.colors[this.options.theme].dayColor,
1324
1352
  };
1325
1353
  let fill = {
1326
1354
  show: true,
1327
- color: this.options.colors.thisMonthFill,
1355
+ color: this.options.colors[this.options.theme].thisMonthFill,
1328
1356
  };
1329
1357
  let selectableFlag = true;
1330
1358
  if (this.options.limitToday) {
@@ -1333,7 +1361,7 @@ class Calendar {
1333
1361
  if (initLimitDay < currentDate) {
1334
1362
  fillText = {
1335
1363
  show: true,
1336
- color: this.options.colors.prevNextMonthFont,
1364
+ color: this.options.colors[this.options.theme].prevNextMonthFont,
1337
1365
  text: 1,
1338
1366
  };
1339
1367
  fill = {
@@ -1352,8 +1380,8 @@ class Calendar {
1352
1380
  fillText,
1353
1381
  fill,
1354
1382
  align: 'center',
1355
- padding: { bottom: 8 },
1356
- font: '10px Roboto Condensed',
1383
+ padding: { bottom: daysPaddingBottom },
1384
+ font: '12px Roboto',
1357
1385
  },
1358
1386
  selectable: selectableFlag,
1359
1387
  date: {
@@ -1369,10 +1397,11 @@ class Calendar {
1369
1397
  let fillText = {
1370
1398
  show: true,
1371
1399
  text: this.monthDay,
1400
+ color: this.options.colors[this.options.theme].dayColor,
1372
1401
  };
1373
1402
  let fill = {
1374
1403
  show: true,
1375
- color: this.options.colors.thisMonthFill,
1404
+ color: this.options.colors[this.options.theme].thisMonthFill,
1376
1405
  };
1377
1406
  let selectableFlag = true; // 선택 여부
1378
1407
  if (this.options.limitToday) {
@@ -1381,7 +1410,7 @@ class Calendar {
1381
1410
  if (initLimitDay < currentDate) {
1382
1411
  fillText = {
1383
1412
  show: true,
1384
- color: this.options.colors.prevNextMonthFont,
1413
+ color: this.options.colors[this.options.theme].prevNextMonthFont,
1385
1414
  text: this.monthDay,
1386
1415
  };
1387
1416
  fill = {
@@ -1400,8 +1429,8 @@ class Calendar {
1400
1429
  fillText,
1401
1430
  fill,
1402
1431
  align: 'center',
1403
- padding: { bottom: 8 },
1404
- font: '10px Roboto Condensed',
1432
+ padding: { bottom: daysPaddingBottom },
1433
+ font: '12px Roboto',
1405
1434
  },
1406
1435
  selectable: selectableFlag,
1407
1436
  date: {
@@ -1456,6 +1485,7 @@ class Calendar {
1456
1485
  drawSplitLine() {
1457
1486
  const ctx = this.context;
1458
1487
  const padding = this.options.padding;
1488
+ ctx.save();
1459
1489
  ctx.beginPath();
1460
1490
  // 중앙 세로
1461
1491
  ctx.moveTo(this.baseCanvas.width / 2, padding.top);
@@ -1466,17 +1496,19 @@ class Calendar {
1466
1496
  ctx.lineTo((this.baseCanvas.width / 2) + this.options.timeArea.titleWidth,
1467
1497
  this.baseCanvas.height - padding.top);
1468
1498
  // content|page 세로
1469
- ctx.moveTo(this.baseCanvas.width - padding.right - this.options.timeArea.pageWidth,
1470
- padding.top);
1471
- ctx.lineTo(this.baseCanvas.width - padding.right - this.options.timeArea.pageWidth,
1472
- this.baseCanvas.height - padding.top);
1499
+ // ctx.moveTo(this.baseCanvas.width - padding.right - this.options.timeArea.pageWidth,
1500
+ // padding.top);
1501
+ // ctx.lineTo(this.baseCanvas.width - padding.right - this.options.timeArea.pageWidth,
1502
+ // this.baseCanvas.height - padding.top);
1473
1503
  // hour|minute|second 가로
1474
1504
  ctx.moveTo(this.baseCanvas.width / 2, (this.baseCanvas.height / 3) + 1);
1475
1505
  ctx.lineTo(this.baseCanvas.width - padding.right, (this.baseCanvas.height / 3) + 1);
1476
1506
  ctx.moveTo(this.baseCanvas.width / 2, ((this.baseCanvas.height / 3) * 2) - 1);
1477
1507
  ctx.lineTo(this.baseCanvas.width - padding.right, ((this.baseCanvas.height / 3) * 2) - 1);
1508
+ ctx.strokeStyle = this.options.colors[this.options.theme].border;
1478
1509
  ctx.stroke();
1479
1510
  ctx.closePath();
1511
+ ctx.restore();
1480
1512
  }
1481
1513
 
1482
1514
  drawTimeArea() {
@@ -1484,6 +1516,7 @@ class Calendar {
1484
1516
  this.drawTimeAreaContent();
1485
1517
  this.drawTimeAreaPage();
1486
1518
  }
1519
+
1487
1520
  // DRAW 'Hour, Min, Sec'
1488
1521
  drawTimeAreaTitle() {
1489
1522
  const ctx = this.context;
@@ -1499,17 +1532,28 @@ class Calendar {
1499
1532
  {
1500
1533
  fillText: {
1501
1534
  show: true,
1535
+ color: this.options.colors[this.options.theme].timeLabelFont,
1502
1536
  text: v,
1503
1537
  },
1538
+ fill: {
1539
+ show: true,
1540
+ color: this.options.colors[this.options.theme].timeLabelFill,
1541
+ },
1542
+ stroke: {
1543
+ show: true,
1544
+ linewidth: 1,
1545
+ color: this.options.colors[this.options.theme].timeLabelStroke,
1546
+ },
1504
1547
  align: 'center',
1505
1548
  padding: {
1506
- bottom: 27,
1549
+ bottom: 30,
1507
1550
  },
1508
- font: '12px Roboto Condensed',
1551
+ font: 'bold 11px Roboto',
1509
1552
  },
1510
1553
  );
1511
1554
  });
1512
1555
  }
1556
+
1513
1557
  // DRAW 0 ~ 23 || 59 BOX
1514
1558
  drawTimeAreaContent(changedType) {
1515
1559
  const ctx = this.context;
@@ -1525,8 +1569,8 @@ class Calendar {
1525
1569
  let timeAreaObj = {};
1526
1570
  for (let ix = 0, ixLen = maxNumber; ix < ixLen; ix++) {
1527
1571
  const columnIdx = ix % this.options.timeArea.columnCount;
1528
- const page = parseInt(ix /
1529
- (this.options.timeArea.columnCount * this.options.timeArea.rowCount), 0) + 1;
1572
+ const page = parseInt(ix
1573
+ / (this.options.timeArea.columnCount * this.options.timeArea.rowCount), 0) + 1;
1530
1574
  let rowIdx = 1;
1531
1575
  if (ix % (this.options.timeArea.columnCount * this.options.timeArea.rowCount)
1532
1576
  < this.options.timeArea.columnCount) {
@@ -1542,11 +1586,13 @@ class Calendar {
1542
1586
  fillText: {
1543
1587
  show: true,
1544
1588
  text: `${ix}`,
1589
+ color: this.options.colors[this.options.theme].dayColor,
1545
1590
  },
1546
1591
  fill: {
1547
1592
  show: true,
1548
- color: this.options.colors.thisMonthFill,
1593
+ color: this.options.colors[this.options.theme].background,
1549
1594
  },
1595
+ font: '12px Roboto',
1550
1596
  align: 'center',
1551
1597
  padding: {
1552
1598
  bottom: 13,
@@ -1578,6 +1624,7 @@ class Calendar {
1578
1624
  });
1579
1625
  }
1580
1626
  }
1627
+
1581
1628
  drawTimeAreaPage() {
1582
1629
  const ctx = this.context;
1583
1630
  const timeType = this.options.timeTypeName;
@@ -1595,6 +1642,19 @@ class Calendar {
1595
1642
  startY: timeTypeTotal.startY,
1596
1643
  height: timeTypeTotal.height,
1597
1644
  };
1645
+ this.dynamicDraw(
1646
+ ctx,
1647
+ timeTypeAreaPage.startX - 1,
1648
+ timeTypeAreaPage.startY - 1,
1649
+ timeTypeAreaPage.width + 2,
1650
+ timeTypeAreaPage.height + 2,
1651
+ {
1652
+ fill: {
1653
+ show: true,
1654
+ color: this.options.colors[this.options.theme].timeAreaFill,
1655
+ },
1656
+ },
1657
+ );
1598
1658
  arrowArr.forEach((v, idx) => {
1599
1659
  arrowObj = {
1600
1660
  centerX: timeTypeAreaPage.startX + (timeTypeAreaPage.width / 2),
@@ -1613,8 +1673,15 @@ class Calendar {
1613
1673
 
1614
1674
  // 외부 Input box에 입력받는 값으로 클래스 내 데이터 갱신하는 함수
1615
1675
  setDateTime(dateTimeValue) {
1676
+ const isValid = dateTimeValue && dateTimeValue.isValid();
1616
1677
  this.options.initSelectDayFlag = true;
1617
- this.options.initSelectDay = new Date(dateTimeValue);
1678
+ if (isValid) {
1679
+ this.options.initSelectDay = new Date(dateTimeValue);
1680
+ } else {
1681
+ const today = new Date();
1682
+ this.options.initSelectDay = null;
1683
+ this.options.currentYearMonth = new Date(today.getFullYear(), today.getMonth(), 1);
1684
+ }
1618
1685
  this.options.initLimitDay = new Date();
1619
1686
  this.coordinate.calendarArea.selectDayArr = [];
1620
1687
  this.init();
@@ -1624,7 +1691,7 @@ class Calendar {
1624
1691
  // DRAW multiple function
1625
1692
  dynamicDraw(context, x, y, width, height, style) {
1626
1693
  if (style) {
1627
- const mergedStyle = _.merge({}, this.options.styleObj, style);
1694
+ const mergedStyle = merge({}, this.options.styleObj, style);
1628
1695
  const ctx = context;
1629
1696
 
1630
1697
  if (mergedStyle.stroke && mergedStyle.stroke.show) {
@@ -1647,8 +1714,8 @@ class Calendar {
1647
1714
  }
1648
1715
  if (mergedStyle.fillText.show && mergedStyle.fillText.text) {
1649
1716
  ctx.font = mergedStyle.font;
1650
- const textWidth = mergedStyle.fillText.text ?
1651
- ctx.measureText(mergedStyle.fillText.text).width : 0;
1717
+ const textWidth = mergedStyle.fillText.text
1718
+ ? ctx.measureText(mergedStyle.fillText.text).width : 0;
1652
1719
  let textStartX;
1653
1720
  if (mergedStyle.align === 'center') {
1654
1721
  textStartX = (x + (width / 2)) - (textWidth / 2);
@@ -1669,31 +1736,31 @@ class Calendar {
1669
1736
  // 중심점을 기준으로 left, right 방향으로 삼각형 그리기
1670
1737
  drawTriangle(context, x, y, direction, length) {
1671
1738
  const ctx = context;
1739
+ const angle = 42;
1740
+ ctx.save();
1672
1741
  ctx.beginPath();
1673
- ctx.moveTo(x, y);
1674
1742
  if (direction === 'right') {
1675
- ctx.lineTo(x, y - (Math.sin(this.toRadians(30)) * length));
1676
- ctx.lineTo(x + (Math.cos(this.toRadians(30)) * length), y);
1677
- ctx.lineTo(x, y + (Math.sin(this.toRadians(30)) * length));
1743
+ ctx.moveTo(x, y - (Math.sin(this.toRadians(angle)) * length));
1744
+ ctx.lineTo(x + (Math.cos(this.toRadians(angle)) * length), y);
1745
+ ctx.lineTo(x, y + (Math.sin(this.toRadians(angle)) * length));
1678
1746
  } else if (direction === 'left') {
1679
- ctx.lineTo(x, y - (Math.sin(this.toRadians(30)) * length));
1680
- ctx.lineTo(x - (Math.cos(this.toRadians(30)) * length), y);
1681
- ctx.lineTo(x, y + (Math.sin(this.toRadians(30)) * length));
1747
+ ctx.moveTo(x, y - (Math.sin(this.toRadians(angle)) * length));
1748
+ ctx.lineTo(x - (Math.cos(this.toRadians(angle)) * length), y);
1749
+ ctx.lineTo(x, y + (Math.sin(this.toRadians(angle)) * length));
1682
1750
  } else if (direction === 'top') {
1683
- ctx.lineTo(x + (Math.sin(this.toRadians(30)) * length), y);
1684
- ctx.lineTo(x, y - (Math.cos(this.toRadians(30)) * length));
1685
- ctx.lineTo(x - (Math.sin(this.toRadians(30)) * length), y);
1751
+ ctx.moveTo(x + (Math.sin(this.toRadians(angle)) * length), y);
1752
+ ctx.lineTo(x, y - (Math.cos(this.toRadians(angle)) * length));
1753
+ ctx.lineTo(x - (Math.sin(this.toRadians(angle)) * length), y);
1686
1754
  } else if (direction === 'bottom') {
1687
- ctx.lineTo(x + (Math.sin(this.toRadians(30)) * length), y);
1688
- ctx.lineTo(x, y + (Math.cos(this.toRadians(30)) * length));
1689
- ctx.lineTo(x - (Math.sin(this.toRadians(30)) * length), y);
1755
+ ctx.moveTo(x + (Math.sin(this.toRadians(angle)) * length), y);
1756
+ ctx.lineTo(x, y + (Math.cos(this.toRadians(angle)) * length));
1757
+ ctx.lineTo(x - (Math.sin(this.toRadians(angle)) * length), y);
1690
1758
  }
1691
- ctx.lineTo(x, y);
1692
- ctx.fillStyle = '#000000';
1693
- ctx.fill();
1694
- ctx.strokeStyle = '#000000';
1759
+ ctx.strokeStyle = this.options.colors[this.options.theme].triangle;
1760
+ ctx.lineWidth = 2.5;
1695
1761
  ctx.stroke();
1696
1762
  ctx.closePath();
1763
+ ctx.restore();
1697
1764
  }
1698
1765
 
1699
1766
  // 삼각형 안에 (px,py)이 존재하는지 확인
@@ -1824,6 +1891,33 @@ class Calendar {
1824
1891
  }
1825
1892
  }
1826
1893
  }
1894
+
1895
+ removeDropdown() {
1896
+ document.body.removeChild(this.dropdown);
1897
+ }
1898
+
1899
+ showDropdown(e) {
1900
+ this.dropdown.style.display = 'block';
1901
+ let targetDivHeight = 0;
1902
+ if (e.currentTarget && e.currentTarget.clientHeight) {
1903
+ targetDivHeight = e.currentTarget.clientHeight;
1904
+ }
1905
+ this.dropdown.style.top = `${(e.pageY - e.offsetY) + targetDivHeight}px`;
1906
+ this.dropdown.style.left = `${(e.pageX - e.offsetX) - 1}px`;
1907
+ this.dropdown.style.width = `${this.baseCanvas.width + 2}px`;
1908
+ this.dropdown.style.height = `${this.baseCanvas.height + 2}px`;
1909
+ }
1910
+
1911
+ hideDropdown() {
1912
+ this.dropdown.style.display = 'none';
1913
+ }
1914
+
1915
+ removeListeners() {
1916
+ this.overCanvas.removeEventListener('mousemove', this.mousemove);
1917
+ this.overCanvas.removeEventListener('mousedown', this.mousedown);
1918
+ this.overCanvas.removeEventListener('mouseleave', this.mouseleave);
1919
+ this.overCanvas.removeEventListener('mousewheel', this.mousewheel);
1920
+ }
1827
1921
  }
1828
1922
 
1829
1923
  export default Calendar;