【问题标题】:How to turn a html form into a complex JavaScript object如何将 html 表单转换为复杂的 JavaScript 对象
【发布时间】:2010-08-05 19:47:07
【问题描述】:

有没有办法将表单转换为基于某种结构化表单的复杂 JavaScript 对象?

现在,我不知道这是否应该以更好的方式完成,但基本上我想要这样的东西:

<form>
   <input name="Foo" value="1" />
   <input name="Parent.Child1" value="1" />
   <input name="Parent.Child2" value="2" />
</form>

我想要这个在 JavaScript 中:

var form = GetForm();
var obj = ConvertFormToComplexObject(form);

//
// Followings should be true
// 
// obj.Foo == 1;
// obj.Parent != null
// obj.Parent.Child1 == 1;
// obj.Parent.Child2 == 2;
// 

有什么建议吗?

谢谢,

【问题讨论】:

  • 目的是什么?这似乎是基本 DOM 脚本的一种变体;为什么不学习使用普通的 DOM 脚本呢?
  • 嗯.. 基本上,我有一个带有动态表单元素的表单。用户可以添加“对象”列表,其中每个“对象”都包含一个整数和一个字符串。我可以通过使用 name="1_Integer" 或 name="2_String" 之类的命名约定来保持表单平坦,但我必须编写一个解析器。如果我正确构建 JavaScript 对象。我可以使用 Json 来序列化它,让 Json 处理复杂性。

标签: javascript json forms serialization


【解决方案1】:

我为此编写了一个插件。 希望它会帮助那里的人。 如果您发现任何错误,请告诉我。

这是 serializeObject.js 的代码:

$.fn.serializeObject = function() {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {

        var arrayIndex = function(name) {
            //note: 2d array not handled

            var startIndex = name.indexOf('[');
            var endIndex = name.indexOf(']');

            if (startIndex == -1 || endIndex == -1 || endIndex != name.length - 1)
                return null;

            return name.substr(startIndex + 1, endIndex - startIndex - 1);
        }

        var trimArrayIndex = function(name) {
            var startIndex = name.indexOf('[');
            return name.substr(0, startIndex);
        }

        var createObject = function(obj, className, value) {
            if (className.length == 0)
                return;

            var classNames = className.split(".");

            if (classNames.length == 1) {

                if (obj[classNames[0]] == null) {
                    obj[classNames[0]] = value;
                }
                else if (obj[classNames[0]] instanceof Array) {
                    obj[classNames[0]].push(value);
                }
                else {
                    var temp = obj[classNames[0]];

                    obj[classNames[0]] = new Array();
                    obj[classNames[0]].push(temp);
                    obj[classNames[0]].push(value);
                }

                return;
            }

            var index = arrayIndex(classNames[0]);
            var isArray = index != null;

            if (!isArray) {
                if (obj[classNames[0]] == null) {
                    obj[classNames[0]] = new Object();
                }

                createObject(obj[classNames[0]], className.substr(classNames[0].length + 1), value);
            }
            else {
                var aryName = trimArrayIndex(classNames[0]);

                if (obj[aryName] == null) {
                    obj[aryName] = new Array();
                }
                else if (!obj[aryName] instanceof Array) {
                    throw "unable to serialize " + aryName + " as an array";
                }

                var ary = obj[aryName];
                var nextObj;

                if (ary[parseInt(index)] == null) {
                    ary[parseInt(index)] = new Object();
                }

                nextObj = ary[parseInt(index)];

                createObject(nextObj, className.substr(classNames[0].length + 1), value);
            }
        }

        createObject(o, this.name, this.value || '');
    });
    return o;
};

$.fn.replaceStarWithIndex = function() {
    var a = this.serializeArray();
    var form = this;


    var arrayIndex = function(name) {
        var startIndex = name.indexOf('[');
        var endIndex = name.indexOf(']');

        if (startIndex == -1 || endIndex == -1) {
            return null;
        }

        return name.substr(startIndex + 1, endIndex - startIndex - 1);
    }

    var trimArrayIndex = function(name) {
        var startIndex = name.indexOf('[');
        return name.substr(0, startIndex);
    }

    for (var key in a) {
        var index = arrayIndex(a[key].name);

        if (index == null || index != "*") {
            continue;
        }

        var count = 0;
        var trimName = trimArrayIndex(a[key].name);

        while (true) {
            var elementName = a[key].name.replace('*', count);
            var element = form[0][elementName];

            if (element == null) {
                $(form[0][a[key].name]).first().attr('name', elementName);
                break;
            }
            count++;
        }
    }
}   

这是测试:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Test</title>
    <link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen" />

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" ></script>
    <script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js" ></script>
    <script type="text/javascript" src="serializeObject.js" ></script>
</head>

<body>

<h1 id="qunit-header">Test serializeObject</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>

<!--Test Form -->

<form id="form1" style="display:none;">
    <input type="text" name="Parent.Child1" value="child1"/>

    <input type="text" name="Parent.Child2" value="child2a"/>
    <input type="text" name="Parent.Child2" value="child2b"/>

    <input type="text" name="Parent.Child3" value="3"/>
    <input type="text" name="Parent.Child3" value="2"/>
    <input type="text" name="Parent.Child3" value="1"/>

    <input type="text" name="Parent.Child4[0].Child1" value="11" />
    <input type="text" name="Parent.Child4[0].Child2" value="aa" />

    <input type="text" name="Parent.Child4[1].Child1" value="22" />
    <input type="text" name="Parent.Child4[1].Child2" value="bb" />



</form>   

<form id="form2" style="display:none;">
    <input type="text" name="Child1[0].Child1" value="0" />
    <input type="text" name="Child1[*].Child1" value="1" />
    <input type="text" name="Child1[*].Child1" value="2" />

    <input type="text" name="Child2[2]" value="2" />
    <input type="text" name="Child2[*]" value="0" />
    <input type="text" name="Child2[*]" value="1" />
</form> 

<script type="text/javascript">
    $(document).ready(function() {
        var obj = $('#form1').serializeObject();

        test("Parent should exist", function() {
            equals(true, obj.Parent != null);
        });

        test("Child1 should exist within parent", function() {
            equals(true, obj.Parent.Child1 != null);
        });

        test("Should create array for items with same name", function() {
            equals("child2a", obj.Parent.Child2[0]);
            equals("child2b", obj.Parent.Child2[1]);
            equals("3", obj.Parent.Child3[0]);
            equals("2", obj.Parent.Child3[1]);
            equals("1", obj.Parent.Child3[2]);
        });


        test("Should allow array of objects", function() {
            equals("11", obj.Parent.Child4[0].Child1);
            equals("aa", obj.Parent.Child4[0].Child2);
            equals("22", obj.Parent.Child4[1].Child1);
            equals("bb", obj.Parent.Child4[1].Child2);
        });

        $('#form2').replaceStarWithIndex();

        test("Should replace * with index", function() {
            equals("0", $('#form2 input[name="Child1[0].Child1"]').val());
            equals("1", $('#form2 input[name="Child1[1].Child1"]').val());
            equals("2", $('#form2 input[name="Child1[2].Child1"]').val());

            equals("0", $('#form2 input[name="Child2[0]"]').val());
            equals("1", $('#form2 input[name="Child2[1]"]').val());
            equals("2", $('#form2 input[name="Child2[2]"]').val());
        });

    });
</script>

</body>
</html>

【讨论】:

    【解决方案2】:

    我猜你要的是 document.forms[0]

    类似:

    var form = document.forms[0]; //或者可以是document.getElementByName...

    然后您可以在尝试时访问其值:form.Foo = 1

    你不需要把它转换成复杂的对象 DOM 本身就足够了

    【讨论】:

      【解决方案3】:
      var form = document.forms[0];
      

      返回一个HTML元素对象,你可以使用

      form.Foo
      

      也获得一个 HTML 元素

      但如果你想获得价值,必须使用:

      form.Foo.value
      

      form['Parent.Child1'].value;
      

      你可以看到这个DEMO

      附:我认为 ConvertFormToComplexObject() 方法不好。你不需要创建它。

      【讨论】:

      • 感谢 Zenofo,但我希望“Parent”成为一个对象,因此如果我愿意,我可以选择将其序列化为 Json。在您的情况下, form.Parent 为 null 或 form.Parent.Child1 给出错误
      【解决方案4】:

      它是一个名称[0]非常基本的版本,但它应该让您对它的工作原理有一个基本的了解。

      $(function(){
          var elements = document.forms[0].elements,
              foo = {};
          for(var i=0; i<elements.length; i++) {
              var element = elements[i];
              var names = element.name.split('.');
              if(names.length >1) {
                  foo[names[0]] = foo[names[0]] || {};
                  foo[names[0]][names[1]] = element.value;
              } else {
               foo[names[0]] = element.value;
              }
      
          }
          console.log(foo)
      });​
      

      【讨论】:

        【解决方案5】:

        许多 Javascript 库都具有此功能。我建议你使用他们的实现,或者至少看看他们是如何做到的。

        原型:http://www.prototypejs.org/api/form/serialize

        用法:$('id-of-form').serialize(true)

        【讨论】:

        • 我看过 jQuery 之一,但它没有执行“结构化”对象序列化。事实上,它甚至没有将它序列化为一个对象。我得到的最接近的:stackoverflow.com/questions/1184624/…
        猜你喜欢
        • 1970-01-01
        • 2012-10-24
        • 1970-01-01
        • 1970-01-01
        • 2013-03-04
        • 2016-10-15
        • 2021-11-06
        • 2012-05-30
        • 1970-01-01
        相关资源
        最近更新 更多