Commit 3580de3e authored by Markus Kalkbrenner's avatar Markus Kalkbrenner
Browse files

Issue #3306634 by mkalkbrenner: Integrate with better_exposed_filters for AJAX

parent d66b15c5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
    "drupal/jquery_ui_touch_punch": "~1.0"
  },
  "suggest": {
    "drupal/better_exposed_filters": "Required for AJAX support for facets rendered as views exposed filters",
    "drupal/jquery_ui_slider": "Required for the 'Facets Range Widget' module to work",
    "drupal/jquery_ui_touch_punch": "Required for the 'Facets Range Widget' module to work"
  },
+0 −15
Original line number Diff line number Diff line
@@ -30,13 +30,6 @@ widget:
    - core/drupal
    - core/jquery.once

drupal.facets.link-widget:
  version: VERSION
  js:
    js/link-widget.js: {}
  dependencies:
    - facets/widget

drupal.facets.checkbox-widget:
  version: VERSION
  js:
@@ -72,11 +65,3 @@ soft-limit:
    - core/jquery.once
    - core/drupal
    - core/drupalSettings

drupal.facets.views-ajax:
  js:
    js/facets-views-ajax.js: {}
  dependencies:
    - facets/widget
    - core/drupalSettings
    - core/drupal.ajax
+5 −0
Original line number Diff line number Diff line
@@ -51,3 +51,8 @@ services:
  facets.language_switcher_links_alterer:
    class: Drupal\facets\LanguageSwitcherLinksAlterer
    arguments: ['@language_manager', '@cache.default', '@entity_type.manager', '@plugin.manager.facets.url_processor']
  cache_context.facets_filter:
    class: Drupal\facets\Cache\Context\FacetsFilterCacheContext
    arguments: ['@request_stack']
    tags:
      - { name: cache.context }
+34 −11
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
   */
  Drupal.facets.makeCheckboxes = function (context) {
    // Find all checkbox facet links and give them a checkbox.
    var $checkboxWidgets = $('.js-facets-checkbox-links', context)
    var $checkboxWidgets = $('.js-facets-checkbox-links, .js-facets-links', context)
      .once('facets-checkbox-transform');

    if ($checkboxWidgets.length > 0) {
@@ -54,24 +54,47 @@
    var description = $link.html();
    var href = $link.attr('href');
    var id = $link.data('drupal-facet-item-id');
    var type = $link.data('drupal-facet-widget-element-class');

    var checkbox = $('<input type="checkbox" class="facets-checkbox">')
    var checkbox = $('<input type="checkbox">')
      .attr('id', id)
      .attr('name', $link.data('drupal-facet-filter-key') + '[]')
      .addClass(type)
      .val($link.data('drupal-facet-filter-value'))
      .data($link.data())
      .data('facetsredir', href);

    var single_selection_group = $(this).data('drupal-facet-single-selection-group');
    if (single_selection_group) {
      checkbox.addClass(single_selection_group);
    }

    if (type === 'facets-link') {
      checkbox.hide();
    }

    var label = $('<label for="' + id + '">' + description + '</label>');

    checkbox.on('change.facets', function (e) {
      if ($link.data('drupal-facet-ajax') == 0) {
        e.preventDefault();

        var $widget = $(this).closest('.js-facets-widget');

        Drupal.facets.disableFacet($widget);
        $widget.trigger('facets_filter', [href]);
      }
      else {
        var current = $(this);
        if (current.is(':checked') && current.hasClass(single_selection_group)) {
          var $widget = current.closest('.js-facets-widget');
          $widget.find('input.' + single_selection_group + ':not(#' + current.attr('id') + ')').prop('checked', false);
        }
      }
    });

    if (active) {
      checkbox.attr('checked', true);
      checkbox.prop('checked', true);
      label.find('.js-facet-deactivate').remove();
    }

@@ -87,8 +110,8 @@
   */
  Drupal.facets.disableFacet = function ($facet) {
    $facet.addClass('facets-disabled');
    $('input.facets-checkbox', $facet).click(Drupal.facets.preventDefault);
    $('input.facets-checkbox', $facet).attr('disabled', true);
    $('input.facets-checkbox, input.facets-link', $facet).click(Drupal.facets.preventDefault);
    $('input.facets-checkbox, input.facets-link', $facet).attr('disabled', true);
  };

  /**

js/facets-views-ajax.js

deleted100644 → 0
+0 −219
Original line number Diff line number Diff line
/**
 * @file
 * Facets views AJAX handling.
 */


(function ($, Drupal) {
  'use strict';

  /**
   * Keep the original beforeSend method to use it later.
   */
  var beforeSend = Drupal.Ajax.prototype.beforeSend;

  /**
   * Trigger views AJAX refresh on click.
   */
  Drupal.behaviors.facetsViewsAjax = {
    attach: function (context, settings) {

      // Loop through all facets.
      $.each(settings.facets_views_ajax, function (facetId, facetSettings) {
        // Get the View for the current facet.
        var view, current_dom_id, view_path;
        if (settings.views && settings.views.ajaxViews) {
          $.each(settings.views.ajaxViews, function (domId, viewSettings) {
            // Check if we have facet for this view.
            if (facetSettings.view_id == viewSettings.view_name && facetSettings.current_display_id == viewSettings.view_display_id) {
              view = $('.js-view-dom-id-' + viewSettings.view_dom_id);
              current_dom_id = viewSettings.view_dom_id;
              view_path = facetSettings.ajax_path;
            }
          });
        }

        if (!view || view.length != 1) {
          return;
        }

        // Update view on summary block click.
        if (updateFacetsSummaryBlock() && (facetId === 'facets_summary_ajax')) {
          $('[data-drupal-facets-summary-id=' + facetSettings.facets_summary_id + ']').children('ul').children('li').once().click(function (e) {
            e.preventDefault();
            var facetLink = $(this).find('a');
            updateFacetsView(facetLink.attr('href'), current_dom_id, view_path);
          });
        }
        // Update view on facet item click.
        else {
          $('[data-drupal-facet-id=' + facetId + ']').each(function (index, facet_item) {
            if ($(facet_item).hasClass('js-facets-widget')) {
              $(facet_item).unbind('facets_filter.facets');
              $(facet_item).on('facets_filter.facets', function (event, url) {
                $('.js-facets-widget').trigger('facets_filtering');

                updateFacetsView(url, current_dom_id, view_path);
              });
            }
          });

        }
      });
    }
  };

  // Helper function to update views output & Ajax facets.
  var updateFacetsView = function (href, current_dom_id, view_path) {
    // Refresh view.
    var views_parameters = Drupal.Views.parseQueryString(href);
    var views_arguments = Drupal.Views.parseViewArgs(href, 'search');
    var views_settings = $.extend(
        {},
        Drupal.views.instances['views_dom_id:' + current_dom_id].settings,
        views_arguments,
        views_parameters
    );

    // Update View.
    var views_ajax_settings = Drupal.views.instances['views_dom_id:' + current_dom_id].element_settings;
    views_ajax_settings.submit = views_settings;
    views_ajax_settings.url = view_path + '?q=' + href;

    Drupal.ajax(views_ajax_settings).execute();

    // Update url.
    window.historyInitiated = true;
    window.history.pushState(null, document.title, href);

    // ToDo: Update views+facets with ajax on history back.
    // For now we will reload the full page.
    window.addEventListener("popstate", function (e) {
      if (window.historyInitiated) {
        window.location.reload();
      }
    });

    // Refresh facets blocks.
    updateFacetsBlocks(href);
  }

  // Helper function, updates facet blocks.
  var updateFacetsBlocks = function (href) {
    var settings = drupalSettings;
    var facets_blocks = facetsBlocks();

    // Remove All Range Input Form Facet Blocks from being updated.
    if(settings.facets && settings.facets.rangeInput) {
      $.each(settings.facets.rangeInput, function (index, value) {
        delete facets_blocks[value.facetId];
      });
    }

    // Update facet blocks.
    var facet_settings = {
      url: Drupal.url('facets-block-ajax'),
      submit: {
        facet_link: href,
        facets_blocks: facets_blocks
      }
    };

    // Update facets summary block.
    if (updateFacetsSummaryBlock()) {
      var facet_summary_wrapper_id = $('[data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax.facets_summary_id + ']').attr('id');
      var facet_summary_block_id = '';
      if (facet_summary_wrapper_id.indexOf('--') !== -1) {
        facet_summary_block_id = facet_summary_wrapper_id.substring(0, facet_summary_wrapper_id.indexOf('--')).replace('block-', '');
      }
      else {
        facet_summary_block_id = facet_summary_wrapper_id.replace('block-', '');
      }
      facet_settings.submit.update_summary_block = true;
      facet_settings.submit.facet_summary_block_id = facet_summary_block_id;
      facet_settings.submit.facet_summary_wrapper_id = settings.facets_views_ajax.facets_summary_ajax.facets_summary_id;
    }

    Drupal.ajax(facet_settings).execute();
  };

  // Helper function to determine if we should update the summary block.
  // Returns true or false.
  var updateFacetsSummaryBlock = function () {
    var settings = drupalSettings;
    var update_summary = false;

    if (settings.facets_views_ajax.facets_summary_ajax) {
      update_summary = true;
    }

    return update_summary;
  };

  // Helper function, return facet blocks.
  var facetsBlocks = function () {
    // Get all ajax facets blocks from the current page.
    var facets_blocks = {};

    $('.block-facets-ajax').each(function (index) {
      var block_id_start = 'js-facet-block-id-';
      var block_id = $.map($(this).attr('class').split(' '), function (v, i) {
        if (v.indexOf(block_id_start) > -1) {
          return v.slice(block_id_start.length, v.length);
        }
      }).join();
      var block_selector = '#' + $(this).attr('id');
      facets_blocks[block_id] = block_selector;
    });

    return facets_blocks;
  };

  /**
   * Overrides beforeSend to trigger facetblocks update on exposed filter change.
   *
   * @param {XMLHttpRequest} xmlhttprequest
   *   Native Ajax object.
   * @param {object} options
   *   jQuery.ajax options.
   */
  Drupal.Ajax.prototype.beforeSend = function (xmlhttprequest, options) {

    // Update facet blocks as well.
    // Get view from options.
    if (typeof options.extraData !== 'undefined' && typeof options.extraData.view_name !== 'undefined') {
      var href = window.location.href;
      var settings = drupalSettings;

      // TODO: Maybe we should limit facet block reloads by view?
      var reload = false;
      $.each(settings.facets_views_ajax, function (facetId, facetSettings) {
        if (facetSettings.view_id == options.extraData.view_name && facetSettings.current_display_id == options.extraData.view_display_id) {
          reload = true;
        }
      });

      if (reload) {
        href = addExposedFiltersToFacetsUrl(href, options.extraData.view_name, options.extraData.view_display_id);
        updateFacetsBlocks(href);
      }
    }

    // Call the original Drupal method with the right context.
    beforeSend.apply(this, arguments);
  }

  // Helper function to add exposed form data to facets url
  var addExposedFiltersToFacetsUrl = function (href, view_name, view_display_id) {
    var $exposed_form = $('form#views-exposed-form-' + view_name.replace(/_/g, '-') + '-' + view_display_id.replace(/_/g, '-'));

    var params = Drupal.Views.parseQueryString(href);

    $.each($exposed_form.serializeArray(), function () {
      params[this.name] = this.value;
    });

    return href.split('?')[0] + '?' + $.param(params);
  };

})(jQuery, Drupal);
Loading