动态表单(javascript实现)

     经常遇到一些项目,需要在数据库某些表中增加一些字段;但是这些字段既不用于查询,也不用于统计,仅仅用于显示。这样一来,每次更改就需要改动许多地方,显得非常繁琐。

     比较流行的动态表单/智能表单,都是很好的解决方案,但用在这里显得大材小用,有些浪费了。

     所以特地用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>

代码下载:点击下载

作者:囧月
出处:http://lwme.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/lwme/p/2233663.html