Browse Source

initial commit

main
Paul Pound 5 days ago
commit
d2d9b56200
  1. 46
      README.md
  2. 59
      js/preserve-advanced-search.js
  3. 5
      preserve_advanced_search.info.yml
  4. 7
      preserve_advanced_search.libraries.yml
  5. 26
      preserve_advanced_search.module

46
README.md

@ -0,0 +1,46 @@
# Preserve Advanced Search
Keeps the advanced search `a[]` query parameters attached to the facet slider
URLs that Facets builds server-side, so clicking a slider doesn't drop the
user's advanced search criteria.
Replaces the equivalent code that previously lived in individual themes
(`THEME.libraries.yml` + `THEME_preprocess_page()`).
## Install
Copy this directory to `web/modules/custom/preserve_advanced_search` on each
site, then:
drush en preserve_advanced_search
drush cr
## Scope
`hook_library_info_alter()` appends this module's library to the dependencies of
`facets_range_nouislider/facets_range_nouislider`. It therefore loads only on
pages that actually render a noUiSlider facet — not site-wide, and with no route
list to maintain per site.
Library info is cached, so run `drush cr` after deploying or the alter won't
take effect.
If a site configures its facets with the **Facets core** slider widget
(`facets_range_widget`) instead of `facets_range_nouislider`, add that
extension's library to the alter as well. Both submodules write to
`drupalSettings.facets.sliders`, so the JavaScript itself needs no change — only
the attachment point does.
## Notes
- Load order is guaranteed by the dependency: our script is loaded ahead of
`slider.js`, so `Drupal.behaviors.preserveAdvancedSearchParams` is registered
first and runs first. `facets_range_nouislider`'s `slider.js` is additionally
marked `defer: true` while ours is not, and non-deferred scripts always
execute before deferred ones — so the ordering holds twice over.
- `rebuildUrl()` is idempotent (it strips all `a[]` params before re-adding the
current ones), so re-running on AJAX rebuilds is safe.
- The JS handles both `sliderSettings.url` and `sliderSettings.urls`. Range
widgets collapse the parent's `urls` map into a single `url`
(`RangeNoUiSliderWidget::build()`); single-handle widgets keep `urls`. Both
branches are live — don't remove either.

59
js/preserve-advanced-search.js

@ -0,0 +1,59 @@
(function (Drupal, drupalSettings) {
'use strict';
Drupal.behaviors.preserveAdvancedSearchParams = {
attach: function (context, settings) {
// Capture the a[] advanced search params from the current URL
const rawSearch = window.location.search;
const aParams = rawSearch
.substring(1)
.split('&')
.filter(part => part.startsWith('a%5B') || part.startsWith('a['))
.join('&');
if (!aParams) return;
const sliders = settings.facets && settings.facets.sliders;
if (!sliders) return;
// Replace any a[] params in a URL with the current page's a[] params.
// The current URL is always the source of truth — the server-built
// slider URL may contain stale or partial a[] params.
function rebuildUrl(url) {
if (!url) return url;
const parts = url.split('?');
const basePath = parts[0];
const query = parts[1] || '';
// Keep everything that is NOT an a[] param (i.e. the f[] facet params)
const keptParams = query
.split('&')
.filter(p => p.length > 0)
.filter(p => !p.startsWith('a%5B') && !p.startsWith('a['))
.join('&');
const finalQuery = [keptParams, aParams].filter(Boolean).join('&');
return basePath + '?' + finalQuery;
}
// Range sliders expose a single `url`; single-handle sliders expose a
// `urls` map keyed by value. Handle both — which one is present depends
// on the widget the facet is configured with.
Object.keys(sliders).forEach(function (key) {
const sliderSettings = sliders[key];
if (sliderSettings.url) {
sliderSettings.url = rebuildUrl(sliderSettings.url);
}
if (sliderSettings.urls) {
Object.keys(sliderSettings.urls).forEach(function (urlKey) {
sliderSettings.urls[urlKey] = rebuildUrl(sliderSettings.urls[urlKey]);
});
}
});
}
};
})(Drupal, drupalSettings);

5
preserve_advanced_search.info.yml

@ -0,0 +1,5 @@
name: 'Preserve Advanced Search'
type: module
description: 'Keeps advanced search a[] query parameters attached to facet slider URLs built by the server.'
package: 'Custom'
core_version_requirement: ^10 || ^11

7
preserve_advanced_search.libraries.yml

@ -0,0 +1,7 @@
preserve-advanced-search:
version: VERSION
js:
js/preserve-advanced-search.js: {}
dependencies:
- core/drupal
- core/drupalSettings

26
preserve_advanced_search.module

@ -0,0 +1,26 @@
<?php
/**
* @file
* Preserves advanced search a[] parameters on facet slider URLs.
*/
/**
* Implements hook_library_info_alter().
*
* Attaches the fix-up library as a dependency of the slider widget library
* rather than to every page. This scopes it to the pages that actually render
* a slider, and guarantees our script loads first so the behavior is
* registered — and therefore runs — before the slider reads
* drupalSettings.facets.sliders.
*/
function preserve_advanced_search_library_info_alter(array &$libraries, $extension)
{
if ($extension !== 'facets_range_nouislider') {
return;
}
if (isset($libraries['facets_range_nouislider'])) {
$libraries['facets_range_nouislider']['dependencies'][] = 'preserve_advanced_search/preserve-advanced-search';
}
}
Loading…
Cancel
Save