@pi0/framework7
Version:
Full featured mobile HTML framework for building iOS & Android apps
310 lines (283 loc) • 8.73 kB
JavaScript
import $ from 'dom7';
import Utils from '../../utils/utils';
// Form Data
const FormData = {
store(form, data) {
const app = this;
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
try {
window.localStorage[`f7form-${formId}`] = JSON.stringify(data);
} catch (e) {
throw e;
}
},
get(form) {
const app = this;
let formId = form;
const $formEl = $(form);
if ($formEl.length && $formEl.is('form') && $formEl.attr('id')) {
formId = $formEl.attr('id');
}
try {
if (window.localStorage[`f7form-${formId}`]) {
return JSON.parse(window.localStorage[`f7form-${formId}`]);
}
} catch (e) {
throw e;
}
if (app.form.data[`form-${formId}`]) {
return app.form.data[`form-${formId}`];
}
return undefined;
},
remove(form) {
const app = this;
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
try {
if (window.localStorage[`f7form-${formId}`]) {
window.localStorage[`f7form-${formId}`] = '';
window.localStorage.removeItem(`f7form-${formId}`);
}
} catch (e) {
throw e;
}
},
};
// Form Storage
const FormStorage = {
init(formEl) {
const app = this;
const $formEl = $(formEl);
const formId = $formEl.attr('id');
if (!formId) return;
const initialData = app.form.data.get(formId);
if (initialData) {
app.form.fromData($formEl, initialData);
}
function store() {
const data = app.form.toData($formEl);
if (!data) return;
app.form.data.store(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((inputIndex, inputEl) => {
const $inputEl = $(inputEl);
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((index, 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((index, el) => {
if (el.checked) data[name].push(el.value);
});
break;
case 'radio':
skipNames.push(name);
$formEl.find(`input[name="${name}"]`).each((index, 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.data.get(formId);
}
if (!data) return;
// Skip input types
const skipTypes = ['submit', 'image', 'button', 'file'];
const skipNames = [];
$formEl.find('input, select, textarea').each((inputIndex, inputEl) => {
const $inputEl = $(inputEl);
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((index, 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((index, 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((index, 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;
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.prop('enctype') || $formEl.attr('enctype');
const url = $formEl.attr('action');
if (!url) return;
let data;
if (method === 'POST') data = new FormData($formEl[0]);
else data = Utils.serializeObject(app.form.toData($formEl[0]));
const xhr = app.request({
method,
url,
contentType,
data,
beforeSend() {
$formEl.trigger('formajax:beforesend', data, xhr);
app.emit('formAjaxBeforeSend', $formEl[0], data, xhr);
},
error() {
$formEl.trigger('formajax:error', data, xhr);
app.emit('formAjaxError', $formEl[0], data, xhr);
},
complete() {
$formEl.trigger('formajax:complete', data, xhr);
app.emit('formAjaxComplete', $formEl[0], data, xhr);
},
success() {
$formEl.trigger('formajax:success', data, xhr);
app.emit('formAjaxSuccess', $formEl[0], data, xhr);
},
});
}
$(document).on('submit change', 'form.form-ajax-submit, form.form-ajax-submit-onchange', onSubmitChange);
}
export default {
name: 'form',
create() {
const app = this;
Utils.extend(app, {
form: {
data: {
store: FormData.store.bind(app),
get: FormData.get.bind(app),
remove: FormData.remove.bind(app),
},
toData: formToData.bind(app),
fromData: 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((index, formEl) => {
app.form.storage.destroy(formEl);
});
},
tabMounted(tabEl) {
const app = this;
$(tabEl).find('.form-store-data').each((index, formEl) => {
app.form.storage.init(formEl);
});
},
pageBeforeRemove(page) {
const app = this;
page.$el.find('.form-store-data').each((index, formEl) => {
app.form.storage.destroy(formEl);
});
},
pageInit(page) {
const app = this;
page.$el.find('.form-store-data').each((index, formEl) => {
app.form.storage.init(formEl);
});
},
},
};