@iamproperty/components 7.2.2--beta3 → 7.4.0

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 (247) hide show
  1. package/assets/css/components/actionbar.component.css +1 -1
  2. package/assets/css/components/actionbar.component.css.map +1 -1
  3. package/assets/css/components/actionbar.global.css +1 -1
  4. package/assets/css/components/actionbar.global.css.map +1 -1
  5. package/assets/css/components/barchart.component.css +1 -1
  6. package/assets/css/components/barchart.component.css.map +1 -1
  7. package/assets/css/components/bento-grid.global.css.map +1 -1
  8. package/assets/css/components/calendar.component.css +1 -0
  9. package/assets/css/components/calendar.component.css.map +1 -0
  10. package/assets/css/components/calendar.config.css +1 -0
  11. package/assets/css/components/calendar.config.css.map +1 -0
  12. package/assets/css/components/card.component.css +1 -1
  13. package/assets/css/components/card.component.css.map +1 -1
  14. package/assets/css/components/carousel.component.css +1 -1
  15. package/assets/css/components/carousel.component.css.map +1 -1
  16. package/assets/css/components/charts.module.css.map +1 -1
  17. package/assets/css/components/collapsible-side.css +1 -1
  18. package/assets/css/components/collapsible-side.css.map +1 -1
  19. package/assets/css/components/content.component.css +1 -0
  20. package/assets/css/components/content.component.css.map +1 -0
  21. package/assets/css/components/doughnutchart.component.css +1 -1
  22. package/assets/css/components/doughnutchart.component.css.map +1 -1
  23. package/assets/css/components/fileupload.css.map +1 -1
  24. package/assets/css/components/inline-edit.css +1 -1
  25. package/assets/css/components/inline-edit.css.map +1 -1
  26. package/assets/css/components/marketing.component.css +1 -0
  27. package/assets/css/components/marketing.component.css.map +1 -0
  28. package/assets/css/components/menu.component.css +1 -1
  29. package/assets/css/components/menu.component.css.map +1 -1
  30. package/assets/css/components/menu.css +1 -1
  31. package/assets/css/components/menu.css.map +1 -1
  32. package/assets/css/components/milestone.css +1 -0
  33. package/assets/css/components/milestone.css.map +1 -0
  34. package/assets/css/components/multiselect.css +1 -1
  35. package/assets/css/components/multiselect.css.map +1 -1
  36. package/assets/css/components/nav.component.css +1 -1
  37. package/assets/css/components/nav.component.css.map +1 -1
  38. package/assets/css/components/nav.global.css +1 -1
  39. package/assets/css/components/nav.global.css.map +1 -1
  40. package/assets/css/components/pagination.css.map +1 -1
  41. package/assets/css/components/rank.component.css +1 -1
  42. package/assets/css/components/rank.component.css.map +1 -1
  43. package/assets/css/components/rankings.component.css +1 -1
  44. package/assets/css/components/rankings.component.css.map +1 -1
  45. package/assets/css/components/rankings.global.css +1 -1
  46. package/assets/css/components/rankings.global.css.map +1 -1
  47. package/assets/css/components/slider.css.map +1 -1
  48. package/assets/css/components/split-button.component.css +1 -0
  49. package/assets/css/components/split-button.component.css.map +1 -0
  50. package/assets/css/components/table-basic.global.css.map +1 -1
  51. package/assets/css/components/table.global.css.map +1 -1
  52. package/assets/css/core.min.css +1 -1
  53. package/assets/css/core.min.css.map +1 -1
  54. package/assets/css/mobile-core.min.css +1 -1
  55. package/assets/css/mobile-core.min.css.map +1 -1
  56. package/assets/css/mobile.min.css +1 -1
  57. package/assets/css/mobile.min.css.map +1 -1
  58. package/assets/css/style.min.css +1 -1
  59. package/assets/css/style.min.css.map +1 -1
  60. package/assets/js/components/accordion/accordion.component.min.js +1 -1
  61. package/assets/js/components/actionbar/actionbar.component.js +51 -31
  62. package/assets/js/components/actionbar/actionbar.component.min.js +17 -17
  63. package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -1
  64. package/assets/js/components/address-lookup/address-lookup.component.min.js +1 -1
  65. package/assets/js/components/advanced-select/advanced-select.component.js +63 -0
  66. package/assets/js/components/advanced-select/advanced-select.component.min.js +23 -0
  67. package/assets/js/components/advanced-select/advanced-select.component.min.js.map +1 -0
  68. package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
  69. package/assets/js/components/barchart/barchart.component.min.js +2 -2
  70. package/assets/js/components/bento-grid/bento-grid.component.min.js +1 -1
  71. package/assets/js/components/calendar/calendar.component.js +1083 -0
  72. package/assets/js/components/calendar/calendar.component.min.js +170 -0
  73. package/assets/js/components/calendar/calendar.component.min.js.map +1 -0
  74. package/assets/js/components/card/card.component.js +20 -8
  75. package/assets/js/components/card/card.component.min.js +10 -10
  76. package/assets/js/components/card/card.component.min.js.map +1 -1
  77. package/assets/js/components/carousel/carousel.component.min.js +2 -2
  78. package/assets/js/components/collapsible-side/collapsible-side.component.js +47 -12
  79. package/assets/js/components/collapsible-side/collapsible-side.component.min.js +6 -5
  80. package/assets/js/components/collapsible-side/collapsible-side.component.min.js.map +1 -1
  81. package/assets/js/components/content/content.component.js +66 -0
  82. package/assets/js/components/content/content.component.min.js +15 -0
  83. package/assets/js/components/content/content.component.min.js.map +1 -0
  84. package/assets/js/components/doughnutchart/doughnutchart.component.min.js +2 -2
  85. package/assets/js/components/fileupload/fileupload.component.min.js +1 -1
  86. package/assets/js/components/filter-card/filter-card.component.min.js +1 -1
  87. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  88. package/assets/js/components/header/header.component.min.js +1 -1
  89. package/assets/js/components/inline-edit/inline-edit.component.min.js +5 -5
  90. package/assets/js/components/marketing/marketing.component.js +1 -1
  91. package/assets/js/components/marketing/marketing.component.min.js +2 -2
  92. package/assets/js/components/marketing/marketing.component.min.js.map +1 -1
  93. package/assets/js/components/menu/menu.component.js +148 -161
  94. package/assets/js/components/menu/menu.component.min.js +4 -69
  95. package/assets/js/components/menu/menu.component.min.js.map +1 -1
  96. package/assets/js/components/milestone/milestone.component.js +38 -0
  97. package/assets/js/components/milestone/milestone.component.min.js +15 -0
  98. package/assets/js/components/milestone/milestone.component.min.js.map +1 -0
  99. package/assets/js/components/milestone-group/milestone-group.component.js +35 -0
  100. package/assets/js/components/milestone-group/milestone-group.component.min.js +13 -0
  101. package/assets/js/components/milestone-group/milestone-group.component.min.js.map +1 -0
  102. package/assets/js/components/multi-step/multi-step.component.min.js +1 -1
  103. package/assets/js/components/multiselect/multiselect.component.js +54 -2
  104. package/assets/js/components/multiselect/multiselect.component.min.js +5 -5
  105. package/assets/js/components/multiselect/multiselect.component.min.js.map +1 -1
  106. package/assets/js/components/nav/nav.component.js +19 -0
  107. package/assets/js/components/nav/nav.component.min.js +6 -6
  108. package/assets/js/components/nav/nav.component.min.js.map +1 -1
  109. package/assets/js/components/notification/notification.component.js +17 -11
  110. package/assets/js/components/notification/notification.component.min.js +4 -4
  111. package/assets/js/components/notification/notification.component.min.js.map +1 -1
  112. package/assets/js/components/pagination/pagination.component.min.js +1 -1
  113. package/assets/js/components/rank/rank.component.js +346 -210
  114. package/assets/js/components/rank/rank.component.min.js +346 -211
  115. package/assets/js/components/rank/rank.component.min.js.map +1 -1
  116. package/assets/js/components/rankings/rankings.component.js +17 -8
  117. package/assets/js/components/rankings/rankings.component.min.js +14 -8
  118. package/assets/js/components/rankings/rankings.component.min.js.map +1 -1
  119. package/assets/js/components/record-card/record-card.component.min.js +1 -1
  120. package/assets/js/components/search/search.component.js +5 -3
  121. package/assets/js/components/search/search.component.min.js +6 -6
  122. package/assets/js/components/search/search.component.min.js.map +1 -1
  123. package/assets/js/components/slider/slider.component.min.js +1 -1
  124. package/assets/js/components/split-button/split-button.component.js +60 -0
  125. package/assets/js/components/split-button/split-button.component.min.js +34 -0
  126. package/assets/js/components/split-button/split-button.component.min.js.map +1 -0
  127. package/assets/js/components/table/table.component.js +12 -0
  128. package/assets/js/components/table/table.component.min.js +3 -3
  129. package/assets/js/components/table/table.component.min.js.map +1 -1
  130. package/assets/js/components/table-ajax/table-ajax.component.js +12 -0
  131. package/assets/js/components/table-ajax/table-ajax.component.min.js +3 -3
  132. package/assets/js/components/table-ajax/table-ajax.component.min.js.map +1 -1
  133. package/assets/js/components/table-basic/table-basic.component.min.js +1 -1
  134. package/assets/js/components/table-basic/table-basic.component.min.js.map +1 -1
  135. package/assets/js/components/table-no-submit/table-no-submit.component.js +12 -0
  136. package/assets/js/components/table-no-submit/table-no-submit.component.min.js +3 -3
  137. package/assets/js/components/table-no-submit/table-no-submit.component.min.js.map +1 -1
  138. package/assets/js/components/table-submit/table-submit.component.js +12 -0
  139. package/assets/js/components/table-submit/table-submit.component.min.js +3 -3
  140. package/assets/js/components/table-submit/table-submit.component.min.js.map +1 -1
  141. package/assets/js/components/tabs/tabs.component.min.js +1 -1
  142. package/assets/js/components/video-card/video-card.component.min.js +1 -1
  143. package/assets/js/components/video-card/video-card.component.min.js.map +1 -1
  144. package/assets/js/components.js +58 -0
  145. package/assets/js/modules/advanced-select.js +106 -0
  146. package/assets/js/modules/dialogs.js +53 -51
  147. package/assets/js/modules/dynamicEvents.js +7 -0
  148. package/assets/js/modules/milestone-group.js +30 -0
  149. package/assets/js/modules/milestone.js +89 -0
  150. package/assets/js/modules/table.js +11 -1
  151. package/assets/js/modules/videos.js +1 -1
  152. package/assets/js/scripts.bundle.js +3 -3
  153. package/assets/js/scripts.bundle.js.map +1 -1
  154. package/assets/js/scripts.bundle.min.js +2 -2
  155. package/assets/js/scripts.bundle.min.js.map +1 -1
  156. package/assets/js/scripts.js +4 -0
  157. package/assets/sass/_components.scss +11 -0
  158. package/assets/sass/_functions/utility-mixins.scss +41 -0
  159. package/assets/sass/_functions/variables.scss +11 -8
  160. package/assets/sass/components/actionbar.component.scss +3 -4
  161. package/assets/sass/components/actionbar.global.scss +4 -4
  162. package/assets/sass/components/bento-grid.global.scss +0 -1
  163. package/assets/sass/components/calendar.component.scss +1380 -0
  164. package/assets/sass/components/calendar.config.scss +476 -0
  165. package/assets/sass/components/card.component.scss +4 -34
  166. package/assets/sass/components/carousel.component.scss +5 -0
  167. package/assets/sass/components/charts.module.scss +0 -2
  168. package/assets/sass/components/collapsible-side.scss +91 -95
  169. package/assets/sass/components/content.component.scss +18 -0
  170. package/assets/sass/components/inline-edit.scss +2 -0
  171. package/assets/sass/components/{marketing.scss → marketing.component.scss} +2 -6
  172. package/assets/sass/components/menu.component.scss +118 -31
  173. package/assets/sass/components/menu.scss +68 -7
  174. package/assets/sass/components/milestone.scss +207 -0
  175. package/assets/sass/components/multiselect.scss +3 -0
  176. package/assets/sass/components/nav.component.scss +1 -0
  177. package/assets/sass/components/nav.global.scss +30 -0
  178. package/assets/sass/components/rank.component.scss +197 -33
  179. package/assets/sass/components/rankings.component.scss +39 -35
  180. package/assets/sass/components/rankings.global.scss +66 -10
  181. package/assets/sass/components/split-button.component.scss +77 -0
  182. package/assets/sass/components/table-basic.global.scss +2 -4
  183. package/assets/sass/components/table.global.scss +4 -4
  184. package/assets/sass/elements/badge-tag.scss +5 -1
  185. package/assets/sass/elements/buttons--compact.scss +4 -0
  186. package/assets/sass/elements/buttons--global.scss +1 -1
  187. package/assets/sass/elements/details.scss +0 -1
  188. package/assets/sass/elements/dialog.scss +1 -3
  189. package/assets/sass/elements/forms.scss +148 -22
  190. package/assets/sass/elements/links.scss +132 -4
  191. package/assets/sass/elements/lists.scss +61 -0
  192. package/assets/sass/elements/popover.scss +64 -10
  193. package/assets/sass/elements/toggle-button.scss +7 -8
  194. package/assets/sass/elements/type.scss +7 -10
  195. package/assets/sass/foundations/reboot.scss +3 -3
  196. package/assets/sass/templates/form.scss +0 -2
  197. package/assets/ts/components/actionbar/actionbar.component.ts +49 -23
  198. package/assets/ts/components/advanced-select/advanced-select.component.ts +74 -0
  199. package/assets/ts/components/calendar/calendar.component.ts +1460 -0
  200. package/assets/ts/components/card/card.component.ts +22 -14
  201. package/assets/ts/components/collapsible-side/collapsible-side.component.ts +53 -12
  202. package/assets/ts/components/content/content.component.ts +78 -0
  203. package/assets/ts/components/marketing/marketing.component.ts +1 -1
  204. package/assets/ts/components/menu/menu.component.ts +162 -173
  205. package/assets/ts/components/milestone/milestone.component.ts +45 -0
  206. package/assets/ts/components/milestone-group/milestone-group.component.ts +41 -0
  207. package/assets/ts/components/multiselect/multiselect.component.ts +69 -3
  208. package/assets/ts/components/nav/nav.component.ts +25 -0
  209. package/assets/ts/components/notification/notification.component.ts +34 -11
  210. package/assets/ts/components/rank/rank.component.ts +345 -214
  211. package/assets/ts/components/rankings/rankings.component.ts +28 -15
  212. package/assets/ts/components/search/search.component.ts +6 -4
  213. package/assets/ts/components/split-button/split-button.component.ts +69 -0
  214. package/assets/ts/components/table/table.component.ts +14 -0
  215. package/assets/ts/components/table-ajax/table-ajax.component.ts +14 -0
  216. package/assets/ts/components/table-no-submit/table-no-submit.component.ts +14 -0
  217. package/assets/ts/components/table-submit/table-submit.component.ts +14 -0
  218. package/assets/ts/components/video-card/video-card.component.ts +2 -3
  219. package/assets/ts/components.ts +63 -0
  220. package/assets/ts/modules/advanced-select.ts +125 -0
  221. package/assets/ts/modules/dialogs.ts +64 -61
  222. package/assets/ts/modules/dynamicEvents.ts +12 -1
  223. package/assets/ts/modules/milestone-group.ts +42 -0
  224. package/assets/ts/modules/milestone.ts +122 -0
  225. package/assets/ts/modules/table.ts +15 -1
  226. package/assets/ts/modules/videos.ts +19 -37
  227. package/assets/ts/scripts.ts +5 -3
  228. package/dist/components.es.js +41 -1923
  229. package/dist/components.umd.js +127 -171
  230. package/package.json +1 -1
  231. package/src/components/AdvancedSelect/AdvancedSelect.vue +23 -0
  232. package/src/components/Calendar/Calendar.vue +26 -0
  233. package/src/components/Card/Card.vue +1 -1
  234. package/src/components/CollapsibleSideMenu/CollapsibleSideMenu.vue +7 -13
  235. package/src/components/Content/Content.vue +23 -0
  236. package/src/components/Milestones/Milestone.vue +27 -0
  237. package/src/components/Milestones/MilestoneGroup.vue +27 -0
  238. package/src/components/Rank/Rank.vue +1 -2
  239. package/src/components/Rankings/Rankings.vue +9 -10
  240. package/src/components/SplitButton/README.md +19 -0
  241. package/src/components/SplitButton/SplitButton.vue +26 -0
  242. package/src/index.js +44 -41
  243. package/assets/css/components/marketing.css +0 -1
  244. package/assets/css/components/marketing.css.map +0 -1
  245. package/assets/css/components/nav.old.css +0 -1
  246. package/assets/css/components/nav.old.css.map +0 -1
  247. package/assets/sass/components/nav.old.scss +0 -891
@@ -0,0 +1,1460 @@
1
+ import { trackComponent, trackComponentRegistered } from '../_global';
2
+ import { uniqueID } from '../../modules/helpers';
3
+
4
+ trackComponentRegistered('iam-calendar');
5
+
6
+ class iamCalendar extends HTMLElement {
7
+ constructor() {
8
+ super();
9
+ this.attachShadow({ mode: 'open' });
10
+
11
+ const assetLocation = document.body.hasAttribute('data-assets-location')
12
+ ? document.body.getAttribute('data-assets-location')
13
+ : '/assets';
14
+
15
+ const loadCSS = `@import "${assetLocation}/css/components/calendar.component.css";`;
16
+
17
+
18
+ const weekViewOnly = `<table class="table--day" role="presentation"><tbody>
19
+ <tr class="allday"><th>All day</th></tr>
20
+ <tr><th data-hour="0">00</th></tr>
21
+ <tr><th data-hour="1">01</th></tr>
22
+ <tr><th data-hour="2">02</th></tr>
23
+ <tr><th data-hour="3">03</th></tr>
24
+ <tr><th data-hour="4">04</th></tr>
25
+ <tr><th data-hour="5">05</th></tr>
26
+ <tr><th data-hour="6">06</th></tr>
27
+ <tr><th data-hour="7">07</th></tr>
28
+ <tr><th data-hour="8">08</th></tr>
29
+ <tr><th data-hour="9">09</th></tr>
30
+ <tr><th data-hour="10">10</th></tr>
31
+ <tr><th data-hour="11">11</th></tr>
32
+ <tr><th data-hour="12">12</th></tr>
33
+ <tr><th data-hour="13">13</th></tr>
34
+ <tr><th data-hour="14">14</th></tr>
35
+ <tr><th data-hour="15">15</th></tr>
36
+ <tr><th data-hour="16">16</th></tr>
37
+ <tr><th data-hour="17">17</th></tr>
38
+ <tr><th data-hour="18">18</th></tr>
39
+ <tr><th data-hour="19">19</th></tr>
40
+ <tr><th data-hour="20">20</th></tr>
41
+ <tr><th data-hour="21">21</th></tr>
42
+ <tr><th data-hour="22">22</th></tr>
43
+ <tr><th data-hour="23">23</th></tr>
44
+ </tbody></table>`;
45
+
46
+ const template = document.createElement('template');
47
+
48
+
49
+ template.innerHTML = `
50
+ <style>
51
+ ${loadCSS}
52
+ ${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
53
+ </style>
54
+ <div class="calendar__container">
55
+
56
+ <div class="calendar__controls">
57
+ <button id="today-button" class="btn btn-action">Today</button>
58
+
59
+
60
+ <button id="prev-button" class="btn btn-action fa-chevron-left border-0"><span class="visually-hidden">previous</span></button>
61
+ <div class="calendar__datepicker">
62
+ <span class="calendar__title"></span>
63
+ <input type="date" id="date" name="date" />
64
+ </div>
65
+ <button id="next-button" class="btn btn-action fa-chevron-right border-0"><span class="visually-hidden">Next</span></button>
66
+
67
+ <hr/>
68
+
69
+
70
+ <select name="view" id="view" class="btn btn-action">
71
+
72
+ <button>
73
+ <selectedcontent></selectedcontent> <i class="fa-regular fa-chevron-down"></i>
74
+ </button>
75
+
76
+ <option value="month"><i class="fa-light fa-calendar-days"></i>Month</option>
77
+ <option value="week"><i class="fa-light fa-calendar-week"></i>Week</option>
78
+ <option value="day"><i class="fa-light fa-calendar-day"></i>Day</option>
79
+ <option value="list"><i class="fa-light fa-list"></i>List</option>
80
+ <option value="year"><i class="fa-light fa-calendars"></i>Year</option>
81
+ </select>
82
+
83
+ <label class="tag tag--toggle"><input type="checkbox" name="split" value="true">Split view</label>
84
+
85
+ <button id="filters-button" class="btn btn-action"><i class="fa-light fa-sliders"></i><span class="visually-hidden">Filters</span></button>
86
+
87
+ <button id="settings-button" class="btn btn-action"><i class="fa-light fa-gear"></i><span class="visually-hidden">Settings</span></button>
88
+
89
+ </div>
90
+
91
+ <dialog id="settings">
92
+ <button class="dialog__close">Close</button>
93
+ <span class="h3">Calendar settings</span>
94
+
95
+ <fieldset id="workday" class="mb-5">
96
+ <label>Start time <span><input type="time" id="start-time" name="start-time" step="3600" value="08:00" /><span class="suffix fa-regular fa-clock" aria-hidden="true"></span></span></label>
97
+ <label>End time <span><input type="time" id="end-time" name="end-time" step="3600" value="18:00" /><span class="suffix fa-regular fa-clock" aria-hidden="true"></span></span></label>
98
+
99
+ </fieldset>
100
+
101
+ <hr/>
102
+ <fieldset>
103
+ <span class="label">Show weekends</span>
104
+ <input type="radio" name="weekends" id="weekends-yes" tabindex="-1">
105
+ <label for="weekends-yes" class="d-inline-block">Yes</label>
106
+ <input type="radio" name="weekends" id="weekends-no" tabindex="-1">
107
+ <label for="weekends-no" class="d-inline-block">No</label>
108
+ </fieldset>
109
+ <hr/>
110
+ <button class="btn btn-primary">Save settings</button>
111
+ <button class="btn btn-secondary">Cancel</button>
112
+
113
+ </dialog>
114
+
115
+
116
+ <div class="calendar__wrapper">
117
+
118
+ <div id="week-view-corner" class="calendar">
119
+ <table>
120
+ <thead>
121
+ <tr>
122
+ <th class="column-header">Empty</th>
123
+ </tr>
124
+ </thead>
125
+ <tbody>
126
+ <tr class="allday">
127
+ <th>All day</th>
128
+ </tr>
129
+ </tbody>
130
+ </table>
131
+ </div>
132
+
133
+ <div id="week-view-header" class="calendar">
134
+ <table>
135
+ <thead>
136
+ </thead>
137
+ <tbody>
138
+ </tbody>
139
+ </table>
140
+ </div>
141
+
142
+ <div id="week-view-side">${weekViewOnly}</div>
143
+
144
+ <div class="calendar month-wrapper" id="calendar" part="calendar">
145
+ <table>
146
+ <thead>
147
+ </thead>
148
+ <tbody>
149
+ </tbody>
150
+ </table>
151
+ </div>
152
+
153
+ <div id="year-view">
154
+ </div>
155
+ </div>
156
+
157
+
158
+ <slot></slot>
159
+
160
+ </div>
161
+ `;
162
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
163
+
164
+
165
+ this.monthArray = ["January","February","March","April","May","June","July","August","September","October","November","December"];
166
+ this.dayArray = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
167
+
168
+ this.english_ordinal_rules = new Intl.PluralRules("en", {type: "ordinal"});
169
+ this.suffixes = {
170
+ one: "st",
171
+ two: "nd",
172
+ few: "rd",
173
+ other: "th"
174
+ };
175
+
176
+ this.calendars = ['Default']; // TO DO allow for these to be set via the component data attributes
177
+ this.eventTypes = []; // TO DO allow for these to be set via the component data attributes
178
+
179
+ this.pauseObserver = false;
180
+ }
181
+
182
+ createThead(sundayFirst: false): string {
183
+
184
+ if(sundayFirst)
185
+ return `<tr>
186
+ <th class="column-header sunday"><span class="long-day-name">Sunday</span><span class="short-day-name" role="presentation">Sun</span></th>
187
+ <th class="column-header monday"><span class="long-day-name">Monday</span><span class="short-day-name" role="presentation">Mon</span></th>
188
+ <th class="column-header tuesday"><span class="long-day-name">Tuesday</span><span class="short-day-name" role="presentation">Tues</span></th>
189
+ <th class="column-header wednesday"><span class="long-day-name">Wednesday</span><span class="short-day-name" role="presentation">Wed</span></th>
190
+ <th class="column-header thursday"><span class="long-day-name">Thursday</span><span class="short-day-name" role="presentation">Thurs</span></th>
191
+ <th class="column-header friday"><span class="long-day-name">Friday</span><span class="short-day-name" role="presentation">Fri</span></th>
192
+ <th class="column-header saturday"><span class="long-day-name">Saturday</span><span class="short-day-name" role="presentation">Sat</span></th>
193
+ </tr>`;
194
+
195
+ return `<tr>
196
+ <th class="column-header monday"><span class="long-day-name">Monday</span><span class="short-day-name" role="presentation">Mon</span></th>
197
+ <th class="column-header tuesday"><span class="long-day-name">Tuesday</span><span class="short-day-name" role="presentation">Tues</span></th>
198
+ <th class="column-header wednesday"><span class="long-day-name">Wednesday</span><span class="short-day-name" role="presentation">Wed</span></th>
199
+ <th class="column-header thursday"><span class="long-day-name">Thursday</span><span class="short-day-name" role="presentation">Thurs</span></th>
200
+ <th class="column-header friday"><span class="long-day-name">Friday</span><span class="short-day-name" role="presentation">Fri</span></th>
201
+ <th class="column-header saturday"><span class="long-day-name">Saturday</span><span class="short-day-name" role="presentation">Sat</span></th>
202
+ <th class="column-header sunday"><span class="long-day-name">Sunday</span><span class="short-day-name" role="presentation">Sun</span></th>
203
+ </tr>`;
204
+ }
205
+
206
+ numberDaysInMonth(year, month): Date {
207
+ return new Date(year, month, 0).getDate();
208
+ }
209
+
210
+ getOrdinalNumber(number): string {
211
+ const category = this.english_ordinal_rules.select(number);
212
+ const suffix = this.suffixes[category];
213
+ return (number + suffix);
214
+ }
215
+
216
+ setToMonday( date ): Date {
217
+ const day = date.getDay() || 7;
218
+ if( day !== 1 )
219
+ date.setHours(-24 * (day - 1));
220
+ return date;
221
+ }
222
+
223
+ setToSunday( date ): Date {
224
+
225
+ const monday = this.setToMonday(date);
226
+ const sunday = new Date(monday);
227
+
228
+ sunday.setDate(sunday.getDate() + 6);
229
+ return sunday;
230
+ }
231
+
232
+ getTitle(dateStr,view): string {
233
+
234
+ const date = new Date(dateStr);
235
+ const month = date.getMonth();
236
+ const year = date.getFullYear();
237
+ const day = date.getDate();
238
+ const dayOfWeek = date.getDay() ? date.getDay(): 7;
239
+
240
+ if(view == "week"){
241
+
242
+ const monday = this.setToMonday(new Date(dateStr));
243
+ const sunday = this.setToSunday(new Date(dateStr));
244
+
245
+ const mondayMonth = monday.getMonth();
246
+ const mondayYear = monday.getFullYear();
247
+ const mondayDay = monday.getDate();
248
+
249
+ const sundayMonth = sunday.getMonth();
250
+ const sundayYear = sunday.getFullYear();
251
+ const sundayDay = sunday.getDate();
252
+
253
+ return `${this.getOrdinalNumber(mondayDay)} ${mondayMonth != sundayMonth ? this.monthArray[sundayMonth] : ''} ${mondayYear != sundayYear ? mondayYear : ''} - ${this.getOrdinalNumber(sundayDay)} ${this.monthArray[sundayMonth]} ${sundayYear}`;
254
+ }
255
+ else if(view == "day"){
256
+
257
+ return `${this.dayArray[dayOfWeek]} ${this.getOrdinalNumber(day)} ${this.monthArray[month]} ${year}`;
258
+ }
259
+ else if(view == "year"){
260
+
261
+ return `${year}`;
262
+ }
263
+
264
+ return `${this.monthArray[month]} ${year}`;
265
+ }
266
+
267
+ createCalendar(selectedDate, today, sundayFirst: false): string {
268
+
269
+ const date = new Date(selectedDate);
270
+ const month = date.getMonth();
271
+ const year = date.getFullYear();
272
+ const day = date.getDate();
273
+ const selectedDateStr = `${year}-${String(month+1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
274
+ const daysThisMonth = this.numberDaysInMonth(year, month+1);
275
+ const startOfMonth = new Date(`${year}-${String(month+1).padStart(2, "0")}-01`);
276
+ const endOfMonth = new Date(`${year}-${String(month+1).padStart(2, "0")}-${daysThisMonth}`);
277
+ const startDay = startOfMonth.getDay() != 0 ? startOfMonth.getDay() : 7;
278
+ const endDay = endOfMonth.getDay() != 0 ? endOfMonth.getDay() : 7;
279
+ const loopDays = daysThisMonth + startDay + (7 - endDay - 1);
280
+
281
+ // Get the previous month
282
+ const prevMonthDate = new Date(selectedDate);
283
+ prevMonthDate.setMonth(prevMonthDate.getMonth() -1);
284
+ const prevMonth = prevMonthDate.getMonth();
285
+ const prevMonthYear = prevMonthDate.getFullYear();
286
+ const daysPrevMonth = this.numberDaysInMonth(year, month);
287
+
288
+ // Get the next month
289
+ const nextMonthDate = new Date(selectedDate);
290
+ nextMonthDate.setMonth(nextMonthDate.getMonth() + 1);
291
+ const nextMonth = nextMonthDate.getMonth();
292
+ const nextMonthYear = nextMonthDate.getFullYear();
293
+
294
+ // Get calendars
295
+
296
+ if(!this.hasAttribute('data-calendars')){
297
+ Array.from(this.querySelectorAll('button[data-calendar]')).forEach((element) => {
298
+
299
+ // Scan through the buttons and look forunique calendar names
300
+ if(!(this.calendars.includes(element.getAttribute('data-calendar'))))
301
+ this.calendars.push(element.getAttribute('data-calendar'));
302
+ })
303
+ }
304
+
305
+ // Create tbody string by looping through the number of days in month plus some days before and after
306
+ let tbodyContent = `<tr>`;
307
+
308
+ for (let i = (sundayFirst ? 0 : 1); i <= loopDays; i++) {
309
+
310
+ const loopDay = i - (startDay - 1);
311
+ const loopDate = `${year}-${String(month+1).padStart(2, "0")}-${String(loopDay).padStart(2, "0")}`
312
+ const dayOfWeek = i%7;
313
+
314
+ tbodyContent += `<td class="day--${this.dayArray[dayOfWeek].toLowerCase()} ${loopDate == today ? 'today' : ''} ${loopDate == selectedDateStr ? 'selected' : ''} ${i < startDay ? 'prev-month' : ''} ${loopDay > daysThisMonth ? 'next-month' : ''}">`;
315
+
316
+ // prev month days
317
+ if(i < startDay){
318
+
319
+ const adjustedLoopDay = daysPrevMonth - (startDay - 1 - i);
320
+ const adjustedLoopDate = `${prevMonthYear}-${String(prevMonth+1).padStart(2, "0")}-${String(adjustedLoopDay).padStart(2, "0")}`
321
+
322
+ tbodyContent += `<time class="column-header" datetime="${adjustedLoopDate}" title="${this.dayArray[dayOfWeek]} ${loopDay} ${this.monthArray[prevMonth]} ${year}"><span class="day-of-week">${this.dayArray[dayOfWeek]} </span><span class="day">${adjustedLoopDay}</span> <span class="month">${this.monthArray[prevMonth]}</span></time>`;
323
+ tbodyContent += this.addDay(adjustedLoopDate, this.calendars);
324
+ }
325
+
326
+ if(i >= startDay && loopDay <= daysThisMonth){
327
+
328
+ tbodyContent += `<time class="column-header" datetime="${loopDate}" title="${this.dayArray[dayOfWeek]} ${loopDay} ${this.monthArray[month]} ${year}"><span class="day-of-week">${this.dayArray[dayOfWeek]} </span><span class="day">${loopDay}</span> <span class="month">${this.monthArray[month]}</span></time>`;
329
+ tbodyContent += this.addDay(loopDate, this.calendars);
330
+ }
331
+
332
+ // next month days
333
+ if(loopDay > daysThisMonth){
334
+
335
+ const adjustedLoopDay = i - (startDay - 1) - daysThisMonth;
336
+ const adjustedLoopDate = `${nextMonthYear}-${String(nextMonth+1).padStart(2, "0")}-${String(adjustedLoopDay).padStart(2, "0")}`
337
+
338
+ tbodyContent += `<time class="column-header" datetime="${adjustedLoopDate}" title="${this.dayArray[dayOfWeek]} ${loopDay} ${this.monthArray[nextMonth]} ${year}"><span class="day-of-week">${this.dayArray[dayOfWeek]} </span><span class="day">${adjustedLoopDay}</span> <span class="month">${this.monthArray[nextMonth]}</span></time>`;
339
+ tbodyContent += this.addDay(adjustedLoopDate, this.calendars);
340
+ }
341
+
342
+ tbodyContent += '</td>';
343
+
344
+ // Close row and start a new one
345
+ if(((sundayFirst ? i+1 : i) % 7) === 0 && i != loopDays){
346
+ tbodyContent += `</tr><tr>`;
347
+ }
348
+
349
+ }
350
+ tbodyContent += '</tr>';
351
+
352
+ return tbodyContent;
353
+ }
354
+
355
+ addDay(day, calendars: []): string {
356
+
357
+ let htmlTable = '<table class="table--day">';
358
+ htmlTable += `<thead><tr><th>time</th>`;
359
+ calendars.forEach(calendarTitle => {
360
+
361
+ htmlTable += `<th class="column-header">${calendarTitle}</th>`;
362
+ });
363
+ htmlTable += `</tr></thead>`;
364
+
365
+ htmlTable += `<tbody>`;
366
+ htmlTable += `<tr class="allday"><th>All day</th>`;
367
+ calendars.forEach(calendarTitle => {
368
+
369
+ htmlTable += `<td datetime="${day}" data-calendar="${calendarTitle}"><span datetime="${day}"></span></td>`;
370
+ });
371
+ htmlTable += `</tr>`;
372
+
373
+ for (let i = 0; i < 24; i++) {
374
+
375
+ htmlTable += `<tr class="hour${i}"><th data-hour="${i}">${i}${i < 12 ? 'am' : 'pm'}</th>`;
376
+ calendars.forEach(calendarTitle => {
377
+
378
+ htmlTable += `<td datetime="${day}T${String(i).padStart(2, "0")}:00" data-calendar="${calendarTitle}"><span datetime="${day}T${String(i).padStart(2, "0")}:00"></span><span datetime="${day}T${String(i).padStart(2, "0")}:15"></span><span datetime="${day}T${String(i).padStart(2, "0")}:30"></span><span datetime="${day}T${String(i).padStart(2, "0")}:45"></span></td>`;
379
+ });
380
+ htmlTable += `</tr>`;
381
+ }
382
+ htmlTable += `</tbody>`;
383
+ htmlTable += '</table>';
384
+
385
+ return htmlTable;
386
+ }
387
+
388
+ addEvents(): void {
389
+
390
+ function setDefaultEventValues(component, element, index): void {
391
+
392
+ const datetime = element.getAttribute('datetime')
393
+ const datetimeArr = datetime.split('T');
394
+ let id = element.getAttribute('id');
395
+
396
+ // Add ID
397
+ if(!element.hasAttribute('id')){
398
+ id = `event${uniqueID(index)}`;
399
+ element.setAttribute('id',id);
400
+ }
401
+
402
+ // Wrap content in span for formatting in week/day view
403
+ if(!element.querySelector('span:not(.tooltip__content')){
404
+ element.innerHTML = `<span>${element.innerHTML}</span>`;
405
+ }
406
+
407
+ // Add event type enum so we can set the correct colours
408
+ //if(!element.hasAttribute('data-event-type-enum') && element.hasAttribute('data-event-type')){
409
+
410
+ const eventType = element.getAttribute('data-event-type');
411
+
412
+ if(!component.eventTypes.includes(eventType))
413
+ component.eventTypes.push(eventType);
414
+
415
+ element.setAttribute('data-event-type-enum', component.eventTypes.indexOf(eventType) + 1);
416
+ //}
417
+
418
+ // Add calendar enum so we can set the correct colours
419
+ if(element.hasAttribute('data-calendar')){
420
+
421
+ const calendar = element.getAttribute('data-calendar');
422
+
423
+ if(!component.calendars.includes(calendar))
424
+ component.calendars.push(calendar);
425
+
426
+ element.setAttribute('data-calendar-enum', component.calendars.indexOf(calendar) + 1);
427
+ }
428
+
429
+ if(!element.hasAttribute('data-calendar-enum')){
430
+ element.setAttribute('data-calendar-enum', 1);
431
+ }
432
+
433
+ if(!element.hasAttribute('data-hours') && !element.hasAttribute('data-days')){
434
+
435
+ if(datetimeArr[1]){
436
+ element.setAttribute('data-hours', 1);
437
+ }
438
+ else {
439
+
440
+ element.setAttribute('data-days', 1);
441
+ }
442
+ }
443
+
444
+
445
+
446
+ let getRoundedDate = (minutes, d=new Date()) => {
447
+
448
+ let ms = 1000 * 60 * minutes; // convert minutes to ms
449
+ let roundedDate = new Date(Math.round(d.getTime() / ms) * ms);
450
+
451
+
452
+ const newMonth = roundedDate.getMonth();
453
+ const newYear = roundedDate.getFullYear();
454
+ const newDay = roundedDate.getDate();
455
+ const newMinutes = roundedDate.getMinutes();
456
+ const newHour = roundedDate.getHours();
457
+
458
+ const strRoundedDate = `${newYear}-${String(newMonth+1).padStart(2, "0")}-${String(newDay).padStart(2, "0")}T${String(newHour).padStart(2, "0")}:${String(newMinutes).padStart(2, "0")}`;
459
+
460
+
461
+ return strRoundedDate;
462
+ }
463
+
464
+
465
+ if(datetimeArr[1]){
466
+ element.setAttribute('data-start', datetimeArr[1]);
467
+ element.querySelector(':scope > span').setAttribute('data-start', datetimeArr[1]);
468
+
469
+ const roundedDatetime = getRoundedDate(15, new Date(datetime));
470
+ element.setAttribute('datetime',roundedDatetime);
471
+
472
+
473
+ console.log(roundedDatetime);
474
+ }
475
+
476
+
477
+ if(element.querySelector('.tooltip__content')){
478
+
479
+ const tooltip = element.querySelector('.tooltip__content');
480
+
481
+ tooltip.style.positionAnchor = `--${id}`;
482
+
483
+ element.style.anchorName = `--${id}`
484
+ }
485
+
486
+
487
+ element.classList.add('defaults-added');
488
+ }
489
+
490
+ function adjustEvent(component, element, continued: false): void {
491
+
492
+ const datetime = element.getAttribute('datetime');
493
+
494
+ const date = new Date(datetime);
495
+ const dayOfWeek = date.getDay() ? date.getDay(): 7;
496
+
497
+ // Locate where we need to add slots for the buttons to go - We need duplicate slots for the split view and fixed header
498
+ const timeTd = component.shadowRoot.querySelector(`.month-wrapper .table--day td:has(span[datetime="${datetime}"])${element.hasAttribute('data-calendar') ? `[data-calendar="${element.getAttribute('data-calendar').replace('_','')}"]` : ''}`);
499
+ const timeTdHeader = component.shadowRoot.querySelector(`#week-view-header .table--day td:has(span[datetime="${datetime}"])${element.hasAttribute('data-calendar') ? `[data-calendar="${element.getAttribute('data-calendar').replace('_','')}"]` : ''}`);
500
+
501
+ if(timeTdHeader && timeTdHeader.closest('tr').classList.contains("allday")){
502
+
503
+ // Add the alldays slot for the fixed header
504
+ if(!timeTdHeader.querySelector(`slot[name="${datetime}${element.hasAttribute('data-calendar') ? `-${element.getAttribute('data-calendar').replace('_','')}` : ''}-header]"`)){
505
+ timeTdHeader.querySelector(`span[datetime="${datetime}"]`).insertAdjacentHTML('beforeEnd',`<slot name="${datetime}${element.hasAttribute('data-calendar') ? `-${element.getAttribute('data-calendar').replace('_','')}` : ''}-header" class="${continued ? 'continued': ''}"></slot>`)
506
+ }
507
+ }
508
+
509
+
510
+ const dateTd = timeTd?.parentElement?.closest('td');
511
+
512
+ // original event needs a slot name adding
513
+ element.setAttribute('slot',`${datetime}${element.hasAttribute('data-calendar') ? `-${element.getAttribute('data-calendar').replace('_','')}` : ''}`);
514
+
515
+ // Add matching slot to the event element to have it show in the correct place on the calendar
516
+ if(timeTd){
517
+
518
+ // Add the default slot
519
+ if(!timeTd.querySelector(`slot[name="${datetime}${element.hasAttribute('data-calendar') ? `-${element.getAttribute('data-calendar').replace('_','')}` : ''}"]`)){
520
+ timeTd.querySelector(`span[datetime="${datetime}"]`).insertAdjacentHTML('beforeEnd',`<slot name="${datetime}${element.hasAttribute('data-calendar') ? `-${element.getAttribute('data-calendar').replace('_','')}` : ''}" class="${continued ? 'continued': ''}"></slot>`)
521
+ }
522
+
523
+ // Set the classes need to create the grey bars in the mobile month view
524
+ const events = dateTd.hasAttribute('data-events') ? parseInt(dateTd.getAttribute('data-events')) : 0;
525
+ let hours = dateTd.hasAttribute('data-hours') ? parseFloat(dateTd.getAttribute('data-hours')) : 0;
526
+ hours += element.hasAttribute('data-hours') ? parseFloat(element.getAttribute('data-hours')) : 0;
527
+
528
+ dateTd.setAttribute('data-events', parseInt(events) + 1);
529
+
530
+ if((events + 1) > 2)
531
+ dateTd.setAttribute('data-more', (parseInt(events) + 1) - 2);
532
+
533
+ dateTd.setAttribute('data-hours', hours);
534
+
535
+ dateTd.classList.add('has-event');
536
+
537
+ if(timeTd.closest('tr').classList.contains('has-event'))
538
+ timeTd.closest('tr').classList.add('multiple-event');
539
+ else
540
+ timeTd.closest('tr').classList.add('has-event');
541
+
542
+ if(hours > 2)
543
+ dateTd.classList.add('multi-events');
544
+
545
+ if(hours > 4)
546
+ dateTd.classList.add('busy-day');
547
+
548
+ if(element.hasAttribute('data-days'))
549
+ dateTd.classList.add('all-day');
550
+
551
+ if(element.classList.contains('continued'))
552
+ dateTd.classList.add('continued-day');
553
+ }
554
+
555
+ // Add CSS properties so we can control the size of the event elements for day and week view
556
+ if(element.hasAttribute('data-hours'))
557
+ element.style.setProperty('--event-height',`${parseInt(element.getAttribute('data-hours')) * (1.09375 * 4)}rem`);
558
+
559
+ if(element.hasAttribute('data-days') && !element.classList.contains('processed')){
560
+
561
+ const eventDayTotal = element.getAttribute('data-days')
562
+
563
+ element.style.setProperty('--event-width',`${eventDayTotal * 100}%`);
564
+ element.style.setProperty('--event-max-width',`${(8 - dayOfWeek) * 100}%`);
565
+ element.classList.add('allday-event');
566
+
567
+
568
+ // Create a duplicate event for each day the orginal
569
+ for (let i = 1; i < eventDayTotal; i++) {
570
+
571
+ const cloneElement = element.cloneNode(true);
572
+ cloneElement.removeAttribute('data-days');
573
+ cloneElement.removeAttribute('style');
574
+ cloneElement.classList.add('continued');
575
+ cloneElement.classList.add('allday-event');
576
+
577
+
578
+ const id = `event${uniqueID(i)}`;
579
+ cloneElement.setAttribute('id',id);
580
+
581
+
582
+ if(cloneElement.querySelector('.tooltip__content')){
583
+
584
+ const tooltip = cloneElement.querySelector('.tooltip__content');
585
+ tooltip.style.positionAnchor = `--${id}`;
586
+ cloneElement.style.anchorName = `--${id}`
587
+ }
588
+
589
+
590
+ const newDate = new Date(datetime);
591
+ newDate.setDate(newDate.getDate() + i);
592
+
593
+ const newMonth = newDate.getMonth();
594
+ const newYear = newDate.getFullYear();
595
+ const newDay = newDate.getDate();
596
+ const newDayOfWeek = newDate.getDay() ? newDate.getDay(): 7;
597
+
598
+ const strCloneEvent = `${newYear}-${String(newMonth+1).padStart(2, "0")}-${String(newDay).padStart(2, "0")}`;
599
+
600
+ cloneElement.setAttribute('data-original-datetime',element.getAttribute('datetime'));
601
+ cloneElement.setAttribute('datetime',strCloneEvent);
602
+
603
+ element.after(cloneElement); // Add after original
604
+ adjustEvent(component, cloneElement, true);
605
+
606
+ if(newDayOfWeek == 1){ // Monday
607
+
608
+ cloneElement.style.setProperty('--event-width',`${(eventDayTotal - i) * 100}%`);
609
+ cloneElement.style.setProperty('--event-max-width',`${(8 - newDayOfWeek) * 100}%`);
610
+
611
+ cloneElement.classList.remove('continued');
612
+ }
613
+ }
614
+ }
615
+
616
+ // Add flag so we dont have to re-do the above
617
+ element.classList.add('processed');
618
+ }
619
+
620
+ this.pauseObserver = true;
621
+
622
+ Array.from(this.querySelectorAll('button[datetime]')).forEach((element, index) => {
623
+
624
+ setDefaultEventValues(this,element,index);
625
+ adjustEvent(this, element);
626
+
627
+ });
628
+
629
+ setTimeout(() => {
630
+ this.pauseObserver = false;
631
+ }, "500");
632
+
633
+ }
634
+
635
+ addJSEvents(component): void {
636
+
637
+ // Add events to the newly created calendar
638
+ const title = component.shadowRoot?.querySelector('.calendar__title');
639
+ const datePicker = component.shadowRoot?.querySelector(`#date`);
640
+ const viewPicker = component.shadowRoot?.querySelector(`#view`);
641
+ const yearView = this.shadowRoot?.querySelector('#year-view');
642
+
643
+ const today = new Date();
644
+ const date = today.getDate();
645
+ const month = today.getMonth();
646
+ const year = today.getFullYear();
647
+ const strToday = `${year}-${String(month+1).padStart(2, "0")}-${String(date).padStart(2, "0")}`;
648
+
649
+ const tbody = component.shadowRoot?.querySelector('#calendar > table > tbody');
650
+
651
+ // clicking on the day istelf
652
+ Array.from(component.shadowRoot.querySelectorAll('.month-wrapper > table > tbody > tr > td:has(slot)')).forEach((element) => {
653
+
654
+ element.addEventListener('click', (event) => {
655
+
656
+ if(!event.target.matches('button')) {
657
+
658
+ const elementDate = element.querySelector('time').getAttribute('datetime');
659
+ datePicker.value = elementDate;
660
+
661
+ Array.from(tbody.querySelectorAll(':scope > tr > td')).forEach((innerelement) => {
662
+ innerelement.classList.remove('selected');
663
+ });
664
+
665
+ element.classList.add('selected');
666
+
667
+ // Go to day if the in month view with out split view enabled
668
+
669
+ if(component.shadowRoot.querySelector('[name="split"]:checked') && viewPicker.value == "month"){
670
+
671
+ Array.from(component.querySelectorAll(`[data-slot]`)).forEach((button) => {
672
+ button.setAttribute('slot',button.getAttribute('data-slot'));
673
+ });
674
+
675
+ Array.from(component.querySelectorAll(`[slot^="${datePicker.value}"]`)).forEach((button) => {
676
+
677
+ button.setAttribute('data-slot',button.getAttribute('slot'));
678
+ button.removeAttribute('slot');
679
+ });
680
+
681
+ }
682
+ else if(!component.shadowRoot.querySelector('[name="split"]:checked') && viewPicker.value == "month"){
683
+
684
+ viewPicker.value = "day";
685
+ title?.innerHTML = this.getTitle(datePicker.value,viewPicker.value);
686
+ component.scrollIntoPlace();
687
+ }
688
+ if(viewPicker.value == "year"){
689
+
690
+ viewPicker.value = "month";
691
+ yearView?.innerHTML = '';
692
+ tbody?.innerHTML = component.createCalendar(datePicker.value, strToday);
693
+ component.addEvents();
694
+ }
695
+ }
696
+ });
697
+ });
698
+
699
+ // Drag and drop
700
+ component.shadowRoot?.querySelectorAll(`#calendar .table--day td span`).forEach((element) => {
701
+
702
+ element.addEventListener("dragover", (ev) => {
703
+ ev.preventDefault();
704
+ return false;
705
+ });
706
+
707
+ element.addEventListener("dragenter", (ev) => {
708
+ ev.preventDefault();
709
+ element.classList.add('dragover');
710
+ });
711
+
712
+ element.addEventListener("dragleave", (ev) => {
713
+ ev.preventDefault();
714
+ element.classList.remove('dragover');
715
+ });
716
+
717
+ element.addEventListener("drop", (ev) => {
718
+ ev.preventDefault();
719
+
720
+ const droppedElement = component.querySelector(`#${ev.dataTransfer.getData("text")}`);
721
+ const td = element.closest('td');
722
+ const datetime = element.getAttribute('datetime');
723
+
724
+ element.classList.remove('dragover');
725
+
726
+ // Add a new slot to te span if needed
727
+ if(!element.querySelector(`slot[name="${datetime}${td.hasAttribute('data-calendar') ? `-${td.getAttribute('data-calendar').replace('_','')}]` : ''}]"`)){
728
+ element.insertAdjacentHTML('beforeEnd',`<slot name="${datetime}${td.hasAttribute('data-calendar') ? `-${td.getAttribute('data-calendar').replace('_','')}` : ''}" class=""></slot>`)
729
+ }
730
+
731
+ // Update the slot attribute to match the slot the event has been dropped on
732
+ droppedElement?.setAttribute('slot',`${datetime}${td.hasAttribute('data-calendar') ? `-${td.getAttribute('data-calendar').replace('_','')}` : ''}`)
733
+ });
734
+
735
+ });
736
+
737
+ // Watch for the event being resized
738
+ const resizeObserver = new ResizeObserver((entries) => {
739
+ for (const entry of entries) {
740
+
741
+ if(entry.target.classList.contains('mousedown'))
742
+ entry.target.classList.add('resizing');
743
+ }
744
+ });
745
+
746
+ if(component.hasAttribute('data-drag')) {
747
+
748
+ component.querySelectorAll(`button:not([draggable])`).forEach((element) => {
749
+
750
+ element.setAttribute('draggable','true');
751
+ element.addEventListener("dragstart", (ev) => {
752
+ ev.dataTransfer.setData("text", ev.target.id); // save the id for when dropped
753
+ });
754
+
755
+ // set onbserver
756
+ resizeObserver.observe(element);
757
+
758
+ element.addEventListener("mousedown", (ev) => {
759
+ element.classList.add('mousedown');
760
+ });
761
+
762
+ element.addEventListener("click", (ev) => {
763
+
764
+ if(element.classList.contains('resizing')){
765
+
766
+ ev.stopPropagation();
767
+ ev.stopImmediatePropagation();
768
+
769
+ element.classList.remove('mousedown');
770
+ element.classList.remove('resizing');
771
+
772
+ // Work out the evnt length in hours and set the height
773
+ const span = this.shadowRoot.querySelector(`span[datetime="${element.getAttribute('datetime')}"]`);
774
+ const spanStyles = window.getComputedStyle(span);
775
+ const hours = Math.round(parseInt(element.style.height)/parseInt(spanStyles.getPropertyValue("height"))) / 4;
776
+
777
+ element.setAttribute('data-hours',hours);
778
+ element.style.setProperty('--event-height',`${hours * (1.09375 * 4)}rem`);
779
+
780
+ element.style.height = "";
781
+
782
+ // to do dispatch event
783
+ }
784
+ });
785
+
786
+ });
787
+ }
788
+
789
+ component.querySelectorAll(`button`).forEach((element) => {
790
+
791
+ element.addEventListener("contextmenu", (event) => {
792
+
793
+ event.preventDefault();
794
+ event.stopPropagation();
795
+
796
+ });
797
+ });
798
+
799
+ component.shadowRoot?.querySelectorAll(`.month-wrapper > table > tbody > tr > td`).forEach((element) => {
800
+
801
+ element.addEventListener("contextmenu", (event) => {
802
+
803
+ event.preventDefault();
804
+
805
+ const customEvent = new CustomEvent('right-click', {
806
+ detail: {
807
+ 'clientX': event.clientX,
808
+ 'clientY': event.clientY,
809
+ 'element': element,
810
+ 'datetime': element.querySelector('time').getAttribute('datetime')
811
+ },
812
+ });
813
+
814
+ console.log(element);
815
+ this.dispatchEvent(customEvent);
816
+
817
+ });
818
+ });
819
+ }
820
+
821
+ paginateDate(direction, view, currentDate): string {
822
+
823
+ if(view == "month" || view == "list") {
824
+
825
+ const selectedDate = new Date(currentDate);
826
+
827
+ if(direction == "next")
828
+ selectedDate.setMonth(selectedDate.getMonth() + 1);
829
+ else
830
+ selectedDate.setMonth(selectedDate.getMonth() - 1);
831
+
832
+ const month = selectedDate.getMonth() + 1;
833
+ const year = selectedDate.getFullYear();
834
+
835
+ const strNextMonth = `${year}-${String(month).padStart(2, "0")}-01`;
836
+
837
+ return strNextMonth;
838
+ }
839
+ else if(view == "week") {
840
+
841
+ //const selectedDate = new Date(currentDate);
842
+ const monday = this.setToMonday(new Date(currentDate));
843
+
844
+ if(direction == "next")
845
+ monday.setDate(monday.getDate() + 7);
846
+ else
847
+ monday.setDate(monday.getDate() - 7);
848
+
849
+
850
+ const date = monday.getDate();
851
+ const month = monday.getMonth() + 1;
852
+ const year = monday.getFullYear();
853
+ const strNextWeek = `${year}-${String(month).padStart(2, "0")}-${String(date).padStart(2, "0")}`;
854
+
855
+ return strNextWeek;
856
+ }
857
+ else if(view == "year"){
858
+
859
+ const selectedDate = new Date(currentDate);
860
+
861
+ if(direction == "next")
862
+ selectedDate.setYear(selectedDate.getFullYear() + 1);
863
+ else
864
+ selectedDate.setYear(selectedDate.getFullYear() - 1);
865
+
866
+ const year = selectedDate.getFullYear();
867
+ const month = selectedDate.getMonth() + 1;
868
+
869
+ const strNextMonth = `${year}-${String(month).padStart(2, "0")}-01`;
870
+
871
+ return strNextMonth;
872
+ }
873
+
874
+ const nextDay = new Date(currentDate);
875
+
876
+ if(direction == "next")
877
+ nextDay.setDate(nextDay.getDate() + 1);
878
+ else
879
+ nextDay.setDate(nextDay.getDate() - 1);
880
+
881
+ const date = nextDay.getDate();
882
+ const month = nextDay.getMonth() + 1;
883
+ const year = nextDay.getFullYear();
884
+ const strNextDay = `${year}-${String(month).padStart(2, "0")}-${String(date).padStart(2, "0")}`;
885
+
886
+ return strNextDay;
887
+ }
888
+
889
+
890
+ setWeekDay(): void {
891
+
892
+ this.shadowRoot?.querySelectorAll('.out-of-hours').forEach(element => {
893
+ element.classList.remove('out-of-hours');
894
+ });
895
+
896
+
897
+ const startTime = parseInt(this.shadowRoot?.querySelector('#start-time').value.split(':')[0]);
898
+ const endTime = parseInt(this.shadowRoot?.querySelector('#end-time').value.split(':')[0]);
899
+
900
+ this.shadowRoot?.querySelectorAll('[data-hour]').forEach(element => {
901
+
902
+ const hour = parseInt(element.getAttribute('data-hour'));
903
+
904
+ if(hour < startTime)
905
+ element.classList.add('out-of-hours');
906
+
907
+ if(hour >= endTime)
908
+ element.classList.add('out-of-hours');
909
+ });
910
+
911
+ }
912
+
913
+ scrollIntoPlace(): void {
914
+
915
+ const fs = parseInt(window.getComputedStyle(document.body).getPropertyValue('font-size'));
916
+ const startTime = parseInt(this.shadowRoot?.querySelector('#start-time').value.split(':')[0]);
917
+ const scrollPos = startTime * (4.5 * fs);
918
+ const viewPicker = this.shadowRoot?.querySelector(`#view`);
919
+ const wrapper = this.shadowRoot.querySelector('.calendar__wrapper');
920
+
921
+ // scroll
922
+ if(viewPicker.value == "week")
923
+ wrapper.scrollTo(0,scrollPos); // TO DO work out how much to scroll by
924
+ else if(viewPicker.value == "day"){
925
+ wrapper.scrollTo(0,scrollPos); // TO DO work out how much to scroll by
926
+ }
927
+ }
928
+
929
+ setupSettings(): void {
930
+
931
+ const settingsButton = this.shadowRoot?.querySelector('#settings-button');
932
+ const settingsDialog = this.shadowRoot?.querySelector('#settings');
933
+
934
+ // Setup the pre-defined attributes and display the form elements to match
935
+ if(this.hasAttribute('data-hide-weekends'))
936
+ settingsDialog.querySelector('#weekends-no').checked = true;
937
+ else
938
+ settingsDialog.querySelector('#weekends-yes').checked = true;
939
+
940
+ if(this.hasAttribute('data-start-time'))
941
+ settingsDialog.querySelector('#start-time').value = this.getAttribute('data-start-time');
942
+ else
943
+ this.setAttribute('data-start-time', settingsDialog.querySelector('#start-time').value);
944
+
945
+ if(this.hasAttribute('data-end-time'))
946
+ settingsDialog.querySelector('#end-time').value = this.getAttribute('data-end-time');
947
+ else
948
+ this.setAttribute('data-end-time', settingsDialog.querySelector('#end-time').value);
949
+
950
+
951
+ // open dialog
952
+ settingsButton?.addEventListener('click', ()=> {
953
+
954
+ settingsDialog.showModal();
955
+ settingsDialog.focus();
956
+
957
+ const customEvent = new CustomEvent('open-settings');
958
+
959
+ this.dispatchEvent(customEvent);
960
+ });
961
+
962
+ // On clicking the save button, adjust the data attributes
963
+ settingsDialog?.addEventListener('click', (event)=> {
964
+
965
+ if (event && event.target.matches('button')) {
966
+
967
+ if(event.target.matches('.btn-primary')){
968
+
969
+ if(settingsDialog.querySelector('#weekends-no:checked'))
970
+ this.setAttribute('data-hide-weekends','true');
971
+ else
972
+ this.removeAttribute('data-hide-weekends');
973
+
974
+
975
+ this.setAttribute('data-start-time', settingsDialog.querySelector('#start-time').value);
976
+ this.setAttribute('data-end-time', settingsDialog.querySelector('#end-time').value);
977
+
978
+ this.setWeekDay();
979
+
980
+ const customEvent = new CustomEvent('save-settings');
981
+ this.dispatchEvent(customEvent);
982
+
983
+ }
984
+
985
+ const customEvent = new CustomEvent('close-settings');
986
+ this.dispatchEvent(customEvent);
987
+
988
+ settingsDialog.close();
989
+ }
990
+ });
991
+ }
992
+
993
+ setTime(): void {
994
+
995
+ if(!this.hasAttribute('data-time')){
996
+
997
+ const today = new Date();
998
+
999
+ const hour = today.getHours();
1000
+ const minute = today.getMinutes();
1001
+ const time = `${hour}:${minute}`;
1002
+
1003
+ this.setAttribute('data-time',time);
1004
+ }
1005
+
1006
+ if(this.hasAttribute('data-time')){
1007
+
1008
+ const time = this.getAttribute('data-time');
1009
+ const hour = parseInt(time.split(':')[0]);
1010
+ const minute = parseInt(time.split(':')[1]);
1011
+
1012
+ this.shadowRoot?.querySelectorAll(`[data-hour="${hour}"]`).forEach((element) => {
1013
+
1014
+ element.setAttribute('data-time',time);
1015
+ element.classList.add('column-header');
1016
+ element.closest('tr')?.style.setProperty('--minute-pos',((minute / 60) * 100) + '%');
1017
+ });
1018
+ }
1019
+ }
1020
+
1021
+ getYearView(selectedDate, today, sundayFirst: false): string {
1022
+
1023
+ let yearViewStr = "";
1024
+
1025
+ for(let i = 0; i < 12; i++){
1026
+
1027
+ console.log(selectedDate);
1028
+ const selectedDateObj = new Date(selectedDate);
1029
+ const selectedYear = selectedDateObj.getFullYear();
1030
+ const selectedFormattedDate = `${selectedYear}-${String(i+1).padStart(2, "0")}-01`;
1031
+
1032
+ yearViewStr += `<div class='month-wrapper'>
1033
+ <time class="column-header">${this.monthArray[i]}</time>
1034
+ <table>
1035
+ <thead>
1036
+ ${this.createThead(sundayFirst)}
1037
+ </thead>
1038
+ <tbody>
1039
+ ${this.createCalendar(selectedFormattedDate, today, sundayFirst)}
1040
+ </tbody>
1041
+ </table>
1042
+ </div>`;
1043
+ }
1044
+
1045
+ return yearViewStr;
1046
+ }
1047
+
1048
+
1049
+
1050
+ connectedCallback(): void {
1051
+
1052
+ // To to transform the below into variables of component to make more re-usable
1053
+ const title = this.shadowRoot?.querySelector('.calendar__title');
1054
+ const tbody = this.shadowRoot?.querySelector('#calendar > table > tbody');
1055
+ const thead = this.shadowRoot?.querySelector('#calendar > table > thead');
1056
+ //const tbodySplit = this.shadowRoot?.querySelector('#split > table > tbody');
1057
+ //const theadSplit = this.shadowRoot?.querySelector('#split > table > thead');
1058
+ const weekViewHeader = this.shadowRoot?.querySelector('#week-view-header > table > tbody');
1059
+ const yearView = this.shadowRoot?.querySelector('#year-view');
1060
+ const datePicker = this.shadowRoot?.querySelector(`#date`);
1061
+ const viewPicker = this.shadowRoot?.querySelector(`#view`);
1062
+ const todayButton = this.shadowRoot?.querySelector('#today-button');
1063
+ const filtersButton = this.shadowRoot?.querySelector('#filters-button');
1064
+ const prevButton = this.shadowRoot?.querySelector('#prev-button');
1065
+ const nextButton = this.shadowRoot?.querySelector('#next-button');
1066
+ const sundayFirst = this.hasAttribute('data-sunday-first');
1067
+
1068
+ const splitButton = this.shadowRoot?.querySelector(`[name="split"]`);
1069
+
1070
+
1071
+
1072
+ // set the table head - starting by monday by default but can be changed to sunday
1073
+ thead?.innerHTML = this.createThead(sundayFirst);
1074
+ //theadSplit?.innerHTML = this.createThead(sundayFirst);
1075
+
1076
+ // Get a formatted version of todays date
1077
+ const today = new Date();
1078
+ const date = today.getDate();
1079
+ const month = today.getMonth();
1080
+ const year = today.getFullYear();
1081
+ const strToday = `${year}-${String(month+1).padStart(2, "0")}-${String(date).padStart(2, "0")}`;
1082
+
1083
+ datePicker.value = strToday;
1084
+
1085
+ // Setup the view, month being default
1086
+ if(this.hasAttribute('data-view'))
1087
+ viewPicker.value = this.getAttribute('data-view');
1088
+ else {
1089
+ this.setAttribute('data-view', "month");
1090
+ viewPicker.value = "month";
1091
+ }
1092
+
1093
+ if(this.hasAttribute('data-views'))
1094
+ viewPicker?.setAttribute('data-views', this.getAttribute('data-views'));
1095
+
1096
+ // Create the calendars
1097
+ if(this.hasAttribute('data-calendars')){
1098
+
1099
+ this.calendars = this.getAttribute('data-calendars').split(',');
1100
+
1101
+ this.calendars.forEach((item,index) => {
1102
+ this.calendars[index] = item.trim();
1103
+ });
1104
+ }
1105
+
1106
+
1107
+
1108
+ // Setup the settings dialog
1109
+ this.setupSettings();
1110
+
1111
+
1112
+
1113
+ // Setup the calendar then adjust and add events
1114
+ title?.innerHTML = this.getTitle(strToday,viewPicker.value);
1115
+
1116
+ const calendarHtml = this.createCalendar(strToday, strToday, sundayFirst);
1117
+ tbody?.innerHTML = calendarHtml;
1118
+ //tbodySplit?.innerHTML = calendarHtml;
1119
+ weekViewHeader?.innerHTML = calendarHtml;
1120
+
1121
+
1122
+ if(viewPicker.value == "year"){
1123
+
1124
+ yearView?.innerHTML = this.getYearView(datePicker.value, strToday, sundayFirst);
1125
+ tbody?.innerHTML = '';
1126
+ }
1127
+
1128
+ this.addEvents();
1129
+ this.addJSEvents(this);
1130
+ this.setWeekDay(); // Working hours
1131
+ this.setTime(); // Month and day view has a current time indicator
1132
+ this.scrollIntoPlace(); // Scroll into place - month and day view needs have the weekday hours in place
1133
+
1134
+ // #region Add events for the basic top controls
1135
+
1136
+ // Remove the slot attribute on selected days when in split mode
1137
+ splitButton?.addEventListener('change', ()=> {
1138
+
1139
+ if(splitButton.checked){
1140
+ Array.from(this.querySelectorAll(`[slot^="${datePicker.value}"]`)).forEach((button) => {
1141
+
1142
+ button.setAttribute('data-slot',button.getAttribute('slot'));
1143
+ button.removeAttribute('slot');
1144
+ });
1145
+ }
1146
+ else {
1147
+ Array.from(this.querySelectorAll(`[data-slot]`)).forEach((button) => {
1148
+ button.setAttribute('slot',button.getAttribute('data-slot'));
1149
+ });
1150
+ }
1151
+ });
1152
+
1153
+ const resizeObserver = new ResizeObserver((entries) => {
1154
+
1155
+ const splitButtonDisplayed = window.getComputedStyle(splitButton?.parentElement, null).display;
1156
+ if(splitButtonDisplayed == "none"){
1157
+
1158
+ Array.from(this.querySelectorAll(`[data-slot]`)).forEach((button) => {
1159
+ button.setAttribute('slot',button.getAttribute('data-slot'));
1160
+ });
1161
+ splitButton.checked = false;
1162
+ }
1163
+ });
1164
+
1165
+ resizeObserver.observe(this);
1166
+
1167
+ viewPicker?.addEventListener('change', ()=> {
1168
+
1169
+ title?.innerHTML = this.getTitle(datePicker.value,viewPicker.value);
1170
+ this.setAttribute('data-view', viewPicker.value);
1171
+
1172
+ if(viewPicker.value == "week"){
1173
+
1174
+ Array.from(this.querySelectorAll(`.allday-event`)).forEach((button) => {
1175
+
1176
+ button.setAttribute('slot',button.getAttribute('slot')+'-header');
1177
+ });
1178
+ }
1179
+ else {
1180
+ Array.from(this.querySelectorAll(`.allday-event`)).forEach((button) => {
1181
+
1182
+ button.setAttribute('slot',button.getAttribute('slot')?.replace('-header',''));
1183
+ });
1184
+ }
1185
+
1186
+
1187
+ if(viewPicker.value == "week" || viewPicker.value == "day")
1188
+ this.scrollIntoPlace();
1189
+
1190
+ if(viewPicker.value != "month"){
1191
+
1192
+ Array.from(this.querySelectorAll(`[data-slot^="${datePicker.value}"]`)).forEach((button) => {
1193
+ button.setAttribute('slot',button.getAttribute('data-slot'));
1194
+ });
1195
+ }
1196
+
1197
+ if(viewPicker.value == "year"){
1198
+
1199
+ yearView?.innerHTML = this.getYearView(datePicker.value, strToday, sundayFirst);
1200
+ tbody?.innerHTML = '';
1201
+ this.addEvents();
1202
+ this.addJSEvents(this);
1203
+ this.setWeekDay(); // Working hours
1204
+ this.setTime(); // Month and day view has a current time indicator
1205
+ this.scrollIntoPlace();
1206
+ }
1207
+ else if(tbody?.innerHTML == "") {
1208
+ yearView?.innerHTML = '';
1209
+ tbody?.innerHTML = this.createCalendar(datePicker.value, strToday);
1210
+ this.addEvents();
1211
+ this.addJSEvents(this);
1212
+ this.setWeekDay(); // Working hours
1213
+ this.setTime(); // Month and day view has a current time indicator
1214
+ this.scrollIntoPlace();
1215
+ }
1216
+
1217
+ const customEvent = new CustomEvent('change-view', {
1218
+ detail: {
1219
+ 'view': viewPicker.value,
1220
+ 'date': datePicker.value
1221
+ },
1222
+ });
1223
+
1224
+ this.dispatchEvent(customEvent);
1225
+ });
1226
+
1227
+
1228
+ function resetCalendar(component): void{
1229
+
1230
+ if(viewPicker.value == "year"){
1231
+
1232
+ yearView?.innerHTML = component.getYearView(datePicker.value, strToday, sundayFirst);
1233
+ tbody?.innerHTML = '';
1234
+ component.addEvents();
1235
+ component.addJSEvents(component);
1236
+ component.setWeekDay(); // Working hours
1237
+ component.setTime(); // Month and day view has a current time indicator
1238
+ }
1239
+ else {
1240
+
1241
+ const calendarHtml = component.createCalendar(datePicker.value, strToday);
1242
+ tbody?.innerHTML = calendarHtml;
1243
+ //tbodySplit?.innerHTML = calendarHtml;
1244
+ weekViewHeader?.innerHTML = calendarHtml;
1245
+
1246
+ component.addEvents();
1247
+ component.addJSEvents(component);
1248
+ component.setWeekDay();
1249
+ component.setTime();
1250
+ }
1251
+ }
1252
+
1253
+ function updateCalendar(component): void{
1254
+
1255
+ Array.from(component.shadowRoot.querySelectorAll('.selected')).forEach((element) => {
1256
+ element.classList.remove('selected');
1257
+ });
1258
+
1259
+ Array.from(component.shadowRoot.querySelectorAll(`td:has(time[datetime="${datePicker.value}"]):not(.prev-month, .next-month)`)).forEach((element) => {
1260
+ element.classList.add('selected');
1261
+ });
1262
+ }
1263
+
1264
+ datePicker?.addEventListener('change', ()=> {
1265
+
1266
+ title?.innerHTML = this.getTitle(datePicker.value,viewPicker.value);
1267
+
1268
+ if(this.shadowRoot.querySelector(`td:has(time[datetime="${datePicker.value}"]):not(.prev-month, .next-month)`))
1269
+ updateCalendar(this);
1270
+ else
1271
+ resetCalendar(this);
1272
+
1273
+ const customEvent = new CustomEvent('change-date', {
1274
+ detail: {
1275
+ 'view': viewPicker.value,
1276
+ 'date': datePicker.value
1277
+ },
1278
+ });
1279
+
1280
+ this.dispatchEvent(customEvent);
1281
+ });
1282
+
1283
+ filtersButton?.addEventListener('click', ()=> {
1284
+
1285
+ const customEvent = new CustomEvent('open-filters',);
1286
+ this.dispatchEvent(customEvent);
1287
+ });
1288
+
1289
+ // HTML Observer
1290
+ const htmlUpdated = (mutationList: any, observer: any): void => {
1291
+
1292
+
1293
+
1294
+
1295
+ observer.disconnect();
1296
+
1297
+ console.log(this.pauseObserver);
1298
+
1299
+ if(this.pauseObserver == false){
1300
+
1301
+ for (const mutation of mutationList) {
1302
+
1303
+ if (mutation.type == 'characterData' || (mutation.type == 'childList' && mutation.addedNodes.length) || mutation.type === 'attributes') {
1304
+
1305
+ //resetCalendar(this);
1306
+ this.addEvents();
1307
+ }
1308
+ }
1309
+ }
1310
+
1311
+ observer.observe(this, { childList: true, characterData: true, subtree: true, attributes: true });
1312
+ };
1313
+
1314
+ const observer = new MutationObserver(htmlUpdated);
1315
+ observer.observe(this, { childList: true, characterData: true, subtree: true, attributes: true });
1316
+
1317
+ todayButton?.addEventListener('click', ()=> {
1318
+
1319
+ datePicker.value = strToday;
1320
+ title?.innerHTML = this.getTitle(datePicker.value,viewPicker.value);
1321
+
1322
+ if(this.shadowRoot.querySelector(`td:has(time[datetime="${datePicker.value}"]):not(.prev-month, .next-month)`))
1323
+ updateCalendar(this);
1324
+ else
1325
+ resetCalendar(this);
1326
+
1327
+ const customEvent = new CustomEvent('change-date-today', {
1328
+ detail: {
1329
+ 'view': viewPicker.value,
1330
+ 'date': datePicker.value
1331
+ },
1332
+ });
1333
+
1334
+ this.dispatchEvent(customEvent);
1335
+ });
1336
+
1337
+ prevButton?.addEventListener('click', ()=> {
1338
+
1339
+ datePicker.value = this.paginateDate("prev",viewPicker.value,datePicker.value);
1340
+ title?.innerHTML = this.getTitle(datePicker.value,viewPicker.value);
1341
+
1342
+ if(this.shadowRoot.querySelector(`td:has(time[datetime="${datePicker.value}"]):not(.prev-month, .next-month)`))
1343
+ updateCalendar(this);
1344
+ else
1345
+ resetCalendar(this);
1346
+
1347
+ const customEvent = new CustomEvent('change-date-previous', {
1348
+ detail: {
1349
+ 'view': viewPicker.value,
1350
+ 'date': datePicker.value
1351
+ },
1352
+ });
1353
+
1354
+ this.dispatchEvent(customEvent);
1355
+ });
1356
+
1357
+ nextButton?.addEventListener('click', ()=> {
1358
+
1359
+ datePicker.value = this.paginateDate("next",viewPicker.value,datePicker.value);
1360
+ title?.innerHTML = this.getTitle(datePicker.value,viewPicker.value);
1361
+
1362
+ console.log(datePicker.value)
1363
+
1364
+ if(this.shadowRoot.querySelector(`td:has(time[datetime="${datePicker.value}"]):not(.prev-month, .next-month)`))
1365
+ updateCalendar(this);
1366
+ else
1367
+ resetCalendar(this);
1368
+
1369
+ const customEvent = new CustomEvent('change-date-next', {
1370
+ detail: {
1371
+ 'view': viewPicker.value,
1372
+ 'date': datePicker.value
1373
+ },
1374
+ });
1375
+
1376
+ this.dispatchEvent(customEvent);
1377
+ });
1378
+ // #endregion
1379
+
1380
+ // TODO
1381
+ trackComponent(this, 'iam-calendar', [
1382
+ 'open-filters',
1383
+ 'change-view',
1384
+ 'change-date',
1385
+ 'change-date-today',
1386
+ 'change-date-previous',
1387
+ 'change-date-next',
1388
+ 'open-settings',
1389
+ 'close-settings',
1390
+ 'save-settings'
1391
+ ]);
1392
+ }
1393
+
1394
+ static get observedAttributes(): any {
1395
+ return ['data-calendars','data-view'];
1396
+ }
1397
+
1398
+ attributeChangedCallback(attrName, oldVal, newVal): void {
1399
+
1400
+ this.pauseObserver = true;
1401
+
1402
+ switch (attrName) {
1403
+ case 'data-calendars': {
1404
+ if (oldVal != newVal) {
1405
+
1406
+
1407
+ const tbody = this.shadowRoot?.querySelector('#calendar > table > tbody');
1408
+ const weekViewHeader = this.shadowRoot?.querySelector('#week-view-header > table > tbody');
1409
+ const datePicker = this.shadowRoot?.querySelector(`#date`);
1410
+
1411
+ // Get a formatted version of todays date
1412
+ const today = new Date();
1413
+ const date = today.getDate();
1414
+ const month = today.getMonth();
1415
+ const year = today.getFullYear();
1416
+ const strToday = `${year}-${String(month+1).padStart(2, "0")}-${String(date).padStart(2, "0")}`;
1417
+
1418
+
1419
+ if(this.hasAttribute('data-calendars')){
1420
+
1421
+ this.calendars = this.getAttribute('data-calendars').split(',');
1422
+
1423
+ this.calendars.forEach((item,index) => {
1424
+ this.calendars[index] = item.trim();
1425
+ });
1426
+ }
1427
+
1428
+ const calendarHtml = this.createCalendar(datePicker.value, strToday);
1429
+ tbody?.innerHTML = calendarHtml;
1430
+ weekViewHeader?.innerHTML = calendarHtml;
1431
+
1432
+ this.addEvents();
1433
+ this.addJSEvents(this);
1434
+ this.setWeekDay();
1435
+ this.setTime();
1436
+
1437
+ }
1438
+ break;
1439
+ };
1440
+ case 'data-view': {
1441
+ if (oldVal != newVal) {
1442
+
1443
+ const viewPicker = this.shadowRoot?.querySelector(`#view`);
1444
+
1445
+ viewPicker.value = newVal;
1446
+ viewPicker.dispatchEvent(new Event('change'));
1447
+ }
1448
+ break;
1449
+ }
1450
+ }
1451
+
1452
+ setTimeout(() => {
1453
+ this.pauseObserver = false;
1454
+ }, "500");
1455
+
1456
+
1457
+ }
1458
+ }
1459
+
1460
+ export default iamCalendar;