DataTablesは、表を扱うのにとても便利なjQueryのライブラリです。
DataTablesについては以下にまとめました。
DataTablesとjQuery UI Sortableを使うと簡単に表を作成して、行のドラッグ&ドロップが出来るようになります。
今回、
jQuery DataTablesでUI Sortableのドラッグ&ドロップした後でcell.index()を更新する方法をまとめました。
DataTablesのjQuery UI Sortableによるドラッグ&ドロップの問題点
jQuery UI Sortableを使った行のドラッグ&ドロップについて課題が2点あります。
課題 1.
ドラッグ&ドロップはJavaScriptで行っているために、ブラウザをリロードすると元に戻ってしまう。
当たり前ですが、並び順を保存しないと意味がありません。
解決するには、UI Sortableでドラッグ&ドロップ後に、サーバー側のデータベースにも結果を反映する必要があります。
課題 2.
ドラッグ&ドロップはjQuery UI Sortableで行っているために、DataTablesのcell.index()までは更新されていない。
そのため、キーボードの矢印キーイベントでフォーカス行を動かそうとすると、正しく行がフォーカスされない。
例えば、4行目を2行目にドラッグ&ドロップします。
前 → 後
1行目 → 1行目
2行目 → 4行目
3行目 → 2行目
4行目 → 3行目
5行目 → 5行目
ドラッグ&ドロップ後で、1行目を選択してキーボードの↓キーを押すと、4行目ではなくて2行目がフォーカスされます。
これはキーイベントがDataTablesのcell.index()を使っているためです。
この課題を解決するには、cell.index()を更新する必要があります。
当初は、DataTablesのRowReorderというライブラリで解決できるかと思ったのですが、無理でした。
そこで、Reorderは使わずに、これらの課題を解決したいと思います。
DataTablesでドラッグ&ドロップした後の処理改善
以下の2点を改善します。
- DataTablesでドラッグ&ドロップ後で並び順を保存する
- DataTablesでドラッグ&ドロップ後でcell.index()を更新する
各行のユニークキーと1行目から順に1から始まるソートキーを紐づけます。
各行はソートキーでソートします。
当然、データベースにもこの値を持つし、PHP側ではこの値でソートして表示します。
前 unique_key sort_key → 後 unique_key sort_key
1行目 101 1 → 1行目 101 1
2行目 102 2 → 4行目 104 2
3行目 103 3 → 2行目 102 3
4行目 104 4 → 3行目 103 4
5行目 105 5 → 5行目 105 5
HTMLのソースサンプル
1 2 3 4 5 6 7 8 9 10 11 12 |
<table id="ichiran_table" class="display" cellspacing="0" width="100%"> <tbody id="ichiran_body"> <tr> <td> </td> <td> </td> <td> </td> </tr> </tbody> </table> |
ユニークキーを3列目に入れておきます。
JavaScriptのソースサンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
ichiran_table = $('#ichiran_table').DataTable({ searching: false, paging: false, ordering: false, info: false, scrollY: 360, scrollCollapse: true, bAutoWidth: false, aoColumns: [ {sWidth: '30%'}, {sWidth: '30%'}, {sWidth: '40%'}, ], keys: { keys: [ 38 /* up */, 40 /* down */ ] } }).on( 'key-focus', function ( e, datatable, cell ) { // キーボードのイベント var row = datatable.row( cell.index().row ); ichiran_table.$('tr.selected').removeClass('selected'); $( row.node() ).addClass( "selected" ); }); $('#ichiran_body').sortable({ axis: 'y', opacity: 0.5, start: function (e, ui) { oldPosition = $("#ichiran_body tr:not(.ui-sortable-placeholder)").index($(ui.helper)); }, beforeStop: function (e, ui) { newPosition = $("#ichiran_body tr:not(.ui-sortable-placeholder)").index($(ui.helper)); }, stop: function () { //ドラッグ&ドロップ結果をサーバー側に反映する var idstrings = []; if(oldPosition == newPosition) { return; } $("tr", "#ichiran_body").each(function (i, item) { var id = item.cells[2].innerHTML; //ユニークキー idstrings.push(id); }); $.ajax({ beforeSend: function (xhr) { return xhr.setRequestHeader('X-CSRF-TOKEN', "{{csrf_token()}}"); }, data: { "idstrings": idstrings.toString() }, type: 'POST', url: 'sorted_tb_keywords' }); //ドラッグ&ドロップ結果を元にcell.index()を更新する var ichiran_table_insertedRow = ichiran_table.row(oldPosition).data(), tempRow; if(oldPosition > newPosition) { for (var i=oldPosition; i>newPosition; i--) { tempRow = ichiran_table.row(i-1).data(); ichiran_table.row(i).data(tempRow).draw(false); } } else { for (var i=oldPosition; i<newPosition; i++) { tempRow = ichiran_table.row(i+1).data(); ichiran_table.row(i).data(tempRow).draw(false); } } ichiran_table.row(newPosition).data(ichiran_table_insertedRow).draw(false); // 動かした行を選択する var row = ichiran_table.row( newPosition ); ichiran_table.$('tr.selected').removeClass('selected'); $( row.node() ).addClass( "selected" ); } }); |
stop: function()以降が改善コードです。
この改善コードがなくても、見た目はドラッグ&ドロップできますが、サーバー側に更新された情報が反映されないために意味がありません。
ドラッグ&ドロップした後でユニークキーの入ったセルの配列を用意してサーバー側を呼び出します。
呼び出す際には、クロスサイトリクエストフォージャリトークンを付けます。
改善コードの場合、以下のURLが呼び出されるので、その関数の中で配列からユニークキー値を引き出します。
また、ドラッグ&ドロップ後のcell.index()の更新には、以下のメソッドを使用します。
ichiran_table.row(newPosition).data(ichiran_table_insertedRow).draw(false);
選択した行に値を入れるところは以下のサンプルを参考にしました。
プログラミングの無料レッスン体験
約8,000名の受講生と80社以上の導入実績のあるプログラミングやWebデザインのオンラインマンツーマンレッスンCodecamp
<Codecampの特徴>
1 現役エンジニアによる指導
2オンラインでのマンツーマン形式の講義
3大手企業にも導入されている実践的なカリキュラム
↓無料体験レッスン実施中です。
コメント