[jQuery][DataTable]結合したセルにてSortを行う

# 概要
以下の投稿で課題としていた結合したセルにてソートが正常に動作しなくなる件について、
これまたdatatableの仕様に苦しんだので解決方法を記載します。

https://qiita.com/nagataichiko2249/items/4c6ffe319190c1bb198f


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [問題事象](#問題事象)
1. [原因](#原因)
1. [解決方法](#解決方法)
1. [終わり](#終わり)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# 問題事象
以下のような表をdatatableを使用して作成した際、
datatableが行なってくれるソート処理が、rowGroupを使用しない場合と使用した場合で異なる仕様となる。
・rowGroupに指定したcolumnは先頭項目でのみソートが可能。
・rowGroupに指定していないcolumnはrowGroupにて結合された項目内でのソートとなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727564/2a0debd8-1723-443a-8584-872566095f94.png)


```html:index.html
<html>

<head>
    <meta charset="UTF-8">
    <!-- !-- for DataTables --> -->
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.24/datatables.min.css" />
</head>
<body>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"
        integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    <script type="text/javascript"
        src="https://cdn.rawgit.com/ashl1/datatables-rowsgroup/fbd569b8768155c7a9a62568e66a64115887d7d0/dataTables.rowsGroup.js"></script>
    <script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.24/datatables.min.js"></script>
    <script type="text/javascript"
        src="https://cdn.rawgit.com/ashl1/datatables-rowsgroup/fbd569b8768155c7a9a62568e66a64115887d7d0/dataTables.rowsGroup.js"></script>
    <table id="example" class="stripe hover cell-border order-column table table-bordered" cellspacing="0" width="100%">
        <thead>
            <tr>
                <th>名前</th>
                <th>電話</th>
                <th>年齢</th>
                <th>購入商品</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>

    <script src="main.js"></script>
</body>
</html>
```

```javascript:main.js
$(document).ready(function (){
    var table = $('#example').DataTable({
        'language': {
            "url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/Japanese.json"
        },
        'data': [
           ["山田","0000000","30","マンが"],
           ["山田","0000000","30","肉"],
           ["山田","0000000","30","魚"],
           ["山田","0000000","30","タバコ"],
           ["山田","0000000","30","皿"],
           ["山田","0000000","30","人形"],
           ["山田","0000000","30","ゲーム"],
           ["佐藤","1111111","21","骨"],
           ["佐藤","1111111","21","パッド"],
           ["佐藤","1111111","21","ボール"],
           ["マイケル","2222222","10","バッド"],
           ["マイケル","2222222","10","刀"],
           ["ヨーコ","3333333","40","お花"],
        ],
        'columnDefs': [
           {
              'targets': [0,1, 2, 3],
              'orderable': true,
              'searchable': false
           }
        ],
        'rowsGroup':[0,1,2],
        "pageLength": 100
     });   
  });

```

ソート時の動作は以下
先頭項目でのソート
・電話/年齢でのソートが動作しない。
![スクリーンショット 0004-07-04 21.18.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727564/68559466-52ef-3a84-65d9-77985bd79e28.png)
スクリーンショット 0004-07-04 21.18.05

rowGroup内部でのソート
・購入商品でソートをしても名前/電話/年齢項目の並び順は変更されない。
![スクリーンショット 0004-07-04 21.18.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727564/f996d286-ca26-4232-d17c-54a6f2c86e4f.png)
スクリーンショット 0004-07-04 21.18.40


<a id="#Chapter2"></a>
# 原因
以下2点から、rowGroupでのソートは、rowGroupにした複数項目にてソートを行う仕様だと考えられる。
・orderClasses機能が動作していること
　・sorting_１/2/3がDOM要素に付与されていた
　https://datatables.net/reference/option/orderClasses

・名前/電話/年齢項目ヘッダーの操作時の動作
　・並び替え無し状態とならない
　・常にrowGroupに含まれる複数項目でのソートを行なっているように見える。
　https://datatables.net/examples/basic_init/multi_col_sort


<a id="#Chapter3"></a>
# 解決方法
datatableの仕様の問題で、プロパティ変更などでは解決しなかった。

datatable側のソート処理を無効化、呼び出し側でソート機能を実装した。
datatableのcssを呼び出すことで見た目上差異はない。

```html:index.html
<html>

<head>
    <meta charset="UTF-8">
    <!-- !-- for DataTables --> -->
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.24/datatables.min.css" />
crossorigin="anonymous">

</head>
<body>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"
        integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    <script type="text/javascript"
        src="https://cdn.rawgit.com/ashl1/datatables-rowsgroup/fbd569b8768155c7a9a62568e66a64115887d7d0/dataTables.rowsGroup.js"></script>
    <script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.24/datatables.min.js"></script>
    <script type="text/javascript"
        src="https://cdn.rawgit.com/ashl1/datatables-rowsgroup/fbd569b8768155c7a9a62568e66a64115887d7d0/dataTables.rowsGroup.js"></script>
    <table id="example" class="stripe hover cell-border order-column table table-bordered" cellspacing="0" width="100%">
        <thead>
            <tr id="tablehead">
                <th class="sorting" onclick="sortTask(event)" id="name">名前</th>
                <th class="sorting" onclick="sortTask(event)" id="tel">電話</th>
                <th class="sorting" onclick="sortTask(event)" id="age">年齢</th>
                <th class="sorting" onclick="sortTask(event)" id="item">購入商品</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
    <script src="main.js"></script>
</body>

</html>
```

```javascript:main.js
$(document).ready(function (){
    table = $('#example').DataTable({
        'language': {
            "url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/Japanese.json"
        },
        'data': [
           ["山田","0000000","30","マンが"],
           ["山田","0000000","30","肉"],
           ["山田","0000000","30","魚"],
           ["山田","0000000","30","タバコ"],
           ["山田","0000000","30","皿"],
           ["山田","0000000","30","人形"],
           ["山田","0000000","30","ゲーム"],
           ["佐藤","1111111","21","骨"],
           ["佐藤","1111111","21","パッド"],
           ["佐藤","1111111","21","ボール"],
           ["マイケル","2222222","10","バッド"],
           ["マイケル","2222222","10","刀"],
           ["ヨーコ","3333333","40","お花"],
        ],
        'columnDefs': [
           {
              'targets': [0,1, 2, 3],
              'searchable': false
           }
        ],
        "ordering": false,
        'rowsGroup':[0,1,2],
        "pageLength": 100
     });   
  });

function sortTask(event)
{

    let buf = table.data();
    table.clear();

    // ソート初期状態を解除
    $(event.target).removeClass('sorting');

    let sortPattern = "";

    if($(event.target).hasClass('sorting_asc')) 
    {
        // 昇順であれば、降順
        $(event.target).removeClass('sorting_asc');
        $(event.target).addClass('sorting_desc');
        sortPattern = 'sorting_desc';
    }
    else
    {
        // 降順であれば、昇順
        $(event.target).removeClass('sorting_desc');
        $(event.target).addClass('sorting_asc');
        sortPattern = 'sorting_asc';
    }

    $.each(document.getElementById('tablehead').childNodes, function (index, element) 
    {
        // 他ヘッダーのソート状態をソートなしに変更
        if(element.id != "" && event.target.id != element.id)
        {
            // 操作したヘッダーは対象外
            $(element).removeClass('sorting_asc');
            $(element).removeClass('sorting_desc');
            $(element).addClass('sorting');				
        }	
    });

    sorttest(buf, event.target.id, sortPattern);

    table.rows.add(buf).draw();
}

function sorttest(table, sortId, sortPattern) 
{
    table.sort(function (a,b) 
    {
        switch (sortId) 
        {
            case "name":
                if(sortPattern === "sorting_asc") 
                {
                    if (a[0] > b[0]) return 1;
                    if (a[0] < b[0]) return -1;
                }
                else if(sortPattern === "sorting_desc") 
                {
                    if (a[0] < b[0]) return 1;
                    if (a[0] > b[0]) return -1;
                }
                break;

            case "tel":
                if(sortPattern === "sorting_asc") 
                {
                    if (a[1] > b[1]) return 1;
                    if (a[1] < b[1]) return -1;
                }
                else if(sortPattern === "sorting_desc") 
                {
                    if (a[1] < b[1]) return 1;
                    if (a[1] > b[1]) return -1;
                }
                break;

            case "age":
                if(sortPattern === "sorting_asc") 
                {
                    if (a[2] > b[2]) return 1;
                    if (a[2] < b[2]) return -1;
                }
                else if(sortPattern === "sorting_desc") 
                {
                    if (a[2] < b[2]) return 1;
                    if (a[2] > b[2]) return -1;
                }
                break;

            case "item":
                if(sortPattern === "sorting_asc") 
                {
                    if (a[3] > b[3]) return 1;
                    if (a[3] < b[3]) return -1;
                }
                else if(sortPattern === "sorting_desc") 
                {
                    if (a[3] < b[3]) return 1;
                    if (a[3] > b[3]) return -1;
                }
                break;

            default:
                break
        }
    });
}


```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727564/14727800-ea03-080f-9cb3-cbf90b500a4b.png)


<a id="#Chapter4"></a>
# 終わり
ここだけの話、datatableにはrowGroupって名前の機能が２つあります。
また、会おうdatatable

以上です。
ありがとうございました。