Let's say I have this form:
<form action="/user/store" method="POST" enctype="multipart/form-data">
Name: <input type="text" name="name"><br>
Male: <input type="radio" name="gender" value="male"><br>
Female: <input type="radio" name="gender" value="female"><br>
Photo: <input type="file" name="photo"><br>
Hobbies: <select name="hobbies[]" multiple>
<option value="sport">Sport</option>
<option value="movies">Movies</option>
<option value="music">Music</option>
<option value="games">Games</option>
</select><br>
Accept the terms?<input type="checkbox" name="terms"><br>
<input type="submit">
</form>
If I submit it to a PHP server with my data, this is the result:
array (size=5)
'name' => string 'John' (length=4)
'gender' => string 'male' (length=4)
'hobbies' =>
array (size=2)
0 => string 'sport' (length=5)
1 => string 'music' (length=5)
'terms' => string 'on' (length=2)
'photo' =>
object(Symfony\Component\HttpFoundation\File\UploadedFile)[9]
private 'test' => boolean false
private 'originalName' => string 'test.jpg' (length=8)
private 'mimeType' => string 'image/jpeg' (length=10)
private 'size' => int 130677
private 'error' => int 0
I want to have similar results with JavaScript, so I wrote this function:
//Add event listener for the form submit to the document
$(document).on('submit', 'form', function(e){
//Prevent form submitting
e.preventDefault();
var form = $(':input').not(':submit,:button,:image,:radio,:checkbox');
$.merge(form, $(':checked').not('option'));
var data = [], input, name;
form.each(function(i, obj){
input = {};
name = obj.name;
if(name.indexOf('[]') < 0) {
input['name'] = name;
if(obj.type==='file'){
var files = obj.files;
input['value'] = files[files.length - 1];
} else {
input['value'] = obj.value;
}
} else {
name = name.replace('[]', '');
if(name in data){
var tmp = input['value'];
if(obj.type==='file'){
input['value'] = $.merge(tmp, obj.files);
} else if(obj.type === 'select-multiple') {
input['value'] = $.merge(tmp, $.map(obj.selectedOptions, function(option, i){
return option.value;
}));
} else {
input['value'] = $.merge(tmp, obj.value);
}
} else {
data[name] = {};
if(obj.type === 'file'){
input['value'] = obj.files;
} else if(obj.type === 'select-multiple') {
input['value'] = $.map(obj.selectedOptions, function(option, i){
return option.value;
});
} else {
input['value'] = [];
input['value'].push(obj.value);
}
}
}
data.push(input);
});
});
And this return (JSON format):
[
{"name":"firstname","value":"John"},
{"name":"photo","value":
{
"webkitRelativePath":"",
"lastModifiedDate":"2014-09-08T18:29:36.000Z",
"name":"test.jpg",
"type":"image/jpeg","size":130677
}
},
{"name":"hobbies","value":["sport","music"]},
{"name":"gender","value":"male"},
{"name":"terms","value":"on"}
]
Is there any better way to do that? By better code, I mean less code. I don't mind if it will become slower.