checkboxをページ間で保持する。

## はじめに
checkboxをページ間で保持する場合のイメージを記載する。

## 内容
以下javascriptで行う。
・ボタンを動的に作成
・チェックボックスを動的に作成
・ページ送り時のチェックボックスの保持
・ボタン押すと、checkした箇所のidを取得する

## 以下を考慮
ページ送りで以下が発生する。
・チェックしたものが戻るとチェックされていない
・ボタン、チェックボックスが増える。

そのために以下を行う。
・チェックボックスをページ送りで保持する方法として「セッションストレージ」を使用。
・作成のタイミングを考慮

jsでボタン等作成する時、
複雑な箇所はinnerHTMLで行えばよい
```
     tr.innerHTML = `<td>${i + 1}</td><td class="checkbox-cell"></td>`;
```
ただし、要素を直接操作するばあい、document.createElement などを使用する。
以下をベースに付与していく
```
       var checkbox = document.createElement('input');
```
チェックボックスを変更したときという処理ができる。
checkbox.addEventListener('change', function(e){});


## ソース例
実際に動かさないと理解できない場合、以下を動かしてみる。
```index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>チェックボックスのサンプル</title>
    <style>
        .hidden {
            display: none;
        }
    </style>
</head>

<body>
   <!-- IDを取得するボタン -->
    <table>
        <thead>
            <tr>
                <th>ID</th>
                <th>チェックボックス</th>
            </tr>
        </thead>
        <tbody>
            <!-- JavaScriptでデータを動的に挿入 -->
        </tbody>
    </table>

    <button id="prevButton">前へ</button>
    <button id="nextButton">次へ</button>

    <script src="script.js"></script>

</body>

</html>
```

```script.js
const itemsPerPage = 15;
let currentPage = 1;
let totalPages = 4; // 50件を20件ずつ表示するためのページ数


//ただのメモ
const now = new Date();
const y = now.getFullYear().toString().slice(-2);
const m = ('0' + (now.getMonth() + 1)).slice(-2);
const d = ('0' + now.getDate()).slice(-2);
const H = ('0' + now.getHours()).slice(-2);
const i = ('0' + now.getMinutes()).slice(-2);
const s = ('0' + now.getSeconds()).slice(-2);

const formattedDate = `${y}${m}${d}_${H}${i}${s}`;
console.log(formattedDate);

function renderPage(page) {
    const tbody = document.querySelector('tbody');
    tbody.innerHTML = ''; // 既存のデータをクリア

    const start = (page - 1) * itemsPerPage;
    const end = start + itemsPerPage;

    for (let i = start; i < end && i < 50; i++) {
        const tr = document.createElement('tr');
        tr.innerHTML = `<td>${i + 1}</td><td class="checkbox-cell"></td>`;
        tbody.appendChild(tr);
    }

    // 一覧画面のチェックボックスの処理
    var checkboxCells = document.querySelectorAll('.checkbox-cell');
    
    checkboxCells.forEach(function(cell, index) {
        var checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.className = 'customCheckbox';

        var recordId = cell.parentElement.querySelector('td:first-child').textContent;
        checkbox.dataset.recordId = recordId;

        var storedState = sessionStorage.getItem('checkbox-' + recordId);
        if (storedState === null) {
            checkbox.checked = false;
        } else {
            checkbox.checked = (storedState === 'true');
        }

        checkbox.addEventListener('change', function(e) {
            sessionStorage.setItem('checkbox-' + e.target.dataset.recordId, e.target.checked);
        });

        cell.appendChild(checkbox);
    });
}
window.addEventListener('beforeunload', function() {
  sessionStorage.clear();
});

document.getElementById('prevButton').addEventListener('click', function() {
    if (currentPage > 1) {
        currentPage--;
        renderPage(currentPage);
    }
});

document.getElementById('nextButton').addEventListener('click', function() {
    if (currentPage < totalPages) {
        currentPage++;
        renderPage(currentPage);
    }
});


/// ボタンを動的に作成する関数
function createGetCheckedIdsButton() {
    const btn = document.createElement("button");
    btn.innerHTML = "チェックされたIDを取得";
    btn.id = "getCheckedIds";

    btn.addEventListener("click", function() {
        const checkedIds = [];

        // セッションストレージのキーをループして、'checkbox-'で始まるキーを検索
        for (let i = 0; i < sessionStorage.length; i++) {
            const key = sessionStorage.key(i);
            if (key.startsWith('checkbox-') && sessionStorage.getItem(key) === 'true') {
                const recordId = key.replace('checkbox-', '');
                checkedIds.push(recordId);
            }
        }

        console.log(checkedIds);
        alert('チェックされたID: ' + checkedIds.join(', '));
    });

    document.body.insertBefore(btn, document.querySelector('table'));
}

// ページが読み込まれたときの処理
window.onload = function() {
   createGetCheckedIdsButton();
  // セッションストレージのデータを全て削除
  sessionStorage.clear();

  // ... その他の処理 ...
};

// 初期表示
renderPage(currentPage);

document.getElementById('getCheckedIds').addEventListener('click', function() {
  // const checkedCheckboxes = document.querySelectorAll('input.customCheckbox:checked');
  // const checkedIds = [];

  // checkedCheckboxes.forEach(function(checkbox) {
  //     checkedIds.push(checkbox.dataset.recordId);
  // });
  const checkedIds = [];

  // セッションストレージのキーをループして、'checkbox-'で始まるキーを検索
  for (let i = 0; i < sessionStorage.length; i++) {
      const key = sessionStorage.key(i);
      if (key.startsWith('checkbox-') && sessionStorage.getItem(key) === 'true') {
          const recordId = key.replace('checkbox-', '');
          checkedIds.push(recordId);
      }
  }

  console.log(checkedIds);
  alert('チェックされたID: ' + checkedIds.join(', '));
});


```
## その他メモ
kintoneの場合
ボタン、チェックボタンが増えないようにする。
・id、classを付与し、同じものがあれば処理を進めないようにする。

```javascript
kintone.events.on('app.record.index.show', function(event) {
    const btn = createGetCheckedIdsButton(event);
    document.body.insertBefore(btn, document.querySelector('table'));
    createCheckboxInTable();
    sessionStorage.clear();

    return event;
});

function createGetCheckedIdsButton(event) {
    if (document.getElementById("getCheckedIds")) {
        return; // ボタンがすでに存在する場合は関数を終了
    }

    const btn = document.createElement("button");
    btn.innerHTML = "チェックされたIDを取得";
    btn.id = "getCheckedIds";

    btn.addEventListener("click", function() {
        const checkedIds = [];

        for (let i = 0; i < sessionStorage.length; i++) {
            const key = sessionStorage.key(i);
            if (key.startsWith('checkbox-') && sessionStorage.getItem(key) === 'true') {
                const recordId = key.replace('checkbox-', '');
                checkedIds.push(recordId);
            }
        }

        console.log(checkedIds);
        alert('チェックされたID: ' + checkedIds.join(', '));
    });

    return btn;
}

function createCheckboxInTable() {
    let table = document.getElementsByClassName("recordlist-data")[0];
    
    // 既にヘッダーにチェックボックス部分があるか確認
    if (!table.tHead.querySelector('.custom-checkbox-header')) {
        let headerCell = document.createElement('th');
        headerCell.className = 'recordlist-header-cell custom-checkbox-header'; // クラスを追加
        headerCell.style.width = '30px';
        headerCell.appendChild(document.createTextNode('チェックボックス'));
        table.tHead.insertBefore(headerCell, table.tHead.children[1]);
    }

    for (let i = 0; i < table.rows.length; i++) {
        if (table.tBodies[0].rows[i].querySelector('.custom-checkbox-cell')) {
            continue; // 既にチェックボックスが存在する行はスキップ
        }

        let recordId = table.tBodies[0].rows[i].querySelector('.recordlist-cell').textContent;
        let cell = table..tBodies[0].rows[i].insertCell(1);
        cell.className = 'recordlist-cell custom-checkbox-cell'; // クラスを追加

        let checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.value = '0';
        
        let storedState = sessionStorage.getItem('checkbox-' + recordId);
        checkbox.checked = (storedState === 'true');

        checkbox.addEventListener('change', function() {
            sessionStorage.setItem('checkbox-' + recordId, this.checked);
        });

        let wrapper = document.createElement('div');
        wrapper.style.textAlign = 'center';
        wrapper.appendChild(checkbox);
        cell.appendChild(wrapper);
    }
}


```

ボタンが複数の時の対応
```javascript
function createButton(buttonId, buttonText, actionFunction, kintoneEvent) {
    const btn = document.createElement("button");
    btn.id = buttonId;
    btn.innerHTML = buttonText;
    btn.addEventListener("click", function(clickEvent) {
        actionFunction(clickEvent, kintoneEvent);  // kintoneのイベントも引数として渡す
    });
    document.body.insertBefore(btn, document.querySelector('table'));
}

// ボタンをクリックしたときの動作を定義
function actionForButton1(clickEvent, kintoneEvent) {
    // ここでclickEventとkintoneEventを使用する
    // 例えば、kintoneEventの中の情報や、clickEventの情報を使って処理を行う
}

function actionForButton2() {
    console.log('ボタン2がクリックされました');
    // その他の処理...
}

function actionForButton3() {
    console.log('ボタン3がクリックされました');
    // その他の処理...
}

// ボタンの作成
// kintoneのイベントハンドラ
kintone.events.on('app.record.index.show', function(event) {
    createButton("button1", "ボタン1のテキスト", actionForButton1, event);
    createButton("button2", "ボタン2のテキスト", actionForButton2);
    createButton("button3", "ボタン3のテキスト", actionForButton3);
    return event;
});


```