IEでcloneしたradioとtextareaを動的にrenameするために(Jqueryベース)

やりたいこと

  • radio群とtextareaが含まれているセクションを丸ごとCloneして、AppendToし、さらにClone元とname値の衝突をしないように、一番上のセクションから数えて、すべてのinputのname値を順番付きで振り直します。

ハマったこと

IE以外はすんなり下記のようにできました。

$.fn.reset_name_num = function(){
        var count = 1;
        //name_1の形のnameを数字の部分だけ現在位置の順番でリネーム
        $('.sys-clone-target',this).each(function(){

            $('input:not(:button)',this).each(function(){

                $(this).attr('name',$(this).attr("name").replace(/_(\d+)/g,'_'+count));
            });

            count++;

        });

でも、IE6だとradioのname値がうまくrenameされません。さらにIE7,6ともにtextareaのrenameはされません。

原因

いろいろ調べて、下記のような理由ではないかと思います。
// Microsoft JScript allows the name to be changed at run time.
// HOWEVER!
// This does not cause the name in the programming model to change
// in the collection of elements, but it does change the name used
// for submitting elements. The NAME attribute cannot be set at run time
// on elements dynamically created with the createElement method.
// To create an element with a name attribute, include the attribute
// and value when using the createElement method.

略して、IEでは特定の部品をcreateElementで生成した後に、動的NAME属性を変えるのは無理、
やりたければ、createElementで生成する際に同時にNAME属性を指定しなければなりません。

対策

  • Textareaには単純にouterHtmlを取得し、nameの部分に対して順番付きに変更したら、outerHtmlソースを動的置換する
if(!+"\v1") {
   // IE
  //Textarea
  var strHTML = $('textarea',this).parent().html();
  if(strHTML){
     strHTML = strHTML.replace(/_(\d+)/g,'_'+count);
     $('textarea',this).parent().html(strHTML);
      }
  }
  • radioに対してはlabelにも対応するようにidとlabelも順番付きで書き換えます。
if(!+"\v1") {
    // IE
    //reset Radio ID and Label
    $(this).attr('id',new_name + $(this).attr("value"));
    $(this).next('label').attr('for',new_name + $(this).attr("value"));
    var strHTML = $(this).parent().html();
    strHTML = strHTML.replace(/_(\d+)/g,'_'+count);
    $(this).parent().html(strHTML);

} else {

    $(this).attr('name',new_name);
    //reset Radio ID and Label
    $(this).attr('id',$(this).attr("name") + $(this).attr("value"));
    $(this).next('label').attr('for',$(this).attr("name") + $(this).attr("value"));
}

おまけ

IEかどうかの判定は(!+"\v1")だけでできる
 http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html