/* Coffermap state page: sort/search the county table, CSV, live top contractors per county. © 2026 CyberMax. All rights reserved. */ (function () { 'use strict'; var main = document.querySelector('main'), ST = main.dataset.state, FY = +main.dataset.fy; var tb = document.querySelector('#t tbody'), rows = Array.prototype.slice.call(tb.rows); var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }; document.getElementById('q').addEventListener('input', function (e) { var q = FF.norm(e.target.value); rows.forEach(function (r) { r.hidden = q && FF.norm(r.cells[0].textContent).indexOf(q) < 0; }); }); var dir = {}; document.querySelectorAll('#t th[data-k]').forEach(function (th) { th.style.cursor = 'pointer'; th.onclick = function () { var k = +th.dataset.k; dir[k] = !dir[k]; rows.sort(function (a, b) { var x = a.cells[k], y = b.cells[k]; var r = k === 0 ? x.textContent.localeCompare(y.textContent) : (+x.dataset.v) - (+y.dataset.v); return dir[k] ? (k === 0 ? r : -r) : (k === 0 ? -r : r); }); rows.forEach(function (r) { tb.appendChild(r); }); }; }); document.getElementById('csv').onclick = function () { var data = rows.map(function (r) { return { fips: r.dataset.fips, county: r.cells[0].textContent, state: ST, contracts_usd: r.cells[1].dataset.v, grants_usd: r.cells[2].dataset.v, population: r.cells[3].dataset.v }; }); var a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([FF.toCsv(data, ['fips', 'county', 'state', 'contracts_usd', 'grants_usd', 'population'])], { type: 'text/csv' })); a.download = 'coffermap-' + ST.toLowerCase() + '-fy' + FY + '.csv'; document.body.appendChild(a); a.click(); a.remove(); }; var det = document.getElementById('detail'); tb.addEventListener('click', function (e) { var b = e.target.closest('button[data-county]'); if (!b) return; var tr = b.closest('tr'), name = tr.cells[0].textContent; det.hidden = false; det.innerHTML = '

Top contractors in ' + esc(name) + ', ' + ST + ' (FY' + FY + ')

Asking USAspending.gov… this can take up to a minute.

'; det.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); fetch('https://api.usaspending.gov/api/v2/search/spending_by_category/recipient/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(FF.countyTopBody(ST, b.dataset.county, FY, 10)) }) .then(function (r) { if (!r.ok) throw new Error('USAspending returned ' + r.status); return r.json(); }) .then(function (d) { var list = (d.results || []).map(function (x) { return '
  • ' + esc(FF.titleCase(x.name)) + ' ' + FF.money(x.amount) + '
  • '; }).join(''); det.innerHTML = '

    Top contractors in ' + esc(name) + ', ' + ST + ' (FY' + FY + ')

    ' + (list ? '
      ' + list + '
    ' : '

    No contract awards reported for this county.

    ') + '

    Live from USAspending.gov, place of performance. Obligations can be negative after de-obligations.

    '; }) .catch(function (err) { det.innerHTML = '

    Could not reach USAspending.gov (' + esc(err.message) + '). Try again.

    '; }); }); })();