Skip to content

Instantly share code, notes, and snippets.

@robertpainsi
Last active October 10, 2025 11:41
Show Gist options
  • Save robertpainsi/2fa433d90ae0136573f155af705f4ee7 to your computer and use it in GitHub Desktop.
Save robertpainsi/2fa433d90ae0136573f155af705f4ee7 to your computer and use it in GitHub Desktop.
Example for loading and storing the checked filters in the browser's hash using filtering.js version 2.0.0
<!-- filtering.js library https://github.com/robertpainsi/filtering.js -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Filtering.js Hash</title>
<style>
.filtering-group {
margin: 12px;
}
.filtering-filter.checked {
background-color: lightblue;
}
.filtering-filter.disabled {
color: lightgrey;
}
/* Items */
.filtering-item.filtered {
display: none;
}
</style>
</head>
<body>
<div id="root">
<div style="display: flex; flex-direction: row;">
<div class="filtering-group" data-group-name="color">
<div class="filtering-filter" data-filter-name="red">Red</div>
<div class="filtering-filter" data-filter-name="blue">Blue</div>
</div>
<div class="filtering-group" data-group-name="size">
<div class="filtering-filter" data-filter-name="small">Small</div>
<div class="filtering-filter" data-filter-name="large">Large</div>
</div>
</div>
<ul>
<li id="item-1" class="filtering-item" data-filter-color="red" data-filter-size="small">Small red item</li>
<li id="item-2" class="filtering-item" data-filter-color="blue" data-filter-size="large">Large blue item</li>
</ul>
</div>
<script src="index.ui.js"></script>
<script>
const { FilteringFlow, FilterData } = filteringjs;
const filteringFlow = new FilteringFlow( document.querySelector( '#root' ) );
const loadFiltersFromHash = registerFilteringHashPlugin( filteringFlow );
// Since we want to enable all filters specified in the browser's hash on page load, we call the loadFiltersFromHash,
// which will internally call filteringFlow.filter(...). Call this function after all plugins have been registered.
loadFiltersFromHash();
// The registerFilteringHashPlugin is just a helper function to registers all listeners. You actually don't have to
// create it, you could also inline the code. However, I strongly encourage you to create it somehow similar to
// encapsulate the plugin and make it reusable in other projects too. The checked filters in the hash for this code
// example look like #color=red&color=blue...
function registerFilteringHashPlugin( filteringFlow ) {
// After a filter is checked or unchecked, store the checked filters in the hash
filteringFlow.addEventListener( 'filter', ( event ) => storeFiltersToHash( event.data.filterData ) );
// To support the browser's history (back and forward), a hash change needs to trigger the filtering with checked
// filters parsed from the hash.
window.addEventListener( 'hashchange', loadFiltersFromHash );
function loadFiltersFromHash() {
const hash = decodeURIComponent( window.location.hash.substring( 1 ) );
// The FilterData is used to specify which filters should be checked and used for filtering
const filteringData = new FilterData();
if ( hash ) {
const filteringAsQueryParams = new URLSearchParams( hash );
for ( const [groupName, filterName] of filteringAsQueryParams ) {
// Set the checked filters parsed from the hash
filteringData.checkFilter( groupName, filterName );
}
}
// Trigger filtering with the parsed filters
filteringFlow.filter( filteringData );
}
// This function just stores the checked filters in the hash.
function storeFiltersToHash( filterData ) {
const filteringAsQueryParams = new URLSearchParams();
for ( const [groupName, checkedFilters] of filterData.checkedFilters ) {
for ( const checkedFilter of checkedFilters ) {
filteringAsQueryParams.append( groupName, checkedFilter );
}
}
const newHash = filteringAsQueryParams.toString();
if ( newHash !== window.location.hash.substring( window.location.hash.indexOf( '#' ) + 1 ) ) {
window.location.hash = newHash;
}
}
return loadFiltersFromHash;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment