datatableでCSVダウンロードボタンを検索要素の隣に配置する

# 完成系

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="jOoaRaW" data-pen-title="Untitled" data-user="10JII_K" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/10JII_K/pen/jOoaRaW">
  Untitled</a> by 10K (<a href="https://codepen.io/10JII_K">@10JII_K</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

:::note
おことわり

jQueryは必要最低限で利用します。

使用ライブラリ
- **jQuery v3.7.1**
- **datatables v2.0.8**
- **datatables Buttons v3.0.2**
:::

# 説明
### ボタンを作る
以下のCDNが必要になります。
```text: linkとかで入れる
https://code.jquery.com/jquery-3.7.1.js
https://cdn.datatables.net/2.0.8/js/dataTables.js
https://cdn.datatables.net/buttons/3.0.2/js/dataTables.buttons.min.js
https://cdn.datatables.net/buttons/3.0.2/js/buttons.html5.min.js
https://cdn.datatables.net/buttons/3.0.2/js/buttons.print.min.js
https://cdn.datatables.net/buttons/3.0.2/js/buttons.colVis.min.js // <- これいらないかも
```

### datatablesのインスタンス化
```javascript:ついでに日本語対応もする
// テーブルの初期化
const table = new DataTable('#datatables', {
  language: {
    url: "https://cdn.datatables.net/plug-ins/2.0.7/i18n/ja.json"
  },
});
```
datatablesは、上下左右の角に検索ボックスやページネーションなどの機能を配置できますが、左上のスペースにボタンを配置するなら、以下のようになります。

```javascript:コピーボタンを追加
const table = new DataTable('#datatables', {
  language: {
    url: "https://cdn.datatables.net/plug-ins/2.0.7/i18n/ja.json"
  },
  layout: {
    topStart: {
      buttons: [
        'csv'
      ]
    }
  }
});
```
![スクリーンショット 2024-06-15 1.02.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/0abe571d-7f30-e9c0-99eb-a1baa84d4e82.png)

### ボタンをインスタンス化によって作るようにする
しかし上記のインスタンスプロパティを指定する方法では位置調整ができないです。
なので、datatablesの拡張機能 `DataTable.Buttons` を使用して、ボタンをインスタンス化する方法で調整します。
```javascript:DataTable.Buttons
const buttons = new DataTable.Buttons(table, {
  buttons: [
    {
      extend: 'csv',
      text: 'CSVダウンロード',
    }
  ]
});
```

### ボタンを配置する
`DataTable.Buttons` を使用してインスタンス化したボタンは、`buttons().container()` APIを使って、テーブルの付近（上下左右）以外にも配置できます。もちろん、上下左右の細かい配置も可能です。
ボタンのDOM要素を取得して、挿入したい場所に要素を挿入しましょう。ついでにボタンを横並びにするためのCSSを適応しましょう。

```javascript:テーブルのCSSを変更し、検索ボックスの左にボタンを挿入する
table.buttons().container().css({
    'display':'inline-block',
    'margin-right':'8px'
  }).insertBefore('div.dt-search > label');
```

しかしこの設定をしてもボタンは表示されません。

![スクリーンショット 2024-06-15 1.53.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/c27fe222-e71a-16e9-1123-3e9428478536.png)

### init.dt イベントの完了後にボタンを挿入する
テーブルが完全に初期化され、データがロードされ、描画された後のタイミングでないと、テーブルにボタンを挿入することができません。（もともと `<table>...</table>` 要素しかないですしね）。
なので、全ての初期化、描画タイミングが終わったことを検知するイベント `init.dt` を使用して、ボタンを挿入したい位置に挿入しましょう。

```javascript:init.dtで初期化検知する
table.on('init.dt', function() {
  table.buttons().container().css({
    'display':'inline-block',
    'margin-right':'8px'
  }).insertBefore('div.dt-search > label');
});
```

![スクリーンショット 2024-06-15 2.03.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/117fa90d-7d57-c4cc-e459-84fc801b3193.png)

これによって、表題の要件を満たすことができました。