数値入力で動的にカンマを入れる(改)
こちらを参考にさせて頂いて、想定どおりの動きに改造してみた。
+naminamiからのリクエストで、キー入力そのものを制限してみたり。
その他、コメントいれたり、構造化してみたり。
一応、IE6SP2とFirefox2.0.0.12で動作を確認。
これをJSFのカスタムタグにした方がええんか、標準のタグ+JavaScriptな感じがええんか、ちょっと考えてみよう。
追記(28-Feb-2008):
FirefoxでdoCheckKeyCodeがちゃんと動作してねかったよ(汗
こちらを参考にイベントからキーコードは拾えるようにしたけど、キーコードがブラウザ毎に違ってるしorz
実際「;+れ』」キーとShiftキーを使って、+を入力するとFirefoxだと61で、IEだと187だし。
charCodeで、と思ったらonkeydownイベントではcharCodeが取れないときたもんだ。
ちょっとそのヘンも調べてみるか。
<HTML> <head> <script type="text/javascript"> var lastVal = ""; /* 数値をカンマ編集する */ function doFormatNum(e) { var curVal = e.value; // 値に変更のないキー入力を無視する if (lastVal == curVal) { return; } // 現在のカーソル位置を取得する var pos = getCursorPosition(e); // カンマなしの数値にする var val = curVal; while (val.indexOf(",") > -1) { val = val.replace(",", ""); } // 値が数値でない場合は、警告&Undoする if ((curVal != "+") && (curVal != "-") && (curVal != ".") && (isNaN(val) == true)) { alert("数値じゃないです"); e.value = lastVal; setCursorPosition(e, pos - 1); } else { // 数値をカンマ編集する var newVal = formatNumeric(val); // カンマ編集した値を設定する e.value = newVal; // カーソルの位置を設定する(カンマ編集によるズレを考慮) setCursorPosition(e, getMovePosition(curVal, newVal, pos)); // 前回値としてカンマ編集した値を保持する lastVal = newVal; } return; } /* 移動するカーソル位置を取得する(カンマを入れるとカーソルをズラす) */ function getMovePosition(curVal, newVal, pos) { var tmpCurVal = curVal; var curCommaCnt = 0; while (tmpCurVal.indexOf(",") > -1) { if (tmpCurVal.indexOf(",") <= pos) { curCommaCnt++; } tmpCurVal = tmpCurVal.replace(",", ""); } var tmpNewVal = newVal; var newCommaCnt = 0; while (tmpNewVal.indexOf(",") > -1) { if (tmpNewVal.indexOf(",") <= pos) { newCommaCnt++; } tmpNewVal = tmpNewVal.replace(",", ""); } // カーソル位置より前にカンマが挿入されたため文字数分ズラす if (newCommaCnt > curCommaCnt) { return pos + (newCommaCnt - curCommaCnt); } // カーソル位置の移動なし return pos; } /* カンマ付きのフォーマットに変換する */ function formatNumeric(val) { var dec = val.length; if (val.indexOf(".") > -1) { dec = val.indexOf("."); } var ret = ""; if (dec > 0) { for ( var i = dec ; i > 0 ; i-- ) { var num = val.substr(i - 1, 1); if ((i != dec) && (((dec - i) % 3) == 0) && (num != "-") && (num != "+")) { ret = "," + ret; } ret = num + ret; } if (val.indexOf(".") > -1) { ret = ret + val.substr(dec); } } else { ret = val; } return ret; } /* カーソルの位置を取得する */ function getCursorPosition(e) { if (e.createTextRange) { var docRange = document.selection.createRange(); var range = e.createTextRange(); range.setEndPoint('EndToStart', docRange); return range.text.length; } else if (e.setSelectionRange) { return e.selectionStart; } return; } /* カーソルの位置を設定する */ function setCursorPosition(e, position) { if (e.createTextRange) { var range = e.createTextRange(); range.move('character', position); range.select(); } else if (e.setSelectionRange) { e.setSelectionRange(position, position); } return; } /* キー入力を制限する */ function doCheckKeyCode(mode) { var code = getWindowEvent().keyCode; // Enter or Shift or Tab or 矢印 or BackSpace or Delete or Home or End if ((code == 13) || (code == 16) || (code == 9) || ((code >= 37) && (code <= 40)) || (code == 8) || (code == 46) || (code == 36) || (code == 35)) { return true; } // 数字 if ((mode == "0") || (mode == "1")) { if (((code >= 48) && (code <= 57)) || ((code >= 96) && (code <= 105))) { return true; } } // + or - or . if (mode == "1") { if ((code == 107) || (code == 109) || (code == 110) || (code == 187) || (code == 189) || (code == 190)) { return true; } } return false; } /* イベントを取得する */ function getWindowEvent() { if (window.event) { return window.event; } var caller = arguments.callee.caller; while (caller) { var ob = caller.arguments[0]; if (ob) { if ((ob.constructor == KeyboardEvent) || (ob.constructor == MouseEvent)) { return ob; } } caller = caller.caller; } return null; } </script> </head> <body> <input type="text" id="num" onkeydown="return doCheckKeyCode(1);" onkeyup="doFormatNum(this);" size="50" /> </body> </HTML>