views:

437

answers:

3

Hi all,

I am trying to clone a div and change the names of the input fields in this div. It works great for most of the browsers but IE 7 does not change the name attribute of the input fields.

Demo: http://jsbin.com/iduro/7

HTML

<body>
  <pre></pre>
  <div><input value="Hello World" name="test"></div>
</body>

JS

var lastRow = $("body div:last"),
    newRow  = lastRow.clone(true)
              .show()
              .insertAfter(lastRow);

newRow.find('input').attr("name","test2");

$("pre").text( newRow[0].innerHTML );

Results:

Firefox: (works) <input value="Hello World" name="test2">

IE8 (works) <INPUT value="Hello World" name=test2 jQuery1273063250500="4">

IE7 (bug): <INPUT value="Hello World" name=test jQuery1273063303968="4">

As you see the name of IE7 does not change to test2.

Is there any obvious reason or work around?

A: 

If you pan on accessing these as a set when the form is posted then there is no need to change the name - just dont put a value within the brackets and it will be incremented for you when you grab the array on the server side:

<input name="test[]" />

If you need to be able to access each one by index from js you can just use get on the appropriate collection returned by a selector. Or you can assign ID attributes like test_1.

prodigitalson
I try to clone a row of radio buttons.However as changing the name does not work the user can only choose one radio button for both rows instead of two.
Ghommey
A: 

I could fix it for now. As long as an input field is not attached to the dom you can change the name and the radio buttons work properly again.

// Old Code
 $("div:last").clone(true).children("input").attr("name","newName");

// New Code
 $("div:last").clone(true).children("input").fixCloneBug ("newName");

To lower the execution time only the jQuery Events, the className and the type attribute are copied.

fixCloneBug Method:

(function( $ )
{


    if ( ! $.browser.msie || parseInt( $.browser.version ) > 7 )
        // NO FIX FOR IE 7+ FF WEBKIT
        $.fn.fixCloneBug = function( newName ){ return this.attr( "name", newName ) };
    else
        // FIX IE 5-7
        $.fn.fixCloneBug = function( newName )
        {
            var $cloned = $();

            this.each(function( )
            {
                    /* -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._

                       Create a new element with className and jQuery events of the buggy element

                    */          

                    var     $elem    = $(this),

                            $newElem = $(document.createElement( $elem.attr('tagName') ));

                            // USE SAME TYPE

                    $newElem.attr('type', $elem.attr('type') );


                            // SET NAME
                    $newElem.attr('name', this.name );
                    $newElem.attr('name', newName );

                            // ADD TO DOM

                    $newElem.insertBefore( $elem );

                            // CLONE EVENTS
                    $newElem.data( "events", $elem.data("events") );

                            // CLASS NAME
                    $newElem.attr('className', this.className );

                    /* -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._

                       Delete buggy element 

                    */

                    $elem.remove();


                    // Add to result
                    $cloned.push($newElem);
            })

            return $cloned;

        }

}(jQuery));

Maybe you think $newElem.attr('name', this.name ); is useless however it allows me to use a jQuery 1.4 feature:

.fixCloneBug (function(i,oldname){ return oldname+"_new" })

Ghommey
A: 

The simple solution for Radio button is :

$("div:last").find("radio").each(function(){
     var name="someNewName";
     var id="someNewId";
    if (!$.browser.msie || parseInt($.browser.version) > 7) {
      this.name = name;
      this.id=id;
    }
    else {
      (this).attr("outerHTML", "<input type=radio id=" + id + " name=" + name + " />");  
    }
});

This will alter the outerHTML of the element so that the HTML for the element(radio button) is overwritten. The same solution can be applied for : find("input") / find("checkbox") for the other controls too.

Siva Gopal