経緯
前に投稿した記事で、keydownで拾ったキー入力を元に別の文字を入力させるようなコードを書いたけど、コードを見ればわかるが実はどの位置でキー入力しても一番後ろにしか入力できない。
気をつけるべきだったこと
- readonly属性
- maxlenth属性
- カーソル位置
- 文字選択の開始位置、終了位置
コード
上記を踏まえて前回のコードを書き直すと、こんな感じになる。
$.fn.insertChar = function insertChar(ch) {
if (this.prop("readonly")) {
return this;
}
var from = this.prop("selectionStart");
var to = this.prop("selectionEnd");
var val = this.val();
var newValue = val.slice(0, from) + ch + val.slice(to);
if (newValue.length >= this.prop("maxlength")) {
this.val(newValue);
var range = this[0].createTextRange();
range.move("character", from + ch.length);
}
return this;
}
var charTable = {
'゙' : '@',
'レ' : '=',
'ケ' : '*'
};
$("input[type=text],textarea").on("keydown", function(e) {
var converted = charTable[e.char];
if (e.keyCode === 229 && e.shiftKey && converted) {
e.key = e.char = converted;
$(this).insertValue(converted);
e.preventDefault();
}
});
上の$.fn.insertValueは複数要素にマッチングした場合の処理を考えていないので、その場合はjQuery.accessとか使って実装したほうがいいんだと思う。