Files
zszq-trs/YLErpWeb/wwwroot/Scripts/fast/fastVue.form.js
T
2024-05-09 14:06:26 +08:00

406 lines
12 KiB
JavaScript

//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 = '<span>' + field.value + '</span>';
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 => '<span class="input-group-text">' + x + '</span>').join("");
}
if (typeof addon === 'string') {
div.innerHTML = '<span class="input-group-text">' + addon + '</span>';
}
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);