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