@iamproperty/components 3.7.9 → 3.9.0-beta-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/assets/css/components/accordion.css.map +1 -1
  2. package/assets/css/components/actionbar-global.css +1 -0
  3. package/assets/css/components/actionbar-global.css.map +1 -0
  4. package/assets/css/components/actionbar.css +1 -0
  5. package/assets/css/components/actionbar.css.map +1 -0
  6. package/assets/css/components/dialog.css +1 -1
  7. package/assets/css/components/dialog.css.map +1 -1
  8. package/assets/css/components/fileupload.css.map +1 -1
  9. package/assets/css/components/forms.css +1 -1
  10. package/assets/css/components/forms.css.map +1 -1
  11. package/assets/css/components/header.css +1 -1
  12. package/assets/css/components/header.css.map +1 -1
  13. package/assets/css/components/lists.css.map +1 -1
  14. package/assets/css/components/nav-global.css +1 -0
  15. package/assets/css/components/nav-global.css.map +1 -0
  16. package/assets/css/components/nav.css +1 -1
  17. package/assets/css/components/nav.css.map +1 -1
  18. package/assets/css/components/nav.docs.css +1 -0
  19. package/assets/css/components/nav.docs.css.map +1 -0
  20. package/assets/css/components/nav.old.css +1 -0
  21. package/assets/css/components/nav.old.css.map +1 -0
  22. package/assets/css/components/pagination.css.map +1 -1
  23. package/assets/css/components/property-searchbar.css +1 -1
  24. package/assets/css/components/property-searchbar.css.map +1 -1
  25. package/assets/css/components/table.css +1 -1
  26. package/assets/css/components/table.css.map +1 -1
  27. package/assets/css/core.min.css +1 -1
  28. package/assets/css/core.min.css.map +1 -1
  29. package/assets/css/style.min.css +1 -1
  30. package/assets/css/style.min.css.map +1 -1
  31. package/assets/js/components/accordion/accordion.component.min.js +1 -1
  32. package/assets/js/components/actionbar/actionbar.component.js +305 -0
  33. package/assets/js/components/actionbar/actionbar.component.min.js +53 -0
  34. package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -0
  35. package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
  36. package/assets/js/components/card/card.component.min.js +1 -1
  37. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  38. package/assets/js/components/header/header.component.min.js +2 -2
  39. package/assets/js/components/nav/nav.component.js +294 -0
  40. package/assets/js/components/nav/nav.component.min.js +51 -0
  41. package/assets/js/components/nav/nav.component.min.js.map +1 -0
  42. package/assets/js/components/notification/notification.component.min.js +1 -1
  43. package/assets/js/components/pagination/pagination.component.min.js +1 -1
  44. package/assets/js/components/table/table.component.js +33 -0
  45. package/assets/js/components/table/table.component.min.js +11 -10
  46. package/assets/js/components/table/table.component.min.js.map +1 -1
  47. package/assets/js/components/tabs/tabs.component.min.js +1 -1
  48. package/assets/js/dynamic.min.js +3 -3
  49. package/assets/js/dynamic.min.js.map +1 -1
  50. package/assets/js/modules/dialogs.js +18 -5
  51. package/assets/js/modules/table.js +22 -4
  52. package/assets/js/scripts.bundle.js +15 -14
  53. package/assets/js/scripts.bundle.js.map +1 -1
  54. package/assets/js/scripts.bundle.min.js +2 -2
  55. package/assets/js/scripts.bundle.min.js.map +1 -1
  56. package/assets/sass/_corefiles.scss +2 -0
  57. package/assets/sass/_functions/mixins.scss +25 -0
  58. package/assets/sass/_functions/variables.scss +5 -3
  59. package/assets/sass/components/actionbar-global.scss +89 -0
  60. package/assets/sass/components/actionbar.scss +254 -0
  61. package/assets/sass/components/dialog.scss +99 -1
  62. package/assets/sass/components/forms.scss +96 -21
  63. package/assets/sass/components/nav-global.scss +619 -0
  64. package/assets/sass/components/nav.docs.scss +54 -0
  65. package/assets/sass/components/nav.old.scss +965 -0
  66. package/assets/sass/components/nav.scss +450 -782
  67. package/assets/sass/components/table.scss +9 -1
  68. package/assets/sass/foundations/buttons.scss +87 -14
  69. package/assets/sass/foundations/links.scss +1 -1
  70. package/assets/sass/foundations/reboot.scss +5 -3
  71. package/assets/ts/components/actionbar/README.md +55 -0
  72. package/assets/ts/components/actionbar/actionbar.component.ts +396 -0
  73. package/assets/ts/components/nav/README.md +68 -0
  74. package/assets/ts/components/nav/nav.component.ts +370 -0
  75. package/assets/ts/components/table/table.component.ts +65 -0
  76. package/assets/ts/modules/dialogs.ts +24 -6
  77. package/assets/ts/modules/table.ts +29 -7
  78. package/dist/components.es.js +1013 -1258
  79. package/dist/components.umd.js +97 -47
  80. package/dist/style.css +1 -1
  81. package/package.json +1 -1
  82. package/src/components/Actionbar/Actionbar.vue +20 -0
  83. package/src/components/Actionbar/README.md +40 -0
  84. package/src/components/Nav/Nav.vue +20 -195
  85. package/src/components/Nav/README.md +43 -13
  86. package/src/components/Nav-old/Nav.vue +213 -0
  87. package/src/components/Nav-old/README.md +23 -0
  88. package/src/components/Nav/Nav.spec.js +0 -35
@@ -0,0 +1,68 @@
1
+ **Add the below to your initialise script**
2
+
3
+ ```
4
+ import('../node_modules/@iamproperty/components/assets/js/components/nav/nav.component.min').then(module => { // Might need to update the path
5
+
6
+ if (!window.customElements.get(`iam-nav`))
7
+ window.customElements.define(`iam-nav`, module.default);
8
+
9
+ }).catch((err) => {
10
+ console.log(err.message);
11
+ });
12
+ ```
13
+
14
+ **Add the below HTML code to where you want the component to live.**
15
+
16
+ ```
17
+ <nav>
18
+ <iam-nav>
19
+ <a href="/" class="brand brand--property" slot="logo">
20
+ <svg>
21
+ <title>iamproperty</title>
22
+ <use xlink:href="/svg/logo.svg#logo-property"></use>
23
+ </svg>
24
+ </a>
25
+
26
+ <a href="/" class="selected">Lorem ipsum</a>
27
+ <a href="/">Lorem ipsum</a>
28
+ <a href="/">Lorem ipsum</a>
29
+ <a href="/">Lorem ipsum</a>
30
+
31
+ <button class="btn btn-primary">Lorem ipsum</button>
32
+ </iam-nav>
33
+ </nav>
34
+ ```
35
+
36
+ **Properties**
37
+
38
+ | Option | Type | Default Value | Description |
39
+ | ------ | ---- | ------------- | ----------- |
40
+ | data-search | String | - | Optional, displays a search button and form. The value passed through is used for the forms action attribute. |
41
+ | data-list | String | - | Optional string with an ID of a datalist, note this list needs to be added as an element in the component |
42
+ | data-prevent-search | String | - | Flag that prevents the search form submitting allowing it to used purely with JavaScript |
43
+ | data-searcd-open | String | - | Flag that opens the search bar on desktop on page load. |
44
+
45
+ **Slots**
46
+
47
+ | Option | Default Value | Description |
48
+ | ------ | ------------- | ----------- |
49
+ | default | - | Populates the main nav area |
50
+ | logo | - | A place to add the logo to the site |
51
+ | secondary | - | Moves the link upto the top of the navbar on desktop |
52
+ | actions | - | A place to add buttons |
53
+ | dual | - | Plave the link or list to the right of the nav, forcing the default slot to the left. |
54
+
55
+ **Class modifiers**
56
+
57
+ - Adding a class of **.bg-primary** will change the background of the navbar without chaning the menu background.
58
+ - Adding a class of **.nav--sticky** will add etxra styling to make the navbar stick to the top of the page
59
+ - Adding a class of **.nav--xs-sticky** will add etxra styling to make the navbar stick to the top of the page BUT only on the mobile view.
60
+
61
+ **Dispatched events**
62
+
63
+ | Event | Dispatched when | Details passed|
64
+ | ------ | ------------- | ----------- |
65
+ | search-keydown | When a user uses the search input field and triggers the keydown event. | { search: $inputValue } |
66
+ | search-keyup | When a user uses the search input field and triggers the keyup event. | { search: $inputValue } |
67
+ | search-change | When a user uses the search input field and triggers the change event. | { search: $inputValue } |
68
+ | search-submit | When a user uses the search form and triggers the submit event. | { search: $inputValue } |
@@ -0,0 +1,370 @@
1
+ // @ts-nocheck
2
+
3
+ // Data layer Web component created
4
+ window.dataLayer = window.dataLayer || [];
5
+ window.dataLayer.push({
6
+ "event": "customElementRegistered",
7
+ "element": "nav"
8
+ });
9
+
10
+ class iamNav extends HTMLElement {
11
+
12
+ constructor(){
13
+ super();
14
+ const shadowRoot = this.attachShadow({ mode: 'open'});
15
+
16
+ const assetLocation = document.body.hasAttribute('data-assets-location') ? document.body.getAttribute('data-assets-location') : '/assets';
17
+ const coreCSS = document.body.hasAttribute('data-core-css') ? document.body.getAttribute('data-core-css') : `${assetLocation}/css/core.min.css`;
18
+ const loadCSS = `@import "${assetLocation}/css/components/nav.css";`;
19
+
20
+ const template = document.createElement('template');
21
+ template.innerHTML = `
22
+ <style class="styles">
23
+ @import "${coreCSS}";
24
+ ${loadCSS}
25
+ </style>
26
+ <link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous">
27
+ <div class="container">
28
+ <slot name="logo"></slot>
29
+ <div class="buttons-holder"></div>
30
+ <button class="btn-menu">Menu<i class="fa-regular fa-bars"></i><i class="fa-regular fa-xmark-large"></i></button>
31
+
32
+ <div class="menu__outer">
33
+ <div class="menu closed">
34
+
35
+ <div class="menu__primary">
36
+ <slot></slot>
37
+ <slot name="dual"></slot>
38
+ </div>
39
+ <div class="dialog__wrapper d-none" id="search-wrapper"></div>
40
+ <slot name="actions"></slot>
41
+ <div class="menu__secondary">
42
+ <div class="container">
43
+ <slot name="secondary"></slot>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ <slot name="menus"></slot>
48
+ </div>
49
+ </div>
50
+ <div class="lists"></div>
51
+ <div class="backdrop" part="backdrop"></div>
52
+ `;
53
+
54
+ shadowRoot.appendChild(template.content.cloneNode(true));
55
+ }
56
+
57
+ connectedCallback() {
58
+
59
+ // Load external CSS if needed
60
+ if(this.hasAttribute('data-css'))
61
+ this.shadowRoot.querySelector('.styles').insertAdjacentHTML('beforeend', `@import "${this.getAttribute('data-css')}";`);
62
+
63
+ const menuButton = this.shadowRoot.querySelector('.btn-menu');
64
+ const menu = this.shadowRoot.querySelector('.menu');
65
+ const iamNav = this;
66
+ const backdrop = this.shadowRoot.querySelector('.backdrop');
67
+ const buttonsHolder = this.shadowRoot.querySelector('.buttons-holder');
68
+
69
+ // Check the content
70
+ this.querySelectorAll(':scope > *').forEach(function(element){
71
+ let tagname = element.tagName;
72
+
73
+ switch(tagname){
74
+ case "BUTTON":
75
+ element.setAttribute('slot','actions');
76
+ menu.classList.add('has-actions')
77
+ break;
78
+ }
79
+
80
+ // Create menu button
81
+ if(element.classList.contains('nav--menu') && element.hasAttribute('data-title') && element.hasAttribute('data-icon')){
82
+
83
+ const title = element.getAttribute('data-title');
84
+ const iconClass = element.getAttribute('data-icon');
85
+
86
+ // Create the menu button that sits seperately to the menu
87
+ const button = document.createElement('button');
88
+ button.setAttribute('slot',title);
89
+ button.classList.add('btn-menu');
90
+ button.innerHTML = `<span class="btn btn-primary"><span>${title}</span><i class="${iconClass}"></i><i class="fa-regular fa-xmark-large"></i></span>`;
91
+ buttonsHolder.insertAdjacentElement('beforeend',button);
92
+
93
+ const mdButton = button.querySelector('.btn-primary');
94
+
95
+ // Make sure the menu is added to the right part of the component
96
+ element.setAttribute('slot','menus');
97
+
98
+ // If open we need to make sure the main mobile menu is closed, the new button has the right state and the backdrop is shown
99
+ if(element.classList.contains('open')){
100
+ button.classList.add('selected');
101
+ mdButton.classList.toggle('active');
102
+ iamNav.classList.add('open');
103
+ backdrop.classList.add('show');
104
+ }
105
+ else {
106
+ element.classList.add('closed'); // closed class is added to prevent the elements being tabbed into, this causes visual issues
107
+ }
108
+
109
+ // Click event
110
+ button.addEventListener('click', function(e){
111
+
112
+ e.preventDefault();
113
+ button.classList.toggle('selected');
114
+ element.classList.toggle('open');
115
+ mdButton.classList.toggle('active');
116
+
117
+ // Close desktop menus
118
+ let openMenu = iamNav.querySelector(':scope > details[open]');
119
+
120
+ if(openMenu)
121
+ openMenu.removeAttribute('open')
122
+
123
+ // Close the main menu and fix states on the button, iamNav component and backdrop
124
+ if(element.classList.contains('open')){
125
+
126
+ menu.classList.remove('open');
127
+ menuButton.classList.remove('selected');
128
+ setTimeout(function(){ menu.classList.add('closed') }, 1000); // Delay until its close so the animation is broken
129
+ iamNav.classList.add('open');
130
+ backdrop.classList.add('show');
131
+ element.classList.remove('closed');
132
+ }
133
+ else{
134
+ iamNav.classList.remove('open');
135
+ backdrop.classList.remove('show');
136
+ setTimeout(function(){ element.classList.add('closed') }, 1000);
137
+ }
138
+
139
+ // Close any open menus
140
+ iamNav.querySelectorAll('.nav--menu.open').forEach(function(openmenu){
141
+ if(openmenu != element) {
142
+ openmenu.classList.remove('open');
143
+ }
144
+ });
145
+
146
+ iamNav.shadowRoot.querySelectorAll('.buttons-holder .btn-menu.selected').forEach(function(selectedButton){
147
+
148
+ if(selectedButton != button){
149
+
150
+ selectedButton.classList.remove('selected');
151
+ let innerBtn = selectedButton.querySelector('.btn-primary');
152
+ innerBtn.classList.remove('active');
153
+ }
154
+ });
155
+
156
+ }, false);
157
+ }
158
+ });
159
+
160
+ // Has secondary link
161
+ if(this.querySelector('a[slot="secondary"]')){
162
+ menu.classList.add('has-secondary');
163
+ }
164
+
165
+ // Create a scroll width variable to help with the sizing of the menu with in the CSS
166
+ document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.offsetWidth) + 'px');
167
+
168
+ // Open and close the menu
169
+ menuButton.addEventListener('click', function(e){
170
+
171
+ e.preventDefault();
172
+ menuButton.classList.toggle('selected');
173
+ menu.classList.toggle('open');
174
+
175
+ // Close any other menus
176
+ iamNav.querySelectorAll('.nav--menu.open').forEach(function(element){
177
+ element.classList.remove('open');
178
+ setTimeout(function(){ element.classList.add('closed') }, 1000);
179
+ });
180
+ iamNav.shadowRoot.querySelectorAll('.buttons-holder .btn-menu.selected').forEach(function(element){
181
+ element.classList.remove('selected');
182
+ let innerBtn = element.querySelector('.btn-primary');
183
+ innerBtn.classList.remove('active');
184
+ });
185
+
186
+ if(menu.classList.contains('open')){
187
+ iamNav.classList.add('open');
188
+ menu.classList.remove('closed');
189
+ }
190
+ else {
191
+ iamNav.classList.remove('open');
192
+ setTimeout(function(){ menu.classList.add('closed') }, 1000);
193
+ }
194
+
195
+ }, false);
196
+
197
+ // Allow outside JS to close the menu
198
+ this.addEventListener("request-close", (event) => {
199
+
200
+ menuButton.classList.remove('selected');
201
+ menu.classList.remove('open');
202
+ iamNav.classList.remove('open');
203
+ });
204
+
205
+ // Close the menu on the click of the backdrop on desktop
206
+ backdrop.addEventListener("click", (event) => {
207
+
208
+ let openMenu = this.querySelector('details[open] summary');
209
+
210
+ if(openMenu)
211
+ openMenu.click();
212
+
213
+ iamNav.querySelectorAll('.nav--menu.open').forEach(function(element){
214
+ element.classList.remove('open');
215
+ });
216
+ iamNav.shadowRoot.querySelectorAll('.buttons-holder .btn-menu.selected').forEach(function(element){
217
+ element.classList.remove('selected');
218
+ let innerBtn = element.querySelector('.btn-primary');
219
+ innerBtn.classList.remove('active');
220
+ });
221
+
222
+ backdrop.classList.remove('show');
223
+ });
224
+
225
+ // On desktop close other menu's (details) when one is clicked
226
+ this.addEventListener("click", (event) => {
227
+
228
+ if (event && event.target instanceof HTMLElement && event.target.closest('summary')){
229
+
230
+ if(window.innerWidth > 992){
231
+
232
+ let summary = event.target.closest('summary');
233
+ let details = summary.closest('details');
234
+ let wrapper = details.parentNode;
235
+
236
+ if(details.hasAttribute('open'))
237
+ details.removeAttribute('open');
238
+ else
239
+ details.setAttribute('open','true');
240
+
241
+ // Close any bespoke menus
242
+ iamNav.querySelectorAll('.nav--menu.open').forEach(function(element){
243
+ element.classList.remove('open');
244
+ setTimeout(function(){ menu.classList.add('closed') }, 1000);
245
+ });
246
+ iamNav.shadowRoot.querySelectorAll('.buttons-holder .btn-menu.selected').forEach(function(element){
247
+ element.classList.remove('selected');
248
+ let innerBtn = element.querySelector('.btn-primary');
249
+ innerBtn.classList.remove('active');
250
+ });
251
+
252
+ // Close any other dropdowns on the same level
253
+ Array.from(wrapper.querySelectorAll(':scope > details')).forEach((detailsArrayElement, index) => {
254
+
255
+ if(detailsArrayElement != details)
256
+ detailsArrayElement.removeAttribute('open')
257
+ });
258
+
259
+ if(this.querySelectorAll(':scope > details[open]').length){
260
+ backdrop.classList.add('show');
261
+ iamNav.classList.add('open');
262
+ }
263
+ else {
264
+ backdrop.classList.remove('show');
265
+ iamNav.classList.remove('open');
266
+ }
267
+
268
+ event.preventDefault();
269
+ }
270
+ };
271
+ });
272
+
273
+ // Mega menu title
274
+ this.querySelectorAll('details').forEach((detailsElement) => {
275
+
276
+ let summary = detailsElement.querySelector('summary');
277
+ let containerDiv = detailsElement.querySelector(':Scope > div');
278
+
279
+ containerDiv.setAttribute('data-title', summary.textContent);
280
+ });
281
+
282
+ // Search
283
+ if(this.hasAttribute('data-search')){
284
+ menu.classList.add('has-search');
285
+ let searchWrapper = this.shadowRoot.querySelector('#search-wrapper');
286
+
287
+ searchWrapper.classList.remove('d-none');
288
+ searchWrapper.insertAdjacentHTML('afterbegin',`<button class="btn btn-secondary btn-compact fa-search me-0 mb-0" id="search-button">Open Search field</button>
289
+ <dialog id="search-dialog">
290
+ <div class="container">
291
+ <form action="${this.hasAttribute('data-search') ? this.getAttribute('data-search') : ''}" class="row" id="search-form">
292
+ <div class="col mb-0 ms-auto col-md-7">
293
+ <label for="search" class="visually-hidden">Search</label>
294
+ <button class="suffix me-0 mb-0"><i class="fa-regular fa-search"></i></button>
295
+ <input type="search" class="" id="search" name="search" required="" autocomplete="off" data-list="${this.hasAttribute('data-list') ? this.getAttribute('data-list') : ''}" />
296
+ </div>
297
+ <div class="col d-none d-md-block mw-fit-content ms-3">
298
+ <button class="btn btn-compact btn-secondary fa-xmark-large m-0 mb-0" type="button" id="search-close"></button>
299
+ </div>
300
+ </form>
301
+ </div>
302
+ </dialog>`);
303
+
304
+ let searchButton = this.shadowRoot.querySelector('#search-button');
305
+ let searchClose = this.shadowRoot.querySelector('#search-close');
306
+ let searchDialog = this.shadowRoot.querySelector('#search-dialog');
307
+ let searchInput = this.shadowRoot.querySelector('#search');
308
+ let searchForm = this.shadowRoot.querySelector('#search-form');
309
+
310
+ if(this.hasAttribute('data-search-open')){
311
+
312
+ searchDialog.setAttribute('open','open');
313
+ this.classList.add('search-open');
314
+ }
315
+
316
+ searchButton.addEventListener("click", (event) => {
317
+
318
+ searchDialog.setAttribute('open','open');
319
+ this.classList.add('search-open');
320
+ });
321
+
322
+ searchClose.addEventListener("click", (event) => {
323
+
324
+ searchDialog.removeAttribute('open');
325
+ this.classList.remove('search-open');
326
+ });
327
+
328
+ // Search events
329
+ searchInput.addEventListener('keydown', (event) => {
330
+
331
+ const keyupEvent = new CustomEvent("search-keydown", { detail: { search: searchInput.value } });
332
+ this.dispatchEvent(keyupEvent);
333
+ });
334
+
335
+ searchInput.addEventListener('keyup', (event) => {
336
+
337
+ if (searchInput.value.length >= 3 && searchInput.hasAttribute('data-list'))
338
+ searchInput.setAttribute("list", searchInput.getAttribute('data-list'));
339
+ else
340
+ searchInput.removeAttribute("list");
341
+
342
+ const keyupEvent = new CustomEvent("search-keyup", { detail: { search: searchInput.value } });
343
+ this.dispatchEvent(keyupEvent);
344
+ });
345
+
346
+ searchInput.addEventListener('change', (event) => {
347
+
348
+ const changeEvent = new CustomEvent("search-change", { detail: { search: searchInput.value } });
349
+ this.dispatchEvent(changeEvent);
350
+ });
351
+
352
+ searchForm.addEventListener('submit', (event) => {
353
+
354
+ if(this.hasAttribute('data-prevent-search'))
355
+ event.preventDefault();
356
+
357
+ const submitEvent = new CustomEvent("search-submit", { detail: { search: searchInput.value } });
358
+ this.dispatchEvent(submitEvent);
359
+ });
360
+
361
+ // Make sure any child lists are available to the search input
362
+ this.querySelectorAll('datalist').forEach((list) => {
363
+
364
+ iamNav.shadowRoot.querySelector('.lists').insertAdjacentElement('beforeend',list);
365
+ });
366
+ }
367
+ }
368
+ }
369
+
370
+ export default iamNav;
@@ -27,6 +27,7 @@ class iamTable extends HTMLElement {
27
27
 
28
28
  ${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
29
29
  </style>
30
+ <slot name="before"></slot>
30
31
  <div class="table--cta">
31
32
  <div class="table__wrapper">
32
33
  <slot></slot>
@@ -124,6 +125,70 @@ class iamTable extends HTMLElement {
124
125
  }
125
126
 
126
127
  });
128
+
129
+
130
+ // Add in the checkboxes
131
+
132
+ if(this.querySelector('iam-actionbar[data-selectall]')){
133
+
134
+ const actionbar = this.querySelector('iam-actionbar[data-selectall]');
135
+
136
+ Array.from(this.table.querySelectorAll('thead tr')).forEach((row,index) => {
137
+
138
+ row.insertAdjacentHTML(
139
+ 'afterbegin',
140
+ "<th></th>"
141
+ );
142
+ });
143
+
144
+ Array.from(this.table.querySelectorAll('tbody tr')).forEach((row,index) => {
145
+
146
+ row.insertAdjacentHTML(
147
+ 'afterbegin',
148
+ `<td class="selectrow"><input type="checkbox" name="row" id="row${index}"/><label for="row${index}"><span class="visually-hidden">Select row</span></label></td>`
149
+ );
150
+ });
151
+
152
+ this.table.addEventListener('change',(event) => {
153
+
154
+ if (event && event.target instanceof HTMLElement && event.target.closest('.selectrow input')){
155
+
156
+
157
+ let count = this.table.querySelectorAll('.selectrow input[type="checkbox"]').length;
158
+ let countChecked = this.table.querySelectorAll('.selectrow input[type="checkbox"]:checked').length;
159
+
160
+ actionbar.setAttribute('data-selected', count == countChecked ? "all" : countChecked);
161
+
162
+ console.log(countChecked);
163
+ };
164
+
165
+ });
166
+
167
+ actionbar.addEventListener('selected', (event) => {
168
+
169
+ console.log(event.detail.selected);
170
+
171
+
172
+ if(event.detail.selected == '0'){
173
+
174
+ Array.from(this.table.querySelectorAll('.selectrow input[type="checkbox"]')).forEach((input,index) => {
175
+
176
+ input.checked = false;
177
+ });
178
+
179
+ }
180
+ else if(event.detail.selected == 'all'){
181
+
182
+ Array.from(this.table.querySelectorAll('.selectrow input[type="checkbox"]')).forEach((input,index) => {
183
+
184
+ input.checked = true;
185
+ });
186
+
187
+ }
188
+
189
+ });
190
+
191
+ }
127
192
  }
128
193
 
129
194
 
@@ -20,6 +20,9 @@ const extendDialogs = (body) => {
20
20
  // Dialogs/modals
21
21
  body.addEventListener('click', (event) => {
22
22
 
23
+ if(event.target.tagName == 'IAM-ACTIONBAR')
24
+ return false;
25
+
23
26
  // Modal
24
27
  if (event && event.target instanceof HTMLElement && event.target.closest('[data-modal]')){
25
28
 
@@ -77,7 +80,12 @@ const extendDialogs = (body) => {
77
80
 
78
81
  // Close the modal when clicked on the backdrop
79
82
  if (event && event.target instanceof HTMLElement && event.target.closest('dialog[open]')){
80
- const dialog = event.target.closest('dialog[open]');
83
+ let dialog = event.target.closest('dialog[open]');
84
+
85
+ // Small fix to make sure the dialog isn't a dialog inside of a dialog.
86
+ var style = window.getComputedStyle(dialog);
87
+ if(style.display === 'contents')
88
+ dialog = dialog.parentNode.closest('dialog[open]');
81
89
 
82
90
  // Dont allow the backdrop to be clicked when transactional
83
91
  if(!dialog.querySelector(':scope > .mh-lg > form:last-child > button:last-child, :scope > .mh-lg > button:last-child') || dialog.classList.contains('dialog--multi')){
@@ -101,13 +109,16 @@ const extendDialogs = (body) => {
101
109
  // Popover
102
110
  if (event && event.target instanceof HTMLElement && event.target.closest('.dialog__wrapper > button')){
103
111
 
112
+
113
+ event.stopPropagation();
114
+
104
115
  let btn = event.target.closest('.dialog__wrapper > button');
105
116
  let parent = event.target.closest('.dialog__wrapper > button').parentNode;
106
117
  let dataEvent = "openPopover"
107
118
  let popover = parent.querySelector(':scope > dialog');
108
119
 
109
- if(document.querySelector('dialog[open]') && document.querySelector('dialog[open]') != popover)
110
- document.querySelector('dialog[open]').close();
120
+ if(document.querySelector('*:not([data-keep-open]) > dialog[open]') && document.querySelector('*:not([data-keep-open]) > dialog[open]') != popover)
121
+ document.querySelector('*:not([data-keep-open]) > dialog[open]').close();
111
122
 
112
123
  // Remove active class from exiting active buttons
113
124
  Array.from(document.querySelectorAll('.dialog__wrapper > button')).forEach((btnElement,index) => {
@@ -152,8 +163,14 @@ const extendDialogs = (body) => {
152
163
  if(popoverBottom > windowPos){
153
164
 
154
165
  let currentStyle = popover.hasAttribute('style') ? popover.getAttribute('style')+' ' : '';
155
-
156
166
  popover.setAttribute('style',currentStyle+`transform: translate(0, calc(-100% - 4rem))`);
167
+
168
+ // Check that the dialog doesn't go over the top of the page
169
+ boundingRec = popover.getBoundingClientRect();
170
+ let popoverTop = boundingRec.top - window.scrollY;
171
+
172
+ if(popoverTop < 100)
173
+ popover.removeAttribute('style');
157
174
  }
158
175
 
159
176
  window.dataLayer = window.dataLayer || [];
@@ -199,6 +216,7 @@ export const createDialog = (dialog) => {
199
216
  createMultiFormDialog(dialog);
200
217
  }
201
218
 
219
+ // If you are using Vue eevents and bindings its recommended to add in the .mh-lg div manually to the dialog
202
220
  if(!dialog.querySelector(':scope > .mh-lg') && !dialog.classList.contains('dialog--multi')){
203
221
  dialog.innerHTML = `<div class="mh-lg">${dialog.innerHTML}</div>`;
204
222
 
@@ -218,7 +236,7 @@ export const createDialog = (dialog) => {
218
236
 
219
237
  // Create close button is needed
220
238
  if(!dialog.querySelector(':scope > button:first-child'))
221
- dialog.innerHTML = `<button class="dialog__close">Close</button>${dialog.innerHTML}`;
239
+ dialog.insertAdjacentHTML('afterbegin', `<button class="dialog__close">Close</button>`);
222
240
 
223
241
  }
224
242
 
@@ -244,7 +262,7 @@ export const createMultiFormDialog = (dialog) => {
244
262
  btnWrapper.innerHTML += `<button data-title="${fieldsets[index].getAttribute('data-title')}" class="btn btn-primary mb-0" data-next type="submit">Submit</button>`;
245
263
  });
246
264
 
247
- dialog.innerHTML = `<div class="steps bg-primary">${buttons}</div>${dialog.innerHTML}`;
265
+ dialog.insertAdjacentHTML('afterbegin',`<div class="steps bg-primary">${buttons}</div>`);
248
266
 
249
267
 
250
268
  // Open the fieldset with an error inside
@@ -456,12 +456,23 @@ export const filterTable = (table, form, wrapper) => {
456
456
  //Display the filter count
457
457
  Array.from(form.querySelectorAll('[data-filter-count]')).forEach((element, index) => {
458
458
  element.innerHTML = '';
459
+ element.parentNode.classList.remove('hover');
459
460
  });
460
461
 
461
- if(Object.keys(filters).length) {
462
-
462
+ let filterCount = 0;
463
+ Object.values(filters).forEach((filter, index) => {
464
+
465
+ if(typeof filter == "object" && Object.values(filter).length)
466
+ filterCount += Object.values(filter).length;
467
+ else
468
+ filterCount++;
469
+ });
470
+
471
+ if(filterCount) {
472
+
463
473
  Array.from(form.querySelectorAll('[data-filter-count]')).forEach((element, index) => {
464
- element.innerHTML += `(${Object.keys(filters).length})`;
474
+ element.innerHTML += `(${filterCount})`;
475
+ element.parentNode.classList.add('hover');
465
476
  });
466
477
  }
467
478
 
@@ -829,12 +840,23 @@ export const loadAjaxTable = async function (table, form, pagination, wrapper){
829
840
 
830
841
  Array.from(form.querySelectorAll('[data-filter-count]')).forEach((element, index) => {
831
842
  element.innerHTML = '';
843
+ element.parentNode.classList.remove('hover');
832
844
  });
833
845
 
834
- if(Object.keys(filters).length) {
835
-
846
+ let filterCount = 0;
847
+ Object.values(filters).forEach((filter, index) => {
848
+
849
+ if(typeof filter == "object" && Object.values(filter).length)
850
+ filterCount += Object.values(filter).length;
851
+ else
852
+ filterCount++;
853
+ });
854
+
855
+ if(filterCount) {
856
+
836
857
  Array.from(form.querySelectorAll('[data-filter-count]')).forEach((element, index) => {
837
- element.innerHTML += `(${Object.keys(filters).length})`;
858
+ element.innerHTML += `(${filterCount})`;
859
+ element.parentNode.classList.add('hover');
838
860
  });
839
861
  }
840
862
 
@@ -944,7 +966,7 @@ export const loadAjaxTable = async function (table, form, pagination, wrapper){
944
966
  wrapper.setAttribute('data-pages', Math.ceil(wrapper.getAttribute('data-total') / wrapper.getAttribute('data-show')));
945
967
 
946
968
 
947
- makeTableFunctional(table, form, pagination, wrapper);
969
+ makeTableFunctional(table, form, pagination, wrapper);
948
970
  createPaginationButttons(wrapper, pagination);
949
971
 
950
972
  Array.from(form.querySelectorAll('[data-ajax-query]')).forEach((queryElement, index) => {