<div class="wrapper">
  <h1>Bitwise Calculator</h1>
  <p>Bitwise calculations convert human-readable base-10 integers into machine-readable base-2 (binary) values. They then compare each bit according to an operator and convert the result back to base-10.</p>
  <p>The operators are "&" (and), "|" (or), and "^" (exclusive or).</p>
  <p>You can imagine the operators working like light switches:</p>
  <ul>
    <li>& = both switches in the "on" position turns the light on</li>
    <li>| = either switch in the "on" position turns the light on</li>
    <li>^ = one switch "on" and one switch "off" turns the light on</li>
  </ul>
  <p>The statuses and bit flags below come from <a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition">Node.compareDocumentPosition()</a></p>
  <table>
    <thead>
      <tr>
        <th>Status</th>
        <th>Bit Flag</th>
        <th>Value 1</th>
        <th></th>
        <th>Value 2</th>
        <th></th>
        <th>Output</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>DISCONNECTED</td>
        <td>1</td>
        <td><input type="checkbox" column="value1"></td>
        <td></td>
        <td><input type="checkbox" column="value2"></td>
        <td></td>
        <td><input type="checkbox" column="output" inert></td>
      </tr>
      <tr>
        <td>PRECEDING</td>
        <td>2</td>
        <td><input type="checkbox" column="value1"></td>
        <td></td>
        <td><input type="checkbox" column="value2"></td>
        <td></td>
        <td><input type="checkbox" column="output" inert></td>
      </tr>
      <tr>
        <td>FOLLOWING</td>
        <td>4</td>
        <td><input type="checkbox" column="value1"></td>
        <td></td>
        <td><input type="checkbox" column="value2"></td>
        <td></td>
        <td><input type="checkbox" column="output" inert></td>
      </tr>
      <tr>
        <td>CONTAINS</td>
        <td>8</td>
        <td><input type="checkbox" column="value1"></td>
        <td></td>
        <td><input type="checkbox" column="value2"></td>
        <td></td>
        <td><input type="checkbox" column="output" inert></td>
      </tr>
      <tr>
        <td>CONTAINED BY</td>
        <td>16</td>
        <td><input type="checkbox" column="value1"></td>
        <td></td>
        <td><input type="checkbox" column="value2"></td>
        <td></td>
        <td><input type="checkbox" column="output" inert></td>
      </tr>
      <tr>
        <td>IMPLEMENTATION<br />SPECIFIC</td>
        <td>32</td>
        <td><input type="checkbox" column="value1"></td>
        <td></td>
        <td><input type="checkbox" column="value2"></td>
        <td></td>
        <td><input type="checkbox" column="output" inert></td>
      </tr>
    </tbody>
    <tfoot>
      <tr>
        <td></td>
        <td></td>
        <td><input type="number" name="value1" id="value1"></td>
        <td>
          <select name="operator" id="operator">
            <option value="&">&</option>
            <option value="|">|</option>
            <option value="^">^</option>
          </select>
        </td>
        <td><input type="number" name="value2" id="value2"></td>
        <td>=</td>
        <td><input type="number" name="output" id="output" inert></td>
      </tr>
    </tfoot>
  </table>
</div>
.wrapper {
  max-width: 600px;
  margin: 0 auto;
  padding: 1rem;
}

table {
  border-collapse: collapse;
  border: 1px solid #bbb;
  box-shadow: 0 0.75rem 1.5rem #aaa;
  margin-top: 2rem;
}

td,
th {
  padding: 0.25rem 0.5rem;
  text-align: center;

  &:first-child,
  &:nth-child(2) {
    text-align: left;
  }
}

td:nth-child(-n + 2) {
  font-family: monospace;
  font-size: 1rem;
}

th,
tr:nth-child(even) {
  background-color: #ddd;
}

input[type="number"],
select {
  width: 7ch;
  text-align: center;
}
View Compiled
console.clear();

const checkboxes = {
  all: document.querySelectorAll('input[type="checkbox"][column^="value"]'),
  value1: document.querySelectorAll('input[type="checkbox"][column="value1"]'),
  value2: document.querySelectorAll('input[type="checkbox"][column="value2"]'),
  output: document.querySelectorAll('input[type="checkbox"][column="output"]')
};

const inputs = {
  all: document.querySelectorAll('input[type="number"], select'),
  value1: document.querySelector("#value1"),
  operator: document.querySelector("#operator"),
  value2: document.querySelector("#value2"),
  output: document.querySelector("#output")
};

// Limit to 6 bits since we only go to 32.
const maxBits = 6;

checkboxes.all.forEach((checkbox) =>
  checkbox.addEventListener("input", updateForm)
);

inputs.all.forEach((input) =>
  input.addEventListener("input", updateCheckboxes)
);

function updateForm() {
  const value1 = [];
  const value2 = [];

  checkboxes.value1.forEach((box) => {
    value1.push(box.checked + 0);
  });

  checkboxes.value2.forEach((box) => {
    value2.push(box.checked + 0);
  });

  inputs.value1.value = parseInt(value1.reverse().join(""), 2);
  inputs.value2.value = parseInt(value2.reverse().join(""), 2);

  setTimeout(updateCheckboxes, 0);
}

function updateCheckboxes() {
  const value1 = parseInt(inputs.value1.value) || 0;
  const value2 = parseInt(inputs.value2.value) || 0;
  const operator = inputs.operator.value;

  let output = 0;

  switch (operator) {
    case "&":
      output = value1 & value2;
      break;

    case "|":
      output = value1 | value2;
      break;

    case "^":
      output = value1 ^ value2;
      break;

    default:
      break;
  }

  inputs.output.value = output;

  const bitmask1 = value1
    .toString(2)
    .padStart(maxBits, "0")
    .split("")
    .reverse();
  const bitmask2 = value2
    .toString(2)
    .padStart(maxBits, "0")
    .split("")
    .reverse();
  const bitmask3 = output
    .toString(2)
    .padStart(maxBits, "0")
    .split("")
    .reverse();

  bitmask1.forEach((bit, i) => {
    if (i < maxBits) {
      checkboxes.value1[i].checked = parseInt(bit);
    }
  });

  bitmask2.forEach((bit, i) => {
    if (i < maxBits) {
      checkboxes.value2[i].checked = parseInt(bit);
    }
  });

  bitmask3.forEach((bit, i) => {
    if (i < maxBits) {
      checkboxes.output[i].checked = parseInt(bit);
    }
  });
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.