From 4d0cb6e1cdd7281b9ab09540927bc3c447fcff17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Gro=C3=9Fe?= <grosse@cosmocode.de> Date: Thu, 22 Mar 2018 15:48:14 +0100 Subject: [PATCH] feat(search): show search adjustments as links This simplifies many aspects. However, it still needs much better styling. --- inc/Ui/Search.php | 134 +++++++++++++++++++++++++----------------- lib/scripts/search.js | 53 +---------------- 2 files changed, 82 insertions(+), 105 deletions(-) diff --git a/inc/Ui/Search.php b/inc/Ui/Search.php index 0fab58db4..4f3b57683 100644 --- a/inc/Ui/Search.php +++ b/inc/Ui/Search.php @@ -131,33 +131,6 @@ class Search extends Ui */ protected function addSearchAssistanceElements(Form $searchForm, array $parsedQuery) { - $matchType = ''; - $searchTerm = null; - if (count($parsedQuery['words']) === 1) { - $searchTerm = $parsedQuery['words'][0]; - $firstChar = $searchTerm[0]; - $lastChar = substr($searchTerm, -1); - $matchType = 'exact'; - - if ($firstChar === '*') { - $matchType = 'starts'; - } - if ($lastChar === '*') { - $matchType = 'ends'; - } - if ($firstChar === '*' && $lastChar === '*') { - $matchType = 'contains'; - } - $searchTerm = trim($searchTerm, '*'); - } - - $searchForm->addTextInput( - 'searchTerm', - '', - $searchForm->findPositionByAttribute('type', 'submit') - ) - ->val($searchTerm) - ->attr('style', 'display: none;'); $searchForm->addButton('toggleAssistant', 'toggle search assistant') ->attr('type', 'button') ->id('search-results-form__show-assistance-button') @@ -167,22 +140,70 @@ class Search extends Ui ->addClass('js-advancedSearchOptions') ->attr('style', 'display: none;'); - $searchForm->addTagOpen('div')->addClass('search-results-form__subwrapper'); - $searchForm->addRadioButton('matchType', 'exact Match FM')->val('exact')->attr('checked', - $matchType === 'exact' ?: null); - $searchForm->addRadioButton('matchType', 'starts with FM')->val('starts')->attr('checked', - $matchType === 'starts' ?: null); - $searchForm->addRadioButton('matchType', 'ends with FM')->val('ends')->attr('checked', - $matchType === 'ends' ?: null); - $searchForm->addRadioButton('matchType', 'contains FM')->val('contains')->attr('checked', - $matchType === 'contains' ?: null); + $this->addFragmentBehaviorLinks($searchForm, $parsedQuery); + $this->addNamespaceSelector($searchForm, $parsedQuery); + $searchForm->addTagClose('div'); + } - $this->addNamespaceSelector($searchForm, $parsedQuery); + protected function addFragmentBehaviorLinks(Form $searchForm, array $parsedQuery) + { + $searchForm->addTagOpen('div')->addClass('search-results-form__subwrapper'); + + $this->addSearchLink( + $searchForm, + 'exact Match', + array_map(function($term){return trim($term, '*');},$this->parsedQuery['and']), + $this->parsedQuery['ns'] + ); + + $searchForm->addHTML(' '); + + $this->addSearchLink( + $searchForm, + 'starts with', + array_map(function($term){return trim($term, '*') . '*';},$this->parsedQuery['and']), + $this->parsedQuery['ns'] + ); + + $searchForm->addHTML(' '); + + $this->addSearchLink( + $searchForm, + 'ends with', + array_map(function($term){return '*' . trim($term, '*');},$this->parsedQuery['and']), + $this->parsedQuery['ns'] + ); + + $searchForm->addHTML(' '); + + $this->addSearchLink( + $searchForm, + 'contains', + array_map(function($term){return '*' . trim($term, '*') . '*';},$this->parsedQuery['and']), + $this->parsedQuery['ns'] + ); $searchForm->addTagClose('div'); } + protected function addSearchLink(Form $searchForm, $label, $and, $ns) { + $newQuery = ft_queryUnparser_simple( + $and, + [], + [], + $ns, + [] + ); + $searchForm->addTagOpen('a') + ->attrs([ + 'href' => wl($newQuery, ['do' => 'search', 'searchPageForm' => '1'], false, '&') + ]) + ; + $searchForm->addHTML($label); + $searchForm->addTagClose('a'); + } + /** * Add the elements for the namespace selector * @@ -192,26 +213,33 @@ class Search extends Ui protected function addNamespaceSelector(Form $searchForm, array $parsedQuery) { $baseNS = empty($parsedQuery['ns']) ? '' : $parsedQuery['ns'][0]; - $namespaces = []; $searchForm->addTagOpen('div')->addClass('search-results-form__subwrapper'); + if ($baseNS) { - $searchForm->addRadioButton('namespace', '(no namespace FIXME)')->val(''); - $parts = [$baseNS => count($this->fullTextResults)]; - $upperNameSpace = $baseNS; - while ($upperNameSpace = getNS($upperNameSpace)) { - $parts[$upperNameSpace] = 0; - } - $namespaces = array_reverse($parts); - }; + $searchForm->addTagOpen('div'); + + $this->addSearchLink( + $searchForm, + 'remove current namespace restriction', + $this->parsedQuery['and'], + [] + ); + + $searchForm->addTagClose('div'); + } + + $extraNS = $this->getAdditionalNamespacesFromResults($baseNS); + if (!empty($extraNS)) { + $searchForm->addTagOpen('div'); + $searchForm->addHTML('first level ns below current: '); - $namespaces = array_merge($namespaces, $this->getAdditionalNamespacesFromResults($baseNS)); + foreach ($extraNS as $extraNS => $count) { + $searchForm->addHTML(' '); + $label = $extraNS . ($count ? " ($count)" : ''); - foreach ($namespaces as $extraNS => $count) { - $label = $extraNS . ($count ? " ($count)" : ''); - $namespaceCB = $searchForm->addRadioButton('namespace', $label)->val($extraNS); - if ($extraNS === $baseNS) { - $namespaceCB->attr('checked', true); + $this->addSearchLink($searchForm, $label, $this->parsedQuery['and'], [$extraNS]); } + $searchForm->addTagClose('div'); } $searchForm->addTagClose('div'); @@ -385,7 +413,7 @@ class Search extends Ui [$ns], [] ); - $href = wl($newQuery, ['do' => 'search']); + $href = wl($newQuery, ['do' => 'search', 'searchPageForm' => '1']); $attributes = buildAttributes([ 'rel' => 'nofollow', 'class' => 'search_namespace_link', diff --git a/lib/scripts/search.js b/lib/scripts/search.js index 0c9dca76a..cf7399b5d 100644 --- a/lib/scripts/search.js +++ b/lib/scripts/search.js @@ -9,59 +9,8 @@ jQuery(function () { return; } const $toggleAssistanceButton = $searchForm.find('#search-results-form__show-assistance-button'); - const $queryInput = $searchForm.find('[name="id"]'); - const $termInput = $searchForm.find('[name="searchTerm"]'); $toggleAssistanceButton.on('click', function () { - jQuery('.js-advancedSearchOptions').toggle(); - $queryInput.toggle(); - $termInput.toggle(); + jQuery('.js-advancedSearchOptions').dw_toggle(); }); - - - const $matchTypeSwitcher = $searchForm.find('[name="matchType"]'); - const $namespaceSwitcher = $searchForm.find('[name="namespace"]'); - const $refiningElements = $termInput.add($matchTypeSwitcher).add($namespaceSwitcher); - $refiningElements.on('input change', function () { - $queryInput.val( - rebuildQuery( - $termInput.val(), - $matchTypeSwitcher.filter(':checked').val(), - $namespaceSwitcher.filter(':checked').val() - ) - ); - }); - - /** - * Rebuild the search query from the parts - * - * @param {string} searchTerm the word which is to be searched - * @param {enum} matchType the type of matching that is to be done - * @param {string} namespace list of namespaces to which to limit the search - * - * @return {string} the query string for the actual search - */ - function rebuildQuery(searchTerm, matchType, namespace) { - let query = ''; - - switch (matchType) { - case 'contains': - query = '*' + searchTerm + '*'; - break; - case 'starts': - query = '*' + searchTerm; - break; - case 'ends': - query = searchTerm + '*'; - break; - default: - query = searchTerm; - } - - if (namespace && namespace.length) { - query += ' @' + namespace; - } - - return query; - } }); -- GitLab