FormData() 对象不添加来自表单的提交类型输入,而在 Firefox 上
FormData() object does not add submit-type inputs from form, while on Firefox
今天我遇到了一个有趣的错误,花了很多时间才弄清楚。
设置
页面上的表单。提交时,数据会被捕获并使用它创建 new FormData()
对象。
该对象与 xhr
请求一起发送到 .php
脚本,然后 returns 一个 ok
/ error
消息。
代码看起来像这样:(简化版本,不需要绒毛)
<form name="frm" id="frm" action="" method="post" onsubmit="save(event, this);" enctype="multipart/form-data">
<input name="name" id="name" type="text" value="..." />
<input name="email" id="email" type="text" value="..." />
<input name="phone" id="phone" type="text" value="..." />
<input name="website" id="website" type="text" value="..." />
<textarea name="details" id="details"></textarea>
<input name="send" type="submit" value="Send" />
</form>
<script type="text/javascript">
function save(e, frm) {
if (document.getElementById('nume').value == '' ||
document.getElementById('email').value == '' ||
document.getElementById('telefon').value == '' ||
document.getElementById('site').value == '') {
alert('Forms empty');
} else {
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
var r = JSON.parse(xhr.responseText);
if (r.code == 0) {
document.getElementById('message_ok').style.display = 'block';
} else {
document.getElementById('message_err').style.display = 'block';
}
}
};
xhr.open('POST', 'http://url', true);
var data = new FormData(frm);
xhr.send(data);
}
e.preventDefault();
}
</script>
将此发送到 .php
将生成一个如下所示的数组:
Array
(
[name] => some name
[email] => some email
[phone] => 11111111
[website] => some site
[details] => some details
[send] => Send
)
和 .php
将响应 {"message":"ok","code":0}
或 {"message":"error","code":1}
现在这是预期的行为。这是我在 Chrome、IE 或 Safari 上得到的结果。
问题
然而,在 Firefox 上,除了没有 submit
输入 (name="send"
) key/value 对:
之外,我得到了相同的数组
Array
(
[name] => some name
[email] => some email
[phone] => 11111111
[website] => some site
[details] => some details
)
我尝试了 Linux 和 Windows,以覆盖我的基础,但它仍然给出了同样令人不满意的结果。
解决方案
在网上搜索后一无所获,我解决它的方法(更多的补丁,而不是真正解决)是覆盖send
key/value:
var data = new FormData(frm);
data.append('send', 'Send');
xhr.send(data);
这是有效的,因为如果它已经被定义(Chrome,等等...)它会被覆盖,如果它不存在,它会被创建。
问题
- 相似 - 你遇到过相似的事情吗?
- 修复 - 我认为我的解决方案是 hack,你有更好的修复方法吗?
根据 WHATWG 规范,FireFox 似乎是正确的。
FormData
构造函数的 XMLHttpRequest
规范说:
- If
form
is given, set fd
's entries to the result of constructing the
form data set for form
.
然后在构造表单数据集的描述中说:
The algorithm to construct the form data set for a form form optionally in the context of a submitter submitter is as follows. If not specified otherwise, submitter is null.
表单中的按钮只有在它是提交者时才会包含在表单数据集中。但是当从 FormData
构造函数执行此算法时,没有指定提交者,因此表单数据集中不应包含任何按钮。
在 Chrome 58.
中遇到类似的事情
在我的问题中,有多个提交按钮,我需要知道选择了哪一个,或者至少是否选择了特定的按钮。
我的骇人听闻的技巧是显式侦听被选中的按钮,创建隐藏输入并将其插入提交按钮之前。
已更新:改进的破解
侦听提交按钮的点击并作为提交者通过按钮发送到 on('submit'),并在 ajax 调用中使用它之前附加到 FormData 对象。
修改以适应输入[type="submit"],可能还会对 submitter
.
的内容进行额外的错误检查
$('#defaultModalObject-1').on('click', 'button[type="submit"]', function(event) {
/* horrible hack to detect wizard_goto_step submissions via ajax */
event.preventDefault();
$(event.target.form).trigger('submit', event.target);
});
$('#defaultModalObject-1').on('submit', 'form', function(event, submitter){
...
var formdata = new FormData(form[0]);
if (submitter != undefined) {
formdata.append(submitter.name, submitter.value);
}
...
});
原创黑客
$('#ajax_form_modal_result').on('click', 'button[type="submit"][name="wizard_goto_step"]', function(event) {
/* horrible hack to detect wizard_goto_step submissions via ajax */
event.preventDefault();
var input = $('input[type="hidden"]').attr('name', 'wizard_goto_step').val(event.target.value);
$(event.target).before(input);
$(event.target.form).trigger('submit');
});
很遗憾,我的委托表单处理程序中没有发起人信息 $('#defaultModalObject-1').on('submit', 'form', function(event) { ... });
我们在 linux 客户端上遇到了同样的问题,使用下面的代码将所有按钮元素添加到我们的表单数据中。
第一个问题是在某些条件下获取表单数据出错
if($this.is('form'))
{
var fd = new FormData($this.get(0));
}
else
{
var fd = new FormData();
}
第二个问题类似于在 ajax 表单中添加按钮的问题。有时我们在一种形式中有多个按钮,并且想要检测按下了哪个按钮。
$this.find('button').each(function()
{
fd.append(this.getAttribute('name'), this.value);
});
如果有人需要使用输入类型提交可以添加如上代码,我们在这种情况下使用按钮:)
今天我遇到了一个有趣的错误,花了很多时间才弄清楚。
设置
页面上的表单。提交时,数据会被捕获并使用它创建 new FormData()
对象。
该对象与 xhr
请求一起发送到 .php
脚本,然后 returns 一个 ok
/ error
消息。
代码看起来像这样:(简化版本,不需要绒毛)
<form name="frm" id="frm" action="" method="post" onsubmit="save(event, this);" enctype="multipart/form-data">
<input name="name" id="name" type="text" value="..." />
<input name="email" id="email" type="text" value="..." />
<input name="phone" id="phone" type="text" value="..." />
<input name="website" id="website" type="text" value="..." />
<textarea name="details" id="details"></textarea>
<input name="send" type="submit" value="Send" />
</form>
<script type="text/javascript">
function save(e, frm) {
if (document.getElementById('nume').value == '' ||
document.getElementById('email').value == '' ||
document.getElementById('telefon').value == '' ||
document.getElementById('site').value == '') {
alert('Forms empty');
} else {
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
var r = JSON.parse(xhr.responseText);
if (r.code == 0) {
document.getElementById('message_ok').style.display = 'block';
} else {
document.getElementById('message_err').style.display = 'block';
}
}
};
xhr.open('POST', 'http://url', true);
var data = new FormData(frm);
xhr.send(data);
}
e.preventDefault();
}
</script>
将此发送到 .php
将生成一个如下所示的数组:
Array
(
[name] => some name
[email] => some email
[phone] => 11111111
[website] => some site
[details] => some details
[send] => Send
)
和 .php
将响应 {"message":"ok","code":0}
或 {"message":"error","code":1}
现在这是预期的行为。这是我在 Chrome、IE 或 Safari 上得到的结果。
问题
然而,在 Firefox 上,除了没有 submit
输入 (name="send"
) key/value 对:
Array
(
[name] => some name
[email] => some email
[phone] => 11111111
[website] => some site
[details] => some details
)
我尝试了 Linux 和 Windows,以覆盖我的基础,但它仍然给出了同样令人不满意的结果。
解决方案
在网上搜索后一无所获,我解决它的方法(更多的补丁,而不是真正解决)是覆盖send
key/value:
var data = new FormData(frm);
data.append('send', 'Send');
xhr.send(data);
这是有效的,因为如果它已经被定义(Chrome,等等...)它会被覆盖,如果它不存在,它会被创建。
问题
- 相似 - 你遇到过相似的事情吗?
- 修复 - 我认为我的解决方案是 hack,你有更好的修复方法吗?
根据 WHATWG 规范,FireFox 似乎是正确的。
FormData
构造函数的 XMLHttpRequest
规范说:
- If
form
is given, setfd
's entries to the result of constructing the form data set forform
.
然后在构造表单数据集的描述中说:
The algorithm to construct the form data set for a form form optionally in the context of a submitter submitter is as follows. If not specified otherwise, submitter is null.
表单中的按钮只有在它是提交者时才会包含在表单数据集中。但是当从 FormData
构造函数执行此算法时,没有指定提交者,因此表单数据集中不应包含任何按钮。
在 Chrome 58.
中遇到类似的事情在我的问题中,有多个提交按钮,我需要知道选择了哪一个,或者至少是否选择了特定的按钮。
我的骇人听闻的技巧是显式侦听被选中的按钮,创建隐藏输入并将其插入提交按钮之前。
已更新:改进的破解
侦听提交按钮的点击并作为提交者通过按钮发送到 on('submit'),并在 ajax 调用中使用它之前附加到 FormData 对象。
修改以适应输入[type="submit"],可能还会对 submitter
.
$('#defaultModalObject-1').on('click', 'button[type="submit"]', function(event) {
/* horrible hack to detect wizard_goto_step submissions via ajax */
event.preventDefault();
$(event.target.form).trigger('submit', event.target);
});
$('#defaultModalObject-1').on('submit', 'form', function(event, submitter){
...
var formdata = new FormData(form[0]);
if (submitter != undefined) {
formdata.append(submitter.name, submitter.value);
}
...
});
原创黑客
$('#ajax_form_modal_result').on('click', 'button[type="submit"][name="wizard_goto_step"]', function(event) {
/* horrible hack to detect wizard_goto_step submissions via ajax */
event.preventDefault();
var input = $('input[type="hidden"]').attr('name', 'wizard_goto_step').val(event.target.value);
$(event.target).before(input);
$(event.target.form).trigger('submit');
});
很遗憾,我的委托表单处理程序中没有发起人信息 $('#defaultModalObject-1').on('submit', 'form', function(event) { ... });
我们在 linux 客户端上遇到了同样的问题,使用下面的代码将所有按钮元素添加到我们的表单数据中。
第一个问题是在某些条件下获取表单数据出错
if($this.is('form'))
{
var fd = new FormData($this.get(0));
}
else
{
var fd = new FormData();
}
第二个问题类似于在 ajax 表单中添加按钮的问题。有时我们在一种形式中有多个按钮,并且想要检测按下了哪个按钮。
$this.find('button').each(function()
{
fd.append(this.getAttribute('name'), this.value);
});
如果有人需要使用输入类型提交可以添加如上代码,我们在这种情况下使用按钮:)