UNPKG

lu2

Version:

Simple and flexible UI component library based on native HTML and JavaScript

351 lines (301 loc) 10.9 kB
/** * @Form.js * @author zhangxinxu * @version * @created 16-03-01 * @edited 19-12-02 ES5原生语法支持 */ /* global module */ (function (global, factory) { if (typeof exports === 'object' && typeof module !== 'undefined') { global.LightTip = require('../ui/LightTip'); global.Loading = require('../ui/Loading'); global.Validate = require('../ui/Validate'); module.exports = factory(); } else if (typeof define === 'function' && (define.amd || define.cmd)) { define(factory); } else { global.Form = factory(); } // eslint-disable-next-line }((typeof global !== 'undefined') ? global // eslint-disable-next-line : ((typeof window !== 'undefined') ? window : ((typeof self !== 'undefined') ? self : this)), function (require) { var LightTip = (this || self).LightTip; var Loading = (this || self).Loading; var Validate = (this || self).Validate; // require if (typeof require == 'function') { // 轻tips if (!LightTip) { LightTip = require('common/ui/LightTip'); } // 加载 if (!Loading) { Loading = require('common/ui/Loading'); } // 验证 if (!Validate) { Validate = require('common/ui/Validate'); } } else if (!Validate || !LightTip || !Loading) { window.console.error('need Validate.js'); if (!LightTip) { window.console.error('need LightTip.js'); } else if (!Loading) { window.console.warn('need Loading.js'); } else { window.console.error('need Validate.js'); } return {}; } /** * 表单解决方案组件 * @使用示例 * new Form('#form', {}, {}); */ var DISABLED = 'disabled'; // 表单 var Form = function (element, optionCallback, optionValidate) { if (typeof element == 'string') { element = document.querySelector(element); } if (!element) { return this; } // 避免重复初始化 if (element.data && element.data.form) { return element.data.form; } // optionCallback可以是对象也可以直接是成功回调 /* optionCallback = { avoidSend: function () {}, // 验证成功之后,请求发送前的条件约束 success: function () {}, error: function () {}, complete: function () {} }; */ optionCallback = optionCallback || function () {}; if (typeof optionCallback == 'function') { optionCallback = { success: optionCallback }; } optionValidate = optionValidate || {}; // 表单元素 var eleForm = element; // 通过submit按钮找到找到关联的我们肉眼所见的提交按钮 var eleBtnSubmit = eleForm.querySelector('[type="submit"], [type="image"]'); if (!eleBtnSubmit) { eleBtnSubmit = eleForm.querySelector('button:nth-of-last-type()'); } if (!eleBtnSubmit) { return this; } // 下拉框的初始化 if (window.autoInit === false) { // 下拉框 eleForm.querySelectorAll('select').forEach(function (eleSelect) { if (eleSelect.refresh) { eleSelect.refresh(); } }); } // 暴露的元素 this.element = { form: eleForm, submit: eleBtnSubmit }; // 回调方法们 this.callback = optionCallback; // 绑定表单验证 this.validate = new Validate(eleForm, function () { // 验证成功之后 if (!optionCallback.avoidSend || !optionCallback.avoidSend.call(this, eleForm)) { this.ajax(); } }.bind(this), optionValidate); if (!eleForm.data) { eleForm.data = {}; } eleForm.data.form = this; return this; }; /** * 表单提交的处理 * @return {[type]} [description] */ Form.prototype.ajax = function () { // 回调 var optionCallback = this.callback; // 元素 var eleForm = this.element.form; var eleButton = null; var eleSubmit = this.element.submit; // 我们肉眼所见的按钮,进行一些状态控制 eleButton = eleSubmit.id && document.querySelector('label[for=' + eleSubmit.id + ']'); if (!eleButton) { eleButton = eleSubmit; } this.element.button = eleButton; // 请求地址 var strUrl = eleForm.action.split('#')[0] || location.href.split('#')[0]; // 请求类型 var strMethod = eleForm.method || 'POST'; var strEnctype = eleForm.enctype; // IE9不支持cros跨域 if (!history.pushState && new URL(strUrl).host != location.host) { new LightTip().error('当前浏览器不支持跨域数据请求。'); return; } // 提交数据 // 1. 菊花转起来 eleButton.loading = true; // 2. 提交按钮禁用 eleSubmit.setAttribute(DISABLED, DISABLED); // 3. 数据 var objFormData = new FormData(eleForm); // 请求类型不同,数据地址也不一样 var strSearchParams = new URLSearchParams(objFormData).toString(); if (strMethod.toLowerCase() == 'get') { if (strUrl.split('?').length > 1) { strUrl = strUrl + '&' + strSearchParams; } else { strUrl = strUrl + '?' + strSearchParams; } } // 4. 请求走起来 var xhr = new XMLHttpRequest(); xhr.open(strMethod, strUrl); if (strEnctype) { xhr.setRequestHeader('Content-Type', strEnctype); } if (optionCallback.beforeSend) { optionCallback.beforeSend.call(this, xhr, objFormData); } // 请求结束 xhr.onload = function () { var json = {}; try { json = JSON.parse(xhr.responseText); if (json && (json.code == 0 || json.error == 0)) { // 成功回调 if (optionCallback.success) { optionCallback.success.call(this, json); } else { // 如果没有成功回调,组件自己提示成功 new LightTip().success(json.msg || '操作成功。'); // 重置 eleForm.reset(); } } else { new LightTip().error((json && json.msg) || '返回数据格式不符合要求。'); // 失败回调 if (optionCallback.error) { optionCallback.error.call(this, json); } } } catch (event) { new LightTip().error(json.msg || '返回数据解析出错。'); // 回调 if (optionCallback.error) { optionCallback.error.call(this, event); } } funLoadend(json); }.bind(this); // 请求错误 xhr.onerror = function () { new LightTip().error('网络异常,刚才的操作没有成功,您可以稍后重试。'); // 回调 if (optionCallback.error) { optionCallback.error.apply(this, arguments); } funLoadend(); }.bind(this); // 请求结束,无论成功还是失败 // xhr.onloadend IE9不支持,因此这里使用 // 其他方法代替 var funLoadend = function () { // 菊花关闭 eleButton.loading = false; // 表单恢复提交 eleSubmit.removeAttribute(DISABLED); // 回调 if (optionCallback.complete) { optionCallback.complete.apply(this, arguments); } }; if (strEnctype && strEnctype.toLowerCase() === 'application/x-www-form-urlencoded') { xhr.send(strSearchParams); } else { xhr.send(objFormData); } }; /** * 执行表单的提交 * @return {Object} 返回当前实例对象 */ Form.prototype.submit = function () { this.element.form.dispatchEvent(new CustomEvent('submit')); return this; }; // 对is-form属性观察 var funAutoInitAndWatching = function () { // 目标选择器 var strSelector = 'form[is-form]'; var funSyncRefresh = function (nodes) { if (!nodes || !nodes.forEach) { return; } nodes.forEach(function (node) { if (node.matches && node.matches(strSelector)) { node.dispatchEvent(new CustomEvent('connected')); } }); }; setTimeout(function () { funSyncRefresh(document.querySelectorAll(strSelector)); }, 1); // 如果没有开启观察,不监听DOM变化 if (window.watching === false) { return; } // DOM Insert自动初始化 // IE11+使用MutationObserver // IE9-IE10使用Mutation Events if (window.MutationObserver) { var observerSelect = new MutationObserver(function (mutationsList) { mutationsList.forEach(function (mutation) { mutation.addedNodes.forEach(function (eleAdd) { if (eleAdd.matches) { if (eleAdd.matches(strSelector)) { funSyncRefresh([eleAdd]); } else if (eleAdd.querySelector) { funSyncRefresh(eleAdd.querySelectorAll(strSelector)); } } }); }); }); observerSelect.observe(document.body, { childList: true, subtree: true }); } else { document.body.addEventListener('DOMNodeInserted', function (event) { // 插入节点 funSyncRefresh([event.target]); }); } }; // 监听-免初始绑定 if (document.readyState != 'loading') { funAutoInitAndWatching(); } else { window.addEventListener('DOMContentLoaded', funAutoInitAndWatching); } return Form; }));