@iamproperty/components 3.7.8--beta-2 → 3.7.9-beta
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.
- package/assets/css/components/dialog.css +1 -1
- package/assets/css/components/dialog.css.map +1 -1
- package/assets/css/components/fileupload.css +1 -0
- package/assets/css/components/fileupload.css.map +1 -0
- package/assets/css/components/forms.css +1 -1
- package/assets/css/components/forms.css.map +1 -1
- package/assets/css/core.min.css +1 -1
- package/assets/css/core.min.css.map +1 -1
- package/assets/css/style.min.css +1 -1
- package/assets/css/style.min.css.map +1 -1
- package/assets/js/components/accordion/accordion.component.min.js +1 -1
- package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
- package/assets/js/components/card/card.component.min.js +1 -1
- package/assets/js/components/fileupload/fileupload.component.js +44 -0
- package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
- package/assets/js/components/header/header.component.min.js +1 -1
- package/assets/js/components/notification/notification.component.min.js +1 -1
- package/assets/js/components/pagination/pagination.component.min.js +1 -1
- package/assets/js/components/table/table.component.min.js +10 -10
- package/assets/js/components/table/table.component.min.js.map +1 -1
- package/assets/js/components/tabs/tabs.component.min.js +1 -1
- package/assets/js/dynamic.min.js +5 -5
- package/assets/js/dynamic.min.js.map +1 -1
- package/assets/js/modules/data-layer.js +32 -34
- package/assets/js/modules/dialogs.js +1 -1
- package/assets/js/modules/fileupload.js +70 -0
- package/assets/js/modules/inputs.js +10 -0
- package/assets/js/modules/table.js +49 -31
- package/assets/js/scripts.bundle.js +22 -22
- package/assets/js/scripts.bundle.js.map +1 -1
- package/assets/js/scripts.bundle.min.js +2 -2
- package/assets/js/scripts.bundle.min.js.map +1 -1
- package/assets/sass/_forms.scss +1 -1
- package/assets/sass/components/dialog.scss +3 -1
- package/assets/sass/components/fileupload.scss +156 -0
- package/assets/sass/components/forms.scss +98 -135
- package/assets/ts/components/accordion/README.md +15 -0
- package/assets/ts/components/applied-filters/README.md +15 -0
- package/assets/ts/components/card/README.md +15 -0
- package/assets/ts/components/fileupload/README.md +28 -0
- package/assets/ts/components/fileupload/fileupload.component.ts +55 -0
- package/assets/ts/components/filterlist/README.md +15 -0
- package/assets/ts/components/header/README.md +16 -3
- package/assets/ts/components/notification/README.md +15 -0
- package/assets/ts/components/pagination/README.md +15 -0
- package/assets/ts/components/table/README.md +15 -0
- package/assets/ts/components/tabs/README.md +15 -0
- package/assets/ts/modules/data-layer.md +72 -0
- package/assets/ts/modules/data-layer.ts +37 -41
- package/assets/ts/modules/dialogs.ts +1 -1
- package/assets/ts/modules/fileupload.ts +106 -0
- package/assets/ts/modules/inputs.ts +14 -0
- package/assets/ts/modules/table.ts +67 -44
- package/assets/ts/tests/data-layer.spec.js +69 -0
- package/dist/components.es.js +1122 -1148
- package/dist/components.umd.js +55 -40
- package/package.json +1 -1
- package/src/components/Card/Card.vue +8 -4
- package/src/components/FileUpload/FileUpload.vue +29 -0
- package/src/components/FileUpload/README.md +13 -0
- package/src/index.js +1 -1
- package/src/components/FileUploads/FileUploads.vue +0 -48
- package/src/components/FileUploads/README.md +0 -24
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import fileupload from "../../modules/fileupload";
|
|
3
|
+
|
|
4
|
+
// Data layer Web component created
|
|
5
|
+
window.dataLayer = window.dataLayer || [];
|
|
6
|
+
window.dataLayer.push({
|
|
7
|
+
"event": "customElementRegistered",
|
|
8
|
+
"element": "fileupload"
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
class iamFileupload extends HTMLElement {
|
|
12
|
+
|
|
13
|
+
constructor(){
|
|
14
|
+
super();
|
|
15
|
+
this.attachShadow({ mode: 'open'});
|
|
16
|
+
|
|
17
|
+
const assetLocation = document.body.hasAttribute('data-assets-location') ? document.body.getAttribute('data-assets-location') : '/assets'
|
|
18
|
+
const coreCSS = document.body.hasAttribute('data-core-css') ? document.body.getAttribute('data-core-css') : `${assetLocation}/css/core.min.css`;
|
|
19
|
+
const loadCSS = `@import "${assetLocation}/css/components/fileupload.css";`;
|
|
20
|
+
|
|
21
|
+
const template = document.createElement('template');
|
|
22
|
+
template.innerHTML = `
|
|
23
|
+
<style>
|
|
24
|
+
@import "${coreCSS}";
|
|
25
|
+
${loadCSS}
|
|
26
|
+
${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
|
|
27
|
+
</style>
|
|
28
|
+
<div class="file-upload">
|
|
29
|
+
<span class="file-upload__title">Upload file</span>
|
|
30
|
+
<p class="helper-text"></p>
|
|
31
|
+
<button class="btn btn-primary"><slot name="btn"></slot> Upload document</button>
|
|
32
|
+
<div class="drop-area"></div>
|
|
33
|
+
<hr/>
|
|
34
|
+
<slot></slot>
|
|
35
|
+
<div class="files"></div>
|
|
36
|
+
</div>
|
|
37
|
+
`;
|
|
38
|
+
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
connectedCallback() {
|
|
42
|
+
|
|
43
|
+
this.innerHTML += '<i class="fa-regular fa-arrow-up-from-bracket me-2" aria-hidden="true" slot="btn"></i>';
|
|
44
|
+
|
|
45
|
+
const wrapper = this.shadowRoot.querySelector('.file-upload');
|
|
46
|
+
const input = this.querySelector('input');
|
|
47
|
+
const helperText = this.shadowRoot.querySelector('.helper-text');
|
|
48
|
+
|
|
49
|
+
helperText.innerHTML = `${this.hasAttribute('data-maxsize') ? `Max file size is ${this.getAttribute('data-maxsize')}kb. ` : '' }${ input.hasAttribute('accept') ? `Supported file types are ${input.getAttribute('accept')}` : '' }`;
|
|
50
|
+
|
|
51
|
+
fileupload(this,wrapper);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default iamFileupload;
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
**Add the below to your initialise script**
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
import('../node_modules/@iamproperty/components/assets/js/components/filterlist/filterlist.component.min').then(module => { // Might need to update the path
|
|
5
|
+
|
|
6
|
+
if (!window.customElements.get(`iam-filterlist`))
|
|
7
|
+
window.customElements.define(`iam-filterlist`, 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
|
+
|
|
1
16
|
```
|
|
2
17
|
<iam-filterlist>
|
|
3
18
|
<ul>
|
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
**Add the below to your initialise script**
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
import('../node_modules/@iamproperty/components/assets/js/components/filterlist/filterlist.component.min').then(module => { // Might need to update the path
|
|
5
|
+
|
|
6
|
+
if (!window.customElements.get(`iam-filterlist`))
|
|
7
|
+
window.customElements.define(`iam-filterlist`, 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.**
|
|
2
15
|
|
|
3
16
|
```
|
|
4
17
|
<iam-header class="bg-secondary" image="/shutterstock_1229155495.webp">
|
|
@@ -11,14 +24,14 @@
|
|
|
11
24
|
</iam-header>
|
|
12
25
|
```
|
|
13
26
|
|
|
14
|
-
|
|
27
|
+
**Properties**
|
|
15
28
|
|
|
16
29
|
| Option | Type | Default Value | Description |
|
|
17
30
|
| ------ | ---- | ------------- | ----------- |
|
|
18
31
|
| image | String | - | Optional image url to display in the background |
|
|
19
32
|
|
|
20
33
|
|
|
21
|
-
|
|
34
|
+
**Slots**
|
|
22
35
|
|
|
23
36
|
| Option | Default Value | Description |
|
|
24
37
|
| ------ | ------------- | ----------- |
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
**Add the below to your initialise script**
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
import('../node_modules/@iamproperty/components/assets/js/components/notification/notification.component.min').then(module => { // Might need to update the path
|
|
5
|
+
|
|
6
|
+
if (!window.customElements.get(`iam-notification`))
|
|
7
|
+
window.customElements.define(`iam-notification`, 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
|
+
|
|
1
16
|
```
|
|
2
17
|
<!-- Inline -->
|
|
3
18
|
<iam-notification data-status="danger" data-dismiss="">
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
**Add the below to your initialise script**
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
import('../node_modules/@iamproperty/components/assets/js/components/pagination/pagination.component.min').then(module => { // Might need to update the path
|
|
5
|
+
|
|
6
|
+
if (!window.customElements.get(`iam-pagination`))
|
|
7
|
+
window.customElements.define(`iam-pagination`, 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
|
+
|
|
1
16
|
```
|
|
2
17
|
<iam-pagination data-total="12"></iam-pagination>
|
|
3
18
|
```
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
**Add the below to your initialise script**
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
import('../node_modules/@iamproperty/components/assets/js/components/table/table.component.min').then(module => { // Might need to update the path
|
|
5
|
+
|
|
6
|
+
if (!window.customElements.get(`iam-table`))
|
|
7
|
+
window.customElements.define(`iam-table`, 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
|
+
|
|
1
16
|
```
|
|
2
17
|
<iam-table class="container">
|
|
3
18
|
<table>
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
**Add the below to your initialise script**
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
import('../node_modules/@iamproperty/components/assets/js/components/tabs/tabs.component.min').then(module => { // Might need to update the path
|
|
5
|
+
|
|
6
|
+
if (!window.customElements.get(`iam-tabs`))
|
|
7
|
+
window.customElements.define(`iam-tabs`, 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
|
+
|
|
1
16
|
```
|
|
2
17
|
<iam-tabs class="container">
|
|
3
18
|
<details>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Function `createDataLayer()`
|
|
2
|
+
|
|
3
|
+
The `createDataLayer()` function sets up a dataLayer for tracking events and interactions on a web page. It initializes the `window.dataLayer` array if it doesn't exist, and then pushes a "Pageview" event with the current document title. It also attaches a click event listener to the document, which tracks additional events related to clicks on elements like `summary`, `a` (anchor), and `button` elements.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
The `createDataLayer()` function should be called in the JavaScript code of the web page, typically during its initialization phase. This allows the dataLayer to be available for tracking various events and interactions.
|
|
8
|
+
|
|
9
|
+
## Function Signature
|
|
10
|
+
|
|
11
|
+
`function createDataLayer(): void`
|
|
12
|
+
|
|
13
|
+
## Events Tracked
|
|
14
|
+
|
|
15
|
+
1. **"Pageview" Event**
|
|
16
|
+
|
|
17
|
+
- Description: This event is automatically pushed to the `window.dataLayer` array during the function's execution, representing the initial pageview with the current document title.
|
|
18
|
+
- Event Data:
|
|
19
|
+
- `event`: "Pageview"
|
|
20
|
+
- `pageTitle`: The title of the current document.
|
|
21
|
+
2. **"closeDetails" Event**
|
|
22
|
+
|
|
23
|
+
- Description: This event is triggered when a click occurs on an element with the attribute `[open] summary`, indicating that a summary element with the `[open]` attribute is being closed.
|
|
24
|
+
- Event Data:
|
|
25
|
+
- `event`: "closeDetails"
|
|
26
|
+
- `detailsTitle`: The text content of the `summary` element associated with the clicked element. If the `summary` element doesn't have any text content, an empty string is used.
|
|
27
|
+
3. **"openDetails" Event**
|
|
28
|
+
|
|
29
|
+
- Description: This event is triggered when a click occurs on a `summary` element (not associated with `[open]` attribute), indicating that a summary element is being opened.
|
|
30
|
+
- Event Data:
|
|
31
|
+
- `event`: "openDetails"
|
|
32
|
+
- `detailsTitle`: The text content of the clicked `summary` element. If the `summary` element doesn't have any text content, an empty string is used.
|
|
33
|
+
4. **"linkClicked" Event**
|
|
34
|
+
|
|
35
|
+
- Description: This event is triggered when a click occurs on an `a` (anchor) element.
|
|
36
|
+
- Event Data:
|
|
37
|
+
- `event`: "linkClicked"
|
|
38
|
+
- `linkText`: The text content of the clicked `a` element. If the `a` element has a `title` attribute, its value is used as `linkText`; otherwise, the text content of the `a` element is used. If the `a` element doesn't have any text content, an empty string is used.
|
|
39
|
+
- `class`: The `class` attribute value of the `a` element. If the `a` element doesn't have a `class` attribute, an empty string is used.
|
|
40
|
+
- `href`: The value of the `href` attribute of the `a` element. If the `a` element doesn't have an `href` attribute, an empty string is used.
|
|
41
|
+
5. **"buttonClicked" Event**
|
|
42
|
+
|
|
43
|
+
- Description: This event is triggered when a click occurs on a `button` element.
|
|
44
|
+
- Event Data:
|
|
45
|
+
- `event`: "buttonClicked"
|
|
46
|
+
- `buttonText`: The text content of the clicked `button` element. If the `button` element doesn't have any text content, an empty string is used.
|
|
47
|
+
- `class`: The `class` attribute value of the `button` element. If the `button` element doesn't have a `class` attribute, an empty string is used.
|
|
48
|
+
|
|
49
|
+
## Notes
|
|
50
|
+
|
|
51
|
+
- The function relies on the `window.dataLayer` array to store the events, so it should be executed after the page has loaded and the `window` object is available.
|
|
52
|
+
- This implementation assumes that the JavaScript code is placed at the end of the HTML document, ensuring that the DOM elements are accessible at the time the function is executed.
|
|
53
|
+
|
|
54
|
+
### Example Usage
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
<!DOCTYPE html>
|
|
58
|
+
<html>
|
|
59
|
+
<head>
|
|
60
|
+
<title>My Web Page</title>
|
|
61
|
+
</head>
|
|
62
|
+
<body>
|
|
63
|
+
<!-- Your web page content here -->
|
|
64
|
+
|
|
65
|
+
<script> // Call the createDataLayer function to initialize event tracking
|
|
66
|
+
createDataLayer();
|
|
67
|
+
</script>
|
|
68
|
+
</body>
|
|
69
|
+
</html>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
In this example, the `createDataLayer()` function is called in a script block within the HTML document, allowing it to set up the dataLayer for event tracking on the page.
|
|
@@ -4,54 +4,50 @@ type WindowWithDataLayer = Window & {
|
|
|
4
4
|
|
|
5
5
|
declare const window: WindowWithDataLayer;
|
|
6
6
|
|
|
7
|
-
function createDataLayer
|
|
8
|
-
|
|
7
|
+
function createDataLayer(): void {
|
|
9
8
|
window.dataLayer = window.dataLayer || [];
|
|
10
9
|
window.dataLayer.push({
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
event: "Pageview",
|
|
11
|
+
pageTitle: document.title,
|
|
13
12
|
});
|
|
14
|
-
|
|
15
|
-
// Global events to track
|
|
16
|
-
document.addEventListener('click', (event) => {
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"detailsTitle": event.target.closest('summary').textContent
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
else if (event && event.target instanceof HTMLElement && event.target.closest('summary')){
|
|
26
|
-
|
|
27
|
-
window.dataLayer.push({
|
|
28
|
-
"event": "openDetails",
|
|
29
|
-
// @ts-ignore: Object is possibly 'null'.
|
|
30
|
-
"detailsTitle": event.target.closest('summary').textContent
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (event && event.target instanceof HTMLElement && event.target.closest('a')){
|
|
35
|
-
window.dataLayer.push({
|
|
36
|
-
"event": "linkClicked",
|
|
37
|
-
// @ts-ignore: Object is possibly 'null'.
|
|
38
|
-
"linkText": event.target.closest('a').hasAttribute('title') ? event.target.closest('a').getAttribute('title') : event.target.closest('a').textContent,
|
|
39
|
-
// @ts-ignore: Object is possibly 'null'.
|
|
40
|
-
"class": (event.target.closest('a').hasAttribute('class') ? event.target.closest('a').getAttribute('class') : ''),
|
|
41
|
-
// @ts-ignore: Object is possibly 'null'.
|
|
42
|
-
"href": event.target.closest('a').getAttribute('href')
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
if (event && event.target instanceof HTMLElement && event.target.closest('button')){
|
|
14
|
+
document.addEventListener("click", (event: MouseEvent) => {
|
|
15
|
+
const target = (event.target as HTMLElement).closest<HTMLElement>("[open] summary");
|
|
16
|
+
|
|
17
|
+
if (target) {
|
|
46
18
|
window.dataLayer.push({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"buttonText": event.target.closest('button').textContent,
|
|
50
|
-
// @ts-ignore: Object is possibly 'null'.
|
|
51
|
-
"class": (event.target.closest('button').hasAttribute('class') ? event.target.closest('button').getAttribute('class') : '')
|
|
19
|
+
event: "closeDetails",
|
|
20
|
+
detailsTitle: target.textContent || "",
|
|
52
21
|
});
|
|
53
|
-
}
|
|
22
|
+
} else {
|
|
23
|
+
const summary = (event.target as HTMLElement).closest<HTMLElement>("summary");
|
|
24
|
+
const link = (event.target as HTMLElement).closest<HTMLAnchorElement>("a");
|
|
25
|
+
const button = (event.target as HTMLElement).closest<HTMLButtonElement>("button");
|
|
54
26
|
|
|
27
|
+
if (summary) {
|
|
28
|
+
window.dataLayer.push({
|
|
29
|
+
event: "openDetails",
|
|
30
|
+
detailsTitle: summary.textContent || "",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (link) {
|
|
35
|
+
window.dataLayer.push({
|
|
36
|
+
event: "linkClicked",
|
|
37
|
+
linkText: link.hasAttribute("title") ? link.getAttribute("title") || "" : link.textContent || "",
|
|
38
|
+
class: link.hasAttribute("class") ? link.getAttribute("class") || "" : "",
|
|
39
|
+
href: link.getAttribute("href") || "",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (button) {
|
|
44
|
+
window.dataLayer.push({
|
|
45
|
+
event: "buttonClicked",
|
|
46
|
+
buttonText: button.textContent || "",
|
|
47
|
+
class: button.hasAttribute("class") ? button.getAttribute("class") || "" : "",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
55
51
|
});
|
|
56
52
|
}
|
|
57
53
|
|
|
@@ -151,7 +151,7 @@ const extendDialogs = (body) => {
|
|
|
151
151
|
let windowPos = window.innerHeight - window.scrollY;
|
|
152
152
|
if(popoverBottom > windowPos){
|
|
153
153
|
|
|
154
|
-
let currentStyle = popover.getAttribute('style');
|
|
154
|
+
let currentStyle = popover.hasAttribute('style') ? popover.getAttribute('style')+' ' : '';
|
|
155
155
|
|
|
156
156
|
popover.setAttribute('style',currentStyle+`transform: translate(0, calc(-100% - 4rem))`);
|
|
157
157
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
function fileupload(fileupload: Element, wrapper: Element) {
|
|
3
|
+
|
|
4
|
+
const filesWrapper = wrapper.querySelector('.files');
|
|
5
|
+
const dropArea = wrapper.querySelector('.drop-area');
|
|
6
|
+
const input = fileupload.querySelector('input');
|
|
7
|
+
const maxSize = fileupload.hasAttribute('data-maxsize') ? fileupload.getAttribute('data-maxsize') : 0;
|
|
8
|
+
|
|
9
|
+
// We clone the input field to work as a buffer input field, this allows us to add new files without losing the old ones
|
|
10
|
+
const cloneInput = input.cloneNode();
|
|
11
|
+
dropArea.append(cloneInput);
|
|
12
|
+
|
|
13
|
+
wrapper.addEventListener('click', (event) => {
|
|
14
|
+
|
|
15
|
+
if (event && event.target instanceof HTMLElement && event.target.closest('.btn-primary')){
|
|
16
|
+
|
|
17
|
+
const button = event.target.closest('.btn-primary');
|
|
18
|
+
|
|
19
|
+
// If the input allows multiples then use the buffer clone input
|
|
20
|
+
const inputTrigger = input.hasAttribute('multiple') ? cloneInput : input;
|
|
21
|
+
|
|
22
|
+
inputTrigger.click();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
wrapper.addEventListener('click', (event) => {
|
|
27
|
+
|
|
28
|
+
if (event && event.target instanceof HTMLElement && event.target.closest('.files button')){
|
|
29
|
+
|
|
30
|
+
const dt = new DataTransfer();
|
|
31
|
+
const { files } = input;
|
|
32
|
+
const button = event.target.closest('.files button');
|
|
33
|
+
|
|
34
|
+
for (let i = 0; i < files.length; i++) {
|
|
35
|
+
const file = files[i]
|
|
36
|
+
|
|
37
|
+
if(file.name != button.getAttribute('data-file'))
|
|
38
|
+
dt.items.add(file) // here you exclude the file. thus removing it.
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
input.files = dt.files // Assign the updates list
|
|
42
|
+
|
|
43
|
+
const changeEvent = new Event('change');
|
|
44
|
+
input.dispatchEvent(changeEvent);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Buffer input change event
|
|
49
|
+
cloneInput.addEventListener('change', (event) => {
|
|
50
|
+
|
|
51
|
+
if(input.hasAttribute('multiple')){
|
|
52
|
+
const filesArray = [...input.files, ...cloneInput.files];
|
|
53
|
+
|
|
54
|
+
let fileNames = [];
|
|
55
|
+
|
|
56
|
+
const dt = new DataTransfer();
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i < filesArray.length; i++) {
|
|
59
|
+
const file = filesArray[i]
|
|
60
|
+
|
|
61
|
+
const size = file.size/1000;
|
|
62
|
+
|
|
63
|
+
if(!fileNames.includes(file.name) && (maxSize == 0 || size < maxSize))
|
|
64
|
+
dt.items.add(file) // here you exclude the file. thus removing it.
|
|
65
|
+
|
|
66
|
+
fileNames.push(file.name);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
input.files = dt.files;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
|
|
73
|
+
input.files = cloneInput.files;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const changeEvent = new Event('change');
|
|
77
|
+
input.dispatchEvent(changeEvent);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
cloneInput.addEventListener('dragenter', (event) => {
|
|
82
|
+
|
|
83
|
+
cloneInput.classList.add('focus');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
cloneInput.addEventListener('dragleave', (event) => {
|
|
87
|
+
|
|
88
|
+
cloneInput.classList.remove('focus');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
cloneInput.addEventListener('drop', (event) => {
|
|
92
|
+
|
|
93
|
+
cloneInput.classList.remove('focus');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
input.addEventListener('change', (event) => {
|
|
97
|
+
|
|
98
|
+
// Reset
|
|
99
|
+
filesWrapper.innerHTML = '';
|
|
100
|
+
|
|
101
|
+
for (const file of input.files)
|
|
102
|
+
filesWrapper.innerHTML += `<span class="file">${file.name} <button data-file="${file.name}">Remove</button></span>`;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export default fileupload;
|
|
@@ -40,6 +40,20 @@ const extendInputs = (body) => {
|
|
|
40
40
|
changeType(input,newType);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
+
|
|
44
|
+
if (event && event.target instanceof HTMLElement && event.target.closest('dialog [type="radio"]')){
|
|
45
|
+
|
|
46
|
+
const dialog = event.target.closest('dialog');
|
|
47
|
+
const radio = event.target.closest('dialog [type="radio"]');
|
|
48
|
+
|
|
49
|
+
Array.from(dialog.querySelectorAll('[type="radio"][autofocus]')).forEach((input,index) => {
|
|
50
|
+
input.removeAttribute('autofocus');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
Array.from(dialog.querySelectorAll('[type="radio"]:checked')).forEach((input,index) => {
|
|
54
|
+
input.setAttribute('autofocus',true);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
43
57
|
});
|
|
44
58
|
|
|
45
59
|
body.addEventListener('click', (event) => {
|
|
@@ -160,6 +160,16 @@ export const addFilterEventListeners = (table, form, pagination, wrapper, savedT
|
|
|
160
160
|
createPaginationButttons(wrapper,pagination);
|
|
161
161
|
populateDataQueries(table,form);
|
|
162
162
|
}
|
|
163
|
+
|
|
164
|
+
// Pass post data back to the page
|
|
165
|
+
if(form.hasAttribute('data-ajax-post')){
|
|
166
|
+
|
|
167
|
+
let formData = new FormData(form);
|
|
168
|
+
let queryString = new URLSearchParams(formData).toString();
|
|
169
|
+
const http = new XMLHttpRequest()
|
|
170
|
+
http.open('GET', `${window.location.href}?ajax=true&${queryString}`);
|
|
171
|
+
http.send();
|
|
172
|
+
}
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
form.addEventListener('keyup', (event) => {
|
|
@@ -417,7 +427,7 @@ export const filterTable = (table, form, wrapper) => {
|
|
|
417
427
|
|
|
418
428
|
table.classList.remove('table--filtered');
|
|
419
429
|
|
|
420
|
-
let filters =
|
|
430
|
+
let filters = filterFilters(form);
|
|
421
431
|
let searches = [];
|
|
422
432
|
let matched = 0;
|
|
423
433
|
let page = form.querySelector('[data-pagination]') ? parseInt(form.querySelector('[data-pagination]').value) : 1;
|
|
@@ -432,40 +442,6 @@ export const filterTable = (table, form, wrapper) => {
|
|
|
432
442
|
row.removeAttribute('data-filtered-by');
|
|
433
443
|
});
|
|
434
444
|
|
|
435
|
-
// Filter
|
|
436
|
-
let filterInputs = Array.from(form.querySelectorAll('[data-filter]'));
|
|
437
|
-
|
|
438
|
-
filterInputs.forEach((filterInput, index) => {
|
|
439
|
-
|
|
440
|
-
// Ignore uncked radio inputs
|
|
441
|
-
if(filterInput.type == 'radio' && !filterInput.checked){
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
if(filterInput.type == 'checkbox' && !filterInput.checked){
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
if(filterInput.getAttribute('data-filter') == "multi"){
|
|
451
|
-
|
|
452
|
-
for (const [key, value] of Object.entries(JSON.parse(filterInput.value))) {
|
|
453
|
-
filters[filterInput.getAttribute('data-filter')].push(value);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
else if (filterInput && filterInput.value) {
|
|
457
|
-
|
|
458
|
-
let dataFilter = filterInput.getAttribute('data-filter');
|
|
459
|
-
|
|
460
|
-
if(!filters[dataFilter])
|
|
461
|
-
filters[dataFilter] = new Array();
|
|
462
|
-
|
|
463
|
-
filters[dataFilter].push(filterInput.value);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
|
|
469
445
|
// Add search columns too
|
|
470
446
|
if(form.querySelector('[data-search]')){
|
|
471
447
|
let searchInput = form.querySelector('[data-search]');
|
|
@@ -482,10 +458,10 @@ export const filterTable = (table, form, wrapper) => {
|
|
|
482
458
|
element.innerHTML = '';
|
|
483
459
|
});
|
|
484
460
|
|
|
485
|
-
if(filters.length) {
|
|
461
|
+
if(Object.keys(filters).length) {
|
|
486
462
|
|
|
487
463
|
Array.from(form.querySelectorAll('[data-filter-count]')).forEach((element, index) => {
|
|
488
|
-
element.innerHTML += `(${filters.length})`;
|
|
464
|
+
element.innerHTML += `(${Object.keys(filters).length})`;
|
|
489
465
|
});
|
|
490
466
|
}
|
|
491
467
|
|
|
@@ -804,7 +780,37 @@ export const makeTableFunctional = function(table, form, pagination, wrapper){
|
|
|
804
780
|
}
|
|
805
781
|
}
|
|
806
782
|
|
|
783
|
+
const filterFilters = function(form){
|
|
784
|
+
|
|
785
|
+
let filters = new Object();
|
|
807
786
|
|
|
787
|
+
// Filter
|
|
788
|
+
let filterInputs = Array.from(form.querySelectorAll('[data-filter]'));
|
|
789
|
+
|
|
790
|
+
filterInputs.forEach((filterInput, index) => {
|
|
791
|
+
|
|
792
|
+
// Ignore uncked radio inputs
|
|
793
|
+
if(filterInput.type == 'radio' && !filterInput.checked){
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
if(filterInput.type == 'checkbox' && !filterInput.checked){
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (filterInput && filterInput.value) {
|
|
802
|
+
|
|
803
|
+
let dataFilter = filterInput.getAttribute('data-filter');
|
|
804
|
+
|
|
805
|
+
if(!filters[dataFilter])
|
|
806
|
+
filters[dataFilter] = new Array();
|
|
807
|
+
|
|
808
|
+
filters[dataFilter].push(filterInput.value);
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
return filters;
|
|
813
|
+
}
|
|
808
814
|
|
|
809
815
|
export const loadAjaxTable = async function (table, form, pagination, wrapper){
|
|
810
816
|
|
|
@@ -818,6 +824,20 @@ export const loadAjaxTable = async function (table, form, pagination, wrapper){
|
|
|
818
824
|
|
|
819
825
|
wrapper.classList.add('table--loading');
|
|
820
826
|
|
|
827
|
+
// Display the filter count
|
|
828
|
+
let filters = filterFilters(form);
|
|
829
|
+
|
|
830
|
+
Array.from(form.querySelectorAll('[data-filter-count]')).forEach((element, index) => {
|
|
831
|
+
element.innerHTML = '';
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
if(Object.keys(filters).length) {
|
|
835
|
+
|
|
836
|
+
Array.from(form.querySelectorAll('[data-filter-count]')).forEach((element, index) => {
|
|
837
|
+
element.innerHTML += `(${Object.keys(filters).length})`;
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
|
|
821
841
|
// Setup controller vars if not already set
|
|
822
842
|
if(!window.controller)
|
|
823
843
|
window.controller = [];
|
|
@@ -927,6 +947,16 @@ export const loadAjaxTable = async function (table, form, pagination, wrapper){
|
|
|
927
947
|
makeTableFunctional(table, form, pagination, wrapper);
|
|
928
948
|
createPaginationButttons(wrapper, pagination);
|
|
929
949
|
|
|
950
|
+
Array.from(form.querySelectorAll('[data-ajax-query]')).forEach((queryElement, index) => {
|
|
951
|
+
|
|
952
|
+
let totalNumber = resolvePath(response, queryElement.getAttribute('data-ajax-query'), '');
|
|
953
|
+
|
|
954
|
+
if(queryElement.hasAttribute('data-total'))
|
|
955
|
+
queryElement.setAttribute('data-total', totalNumber);
|
|
956
|
+
else
|
|
957
|
+
queryElement.innerHTML = totalNumber;
|
|
958
|
+
});
|
|
959
|
+
|
|
930
960
|
if(parseInt(totalNumber) == 0){
|
|
931
961
|
tbody.innerHTML = `<tr><td colspan="100%"><span>${emptyMsg}</span></td></tr>`;
|
|
932
962
|
}
|
|
@@ -943,13 +973,6 @@ export const loadAjaxTable = async function (table, form, pagination, wrapper){
|
|
|
943
973
|
else {
|
|
944
974
|
tbody.innerHTML = '<tr><td colspan="100%"><span>Error loading table</span></td></tr>';
|
|
945
975
|
}
|
|
946
|
-
|
|
947
|
-
// Pass post data back to the page
|
|
948
|
-
if(form.hasAttribute('data-ajax-post')){
|
|
949
|
-
const http = new XMLHttpRequest()
|
|
950
|
-
http.open('GET', `${window.location.href}?ajax=true&${queryString}`);
|
|
951
|
-
http.send();
|
|
952
|
-
}
|
|
953
976
|
});
|
|
954
977
|
} catch (error) {
|
|
955
978
|
console.log(error);
|