Hatena::ブログ(Diary)

むつらつれづれ

シンプルなのがいい

この日記のはてなブックマーク数
 | 

2008-03-18

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

| 14:18 |

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値ならエラーは発生しない

ズベズベ 2008/08/05 09:16 jQueryではないのですが、Ajaxとセレクトボックスの組み合わせで同様のエラーが発生しました。
意味不明ですが、alert()の変わりにセレクト.focus()を用いることでも回避できました。
参考になりました。

x6x6x6x6 2009/01/07 12:48 最近判ったんですが、これらはDOMの構築や描画のタイミングによる問題のようで、setTimeoutを使って後述の処理を遅らせたりすると上手くいく場合が多いようです。
おそらく、alertやfocusでも処理のタイミングがずれて回避できたんでしょうね。

hogehoge 2010/04/14 14:58 私もIE系にてひっかかりました。どうやら描写のタイミングみたいですね。

hogehoge 2010/04/14 14:58 私もIE系にてひっかかりました。どうやら描写のタイミングみたいですね。

dodoriasandodoriasan 2010/09/09 11:37 この記事のおかげで非常に助かりました。
ありがとうございました。

 |