JetSmartFilters frontend events

SkillDatabases & data

Handle the JetSmartFilters frontend AJAX lifecycle and reinitialize behavior after provider DOM replacement. Use when JavaScript must react when filtering starts, rendered content updates, loading ends, or JSF initializes; when integrating sliders, galleries, analytics, accessibility, or other widgets; or when code references JetSmartFilters.events, ajaxFilters/start-loading, ajaxFilters/updated, ajaxFilters/end-loading, provider/content-rendered, or jet-filter-content-rendered.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the JetSmartFilters frontend events skill

What this skill tells your AI

The instructions your AI receives, as published by lonsdale201/wp-agent-skills in jetsmartfilter/jsf-frontend-events/SKILL.md and read by ahel’s review.

Subscribe to the JSF event bus and scope every callback. For a listing, the three essential lifecycle channels are:

ChannelCallback argumentsMeaning
ajaxFilters/start-loadingprovider, queryIdA real AJAX request started; preloader is active
ajaxFilters/updatedprovider, queryId, response, requestOptionsResponse was processed and provider DOM/fragments were updated
ajaxFilters/end-loadingprovider, queryIdLoading teardown ran and the preloader was hidden

Use updated to read or initialize the new DOM. Use end-loading for a global “cycle finished” UI state. They are not aliases.

Load a companion script after JSF

JSF enqueues its public script in wp_footer only on pages where filters were rendered. Queue the bridge after JSF has enqueued itself and before footer scripts print:

add_action( 'wp_footer', static function (): void {
    if ( ! wp_script_is( 'jet-smart-filters', 'enqueued' ) ) {
        return;
    }

    wp_enqueue_script(
        'acme-jsf-bridge',
        plugins_url( 'assets/js/jsf-bridge.js', __FILE__ ),
        array( 'jet-smart-filters' ),
        '1.0.0',
        true
    );
}, 16 );

Subscribe with provider/query scoping

(() => {
  const targetProvider = 'jsf-listing';
  const targetQueryId = 'catalog-listing';

  const isTarget = (provider, queryId) =>
    provider === targetProvider && queryId === targetQueryId;

  const bind = () => {
    const bus = window.JetSmartFilters?.events;

    if (!bus?.subscribe) {
      return;
    }

    bus.subscribe('ajaxFilters/start-loading', (provider, queryId) => {
      if (!isTarget(provider, queryId)) return;
      document.querySelector('.catalog-shell')?.setAttribute('aria-busy', 'true');
    });

    bus.subscribe(
      'ajaxFilters/updated',
      (provider, queryId, response, requestOptions) => {
        if (!isTarget(provider, queryId)) return;
        initCatalogWidgets(document.querySelector('#catalog-listing'));
      }
    );

    bus.subscribe('ajaxFilters/end-loading', (provider, queryId) => {
      if (!isTarget(provider, queryId)) return;
      document.querySelector('.catalog-shell')?.setAttribute('aria-busy', 'false');
    });
  };

  if (window.JetSmartFilters?.events) {
    bind();
  } else {
    document.addEventListener('jet-smart-filters/before-init', bind, { once: true });
  }
})();

Make initCatalogWidgets() idempotent: destroy or detect an existing widget before recreating it.

Other useful events

  • DOM jet-smart-filters/before-init: JSF global exists; filter discovery has not run.
  • DOM jet-smart-filters/inited: initial filter groups are available.
  • Bus provider/content-rendered: callback receives provider, $provider after provider HTML and builder integrations render. It has no query ID, so it is insufficient alone when several instances share a provider.
  • Legacy jQuery jet-filter-content-rendered: document event with event, $provider, filterGroup, provider, queryId. Prefer the event bus in new code; keep this only for a legacy integration contract.
  • A provider element may receive jet-filter-data-updated for providers that return data rather than HTML.

Failure and concurrency rules

  • A “start” event is not proof that content changed.
  • In 3.8.3.1 a newer request aborts the previous XHR, and the abort path can skip end-loading. Do not maintain an unbounded global counter that assumes perfect start/end pairs.
  • Key UI state by provider/query ID and make repeated cleanup harmless.
  • updated fires on successful processing. Use application-level monitoring if failed AJAX requests must also be reported.
  • Prefer delegated click/input handlers for elements inside the replaced wrapper.

References

Verified against JetSmartFilters 3.8.3.1 source:

  • includes/filters/manager.php:22-112
  • assets/js/public.js channels ajaxFilters/start-loading, ajaxFilters/updated, ajaxFilters/end-loading, provider/content-rendered
  • assets/lib/jet-plugins/jet-plugins.js

Signals

GitHub stars
22
Forks
2
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
jsf-frontend-events
Source
github.com/lonsdale201/wp-agent-skills