JavaScript による入力項目無効設定の高速化 - その2

コメントにてご指摘を受けたように、下記例のように単に入力項目が多いというだけでは、無効化の処理は遅くはならないようです。

<!-- tag.disabled = true; で遅くならない例 -->
<html>
  <body>
    <form>
      <input type="text"/>
      <input type="text"/>
      <input type="text"/>
         :
         :
    </form>
  </body>
</html>

しかし、下記例のように、テーブルタグ内に入力項目を配置すると、途端に遅くなります。

<!-- tag.disabled = true; で遅くなる例 -->
<html>
  <body>
    <form>
      <table>
        <tr>
          <td>
            <input type="text"/>
            <input type="text"/>
            <input type="text"/>
            <input type="text"/>
          </td>
        </tr>
         :
         :
      </table>
    </form>
  </body>
</html>

また、すべての入力項目が遅くなるわけではなく、type="text"、type="password"、type="file"についてのみ、遅くなるようです*1

先日のエントリでは、これらの項目に対して、DOM によるノードの複製と入れ替えを利用することで、無効化処理を高速化することを記述しました。が、バグがありました(汗。
IE固有の問題なのか、<input type="checkbox">タグ、<input type="radio">タグ、<select>タグに対して Node#cloneNode(true) を使用して、ノードの複製を作成した場合、選択状態が正しく複製されません。このため、チェックボックスラジオボタンの選択が解除される、ドロップダウンリスト選択が変更されるなどの不具合が発生します。


これらの問題を回避するために、ノードの複製以外で高速化を行ないました。
先日のれー氏のコメント(レンダリングによる性能劣化)をヒントに、以下のようなコードによる無効化処理を行ないました。

function setEnabled(enabled) {
  var tags = document.all.tags("input");
  var length = tags.length; // drry 氏の指摘により改善
  for (var i=0; i<length; i++) {
    var tag = tags[i];
    var display = tag.style.display;
    tag.style.display = "none";
    tag.disabled = !enabled;
    tag.style.display = display;
  }
}

入力項目を無効に設定する前に、項目を非表示にしておき、無効設定後に元通り表示状態にもどします。
たったコレだけのことで、入力項目がテーブル内に配置されていても、ほぼ一瞬で処理が終わるようになりました。

項目が表示状態のままであろうが、無効に設定後に表示状態に変更されようが、差は無いような気もする*2のですが、なぜこんなにも速度に差がでるのか不思議です。

*1:テキストの1行入力用コントロールとして表示されるものが関係している模様

*2:1個ずつ [表示→非表示→無効設定→表示] しているので。一気に表示、非表示を切り替えるとかならまだ分かるのですが・・・