Skip to content
Snippets Groups Projects
Commit 8d7b1c95 authored by Joris Vercammen's avatar Joris Vercammen
Browse files

Actually commit 3031581

parent c88a3b27
No related branches found
No related tags found
No related merge requests found
......@@ -21,15 +21,29 @@ drupal.facets.admin_css:
theme:
css/facets.admin.css: {}
drupal.facets.checkbox-widget:
widget:
version: VERSION
js:
js/checkbox-widget.js: {}
js/base-widget.js: {}
dependencies:
- core/jquery
- 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:
js/checkbox-widget.js: {}
dependencies:
- facets/widget
drupal.facets.hierarchical:
version: VERSION
css:
......@@ -47,9 +61,8 @@ drupal.facets.dropdown-widget:
js:
js/dropdown-widget.js: {}
dependencies:
- core/jquery
- core/drupal
- core/jquery.once
- facets/widget
soft-limit:
version: VERSION
js:
......@@ -59,12 +72,11 @@ soft-limit:
- core/jquery.once
- core/drupal
- core/drupalSettings
drupal.facets.views-ajax:
js:
js/facets-views-ajax.js: {}
dependencies:
- core/jquery
- core/jquery.once
- core/drupal
- facets/widget
- core/drupalSettings
- core/drupal.ajax
/**
* @file
* Provides base widget behaviours.
*/
(function ($, Drupal) {
'use strict';
/**
* Handles "facets_filter" event and triggers "facets_filtering".
*
* The facets module will listend and trigger defined events on elements with
* class: "js-facets-widget".
*
* Events are doing following:
* "facets_filter" - widget should trigger this event. The facets module will
* handle it accordingly in case of AJAX and Non-AJAX views.
* "facets_filtering" - The facets module will trigger this event before
* filter is executed.
*
* This is an example how to trigger "facets_filter" event for your widget:
* $('.my-custom-widget.js-facets-widget')
* .once('my-custom-widget-on-change')
* .on('change', function () {
* // In this example $(this).val() will provide needed URL.
* $(this).trigger('facets_filter', [ $(this).val() ]);
* });
*
* The facets module will trigger "facets_filtering" before filter is
* executed. Widgets can listen on "facets_filtering" event and react before
* filter is executed. Most common use case is to disable widget. When you
* disable widget, a user will not be able to trigger new "facets_filter"
* event before initial filter request is finished.
*
* This is an example how to handle "facets_filtering":
* $('.my-custom-widget.js-facets-widget')
* .once('my-custom-widget-on-facets-filtering')
* .on('facets_filtering.my_widget_module', function () {
* // Let's say, that widget can be simply disabled (fe. select).
* $(this).prop('disabled', true);
* });
*
* You should namespace events for your module widgets. With namespaced events
* you have better control on your handlers and if it's needed, you can easier
* register/deregister them.
*/
Drupal.behaviors.facetsFilter = {
attach: function (context) {
$('.js-facets-widget', context)
.once('js-facet-filter')
.on('facets_filter.facets', function (event, url) {
$('.js-facets-widget').trigger('facets_filtering');
window.location = url;
});
}
};
})(jQuery, Drupal);
......@@ -3,24 +3,43 @@
* Transforms links into checkboxes.
*/
(function ($) {
(function ($, Drupal) {
'use strict';
Drupal.facets = Drupal.facets || {};
Drupal.behaviors.facetsCheckboxWidget = {
attach: function (context, settings) {
Drupal.facets.makeCheckboxes();
attach: function (context) {
Drupal.facets.makeCheckboxes(context);
}
};
/**
* Turns all facet links into checkboxes.
*/
Drupal.facets.makeCheckboxes = function () {
Drupal.facets.makeCheckboxes = function (context) {
// Find all checkbox facet links and give them a checkbox.
var $links = $('.js-facets-checkbox-links .facet-item a');
$links.once('facets-checkbox-transform').each(Drupal.facets.makeCheckbox);
var $checkboxWidgets = $('.js-facets-checkbox-links', context)
.once('facets-checkbox-transform');
if ($checkboxWidgets.length > 0) {
$checkboxWidgets.each(function (index, widget) {
var $widget = $(widget);
var $widgetLinks = $widget.find('.facet-item > a');
// Add correct CSS selector for the widget. The Facets JS API will
// register handlers on that element.
$widget.addClass('js-facets-widget');
// Transform links to checkboxes.
$widgetLinks.each(Drupal.facets.makeCheckbox);
});
// We have to trigger attaching of behaviours, so that Facets JS API can
// register handlers on checkbox widgets.
Drupal.attachBehaviors(context, Drupal.settings);
}
// Set indeterminate value on parents having an active trail.
$('.facet-item--expanded.facet-item--active-trail > input').prop('indeterminate', true);
};
......@@ -42,8 +61,12 @@
var label = $('<label for="' + id + '">' + description + '</label>');
checkbox.on('change.facets', function (e) {
Drupal.facets.disableFacet($link.parents('.js-facets-checkbox-links'));
$(this).siblings('a')[0].click();
e.preventDefault();
var $widget = $(this).closest('.js-facets-widget');
Drupal.facets.disableFacet($widget);
$widget.trigger('facets_filter', [ href ]);
});
if (active) {
......@@ -77,4 +100,4 @@
e.preventDefault();
};
})(jQuery);
})(jQuery, Drupal);
......@@ -38,6 +38,7 @@
$dropdown.removeClass('js-facets-dropdown-links');
$dropdown.addClass('facets-dropdown');
$dropdown.addClass('js-facets-widget');
$dropdown.addClass('js-facets-dropdown');
var id = $(this).data('drupal-facet-id');
......@@ -75,12 +76,10 @@
// Go to the selected option when it's clicked.
$dropdown.on('change.facets', function () {
var anchor = $($ul).find("[data-drupal-facet-item-id='" + $(this).find(':selected').data('drupalFacetItemId') + "']");
if ( anchor.length > 0) {
$(anchor)[0].click();
}
else {
$ul.find('.default-option a')[0].click();
}
var $linkElement = (anchor.length > 0) ? $(anchor) : $ul.find('.default-option a');
var url = $linkElement.attr('href');
$(this).trigger('facets_filter', [ url ]);
});
// Append empty text option.
......
......@@ -47,18 +47,13 @@
}
// Update view on facet item click.
else {
$('[data-drupal-facet-id=' + facetId + ']').find('.facet-item').once().each(function (index, facet_item) {
$(facet_item).children('a').once().click(function (e) {
e.preventDefault();
updateFacetsView($(this).attr('href'), current_dom_id, view_path);
});
});
$('[data-drupal-facet-id=' + facetId + ']').each(function (index, facet_item) {
if ($(facet_item).hasClass('js-facets-dropdown')) {
$(facet_item).unbind('change.facets');
$(facet_item).on('change.facets', function () {
updateFacetsView($(this).val(), current_dom_id, view_path);
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);
});
}
});
......@@ -109,7 +104,7 @@
var facets_blocks = facetsBlocks();
// Update facet blocks.
let facet_settings = {
var facet_settings = {
url: Drupal.url('facets-block-ajax'),
submit: {
facet_link: href,
......
/**
* @file
* Facets views Link widgets handling.
*/
(function ($, Drupal) {
'use strict';
/**
* Handle link widgets.
*/
Drupal.behaviors.facetsLinkWidget = {
attach: function (context) {
var $linkFacets = $('.js-facets-links', context)
.once('js-facets-link-on-click');
// We are using list wrapper element for Facet JS API.
if ($linkFacets.length > 0) {
$linkFacets
.each(function (index, widget) {
var $widget = $(widget);
var $widgetLinks = $widget.find('.facet-item > a');
// Click on link will call Facets JS API on widget element.
var clickHandler = function (e) {
e.preventDefault();
$widget.trigger('facets_filter', [$(this).attr('href')]);
};
// Add correct CSS selector for the widget. The Facets JS API will
// register handlers on that element.
$widget.addClass('js-facets-widget');
// Add handler for clicks on widget links.
$widgetLinks.on('click', clickHandler);
});
// We have to trigger attaching of behaviours, so that Facets JS API can
// register handlers on link widgets.
Drupal.attachBehaviors(context, Drupal.settings);
}
}
};
})(jQuery, Drupal);
......@@ -2,8 +2,6 @@
namespace Drupal\facets\Plugin\facets\widget;
use Drupal\facets\FacetInterface;
/**
* The checkbox / radios widget.
*
......@@ -18,11 +16,9 @@ class CheckboxWidget extends LinksWidget {
/**
* {@inheritdoc}
*/
public function build(FacetInterface $facet) {
$build = parent::build($facet);
protected function appendWidgetLibrary(array &$build) {
$build['#attributes']['class'][] = 'js-facets-checkbox-links';
$build['#attached']['library'][] = 'facets/drupal.facets.checkbox-widget';
return $build;
}
}
......@@ -40,6 +40,7 @@ class LinksWidget extends WidgetPluginBase {
*/
public function build(FacetInterface $facet) {
$build = parent::build($facet);
$this->appendWidgetLibrary($build);
$soft_limit = (int) $this->getConfiguration()['soft_limit'];
if ($soft_limit !== 0) {
$show_less_label = $this->getConfiguration()['soft_limit_settings']['show_less_label'];
......@@ -113,6 +114,17 @@ class LinksWidget extends WidgetPluginBase {
return $build;
}
/**
* Appends widget library and relevant information for it to build array.
*
* @param array $build
* Reference to build array.
*/
protected function appendWidgetLibrary(array &$build) {
$build['#attached']['library'][] = 'facets/drupal.facets.link-widget';
$build['#attributes']['class'][] = 'js-facets-links';
}
/**
* {@inheritdoc}
*/
......
......@@ -73,6 +73,110 @@ class AjaxBehaviorTest extends JsBase {
$this->assertEmpty($links);
}
/**
* Tests ajax dropdown.
*/
public function testAjaxDropdown() {
// Create facets.
$this->createFacet('owl');
$this->createFacet('duck', 'category', 'dropdown', []);
// Go to the views page.
$this->drupalGet('search-api-test-fulltext');
// Make sure the blocks are shown on the page.
$page = $this->getSession()->getPage();
$block_owl = $page->findById('block-owl-block');
$block_owl->isVisible();
$block_duck = $page->findById('block-duck-block');
$block_duck->isVisible();
$this->assertSession()->pageTextContains('Displaying 5 search results');
// Check that the article_category option disappears when filtering on item.
$dropdown_entry = $this->xpath('//*[@id="block-duck-block"]/div/select/option[normalize-space(text())=:label]', [':label' => 'article_category']);
$this->assertNotEmpty($dropdown_entry);
$block_owl->clickLink('item');
$this->assertSession()->assertWaitOnAjaxRequest();
$dropdown_entry = $this->xpath('//*[@id="block-duck-block"]/div/select/option[normalize-space(text())=:label]', [':label' => 'article_category']);
$this->assertEmpty($dropdown_entry);
// Click the item facet again.
$block_owl->clickLink('item');
$this->assertSession()->assertWaitOnAjaxRequest();
// Select the article_category in the dropdown.
$dropdown = $this->xpath('//*[@id="block-duck-block"]/div/select');
$dropdown[0]->selectOption('article_category');
$this->assertSession()->assertWaitOnAjaxRequest();
$this->assertSession()->pageTextContains('Displaying 2 search results');
// Check that the article link exists (and is formatted like a facet) link.
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'article']);
$this->assertNotEmpty($links);
// Check that the item link didn't exists.
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'item']);
$this->assertEmpty($links);
}
/**
* Tests ajax checkbox.
*/
public function testAjaxCheckbox() {
// Create facets.
$this->createFacet('owl');
$this->createFacet('duck', 'keywords', 'checkbox');
// Go to the views page.
$this->drupalGet('search-api-test-fulltext');
// Make sure the blocks are shown on the page.
$page = $this->getSession()->getPage();
$block_owl = $page->findById('block-owl-block');
$block_owl->isVisible();
$block_duck = $page->findById('block-duck-block');
$block_duck->isVisible();
$this->assertSession()->pageTextContains('Displaying 5 search results');
// Check that the article link exists (and is formatted like a facet) link.
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'article']);
$this->assertNotEmpty($links);
// Click the item facet.
$this->clickLink('item');
$this->assertSession()->assertWaitOnAjaxRequest();
$this->assertSession()->pageTextContains('Displaying 3 search results');
// Check that the article facet is now gone.
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'article']);
$this->assertEmpty($links);
// Click the item facet again, and check that the article facet is back.
$this->clickLink('item');
$this->assertSession()->assertWaitOnAjaxRequest();
$this->assertSession()->pageTextContains('Displaying 5 search results');
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'article']);
$this->assertNotEmpty($links);
// Check that the strawberry link disappears when filtering on items.
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'strawberry']);
$this->assertNotEmpty($links);
$this->clickLink('item');
$this->assertSession()->assertWaitOnAjaxRequest();
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'strawberry']);
$this->assertEmpty($links);
$this->clickLink('item');
$this->getSession()->getPage()->checkField('strawberry');
// Check that the article link exists (and is formatted like a facet) link.
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'article']);
$this->assertNotEmpty($links);
// Check that the item link didn't exists.
$links = $this->xpath('//a//span[normalize-space(text())=:label]', [':label' => 'item']);
$this->assertEmpty($links);
}
/**
* Tests links with exposed filters.
*/
......
......@@ -134,8 +134,16 @@ abstract class JsBase extends WebDriverTestBase {
* The id of the facet.
* @param string $field
* The field name.
* @param string $widget_type
* The type of the facet widget. links by default.
* @param array $widget_settings
* The widget config.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\Core\Entity\EntityStorageException
*/
protected function createFacet($id, $field = 'type') {
protected function createFacet($id, $field = 'type', $widget_type = 'links', array $widget_settings = ['show_numbers' => TRUE, 'soft_limit' => 0]) {
$facet_storage = \Drupal::entityTypeManager()->getStorage('facets_facet');
// Create and save a facet with a checkbox widget.
$facet_storage->create([
......@@ -147,11 +155,8 @@ abstract class JsBase extends WebDriverTestBase {
'empty_behavior' => ['behavior' => 'none'],
'weight' => 1,
'widget' => [
'type' => 'links',
'config' => [
'show_numbers' => TRUE,
'soft_limit' => 0,
],
'type' => $widget_type,
'config' => $widget_settings,
],
'processor_configs' => [
'url_processor_handler' => [
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment