UNPKG

framework7

Version:

Full featured mobile HTML framework for building iOS & Android apps

311 lines (302 loc) 9.47 kB
import { getWindow, getDocument } from 'ssr-window'; import $ from '../../shared/dom7.js'; import { extend, serializeObject } from '../../shared/utils.js'; // Form Data const FormData = { store(form, data) { const app = this; const window = getWindow(); let formId = form; const $formEl = $(form); if ($formEl.length && $formEl.is('form') && $formEl.attr('id')) { formId = $formEl.attr('id'); } // Store form data in app.formsData app.form.data[`form-${formId}`] = data; // Store form data in local storage also window.localStorage[`f7form-${formId}`] = JSON.stringify(data); }, get(form) { const app = this; const window = getWindow(); let formId = form; const $formEl = $(form); if ($formEl.length && $formEl.is('form') && $formEl.attr('id')) { formId = $formEl.attr('id'); } if (window.localStorage[`f7form-${formId}`]) { return JSON.parse(window.localStorage[`f7form-${formId}`]); } if (app.form.data[`form-${formId}`]) { return app.form.data[`form-${formId}`]; } return undefined; }, remove(form) { const app = this; const window = getWindow(); let formId = form; const $formEl = $(form); if ($formEl.length && $formEl.is('form') && $formEl.attr('id')) { formId = $formEl.attr('id'); } // Delete form data from app.formsData if (app.form.data[`form-${formId}`]) { app.form.data[`form-${formId}`] = ''; delete app.form.data[`form-${formId}`]; } // Delete form data from local storage also if (window.localStorage[`f7form-${formId}`]) { window.localStorage[`f7form-${formId}`] = ''; window.localStorage.removeItem(`f7form-${formId}`); } } }; // Form Storage const FormStorage = { init(formEl) { const app = this; const $formEl = $(formEl); const formId = $formEl.attr('id'); if (!formId) return; const initialData = app.form.getFormData(formId); if (initialData) { app.form.fillFromData($formEl, initialData); } function store() { const data = app.form.convertToData($formEl); if (!data) return; app.form.storeFormData(formId, data); $formEl.trigger('form:storedata', data); app.emit('formStoreData', $formEl[0], data); } $formEl.on('change submit', store); }, destroy(formEl) { const $formEl = $(formEl); $formEl.off('change submit'); } }; // Form To/From Data function formToData(formEl) { const app = this; const $formEl = $(formEl).eq(0); if ($formEl.length === 0) return undefined; // Form data const data = {}; // Skip input types const skipTypes = ['submit', 'image', 'button', 'file']; const skipNames = []; $formEl.find('input, select, textarea').each(inputEl => { const $inputEl = $(inputEl); if ($inputEl.hasClass('ignore-store-data') || $inputEl.hasClass('no-store-data')) { return; } const name = $inputEl.attr('name'); const type = $inputEl.attr('type'); const tag = inputEl.nodeName.toLowerCase(); if (skipTypes.indexOf(type) >= 0) return; if (skipNames.indexOf(name) >= 0 || !name) return; if (tag === 'select' && $inputEl.prop('multiple')) { skipNames.push(name); data[name] = []; $formEl.find(`select[name="${name}"] option`).each(el => { if (el.selected) data[name].push(el.value); }); } else { switch (type) { case 'checkbox': skipNames.push(name); data[name] = []; $formEl.find(`input[name="${name}"]`).each(el => { if (el.checked) data[name].push(el.value); }); break; case 'radio': skipNames.push(name); $formEl.find(`input[name="${name}"]`).each(el => { if (el.checked) data[name] = el.value; }); break; default: data[name] = $inputEl.val(); break; } } }); $formEl.trigger('form:todata', data); app.emit('formToData', $formEl[0], data); return data; } function formFromData(formEl, formData) { const app = this; const $formEl = $(formEl).eq(0); if (!$formEl.length) return; let data = formData; const formId = $formEl.attr('id'); if (!data && formId) { data = app.form.getFormData(formId); } if (!data) return; // Skip input types const skipTypes = ['submit', 'image', 'button', 'file']; const skipNames = []; $formEl.find('input, select, textarea').each(inputEl => { const $inputEl = $(inputEl); if ($inputEl.hasClass('ignore-store-data') || $inputEl.hasClass('no-store-data')) { return; } const name = $inputEl.attr('name'); const type = $inputEl.attr('type'); const tag = inputEl.nodeName.toLowerCase(); if (typeof data[name] === 'undefined' || data[name] === null) return; if (skipTypes.indexOf(type) >= 0) return; if (skipNames.indexOf(name) >= 0 || !name) return; if (tag === 'select' && $inputEl.prop('multiple')) { skipNames.push(name); $formEl.find(`select[name="${name}"] option`).each(el => { const selectEl = el; if (data[name].indexOf(el.value) >= 0) selectEl.selected = true;else selectEl.selected = false; }); } else { switch (type) { case 'checkbox': skipNames.push(name); $formEl.find(`input[name="${name}"]`).each(el => { const checkboxEl = el; if (data[name].indexOf(el.value) >= 0) checkboxEl.checked = true;else checkboxEl.checked = false; }); break; case 'radio': skipNames.push(name); $formEl.find(`input[name="${name}"]`).each(el => { const radioEl = el; if (data[name] === el.value) radioEl.checked = true;else radioEl.checked = false; }); break; default: $inputEl.val(data[name]); break; } } if (tag === 'select' || tag === 'input' || tag === 'textarea') { $inputEl.trigger('change', 'fromdata'); } }); $formEl.trigger('form:fromdata', data); app.emit('formFromData', $formEl[0], data); } function initAjaxForm() { const app = this; const window = getWindow(); const document = getDocument(); function onSubmitChange(e, fromData) { const $formEl = $(this); if (e.type === 'change' && !$formEl.hasClass('form-ajax-submit-onchange')) return; if (e.type === 'submit') e.preventDefault(); if (e.type === 'change' && fromData === 'fromdata') return; const method = ($formEl.attr('method') || 'GET').toUpperCase(); const contentType = $formEl.attr('enctype') || $formEl.prop('enctype'); let url = $formEl.attr('action'); if (!url) return; let data; if (method === 'POST') { if (contentType === 'application/x-www-form-urlencoded' || contentType === 'application/json') { data = app.form.convertToData($formEl[0]); if (contentType === 'application/json') { data = JSON.stringify(data); } } else { data = new window.FormData($formEl[0]); } } else { data = serializeObject(app.form.convertToData($formEl[0])); if (url.includes('?')) { url += `&${data}`; } else { url += `?${data}`; } } $formEl.trigger('formajax:beforesend', { data }); app.emit('formAjaxBeforeSend', $formEl[0], data); fetch(url, { method, headers: { 'Content-Type': contentType || 'application/x-www-form-urlencoded' }, ...(method === 'POST' || method === 'PUT' ? { body: data } : {}) }).then(response => { $formEl.trigger('formajax:complete', { data, response }); app.emit('formAjaxComplete', $formEl[0], data, response); $formEl.trigger('formajax:success', { data, response }); app.emit('formAjaxSuccess', $formEl[0], data, response); }).catch(error => { $formEl.trigger('formajax:error', { data, error }); app.emit('formAjaxError', $formEl[0], data, error); }); } $(document).on('submit change', 'form.form-ajax-submit, form.form-ajax-submit-onchange', onSubmitChange); } export default { name: 'form', create() { const app = this; extend(app, { form: { data: {}, storeFormData: FormData.store.bind(app), getFormData: FormData.get.bind(app), removeFormData: FormData.remove.bind(app), convertToData: formToData.bind(app), fillFromData: formFromData.bind(app), storage: { init: FormStorage.init.bind(app), destroy: FormStorage.destroy.bind(app) } } }); }, on: { init() { const app = this; initAjaxForm.call(app); }, tabBeforeRemove(tabEl) { const app = this; $(tabEl).find('.form-store-data').each(formEl => { app.form.storage.destroy(formEl); }); }, tabMounted(tabEl) { const app = this; $(tabEl).find('.form-store-data').each(formEl => { app.form.storage.init(formEl); }); }, pageBeforeRemove(page) { const app = this; page.$el.find('.form-store-data').each(formEl => { app.form.storage.destroy(formEl); }); }, pageInit(page) { const app = this; page.$el.find('.form-store-data').each(formEl => { app.form.storage.init(formEl); }); } } };