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
Tags 8.x-3.0-alpha21
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