JSでフォームの入力値をobjectにして取得するよ
Posted: Updated:
ちょっちメモ的に
軽い気持ちで書いてたら,思ったよりぐんにょりした仕様が多かったのでメモ的にエントリ.てきとーに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)
手元でさらっと見てみた感じだと,上記のような対応状況でした.