9
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

HTML上で、ExcelみたいにEnterで上下TABで左右にフォーカス移動するやつ書いた

Last updated at Posted at 2016-04-20

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;
    }
  }
}
9
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?