UNPKG

lu2

Version:

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

265 lines (228 loc) 8.1 kB
/** * @Form.js * @author zhangxinxu * @version * @created 16-03-01 * @edited 19-12-02 ES5原生语法支持 */ /** * 表单解决方案组件 * @使用示例 * <form is="ui-form"> */ import LightTip from '../ui/LightTip.js'; import Validate from '../ui/Validate.js'; import '../ui/Loading.js'; // 表单 class Form extends HTMLFormElement { constructor () { super(); this.element = this.element || {}; this.params = this.params || { // 验证成功之后,请求发送前的条件约束 // avoidSend: function () {} }; // 回调方法们 this.callback = this.callback || {}; Object.defineProperty(this.params, 'validate', { set (value) { if (this.validate) { this.validate.setCustomValidity(value); } } }); return this; } /** * 表单提交的处理 * @return {[type]} [description] */ ajax () { // 回调 // optionCallback可以是对象也可以直接是成功回调 /* optionCallback = { success: function () {}, error: function () {}, complete: function () {} }; */ let optionCallback = this.callback; optionCallback = optionCallback || function () {}; if (typeof optionCallback == 'function') { optionCallback = { success: optionCallback }; } // 表单提交按钮元素的获取 let eleSubmit = [...this.elements].filter(function (control) { return control.type && /^(?:submit|image)$/i.test(control.type); })[0] || this.querySelector('button:nth-last-of-type(1)'); if (!eleSubmit) { eleSubmit = (() => { let ele = document.createElement('button'); ele.type = 'submit'; ele.setAttribute('hidden', ''); this.appendChild(ele); return ele; })(); } this.element.submit = eleSubmit; // 按钮元素 let eleButton = null; // 我们肉眼所见的按钮,进行一些状态控制 eleButton = eleSubmit.id && document.querySelector('label[for=' + eleSubmit.id + ']'); if (!eleButton) { eleButton = eleSubmit; } this.element.button = eleButton; // 请求地址 let strUrl = this.action.split('#')[0] || location.href.split('#')[0]; // 请求类型 let strMethod = this.method || 'POST'; let strEnctype = this.getAttribute('enctype') || this.enctype; // 提交数据 // 1. 菊花转起来 eleButton.loading = true; // 2. 提交按钮禁用 eleSubmit.setAttribute('disabled', 'disabled'); // 3. 数据 let objFormData = new FormData(this); // 支持外部传入额外的请求参数 if (this.params.data) { Object.keys(this.params.data).forEach(key => { objFormData.append(key, this.params.data[key]); }); } // 请求类型不同,数据地址也不一样 let strSearchParams = new URLSearchParams(objFormData).toString(); if (strMethod.toLowerCase() == 'get') { if (strUrl.split('?').length > 1) { strUrl = strUrl + '&' + strSearchParams; } else { strUrl = strUrl + '?' + strSearchParams; } } // 4. 请求走起来 let xhr = new XMLHttpRequest(); xhr.open(strMethod, strUrl); if (optionCallback.beforeSend) { optionCallback.beforeSend.call(this, xhr, objFormData); } // 请求结束 xhr.onload = () => { let json = {}; try { json = JSON.parse(xhr.responseText); } catch (event) { new LightTip('返回数据解析出错。', 'error'); // 回调 if (optionCallback.error) { optionCallback.error.call(this, event); } // 触发出错自定义事件 this.dispatchEvent(new CustomEvent('error', { detail: { data: { code: -1, msg: '解析出错' } } })); return; } if (json && (json.code === 0 || json.error === 0)) { // 成功回调 if (optionCallback.success) { optionCallback.success.call(this, json); } else { // 如果没有成功回调,组件自己提示成功 new LightTip(json.msg || '操作成功。', 'success'); // 表单重置 this.reset(); } // 支持绑定success事件 this.dispatchEvent(new CustomEvent('success', { detail: { data: json } })); } else { new LightTip((json && json.msg) || '返回数据格式不符合要求。', 'error'); // 失败回调 if (optionCallback.error) { optionCallback.error.call(this, json); } // 触发出错自定义事件 this.dispatchEvent(new CustomEvent('error', { detail: { data: json } })); } }; // 请求错误 xhr.onerror = () => { new LightTip('网络异常,刚才的操作没有成功,您可以稍后重试。', 'error'); // 回调 if (optionCallback.error) { optionCallback.error.apply(this, arguments); } // 触发出错自定义事件 this.dispatchEvent(new CustomEvent('error', { detail: { code: -1, msg: '网络异常' } })); }; // 请求结束,无论成功还是失败 xhr.onloadend = () => { // 菊花关闭 eleButton.loading = false; // 表单恢复提交 eleSubmit.removeAttribute('disabled'); // 回调 if (optionCallback.complete) { optionCallback.complete.apply(this, arguments); } // 支持绑定complete事件 this.dispatchEvent(new CustomEvent('complete')); }; if (strEnctype && strEnctype.toLowerCase() === 'application/x-www-form-urlencoded') { xhr.send(strSearchParams); } else if (strEnctype == 'application/json') { xhr.setRequestHeader('Content-Type', strEnctype); const objSend = {}; objFormData.forEach(function(value, key){ objSend[key] = value; }); xhr.send(JSON.stringify(objSend)); } else { xhr.send(objFormData); } } connectedCallback () { // 绑定表单验证 this.validate = new Validate(this, () => { let funAvoidSend = this.params.avoidSend || this.callback.avoidSend; // 验证成功之后 if (!funAvoidSend || !funAvoidSend(this)) { this.ajax(); } }, this.params.validate || {}); // 全局事件 this.dispatchEvent(new CustomEvent('connected', { detail: { type: 'ui-form' } })); this.isConnectedCallback = true; this.dispatchEvent(new CustomEvent('DOMContentLoaded')); } } if (!customElements.get('ui-form')) { customElements.define('ui-form', Form, { extends: 'form' }); }