6

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?

1

4 Answers 4

2

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" })

Sign up to request clarification or add additional context in comments.

Comments

1

try this ( raw code)

$(some_cloned_element).each(function(i, elem){
    var newName = "yay_i_love_my_new_name";
    if ($.browser.msie === true){ // evil browser sniffing *cries*
        $(elem).replaceWith(document.createElement(
            this.outerHTML.replace(/name=\w+/ig, 'name='+newName+'_'+i)
        ));
    } else {
        $(elem).attr('name',newName+'_'+i);
    }
    $("body").append(some_cloned_element);
});

check when i=50 and then break/exit

better way : use name as array like name=picture[]

Refernece

Comments

0

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.

3 Comments

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.
@prodigtalson +1. Tried this when running into the same solution and solved my issue. I only used text inputs and select statements, so radio issues as mentioned above may still occur.
Useful info, but -1 because this doesn't answer the question that was asked.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.