@iamproperty/components 3.1.0 → 3.4.4

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 (179) hide show
  1. package/README.md +141 -16
  2. package/assets/css/core.min.css +1 -1
  3. package/assets/css/core.min.css.map +1 -1
  4. package/assets/css/style.min.css +1 -1
  5. package/assets/css/style.min.css.map +1 -1
  6. package/assets/favicons/manifest.json +31 -31
  7. package/assets/js/main.js +57 -57
  8. package/assets/js/modules/accordion.js +33 -32
  9. package/assets/js/modules/alert.js +41 -57
  10. package/assets/js/modules/carousel.js +76 -102
  11. package/assets/js/modules/chart.js +151 -218
  12. package/assets/js/modules/drawer.js +10 -16
  13. package/assets/js/modules/file-upload.js +33 -48
  14. package/assets/js/modules/form.js +122 -168
  15. package/assets/js/modules/helpers.js +90 -119
  16. package/assets/js/modules/modal.js +69 -90
  17. package/assets/js/modules/nav.js +18 -28
  18. package/assets/js/modules/orderablelist.js +91 -122
  19. package/assets/js/modules/table.js +451 -585
  20. package/assets/js/modules/testimonial.js +64 -83
  21. package/assets/js/modules/youtubevideo.js +114 -145
  22. package/assets/js/scripts.bundle.js +895 -955
  23. package/assets/js/scripts.bundle.js.map +1 -1
  24. package/assets/js/scripts.bundle.min.js +3 -3
  25. package/assets/js/scripts.bundle.min.js.map +1 -1
  26. package/assets/sass/_components.scss +14 -14
  27. package/assets/sass/_corefiles.scss +40 -40
  28. package/assets/sass/_fonts.scss +16 -16
  29. package/assets/sass/_forms.scss +10 -10
  30. package/assets/sass/_func.scss +12 -12
  31. package/assets/sass/_functions/functions.scss +141 -141
  32. package/assets/sass/_functions/mixins.scss +170 -170
  33. package/assets/sass/_functions/utilities.scss +143 -143
  34. package/assets/sass/_functions/variables.scss +467 -467
  35. package/assets/sass/_print.scss +61 -61
  36. package/assets/sass/_tests/{sass.spec.js → colours.spec.js} +9 -9
  37. package/assets/sass/_tests/colours.spec.scss +44 -44
  38. package/assets/sass/_tests/func.spec.js +9 -0
  39. package/assets/sass/_tests/func.spec.scss +232 -232
  40. package/assets/sass/_tests/mixins.spec.js +9 -0
  41. package/assets/sass/_tests/mixins.spec.scss +194 -194
  42. package/assets/sass/_tests/typography.spec.js +9 -0
  43. package/assets/sass/_tests/typography.spec.scss +35 -35
  44. package/assets/sass/components/accordion.scss +197 -197
  45. package/assets/sass/components/alert.scss +98 -98
  46. package/assets/sass/{elements → components}/buttons.scss +251 -251
  47. package/assets/sass/{elements → components}/card.scss +288 -288
  48. package/assets/sass/components/cardDeck.scss +107 -107
  49. package/assets/sass/components/carousel.scss +234 -234
  50. package/assets/sass/components/charts.scss +569 -569
  51. package/assets/sass/{elements → components}/container.scss +236 -236
  52. package/assets/sass/components/drawer.scss +46 -46
  53. package/assets/sass/{elements → components}/forms.scss +261 -261
  54. package/assets/sass/components/header.scss +63 -63
  55. package/assets/sass/{elements → components}/links.scss +97 -97
  56. package/assets/sass/{elements → components}/lists.scss +159 -159
  57. package/assets/sass/components/modal.scss +136 -136
  58. package/assets/sass/components/nav.scss +960 -960
  59. package/assets/sass/{elements → components}/panel.scss +161 -161
  60. package/assets/sass/components/property-searchbar.scss +143 -143
  61. package/assets/sass/components/snapshot.scss +70 -70
  62. package/assets/sass/components/stepper.scss +164 -164
  63. package/assets/sass/{elements → components}/tables.scss +290 -290
  64. package/assets/sass/components/tabs.scss +87 -87
  65. package/assets/sass/components/testimonial.scss +132 -132
  66. package/assets/sass/components/timeline.scss +95 -95
  67. package/assets/sass/{elements → components}/tooltips.scss +84 -84
  68. package/assets/sass/core.scss +6 -6
  69. package/assets/sass/email.scss +65 -65
  70. package/assets/sass/error.scss +4 -4
  71. package/assets/sass/foundations/brand.scss +76 -72
  72. package/assets/sass/foundations/circles.scss +74 -74
  73. package/assets/sass/foundations/icons.scss +80 -80
  74. package/assets/sass/foundations/media.scss +50 -50
  75. package/assets/sass/foundations/reboot.scss +130 -130
  76. package/assets/sass/foundations/root.scss +125 -125
  77. package/assets/sass/{elements → foundations}/type.scss +136 -136
  78. package/assets/sass/main.scss +7 -7
  79. package/assets/svg/icons.svg +598 -598
  80. package/assets/svg/logo.svg +49 -43
  81. package/assets/ts/main.ts +68 -68
  82. package/assets/ts/modules/accordion.ts +44 -43
  83. package/assets/ts/modules/alert.ts +58 -0
  84. package/assets/ts/modules/carousel.ts +103 -0
  85. package/assets/ts/modules/chart.ts +219 -0
  86. package/assets/ts/modules/drawer.ts +17 -0
  87. package/assets/ts/modules/file-upload.ts +49 -0
  88. package/assets/ts/modules/form.ts +169 -0
  89. package/assets/ts/modules/helpers.ts +120 -0
  90. package/assets/ts/modules/modal.ts +91 -0
  91. package/assets/ts/modules/nav.ts +29 -0
  92. package/assets/ts/modules/orderablelist.ts +123 -0
  93. package/assets/ts/modules/table.ts +586 -0
  94. package/assets/ts/modules/testimonial.ts +84 -0
  95. package/assets/ts/modules/youtubevideo.ts +146 -0
  96. package/dist/components.es.js +493 -509
  97. package/dist/components.umd.js +15 -15
  98. package/package.json +109 -108
  99. package/src/components/Accordion/Accordion.spec.js +63 -63
  100. package/src/components/Accordion/Accordion.vue +22 -22
  101. package/src/components/Accordion/AccordionItem.vue +52 -52
  102. package/src/components/Accordion/README.md +34 -34
  103. package/src/components/Alert/Alert.spec.js +49 -49
  104. package/src/components/Alert/Alert.vue +39 -39
  105. package/src/components/Alert/README.md +28 -28
  106. package/src/components/Banner/Banner.spec.js +28 -28
  107. package/src/components/Banner/Banner.vue +38 -38
  108. package/src/components/Banner/README.md +23 -23
  109. package/src/{elements → components}/Card/Card.vue +122 -122
  110. package/src/{elements/FileUploads → components/Card}/README.md +24 -24
  111. package/src/components/CardDeck/CardDeck.spec.js +99 -99
  112. package/src/components/CardDeck/CardDeck.vue +77 -77
  113. package/src/components/CardDeck/README.md +24 -24
  114. package/src/components/Carousel/Carousel.spec.js +45 -45
  115. package/src/components/Carousel/Carousel.vue +85 -85
  116. package/src/components/Carousel/README.md +19 -19
  117. package/src/components/Chart/Chart.spec.js +201 -201
  118. package/src/components/Chart/Chart.vue +88 -88
  119. package/src/components/Chart/README.md +17 -17
  120. package/src/components/Drawer/Drawer.vue +53 -53
  121. package/src/components/Drawer/README.md +22 -22
  122. package/src/{elements → components}/FileUploads/FileUploads.vue +48 -48
  123. package/src/{elements/Card → components/FileUploads}/README.md +24 -24
  124. package/src/components/Header/Header.spec.js +33 -33
  125. package/src/components/Header/Header.vue +38 -38
  126. package/src/components/Header/README.md +27 -27
  127. package/src/{elements → components}/Input/Input.vue +272 -272
  128. package/src/{elements → components}/Input/README.md +19 -19
  129. package/src/components/Modal/Modal.spec.js +22 -22
  130. package/src/components/Modal/Modal.vue +43 -43
  131. package/src/components/Modal/README.md +19 -19
  132. package/src/components/Nav/Nav.spec.js +35 -35
  133. package/src/components/Nav/Nav.vue +215 -215
  134. package/src/components/Nav/README.md +22 -22
  135. package/src/components/NoteFeed/NoteFeed.vue +79 -79
  136. package/src/components/NoteFeed/README.md +16 -16
  137. package/src/components/PropertySearchbar/PropertySearchbar.vue +204 -204
  138. package/src/components/PropertySearchbar/README.md +25 -25
  139. package/src/components/Snapshot/README.md +20 -20
  140. package/src/components/Snapshot/Snapshot.vue +32 -32
  141. package/src/components/Stepper/README.md +32 -32
  142. package/src/components/Stepper/Step.vue +28 -28
  143. package/src/components/Stepper/Stepper.spec.js +99 -99
  144. package/src/components/Stepper/Stepper.vue +33 -33
  145. package/src/{elements → components}/Table/README.md +62 -62
  146. package/src/{elements → components}/Table/Table.spec.js +90 -90
  147. package/src/{elements → components}/Table/Table.vue +129 -129
  148. package/src/components/Tabs/README.md +27 -27
  149. package/src/components/Tabs/Tab.vue +32 -32
  150. package/src/components/Tabs/Tabs.vue +77 -77
  151. package/src/components/Testimonial/README.md +25 -25
  152. package/src/components/Testimonial/Testimonial.spec.js +57 -57
  153. package/src/components/Testimonial/Testimonial.vue +60 -60
  154. package/src/components/Timeline/README.md +18 -18
  155. package/src/components/Timeline/Timeline.spec.js +17 -17
  156. package/src/components/Timeline/Timeline.vue +24 -24
  157. package/src/foundations/Icon/Icon.spec.js +24 -24
  158. package/src/foundations/Icon/Icon.vue +24 -24
  159. package/src/foundations/Icon/README.md +11 -11
  160. package/src/foundations/Logo/Logo.spec.js +56 -56
  161. package/src/foundations/Logo/Logo.vue +39 -39
  162. package/src/foundations/Logo/README.md +20 -20
  163. package/src/foundations/YoutubeVideo/README.md +11 -11
  164. package/src/foundations/YoutubeVideo/YoutubeVideo.vue +24 -24
  165. package/src/helpers/strings.js +12 -12
  166. package/src/index.js +27 -27
  167. package/src/vue-shim.d.ts +6 -6
  168. package/assets/css/email.min.css +0 -1
  169. package/assets/css/email.min.css.map +0 -1
  170. package/assets/css/error.min.css +0 -1
  171. package/assets/css/error.min.css.map +0 -1
  172. package/assets/ts/main.js +0 -57
  173. package/assets/ts/main.js.map +0 -1
  174. package/assets/ts/modules/accordion.js +0 -33
  175. package/assets/ts/modules/accordion.js.map +0 -1
  176. package/src/components/Accordion/Accordion.screenshot.vue +0 -57
  177. package/src/components/Accordion/__screenshots__/win32/laptop/Accordion.png +0 -0
  178. package/src/components/Accordion/__screenshots__/win32/mobile/Accordion.png +0 -0
  179. package/src/components/Accordion/__screenshots__/win32/tablet/Accordion.png +0 -0
@@ -0,0 +1,586 @@
1
+ // @ts-nocheck
2
+ import { zeroPad, isNumeric } from "./helpers";
3
+
4
+ function table(tableElement) {
5
+
6
+ if(typeof tableElement != "object")
7
+ return false;
8
+
9
+ const thead = tableElement.querySelector('thead');
10
+ const tbody = tableElement.querySelector('tbody');
11
+ const storedData = tbody.cloneNode(true);
12
+ const sortedEvent = new Event('sorted');
13
+ const filteredEvent = new Event('filtered');
14
+ const reorderedEvent = new Event('reordered');
15
+ const randID = 'table_'+Math.random().toString(36).substr(2, 9); // Random to make sure IDs created are unique
16
+ let draggedRow;
17
+
18
+ tableElement.setAttribute('id',randID)
19
+
20
+ // #region Sortable
21
+ const sortTable = function(sortBy,sort){
22
+
23
+ // Create an array from the table rows, the index created is then used to sort the array
24
+ let tableArr = [];
25
+ Array.from(tbody.querySelectorAll('tr')).forEach((tableRow, index) => {
26
+
27
+ let rowIndex = tableRow.querySelector('td[data-label="'+sortBy+'"], th[data-label="'+sortBy+'"]').textContent;
28
+
29
+ if(isNumeric(rowIndex))
30
+ rowIndex = zeroPad(rowIndex,10)
31
+
32
+ const dataRow = {
33
+ index: rowIndex,
34
+ row: tableRow
35
+ }
36
+ tableArr.push(dataRow);
37
+ });
38
+
39
+ // Sort array
40
+ tableArr.sort((a, b) => (a.index > b.index) ? 1 : -1)
41
+
42
+ // Reverse if descending
43
+ if(sort == "descending")
44
+ tableArr = tableArr.reverse();
45
+
46
+ // Create a string to return and populate the tbody
47
+ let strTbody = '';
48
+ tableArr.forEach((tableRow, index) => {
49
+ strTbody += tableRow.row.outerHTML;
50
+ });
51
+ tbody.innerHTML = strTbody;
52
+
53
+ // Dispatch the sortable event
54
+ tableElement.dispatchEvent(sortedEvent);
55
+ }
56
+
57
+ // Declare event handlers
58
+ tableElement.addEventListener('click', function(e){
59
+ for (var target = e.target; target && target != this; target = target.parentNode) {
60
+ if (target.matches('[data-sortable]')) {
61
+
62
+ // Get current sort order
63
+ let sort = target.getAttribute('aria-sort') == "ascending" ? "descending" : "ascending";
64
+
65
+ // unset sort attributes
66
+ Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
67
+ col.setAttribute('aria-sort','none');
68
+ });
69
+
70
+ // Set the sort order attribute
71
+ target.setAttribute('aria-sort', sort);
72
+
73
+ // Save the sort options on the table element so that it can be re-sorted later
74
+ tableElement.setAttribute('data-sort', sort);
75
+ tableElement.setAttribute('data-sortBy', target.textContent);
76
+
77
+ // Sort the table
78
+ sortTable(target.textContent, sort);
79
+
80
+ Array.from(tableElement.querySelectorAll('tr[draggable]')).forEach((tableRow, index) => {
81
+
82
+ tableRow.removeAttribute('draggable');
83
+ });
84
+ break;
85
+ }
86
+ }
87
+ }, false);
88
+
89
+ // On page load check if the table should be pre-sorted, if so trigger a click
90
+ if(tableElement.getAttribute('data-sortBy')){
91
+
92
+ let sort = tableElement.getAttribute('data-sort') == "ascending" ? "descending" : "ascending";
93
+
94
+ Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
95
+ if(col.textContent == tableElement.getAttribute('data-sortBy')){
96
+ col.setAttribute('aria-sort',sort)
97
+ col.click();
98
+ }
99
+ });
100
+ }
101
+
102
+ // #endregion Sortable
103
+
104
+ // #region Filters
105
+ const createFilterForm = function(count){
106
+
107
+ // Create wrapper div
108
+ const form = document.createElement("div");
109
+ form.classList.add('table__filters');
110
+ form.classList.add('row');
111
+ form.classList.add('pt-1');
112
+ form.classList.add('pb-3');
113
+
114
+ // Create the filter options array
115
+ const filterColumns = Array.from(tableElement.querySelectorAll('th[data-filterable]'));
116
+
117
+ // Populate a list of searchable terms from the cells of the columns that could be used as a filter
118
+ let searchableTerms = {};
119
+ filterColumns.forEach((columnHeading, index) => {
120
+ Array.from(tableElement.querySelectorAll('td[data-label="'+columnHeading.textContent+'"]')).forEach((label, index) => {
121
+
122
+ searchableTerms[label.textContent] = label.textContent;
123
+ });
124
+ });
125
+
126
+ // Create the form
127
+ const filterTitle = filterColumns.length == 1 ? "Filter by "+filterColumns[0].textContent : "Filter"; // Update title if only one filter is chosen
128
+ const checkboxClass = filterColumns.length == 1 ? "d-none" : "d-sm-flex"; // Hide controls when only one filter is chosen
129
+
130
+ form.innerHTML = `<div class="col-sm-6 col-md-4 pb-3">
131
+ <div class="form-control__wrapper form-control-inline mb-0">
132
+ <label for="${randID}_filter" class="form-label">${filterTitle}:</label>
133
+ <input type="search" name="${randID}_filter" id="${randID}_filter" class="form-control form-control-sm" placeholder="" list="${randID}_list" />
134
+ </div>
135
+ <datalist id="${randID}_list">
136
+ ${Object.keys(searchableTerms).map(term => `<option value="${term}"></option>`).join("")}
137
+ </datalist>
138
+ </div>
139
+ <div class="col-md-8 align-items-center pb-3 ${checkboxClass}">
140
+ ${`<span class="pe-3 text-nowrap h5 mb-0">Filter by: </span>` + filterColumns.map(column => `<div class="form-check pe-3 mt-0 mb-0"><input class="form-check-input" type="checkbox" id="${randID}_${column.textContent.replace(' ','_').toLowerCase()}" checked="checked" /><label class="form-check-label text-nowrap" for="${randID}_${column.textContent.replace(' ','_').toLowerCase()}">${column.textContent}</label></div>`).join("")}
141
+ </div>`;
142
+
143
+ // Add before the actual table
144
+ tableElement.prepend(form)
145
+ }
146
+
147
+ const filterTable = function(searchTerm){
148
+
149
+ // Create an array of rows that match the search term
150
+ let tableArr = [];
151
+ Array.from(storedData.querySelectorAll('tr')).forEach((tableRow, index) => {
152
+
153
+ // We want one long search string per row including each filterable table cell
154
+ let rowSearchString = '';
155
+ Array.from(tableElement.querySelectorAll('[type="checkbox"]:checked + label')).forEach((label, index) => {
156
+ rowSearchString += tableRow.querySelector('td[data-label="'+label.textContent+'"]').textContent+' | ';
157
+ });
158
+
159
+ // Check if the table row search string contains the search term
160
+ if(rowSearchString.indexOf(searchTerm) >= 0){
161
+
162
+ const dataRow = { row: tableRow }
163
+ tableArr.push(dataRow);
164
+ }
165
+ });
166
+
167
+ // Create a string to return and populate the tbody
168
+ let strTbody = '';
169
+ tableArr.forEach((tableRow, index) => {
170
+ strTbody += tableRow.row.outerHTML;
171
+ });
172
+ tbody.innerHTML = strTbody;
173
+
174
+ // Dispatch the filter event.
175
+ tableElement.dispatchEvent(filteredEvent);
176
+ }
177
+
178
+ const createFilterList = function(){
179
+
180
+ // Check which options are checked
181
+ let filterOptions = [];
182
+ Array.from(tableElement.querySelectorAll('[type="checkbox"]:checked + label')).forEach((label, index) => {
183
+ filterOptions.push(label.textContent);
184
+ });
185
+
186
+ // Build up the list of searchable terms
187
+ let searchableTerms = [];
188
+ filterOptions.forEach((option, index) => {
189
+ Array.from(tableElement.querySelectorAll('td[data-label="'+option+'"]')).forEach((label, index) => {
190
+ searchableTerms[label.textContent] = label.textContent;
191
+ });
192
+ });
193
+
194
+ // Rebuild the list
195
+ let dataList = tableElement.querySelector('datalist');
196
+ dataList.innerHTML = Object.keys(searchableTerms).map(term => `<option value="${term}"></option>`).join("");
197
+ }
198
+
199
+ // On page load check if filters are needed
200
+ if(Array.from(tableElement.querySelectorAll('[data-filterable]')).length){
201
+
202
+ // Create the filter options
203
+ createFilterForm(tableElement,Array.from(tableElement.querySelectorAll('[data-filterable]')).length);
204
+
205
+ // Add event handlers for the filter options
206
+ tableElement.addEventListener('keyup', function(e){
207
+ for (var target = e.target; target && target != this; target = target.parentNode) {
208
+ if (target.matches('input[type="search"]')) {
209
+
210
+ const searchTerm = target.value;
211
+ filterTable(searchTerm)
212
+ }
213
+ }
214
+ });
215
+
216
+ tableElement.addEventListener('change', function(e){
217
+ for (var target = e.target; target && target != this; target = target.parentNode) {
218
+ if (target.matches('input[type="search"]')) {
219
+
220
+ const searchTerm = target.value;
221
+ filterTable(searchTerm)
222
+ }
223
+ }
224
+ });
225
+
226
+ tableElement.addEventListener('change', function(e){
227
+ for (var target = e.target; target && target != this; target = target.parentNode) {
228
+ if (target.matches('input[type="checkbox"]')) {
229
+
230
+ const searchTerm = tableElement.querySelector('input[type="search"]').value;
231
+ filterTable(searchTerm)
232
+ createFilterList()
233
+ }
234
+ }
235
+ });
236
+ }
237
+ // #endregion Filters
238
+
239
+ // #region Pagination
240
+ const paginateRows = function(show, page){
241
+
242
+ // Create some inline CSS to control what is viewed on the table, unline the filters we are just hiding the rable rows not removing them from the DOM.
243
+ let style = document.getElementById(randID+'_style');
244
+
245
+ if(style == null){
246
+ style = document.createElement("style");
247
+ style.setAttribute('id',randID+'_style')
248
+ }
249
+
250
+ const startShowing = (show*(page-1))+1;
251
+ const stopShowing = show*(page);
252
+
253
+ style.innerHTML = `
254
+ #${randID} tbody tr {
255
+ display: none;
256
+ }
257
+ #${randID} tbody tr:nth-child(${startShowing}),
258
+ #${randID} tbody tr:nth-child(${startShowing}) ~ tr{
259
+ display: block;
260
+ }
261
+ @media screen and (min-width: 36em) {
262
+ #${randID} tbody tr:nth-child(${startShowing}),
263
+ #${randID} tbody tr:nth-child(${startShowing}) ~ tr{
264
+ display: table-row;
265
+ }
266
+ }
267
+ #${randID} tbody tr:nth-child(${stopShowing}) ~ tr{
268
+ display: none;
269
+ }
270
+ `;
271
+
272
+ tableElement.append(style);
273
+ }
274
+
275
+ // On page load check if the table should be paginated
276
+ if(tableElement.getAttribute('data-show')){
277
+
278
+ const show = parseInt(tableElement.getAttribute('data-show'));
279
+ const page = parseInt(tableElement.getAttribute('data-page')) ? parseInt(tableElement.getAttribute('data-page')) : 1;
280
+ const totalRows = tableElement.querySelectorAll('tbody tr').length;
281
+
282
+ if(show < totalRows){
283
+ paginateRows(show,page);
284
+ createPaginationForm(randID,tableElement,show,page,totalRows);
285
+ createPaginationButttons(randID,tableElement,show,page,totalRows);
286
+
287
+ tableElement.addEventListener('change', function(e){
288
+ for (var target = e.target; target && target != this; target = target.parentNode) {
289
+ if (target.matches('.table__pagination input[type="number"]')) {
290
+
291
+ paginateRows(target.value,page);
292
+ createPaginationButttons(randID,tableElement,target.value,page,totalRows);
293
+ tableElement.setAttribute('data-show',target.value)
294
+ }
295
+ }
296
+ });
297
+
298
+ tableElement.addEventListener('click', function(e){
299
+ for (var target = e.target; target && target != this; target = target.parentNode) {
300
+ if (target.matches('.page-item:not(.active):not(.disabled) .page-link')) {
301
+
302
+ paginateRows(tableElement.getAttribute('data-show'),target.getAttribute('data-page'));
303
+ createPaginationButttons(randID,tableElement,tableElement.getAttribute('data-show'),target.getAttribute('data-page'),totalRows);
304
+ }
305
+ }
306
+ }, false);
307
+
308
+ tableElement.addEventListener('change', function(e){
309
+ for (var target = e.target; target && target != this; target = target.parentNode) {
310
+ if (target.matches('.table__pagination select')) {
311
+
312
+ paginateRows(tableElement.getAttribute('data-show'),target.value);
313
+ createPaginationButttons(randID,tableElement,tableElement.getAttribute('data-show'),target.value,totalRows);
314
+ }
315
+ }
316
+ });
317
+ }
318
+ }
319
+ // #endregion Pagination
320
+
321
+ // #region Reorderable
322
+ // Set the row thats being dragged and copy the row
323
+ function setDraggedRow(e) {
324
+ e.dataTransfer.setData("text/plain", e.target.id);
325
+ draggedRow = e.target;
326
+ e.target.classList.add('tr--dragging');
327
+ }
328
+
329
+ // Create the order column and event handler for rows
330
+ const setReorderRows = function(){
331
+
332
+ Array.from(tbody.querySelectorAll('tr')).forEach((tableRow, index) => {
333
+
334
+ // Create column if not already created
335
+ if(tableRow.querySelector('[data-label="Order"]') == null){
336
+
337
+ const orderColumn = document.createElement('th');
338
+ orderColumn.innerHTML = index + 1;
339
+ orderColumn.setAttribute('data-label','Order');
340
+ tableRow.prepend(orderColumn);
341
+ }
342
+
343
+ // Make draggable
344
+ tableRow.setAttribute('id',randID+'_row_'+(index+1));
345
+ tableRow.setAttribute('data-order',index+1);
346
+ tableRow.setAttribute('draggable','true');
347
+ tableRow.addEventListener("dragstart", setDraggedRow);
348
+ });
349
+ }
350
+
351
+ if(tableElement.getAttribute('data-reorder') && tableElement.getAttribute('data-reorder') != "false"){
352
+
353
+ // Add column heading
354
+ const orderHeading = document.createElement('th');
355
+ orderHeading.innerHTML = 'Order';
356
+ orderHeading.title = 'Click here to enable re-ordering via drag and drop';
357
+ orderHeading.classList.add('table-order-reset');
358
+ thead.querySelector('tr').prepend(orderHeading);
359
+
360
+ setReorderRows();
361
+
362
+ // Reset order button
363
+ tableElement.addEventListener('click', function(e){
364
+ for (var target = e.target; target && target != this; target = target.parentNode) {
365
+ if (target.matches('.table-order-reset')) {
366
+
367
+ // unset sort attributes
368
+ Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
369
+ col.setAttribute('aria-sort','none');
370
+ });
371
+
372
+ // Save the sort options on the table element so that it can be re-sorted later
373
+ tableElement.removeAttribute('data-sort');
374
+ tableElement.removeAttribute('data-sortBy');
375
+
376
+ // Sort the table
377
+ sortTable('Order', 'ascending');
378
+
379
+ Array.from(tableElement.querySelectorAll('tbody tr')).forEach((tableRow, index) => {
380
+
381
+ tableRow.setAttribute('draggable','true');
382
+ });
383
+
384
+ break;
385
+ }
386
+ }
387
+ }, false);
388
+
389
+
390
+ document.addEventListener("dragover", function( e ) {
391
+ // prevent default to allow drop
392
+ e.preventDefault();
393
+ }, false);
394
+
395
+ document.addEventListener("dragenter", function( e ) {
396
+ // prevent default to allow drop
397
+ e.preventDefault();
398
+ e.dataTransfer.dropEffect = "move";
399
+
400
+ for (var target = e.target; target && target != this; target = target.parentNode) {
401
+ if (target.matches('[data-reorder] tbody tr')) {
402
+
403
+ target.classList.add('tr--dropable')
404
+ }
405
+ }
406
+ }, false);
407
+
408
+ document.addEventListener("dragleave", function( e ) {
409
+ // prevent default to allow drop
410
+ e.preventDefault();
411
+ for (var target = e.target; target && target != this; target = target.parentNode) {
412
+ if (target.matches('[data-reorder] tbody tr')) {
413
+
414
+ target.classList.remove('tr--dropable')
415
+ }
416
+ }
417
+ }, false);
418
+
419
+ document.addEventListener("drop", function(e) {
420
+
421
+ e.preventDefault();
422
+
423
+ for (var target = e.target; target && target != this; target = target.parentNode) {
424
+ if (target.matches('[data-reorder] tbody tr')) {
425
+
426
+ if(target.parentNode != null && draggedRow.parentNode != null && target != draggedRow){
427
+
428
+ draggedRow.parentNode.removeChild( draggedRow );
429
+
430
+ if(draggedRow.getAttribute('data-order') > target.getAttribute('data-order'))
431
+ target.parentNode.insertBefore(draggedRow, target);
432
+ else
433
+ target.parentNode.insertBefore(draggedRow, target.nextElementSibling);
434
+
435
+ // Re label the rows
436
+ Array.from(tbody.querySelectorAll('tr')).forEach((tableRowOrder, index) => {
437
+ tableRowOrder.classList.remove('tr--dragging')
438
+ tableRowOrder.classList.remove('tr--dropable')
439
+ tableRowOrder.querySelector('th').innerHTML = index + 1;
440
+ tableRowOrder.setAttribute('data-order',index+1);
441
+ });
442
+
443
+ tableElement.dispatchEvent(reorderedEvent);
444
+ }
445
+ break;
446
+ }
447
+ }
448
+ }, false);
449
+
450
+ }
451
+ // #endregion Reorderable
452
+
453
+ // Watch for the filterable event and re-sort the tbody
454
+ tableElement.addEventListener('filtered', function (e) {
455
+
456
+ if(tableElement.getAttribute('data-sortBy') && tableElement.getAttribute('data-sort'))
457
+ sortTable(tableElement.getAttribute('data-sortBy'), tableElement.getAttribute('data-sort'));
458
+
459
+ if(tableElement.getAttribute('data-show')){
460
+
461
+ const show = parseInt(tableElement.getAttribute('data-show'));
462
+ const totalRows = tableElement.querySelectorAll('tbody tr').length;
463
+ const tablePagination = tableElement.querySelector('.table__pagination');
464
+
465
+ if(tablePagination != null)
466
+ tablePagination.remove();
467
+
468
+ if(show < totalRows){
469
+
470
+ paginateRows(show,1);
471
+ createPaginationForm(randID,tableElement,show,1,totalRows);
472
+ createPaginationButttons(randID,tableElement,show,1,totalRows);
473
+ }
474
+ }
475
+
476
+ if(tableElement.getAttribute('data-reorder')){
477
+
478
+ setReorderRows();
479
+ }
480
+ }, false);
481
+
482
+ tableElement.addEventListener('sorted', function (e) {
483
+
484
+ if(tableElement.getAttribute('data-reorder')){
485
+
486
+ setReorderRows();
487
+ }
488
+ }, false);
489
+
490
+ tableElement.addEventListener('populated', function (e) {
491
+
492
+ var tableFilter = tableElement.querySelector('.table__filters')
493
+ tableFilter.remove();
494
+
495
+ var tablePagination = tableElement.querySelector('.table__pagination')
496
+ tablePagination.remove();
497
+
498
+ var newTable = tableElement.cloneNode(true);
499
+ tableElement.parentNode.replaceChild(newTable, tableElement);
500
+
501
+ table(newTable);
502
+ }, false);
503
+ }
504
+
505
+ export const createPaginationForm = function(randID,tableElement,show,page,totalRows){
506
+
507
+ const form = document.createElement("div");
508
+ form.classList.add('table__pagination');
509
+ form.classList.add('row');
510
+ form.classList.add('pt-3');
511
+ form.classList.add('pb-3');
512
+
513
+ // Create the form and create a container div to hold the pagination buttons
514
+ form.innerHTML = `<div class="col mw-fit-content mb-3">
515
+ <div class="form-control__wrapper form-control-inline mb-0">
516
+ <label for="${randID}_showing" class="form-label">Showing:</label>
517
+ <input type="number" name="${randID}_showing" id="${randID}_showing" class="form-control form-control-sm showing-input-field" placeholder="" list="${randID}_pagination" value="${show}" min="1" max="${totalRows}" />
518
+ </div>
519
+ <datalist id="${randID}_pagination">
520
+ <option value="5">5</option>
521
+ ${totalRows > 10 ? `<option value="10">10</option>` : ''}
522
+ ${totalRows > 20 ? `<option value="20">20</option>` : ''}
523
+ <option value="${totalRows}">${totalRows}</option>
524
+ </datalist>
525
+ </div>
526
+ <div class="col mw-fit-content me-auto d-flex align-items-center mb-3"><span class="label">per page</span></div>
527
+ <div class="col mw-fit-content d-sm-flex justify-content-end align-items-center" id="${randID}_paginationBtns"></div>`;
528
+
529
+ // Add after the actual table
530
+ tableElement.append(form)
531
+ }
532
+
533
+ export const createPaginationButttons = function(randID,tableElement,show,page,totalRows){
534
+
535
+ const paginationButtonsWrapper = document.getElementById(randID+'_paginationBtns')
536
+
537
+ if(paginationButtonsWrapper == null)
538
+ return false;
539
+
540
+ const numberPages = Math.ceil(totalRows / show)
541
+
542
+ if(numberPages == 1){ // Remore the buttons or dont display any if we dont need them
543
+ paginationButtonsWrapper.innerHTML = '';
544
+ }
545
+ else if(numberPages < 5){ // If less than 5 pages (which fits comfortably on mobile) we display buttons
546
+
547
+ let strButtons = '';
548
+
549
+ for (let i = 1; i <= numberPages; i++) {
550
+
551
+ if(i == page)
552
+ strButtons += `<li class="page-item active" aria-current="page"><span class="page-link">${i}</span></li>`;
553
+ else
554
+ strButtons += `<li class="page-item"><button class="page-link" data-page="${i}">${i}</button></li>`;
555
+ }
556
+
557
+ paginationButtonsWrapper.innerHTML = `<span class="pe-2 mb-3">Page: </span><ul class="pagination mb-3">
558
+ ${page == 1 ? `<li class="page-item disabled"><span class="page-link">Previous</span></li>` : `<li class="page-item"><button class="page-link" data-page="${parseInt(page)-1}">Previous</button></li>`}
559
+ ${strButtons}
560
+ ${page == numberPages ? `<li class="page-item disabled"><span class="page-link">Next</span></li>` : `<li class="page-item"><button class="page-link" data-page="${parseInt(page)+1}">Next</button></li>`}
561
+ </ul>`;
562
+
563
+ }
564
+ else { // If more than 5 lets show a select field instead so that we dont have loads and loads of buttons
565
+
566
+ let strOptions = '';
567
+
568
+ for (let i = 1; i <= numberPages; i++) {
569
+
570
+ if(i == page)
571
+ strOptions += `<option value="${i}" selected>Page ${i}</option>`;
572
+ else
573
+ strOptions += `<option value="${i}">Page ${i}</option>`;
574
+ }
575
+
576
+ paginationButtonsWrapper.innerHTML = `
577
+ <div class="form-control__wrapper page-number mb-2">
578
+ <select class="form-select">
579
+ ${strOptions}
580
+ </select>
581
+ </div>
582
+ `;
583
+ }
584
+ }
585
+
586
+ export default table
@@ -0,0 +1,84 @@
1
+ // @ts-nocheck
2
+ function testimonial(testimonialElement) {
3
+
4
+ var scrollTimeout;
5
+ const imagesCarousel = testimonialElement.querySelector('.testimonial__images');
6
+ const itemCount = imagesCarousel.querySelectorAll('img').length;
7
+
8
+ // If we only have 1 item lets not bother doing anything else
9
+ if(itemCount == 1){
10
+ return false;
11
+ }
12
+
13
+ testimonialElement.classList.add('testimonial--multi')
14
+
15
+ // Set where the buttons go to
16
+ const setButtons = function(scrollTo){
17
+
18
+ const nextButton = testimonialElement.querySelector('.btn-next');
19
+ const prevButton = testimonialElement.querySelector('.btn-prev');
20
+
21
+ nextButton.setAttribute('data-go',scrollTo+1);
22
+ prevButton.setAttribute('data-go',scrollTo-1);
23
+ nextButton.removeAttribute('disabled')
24
+ prevButton.removeAttribute('disabled')
25
+
26
+ if(scrollTo == 1)
27
+ prevButton.setAttribute('disabled',true);
28
+ else if(scrollTo == itemCount)
29
+ nextButton.setAttribute('disabled',true);
30
+ }
31
+
32
+ // On scroll we need to make sure the buttons get corrected and the next testimonial is shown
33
+ imagesCarousel.addEventListener('scroll', function(e){
34
+ clearTimeout(scrollTimeout);
35
+ scrollTimeout = setTimeout(function(){
36
+
37
+ let scrollWidth = imagesCarousel.scrollWidth;
38
+ let scrollHeight = imagesCarousel.scrollHeight;
39
+ let scrollLeft = imagesCarousel.scrollLeft;
40
+ let scrollDown = imagesCarousel.scrollTop;
41
+ let scrollTo = Math.round((scrollLeft / scrollWidth) * itemCount) + 1;
42
+
43
+ // Change in scroll direction
44
+ if(scrollLeft == 0 && scrollDown != 0)
45
+ scrollTo = Math.round((scrollDown / scrollHeight) * itemCount) + 1;
46
+
47
+ testimonialElement.setAttribute('data-show',scrollTo)
48
+ setButtons(scrollTo);
49
+ }, 300);
50
+
51
+ }, false);
52
+
53
+ // when the buttons are used we need to make sure the carousel scrolls to the correct place
54
+ testimonialElement.addEventListener('click', function(e){
55
+
56
+ for (var target = e.target; target && target != this; target = target.parentNode) {
57
+
58
+ if (target.matches('[data-go]')) {
59
+
60
+ let scrollTo = parseInt(target.getAttribute('data-go'));
61
+ let scrollDown = 0;
62
+ let scrollLeft = 0
63
+ let scrollWidth = imagesCarousel.scrollWidth;
64
+ let scrollHeight = imagesCarousel.scrollHeight;
65
+
66
+ if(scrollWidth > scrollHeight)
67
+ scrollLeft = Math.floor(scrollWidth * ((scrollTo-1) / itemCount))
68
+ else
69
+ scrollDown = Math.floor(scrollHeight * ((scrollTo-1) / itemCount))
70
+
71
+ // Trigger the scroll
72
+ imagesCarousel.scroll({
73
+ top: scrollDown,
74
+ left: scrollLeft,
75
+ behavior: 'smooth'
76
+ });
77
+
78
+ break;
79
+ }
80
+ }
81
+ }, false);
82
+ }
83
+
84
+ export default testimonial