Strange behavior with jQuery's clone() and a POST request
Playing around with jQuery, I was trying to dynamically multiply a form element (a file upload box) on the click of a button. Here's the code:
$(document).ready(function () {
$('#new-image').click(function () {
var idx = $('.input.file').size();
var upload = $('.input.file:first-child').clone();
$(upload.find('label')).attr('for', 'Attachment'+idx+'File');
$(upload.find('input[type=file]')).attr('name', 'data[Attachment]['+idx+']开发者_开发知识库[file]');
$(upload.find('input[type=file]')).attr('id', 'Attachment'+idx+'File');
upload.insertBefore('#new-image');
return false;
});
});
The problem is that, if I try and modify the input's name I end up with something like this in the post request - taken from Chrome's (dev build) console, also borks on Firefox (3.6).
------WebKitFormBoundaryMXYcXg2mbP1HZsVJ
Content-Disposition: form-data; name="data[Attachment]​[3]​[file]"; filename="logo.png"
Content-Type: image/png
It is not because of the string concatenation, I tried with a hardcoded value and the weirdness in the request was still there. Am I missing something here or is this a bug in jQuery?
(If anyone is wondering, the name attribute format - data[...
comes from CakePHP)
Update
It seems the problem is not because of .attr()
, but because of .clone()
. I modified the question accordingly.
I was under the impression that this worked:
upload.find('input[type=file]').name = 'data[Attachment]['+idx+'][file]';
// wrong -> find returns a jQuery object and setting name has no effect
because I did not try to add multiple files, I was just trying the last added field :). It does not work even in the correct form:
upload.find('input[type=file]').get(0).name = 'data[Attachment]['+idx+'][file]';
// I still get mumbo-jumbo in the post, between the ][ characters
I just tried without clone()
and it works, for real this time :).
$('#new-image').click(function () {
var idx = $('.input.file').size();
var upload = $('<div class="input file"><label for="Attachment'+idx+'File">File</label><input type="file" name="data[Attachment]['+idx+'][file]" id="Attachment'+idx+'File"></div>');
upload.insertBefore('#new-image');
return false;
});
Does anyone have any idea why clone()
behaves this way?
Try this:
<div class="file">
<div>
<label for="Attachment0File">File: </label>
<input type="file" name="data[Attachment][file][]" id="Attachment0File" />
</div>
</div>
<button type="button" id="new-image">New</button>
$(document).ready(function () {
$('#new-image').click(function (e) {
e.preventDefault();
var idx = $('.file').length;
$('.file:first-child').clone(true, true)
.find('label').attr('for', 'Attachment'+idx+'File').end()
.find('input[type="file"]').attr('name', 'data[Attachment][file][]').attr('id', 'Attachment'+idx+'File').end()
.insertBefore('#new-image');
});
});
upload does not need to be wrapped with $() since it is already a jQuery objct
精彩评论