# How to Create Filter Combinations Like Bodyweight Chest Exercises in the Exercises Dataset

> Learn to create bodyweight chest filter combinations by intersecting equipment, category, and muscle criteria programmatically or in the interactive browser for the exercises dataset.

- Repository: [Hasan Emir Yıldırım/exercises-dataset](https://github.com/hasaneyldrm/exercises-dataset)
- Tags: how-to-guide
- Published: 2026-07-30

---

**You can create bodyweight chest filter combinations by intersecting independent Equipment, Category, and Target Muscle criteria in the interactive browser or by programmatically filtering the JSON dataset.**

The `hasaneyldrm/exercises-dataset` repository ships with a vanilla-JavaScript exercise browser that supports multi-dimensional filtering out of the box. When you need to create filter combinations like bodyweight chest exercises, the browser's `applyFilters()` function in [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html) intersects active selections from three independent groups against the full catalog stored in [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json). This guide breaks down the engine and shows how to replicate the logic in your own projects.

## How the Filter Logic Works in index.html

The browser constructs three independent filter groups—**Category**, **Equipment**, and **Target Muscle**—from distinct values discovered in [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json). Each group is rendered as a set of clickable chips that manipulate a shared `state.filters` object. When any filter or search term changes, the `applyFilters()` function recomputes the visible list by requiring every active criterion to match, producing a strict logical AND across all dimensions.

### Rendering Filter Chips with renderChips

The `renderChips()` function in [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html) generates a clickable button for every distinct value inside a filter dimension. It also appends a **show more** toggle when the number of values exceeds the visible limit, keeping the sidebar uncluttered while still exposing every possible filter value.

### Toggling Filter State with toggleFilter

Each chip click triggers `toggleFilter()`, which adds or removes the selected value from the appropriate `Set` stored in `state.filters`. Because the state uses native JavaScript `Set` objects, duplicate entries are impossible and membership tests remain constant-time.

### Applying Combined Filters with applyFilters

The core intersection logic lives in `applyFilters()` within [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html). It iterates over the full exercise array and retains only records whose pre-computed search index (`_idx`) matches the current query and whose `category`, `equipment`, and `target` properties are all present in the corresponding active filter sets. If no filters are active for a given dimension, that dimension is skipped, allowing combinations of any granularity—from a single equipment type to a fully qualified bodyweight-chest-target triad.

## Step-by-Step Example: Bodyweight Chest Exercises

### Using the Interactive UI

To obtain bodyweight chest exercises without writing any code, follow these steps in the browser:

1. Open [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html) in any modern web browser.
2. Click the **Equipment** chip labeled **body weight**.
3. Click the **Category** chip labeled **chest** (or the **Target Muscle** chip for pectoralis work).
4. Review the filtered grid and the removable active badges at the top of the results pane.

### Programmatic Filtering in JavaScript

You can reproduce the browser's `applyFilters()` behavior in your own scripts by loading [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json) and chaining equality checks. The pattern below mirrors the checks found inside the filter logic in [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html):

```javascript
// Load the dataset (already available as EXERCISES in index.html)
const exercises = EXERCISES;

// Helper to filter by equipment and category
function filterBodyweightChest(data) {
  return data.filter(
    ex => ex.equipment === 'body weight' && ex.category === 'chest'
  );
}

// Example usage
const bodyweightChest = filterBodyweightChest(exercises);
console.log('Body-weight chest exercises:', bodyweightChest.length);
console.table(bodyweightChest.map(e => ({ id: e.id, name: e.name })));

```

Passing `exercises` through this function yields only records that satisfy both constraints, identical to the UI's logical AND behavior.

### Building a Custom Filter Interface

If you want to embed this logic into a bespoke layout, reuse the existing `createCard()` renderer while supplying your own controls. The snippet below wires two `<select>` elements to the dataset:

```javascript
// Assume you have two <select> elements: #equipmentSelect and #categorySelect
document.getElementById('applyBtn').addEventListener('click', () => {
  const eq = document.getElementById('equipmentSelect').value;
  const cat = document.getElementById('categorySelect').value;

  const filtered = EXERCISES.filter(
    ex => (eq === '' || ex.equipment === eq) &&
          (cat === '' || ex.category === cat)
  );

  // Render the result grid (reuse the createCard function from index.html)
  const grid = document.getElementById('exercise-grid');
  grid.innerHTML = '';
  filtered.forEach(ex => grid.appendChild(createCard(ex)));
});

```

This preserves the repository's card styling and event bindings while letting you define arbitrary filter combinations programmatically.

## Summary

- The exercise browser in [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html) groups filters into **Category**, **Equipment**, and **Target Muscle** chips via `renderChips()`.
- Clicks update `state.filters` through `toggleFilter()`, which tracks active values in memory-efficient `Set` objects.
- `applyFilters()` intersects all active criteria with a logical AND against [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json), enabling precise combinations like bodyweight chest exercises.
- You can replicate or extend this behavior in custom JavaScript by filtering the `EXERCISES` array on `equipment`, `category`, and `target` fields.

## Frequently Asked Questions

### How does the exercise browser combine multiple filter selections?

The browser collects active values into `state.filters` and evaluates them inside `applyFilters()` in [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html). Each exercise must satisfy every active dimension simultaneously, so selecting **body weight** under Equipment and **chest** under Category returns only exercises that match both properties. This strict logical AND is what makes precise combinations possible.

### Which data fields support filter combinations?

The underlying [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json) supplies `category`, `equipment`, and `target` fields for every record. The UI surfaces these three columns as independent chip groups, and you can use the same fields in custom scripts to build comparable queries. No other schema transformations are required.

### Can I filter exercises without using the provided web interface?

Yes. Because the dataset is a flat JSON array, you can load [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json) directly and call `Array.prototype.filter()` on properties such as `equipment` and `category`. This approach bypasses [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html) entirely while producing identical bodyweight chest subsets.

### Where is the active filter state stored?

Filter state is maintained in a global `state` object inside [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html), specifically within `state.filters`, which contains a `Set` for each dimension. `toggleFilter()` mutates these sets, and `applyFilters()` reads them on every user interaction to refresh the results grid. The active badges rendered by `updateActiveBadges` reflect the same underlying state.