Hacking searx
In no specific order...
I want to add a new checkbox for the custom_option. I direct preferences.html to the the preferences folder and then add a new template for the option.
Update the preferences UI: searx/templates/preferences/custom_option.html, simply copy center_alignment.html and rename it to custom_option.html for this exercise.
<fieldset>{{- '' -}}
<legend id="pref_custom_option">{{ _('Custom Option Language') }}</legend>{{- '' -}}
<p class="value">{{- '' -}}
<input type="checkbox" {{- ' ' -}}
name="custom_option" {{- ' ' -}}
aria-labelledby="pref_custom_option" {{- ' ' -}}
class="checkbox-onoff" {{- ' ' -}}
{%- if preferences.get_value('custom_option') -%}
checked
{%- endif -%}{{- ' ' -}}
/>{{- '' -}}
</p>{{- '' -}}
<div class="description">
{{- _('Displays my cock (Oscar layout).') -}}
</div>{{- '' -}}
</fieldset>{{- '' -}}
Add the custom template to preferences.html: searx/templates/preferences.html, for example line 197 slot in...
{%- if 'custom_option' not in locked_preferences -%}
{%- include 'simple/preferences/custom_option.html' -%}
{%- endif -%}
Open searx/preferences.py and add a new preference say on line 450
'custom_option': BooleanSetting(
settings['ui']['custom_option'],
locked=is_locked('custom_option')
),
Add the setting in settings.yaml... line 131
custom_option: false
Open searx/settings_defaults.py on Line 199 add...
'custom_option': SettingsValue(bool, False),
Open searx/webapp.py on Line 396 add...
kwargs['custom_option'] = request.preferences.get_value('custom_option')
Other Changes
Version 2024.6.23
- 1)**
If no search is entered, the search is performed with q="" and the page refreshes, giving the start page again.
Check the result on different existing search engines, push the search button with no query.
In google, pushing the search button with no query gives trending topics
In DuckDuckGo, the search button is disabled until search query is entered
The solution is to replicate the DuckDuckGo action. Disable the button until a search term is entered.
Two layers, requires no python code change...
Add the html5 tag ** required ** in both the template searches, one being the search.html and the other being simple_search.html, output a tooltip. However, this tooltip is only never shown if JavaScript is disabled and if previous html5 browser is used. Add the required tag.
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" autocomplete="off" autocapitalize="none" spellcheck="false" autocorrect="off" dir="auto" value="{{ q or '' }}" required>
Adding the required tag will also add a input box hover tooltip.
The DuckDuckGo JavaScript solution along with the required tag is...
<style>
#send_search:disabled,.category_button:disabled {
pointer-events: none;
opacity: 0.5; /* Optionally, to visually indicate the disabled state */
}</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('q');
const searchButton = document.getElementById('send_search');
const clearButton = document.getElementById('clear_search');
const form = document.getElementById('search');
const categoryButtons = document.querySelectorAll('.category_button');
// Function to toggle the search button state
function toggleSearchButton() {
const isInputEmpty = searchInput.value.trim() === '';
searchButton.disabled = isInputEmpty;
toggleCategoryButtons(isInputEmpty);
}
// Function to toggle the state of all category buttons
function toggleCategoryButtons(isDisabled) {
categoryButtons.forEach(button => {
button.disabled = isDisabled;
});
}
// Add input event listener to toggle the search and category buttons
searchInput.addEventListener('input', toggleSearchButton);
// Add click event listener to the clear button
clearButton.addEventListener('click', function() {
// Clear the input
searchInput.value = '';
// Disable the search and category buttons
toggleSearchButton();
});
// Add reset event listener to the form
form.addEventListener('reset', function() {
// Delay to allow the reset to complete
setTimeout(toggleSearchButton, 0);
});
// Initial check in case there's a pre-filled value
toggleSearchButton();
});
</script>
The existing python code handles the situation, so it's not technically a bug, but might be a slight efficiency improvement.
- 2)**
Also, if a search is pasted rather than entered by keyboard, the x clear button does not appear but still works. The x icon does not appear if no keyboard is used and the search term is pasted. Thereafter, if the keyboard is used, the clear input x appears. The JavaScript has something to do with keyboard and perhaps not onchange.
The fix is to look for the input event /searxng.min.js:
function a(t){
var e=document.getElementById("clear_search");
var n=function(){
if(t.value.length===0){
e.classList.add("empty")
}else{
e.classList.remove("empty")
}
};
n();
e.addEventListener("click",function(e){
t.value="";
t.focus();
n();
e.preventDefault()
});
t.addEventListener("keyup",n,false);
t.addEventListener("input",n,false); // Add this line to handle paste events
}
- 3)**
While the input box handles text entry to an unlimited length which is great as it does not inhibit the user, the left whitespace and training whitespace are not counted, but they appear in the input box. The JavaScript trim() method is used to remove leading and trailing whitespace from the input value.
document.addEventListener('DOMContentLoaded', (event) => {
const searchForm = document.getElementById('search');
const searchInput = document.getElementById('q');
searchForm.addEventListener('submit', (event) => {
const trimmedValue = searchInput.value.trim();
searchInput.value = trimmedValue;
});
});
- 4)**
When the search drop down box offers suggestions auto complete I do not think it should auto execute on selection, as the user may not be finished with working with the input box and may use the input as a builder of a complete search term where the autocomplete may not offer a match or another case, and it should also be careful how if it rewrites the input box. For example: user types test, the suggestion is "test speed", it is selected and executes, but the user actually has not finished with the search term. They may have wanted, "test speed of my leopard"...
// t.submit() // disable the submission of combo box
Now when enter more search terms, the auto complete will attempt to keep guessing and try and rework the search term.
- 5)**
Placing autofocus to send the cursor directly to the input box for keyboard input in both templates/ simple_search.html and search.html
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" autocomplete="off" autocapitalize="none" spellcheck="false" autocorrect="off" dir="auto" value="{{ q or '' }}" required autofocus>
and
<script>
document.addEventListener("DOMContentLoaded", function() {
const searchInput = document.getElementById("q");
if (searchInput) {
searchInput.focus();
const length = searchInput.value.length;
searchInput.setSelectionRange(length, length);
}
});
</script>
Autofocus is not supported by some browsers and I cannot get it to set correctly in Firefox with the HTML 5 tag or the JavaScript, sometimes it's there correctly.