//FastVue.Form (function (Form, $) { "use strict"; Form.fields = {}; Form.renders = {}; function initForm(Form) { var _fields = []; //销毁字段 function __destroyField(f) { if (!f.view.el) return; this.view.el = f.view.el; f.destroyed && f.destroyed.call(this); f.view.el.remove(); f.view.el = null; } //初始化字段 function __initFields(ctx, opts) { !opts.preId && (opts.preId = "fv"); let results = [], layout = ctx.layout('input'), data = ctx.data; for (let [pname, field] of Object.entries(opts.fields)) { !field.name && (field.name = pname); if (field.name in data) { field.value = data[field.name]; } else { data[field.name] = field.value; } !field.type && (field.type = 'text'); !field.id && (field.id = opts.preId + pname); field = FastVue.extend(true, {}, layout, field); let constructor = Form.fields[field.type] || Form.Field; field = new constructor(field); field.onchange = field.onchange.bind(ctx); //可能存在多个name相同的field if (field.name in ctx.fields) { ctx.fields[field.name].push(field); } else { ctx.fields[field.name] = [field]; } results.push(field); } return results; } //初始化Form Form.prototype.init = function (opts) { if (!opts) return; //init dom root let domRoot = document.getElementById(opts.el.substring(1)); if (!domRoot) throw '[FastVue.Form]el not found:' + opts.el; //init data if (opts.data) { Object.assign(this.data, opts.data); } //init layout let layout = FastVue.extend(true, this.layout, opts.layout); !layout.display && (layout.display = 'inline'); !layout.cssClass && (layout.display = ''); !layout.title && (layout.title = {}); //init fields let fields = __initFields(opts); //render fields Form.render(this, domRoot, fields); let self = this; fields.forEach(f => { self.view.el = f.view.el; f.created && f.created.call(self); }); }; Form.prototype.set = function (name, newVal, byInput) { var oldVal = this.data[name]; this.data[name] = newVal; var fs = this.fields[name]; fs && fs.forEach(f => { if (f.view.visible !== false && f.onchange && f.view.el) { var oldVal = f.view.el.value; f.view.el.value = value; f.onchange(f.view.el, value, oldVal, false); } }); }; } initForm(Form); }(FastVue.Form)); //Form-render (function (Form, $) { function __readonly(field) { let props = { type: 'hidden', name: field.name, id: field.id, value: field.value, required: !!field.required }; let input = Object.assign(document.createElement('input'), props); let div = document.createElement('div'); div.className = 'readonly'; div.innerHTML = '' + field.value + ''; field.width && FastVue.setWidth(div, field.width); return div.append(input) || div; } function __field(field) { if (field.type === 'hidden') { return; } var type = typeof field.visible; if (type !== "undefined" && (type === 'function' && !field.visible.call(this.context) || !field.visible)) { field.$visible = false; return; } let domDiv = document.createElement('div'); domDiv.className = 'form-group'; let domTitle = Object.assign(document.createElement('label'), { className: this.titleLayout.cssClass || '', innerText: field.title }); this.titleLayout.width && FastVue.setWidth(domTitle, this.titleLayout.width); let domInput; if (field.readonly) { domInput = __readonly(field); } else { domInput = field.$create(this.context); if (domInput.parentElement) { while (domInput.parentElement) { domInput = domInput.parentElement; } } else { let temp = domInput; domInput = document.createElement('div'); domInput.append(temp); } } domDiv.append(domTitle) || domDiv.append(domInput) || this.domForm.append(domDiv); } function render(domRoot, fields) { let domForm = Object.assign(document.createElement('form'), { autocomplete: "off", className: "form-" + (this.$layout.display || "inline") + ' ' + (this.$layout.cssClass || '') }); let func = __field.bind({ context: this, domForm: domForm, titleLayout: layout.title }); fields.forEach(f => func(f)); domRoot.append(domForm); } Form.render = render; }(FastVue.Form)); //Form-Field (function (Form, $) { function Field(config) { !this.title && (this.title = this.name); this.$create = function () { let span = document.createElement('span'); span.style.color = 'red'; span.innerText = '错误!!'; this.$el = span; return span; }; this.$onchange = function (ctx) { let newVal = this.$el.value; ctx.data[this.name] = newVal; if (this.onchange) { ctx.view.el = this.vue.el; this.onchange.call(ctx, newVal, oldVal, true); } }; FastVue.extend(true, this, config); } Field.prototype = { name: "", title: "", value: "", cssClass: "", visible: true, readonly: false, required: false, format(value) { return value; }, unformat(value) { return value; }, onchange(oldVal, newVal) { }, created() { }, destroyed() { } }; Object.freeze(Field); Form.Field = Field; }(FastVue.Form)); //Form-TextField (function (Form) { let Field = Form.Field; //返回dom对象 function createAddon(context, domInput, groupOptions) { //返回dom对象 function _create(addon, isPrepend) { if (typeof addon === 'function') { addon = addon.call(context); } let div = document.createElement('div'); div.className = isPrepend ? 'input-group-append' : 'input-group-append'; if (Array.isArray(addon)) { div.innerHTML = addon.map(x => '' + x + '').join(""); } if (typeof addon === 'string') { div.innerHTML = '' + addon + ''; } return div; } let groupFlag = (groupOptions.prepend ? 1 : 0) | (groupOptions.append ? 2 : 0); if (groupFlag > 0) { let inputGroup = document.createElement('div'); inputGroup.className = "input-group"; if (1 === (groupFlag & 1)) { inputGroup.append(_create(groupOptions.prepend, true)); } inputGroup.append(domInput); if (2 === (groupFlag & 2)) { inputGroup.append(_create(groupOptions.append, false)); } inputGroup.style.width = domInput.style.width; domInput.style.width = ''; return inputGroup; } } function setAutoComplete(context, domInput) { if (this.autocomplete === true) { domInput.setAttribute("autocomplete", "on"); } else if (typeof this.autocomplete === "string") { domInput.setAttribute("autocomplete", this.autocomplete); } else if (typeof this.autocomplete === "object") { let opts = this.autocomplete; if (Array.isArray(this.autocomplete)) { opts = { lookup: this.autocomplete, onSelect: onchange }; } else { opts = { lookup: opts.items, formatResult: opts.itemRender, onSelect: onchange, nameField: opts.nameField, valueField: opts.valueField, searchField: opts.searchField }; } FastVue.autocomplete(domInput, opts); } else { throw "[FastVue.Form]autocomplete unknown"; } } //返回dom对象 function create(context) { let props = { type: 'input', id: this.id, name: this.name, className: 'form-control ' + this.cssClass, autocomplete: "off", value: this.value, placeholder: this.placeholder, readonly: !!this.readOnly, required: !!this.required }; let domInput = Object.assign(document.createElement('input'), props); this.width && FastVue.setWidth(domInput, this.width); if (this.group) { createAddon(context, domInput, this.group); } var onchange = this.$onchange.bind(this, context); if (this.autocomplete) { setAutoComplete.call(this, context, domInput); } else { domInput.addEventListener('change', onchange); } return this.$el = domInput; } function TextField(config) { Field.call(this, config); this.$checkFunction(['validate']); this.$create = create; } TextField.prototype = new Field({ placeholder: '', group: null,//{append:''|[]|function,prepend} validate(value) { return ""; } }); Object.freeze(TextField); Form.fields.text = Form.TextField = TextField; }(FastVue.Form)); //Form-SelectField (function (Form) { let Field = Form.Field; //field.create,返回dom对象 function create(context) { let props = { id: this.id, name: this.name, className: 'form-control ' + this.cssClass, value: this.value, placeholder: this.placeholder, required: !!this.required }; let domSelect = Object.assign(document.createElement('select'), props); this.width && FastVue.setWidth(domSelect, this.width); domSelect.addEventListener('change', this.$onchange.bind(this, context)); let options = this.options; if (options) { if (typeof options === 'function') { options = options.call(context.Proxy); } if (Array.isArray(options)) { if (typeof options[0] === 'string') { options = options.map(x => new Object({ value: x, text: x })); } options.forEach(function (item) { let domOption = document.createElement('option'); domOption.setAttribute('value', item.value); domOption.innerText = item.text; domSelect.append(domOption); }); } else { throw '[SelectField.options]必须为数组或返回数组结果的函数'; } } return this.$el = domSelect; } function SelectField(config) { Field.call(this, config); this.$create = create; } SelectField.prototype = new Field({ options: [] }); Object.freeze(SelectField); Form.fields.select = Form.SelectField = SelectField; }(FastVue.Form)); Object.freeze(FastVue.Form);