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, // 表单错误信息class errorClass: 'has-error', // 表单错误信息容器选择器 errorContainerSelector: '.with-errors', // 表单组css选择器 groupSelector: '.form-group,.form-label-group', // tab表单css选择器 tabSelector: '.tab-pane', // 错误信息模板 errorTemplate: '
', // 保存成功后自动跳转 autoRedirect: false, // 不允许自动移除表单错误信息 disableAutoRemoveError: false, // 表单提交之前事件监听,返回false可以中止表单继续提交 before: function () {}, // 表单提交之后事件监听,返回false可以中止后续逻辑 after: function () {}, // 成功事件,返回false可以中止后续逻辑 success: function () {}, // 失败事件,返回false可以中止后续逻辑 error: function () {}, }, options); _this.originalValues = {}; _this.$form = $(_this.options.form).first(); _this._errColumns = {}; _this.submit(); } submit() { let Dcat = window.Dcat, _this = this, $form = _this.$form, options = _this.options, $submitButton = $form.find(':submit'); // 移除所有错误信息 _this.removeErrors(); $form.ajaxSubmit({ 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) { $submitButton.buttonLoading(false); 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.status) { Dcat.error(response.message || 'Save failed!'); return; } Dcat.success(response.message || 'Save succeeded!'); if (response.redirect === false) { return; } if (response.redirect) { return Dcat.reload(response.redirect); } if (options.autoRedirect) { history.back(-1); } }, 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')) { 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), render = function (msg) { $group.find(_this.options.errorContainerSelector).first().append( _this.options.errorTemplate.replace('{message}', msg) ); }; 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; } let $group = $field.closest(_this.options.groupSelector), j; $group.addClass(_this.options.errorClass); if (typeof errors === 'string') { render(errors) } else { for (j in errors) { render(errors[j]) } } if (! _this.options.disableAutoRemoveError) { 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 parent = $field.parents(this.options.groupSelector), errorClass = this.options.errorClass; parent.removeClass(errorClass); parent.find('error').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 _this = form, removeError = function () { _this.removeError($field, column) }; $field.one('change', removeError); $field.off('blur', removeError).on('blur', function () { if (_this.isValueChanged($field, column)) { removeError(); } }); // 表单值发生变化就移除错误信息 function handle() { setTimeout(function () { if (! $field.length) { return; } if (_this.isValueChanged($field, column)) { return removeError(); } handle(); }, 500); } handle(); } function getTabId(form, $field) { return $field.parents(form.options.tabSelector).attr('id'); } function queryTabByField(form, $field) { let id = getTabId(form, $field); if (! id) { return $(''); } return $('#' + id); } function queryTabTitleError(form, $field) { return queryTabByField(form, $field).find('.text-danger'); } // 触发钩子事件 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.find(':submit').click(function (e) { Dcat.Form(options); return false; }); }; export default Form