4
0
Fork 0
dcat-admin/resources/assets/dcat/js/extensions/Form.js

426 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import '../jquery-form/jquery.form.min';
let formCallbacks = {
before: [], success: [], error: []
};
class Form {
constructor(options) {
let _this = this;
_this.options = $.extend({
// 表单的 jquery 对象或者css选择器
form: null,
// 开启表单验证
validate: false,
// 确认弹窗
confirm: {title: null, content: null},
// 是否使用Toastr展示字段验证错误信息
validationErrorToastr: false,
// 表单错误信息class
errorClass: 'has-error',
// 表单错误信息容器选择器
errorContainerSelector: '.with-errors',
// 表单组css选择器
groupSelector: '.form-group,.form-label-group,.form-field',
// tab表单css选择器
tabSelector: '.tab-pane',
// 错误信息模板
errorTemplate: '<label class="control-label" for="inputError"><i class="feather icon-x-circle"></i> {message}</label><br/>',
// 是否允许跳转
redirect: true,
// 自动移除表单错误信息
autoRemoveError: true,
// 表单提交之前事件监听返回false可以中止表单继续提交
before: function () {},
// 表单提交之后事件监听返回false可以中止后续逻辑
after: function () {},
// 成功事件返回false可以中止后续逻辑
success: function () {},
// 失败事件返回false可以中止后续逻辑
error: function () {},
}, options);
_this.originalValues = {};
_this.$form = $(_this.options.form).first();
_this._errColumns = {};
_this.init();
}
init() {
let _this = this;
let confirm = _this.options.confirm;
if (! confirm.title) {
return _this.submit();
}
Dcat.confirm(confirm.title, confirm.content, function () {
_this.submit();
});
}
submit() {
let _this = this,
$form = _this.$form,
options = _this.options,
$submitButton = $form.find('[type="submit"],.submit');
// 移除所有错误信息
_this.removeErrors();
$form.ajaxSubmit({
data: {_token: Dcat.token},
beforeSubmit: function (fields, form, _opt) {
if (options.before(fields, form, _opt, _this) === false) {
return false;
}
// 触发全局事件
if (fire(formCallbacks.before, fields, form, _opt, _this) === false) {
return false;
}
// 开启表单验证
if (options.validate) {
$form.validator('validate');
if ($form.find('.' + options.errorClass).length > 0) {
return false;
}
}
$submitButton.buttonLoading();
},
success: function (response) {
setTimeout(function () {
$submitButton.buttonLoading(false);
}, 700);
if (options.after(true, response, _this) === false) {
return;
}
if (options.success(response, _this) === false) {
return;
}
if (fire(formCallbacks.success, response, _this) === false) {
return;
}
if (response.redirect === false || ! options.redirect) {
if (response.data && response.data.then) {
delete response.data['then'];
delete response.data['then'];
delete response.data['then'];
}
}
Dcat.handleJsonResponse(response);
},
error: function (response) {
$submitButton.buttonLoading(false);
if (options.after(false, response, _this) === false) {
return;
}
if (options.error(response, _this) === false) {
return;
}
if (fire(formCallbacks.error, response, _this) === false) {
return;
}
try {
var error = JSON.parse(response.responseText),
key;
if (response.status != 422 || ! error || ! Dcat.helpers.isset(error, 'errors')) {
let json = response.responseJSON;
if (json && json.message) {
return Dcat.error(json.message);
}
return Dcat.error(response.status + ' ' + response.statusText);
}
error = error.errors;
for (key in error) {
// 显示错误信息
_this._errColumns[key] = _this.showError($form, key, error[key]);
}
} catch (e) {
return Dcat.error(response.status + ' ' + response.statusText);
}
}
});
}
// 显示错误信息
showError($form, column, errors) {
let _this = this,
$field = _this.queryFieldByName($form, column),
$group = $field.closest(_this.options.groupSelector),
render = function (msg) {
$group.addClass(_this.options.errorClass);
if (typeof msg === 'string') {
msg = [msg];
}
for (let j in msg) {
$group.find(_this.options.errorContainerSelector).first().append(
_this.options.errorTemplate.replace('{message}', msg[j])
);
}
if (_this.options.validationErrorToastr) {
Dcat.error(msg.join('<br/>'));
}
};
queryTabTitleError(_this, $field).removeClass('d-none');
// 保存字段原始数据
_this.originalValues[column] = _this.getFieldValue($field);
if (! $field) {
if (Dcat.helpers.len(errors) && errors.length) {
Dcat.error(errors.join(" \n "));
}
return;
}
render(errors);
if (_this.options.autoRemoveError) {
removeErrorWhenValChanged(_this, $field, column);
}
return $field;
}
// 获取字段值
getFieldValue($field) {
let vals = [],
type = $field.attr('type'),
checker = type === 'checkbox' || type === 'radio',
i;
for (i = 0; i < $field.length; i++) {
if (checker) {
vals.push($($field[i]).prop('checked'));
continue;
}
vals.push($($field[i]).val());
}
return vals;
}
// 判断值是否改变
isValueChanged($field, column) {
return ! Dcat.helpers.equal(this.originalValues[column], this.getFieldValue($field));
}
// 获取字段jq对象
queryFieldByName($form, column) {
if (column.indexOf('.') !== -1) {
column = column.split('.');
let first = column.shift(),
i,
sub = '';
for (i in column) {
sub += '[' + column[i] + ']';
}
column = first + sub;
}
var $c = $form.find('[name="' + column + '"]');
if (!$c.length) $c = $form.find('[name="' + column + '[]"]');
if (!$c.length) {
$c = $form.find('[name="' + column.replace(/start$/, '') + '"]');
}
if (!$c.length) {
$c = $form.find('[name="' + column.replace(/end$/, '') + '"]');
}
if (!$c.length) {
$c = $form.find('[name="' + column.replace(/start\]$/, ']') + '"]');
}
if (!$c.length) {
$c = $form.find('[name="' + column.replace(/end\]$/, ']') + '"]');
}
return $c;
}
// 移除给定字段的错误信息
removeError($field, column) {
let options = this.options,
parent = $field.parents(options.groupSelector),
errorClass = this.errorClass;
parent.removeClass(errorClass);
parent.find(options.errorContainerSelector).html('');
// tab页下没有错误信息了隐藏title的错误图标
let tab;
if (! queryTabByField(this, $field).find('.'+errorClass).length) {
tab = queryTabTitleError(this, $field);
if (! tab.hasClass('d-none')) {
tab.addClass('d-none');
}
}
delete this._errColumns[column];
}
// 删除所有错误信息
removeErrors() {
let _this = this,
column,
tab;
// 移除所有字段的错误信息
_this.$form.find(_this.options.errorContainerSelector).each(function (_, $err) {
$($err).parents(_this.options.groupSelector).removeClass(_this.options.errorClass);
$($err).html('');
});
// 移除tab表单tab标题错误信息
for (column in _this._errColumns) {
tab = queryTabTitleError(_this._errColumns[column]);
if (! tab.hasClass('d-none')) {
tab.addClass('d-none');
}
}
// 重置
_this._errColumns = {};
}
}
// 监听表单提交事件
Form.submitting = function (callback) {
typeof callback == 'function' && (formCallbacks.before.push(callback));
return this
};
// 监听表单提交完毕事件
Form.submitted = function (success, error) {
typeof success == 'function' && (formCallbacks.success.push(success));
typeof error == 'function' && (formCallbacks.error.push(error));
return this
};
// 当字段值变化时移除错误信息
function removeErrorWhenValChanged(form, $field, column) {
let remove = function () {
form.removeError($field, column)
};
$field.one('change', remove);
$field.off('blur', remove).on('blur', function () {
if (form.isValueChanged($field, column)) {
remove();
}
});
// 表单值发生变化就移除错误信息
let interval = function () {
setTimeout(function () {
if (! $field.length) {
return;
}
if (form.isValueChanged($field, column)) {
return remove();
}
interval();
}, 500);
};
interval();
}
function getTabId(form, $field) {
return $field.parents(form.options.tabSelector).attr('id');
}
function queryTabByField(form, $field)
{
let tabId = getTabId(form, $field);
if (! tabId) {
return $('<none></none>');
}
return $(`a[href="#${tabId}"]`);
}
function queryTabTitleError(form, $field) {
return queryTabByField(form, $field).find('.has-tab-error');
}
// 触发钩子事件
function fire(callbacks) {
let i, j,
result,
args = arguments,
argsArr = [];
delete args[0];
args = args || [];
for (j in args) {
argsArr.push(args[j]);
}
for (i in callbacks) {
result = callbacks[i].apply(callbacks[i], argsArr);
if (result === false) {
return result; // 返回 false 会代码阻止继续执行
}
}
}
// 开启form表单模式
$.fn.form = function (options) {
let $this = $(this);
options = $.extend(options, {
form: $this,
});
$this.on('submit', function () {
return false;
});
$this.find('[type="submit"],.submit').click(function (e) {
Dcat.Form(options);
return false;
});
};
export default Form