PageSourceSearch

https://www.matthewrobertballard.com/assets/js/bibsearch.js?v=1bc438ca9037884cc579601c09afd847

js matthewrobertballard.com collected 2026-09-24 11:50:40 UTC 3,096 bytes, 70 lines download raw bytes

1import { highlightSearchTerm } from "./highlight-search-term.js";
2
3document.addEventListener("DOMContentLoaded", function () {
4  // actual bibsearch logic
5  const filterItems = (searchTerm) => {
6    document.querySelectorAll(".bibliography, .unloaded").forEach((element) => element.classList.remove("unloaded"));
7
8    // highlight-search-term
9    if (CSS.highlights) {
10      const nonMatchingElements = highlightSearchTerm({ search: searchTerm, selector: ".bibliography > li" });
11      if (nonMatchingElements == null) {
12        return;
13      }
14      nonMatchingElements.forEach((element) => {
15        element.classList.add("unloaded");
16      });
17    } else {
18      // Simply add unloaded class to all non-matching items if Browser does not support CSS highlights
19      document.querySelectorAll(".bibliography > li").forEach((element, index) => {
20        const text = element.innerText.toLowerCase();
21        if (text.indexOf(searchTerm) == -1) {
22          element.classList.add("unloaded");
23        }
24      });
25    }
26
27    document.querySelectorAll("h2.bibliography").forEach(function (element) {
28      let iterator = element.nextElementSibling; // get next sibling element after h2, which can be h3 or ol
29      let hideFirstGroupingElement = true;
30      // iterate until next group element (h2), which is already selected by the querySelectorAll(-).forEach(-)
31      while (iterator && iterator.tagName !== "H2") {
32        if (iterator.tagName === "OL") {
33          const ol = iterator;
34          const unloadedSiblings = ol.querySelectorAll(":scope > li.unloaded");
35          const totalSiblings = ol.querySelectorAll(":scope > li");
36
37          if (unloadedSiblings.length === totalSiblings.length) {
38            ol.previousElementSibling.classList.add("unloaded"); // Add the '.unloaded' class to the previous grouping element (e.g. year)
39            ol.classList.add("unloaded"); // Add the '.unloaded' class to the OL itself
40          } else {
41            hideFirstGroupingElement = false; // there is at least some visible entry, don't hide the first grouping element
42          }
43        }
44        iterator = iterator.nextElementSibling;
45      }
46      // Add unloaded class to first grouping element (e.g. year) if no item left in this group
47      if (hideFirstGroupingElement) {
48        element.classList.add("unloaded");
49      }
50    });
51  };
52
53  const updateInputField = () => {
54    const hashValue = decodeURIComponent(window.location.hash.substring(1)); // Remove the '#' character
55    document.getElementById("bibsearch").value = hashValue;
56    filterItems(hashValue);
57  };
58
59  // Sensitive search. Only start searching if there's been no input for 300 ms
60  let timeoutId;
61  document.getElementById("bibsearch").addEventListener("input", function () {
62    clearTimeout(timeoutId); // Clear the previous timeout
63    const searchTerm = this.value.toLowerCase();
64    timeoutId = setTimeout(filterItems(searchTerm), 300);
65  });
66
67  window.addEventListener("hashchange", updateInputField); // Update the filter when the hash changes
68
69  updateInputField(); // Update filter when page loads
70});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.