Problem using jQuery clone function in form

2020-06-30 04:28发布

问题:

Those snippes of code that you will check works fine for FF, Chrome, Safari, but seems to be a problem with IE when running jQuery clone function:

My template:

<form method="post" action="/post/add/">
{{ form.management_form }}
    <div class='table'>
      <table class='no_error'>
        <input id="id_mypost_set-0-title" type="text" name="mypost_set-0-title" />
        <input id="id_mypost_set-0-content" type="text" name="mypost_set-0-content" />
      </table>
    </div>
    <input type="button" value="Add Other" id="add_more">
    <script>
        $('#add_more').click(function() {
            cloneMore('div.table:last', 'mypost_set');
         });
    </script>
</form>

In a javascript file:

function cloneMore(selector, type) {
    var newElement = $(selector).clone(true);
    var total = $('#id_' + type + '-TOTAL_FORMS').val();
    newElement.find(':input').each(function() {
        var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
        var id = 'id_' + name;
        $(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
    });
    newElement.find('label').each(function() {
        var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
        $(this).attr('for', newFor);
    });
    total++;
    $('#id_' + type + '-TOTAL_FORMS').val(total);
    $(selector).after(newElement);
 }

The problem is with the selector: "A clone of the original html piece of code works OK", but, A clone from cloned piece of code marks the selector as "undefined", in other words, the second time that I clone the table the selector doesnt work anymore for those cloned items.

Problem only for IE.

What im missing? Any hint is apreciated :)

回答1:

This is a known jQuery bug, though they claim it is fixed.
One option here is to use .html(), and clone them manually. This will not clone events and saved .data, which may be an issue for you. .live can help if you have events here.

If the only thing you need is to change the names and id, a better option is to use a regular expression (this clones the events from the first element, mind you):

var name = $(this).attr('name').replace(/-\d+-/,'-' + total + '-');

this will search for -number-, and replace it, so it finds the last number on all browsers, or -0- on IE.

Here's a working demo with alerts: http://jsbin.com/evapu

As a side note - your code is a little messy. jQuery code should be inside $(document).ready (the click), you have a table with no body (no <tr>,<td> - the inputs are thrown out), and the code has some duplications.
Although it didn't help in this case, invalid DOM and not using the ready event can cause problems.



回答2:

you're missing a hidden input with id 'id_' + type + '-TOTAL_FORMS' - you're getting your total from this object and using it to modify the name and id of cloned objects.

I tried your code with this:

<input type="hidden" id="id_mypost_set-TOTAL_FORMS" value="1"/>

added right after

<form method="post" action="/post/add/">

and it works correctly, all new inputs have correct ids. does this really work in FF ??



回答3:

You code works perfectly on all browsers as stated before Still if you could replace:

var newElement = $(selector).clone(true);

with:

var newElement = $($(selector).html());

and see if it helps.

Also, re-attach the event handler, like so.

newElement.bind(EVENT, function() {});

Or use the appropriate helper.



回答4:

perhaps you can use this clone function :

/*
 * Clone method
 * Prevents reference problem
 */
clone: function( obj ){
  if(obj == null || typeof(obj) != 'object')
    return obj;
  var temp = new obj.constructor();
  for(var key in obj)
    temp[key] = clone(obj[key]);
  return temp;
}