Gists

6 days ago
<!--
In the listing's Display tab in Dev mode, add the following to var_dump the SQL of the listing query.
This can be handy for seeing the SQL of a static listing, for which Debug Mode (FWP.settings.debug.sql in the Console) will not work.
See: https://facetwp.com/help-center/listing-templates/listing-builder/using-the-listing-builder-in-dev-mode/#debug-static-listing-queries
-->

<pre>
<?php var_dump( $GLOBALS['wp_query']->request ); ?>
</pre>
2 weeks ago
<?
/**
 * disables map filtering if enabled when other
 * filters are used instead
 **/
add_action( 'facetwp_scripts', function() {
 ?>
  <script>
    (function($) {
    document.addEventListener('facetwp-refresh', function() {
        if ( null !== FWP.active_facet &&
                '' !== $(FWP.active_facet.nodes[0]).attr('data-name' ) &&
                /** change 'my_map_facet' to name of your map facet */
                'my_map_facet' !== $(FWP.active_facet.nodes[0]).attr( 'data-name' ) ) {
            var $button = $('.facetwp-map-filtering');
            $button.text(FWP_JSON['map']['filterText']);
            FWP_MAP.is_filtering = false;
            $button.toggleClass('enabled');
            FWP.facets.map = [];
        } 
    });
    })(fUtil);
  </script>
  <?php
}, 100 );
2 weeks ago
<?php
// Let a facet show all options instead of the ones based on the currently filtered results.
// This changes the SQL that loads the facet values.
// Only for use in highly customized situations, doing this can have unexpected side effects.

add_filter( 'facetwp_facet_where', function( $where_clause, $facet ) {
    if ( 'my-facet' == $facet['name'] ) { // change 'my-facet' to the name of your facet
        $post_ids = FWP()->unfiltered_post_ids;
        $post_ids = empty( $post_ids ) ? [ 0 ] : $post_ids;
        $where_clause = ' AND post_id IN (' . implode( ',', $post_ids ) . ')';
    }
    return $where_clause;
}, 10, 2 )
2 weeks ago
<?php
add_action( 'facetwp_scripts', function() {
  ?>
  <script>
    (function($) {
      // Store original alert
      var originalAlert = window.alert;

      // Override window.alert
      window.alert = function(msg) {
        // Catch all FacetWP geolocation alerts
        if (
          msg === "User denied the request for Geolocation." ||
          msg === "Location information is unavailable." ||
          msg === "The request to get user location timed out." ||
          msg === "An unknown error occurred."
        ) {
          // Suppress FacetWP's original alert, do nothing here
          return;
        }
        // Otherwise, let other alerts work as normal
        originalAlert(msg);
      };

      // Now show custom messages via the FacetWP error hook
      FWP.hooks.addAction('facetwp/geolocation/error', function(obj) {
        let error = obj.error;
        let customMessage = "We couldn’t detect your location. Please allow location access.";

        switch (error.code) {
          case error.PERMISSION_DENIED:
            customMessage = "⚠️ You blocked location sharing. Please enable it in your browser.";
            break;
          case error.POSITION_UNAVAILABLE:
            customMessage = "📡 Location info is not available right now.";
            break;
          case error.TIMEOUT:
            customMessage = "⏳ The request took too long. Please try again.";
            break;
          case error.UNKNOWN_ERROR:
            customMessage = "❌ An unknown error occurred while getting your location.";
            break;
        }

        originalAlert(customMessage); // Show thecustom alert
      });
    })(fUtil);

  </script>
  <?php
}, 100 );
2 weeks ago
/**
 ** Styles a Radio facet to look like a Checkboxes facet, but still
 ** function like a (single select) Radio facet. 
 ** Change 'my_facet' in '.facetwp-facet-my_facet' to match the facet
 ** name (not label, see https://facetwp.com/help-center/facets/#the-facet-label)
 ** of your facet and the background URL to be
 ** a relative or full URL to the correct image.
 ** Also see: https://facetwp.com/help-center/facets/facet-types/radio/#style-radio-facet-choices-as-checkboxes
 **/


.facetwp-facet-my_facet .facetwp-radio {
  background: url('/wp-content/plugins/facetwp/assets/images/checkbox.png') 0 50% no-repeat;
  background-size: 14px 14px;
}

.facetwp-facet-my_facet .facetwp-radio.checked {
  background-image: url('/wp-content/plugins/facetwp/assets/images/checkbox-on.png');
}
2 weeks ago
<?php
/**
 ** Replace "dots" section of pager with custom HTML to remove the <a> links,
 ** so that accessibility does not treat it as a link to be clicked.
 ** Also see: https://facetwp.com/help-center/developers/hooks/output-hooks/facetwp_facet_pager_link/#replace-or-customize-the-dots
 **/
add_filter( 'facetwp_facet_pager_link', function( $html, $params ) {
  if ( '' == $params['page'] ) {
    $html = '<span class="facetwp-page dots">…</span>';
  }
  return $html;
}, 10, 2 );
2 months ago
<?php
/*
Plugin Name: Custom Hooks
Plugin URI: https://facetwp.com/
Description: A container for custom hooks
Version: 1.0
Author: FacetWP, LLC
*/
2 months ago
<?php
// The .accordionjs class in line 9 is the class of the ul that is the accordion wrapper. Adapt if needed.
add_action( 'facetwp_scripts', function() {
  ?>
  <script>
    (function($) {
      document.addEventListener('facetwp-loaded', function() {
        if ( FWP.loaded ) {
          $('.accordionjs').accordionjs( {
            activeIndex: false // This prevents the first section from opening by default. Remove this option if you want that to happen.
          } );
        }
      });
    })(jQuery);
  </script>
  <?php
}, 100 );
2 months ago
<?php
// Google Pagespeed insights may complain about links without a href not being crawlable.
// The following code replaces these <a> tags with class .facetwp-toggle with <span> tags.
// .facetwp-toggle links are in Checkboxes, Hierarchy and Color facets.

// Option 1: with JS
add_action( 'facetwp_scripts', function() {
  ?>
  <script>
    document.addEventListener('facetwp-loaded', function() {
      const anchorElements = document.querySelectorAll('a.facetwp-toggle');
      anchorElements.forEach(anchor => {
        const span = document.createElement('span');
        for (let i = 0; i < anchor.attributes.length; i++) {
          const attribute = anchor.attributes[i];
          if (attribute.name !== 'href') {
            span.setAttribute(attribute.name, attribute.value);
          }
        }
        span.innerHTML = anchor.innerHTML;
        if (anchor.parentNode) {
          anchor.parentNode.replaceChild(span, anchor);
        }
      });
    });
  </script>
  <?php
}, 100 );

// Option 2: with the 'facetwp_facet_html' hook
add_filter( 'facetwp_facet_html', function( $output, $params ) {

  if ( in_array( $params['facet']['type'], [ 'checkboxes', 'hierarchy', 'color' ] ) ) {

    // Regex to find <a> tags with class="facetwp-toggle" and capture their content and any other attributes
    $pattern = '/<a\s+(class="[^"]*\bfacetwp-toggle\b[^"]*")([^>]*)>(.*?)<\/a>/si';

    // Replacement string: change <a> to <span>, keep class and other attributes, and content
    // $1 captures the class attribute
    // $2 captures any other attributes
    // $3 captures the inner HTML content
    $replacement = '<span $1$2>$3</span>';

    $output = preg_replace( $pattern, $replacement, $output );
  }

  return $output;
}, 10, 2 );
2 months ago
<?php
// For a Proximity facet, index an ACF Google Maps field of a post linked by an ACF Post Object field.
// The Proximity facet's data source can be set to anything as long as that value is not empty. E.g. 'Post Type'.
// The 'Return Format' of the Post Object field does not matter: it works with both 'Post Object' and 'Post ID'.
// See: https://facetwp.com/help-center/developers/hooks/indexing-hooks/facetwp_index_row/#index-values-in-a-related-custom-field

add_filter( 'facetwp_index_row', function( $params, $class ) {

  if ( 'my_proximity_facet' == $params['facet_name'] ) { // Change "my_proximity_facet" to the name of your Proximity facet

    $post_id = $params['post_id'];
      
    // Get the Post Object field value 
    $location_id = get_field( 'my_acf_post_object field', $post_id ); // Change "my_acf_post_object field" to the name of your ACF Post Object field

    $location = '';
    if ( $location_id ) { // Check if the Post Object field has a value
      // If we have a Post Object field value, use it to get the Google Maps field value  
      $location = get_field( 'my_acf_googlemapfield', $location_id ); // Change "my_acf_googlemapfield" to the name of your ACF Google Maps field
    }

    // If there is a location, index it, otherwise skip this post by setting facet_value to ''.  
    $params['facet_value'] = empty( $location ) ? '' : $location['lat'];
    $params['facet_display_value'] = empty( $location ) ? '' : $location['lng'];
      
    // Optionally replicate the extra checks that Proximity facets normally have:

    // 1. Make sure lat and lng are valid floats
    $params['facet_value'] = $params['facet_value'] == (float)$params['facet_value'] ? (float)$params['facet_value'] : '';
    $params['facet_display_value'] = $params['facet_display_value'] == (float)$params['facet_display_value'] ? (float)$params['facet_display_value'] : '';

    // 2. Check for a valid range of lat and lng
    if  ( '' == $params['facet_value'] || '' == $params['facet_display_value'] || 90 < abs( $params['facet_value'] ) || 180 < abs( $params['facet_display_value'] ) ) {
      $params['facet_value'] = ''; // don't index
    }
      
  }

  return $params;
}, 10, 2 );