[feat] search on category select without JS

Co-authored-by: Alexandre Flament <alex@al-f.net>
This commit is contained in:
Bnyro 2023-09-09 16:49:14 +02:00 committed by Markus Heiser
parent 90b0bfd1bf
commit a55e0ac553
12 changed files with 118 additions and 68 deletions

View file

@ -19,6 +19,7 @@
default_theme: simple default_theme: simple
theme_args: theme_args:
simple_style: auto simple_style: auto
search_on_category_select: true
.. _static_use_hash: .. _static_use_hash:
@ -60,3 +61,6 @@
``results_on_new_tab``: ``results_on_new_tab``:
Open result links in a new tab by default. 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.

View file

@ -92,16 +92,14 @@ Parameters
List of enabled plugins. List of enabled plugins.
:default: :default:
``Hash_plugin``, ``Search_on_category_select``, ``Hash_plugin``, ``Self_Information``,
``Self_Information``, ``Tracker_URL_remover``, ``Tracker_URL_remover``, ``Ahmia_blacklist``
``Ahmia_blacklist``
:values: :values:
.. enabled by default .. enabled by default
``Hash_plugin``, ``Search_on_category_select``, ``Hash_plugin``, ``Self_Information``,
``Self_Information``, ``Tracker_URL_remover``, ``Tracker_URL_remover``, ``Ahmia_blacklist``,
``Ahmia_blacklist``,
.. disabled by default .. disabled by default

View file

@ -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, <asciimoo@gmail.com>
'''
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'

View file

@ -461,6 +461,10 @@ class Preferences:
settings['ui']['infinite_scroll'], settings['ui']['infinite_scroll'],
locked=is_locked('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 # fmt: on
} }

View file

@ -123,6 +123,9 @@ ui:
theme_args: theme_args:
# style of simple theme: auto, light, dark # style of simple theme: auto, light, dark
simple_style: auto 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 # 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". # setting you want to lock, check the ID of the form on the page "preferences".

View file

@ -199,6 +199,7 @@ SCHEMA = {
'query_in_title': SettingsValue(bool, False), 'query_in_title': SettingsValue(bool, False),
'infinite_scroll': SettingsValue(bool, False), 'infinite_scroll': SettingsValue(bool, False),
'cache_url': SettingsValue(str, 'https://web.archive.org/web/'), 'cache_url': SettingsValue(str, 'https://web.archive.org/web/'),
'search_on_category_select': SettingsValue(bool, True),
}, },
'preferences': { 'preferences': {
'lock': SettingsValue(list, []), 'lock': SettingsValue(list, []),

View file

@ -151,28 +151,27 @@
} }
// vanilla js version of search_on_category_select.js // vanilla js version of search_on_category_select.js
if (qinput !== null && d.querySelector('.help') != null && searxng.settings.search_on_category_select) { if (qinput !== 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;
});
searxng.on(d.getElementById('safesearch'), 'change', submitIfQuery); searxng.on(d.getElementById('safesearch'), 'change', submitIfQuery);
searxng.on(d.getElementById('time_range'), 'change', submitIfQuery); searxng.on(d.getElementById('time_range'), 'change', submitIfQuery);
searxng.on(d.getElementById('language'), '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); })(window, document, window.searxng);

View file

@ -23,12 +23,15 @@
"spacer categories"; "spacer categories";
} }
.category { .category_checkbox,
.category_button {
display: inline-block; display: inline-block;
position: relative; position: relative;
.ltr-margin-right(1rem); .ltr-margin-right(1rem);
padding: 0; padding: 0;
}
.category_checkbox {
input { input {
display: none; 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 { #search_logo {
grid-area: logo; grid-area: logo;
display: flex; display: flex;
@ -205,11 +237,6 @@ html.no-js #clear_search.hide_if_nojs {
#categories { #categories {
font-size: 90%; font-size: 90%;
clear: both; clear: both;
.checkbox_container {
margin: auto;
margin-top: 2px;
}
} }
} }
@ -219,7 +246,7 @@ html.no-js #clear_search.hide_if_nojs {
#categories_container { #categories_container {
width: max-content; width: max-content;
.category { .category_checkbox {
display: inline-block; display: inline-block;
width: auto; width: auto;
} }
@ -271,14 +298,21 @@ html.no-js #clear_search.hide_if_nojs {
width: auto; width: auto;
margin: 0; margin: 0;
label {
padding: 1rem !important;
margin: 0 !important;
svg { svg {
display: none; display: none;
} }
} }
.category_checkbox {
label {
padding: 1rem !important;
margin: 0 !important;
}
}
.category_button {
padding: 1rem !important;
margin: 0 !important;
} }
#search_view:focus-within { #search_view:focus-within {

View file

@ -13,8 +13,10 @@
} -%} } -%}
<div id="categories" class="search_categories">{{- '' -}} <div id="categories" class="search_categories">{{- '' -}}
<div id="categories_container"> <div id="categories_container">
{%- for category in categories -%} {%- if not search_on_category_select or not display_tooltip -%}
<div class="category"><input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}"{% if category in selected_categories %} checked="checked"{% endif %}/> {%- for category in categories_as_tabs -%}
<div class="category category_checkbox">{{- '' -}}
<input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}"{% if category in selected_categories %} checked="checked"{% endif %}/>
<label for="checkbox_{{ category|replace(' ', '_') }}" class="tooltips"> <label for="checkbox_{{ category|replace(' ', '_') }}" class="tooltips">
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe-outline') -}} {{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe-outline') -}}
<div class="category_name">{{- _(category) -}}</div> <div class="category_name">{{- _(category) -}}</div>
@ -22,5 +24,14 @@
</div> </div>
{%- endfor -%} {%- endfor -%}
{%- if display_tooltip %}<div class="help">{{ _('Click on the magnifier to perform search') }}</div>{% endif -%} {%- if display_tooltip %}<div class="help">{{ _('Click on the magnifier to perform search') }}</div>{% endif -%}
{%- else -%}
{%- for category in categories_as_tabs -%}{{- '\n' -}}
<button type="submit" name="category_{{ category|replace(' ', '_') }}" class="category category_button {% if category in selected_categories %}selected{% endif %}">
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe-outline') -}}
<div class="category_name">{{- _(category) -}}</div>{{- '' -}}
</button>{{- '' -}}
{%- endfor -%}
{{- '\n' -}}
{%- endif -%}
</div>{{- '' -}} </div>{{- '' -}}
</div> </div>

View file

@ -197,6 +197,9 @@
{%- if 'infinite_scroll' not in locked_preferences -%} {%- if 'infinite_scroll' not in locked_preferences -%}
{%- include 'simple/preferences/infinite_scroll.html' -%} {%- include 'simple/preferences/infinite_scroll.html' -%}
{%- endif -%} {%- endif -%}
{%- if 'search_on_category_select' not in locked_preferences -%}
{%- include 'simple/preferences/search_on_category_select.html' -%}
{%- endif -%}
{{- plugin_preferences('ui') -}} {{- plugin_preferences('ui') -}}
{{- tab_footer() -}} {{- tab_footer() -}}

View file

@ -0,0 +1,16 @@
<fieldset>{{- '' -}}
<legend>{{ _('Search on category select') }}</legend>{{- '' -}}
<p class="value">{{- '' -}}
<input type="checkbox" {{- ' ' -}}
name="search_on_category_select" {{- ' ' -}}
aria-labelledby="pref_search_on_category_select" {{- ' ' -}}
class="checkbox-onoff" {{- ' ' -}}
{%- if preferences.get_value('search_on_category_select') -%}
checked
{%- endif -%}{{- ' ' -}}
/>{{- '' -}}
</p>{{- '' -}}
<div class="description">
{{- _('Perform search immediately if a category selected. Disable to select multiple categories') -}}
</div>{{- '' -}}
</fieldset>{{- '' -}}

View file

@ -361,7 +361,7 @@ def get_client_settings():
'http_method': req_pref.get_value('method'), 'http_method': req_pref.get_value('method'),
'infinite_scroll': req_pref.get_value('infinite_scroll'), 'infinite_scroll': req_pref.get_value('infinite_scroll'),
'translations': get_translations(), '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'], 'hotkeys': req_pref.plugins.choices['searx.plugins.vim_hotkeys'],
'theme_static_path': custom_url_for('static', filename='themes/simple'), '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['preferences'] = request.preferences
kwargs['autocomplete'] = request.preferences.get_value('autocomplete') kwargs['autocomplete'] = request.preferences.get_value('autocomplete')
kwargs['infinite_scroll'] = request.preferences.get_value('infinite_scroll') 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['results_on_new_tab'] = request.preferences.get_value('results_on_new_tab')
kwargs['advanced_search'] = request.preferences.get_value('advanced_search') kwargs['advanced_search'] = request.preferences.get_value('advanced_search')
kwargs['query_in_title'] = request.preferences.get_value('query_in_title') kwargs['query_in_title'] = request.preferences.get_value('query_in_title')