Skip to content

Instantly share code, notes, and snippets.

@simonw
Last active August 14, 2023 21:51
Show Gist options
  • Save simonw/d1c1c4ec33914b0f68bf3e55a5104d65 to your computer and use it in GitHub Desktop.
Save simonw/d1c1c4ec33914b0f68bf3e55a5104d65 to your computer and use it in GitHub Desktop.

Prepend Checkbox to Table

2023-03-30 02:11:30

user: JavaScript to prepend a to the first table cell in each row of a table


assistant: To prepend an <input type="checkbox"> to the first table cell in each row of a table, you can use the following JavaScript code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Prepend Checkbox to Table Rows</title>
</head>
<body>
    <table id="myTable">
        <tr>
            <td>Row 1 Cell 1</td>
            <td>Row 1 Cell 2</td>
        </tr>
        <tr>
            <td>Row 2 Cell 1</td>
            <td>Row 2 Cell 2</td>
        </tr>
    </table>

    <script>
        function prependCheckboxes() {
            const table = document.getElementById('myTable');
            const rows = table.getElementsByTagName('tr');

            for (let i = 0; i < rows.length; i++) {
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';

                const firstCell = rows[i].cells[0];
                firstCell.insertBefore(checkbox, firstCell.firstChild);
            }
        }

        prependCheckboxes();
    </script>
</body>
</html>

This code first selects the table element with the ID "myTable". Then, it loops through all the rows and creates a new checkbox input element. The checkbox is inserted as the first child of the first cell in each row.


user: Only output the JavaScript code. Add code that sets it up to holding shift and clicking a box selects all other boxes between the clicked box and the previously selected one


assistant: Here's the JavaScript code to prepend a checkbox to the first table cell in each row and to set up the Shift+Click functionality to select all checkboxes between the clicked one and the previously selected one:

const table = document.getElementById('myTable');
const rows = table.getElementsByTagName('tr');
let lastChecked = null;

function prependCheckboxes() {
  for (let i = 0; i < rows.length; i++) {
    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.addEventListener('click', handleCheckboxClick);

    const firstCell = rows[i].cells[0];
    firstCell.insertBefore(checkbox, firstCell.firstChild);
  }
}

function handleCheckboxClick(e) {
  const checkbox = e.target;
  let inBetween = false;

  if (e.shiftKey && checkbox.checked && lastChecked) {
    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      const currentCheckbox = row.cells[0].querySelector('input[type="checkbox"]');

      if (currentCheckbox === checkbox || currentCheckbox === lastChecked) {
        inBetween = !inBetween;
      }

      if (inBetween) {
        currentCheckbox.checked = true;
      }
    }
  }

  if (checkbox.checked) {
    lastChecked = checkbox;
  } else if (lastChecked === checkbox) {
    lastChecked = null;
  }
}

prependCheckboxes();

First, this code appends a checkbox to the first cell of each row in the table. Then, it adds an event listener to the checkboxes for handling the click event. The handleCheckboxClick function checks if the Shift key was pressed and if the clicked checkbox is checked, and if there is a previously selected checkbox. If these conditions are met, the function iterates through the rows, selecting all the checkboxes between the clicked one and the previously selected one. It also updates the lastChecked variable, which keeps track of the last selected checkbox.


user: Make it so the very first checkbox behaves differently: when checked, it checks ALL other boxes - when unchecked it unchecks them all


assistant: Here's the updated JavaScript code to make the first checkbox behave differently, checking or unchecking all other checkboxes when clicked:

const table = document.getElementById('myTable');
const rows = table.getElementsByTagName('tr');
let lastChecked = null;

function prependCheckboxes() {
  for (let i = 0; i < rows.length; i++) {
    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';

    if (i === 0) {
      checkbox.addEventListener('click', handleFirstCheckboxClick);
    } else {
      checkbox.addEventListener('click', handleCheckboxClick);
    }

    const firstCell = rows[i].cells[0];
    firstCell.insertBefore(checkbox, firstCell.firstChild);
  }
}

function handleFirstCheckboxClick(e) {
  const mainCheckbox = e.target;
  const checkAll = mainCheckbox.checked;

  for (let i = 1; i < rows.length; i++) {
    const row = rows[i];
    const currentCheckbox = row.cells[0].querySelector('input[type="checkbox"]');
    currentCheckbox.checked = checkAll;
  }
}

function handleCheckboxClick(e) {
  const checkbox = e.target;
  let inBetween = false;

  if (e.shiftKey && checkbox.checked && lastChecked) {
    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      const currentCheckbox = row.cells[0].querySelector('input[type="checkbox"]');

      if (currentCheckbox === checkbox || currentCheckbox === lastChecked) {
        inBetween = !inBetween;
      }

      if (inBetween) {
        currentCheckbox.checked = true;
      }
    }
  }

  if (checkbox.checked) {
    lastChecked = checkbox;
  } else if (lastChecked === checkbox) {
    lastChecked = null;
  }
}

prependCheckboxes();

In this updated code, the prependCheckboxes function now checks if the current row is the first row (using i === 0). If it is, the handleFirstCheckboxClick event listener is added to the checkbox, otherwise the handleCheckboxClick event listener is added.

The handleFirstCheckboxClick function is responsible for checking or unchecking all other checkboxes when the first checkbox is clicked. It iterates through all the rows, starting from the second row, and sets the checked property of the checkboxes to the same value as the first checkbox's checked property.


user:

const table = document.querySelector('table');
const rows = table.getElementsByTagName('tr');
let lastChecked = null;

function prependCheckboxes() {
  for (let i = 0; i < rows.length; i++) {
    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.style.marginRight = '8px';

    if (i === 0) {
      checkbox.addEventListener('click', handleFirstCheckboxClick);
    } else {
      checkbox.addEventListener('click', handleCheckboxClick);
    }

    const firstCell = rows[i].cells[0];
    firstCell.insertBefore(checkbox, firstCell.firstChild);
  }
}

function handleFirstCheckboxClick(e) {
  const mainCheckbox = e.target;
  const checkAll = mainCheckbox.checked;

  for (let i = 1; i < rows.length; i++) {
    const row = rows[i];
    const currentCheckbox = row.cells[0].querySelector('input[type="checkbox"]');
    currentCheckbox.checked = checkAll;
  }
}

function handleCheckboxClick(e) {
  const checkbox = e.target;
  let inBetween = false;

  if (e.shiftKey && checkbox.checked && lastChecked) {
    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      const currentCheckbox = row.cells[0].querySelector('input[type="checkbox"]');

      if (currentCheckbox === checkbox || currentCheckbox === lastChecked) {
        inBetween = !inBetween;
      }

      if (inBetween) {
        currentCheckbox.checked = true;
      }
    }
  }

  if (checkbox.checked) {
    lastChecked = checkbox;
  } else if (lastChecked === checkbox) {
    lastChecked = null;
  }
}

prependCheckboxes();

Modify the above code to also add a textarea to the page directly above the table. The textarea should display a JSON array of values corresponding to the checked checkboxes - those values are the innerText content of the table cell each checkbox is contained within


assistant: Here's the modified code that adds a textarea above the table and updates it with a JSON array of values corresponding to the checked checkboxes:

const table = document.querySelector('table');
const rows = table.getElementsByTagName('tr');
let lastChecked = null;

function prependCheckboxes() {
  for (let i = 0; i < rows.length; i++) {
    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.style.marginRight = '8px';

    if (i === 0) {
      checkbox.addEventListener('click', handleFirstCheckboxClick);
    } else {
      checkbox.addEventListener('click', handleCheckboxClick);
    }

    const firstCell = rows[i].cells[0];
    firstCell.insertBefore(checkbox, firstCell.firstChild);
  }
}

function handleFirstCheckboxClick(e) {
  const mainCheckbox = e.target;
  const checkAll = mainCheckbox.checked;

  for (let i = 1; i < rows.length; i++) {
    const row = rows[i];
    const currentCheckbox = row.cells[0].querySelector('input[type="checkbox"]');
    currentCheckbox.checked = checkAll;
  }

  updateTextarea();
}

function handleCheckboxClick(e) {
  const checkbox = e.target;
  let inBetween = false;

  if (e.shiftKey && checkbox.checked && lastChecked) {
    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      const currentCheckbox = row.cells[0].querySelector('input[type="checkbox"]');

      if (currentCheckbox === checkbox || currentCheckbox === lastChecked) {
        inBetween = !inBetween;
      }

      if (inBetween) {
        currentCheckbox.checked = true;
      }
    }
  }

  if (checkbox.checked) {
    lastChecked = checkbox;
  } else if (lastChecked === checkbox) {
    lastChecked = null;
  }

  updateTextarea();
}

function createTextarea() {
  const textarea = document.createElement('textarea');
  textarea.rows = 5;
  textarea.style.width = '100%';
  textarea.style.marginBottom = '16px';
  table.parentNode.insertBefore(textarea, table);
  return textarea;
}

function updateTextarea() {
  const checkedValues = [];

  for (let i = 1; i < rows.length; i++) {
    const row = rows[i];
    const currentCheckbox = row.cells[0].querySelector('input[type="checkbox"]');
    if (currentCheckbox.checked) {
      checkedValues.push(row.cells[0].innerText);
    }
  }

  textarea.value = JSON.stringify(checkedValues, null, 2);
}

const textarea = createTextarea();
prependCheckboxes();

The createTextarea function creates a textarea element, sets its rows, width, and margin properties, and inserts it before the table element. The updateTextarea function iterates through the rows, skipping the first row, and creates an array of the checked checkboxes' corresponding table cell text values. It then updates the textarea value with the JSON-formatted array of checked values.

The handleCheckboxClick and handleFirstCheckboxClick functions are updated to call updateTextarea to refresh the textarea content whenever a checkbox is clicked.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment