I have the following code which works perfectly fine in any browser apart from safari, displaying a list of football clubs. Afterwards I have implemented a search bar, filtering the list with javascript.
Filtering works in chrome. Safari only displays the list of clubs and does nothing when typing in the filtering box. Everything has been tried on the settings side of safari and multiple computers have been used.
Maybe someone has an idea what is wrong...
<input type="text" id="filter" oninput="filterDropdown()" placeholder="Type to filter" >
<select id="dropdown" name="club_name" class="form-select bg-custom" size="17" aria-label="Size 10 select example" style="background-color: #B9B4C7;" >
<!-- <option selected></option> -->
{% for name in df["name"] %}
<option class="list bg-custom" data-league="{{ df[df['name']==name]['league'].values[0] }}" value="{{ name }}" {% if loop.first %}selected{% endif %}>{{ name }}</option>
{% endfor %}
</select>
JavaScript
function filterDropdown() {
// Get input value
var input, filter, dropdown, options, i, txtValue;
input = document.getElementById("filter");
filter = input.value.toUpperCase();
dropdown = document.getElementById("dropdown");
options = dropdown.getElementsByTagName("option");
// Loop through all options, hide those that don't match the filter
for (i = 0; i < options.length; i++) {
txtValue = options[i].text;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
options[i].style.display = "";
} else {
options[i].style.display = "none";
}
}
}
Not all browsers handle styling of form fields the same way: The HTML Select element.
First I refactored your example. It doesn't solve the problem.
document.forms.form01.filter.addEventListener('input', e => {
let form = e.target.form;
let filter = e.target.value.toUpperCase();
[...form.club_name.options].forEach(option => {
option.classList.add('hidden');
if (option.text.toUpperCase().startsWith(filter)) {
option.classList.remove('hidden');
}
});
});
option.hidden {
display: none;
}
<form name="form01">
<input type="text" name="filter" placeholder="Type to filter">
<select id="dropdown" name="club_name" class="form-select bg-custom" size="5" aria-label="Size 10 select example" style="background-color: #B9B4C7;">
<option class="list bg-custom" value="1">Abc</option>
<option class="list bg-custom" value="2">Abcde</option>
<option class="list bg-custom" value="3">Abcdefg</option>
</select>
</form>
And then an example that might help where all options are removed and added to the DOM. All options are stored in a array and the function refresh_options()
can be used for, first removing and then inserting options.
const options = [{text:'Abc',value:1},{text:'Abcde',value:2},{text:'Abcdefg',value:2}];
refresh_options(document.forms.form01.club_name, options);
document.forms.form01.filter.addEventListener('input', e => {
let form = e.target.form;
let text = e.target.value.toUpperCase();
let filteredoptions = options.filter(opt => opt.text.toUpperCase().startsWith(text));
refresh_options(form.club_name, filteredoptions);
});
function refresh_options(select, filteredoptions){
select.textContent = '';
filteredoptions.forEach(opt => {
let optelm = document.createElement("option");
optelm.value = opt.value;
optelm.text = opt.text;
select.add(optelm);
});
}
<form name="form01">
<input type="text" name="filter" placeholder="Type to filter">
<select id="dropdown" name="club_name" class="form-select bg-custom" size="5" aria-label="Size 10 select example" style="background-color: #B9B4C7;">
</select>
</form>