i2psnark/res/js/togglePriorities.js

/**
 * @module togglePriorities
 * @file togglePriorities.js - Toggle file download priorities for all displayed files in I2PSnark.
 * @description Adds a toggle row to the file directory header that allows bulk toggling of
 * download priority (high/skip) for all incomplete files. Supports mutual exclusion between
 * priority levels and falls back to normal priority when all toggles are unchecked.
 * @author dr|z3d
 * @license AGPL3 or later
 */

document.addEventListener("DOMContentLoaded", function() {
  const dirNav = document.getElementById("dirNav");
  const headerRow = dirNav ? document.querySelector("#dirInfo tbody tr:first-child") : document.querySelector("#dirInfo thead tr:last-child");
  const incomplete = document.querySelectorAll("#dirInfo tr.incomplete").length;
  if (!incomplete || incomplete < 2) {return;}
  const priorityColumn = document.querySelector("#dirInfo td.priority");
  const columns = ["prihigh", "priskip"];
  const toggleRow = headerRow.cloneNode(false);
  const thSpacer = document.createElement("th");
  const thToggle = document.createElement("th");
  toggleRow.removeAttribute("class");
  toggleRow.id = "togglePriorities";
  thSpacer.setAttribute("colspan", "4");

  columns.forEach(function(column, index) {
    const toggleId = `toggle-${column}`;
    const toggle = document.createElement("input");
    const label = document.createElement("label");
    toggle.type = "checkbox";
    toggle.id = toggleId;
    toggle.style.opacity = "0";
    label.setAttribute("for", toggleId);
    label.appendChild(toggle);
    thToggle.appendChild(label);
  });

  const style = document.createElement("style");
  style.textContent = '#togglePriorities label{height:24px;width:50%;display:inline-block;vertical-align:middle;background:url(/i2psnark/.res/icons/clock_red.png) no-repeat 30% center/18px;cursor:pointer;mix-blend-mode:luminosity}#togglePriorities label[for="toggle-priskip"]{background:url(/i2psnark/.res/icons/block.png) no-repeat 60% center/18px}#togglePriorities label:hover{background-size:22px;mix-blend-mode:normal}';
  document.head.appendChild(style);
  toggleRow.appendChild(thToggle);
  toggleRow.insertBefore(thSpacer, thToggle);
  headerRow.parentNode.insertBefore(toggleRow, headerRow.nextSibling);

  document.body.addEventListener("click", function(event) {
      const target = event.target;
      if (target.matches("input[type='checkbox'][id^='toggle-']")) {
        const toggleId = target.id;
        const column = toggleId.substr(7);
        const radios = document.querySelectorAll(`#dirInfo .${column}`);
        const normalPriority = document.querySelectorAll("#dirInfo .prinorm");
        let allChecked = true;
        radios.forEach(function(radio) {
          if (!radio.checked) {allChecked = false;}
        });
        if (allChecked) {
          radios.forEach(function(radio) {radio.checked = false;});
          normalPriority.forEach(function(radio) {radio.checked = true;});
        } else {
          radios.forEach(function(radio) {radio.checked = target.checked;});
        }
        const checkedToggles = document.querySelectorAll("#dirInfo input[type=checkbox]:checked");
        if (checkedToggles.length === 0) {
          normalPriority.forEach(function(radio) {radio.checked = true;});
        }
        if (target.checked) {
          columns.forEach(function(col) {
            if (col !== column) {
              const otherToggle = document.getElementById(`toggle-${col}`);
              if (otherToggle) {otherToggle.checked = false;}
              document.querySelectorAll(`#dirInfo .${col}`).forEach(function(radio) {radio.checked = false;});
            }
          });
        }
      }
  });
});