经常遇到一些项目,需要在数据库某些表中增加一些字段;但是这些字段既不用于查询,也不用于统计,仅仅用于显示。这样一来,每次更改就需要改动许多地方,显得非常繁琐。
比较流行的动态表单/智能表单,都是很好的解决方案,但用在这里显得大材小用,有些浪费了。
所以特地用javascript实现一种比较简便的方法,对于所有仅用于显示的表单元素,取得它们的值,以”key=value,key=value”形式存储到数据库中,数据库中仅需要一个text字段即可;在修改时,从数据库取得这些值,再根据key给相应的元素赋值。
主要使用data-skey的自定义属性作为key,支持select、textarea及input type为text、radio、checkbox的表单元素。
具体实现如下:
function dynamicForm(container) {
this.container = typeof (container) === 'string' ? document.getElementById(container) : container;
}
dynamicForm.prototype = {
_keyValueSplitter: '=',
_itemSplitter: ',',
_attrKey: 'data-skey',
_chkTypes: ['checkbox', 'radio'],
_isInType: function (a, el) {
var etype = el.type.toLowerCase();
var i = a.length;
while (i--) {
if (a[i] === etype) {
return true;
}
}
return false;
},
_addElement: function (array, tag, types) {
var el, nodes = this.container.getElementsByTagName(tag);
for (var i = 0, l = nodes.length; i < l; i++) {
el = nodes[i];
if (!types || (types && this._isInType(types, el))) {
array.push(el);
}
}
},
_getElements: function () {
var ret = [];
this._addElement(ret, 'input', ['text'].concat(this._chkTypes));
this._addElement(ret, 'textarea');
this._addElement(ret, 'select');
return ret;
},
/*获取所有元素的值*/
getValues: function () {
var elArray = this._getElements(), ret = [], el, key, isChk;
for (var i = 0, l = elArray.length; i < l; i++) {
el = elArray[i];
key = el.getAttribute(this._attrKey);
if (key) {
isChk = this._isInType(this._chkTypes, el);
if ((!isChk && el.value) || (isChk && el.checked))
ret.push(key + this._keyValueSplitter + encodeURIComponent(el.value));
}
}
return ret.join(this._itemSplitter);
},
_setValues: function (val, elArray, callback) {
if (!(val || val.length)) return;
var elen = elArray.length, valArray = val.split(this._itemSplitter), keyValue;
for (var i = 0, l = valArray.length; i < l; i++) {
keyValue = valArray[i].split(this._keyValueSplitter);
callback.call(this, elArray, elen, keyValue);
}
},
/*为所有元素赋值(可用于修改页面)*/
setValues: function (val) {
if (!(val || val.length)) return;
this._setValues(val, this._getElements(), this._setElementValue);
},
_setElementValue: function (elArray, elen, keyValue) {
var el, key = keyValue[0], val = decodeURIComponent(keyValue[1]), hasSet;
for (var i = 0; i < elen; i++) {
el = elArray[i];
if (el.getAttribute(this._attrKey) == key) {
if (this._isInType(this._chkTypes, el)) {
if (val == el.value)
hasSet = el.checked = true;
}
else if (val) {
el.value = val;
hasSet = true;
}
if (hasSet) {
elArray.splice(i, 1);
break;
}
}
}
},
/*用于显示到页面(只读)*/
showTo: function (val, tag) {
if (!(val || val.length)) return;
var ret = [];
this._addElement(ret, tag);
this._setValues(val, ret, this._showToElement);
},
_showToElement: function (elArray, elen, keyValue) {
var el, key = keyValue[0], val = decodeURIComponent(keyValue[1]), hasSet;
for (var i = 0; i < elen; i++) {
el = elArray[i];
if (el.getAttribute(this._attrKey) == key) {
el.innerHTML = val;
elArray.splice(i, 1);
break;
}
}
}
};
相关的测试代码:
<!DOCTYPE HTML>
<html>
<head>
<title></title>
<script src="dynamicForm-compiled.js"></script>
<script>
function saveData() {
var f = new dynamicForm('form-wrapper');
document.getElementById('hf1').value = f.getValues();
}
function restoreData() {
var f = new dynamicForm('form-wrapper');
f.setValues(document.getElementById('hf1').value);
}
function showData() {
var f = new dynamicForm('view-wrapper');
f.showTo(document.getElementById('hf1').value, 'span');
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="form-wrapper">
<asp:Literal runat="server" ID="view1" />
</div>
<asp:HiddenField ID="hf1" runat="server" />
<asp:Button ID="B1" runat="server" Text="提交" onclick="B1_Click" OnClientClick="saveData()" />
<input type="button" value="还原表单" onclick="restoreData()" />
<hr />
<div id="view-wrapper">
<asp:Literal runat="server" ID="view2" />
</div>
</form>
</body>
</html>
后台代码:
public partial class test_Default : Page
{
protected override void OnLoad(EventArgs e)
{
view1.Text = File.ReadAllText(Server.MapPath("template-form.html"));
base.OnLoad(e);
}
protected void B1_Click(object sender, EventArgs e)
{
view2.Text = File.ReadAllText(Server.MapPath("template-view.html"));
ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), "showData();", true);
}
}
用于添加修改数据的模板:
姓名:<input type="text" data-skey="name" />
<br />
性别:
<input type="radio" name="rdo_group1" value="男" data-skey="gender" />男
<input type="radio" name="rdo_group1" value="女" data-skey="gender" />女
<br />
谁可以看到:
<select data-skey="see">
<option value="">请选择</option>
<option value="任何人">任何人</option>
<option value="仅好友">仅好友</option>
<option value="保密">保密</option>
</select>
<br />
自我介绍:
<textarea data-skey="intro"></textarea>
用于显示数据的模板:
姓名:<span data-skey="name"></span> <br /> 性别: <span data-skey="gender"></span> <br /> 谁可以看到: <span data-skey="see"></span> <br /> 自我介绍: <span data-skey="intro"></span>
代码下载:点击下载