2012-07-26 38 views
71

想知道是否有一个JavaScript没有jQuery或任何允许我序列化窗体和访问序列化版本的框架的函数?窗体序列化javascript(无框架)

+2

要回答这个问题,没有。 – RobG

+1

“访问序列化版本”是什么意思?我已经开发了有没有第三方的依赖,可以在HTML格式转换成像对象JSON是多维的脚本:https://github.com/serbanghita/formToObject - 如果它有助于降回复 –

回答

24

这个微型library不依赖于框架。除此之外,您需要自己实现序列化功能。 (虽然在重量的1.2千字节,为什么不使用它?)

+1

这是完美的。但必须在代码 – aravind

+0

的输入部分添加一个'case'电子邮件':'链接被破坏 – user1040495

+1

@ user1040495链接适用于我。 –

29
function serialize (form) { 
    if (!form || form.nodeName !== "FORM") { 
      return; 
    } 
    var i, j, q = []; 
    for (i = form.elements.length - 1; i >= 0; i = i - 1) { 
     if (form.elements[i].name === "") { 
      continue; 
     } 
     switch (form.elements[i].nodeName) { 
      case 'INPUT': 
       switch (form.elements[i].type) { 
        case 'text': 
        case 'tel': 
        case 'email': 
        case 'hidden': 
        case 'password': 
        case 'button': 
        case 'reset': 
        case 'submit': 
         q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 
         break; 
        case 'checkbox': 
        case 'radio': 
         if (form.elements[i].checked) { 
           q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 
         }            
         break; 
       } 
       break; 
       case 'file': 
       break; 
      case 'TEXTAREA': 
        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 
        break; 
      case 'SELECT': 
       switch (form.elements[i].type) { 
        case 'select-one': 
         q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 
         break; 
        case 'select-multiple': 
         for (j = form.elements[i].options.length - 1; j >= 0; j = j - 1) { 
          if (form.elements[i].options[j].selected) { 
            q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value)); 
          } 
         } 
         break; 
       } 
       break; 
      case 'BUTTON': 
       switch (form.elements[i].type) { 
        case 'reset': 
        case 'submit': 
        case 'button': 
         q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 
         break; 
       } 
       break; 
      } 
     } 
    return q.join("&"); 
} 

来源:http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js

+1

该序列似乎不符合标准形式系列化,其中空格用“+”来表示兼容。上面只使用* encodeURIComponent *,它将空间编码为“%20”。如果需要一致性,最后可以使用正则表达式在传输之前将“%20”转换为“+”。 – RobG

+3

我添加了这样一个修改版本,以https://gist.github.com/brettz9/7147458(与其他一些改进) –

+3

提交按钮,不一定要提交,重置按钮不应该被提交,并且按钮只有在那里用于提交并在这种情况下被视为提交按钮。请参阅[HTML5 4.10.22表单提交](http://www.w3.org/html/wg/drafts/html/CR/forms.html#concept-form-submit)。 – RobG

8

我开始从Johndave Decano答案。

这应该解决在他的功能回复中提到的一些问题。

  1. 用%符号替换%20。
  2. 提交/按钮类型将只被提交,如果他们被点击 提交表格。
  3. 重置按钮将被忽略。
  4. 该代码对我来说似乎是多余的,因为它基本上做的是 相同的事情,不管字段类型如何。更不用说 与'tel'和'email'等HTML5字段类型不兼容,因此我使用switch语句删除了大部分细节。

如果按钮类型没有名称值,它仍然会被忽略。

function serialize(form, evt){ 
    var evt = evt || window.event; 
    evt.target = evt.target || evt.srcElement || null; 
    var field, query=''; 
    if(typeof form == 'object' && form.nodeName == "FORM"){ 
     for(i=form.elements.length-1; i>=0; i--){ 
      field = form.elements[i]; 
      if(field.name && field.type != 'file' && field.type != 'reset'){ 
       if(field.type == 'select-multiple'){ 
        for(j=form.elements[i].options.length-1; j>=0; j--){ 
         if(field.options[j].selected){ 
          query += '&' + field.name + "=" + encodeURIComponent(field.options[j].value).replace(/%20/g,'+'); 
         } 
        } 
       } 
       else{ 
        if((field.type != 'submit' && field.type != 'button') || evt.target == field){ 
         if((field.type != 'checkbox' && field.type != 'radio') || field.checked){ 
          query += '&' + field.name + "=" + encodeURIComponent(field.value).replace(/%20/g,'+'); 
         } 
        } 
       } 
      } 
     } 
    } 
    return query.substr(1); 
} 

这就是我目前如何使用这个功能。

<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))"> 
+4

对于重构良好的代码+1。 -1用于忽略禁用的字段,该字段不应出现在查询字符串中。为非常优雅的语句+1,避免重复计算表单元素。总数:+1 :-)谢谢! –

+2

+1 @SimonSteinberger在评论中做数学运算。 –

+0

关于禁用字段的好消息,我最近遇到了一个我正在写的新函数。 +1给你们两个,因为我喜欢阅读有趣的评论。 :) – TibTibs

97

这里是纯JavaScript的方法:

var form = document.querySelector('form'); 
var data = new FormData(form); 
var req = new XMLHttpRequest(); 
req.send(data); 

虽然它似乎POST请求被唯一的工作。

https://developer.mozilla.org/en-US/docs/Web/API/FormData

+4

注意这是IE10及以上而已,但一个很好的解决方案 – John

+8

注意,这发出多,这与一些简单的REST服务(即羽毛-的MongoDB) –

+0

我完全忘了这个不好的作品,我很高兴你张贴在这里。谢谢 – jaggedsoft

17

这里的TibTibs略加修改版本:

function serialize(form) { 
    var field, s = []; 
    if (typeof form == 'object' && form.nodeName == "FORM") { 
     var len = form.elements.length; 
     for (i=0; i<len; i++) { 
      field = form.elements[i]; 
      if (field.name && !field.disabled && field.type != 'file' && field.type != 'reset' && field.type != 'submit' && field.type != 'button') { 
       if (field.type == 'select-multiple') { 
        for (j=form.elements[i].options.length-1; j>=0; j--) { 
         if(field.options[j].selected) 
          s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.options[j].value); 
        } 
       } else if ((field.type != 'checkbox' && field.type != 'radio') || field.checked) { 
        s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value); 
       } 
      } 
     } 
    } 
    return s.join('&').replace(/%20/g, '+'); 
} 

残疾人字段将被丢弃和名称也是URL编码。在返回字符串之前,正则表达式替换%20个字符只发生一次。

查询字符串与jQuery的$ .serialize()方法的结果形式相同。

+3

+1,以便花时间改进代码。 我喜欢当人们发现我的缺点,因为这是一个很好的学习机会。 +1保持它看起来不错。 -1因为我不能给+2 =( – TibTibs

+0

你可以添加'form.nodeName.toLowerCase()==“form”'而不是'form.nodeName ==“FORM”' – StefanNch

+1

会有什么优势? –

4

如果您想要序列化事件上的输入。这是我使用的纯JavaScript方法。

// serialize form 
var data = {}; 
var inputs = [].slice.call(e.target.getElementsByTagName('input')); 
inputs.forEach(input => { 
    data[input.name] = input.value; 
}); 

数据将是输入的JavaScript对象。

+2

这应该对大多数元素,绝对不是文本区域/选择工作,虽然 – jaggedsoft

+0

是slice.call一样Array.from? – user1040495

4

一个使用更少的变量,并采取forEach循环的速度优势(这是有点快于for S)

function serialize(form) { 
    var result = []; 
    if (typeof form === 'object' && form.nodeName === 'FORM') 
     Array.prototype.slice.call(form.elements).forEach(function(control) { 
      if (
       control.name && 
       !control.disabled && 
       ['file', 'reset', 'submit', 'button'].indexOf(control.type) === -1 
      ) 
       if (control.type === 'select-multiple') 
        Array.prototype.slice.call(control.options).forEach(function(option) { 
         if (option.selected) 
          result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(option.value)); 
        }); 
       else if (
        ['checkbox', 'radio'].indexOf(control.type) === -1 || 
        control.checked 
       ) result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(control.value)); 
     }); 
     return result.join('&').replace(/%20/g, '+'); 
} 
2

我重构TibTibs回答到的东西,是更清晰,以重构的@ SimonSteinberger的代码版本读。由于80个字符的宽度和一些注释,它有点长。

此外,它会忽略空白字段名称和空白值。

// Serialize the specified form into a query string. 
// 
// Returns a blank string if +form+ is not actually a form element. 
function $serialize(form, evt) { 
    if(typeof(form) !== 'object' && form.nodeName !== "FORM") 
    return ''; 

    var evt = evt || window.event || { target: null }; 
    evt.target = evt.target || evt.srcElement || null; 
    var field, query = ''; 

    // Transform a form field into a query-string-friendly 
    // serialized form. 
    // 
    // [NOTE]: Replaces blank spaces from its standard '%20' representation 
    //   into the non-standard (though widely used) '+'. 
    var encode = function(field, name) { 
    if (field.disabled) return ''; 

    return '&' + (name || field.name) + '=' + 
      encodeURIComponent(field.value).replace(/%20/g,'+'); 
    } 

    // Fields without names can't be serialized. 
    var hasName = function(el) { 
    return (el.name && el.name.length > 0) 
    } 

    // Ignore the usual suspects: file inputs, reset buttons, 
    // buttons that did not submit the form and unchecked 
    // radio buttons and checkboxes. 
    var ignorableField = function(el, evt) { 
    return ((el.type == 'file' || el.type == 'reset') 
     || ((el.type == 'submit' || el.type == 'button') && evt.target != el) 
     || ((el.type == 'checkbox' || el.type == 'radio') && !el.checked)) 
    } 

    var parseMultiSelect = function(field) { 
    var q = ''; 

    for (var j=field.options.length-1; j>=0; j--) { 
     if (field.options[j].selected) { 
     q += encode(field.options[j], field.name); 
     } 
    } 

    return q; 
    }; 

    for(i = form.elements.length - 1; i >= 0; i--) { 
    field = form.elements[i]; 

    if (!hasName(field) || field.value == '' || ignorableField(field, evt)) 
     continue; 

    query += (field.type == 'select-multiple') ? parseMultiSelect(field) 
               : encode(field); 
    } 

    return (query.length == 0) ? '' : query.substr(1); 
} 
+0

我复制此直接进入我的应用程序和多选不出现工作(该值重复) – anastymous

+0

@anastymous感谢您的接触,它已被修复。 –

+0

嗨,布赖恩,什么是** evt **?我应该通过什么呢? Firefox告诉我它没有被定义。 – anastymous

5
HTMLElement.prototype.serialize = function(){ 
    var obj = {}; 
    var elements = this.querySelectorAll("input, select, textarea"); 
    for(var i = 0; i < elements.length; ++i) { 
     var element = elements[i]; 
     var name = element.name; 
     var value = element.value; 

     if(name) { 
      obj[ name ] = value; 
     } 
    } 
    return JSON.stringify(obj); 
} 

要使用这样的:

var dataToSend = document.querySelector("form").serialize(); 

我希望我帮助。

+1

上混淆了此行为的一个非常基本的示例。将无法使用复选框。在这里,您必须明确检查输入类型。 –

14

如果你的目标是支持URLSearchParams API(all recent browsers)浏览器,使用:否则

new URLSearchParams(new FormData(formElement)).toString() 

,用这一个班轮(作品无处不在,除了IE):

​​
5

如果您需要使用JSON格式的POST提交表单“myForm”,你可以这样做:

const formEntries = new FormData(myForm).entries(); 
const json = Object.assign(...Array.from(formEntries, ([x,y]) => ({[x]:y}))); 
fetch('/api/foo', { 
    method: 'POST', 
    body: JSON.stringify(json) 
}); 

第二行从数组转换等:

[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ] 

...到常规目的,如:

{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... } 

...它通过传递mapFn成Array.from执行此转换()。这个mapFn应用于每个[“a”,“b”]对,并将它们转换为{“a”:“b”},以便数组包含很多对象,每个对象只有一个属性。 mapFn使用“解构”来获取对的第一部分和第二部分的名称,并且它还使用ES6“ComputedPropertyName”来设置由mapFn返回的对象中的属性名称(这就是为什么说“然后将所有这些单个属性对象传递到Object.assign()函数的参数中,该函数将所有单个属性对象合并成一个单独的对象,该对象具有所有属性

Array.from(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

解构在参数: https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/

更多关于计算的属性名称的位置: Variable as the property name in a JavaScript object literal?

+0

即使我不理解第二行,你能给我更多关于它的信息吗? –

+0

我在上面的一些信息编辑 – molsson

+0

使用扩展运算符和本机对象和数组方法的美丽答案。 –

1
// supports IE8 and IE9 
    function serialize(form) { 
    var inputs = form.elements; 
    var array = []; 
    for(i=0; i < inputs.length; i++) { 
     var inputNameValue = inputs[i].name + '=' + inputs[i].value; 
     array.push(inputNameValue); 
    } 
    return array.join('&'); 
    } 
//using the serialize function written above 
var form = document.getElementById("form");//get the id of your form. i am assuming the id to be named form. 
var form_data = serialize(form); 
var xhr = new XMLHttpRequest(); 
xhr.send(form_data); 

//does not work with IE8 AND IE9 
var form = document.querySelector('form'); 
var data = new FormData(form); 
var xhr = new XMLHttpRequest(); 
xhr.send(data); 
1

我从@moison答案,从MDN抢过项()FORMDATA的方法,它是说:

的FORMDATA 。entries()方法返回一个迭代器,允许通过包含在此对象中的所有键/值对去执行 。每个 对的关键是一个USVString对象;该值可以是USVString或Blob。

但唯一的问题是,手机浏览器(Android和Safari浏览器不支持)和IE和Safari桌面过于

但基本上这里是我的方法:

let theForm = document.getElementById("contact"); 

theForm.onsubmit = function(event) { 
    event.preventDefault(); 

    let rawData = new FormData(theForm); 
    let data = {}; 

    for(let pair of rawData.entries()) { 
    data[pair[0]] = pair[1]; 
    } 
    let contactData = JSON.stringify(data); 
    console.warn(contactData); 
    //here you can send a post request with content-type :'application.json' 

}; 

码即可发现here

0
document.serializeForm = function (selector) { 
    var dictionary = {}; 
    var form = document.querySelector(selector); 
    var formdata = new FormData(form); 
    var done = false; 
    var iterator = formdata.entries(); 
    do { 
     var prop = iterator.next(); 
     if (prop.done && !prop.value) { 
      done = true; 
     } 
     else { 
      dictionary[prop.value[0]] = prop.value[1]; 
     } 

    } while (!done); 
    return dictionary; 
}