Feat : use text input for filtering of exclude_list & include_list (#69)
* Change input box logic from selection to filtering * Change user input logic from going to filtering * Update scripts/include_list.php Co-authored-by: Nachtzuster <Nachtzuster@users.noreply.github.com> * Multiple size reverted to 25 ; typo "ol" removed https://github.com/Nachtzuster/BirdNET-Pi/pull/69 * Re-add dummy "Please select"option * Update include_list.php * Align with "option disabled" * Update scripts/exclude_list.php thanks Co-authored-by: Nachtzuster <Nachtzuster@users.noreply.github.com> --------- Co-authored-by: Nachtzuster <Nachtzuster@users.noreply.github.com>
This commit is contained in:
+29
-64
@@ -9,7 +9,6 @@
|
|||||||
<br>
|
<br>
|
||||||
<span>Once the desired species has been highlighted, click it and then click ADD to have it excluded.</span>
|
<span>Once the desired species has been highlighted, click it and then click ADD to have it excluded.</span>
|
||||||
<select name="species[]" id="species" multiple size="25">
|
<select name="species[]" id="species" multiple size="25">
|
||||||
<option selected value="base">Please Select</option>
|
|
||||||
<?php
|
<?php
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
ini_set('display_errors',1);
|
ini_set('display_errors',1);
|
||||||
@@ -41,7 +40,7 @@
|
|||||||
<h3>Excluded Species List</h3>
|
<h3>Excluded Species List</h3>
|
||||||
<br><br><br>
|
<br><br><br>
|
||||||
<select name="species[]" id="value2" multiple size="25">
|
<select name="species[]" id="value2" multiple size="25">
|
||||||
<option selected value="base">Please Select</option>
|
<option disabled value="base">Please Select</option>
|
||||||
<?php
|
<?php
|
||||||
$filename = './scripts/exclude_species_list.txt';
|
$filename = './scripts/exclude_species_list.txt';
|
||||||
$eachline = file($filename, FILE_IGNORE_NEW_LINES);
|
$eachline = file($filename, FILE_IGNORE_NEW_LINES);
|
||||||
@@ -58,9 +57,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// Store the original list of options in a variable
|
||||||
|
var originalOptions = {};
|
||||||
|
|
||||||
document.getElementById("add").addEventListener("submit", function(event) {
|
document.getElementById("add").addEventListener("submit", function(event) {
|
||||||
var speciesSelect = document.getElementById("species");
|
var speciesSelect = document.getElementById("species");
|
||||||
if (speciesSelect.selectedIndex < 1) {
|
if (speciesSelect.selectedIndex < 0) {
|
||||||
alert("Please click the species you want to add.");
|
alert("Please click the species you want to add.");
|
||||||
document.querySelector('.views').style.opacity = 1;
|
document.querySelector('.views').style.opacity = 1;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -68,72 +70,35 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
var search_term = document.querySelector("input#exclude_species_searchterm");
|
var search_term = document.querySelector("input#exclude_species_searchterm");
|
||||||
search_term.addEventListener("keydown", doSearch);
|
search_term.addEventListener("keyup", function() {
|
||||||
//Index where we found a match
|
filterOptions("species");
|
||||||
var search_match_idx = 1;
|
});
|
||||||
var last_search_term = "";
|
|
||||||
|
|
||||||
function doSearch(eventObj) {
|
// Function to filter options in a select element
|
||||||
//Don't do anything if the user is till composing
|
function filterOptions(id) {
|
||||||
if (eventObj.isComposing || eventObj.keyCode === 229) {
|
var input = document.getElementById("exclude_species_searchterm");
|
||||||
return;
|
var filter = input.value.toUpperCase();
|
||||||
|
var select = document.getElementById(id);
|
||||||
|
var options = select.getElementsByTagName("option");
|
||||||
|
|
||||||
|
// If the original list of options for this select element hasn't been stored yet, store it
|
||||||
|
if (!originalOptions[id]) {
|
||||||
|
originalOptions[id] = Array.from(options).map(option => option.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
//If the key pressed is the enter key capture it, stop the form submitting and do the search
|
// Clear the select element
|
||||||
if (eventObj.key === 'Enter' || eventObj.keyCode === 13) {
|
while (select.firstChild) {
|
||||||
eventObj.preventDefault();
|
select.removeChild(select.firstChild);
|
||||||
|
|
||||||
//User wants to submit the text as a search
|
|
||||||
var search_text = search_term.value.toLowerCase();
|
|
||||||
|
|
||||||
//Now look at the select list, loop over the options and try find part of the text in the option's name/text
|
|
||||||
var species_select_list = document.querySelector('select#species');
|
|
||||||
|
|
||||||
//if the search text differs from last time start the search from the beginning of te list
|
|
||||||
if (search_text !== last_search_term) {
|
|
||||||
//Also unselect the last match
|
|
||||||
species_select_list[search_match_idx].removeAttribute('class');
|
|
||||||
search_match_idx = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Start the loop at 1 so we skip the very initial value asking the user to select a option
|
// Populate the select element with the filtered labels
|
||||||
for (let i = search_match_idx; i < species_select_list.length; i++) {
|
originalOptions[id].forEach(label => {
|
||||||
// if (species_select_list[i] !== 'undefined') {
|
if (label.toUpperCase().indexOf(filter) > -1) {
|
||||||
option_text = species_select_list[i].value;
|
let option = document.createElement('option');
|
||||||
search_match_text = option_text.toLowerCase().includes(search_text)
|
option.value = label;
|
||||||
|
option.text = label;
|
||||||
//Check if the item is already selected, that could mean that user may be searching the same phrase
|
select.appendChild(option);
|
||||||
if (species_select_list[search_match_idx].getAttribute('class') === "exclude_species_list_option_highlight") {
|
|
||||||
species_select_list[search_match_idx].removeAttribute('class');
|
|
||||||
// species_select_list[search_match_idx].removeAttribute('style');
|
|
||||||
//Go to the next item
|
|
||||||
i++
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//There was a match,
|
|
||||||
if (search_match_text === true) {
|
|
||||||
//already on this item so skip it and continue with list
|
|
||||||
if (search_match_idx === i) {
|
|
||||||
i++
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//Finally we havent found this item before
|
|
||||||
search_match_idx = i;
|
|
||||||
|
|
||||||
//Scroll into view and select it
|
|
||||||
species_select_list[search_match_idx].scrollIntoView({behavior: 'smooth', block: 'start'});
|
|
||||||
//Apply a style to the option since setting the selected value to true breaks scrolling on chrome :(
|
|
||||||
//the style is nicer anyway :)
|
|
||||||
species_select_list[search_match_idx].setAttribute('class', "exclude_species_list_option_highlight");
|
|
||||||
// species_select_list[search_match_idx].setAttribute('selected', 'true');
|
|
||||||
|
|
||||||
//break the loop
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Track what search term was used so we know when to start over
|
|
||||||
last_search_term = search_text
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ $eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
|||||||
<div class="customlabels2 column1">
|
<div class="customlabels2 column1">
|
||||||
<form action="" method="GET" id="add">
|
<form action="" method="GET" id="add">
|
||||||
<h2>All Species Labels</h2>
|
<h2>All Species Labels</h2>
|
||||||
<select name="species[]" id="species" multiple size="30">
|
<input autocomplete="off" size="18" type="text" placeholder="Search Species..." id="species_searchterm" name="species_searchterm">
|
||||||
<option selected value="base">Please Select</option>
|
<select name="species[]" id="species" multiple size="25">
|
||||||
<?php
|
<?php
|
||||||
foreach($eachlines as $lines){echo
|
foreach($eachlines as $lines){echo
|
||||||
"<option value=\"".$lines."\">$lines</option>";}
|
"<option value=\"".$lines."\">$lines</option>";}
|
||||||
@@ -44,8 +44,8 @@ $eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
|||||||
<div class="customlabels2 column3">
|
<div class="customlabels2 column3">
|
||||||
<form action="" method="GET" id="del">
|
<form action="" method="GET" id="del">
|
||||||
<h2>Custom Species List</h2>
|
<h2>Custom Species List</h2>
|
||||||
<select name="species[]" id="value2" multiple size="30">
|
<select name="species[]" id="value2" multiple size="25">
|
||||||
<option selected value="base">Please Select</option>
|
<option disabled value="base">Please Select</option>
|
||||||
<?php
|
<?php
|
||||||
$filename = './scripts/include_species_list.txt';
|
$filename = './scripts/include_species_list.txt';
|
||||||
$eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
$eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
||||||
@@ -59,4 +59,50 @@ $eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
|||||||
<button type="submit" name="view" value="Included" form="del">REMOVE</button>
|
<button type="submit" name="view" value="Included" form="del">REMOVE</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
|
||||||
|
<script>
|
||||||
|
// Store the original list of options in a variable
|
||||||
|
var originalOptions = {};
|
||||||
|
|
||||||
|
document.getElementById("add").addEventListener("submit", function(event) {
|
||||||
|
var speciesSelect = document.getElementById("species");
|
||||||
|
if (speciesSelect.selectedIndex < 0) {
|
||||||
|
alert("Please click the species you want to add.");
|
||||||
|
document.querySelector('.views').style.opacity = 1;
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var search_term = document.querySelector("input#species_searchterm");
|
||||||
|
search_term.addEventListener("keyup", function() {
|
||||||
|
filterOptions("species");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function to filter options in a select element
|
||||||
|
function filterOptions(id) {
|
||||||
|
var input = document.getElementById(id + "_searchterm");
|
||||||
|
var filter = input.value.toUpperCase();
|
||||||
|
var select = document.getElementById(id);
|
||||||
|
var options = select.getElementsByTagName("option");
|
||||||
|
|
||||||
|
// If the original list of options for this select element hasn't been stored yet, store it
|
||||||
|
if (!originalOptions[id]) {
|
||||||
|
originalOptions[id] = Array.from(options).map(option => option.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the select element
|
||||||
|
while (select.firstChild) {
|
||||||
|
select.removeChild(select.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the select element with the filtered labels
|
||||||
|
originalOptions[id].forEach(label => {
|
||||||
|
if (label.toUpperCase().indexOf(filter) > -1) {
|
||||||
|
let option = document.createElement('option');
|
||||||
|
option.value = label;
|
||||||
|
option.text = label;
|
||||||
|
select.appendChild(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user