|
18 | 18 | // and returning false doesn't seem to reliably work.
|
19 | 19 | event.preventDefault();
|
20 | 20 | event.stopPropagation();
|
21 |
| - |
| 21 | + |
22 | 22 | // respect any field validation attributes
|
23 | 23 | if (this.checkValidity()) {
|
24 | 24 | this.fire('submitting');
|
|
35 | 35 | }
|
36 | 36 | }
|
37 | 37 | }.bind(this));
|
38 |
| - |
| 38 | + |
39 | 39 | // Intercept native form submit function.
|
40 | 40 | // In order to force the browser to highlight the invalid fields,
|
41 | 41 | // we need to create a hidden submit button and click it if the form is invalid.
|
|
52 | 52 | }
|
53 | 53 | };
|
54 | 54 | },
|
55 |
| - |
| 55 | + |
56 | 56 | listenForAjaxComplete = function() {
|
57 | 57 | var sender = this.shadowRoot.getElementsByTagName('core-ajax')[0];
|
58 |
| - |
| 58 | + |
59 | 59 | sender.addEventListener('core-complete', function(event) {
|
60 | 60 | this.fire('submitted', event.detail.xhr);
|
61 | 61 | }.bind(this));
|
62 | 62 | },
|
63 |
| - |
| 63 | + |
64 | 64 | parseCustomElements = function(form, parseFileInputs) {
|
65 | 65 | var data = {};
|
66 |
| - |
| 66 | + |
67 | 67 | Array.prototype.slice.call(form.querySelectorAll('*[name]')).forEach(function(el) {
|
68 | 68 | if (parseFileInputs && el.tagName.toLowerCase() === 'file-input') {
|
69 | 69 | var fileInputName = el.getAttribute('name') || 'files';
|
70 |
| - |
| 70 | + |
71 | 71 | if (el.files.length > 1) {
|
72 | 72 | fileInputName += '[]';
|
73 | 73 | }
|
74 |
| - |
| 74 | + |
75 | 75 | el.files.forEach(function(file) {
|
76 | 76 | data[fileInputName] = file;
|
77 | 77 | });
|
78 | 78 | }
|
79 | 79 | else if (el.tagName.indexOf('-') >= 0 && el.value != null) {
|
80 |
| - data[el.getAttribute('name')] = el.value; |
| 80 | + data[el.getAttribute('name')] = el.value; |
81 | 81 | }
|
82 | 82 | });
|
83 |
| - |
| 83 | + |
84 | 84 | return data;
|
85 | 85 | },
|
86 |
| - |
| 86 | + |
87 | 87 | // @TODO: should these FormData parse methods be exposed as events
|
88 | 88 | // if, say, someone wanted to filter or transform the data in a form
|
89 | 89 | // (i.e., radio from yes/no to true/false, or textarea from markdown to
|
90 | 90 | // html)?
|
91 | 91 | parseFormData = function(form) {
|
92 |
| - var formData = new FormData(window.unwrap(form)), |
| 92 | + var formData = new FormData(form), |
93 | 93 | customElementData = parseCustomElements(form, true);
|
94 |
| - |
| 94 | + |
95 | 95 | if (customElementData) {
|
96 | 96 | Object.keys(customElementData).forEach(function(fieldName) {
|
97 |
| - formData.append(fieldName, customElementData[fieldName]); |
| 97 | + formData.append(fieldName, customElementData[fieldName]); |
98 | 98 | });
|
99 | 99 | }
|
100 |
| - |
| 100 | + |
101 | 101 | return formData;
|
102 |
| - |
| 102 | + |
103 | 103 | },
|
104 |
| - |
| 104 | + |
105 | 105 | /**
|
106 | 106 | * Parse an `HTMLRadioElement`'s value, returning the value iff
|
107 | 107 | * the element has a present `checked` attribute.
|
|
115 | 115 | value = element.value;
|
116 | 116 | }
|
117 | 117 | return value;
|
118 |
| - |
| 118 | + |
119 | 119 | },
|
120 |
| - |
| 120 | + |
121 | 121 | /**
|
122 | 122 | * Parse an `HTMLOptionElement`'s value, returning the value iff
|
123 | 123 | * the element has a present `selected` attribute.
|
|
131 | 131 | }
|
132 | 132 | return elementValue;
|
133 | 133 | },
|
134 |
| - |
| 134 | + |
135 | 135 | /**
|
136 | 136 | * Parse an `HTMLOptGroupElement` return the `HTMLOptionElement` that
|
137 | 137 | * has a `checked` attribute.
|
|
148 | 148 | });
|
149 | 149 | return elementValue;
|
150 | 150 | },
|
151 |
| - |
| 151 | + |
152 | 152 | /**
|
153 | 153 | * Parse an `HTMLSelectElement`'s value.
|
154 | 154 | *
|
|
157 | 157 | */
|
158 | 158 | parseSelectElementValues = function(element) {
|
159 | 159 | var elementValues = [];
|
160 |
| - |
| 160 | + |
161 | 161 | Array.prototype.forEach.call(element.options, function(optionElement){
|
162 | 162 | var tempElementValue = parseSelectOptionElementValue(optionElement);
|
163 | 163 | tempElementValue && elementValues.push(tempElementValue);
|
164 | 164 | });
|
165 |
| - |
| 165 | + |
166 | 166 | return elementValues;
|
167 | 167 | },
|
168 |
| - |
| 168 | + |
169 | 169 | /**
|
170 | 170 | * Parse an `HTMLInputElement`'s value.
|
171 | 171 | * @param HTMLInputElement element
|
|
174 | 174 | parseInputElementValue = function(element){
|
175 | 175 | var elementValue,
|
176 | 176 | elementType = element.type;
|
177 |
| - |
| 177 | + |
178 | 178 | if (element.disabled === true ||
|
179 | 179 | ['submit', 'reset', 'button', 'image'].indexOf(elementType) !== -1) {
|
180 | 180 | // do nothing for these button types
|
|
184 | 184 | } else {
|
185 | 185 | elementValue = element.value;
|
186 | 186 | }
|
187 |
| - |
| 187 | + |
188 | 188 | return elementValue;
|
189 | 189 | },
|
190 |
| - |
| 190 | + |
191 | 191 | /**
|
192 | 192 | * Return the value of some `HTMLElement`s value attribute if possible.
|
193 | 193 | * @param HTMLElement element
|
|
196 | 196 | parseElementValue = function(element){
|
197 | 197 | var elementValue,
|
198 | 198 | elementTag = element.tagName.toLowerCase();
|
199 |
| - |
| 199 | + |
200 | 200 | if (elementTag === 'input') {
|
201 | 201 | elementValue = parseInputElementValue(element);
|
202 | 202 | }
|
|
207 | 207 | else if (elementTag === 'select') {
|
208 | 208 | elementValue = parseSelectElementValues(element);
|
209 | 209 | }
|
210 |
| - |
| 210 | + |
211 | 211 | return elementValue;
|
212 |
| - |
| 212 | + |
213 | 213 | },
|
214 |
| - |
| 214 | + |
215 | 215 | /**
|
216 | 216 | * Parse an `HTMLFormElement` into key value pairs
|
217 | 217 | * @param HTMLFormElement form
|
|
221 | 221 | var formObj = {},
|
222 | 222 | formElements = form.getElementsByTagName('input'),
|
223 | 223 | customElementsData = parseCustomElements(form);
|
224 |
| - |
| 224 | + |
225 | 225 | formElements = Array.prototype.slice.call(formElements);
|
226 | 226 | formElements = formElements.concat(Array.prototype.slice.call(form.getElementsByTagName('select')));
|
227 | 227 | formElements = formElements.concat(Array.prototype.slice.call(form.getElementsByTagName('textarea')));
|
228 |
| - |
| 228 | + |
229 | 229 | formElements.forEach(function(formElement){
|
230 | 230 | var key = formElement.name,
|
231 | 231 | val = parseElementValue(formElement);
|
232 |
| - |
| 232 | + |
233 | 233 | if (key && val) {
|
234 | 234 | formObj[key] = val;
|
235 | 235 | }
|
236 | 236 | });
|
237 |
| - |
238 |
| - Object.keys(customElementsData).forEach(function(fieldName) { |
239 |
| - formObj[fieldName] = customElementsData[fieldName]; |
| 237 | + |
| 238 | + Object.keys(customElementsData).forEach(function(fieldName) { |
| 239 | + formObj[fieldName] = customElementsData[fieldName]; |
240 | 240 | });
|
241 |
| - |
| 241 | + |
242 | 242 | return formObj;
|
243 | 243 | },
|
244 |
| - |
| 244 | + |
245 | 245 | /**
|
246 | 246 | * Send a url-encoded `HTMLFormElement` in the URL query string.
|
247 | 247 | * @param HTMLFormElement form
|
248 | 248 | */
|
249 | 249 | sendUrlencodedForm = function(form){
|
250 | 250 | var sender = this.shadowRoot.getElementsByTagName('core-ajax')[0],
|
251 |
| - // We must URL encode the data and place it in the body or |
252 |
| - // query paramter section of the URI (depending on the method). |
253 |
| - // core-ajax attempts to do this for us, but this requires we pass |
254 |
| - // an Object to core-ajax with the params and we cannot properly |
255 |
| - // express multiple values for a <select> (which is possible) |
| 251 | + // We must URL encode the data and place it in the body or |
| 252 | + // query paramter section of the URI (depending on the method). |
| 253 | + // core-ajax attempts to do this for us, but this requires we pass |
| 254 | + // an Object to core-ajax with the params and we cannot properly |
| 255 | + // express multiple values for a <select> (which is possible) |
256 | 256 | // via a JavaScript Object.
|
257 | 257 | data = toQueryString(parseForm(form));
|
258 |
| - |
| 258 | + |
259 | 259 | if (this.cookies) {
|
260 | 260 | sender.withCredentials = true;
|
261 | 261 | }
|
262 |
| - |
| 262 | + |
263 | 263 | if (this.acceptableMethod === 'POST') {
|
264 | 264 | sender.body = data;
|
265 | 265 | }
|
266 | 266 | else {
|
267 |
| - sender.url += (sender.url.indexOf('?') > 0 ? '&' : '?') + data; |
| 267 | + sender.url += (sender.url.indexOf('?') > 0 ? '&' : '?') + data; |
268 | 268 | }
|
269 |
| - |
| 269 | + |
270 | 270 | sender.go();
|
271 | 271 | },
|
272 |
| - |
| 272 | + |
273 | 273 | /**
|
274 | 274 | * Send a multipart-encoded `HTMLFormElement` in the request body.
|
275 | 275 | * @param HTMLFormElement form
|
276 | 276 | */
|
277 | 277 | sendMultipartForm = function(form) {
|
278 | 278 | var sender = this.shadowRoot.getElementsByTagName('core-ajax')[0],
|
279 | 279 | data = parseFormData(form);
|
280 |
| - |
| 280 | + |
281 | 281 | // make sure Polymer/core-ajax doesn't touch the Content-Type.
|
282 | 282 | // The browser must set this with the proper multipart boundary ID.
|
283 | 283 | sender.contentType = null;
|
284 |
| - |
| 284 | + |
285 | 285 | if (this.cookies) {
|
286 | 286 | sender.withCredentials = true;
|
287 | 287 | }
|
288 |
| - |
| 288 | + |
289 | 289 | sender.body = data;
|
290 | 290 | sender.go();
|
291 | 291 | },
|
292 |
| - |
| 292 | + |
293 | 293 | toQueryString = function(params) {
|
294 | 294 | var queryParams = [];
|
295 |
| - |
| 295 | + |
296 | 296 | Object.keys(params).forEach(function(key) {
|
297 | 297 | var val = params[key];
|
298 | 298 | key = encodeURIComponent(key);
|
299 |
| - |
| 299 | + |
300 | 300 | if (val && Object.prototype.toString.call(val) === '[object Array]') {
|
301 | 301 | val.forEach(function(valInArray) {
|
302 | 302 | queryParams.push(key + '=' + encodeURIComponent(valInArray));
|
|
306 | 306 | queryParams.push(val == null ? key : (key + '=' + encodeURIComponent(val)));
|
307 | 307 | }
|
308 | 308 | });
|
309 |
| - |
| 309 | + |
310 | 310 | return queryParams.join('&');
|
311 | 311 | },
|
312 |
| - |
| 312 | + |
313 | 313 | watchForInvalidFields = function(form) {
|
314 | 314 | var customEl = this,
|
315 | 315 | fields = form.getElementsByTagName('input'),
|
316 | 316 | invalidFields = [],
|
317 | 317 | timer = null;
|
318 |
| - |
| 318 | + |
319 | 319 | fields = Array.prototype.slice.call(fields);
|
320 | 320 | fields = fields.concat(Array.prototype.slice.call(form.getElementsByTagName('select')));
|
321 | 321 | fields = fields.concat(Array.prototype.slice.call(form.getElementsByTagName('textarea')));
|
322 |
| - |
| 322 | + |
323 | 323 | fields.forEach(function(field) {
|
324 | 324 | field.addEventListener('invalid', function() {
|
325 | 325 | invalidFields.push(this);
|
326 |
| - |
| 326 | + |
327 | 327 | // In case another element is invalid and the event
|
328 | 328 | // hasn't been triggered yet, hold off on firing the
|
329 | 329 | // invalid event on the custom el.
|
|
0 commit comments