Focus manangement and live region

Recipe 10.2 Filter the data

Sample:

Records

Filter

Country
Shipping

Results

Showing 40 of 40 records
  1. Bambule (1998) Absolute Beginner
  2. Very proud of ya (1996) AFI
  3. All Hollows EP (1999) AFI
  4. Die große Palmöllüge (2020) Akne Kid Joe
  5. Suffer (1988) Bad Religion
  6. Age of Unreason (2019) Bad Religion
  7. Licensed to Ill (1986) Beastie Boys
  8. Paul's Boutique (1989) Beastie Boys
  9. Check Your Head (1992) Beastie Boys
  10. Ill Communication (1994) Beastie Boys
  11. Hello Nasty (1998) Beastie Boys
  12. The Mix-Up (2007) Beastie Boys
  13. To the 5 Boroughs (2004) Beastie Boys
  14. Solid Gold Hits (2005) Beastie Boys
  15. Hot Sauce Committee Part Two (2011) Beastie Boys
  16. Magic Life (2017) Bilderbuch
  17. Piano Man (1973) Billy Joel
  18. Turnstiles (1976) Billy Joel
  19. 52nd Street (1978) Billy Joel
  20. The Stranger (1977) Billy Joel
  21. Songs in the Attic (1981) Billy Joel
  22. Post Human: Survial Horror (2020) Bring me the Horizon
  23. Suicide Season (2008) Bring me the Horizon
  24. Da Nich Für! (2019) Dendemann
  25. Fresh Food for Rotting Vegetables (1980) Dead Kennedys
  26. Der Nino aus Wien (2018) Der Nino aus Wien
  27. Wach (2017) Der Nino aus Wien
  28. Immer noch besser als Spinat (2015) Der Nino aus Wien
  29. Unser Österreich (2015) Der Nino aus Wien
  30. All Boro Kings (1994) Dog Eat Dog
  31. 2001 (1999) Dr. Dre
  32. The Album (1977) Eater
  33. Joy as an Act of Resistance (2018) Idles
  34. Ballot Result (1986) Minutemen
  35. PUP (2014) PUP
  36. The Dream Is Over (2016) PUP
  37. Morbid Stuff (2019) PUP
  38. …and out come the wolves (1995) Rancid
  39. The Eradicator (2017) The Eradicator
  40. After The party (2017) The Menzingers

Code:

<style>
  strong {
    display: block;
  }
</style>

<h1>Records</h1>

<h2>Filter</h2>

<form role="form" aria-label="Filter" id="filter">
  <label for="artist">Artist</label>
  <select id="artist" name="artist">
    <option value="">All</option>
    <option value="afi">AFI</option>
    <option>Absolute Beginner</option>
    <option>Akne Kid Joe</option>
    <option>Bad Religion</option>
    <option>Beastie Boys</option>
    <option>Bilderbuch</option>
    <option>Billy Joel</option>
    <option>Bring me the Horizon</option>
    <option>Dead Kennedys</option>
    <option>Dendemann</option>
    <option>Der Nino aus Wien</option>
    <option>Dog Eat Dog</option>
    <option>Dr. Dre</option>
    <option>Eater</option>
    <option>Idles</option>
    <option>Minutemen</option>
    <option>PUP</option>
    <option>Rancid</option>
    <option>The Eradicator</option>
    <option>The Menzingers</option>
  </select>

  <fieldset>
    <legend>Country</legend>

    <input type="checkbox" name="country" id="country_at" value="at">
    <label for="country_at">Austria</label>

    <input type="checkbox" name="country" id="country_ca" value="ca">
    <label for="country_ca">Canada</label>

    <input type="checkbox" name="country" id="country_us" value="us">
    <label for="country_us">USA</label>

    <input type="checkbox" name="country" id="country_de" value="de">
    <label for="country_de">Germany</label>

    <input type="checkbox" name="country" id="country_uk" value="uk">
    <label for="country_uk">United Kingdom</label>
  </fieldset>

  <fieldset>
    <legend>Shipping</legend>

    <input type="radio" name="shipping" id="shipping_eu" value="eu">
    <label for="shipping_eu">Europe</label>

    <input type="radio" name="shipping" id="shipping_world" value="worldwide">
    <label for="shipping_world">Worldwide</label>

    <input type="radio" name="shipping" id="shipping_us" value="us">
    <label for="shipping_us">USA</label>
  </fieldset>

  <button>Search</button>
</form>

<div role="region" aria-labelledby="results_heading" id="results" tabindex="-1">
  <h2 id="results_heading">Results</h2>
  <div role="status">Showing 40 of 40 records</div>

  <ol>
    
      <li>
        <strong>Bambule (1998)</strong>
        Absolute Beginner
      </li>
    
      <li>
        <strong>Very proud of ya (1996)</strong>
        AFI
      </li>
    
      <li>
        <strong>All Hollows EP (1999)</strong>
        AFI
      </li>
    
      <li>
        <strong>Die große Palmöllüge (2020)</strong>
        Akne Kid Joe
      </li>
    
      <li>
        <strong>Suffer (1988)</strong>
        Bad Religion
      </li>
    
      <li>
        <strong>Age of Unreason (2019)</strong>
        Bad Religion
      </li>
    
      <li>
        <strong>Licensed to Ill (1986)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>Paul&#39;s Boutique (1989)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>Check Your Head (1992)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>Ill Communication (1994)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>Hello Nasty (1998)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>The Mix-Up (2007)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>To the 5 Boroughs (2004)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>Solid Gold Hits (2005)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>Hot Sauce Committee Part Two  (2011)</strong>
        Beastie Boys
      </li>
    
      <li>
        <strong>Magic Life (2017)</strong>
        Bilderbuch
      </li>
    
      <li>
        <strong>Piano Man (1973)</strong>
        Billy Joel
      </li>
    
      <li>
        <strong>Turnstiles (1976)</strong>
        Billy Joel
      </li>
    
      <li>
        <strong>52nd Street (1978)</strong>
        Billy Joel
      </li>
    
      <li>
        <strong>The Stranger (1977)</strong>
        Billy Joel
      </li>
    
      <li>
        <strong>Songs in the Attic (1981)</strong>
        Billy Joel
      </li>
    
      <li>
        <strong>Post Human: Survial Horror (2020)</strong>
        Bring me the Horizon
      </li>
    
      <li>
        <strong>Suicide Season (2008)</strong>
        Bring me the Horizon
      </li>
    
      <li>
        <strong>Da Nich Für! (2019)</strong>
        Dendemann
      </li>
    
      <li>
        <strong>Fresh Food for Rotting Vegetables (1980)</strong>
        Dead Kennedys
      </li>
    
      <li>
        <strong>Der Nino aus Wien (2018)</strong>
        Der Nino aus Wien
      </li>
    
      <li>
        <strong>Wach (2017)</strong>
        Der Nino aus Wien
      </li>
    
      <li>
        <strong>Immer noch besser als Spinat (2015)</strong>
        Der Nino aus Wien
      </li>
    
      <li>
        <strong>Unser Österreich (2015)</strong>
        Der Nino aus Wien
      </li>
    
      <li>
        <strong>All Boro Kings (1994)</strong>
        Dog Eat Dog
      </li>
    
      <li>
        <strong>2001 (1999)</strong>
        Dr. Dre
      </li>
    
      <li>
        <strong>The Album (1977)</strong>
        Eater
      </li>
    
      <li>
        <strong>Joy as an Act of Resistance (2018)</strong>
        Idles
      </li>
    
      <li>
        <strong>Ballot Result (1986)</strong>
        Minutemen
      </li>
    
      <li>
        <strong>PUP (2014)</strong>
        PUP
      </li>
    
      <li>
        <strong>The Dream Is Over (2016)</strong>
        PUP
      </li>
    
      <li>
        <strong>Morbid Stuff (2019)</strong>
        PUP
      </li>
    
      <li>
        <strong>…and out come the wolves (1995)</strong>
        Rancid
      </li>
    
      <li>
        <strong>The Eradicator (2017)</strong>
        The Eradicator
      </li>
    
      <li>
        <strong>After The party (2017)</strong>
        The Menzingers
      </li>
    
  </ol>
</div>

<script>
const form = document.getElementById("filter");
const results = document.getElementById("results");
const list = results.querySelector("ol");
const liveRegion = document.querySelector("[role='status']")
let records,
filtered;

function finishQuery() {
  results.focus();
  const total = records.length;
  const found = list.querySelectorAll('li').length;
  liveRegion.textContent = `Showing ${found} of ${total} records`
}

function showResults(data) {
  list.innerHTML = "";

  for (let i = 0; i < data.length; i++) {
    const record = data[i];
    const item = document.createElement("li");
    const title = document.createElement("strong");
    title.textContent = `${record.title} (${record.year})`;
    item.append(title, record.artist);
    list.append(item);
  }
}

function filterForm(e) {
  e.preventDefault();

  const formData = new FormData(form);

  filtered = records.filter((record) => {
    const artist = formData.get("artist");
    const countries = formData.getAll("country");
    const shipping = formData.getAll("shipping");

    if (artist && record.artist !== artist) {
      return;
    }

    if (countries.length && !countries.includes(record.country)) {
      return;
    }

    if (shipping.length && !shipping.includes(record.shipping)) {
      return;
    }

    return true;
  });

  showResults(filtered);
  finishQuery();
}

async function getRecords() {
  const response = await fetch("/assets/data/records.json");
  return await response.json();
}

getRecords().then((data) => {
  records = data;
  filtered = data;
  
  form.addEventListener("submit", filterForm);
});
</script>