WEB制作、マーケティングに関する情報をお届けします。ホームページ制作会社、テラのブログ

Javascriptで表をクリックで昇順、降順にリアルタイムで並び替える方法

タグ:

本記事ではテーブル内のセルの並びを変更したいという時に使える『Javascriptで表をクリックで昇順、降順にリアルタイムで並び替える方法』を紹介します。金額や商品名など並び替えたいといった場面にユーザービリティの向上の一つとして使えるTipsです。

コードを紹介

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Sortable Table</title>
    <style>
        /* ソート用の矢印スタイル(クリック可能) */
        .sort-arrow {
            cursor: pointer;
            user-select: none; /* テキスト選択を無効化 */
            margin-left: 5px; /* 矢印とテキストの間の余白 */
        }

        /* テーブルヘッダーのスタイル */
        th {
            position: relative; /* 絶対位置の要素を基準にするため */
            padding-right: 25px; /* 矢印用のスペースを確保 */
            background: #f3f3f3
        }
        table{
            width: 100%;
        }
        th,td{
            padding: 10px;
            text-align: center;   
        }
        /* 矢印の絶対位置の設定 */
        th .sort-arrow {
            position: absolute;
            right: 20px;
            top: 50%;
            transform: translateY(-50%);
            display: block;
            width: 0;
            height: 0;
            border-left: 6px solid transparent;
            border-right: 6px solid transparent;
            border-top: 6px solid black;
            opacity: 0;
        }

        /* 昇順ソート時の矢印の表示(CSSでは内容を変更できないため、この部分はJSで制御する) */
        th.sorted-asc .sort-arrow {
            transform: rotate(180deg) translateY(4px);
            opacity: 1;
        }

        /* 降順ソート時の矢印の表示 */
        th.sorted-desc .sort-arrow {
            opacity: 1;
        }
    </style>
</head>
<body>
    <!-- ソート可能なテーブル -->
    <table id="sortable_table" border="1" style="border-collapse: collapse">
        <thead>
            <tr>
                <!-- 各列のヘッダー部分。クリックでソート可能。データタイプとして "number" を指定。 -->
                <th>商品名</th>
                <th data-type="number">タンパク質 <span class="sort-arrow"></span></th>
                <th data-type="number">脂質 <span class="sort-arrow"></span></th>
                <th data-type="number">カロリー <span class="sort-arrow"></span></th>
            </tr>
        </thead>
        <tbody>
            <!-- テーブルのデータ部分 -->
            <tr>
                <td>商品1</td>
                <td>4.5g</td>
                <td>10g</td>
                <td>324.5kcal</td>
            </tr>
            <tr>
                <td>商品2</td>
                <td>6.5g</td>
                <td>30g</td>
                <td>524.5kcal</td>
            </tr>
            <tr>
                <td>商品3</td>
                <td>9g</td>
                <td>10g</td>
                <td>150.3kcal</td>
            </tr>
        </tbody>
    </table>

    <script>
        // テーブルをソートする関数
        function sortTable(table, col, reverse) {
            // テーブルのtbodyを取得
            // tbody内のすべての行を配列に変換
            var tbody = table.tBodies[0];
            var tr = Array.prototype.slice.call(tbody.rows);
            
            // 行をソート
            tr.sort(function(a, b) {
                // 各行の指定列の値を取得し、数値として比較
                var aValue = parseFloat(a.cells[col].textContent.trim());
                var bValue = parseFloat(b.cells[col].textContent.trim());
                // 昇順または降順でソート
                return reverse ? bValue - aValue : aValue - bValue;
            });
            // ソートされた行をテーブルに再配置
            tr.forEach(function(row) {
                tbody.appendChild(row);
            });
        }

        // テーブルのヘッダーをクリック可能にする関数
        function makeSortable(table) {
            // テーブル内のすべてのヘッダーセルを取得
            var headers = table.querySelectorAll('th');
            
            // 各ヘッダーにクリックイベントを追加
            headers.forEach(function(header, index) {
                header.addEventListener('click', function() {
                    // ヘッダーが既に昇順ソートされているか確認
                    var isAsc = header.classList.contains('sorted-asc');
                    // 他のヘッダーのソート状態をリセット
                    resetSortIndicators(headers);

                    // 昇順の場合は降順にソート、それ以外は昇順にソート
                    if (isAsc) {
                        sortTable(table, index, true); // 降順
                        header.classList.add('sorted-desc'); // 降順のクラスを追加
                    } else {
                        sortTable(table, index, false); // 昇順
                        header.classList.add('sorted-asc'); // 昇順のクラスを追加
                    }
                });
            });
        }

        // すべてのヘッダーのソート状態をリセットする関数
        function resetSortIndicators(headers) {
            // 各ヘッダーからソートクラスを削除
            headers.forEach(function(header) {
                header.classList.remove('sorted-asc', 'sorted-desc');
            });
        }

        // ページが読み込まれたら、テーブルをソート可能にする
        document.addEventListener('DOMContentLoaded', function() {
            makeSortable(document.getElementById('sortable_table'));
        });
    </script>
</body>
</html>

 

コードを解説

HTML、CSSの解説は割愛します。
まずはテーブルをソートする関数を定義しています。

function sortTable(table, col, reverse) {}

テーブルのtbodyを取得し、tbody内を配列に変換します。
以下ではtrの横列(row)を配列に入れています。

var tbody = table.tBodies[0];
var tr = Array.prototype.slice.call(tbody.rows);

『.sort()』は文字列や数字の大小による昇順・降順で並び替えをするメソッドです。
『parseFloat()』は文字列を数値(少数と整数)に変換します。例えば45.55kgという文字列の場合は45.55の数値のみが抽出されます。
.cells[]ではテーブルのセルのデータにアクセスできます。
最後にソート順を返します。

// 行をソート
tr.sort(function(a, b) {
    // 各行の指定列の値を取得し、数値として比較
    var aValue = parseFloat(a.cells[col].textContent.trim());
    var bValue = parseFloat(b.cells[col].textContent.trim());
    // 昇順または降順でソート
    return reverse ? bValue - aValue : aValue - bValue;
});

次にforEachで配列内のテーブルを再配置します。

// ソートされた行をテーブルに再配置
tr.forEach(function(row) {
    tbody.appendChild(row);
});

テーブルのthタグをクリックして実行できるように関数を設定します。

function makeSortable(table) { });

『table.querySelectorAll(‘th’)』でthタグを配列で格納することができます。
forEachで全てのthタグにクリックイベントを追加します。
また、thタグ内に昇順ソートが設定されているかどうかをチェックします。
『resetSortIndicators(headers);』関数を呼び出してソートのクラス名を削除(この関数は後で解説)します。

var isAsc = header.classList.contains('sorted-asc');
resetSortIndicators(headers);

thタグをクリックされた際のソート順を入れ替えるための関数を呼び出します。
同時にthタグにクラス名をつけてthタグにある昇順、降順マークを入れ替えています。

// 昇順の場合は降順にソート、それ以外は昇順にソート
if (isAsc) {
    sortTable(table, index, true); // 降順
    header.classList.add('sorted-desc'); // 降順のクラスを追加
} else {
    sortTable(table, index, false); // 昇順
    header.classList.add('sorted-asc'); // 昇順のクラスを追加
}

以下はソートのリセット関数です。
全てのthタグからクラス名が削除されます。

function resetSortIndicators(headers) {
    // 各ヘッダーからソートクラスを削除
    headers.forEach(function(header) {
        header.classList.remove('sorted-asc', 'sorted-desc');
    });
}

対象とするテーブルにはIDを振っておく必要があります。
ページ読み込み後にIDを指定して『makeSortable()』の関数を呼び出しています。

// ページが読み込まれたら、テーブルをソート可能にする
document.addEventListener('DOMContentLoaded', function() {
    makeSortable(document.getElementById('sortable_table'));
});

まとめ

以上、『Javascriptで表をクリックで昇順、降順にリアルタイムで並び替える方法』でした。
表を並べ替えるといった場面は多く発生するので活用しやすい機能かと思います。
ぜひ、ご参考ください。

テラ合同会社(東京都)

テラは2014年に東京都でスタートアップしたホームページ制作会社です。ホームページ制作以外にも広告運用、マーケティング、ブランディング、印刷物など幅広い領域をサポートしています。
コーポレートサイトはこちらをご覧ください。