JSでフォームの入力値をobjectにして取得するよ

ちょっちメモ的に

軽い気持ちで書いてたら,思ったよりぐんにょりした仕様が多かったのでメモ的にエントリ.てきとーにgistで貼り付けてみたり.

/**
* フォーム内の入力値をobjectとして取得する
*
* @param {Node} form
* @return {Object}
*/
function getFormData(form) {
if (form.tagName !== 'FORM') {
throw new TypeError('Argument must be HTMLFormElement.');
}
var elms = toArray(form.elements),
e, i, pos, isAry, name, val, rv = {},
list = [], li,
option, j, jz;
// form.elementsに,INPUT[type="image"]要素は含まれない
if (form.innerHTML.indexOf('type="image"') || form.innerHTML.indexOf("type='image'")) {
list = toArray(form.getElementsByTagName('input'));
i = 0;
while (li = list[i++]) {
if (li.type === 'image') {
elms.push(li);
}
}
}
i = 0;
while (e = elms[i++]) {
// form.elementsに,FIELDSET要素も含まれる
if (
e.disabled === true ||
e.type === 'radio' && e.checked === false ||
e.type === 'checkbox' && e.checked === false ||
e.tagName === 'FIELDSET' ||
0
) {
continue;
}
pos = e.name.indexOf('[');
isAry = pos !== -1;
name = isAry ? e.name.substr(0, pos) : e.name;
val = e.value;
// multiple属性のついたSELECT要素
if (e.tagName === 'SELECT' && e.multiple === true && isAry) {
rv[name] || (rv[name] = []);
j = 0;
jz = e.length;
for (; j<jz; j++) {
option = e[j];
if (option.selected === true) {
rv[name].push(option.value);
}
}
} else if (isAry) {
rv[name] || (rv[name] = []);
rv[name].push(val);
} else {
rv[name] = val;
}
}
return rv;
}

form.elementsにINPUT[type='image']な要素が含まれない

oh…歴史的な理由て.

form.elementsにFIELDSET要素が含まれる

今回は判定しないので単純に無視してます.さらにfieldset.elementsにはFIELDSET要素以下の子要素が含まれます.まとめてコントロールするときには何か使えるかも.

multiple属性のついたSELECT要素の扱い

multiple属性が有効であっても,name属性がvars[]のようになっていなければ,一番最後のselectedな要素の値を送信します.

よって,他と同様にisAryのときだけmultipleとして扱って,子のOPTION要素を走査しています.

valueなしのOPTION要素の扱い

option要素にvalue属性が指定されていないとき,中のテキストがデータとして扱われるはず.

<select>
<option value="valueあり" selected="selected">あるよ</option>
</select>
→ select.value === 'valueあり'

<select>
<option selected="selected">ないよ</option>
</select>
→ select.value === 'ないよ'

上記のような感じですね.しかし,IE6〜8ではselect.valueから値を取得できず,IE6〜7ではoption.valueでも取得できません.

<option value="">ラベル</option>
 と
<option>ラベル</option>

これらの区別が付きづらそうだったので,とりあえず対応しないことにしてます.スマートに判別できるのかな…

おまけ.fieldset要素のdisabled属性

上記を見ると,fieldsetのdisabled属性がtrueの場合に,中に入ったコントロール類はすべて無効になるとされていますが今回は仕様外としています.

有効 : Firefox 8 (Mac), Opera 11.6 (Mac)

無効 : InternetExplorer 9, Safari 5.1 (Mac), Chrome16 (Mac)

手元でさらっと見てみた感じだと,上記のような対応状況でした.


Author

ahomuAyumu Sato

KINTOテクノロジーズ株式会社

Web 技術、組織開発、趣味など雑多なブログ。技術の話題は zenn、ご飯の話題はしずかなインターネットにも分散して投稿しています。

Bio: aho.mu
X: @ahomu
Zenn: ahomu
GitHub: ahomu
Sizu: ahomu

Related

Latest

Archives

Tags

Search