HTMLで、ExcelみたいにEnterで上下TABで左右にフォーカス移動するやつ書いた。
shift同時押しで逆方向に行きます。
業務で使うような入力画面はこんな機能あったらいいと思うんだけど、ググっても欲しいようなのが無いみたいなので自作。
矢印キーも対応したいけど、TextBoxとかはFocus = 編集モードだから、使い勝手が悪くなりすぎるので実装してません。
矢印移動も欲しい!
書き散らした感あるんで後で整理します。。。
// 使い方
// ======
// 移動させたいElementに「data-cell」というカスタムデータ属性を振る。
// そのうえで、「setKeyMove()」を実行すると、キー移動が制御される。
// data-cellへの数字の振り方は、ExcelのCellと同じかんじで、"row,column"と数字をふる。
// サンプル
// ========
// <a href="" data-cell="1,1">1-1</a><a href="" data-cell="1,2">1-2</a>
// <a href="" data-cell="2,1">2-1</a><a href="" data-cell="2,2">2-2</a>
// <script>setKeyMove()</script>
// ↑この場合、
// TABだと 1-1 => 1-2 => 2-1 => 2-2 => 1-1...
// ENTERだと1-1 => 2-1 => 1-2 => 2-2 => 1-1...
// と移動する。
// 要素が増えたり減ったりしたときは、再度setKeyMoveをすると新しい移動順で上書きされる。
var KeyCode = {
TAB: 9,
ENTER: 13,
};
function query(s) { return document.querySelectorAll(s);}
function sortCell(list, order) {
var copy = list.slice();
copy.sort(function(a, b) { return order(cell(a), cell(b));});
return copy;
}
function cell(elem) {
var c = elem.getAttribute('data-cell').split(',');
return { row: +c[0], column: +c[1] };
}
function orderByRowColumn(a, b) {
return a.row != b.row ? a.row - b.row : a.column - b.column;
}
function orderByColumnRow(a, b) {
return a.column != b.column ? a.column - b.column : a.row - b.row;
}
function setKeyMove() {
if (setKeyMove.horizontal) {
remove(setKeyMove.horizontal, KeyCode.TAB);
remove(setKeyMove.vertical, KeyCode.ENTER);
}
var list = [].slice.call(query('[data-cell]'));
setKeyMove.horizontal = sortCell(list, orderByRowColumn);
setKeyMove.vertical = sortCell(list, orderByColumnRow);
add(setKeyMove.horizontal, KeyCode.TAB);
add(setKeyMove.vertical, KeyCode.ENTER);
}
function add(list, keyCode) {
list.forEach(function(v,i,a) {
v.addEventListener('keydown', factory(keyCode, i, a));
});
}
function remove(list, keyCode) {
list.forEach(function(v,i,a) {
v.removeEventListener('keydown', factory(keyCode, i, a));
});
}
function factory(keyCode, i, ary) {
return function(event) {
if (event.keyCode != keyCode) return;
event.preventDefault();
ary[nextIndex(i, ary.length, event.shiftKey)].focus();
}
}
function nextIndex(cur, end, back) {
if (back) {
if (cur === 0) {
return end - 1;
} else {
return cur - 1;
}
} else {
if (cur === end - 1) {
return 0;
} else {
return cur + 1;
}
}
}