こんにちは。
一度に複雑な判定をやり切る正規表現を書こうとすると、後からデバッグしたり、機能を追加、修正するときに大変そうなので、入力値のバリデーション全体をいくつかのステップに分け、各ステップでは、目的が明確なチェック、または置換を行うという方向で以下を作成しました。(動作を明確にするため、エラーメッセージを表示する <span>
とCSSを追加しています。)
html
1 < input class = " text_input " />
2 < br />
3 < span id = " error_message " />
css
1 input {
2 border : 1 px solid #444 ;
3 font-size : 32 px ;
4 width : 240 px ;
5 }
6 .valid { text-align : right ; }
7 .error { border : medium solid red ; }
javascript
1
2 $ ( document ) . on ( 'focus' , '.text_input' , function ( ) {
3
4 if ( ! $ ( this ) . hasClass ( 'error' ) ) {
5 let num = $ ( this ) . val ( ) ;
6 num = num . replace ( / , / g , '' ) ;
7 $ ( this ) . val ( num ) ; // フォーカス中はカンマを消去
8 }
9
10 // バリデーション結果を表すクラスを削除
11 $ ( this )
12 . removeClass ( 'valid' )
13 . removeClass ( 'error' ) ;
14
15 // エラーメッセージを消去
16 $ ( '#error_message' ) . text ( '' ) ;
17 } ) ;
18
19 $ ( document ) . on ( 'input' , '.text_input' , function ( ) {
20 if ( $ ( this ) . val ( ) === '' )
21 $ ( this ) . data ( 'comma-separated' , false ) ;
22 } ) ;
23
24 const validate = ( str , option ) => {
25
26 // 最初にトリミングしておく
27 str = str . trim ( ) ;
28
29 if ( str . length === 0 )
30 return str ;
31
32 // チェック1: 先頭にのみ-を許容し、半角数字と何個かのカンマと、0個または1個のピリオドで構成されること
33 let groups = / ^([-]?)([0-9,]+)(.[0-9]*)?$ / . exec ( str ) ;
34
35 if ( ! groups )
36 throw new Error ( '許容されない文字を含む。あるいは許容されない位置に数字以外の文字がある。' ) ;
37
38 // チェック2: 整数部分が2文字以上の場合、0から始まっていないこと
39 if ( / ^0. / . test ( groups [ 2 ] ) )
40 throw new Error ( '整数部分が2文字以上であり、かつ0で始まっている。' ) ;
41
42 // チェック3: 整数部分にカンマが含まれる場合、正しく下の桁から3桁ごとに区切られている。
43 if ( groups [ 2 ] . includes ( ',' ) && ! / ^[^,]{1,3}(,[^,]{3})+$ / . test ( groups [ 2 ] ) ) {
44 throw new Error ( '整数部分のカンマ区切りが正しく3桁ごとになっていない。' ) ;
45 }
46
47 // 置換1: 整数部分にカンマが含まれず、かつオプションでカンマ区切りが指定されていれば、カンマ区切りに変換
48 if ( ! groups [ 2 ] . includes ( ',' ) && option . commaSeparated )
49 groups [ 2 ] = Number ( groups [ 2 ] ) . toLocaleString ( 'ja-JP' ) ;
50
51 // 置換2: 小数部分が存在し、かつ、小数部分の末尾が1個以上の0の場合、この末尾の0を削除する。
52 if ( groups [ 3 ] && groups [ 3 ] . length > 1 ) {
53 const m = / ^.([0-9]*[1-9])?(0+)$ / . exec ( groups [ 3 ] ) ;
54 if ( m )
55 groups [ 3 ] = ( m [ 1 ] ? '.' + m [ 1 ] : '' ) ;
56 }
57
58 // 置換3: 小数点はあるが、少数点の後ろに数字がない場合、小数部分を空文字列にする。
59 if ( groups [ 3 ] === '.' )
60 groups [ 3 ] = '' ;
61
62 return groups [ 1 ] + groups [ 2 ] + ( groups [ 3 ] || '' ) ;
63 } ;
64
65
66 $ ( document ) . on ( 'blur' , '.text_input' , function ( ) {
67
68 try {
69 // 入力値をチェックし、かつ不要な文字を除去した文字列を取得
70 const str = validate (
71 $ ( this ) . val ( ) ,
72 { commaSeparated : $ ( this ) . data ( 'comma-separated' ) }
73 ) ;
74
75 // チェックが通った場合、置換後の文字列をinputに設定
76 $ ( this ) . val ( str )
77
78 // 入力文字列が空ではない場合、エラーの通ったことを示すクラスを追加
79 if ( str . length > 0 )
80 $ ( this ) . addClass ( 'valid' ) ;
81
82 // セルの表示状態をカンマありにするかどうかのフラグ設定
83 $ ( this ) . data ( 'comma-separated' , str . includes ( ',' ) ) ;
84
85 } catch ( e ) {
86 // エラー状態を示すクラスを追加
87 $ ( this ) . addClass ( 'error' ) ;
88
89 // エラーメッセージを表示
90 $ ( '#error_message' ) . text ( e . message ) ;
91 }
92 } ) ;
上記のコードを以下に上げていますので、実際に入力してお試し頂ければと思います。
https://jsfiddle.net/jun68ykt/nym6bxLh/3/
動作について、ご質問にある
正負について、文頭の「-」は許可、「+」は許可しない
ゼロ埋めは許可しない
文頭の小数点は許可しない
4桁以上の数字を入力する場合、3桁毎のカンマは許可する
上記の許可するものと半角数値を除き、許可しない
extra ) フォーカス中はカンマを表示しない
は満たせているのではないかと思います。さらに上記に加えて、以下のように動作します
数値を入力してからフォーカスを外し、入力値の検査後、入力値に
問題がなければ右寄せで表示される。(Excelと同様)
問題があると、<input>
が赤い線で囲まれ、かつエラーメッセージが表示される。
少数点はあっても小数点以下の数字がない場合、たとえば 55.
と入力してフォーカスを外すと、少数点は除去されて、55
と表示される。(Excelと同様)
3) 初めにカンマ区切りの数字、たとえば 123,555
を入力して一度フォーカスを外してから、再度、フォーカスすると、カンマのない文字列になるが、何らかの修正後に再度フォーカスを外し、値に問題がない場合、カンマ区切り表示に戻る。その後、いったん空欄にすると、カンマ区切り表示モードは解除される。
小数点以下の数字の末尾にいくつかの 0
がある場合、たとえば 12.340500
と入力してフォーカスを外すと、末尾の余分な 0
は除去されて,12.3405
と表示される。(Excelと同様)
以上です。
pegyさんの要件、あるいはご要望どおりではないところが何かあれば、コメントからお知らせください。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/09/11 06:10
2018/09/11 13:16