经常遇到一些项目,需要在数据库某些表中增加一些字段;但是这些字段既不用于查询,也不用于统计,仅仅用于显示。这样一来,每次更改就需要改动许多地方,显得非常繁琐。
比较流行的动态表单/智能表单,都是很好的解决方案,但用在这里显得大材小用,有些浪费了。
所以特地用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>
代码下载:点击下载