jQueryでoption要素を追加した際の諸問題

jQueryで任意のoption要素を追加するには、append()やprepend()を利用するのが手軽。

$('#target').append($('<option>').attr({ value: 'xxx' }).text('xxxxxxx'));

だが、この操作はIEの場合に問題が生じる。v1.1.3.1以前ではoption要素を追加しても幅が調整されない不具合があり*1、v1.2.3ではoption要素を増やした直後にそのvalue値をval()で設定しようとすると、

「selected プロパティを設定できませんでした。 未定義のエラーです」

というスクリプトエラーが発生する*2。これらの問題はselect要素ごと作り直してしまうことで回避できる。

$('#target').after($('#target').clone());
$('#target').remove();

一時的に同一のidを持つ要素が二つできてしまうが、jQueryはこれも問題なく扱える。after()で追加したselect要素のコピーは正しい幅を持ち、val()による値のセットも問題なく行える。after()の戻り値は$('#target')なので、一行で書くこともできる。

$('#target').after($('#target').clone()).remove();

上記はreplaceWith()と等価なはずなのだが、何故かこちらではval()のエラーが回避されない。

$('$target').replaceWith($('#target').clone());

このメソッドはv1.2.3の460行目付近に定義されている。

	replaceWith: function( value ) {
		return this.after( value ).remove();
	},

回避策はもう一つある。option要素を増やした直後に

$('#target').width();

上記のようにwidth()を呼び出すと、v1.1.3.1では幅が調整され、v1.2.3では以後val()による値のセットでエラーが生じなくなる。ソースを追ってみたが、理由はよく判らない。

更に言うと、v1.2.3ではoption要素を増やした後に任意の引数でalert()を呼び出してからval()をセットすると、何故かエラーが発生しない。

$('#target').append($('<option>').attr({ value: 'xxx' }).text('xxxxxxx'));
alert('press any key'); // この一行がないとエラーになる
$('#target').val('xxx');

意味不明。誰かこのメカニズムを解明できたら、是非教えてください。

*1:どうやら、select要素を含むbodyやdiv要素をappend()等で直前に操作している場合に発生するらしい

*2:元々存在していたoption要素に設定されているvalue値ならエラーは発生しない