diff --git a/facets.libraries.yml b/facets.libraries.yml index 62daaf3..23cbc63 100644 --- a/facets.libraries.yml +++ b/facets.libraries.yml @@ -28,3 +28,13 @@ drupal.facets.checkbox-widget: dependencies: - core/jquery - core/drupal + - core/jquery.once + +drupal.facets.dropdown-widget: + version: VERSION + js: + js/dropdown-widget.js: {} + dependencies: + - core/jquery + - core/drupal + - core/jquery.once \ No newline at end of file diff --git a/js/dropdown-widget.js b/js/dropdown-widget.js new file mode 100644 index 0000000..8eb113f --- /dev/null +++ b/js/dropdown-widget.js @@ -0,0 +1,50 @@ +/** + * @file + * Transforms links into a dropdown list. + */ + +(function ($) { + + "use strict"; + + var $dropdown = '"; + + $('.js-facets-dropdown-links .item-list').html($dropdown); + + // Go to the selected option when it's clicked. + $('.facets-dropdown').on('change', function() { + window.location.href = this.value; + }); + }; + + /** + * Create an option for the dropdown list and append it to it. + */ + Drupal.facets.makeOption = function () { + var $link = $(this)[0]; + var href = $($link.innerHTML)[0].href; + var text = $link.innerText.replace('(-) ',''); + var option = ''; + + $dropdown += option; + }; + +})(jQuery); diff --git a/src/Form/DropdownWidgetForm.php b/src/Form/DropdownWidgetForm.php deleted file mode 100644 index afd09d9..0000000 --- a/src/Form/DropdownWidgetForm.php +++ /dev/null @@ -1,111 +0,0 @@ -facet = $facet; - } - - /** - * {@inheritdoc} - */ - public function getBaseFormId() { - return 'facets_dropdown_widget'; - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return $this->getBaseFormId() . '__' . $this->facet->id(); - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state) { - $results = $this->facet->getResults(); - - $configuration = $this->facet->getWidgetConfigs(); - $form[$this->facet->getFieldAlias()] = [ - '#type' => 'select', - '#title' => $this->facet->getName(), - '#default_value' => '_none', - ]; - - $options = []; - $active_result_url = '_none'; - foreach ($results as $result) { - $result_url = $result->getUrl()->setAbsolute()->toString(); - - $text = $result->getDisplayValue(); - if (!empty($configuration['show_numbers'])) { - $text .= ' (' . $result->getCount() . ')'; - } - - if ($result->isActive()) { - $options['_none'] = $text; - $active_result_url = $result_url; - } - else { - $options[$result_url] = $text; - } - } - - $options = [$active_result_url => $this->t('- All -')] + $options; - - $form[$this->facet->getFieldAlias()]['#options'] = $options; - - $form[$this->facet->getFieldAlias() . '_submit'] = [ - '#type' => 'submit', - '#value' => 'submit', - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $field_alias = $this->facet->getFieldAlias(); - $form_value = $form_state->getValue($field_alias); - if ($form_value != '_none') { - $form_state->setResponse(new RedirectResponse($form_value)); - } - } - -} diff --git a/src/Plugin/facets/widget/DropdownWidget.php b/src/Plugin/facets/widget/DropdownWidget.php index 5a90347..0e48bdc 100644 --- a/src/Plugin/facets/widget/DropdownWidget.php +++ b/src/Plugin/facets/widget/DropdownWidget.php @@ -2,11 +2,8 @@ namespace Drupal\facets\Plugin\facets\widget; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\facets\FacetInterface; -use Drupal\facets\Form\DropdownWidgetForm; -use Drupal\facets\Widget\WidgetInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * The dropdown widget. @@ -17,44 +14,54 @@ use Drupal\facets\Widget\WidgetInterface; * description = @Translation("A configurable widget that shows a dropdown."), * ) */ -class DropdownWidget implements WidgetInterface { - use StringTranslationTrait; +class DropdownWidget extends LinksWidget{ /** - * {@inheritdoc} + * The facet the widget is being built for. + * + * @var \Drupal\facets\FacetInterface */ - public function build(FacetInterface $facet) { - $form_builder = \Drupal::getContainer()->get('form_builder'); - $form_object = new DropdownWidgetForm($facet); - return $form_builder->getForm($form_object); - } + protected $facet; /** * {@inheritdoc} */ - public function getQueryType($query_types) { - return $query_types['string']; - } + public function build(FacetInterface $facet) { - /** - * {@inheritdoc} - */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state, $config) { + $this->facet = $facet; - $form['show_numbers'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Show the amount of results'), - ]; + /** @var \Drupal\facets\Result\Result[] $results */ + $results = $facet->getResults(); + $items = []; + + $configuration = $facet->getWidgetConfigs(); + $this->showNumbers = empty($configuration['show_numbers']) ? FALSE : (bool) $configuration['show_numbers']; - if (!is_null($config)) { - $widget_configs = $config->get('widget_configs'); - if (isset($widget_configs['show_numbers'])) { - $form['show_numbers']['#default_value'] = $widget_configs['show_numbers']; + foreach ($results as $result) { + if (is_null($result->getUrl())) { + $text = $this->extractText($result); + $items[] = ['#markup' => $text]; + } + else { + $items[] = $this->buildListItems($result); } } - return $form; + $build = [ + '#theme' => 'item_list', + '#items' => $items, + '#attributes' => ['class' => ['js-facets-dropdown-links']], + '#cache' => [ + 'contexts' => [ + 'url.path', + 'url.query_args', + ], + ], + ]; + $build['#attached']['library'][] = 'facets/drupal.facets.dropdown-widget'; + + return $build; } } diff --git a/tests/src/Unit/Form/SelectWidgetFormTest.php b/tests/src/Unit/Form/SelectWidgetFormTest.php deleted file mode 100644 index d237cbf..0000000 --- a/tests/src/Unit/Form/SelectWidgetFormTest.php +++ /dev/null @@ -1,159 +0,0 @@ -setUrl(new Url('llama')); - $result2 = new Result('badger', 'Badger', 20); - $result2->setUrl(new Url('badger')); - $result3 = new Result('duck', 'Duck', 15); - $result3->setUrl(new Url('duck')); - $result4 = new Result('alpaca', 'Alpaca', 9); - $result4->setUrl(new Url('alpaca')); - - $this->originalResults = [ - $result, - $result2, - $result3, - $result4, - ]; - - $url_generator = $this->getMock(UrlGeneratorInterface::class); - $url_generator->expects($this->any()) - ->method('generateFromRoute') - ->willReturnCallback(function ($param) { - return 'http://test/' . $param; - }); - $string_translation = $this->getMockBuilder(TranslationManager::class) - ->disableOriginalConstructor() - ->getMock(); - - $container_builder = new ContainerBuilder(); - $container_builder->set('url_generator', $url_generator); - $container_builder->set('string_translation', $string_translation); - \Drupal::setContainer($container_builder); - } - - /** - * Tests widget form with default settings. - */ - public function testDefaultSettings() { - $facet = new Facet(['id' => 'zoo_animal'], 'facet'); - $facet->setResults($this->originalResults); - $facet->setFieldIdentifier('zoo_animal'); - - $form_state = new FormState(); - $form_state->addBuildInfo('args', [$facet]); - $form = []; - - $widget_form = new DropdownWidgetForm($facet); - $built_form = $widget_form->buildForm($form, $form_state); - - $this->assertInternalType('array', $built_form); - $this->assertCount(5, $built_form['zoo_animal']['#options']); - $this->assertEquals('select', $built_form['zoo_animal']['#type']); - - $expected_links = [ - 'http://test/llama' => 'Llama', - 'http://test/badger' => 'Badger', - 'http://test/duck' => 'Duck', - 'http://test/alpaca' => 'Alpaca', - ]; - foreach ($expected_links as $index => $value) { - $this->assertEquals($value, $built_form['zoo_animal']['#options'][$index]); - } - $this->assertEquals(array('zoo_animal', 'zoo_animal_submit'), array_keys($built_form)); - } - - /** - * Tests widget form, make sure hiding and showing numbers works. - */ - public function testHideNumbers() { - $facet = new Facet([], 'facet'); - $facet->setResults($this->originalResults); - $facet->setFieldIdentifier('zoo__animal'); - $facet->setWidgetConfigs(['show_numbers' => 0]); - - $form_state = new FormState(); - $form_state->addBuildInfo('args', [$facet]); - $form = []; - - $widget_form = new DropdownWidgetForm($facet); - $built_form = $widget_form->buildForm($form, $form_state); - - $this->assertInternalType('array', $built_form); - $this->assertCount(5, $built_form['zoo__animal']['#options']); - $expected_links = [ - 'http://test/llama' => 'Llama', - 'http://test/badger' => 'Badger', - 'http://test/duck' => 'Duck', - 'http://test/alpaca' => 'Alpaca', - ]; - foreach ($expected_links as $index => $value) { - $this->assertEquals($value, $built_form['zoo__animal']['#options'][$index]); - } - - // Enable the 'show_numbers' setting again to make sure that the switch - // between those settings works. - $facet->setWidgetConfigs(['show_numbers' => 1]); - - $built_form = $widget_form->buildForm($form, $form_state); - $this->assertInternalType('array', $built_form); - $this->assertCount(5, $built_form['zoo__animal']['#options']); - - $expected_links = [ - 'http://test/llama' => 'Llama (10)', - 'http://test/badger' => 'Badger (20)', - 'http://test/duck' => 'Duck (15)', - 'http://test/alpaca' => 'Alpaca (9)', - ]; - foreach ($expected_links as $index => $value) { - $this->assertEquals($value, $built_form['zoo__animal']['#options'][$index]); - } - } - - /** - * Tests form default methods. - */ - public function testForm() { - $facet = new Facet(['id' => 'donkey'], 'facet'); - $facet->setResults($this->originalResults); - $facet->setFieldIdentifier('donkey'); - - $form = new DropdownWidgetForm($facet); - - $this->assertEquals('facets_dropdown_widget', $form->getBaseFormId()); - $this->assertEquals('facets_dropdown_widget__donkey', $form->getFormId()); - } - -} diff --git a/tests/src/Unit/Plugin/widget/SelectWidgetTest.php b/tests/src/Unit/Plugin/widget/SelectWidgetTest.php index 8f1bf73..6ef4664 100644 --- a/tests/src/Unit/Plugin/widget/SelectWidgetTest.php +++ b/tests/src/Unit/Plugin/widget/SelectWidgetTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\facets\Unit\Plugin\widget; +use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Url; use Drupal\facets\Entity\Facet; use Drupal\facets\Plugin\facets\widget\DropdownWidget; @@ -49,35 +50,64 @@ class SelectWidgetTest extends UnitTestCase { } $this->originalResults = $original_results; - $form_builder = $this->getMockBuilder('\Drupal\Core\Form\FormBuilder') - ->disableOriginalConstructor() - ->getMock(); - $form_builder->expects($this->once()) - ->method('getForm') - ->willReturn('build'); - - $string_translation = $this->getMockBuilder('\Drupal\Core\StringTranslation\TranslationManager') - ->disableOriginalConstructor() - ->getMock(); - - $container_builder = new ContainerBuilder(); - $container_builder->set('form_builder', $form_builder); - $container_builder->set('string_translation', $string_translation); - \Drupal::setContainer($container_builder); - $this->widget = new DropdownWidget(); } /** - * Tests widget with default settings. + * Tests widget without filters. */ - public function testDefaultSettings() { + public function testNoFilterResults() { $facet = new Facet([], 'facet'); $facet->setResults($this->originalResults); - $facet->setFieldIdentifier('test_field'); + $facet->setWidgetConfigs(['show_numbers' => 1]); + + $output = $this->widget->build($facet); + + $this->assertInternalType('array', $output); + $this->assertCount(4, $output['#items']); - $built_form = $this->widget->build($facet); - $this->assertEquals('build', $built_form); + $this->assertEquals(['js-facets-dropdown-links'], $output['#attributes']['class']); + + $expected_links = [ + $this->buildLinkAssertion('Llama', 10), + $this->buildLinkAssertion('Badger', 20), + $this->buildLinkAssertion('Duck', 15), + $this->buildLinkAssertion('Alpaca', 9), + ]; + foreach ($expected_links as $index => $value) { + $this->assertInternalType('array', $output['#items'][$index]); + $this->assertEquals($value, $output['#items'][$index]['#title']); + $this->assertInstanceOf(FormattableMarkup::class, $output['#items'][$index]['#title']); + $this->assertEquals('link', $output['#items'][$index]['#type']); + $this->assertEquals(['facet-item'], $output['#items'][$index]['#wrapper_attributes']['class']); + } } + /** + * Build a formattable markup object to use in the other tests. + * + * @param string $text + * Text to display. + * @param int $count + * Number of results. + * @param bool $active + * Link is active. + * @param bool $show_numbers + * Numbers are displayed. + * + * @return \Drupal\Component\Render\FormattableMarkup + * Formattable markup object for link. + */ + private function buildLinkAssertion($text, $count = 0, $active = FALSE, $show_numbers = TRUE) { + $text = new FormattableMarkup('@text', ['@text' => $text, '@count' => $count]); + if ($show_numbers !== FALSE) { + $text->string .= ' (@count)'; + } + if ($active) { + $text->string = '(-) ' . $text->string; + } + return $text; + } + + }