時々この機能が欲しくなる。特に「全角→半角」の方向。
ワリと大きな企業サイトのフォームでも「半角で入力してください」などと注文がつけられている項目があり,それに気づかず全角で入力してしまうと受け付けてくれなかったりする。しかし,「かな」を考えなければ,全角を半角にするのはそんなにむずかしくないのではないか。自動で変換する機能くらい付けてくれりゃいいのにと思う。大企業でもそこまで考慮してコード書ける人がいないのか,あるいはやはりコードはどこかに「丸投げ」して,「文字コード」というものをよく知らない人がフォーム作ったりしているということなのか……。
特に Perl の正規表現置換によって簡単に実現すると分かったので,メモついでに書いておく。
● Perl
Perl には UNICODE の「内部表現」機能があるが,それを使うと負担が大きそうな気がする。ファイルなどでは UTF-8 を直接扱えたほうがラクな気もするし。というわけで,ここでは UTF-8 前提で考える。
◆ 全角→半角
UTF-8 で,スペースとかなを考慮しなくてもいいなら,正規表現置換一文で書ける。既定変数 $_ を対象にするなら,これでいい。
# UTF-8 全角 → 半角 by M.Ishikawa(スペース,かな除く) s/\xEF(\xBC[\x81-\xBF]|\xBD[\x80-\x9E])/chr((ord(substr($1,0,1))& 1)*64+(ord(substr($1,1,1))&0x3F)+32)/eg;
● JavaScript
JavaScript の内部表現は UNICODE そのものだから,文字単位で考えればいい。
◆ 全角→半角
String オブジェクトにはいちおう replace() というメソッドが用意されているが,全置換するには正規表現を使う必要がある。また,筆者が使っている FireFox 45 では,replaceAll() というメソッドは使えず,結局 replace() の正規表現に全置換オプション(g)を付けて対応する必要が出てくる。いずれにせよ,正規表現未対応の古いブラウザでは使えない。もし正規表現が使える場合は,String オブジェクトにメソッドを追加して使うとしたらこんな感じ。“*1”というのは,十進数 parseInt() の省略形。直後の“+2”を数値として加算するため。
String.prototype.ztoh = function(){ // 全角 → 半角 return unescape( escape( this ). replace( /%uFF([0-5])/ig, '%u00'+('$1'* 1 + 2) ) ); }
しかしこれ,筆者の使う FireFox 45 ではうまくいかない。“$1”が単なる文字列,あるいは裸だと未定義となってしまう。JavaScript の正規表現の実装は,わりと中途半端のようだ。
ただ,数字に限るなら,これでいいのかもしれない。
String.prototype.ztoh = function(){ // 全角 → 半角 return unescape( escape( this ).replace(/%uFF1/ig,'%u003') ); }
正規表現を使わない場合は,こんな感じか。たぶんこのほうが確実。
String.prototype.ztoh = function(){ // 全角 → 半角 var i, c, res =''; // by M.Ishikawa(スペース,かな除く) for( i=0; i < this.length; i++ ) res += ( '\uFF01'<=( c = this.charAt( i ) )&& c <'\uFF5F' ) ? unescape( '%'+(escape( c ).substr( -2, 1 )*1+2)+ escape( c ).substr( -1, 1 ) ): c; return res; }
フォームで,たとえば郵便番号(zipcode)の項目の記載内容にある全角文字を半角にしたい時はこんな感じになる。
var elemobj = document.forms[0].elements.zipcode; elemobj.value = elemobj.value.ztoh();