Problem using jQuery clone function in form

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" />
    <input type="button" value="Add Other" id="add_more">
        $('#add_more').click(function() {
            cloneMore('div.table:last', 'mypost_set');

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);
    $('#id_' + type + '-TOTAL_FORMS').val(total);

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 :)

13.10.2009 15:15:22
Why aren't you just cloning the original all the time with :first instead of :last in the selector?
googletorp 13.10.2009 15:45:50
The :last part of it is important because the selector is also used to determine what the new form will be inserted after. but I've testes like that with no results, the same behaviour with all browsers now :(
panchicore 13.10.2009 16:15:01
Your code works well, as posted, on IE6, 8, 8 on 7 compatibility mode, and Firefox: . Of course, some controls are missing, but the code works.
Kobi 19.10.2009 20:01:36
thx for test, cloning works OK, but inside, the selectors are not. If you can, do it in your server with your lang of preference, get a POST o GET from that form and plz tellme what you see =)
panchicore 20.10.2009 03:44:25

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:

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.

20.10.2009 06:42:10
Hi Kobi, first than all: thanks 4 understandme, im taking all your advices (notes) and fixed messy code, and applying to my code it results this error: $(selector).after(newElement); Node cannot be inserted at the specified point in the hierarchy" code: "3, the element is cloned but when JS run this line, return this error and delete the cloned items.
panchicore 23.10.2009 14:49:42
OMG, if I remove the $(selector).after(newElement); line, it now works fine in IE, why Kobi?
panchicore 23.10.2009 14:56:09
you are the best Kobi :)
panchicore 23.10.2009 15:06:54
Happy to help. The version I posted is a little different, but I guess you figured it out. Thanks!
Kobi 23.10.2009 17:44:58

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;
13.10.2009 16:31:36
thanks, but, how do I use this function?, having count my context?
panchicore 13.10.2009 16:54:57

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

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


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.

23.10.2009 09:46:31
doesnt help, it does not attach the event handler :(
panchicore 22.10.2009 20:45:10
Yeah, the even handler, you have to re-attach those :) See if this new edit helps
partoa 23.10.2009 09:31:16

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 ??

22.10.2009 14:56:19