jqueryのserializeArrayでdisabledの値を取得

jqueryのserializeArrayをよく使用しているのですが、disabledにしたformの値を取得しようとして問題にぶち当たりました。

あれ?disabledにしたformの値が取れないぞ!困った!

ググる。

一度disabled外してから取得しろとか、disabledの分は別途取得しろとかマジですか・・・。

仕方ない。ちょっとserializeArrayの中身を見てみよう。

という流れで、serializeArrayの処理の中身を見てみることにしました。

最近使用したjqueryは「jquery-1.10.1」なので、これを元に話を進めていきます。
※変数の位置は実際とちょっと違ったり、serializeArrayの処理部分だけを抜き出しています。

var rCRLF = /\r?\n/g,
rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
rsubmittable = /^(?:input|select|textarea|keygen)/i,
manipulation_rcheckableType = /^(?:checkbox|radio)$/i;

jQuery.fn.extend({
serializeArray: function() {
return this.map(function(){
// Can add propHook for “elements” to filter or add form elements
var elements = jQuery.prop( this, “elements” );
return elements ? jQuery.makeArray( elements ) : this;
})
.filter(function(){
var type = this.type;
// Use .is(“:disabled”) so that fieldset[disabled] works
return this.name && !jQuery( this ).is( “:disabled” ) &&
rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
( this.checked || !manipulation_rcheckableType.test( type ) );
})
.map(function( i, elem ){
var val = jQuery( this ).val();

return val == null ?
null :
jQuery.isArray( val ) ?
jQuery.map( val, function( val ){
return { name: elem.name, value: val.replace( rCRLF, “\r\n” ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, “\r\n” ) };
}).get();
}
});

上記がserializeArrayの中身のようです。
map.filter.mapとメソッドチェーンで繋げていますね。
見やすさはありますが、処理回数の面ではちょっと無駄なような気がするようなしないような。

さて、中身を見ると一目瞭然。
filterでdisabledが弾かれています。
16行目の「!jQuery( this ).is( “:disabled” )」←この部分

問答無用でdisabledの値を取得しないようにしたのには、何か理由があるのでしょうか。
とにかく元々のメソッドを書き換えたくないので、新しくメソッドを作成しましょう。

別途共通で読み込むjsファイルを作成し、こんな感じに書いてみました。
※もちろんjquery使用前提&jquery本体より後に読み込む。
まるっと処理を書き換えてもよかったのですが、今回は元々のserializeArrayになるべく手を入れないように書き換えました。

var rCRLF = /\r?\n/g,
rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
rsubmittable = /^(?:input|select|textarea|keygen)/i,
manipulation_rcheckableType = /^(?:checkbox|radio)$/i;

jQuery.fn.extend({
serializeArrayCustom: function( option ) {

var option = option || {},
filterDisabled = option.disabled || false;

return this.map(function(){
// Can add propHook for “elements” to filter or add form elements
var elements = jQuery.prop( this, “elements” );
return elements ? jQuery.makeArray( elements ) : this;
})
.filter(function(){
var type = this.type;
// Use .is(“:disabled”) so that fieldset[disabled] works
return this.name && ( !jQuery( this ).is( “:disabled” ) || filterDisabled ) &&
rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
( this.checked || !manipulation_rcheckableType.test( type ) );
})
.map(function( i, elem ){
var val = jQuery( this ).val();

return val == null ?
null :
jQuery.isArray( val ) ?
jQuery.map( val, function( val ){
return { name: elem.name, value: val.replace( rCRLF, “\r\n” ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, “\r\n” ) };
}).get();
}
});

今回はファイルを分けたため、必要な変数を再定義しています。
serializeArrayCustomっていうメソッド名になっているのはグフカスタムを意識したからです。嘘です。手抜きです。
これで、「$(“:input”).serializeArrayCustom({disabled: true})」のように引数を渡してあげれば、disabledの値も取得してくれるはずです。
引数を渡さなければ通常のserializeArrayと同じ動きをしますし、必要に応じて引数を増やしていろいろ条件分岐する処理を追加とかしてもよいですね。

というわけで、今回はserializeArrayをちょっとだけカスタマイズして新たなメソッドを作成してみました。