diff --git a/docs/admin/settings/settings_ui.rst b/docs/admin/settings/settings_ui.rst index 8f390e58d..0039f6fb2 100644 --- a/docs/admin/settings/settings_ui.rst +++ b/docs/admin/settings/settings_ui.rst @@ -19,6 +19,7 @@ default_theme: simple theme_args: simple_style: auto + search_on_category_select: true .. _static_use_hash: @@ -60,3 +61,6 @@ ``results_on_new_tab``: Open result links in a new tab by default. + +``search_on_category_select``: + Perform search immediately if a category selected. Disable to select multiple categories. diff --git a/docs/dev/search_api.rst b/docs/dev/search_api.rst index 423232090..13858ae9e 100644 --- a/docs/dev/search_api.rst +++ b/docs/dev/search_api.rst @@ -92,16 +92,14 @@ Parameters List of enabled plugins. :default: - ``Hash_plugin``, ``Search_on_category_select``, - ``Self_Information``, ``Tracker_URL_remover``, - ``Ahmia_blacklist`` + ``Hash_plugin``, ``Self_Information``, + ``Tracker_URL_remover``, ``Ahmia_blacklist`` :values: .. enabled by default - ``Hash_plugin``, ``Search_on_category_select``, - ``Self_Information``, ``Tracker_URL_remover``, - ``Ahmia_blacklist``, + ``Hash_plugin``, ``Self_Information``, + ``Tracker_URL_remover``, ``Ahmia_blacklist``, .. disabled by default diff --git a/searx/plugins/search_on_category_select.py b/searx/plugins/search_on_category_select.py deleted file mode 100644 index 85b73a9bd..000000000 --- a/searx/plugins/search_on_category_select.py +++ /dev/null @@ -1,24 +0,0 @@ -''' -searx is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -searx is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with searx. If not, see < http://www.gnu.org/licenses/ >. - -(C) 2015 by Adam Tauber, -''' -from flask_babel import gettext - -name = gettext('Search on category select') -description = gettext( - 'Perform search immediately if a category selected. Disable to select multiple categories. (JavaScript required)' -) -default_on = True -preference_section = 'ui' diff --git a/searx/preferences.py b/searx/preferences.py index 0c59effc4..20d3eb2cb 100644 --- a/searx/preferences.py +++ b/searx/preferences.py @@ -461,6 +461,10 @@ class Preferences: settings['ui']['infinite_scroll'], locked=is_locked('infinite_scroll') ), + 'search_on_category_select': BooleanSetting( + settings['ui']['search_on_category_select'], + locked=is_locked('search_on_category_select') + ), # fmt: on } diff --git a/searx/settings.yml b/searx/settings.yml index bd2cc1bfb..27ecc1a3e 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -123,6 +123,9 @@ ui: theme_args: # style of simple theme: auto, light, dark simple_style: auto + # Perform search immediately if a category selected. + # Disable to select multiple categories at once and start the search manually. + search_on_category_select: true # Lock arbitrary settings on the preferences page. To find the ID of the user # setting you want to lock, check the ID of the form on the page "preferences". diff --git a/searx/settings_defaults.py b/searx/settings_defaults.py index c6a603c16..fa39796a3 100644 --- a/searx/settings_defaults.py +++ b/searx/settings_defaults.py @@ -199,6 +199,7 @@ SCHEMA = { 'query_in_title': SettingsValue(bool, False), 'infinite_scroll': SettingsValue(bool, False), 'cache_url': SettingsValue(str, 'https://web.archive.org/web/'), + 'search_on_category_select': SettingsValue(bool, True), }, 'preferences': { 'lock': SettingsValue(list, []), diff --git a/searx/static/themes/simple/src/js/main/search.js b/searx/static/themes/simple/src/js/main/search.js index 361d2fdcf..2ad8e48c5 100644 --- a/searx/static/themes/simple/src/js/main/search.js +++ b/searx/static/themes/simple/src/js/main/search.js @@ -151,28 +151,27 @@ } // vanilla js version of search_on_category_select.js - if (qinput !== null && d.querySelector('.help') != null && searxng.settings.search_on_category_select) { - d.querySelector('.help').className = 'invisible'; - - searxng.on('#categories input', 'change', function () { - var i, categories = d.querySelectorAll('#categories input[type="checkbox"]'); - for (i = 0; i < categories.length; i++) { - if (categories[i] !== this && categories[i].checked) { - categories[i].click(); - } - } - if (! this.checked) { - this.click(); - } - submitIfQuery(); - return false; - }); - + if (qinput !== null && searxng.settings.search_on_category_select) { searxng.on(d.getElementById('safesearch'), 'change', submitIfQuery); searxng.on(d.getElementById('time_range'), 'change', submitIfQuery); searxng.on(d.getElementById('language'), 'change', submitIfQuery); } + // most common browsers at the time of writing this support :has, except for Firefox + // can be removed when Firefox / Firefox ESL starts supporting it as well + try { + // this fails when the browser does not support :has + d.querySelector("html:has(body)"); + } catch (_) { + // manually deselect the old selection when a new category is selected + for (let button of d.querySelectorAll("button.category_button")) { + searxng.on(button, 'click', () => { + const selected = d.querySelector("button.category_button.selected"); + console.log(selected); + selected.classList.remove("selected"); + }) + } + } }); })(window, document, window.searxng); diff --git a/searx/static/themes/simple/src/less/search.less b/searx/static/themes/simple/src/less/search.less index 0338f9667..c4f7fe942 100644 --- a/searx/static/themes/simple/src/less/search.less +++ b/searx/static/themes/simple/src/less/search.less @@ -23,12 +23,15 @@ "spacer categories"; } -.category { +.category_checkbox, +.category_button { display: inline-block; position: relative; .ltr-margin-right(1rem); padding: 0; +} +.category_checkbox { input { display: none; } @@ -57,6 +60,35 @@ } } +button.category_button { + background-color: inherit; + color: var(--color-base-font); + cursor: pointer; + padding: 0.2rem 0; + display: inline-flex; + align-items: center; + text-transform: capitalize; + font-size: 0.9em; + border: none; + border-bottom: 2px solid transparent; + + svg { + padding-right: 0.2rem; + } + + &.selected, + &:active, + &:focus-within { + color: var(--color-categories-item-selected-font); + border-bottom: 2px solid var(--color-categories-item-border-selected); + } +} + +#categories_container:has(button.category_button:focus-within) button.category_button.selected { + color: var(--color-base-font); + border-bottom: none; +} + #search_logo { grid-area: logo; display: flex; @@ -205,11 +237,6 @@ html.no-js #clear_search.hide_if_nojs { #categories { font-size: 90%; clear: both; - - .checkbox_container { - margin: auto; - margin-top: 2px; - } } } @@ -229,7 +256,7 @@ html.no-js #clear_search.hide_if_nojs { #categories_container { width: max-content; - .category { + .category_checkbox { display: inline-block; width: auto; } @@ -281,16 +308,23 @@ html.no-js #clear_search.hide_if_nojs { width: auto; margin: 0; + svg { + display: none; + } + } + + .category_checkbox { label { padding: 1rem !important; margin: 0 !important; - - svg { - display: none; - } } } + .category_button { + padding: 1rem !important; + margin: 0 !important; + } + #search_view:focus-within { display: block; background-color: var(--color-search-background); diff --git a/searx/templates/simple/categories.html b/searx/templates/simple/categories.html index 29616f127..6ba550015 100644 --- a/searx/templates/simple/categories.html +++ b/searx/templates/simple/categories.html @@ -13,14 +13,25 @@ } -%}
{{- '' -}}
- {%- for category in categories -%} -
- -
- {%- endfor -%} - {%- if display_tooltip %}
{{ _('Click on the magnifier to perform search') }}
{% endif -%} + {%- if not search_on_category_select or not display_tooltip -%} + {%- for category in categories_as_tabs -%} +
{{- '' -}} + + +
+ {%- endfor -%} + {%- if display_tooltip %}
{{ _('Click on the magnifier to perform search') }}
{% endif -%} + {%- else -%} + {%- for category in categories_as_tabs -%}{{- '\n' -}} + {{- '' -}} + {%- endfor -%} + {{- '\n' -}} + {%- endif -%}
{{- '' -}}
diff --git a/searx/templates/simple/preferences.html b/searx/templates/simple/preferences.html index 22979ab05..3d62682bb 100644 --- a/searx/templates/simple/preferences.html +++ b/searx/templates/simple/preferences.html @@ -197,6 +197,9 @@ {%- if 'infinite_scroll' not in locked_preferences -%} {%- include 'simple/preferences/infinite_scroll.html' -%} {%- endif -%} + {%- if 'search_on_category_select' not in locked_preferences -%} + {%- include 'simple/preferences/search_on_category_select.html' -%} + {%- endif -%} {{- plugin_preferences('ui') -}} {{- tab_footer() -}} diff --git a/searx/templates/simple/preferences/search_on_category_select.html b/searx/templates/simple/preferences/search_on_category_select.html new file mode 100644 index 000000000..2bc680a61 --- /dev/null +++ b/searx/templates/simple/preferences/search_on_category_select.html @@ -0,0 +1,16 @@ +
{{- '' -}} + {{ _('Search on category select') }}{{- '' -}} +

{{- '' -}} + {{- '' -}} +

{{- '' -}} +
+ {{- _('Perform search immediately if a category selected. Disable to select multiple categories') -}} +
{{- '' -}} +
{{- '' -}} \ No newline at end of file diff --git a/searx/webapp.py b/searx/webapp.py index aa5e545d5..719ff92a1 100755 --- a/searx/webapp.py +++ b/searx/webapp.py @@ -361,7 +361,7 @@ def get_client_settings(): 'http_method': req_pref.get_value('method'), 'infinite_scroll': req_pref.get_value('infinite_scroll'), 'translations': get_translations(), - 'search_on_category_select': req_pref.plugins.choices['searx.plugins.search_on_category_select'], + 'search_on_category_select': req_pref.get_value('searx.plugins.search_on_category_select'), 'hotkeys': req_pref.plugins.choices['searx.plugins.vim_hotkeys'], 'theme_static_path': custom_url_for('static', filename='themes/simple'), } @@ -389,6 +389,7 @@ def render(template_name: str, **kwargs): kwargs['preferences'] = request.preferences kwargs['autocomplete'] = request.preferences.get_value('autocomplete') kwargs['infinite_scroll'] = request.preferences.get_value('infinite_scroll') + kwargs['search_on_category_select'] = request.preferences.get_value('search_on_category_select') kwargs['results_on_new_tab'] = request.preferences.get_value('results_on_new_tab') kwargs['advanced_search'] = request.preferences.get_value('advanced_search') kwargs['query_in_title'] = request.preferences.get_value('query_in_title')