← TssGrid/例一覧

TssGrid 例: 多段(複数列)ソート onHeaderRender + sortByCols

ヘッダ右端の ▲▼ がソート(▲=昇順・▼=降順、点灯中をもう一度押すと解除)。普通のクリックは単独ソート=別の列を押せば置き換わるので全消しも一発Ctrl+クリックで多段(押した順=優先度。マーク左に小さく番号)。
ヘッダ本体クリックは列選択Shift+クリックで列の範囲選択)=ソートと選択が別の場所で両立します。▲▼ は onHeaderRender フックで差し込み(再描画でも自動)、並べ替えの中身は grid.sortByCols(specs)

デモ

ソートなし(入力順)

要点

let specs = [];                                  // [{col, dir}] 位置=優先度
const find = c => specs.findIndex(s => s.col === c);

const grid = new TssGrid(host, {
  headers, columns, data,
  // ★ 各ヘッダthの生成後に呼ばれる(再描画毎に自動)=ここで ▲▼ を差し込む
  onHeaderRender(th, c) {
    const i = find(c), active = i >= 0 ? specs[i].dir : '';
    const num = (i >= 0 && specs.length >= 2) ? (i + 1) : '';
    const g = document.createElement('span');
    g.className = 'ms-grp';
    g.innerHTML = '<span class="ms-num">' + num + '</span>' +
      '<span class="ms-sort ' + active + '">' +
        '<span class="ms-seg ms-up" data-dir="asc"></span>' +
        '<span class="ms-seg ms-dn" data-dir="desc"></span>' +
      '</span>';
    th.appendChild(g);
  },
  // ★ マーク上ならソート(return false で列選択を抑止)/本体なら列選択(そのまま通す)
  onHeaderClick(c, e) {
    const seg = e.target.closest('.ms-seg');
    if (!seg) return;                              // 本体クリック=コアの列選択に任せる
    const dir = seg.dataset.dir, i = find(c);
    if (e.ctrlKey || e.metaKey) {                  // Ctrl=多段(押した順=優先度・点灯向き再クリックで解除)
      if (i >= 0 && specs[i].dir === dir) specs.splice(i, 1);
      else if (i >= 0) specs[i].dir = dir; else specs.push({ col: c, dir });
    } else {                                       // 単独(置換)=点灯中を再クリックで全解除
      if (specs.length === 1 && specs[0].col === c && specs[0].dir === dir) specs = [];
      else specs = [{ col: c, dir }];
    }
    apply();
    return false;
  },
});
function apply() { specs.length ? grid.sortByCols(specs) : (grid.clearSort() || grid.redraw()); }