This repository has been archived by the owner on Aug 2, 2021. It is now read-only.
/
form.js
127 lines (102 loc) · 2.85 KB
/
form.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
'use strict';
import { HTMLCustomElement, ChildrenReady, define } from 'mara';
import { FormSection } from './api';
import delegate from 'mara/events/delegate';
let markAsChanged = function() {
this.classList.add('mara-changed');
};
export class MaraForm extends HTMLCustomElement.with(FormSection, ChildrenReady) {
createdCallback() {
super.createdCallback();
delegate(this, 'input', 'input, select, textarea', markAsChanged);
}
connectedCallback() {
super.connectedCallback();
let p = this.parentNode;
while(p) {
if(p.hasPageState) {
p.addPageState(this);
break;
}
p = p.parentNode;
}
}
childrenReadyCallback() {
super.childrenReadyCallback();
// Create the wrapping form
this.wrapper = document.createElement('form');
this.wrapper.addEventListener('submit', e => {
e.preventDefault();
e.stopImmediatePropagation();
this.submit();
});
this.wrapper.submit = this.submit.bind(this);
while(this.firstChild) {
this.wrapper.appendChild(this.firstChild);
}
this.appendChild(this.wrapper);
// Create the hidden form that will actually be submitted
this.form = document.createElement('form');
this.form.style.display = 'none';
this.form.method = this.method || 'POST';
this.form.action = this.action || document.location.toString();
this.form.enctype = this.enctype || 'application/x-www-form-urlencoded';
var i = document.createElement('input');
i.setAttribute('type', 'hidden');
i.setAttribute('name', 'data');
this.form.appendChild(i);
this.appendChild(this.form);
}
get sectionInputRoot() {
return this.wrapper;
}
get method() {
return this.getAttribute('method') || 'POST';
}
get action() {
return this.getAttribute('action') || document.location.toString();
}
get enctype() {
return this.getAttribute('enctype');
}
get debug() {
return this.hasAttribute('debug');
}
get pageState() {
return this.toData();
}
set pageState(state) {
this.fromData(state);
}
// Custom submit function
submit() {
const data = this.toData();
let files = [];
getFilesFromData(data, files);
if(this.debug) {
console.log('data=', data, 'files=', files); // eslint-disable-line no-console
} else {
// Look through the form for files
this.form.elements[0].value = JSON.stringify(data);
this.form.files = files;
var event = new CustomEvent('submit', { bubbles: true, cancelable: true });
if(this.form.dispatchEvent(event)) {
this.form.submit();
}
}
}
}
define('mara-form', MaraForm);
function getFilesFromData(data, result) {
if(data && data.data instanceof window.File) {
result.push({
id: data.id,
file: data.data
});
delete data.data;
} else if(Array.isArray(data)) {
data.forEach(sub => getFilesFromData(sub, result));
} else if(data && typeof data === 'object') {
Object.keys(data).forEach(key => getFilesFromData(data[key], result));
}
}