mirror of
https://github.com/wled/WLED.git
synced 2025-07-22 18:26:32 +00:00
Merge pull request #3540 from WoodyLetsCode/search
Improve search and filter functionality
This commit is contained in:
commit
8c69b85280
@ -469,6 +469,7 @@ button {
|
|||||||
height: 54px;
|
height: 54px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* New tooltip */
|
/* New tooltip */
|
||||||
@ -1240,6 +1241,7 @@ TD .checkmark, TD .radiomark {
|
|||||||
.filter .fchkl {
|
.filter .fchkl {
|
||||||
margin: 0 4px;
|
margin: 0 4px;
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lbl-l {
|
.lbl-l {
|
||||||
|
@ -197,33 +197,33 @@
|
|||||||
<div id="Effects" class="tabcontent">
|
<div id="Effects" class="tabcontent">
|
||||||
<div id="fx">
|
<div id="fx">
|
||||||
<p class="labels hd" id="modeLabel">Effect mode</p>
|
<p class="labels hd" id="modeLabel">Effect mode</p>
|
||||||
<div class="staytop fnd" id="fxFind">
|
<div class="staytop fnd" id="fxFind" onmousedown="preventBlur(event);">
|
||||||
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="filterFocus(event);search(this,'fxlist');" onblur="filterFocus(event);" />
|
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="filterFocus(event);search(this,'fxlist');" onblur="filterFocus(event);">
|
||||||
<i class="icons clear-icon" onclick="clean(this);"></i>
|
<i class="icons clear-icon" onclick="clean(this);"></i>
|
||||||
<i class="icons search-icon" style="cursor:pointer;"></i>
|
<i class="icons search-icon" style="cursor:pointer;"></i>
|
||||||
<div id="filters" class="filter fade">
|
<div id="filters" class="filter fade">
|
||||||
<label id="filterPal" tooltip="Uses palette" class="check fchkl">🎨
|
<label id="filterPal" tooltip="Uses palette" class="check fchkl">🎨
|
||||||
<input type="checkbox" data-flt="🎨" onchange="filterFx(this);">
|
<input type="checkbox" data-flt="🎨" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filter0D" tooltip="Single pixel" class="check fchkl">•
|
<label id="filter0D" tooltip="Single pixel" class="check fchkl">•
|
||||||
<input type="checkbox" data-flt="•" onchange="filterFx(this);">
|
<input type="checkbox" data-flt="•" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filter1D" tooltip="1D" class="check fchkl">⋮
|
<label id="filter1D" tooltip="1D" class="check fchkl">⋮
|
||||||
<input type="checkbox" data-flt="⋮" onchange="filterFx(this);">
|
<input type="checkbox" data-flt="⋮" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filter2D" tooltip="2D" class="check fchkl">▦
|
<label id="filter2D" tooltip="2D" class="check fchkl">▦
|
||||||
<input type="checkbox" data-flt="▦" onchange="filterFx(this);">
|
<input type="checkbox" data-flt="▦" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filterVol" tooltip="Volume" class="check fchkl">♪
|
<label id="filterVol" tooltip="Volume" class="check fchkl">♪
|
||||||
<input type="checkbox" data-flt="♪" onchange="filterFx(this);">
|
<input type="checkbox" data-flt="♪" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filterFreq" tooltip="Frequency" class="check fchkl">♫
|
<label id="filterFreq" tooltip="Frequency" class="check fchkl">♫
|
||||||
<input type="checkbox" data-flt="♫" onchange="filterFx(this);">
|
<input type="checkbox" data-flt="♫" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -232,6 +232,7 @@ function onLoad()
|
|||||||
|
|
||||||
tooltip();
|
tooltip();
|
||||||
resetPUtil();
|
resetPUtil();
|
||||||
|
initFilters();
|
||||||
|
|
||||||
if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true);
|
if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true);
|
||||||
applyCfg();
|
applyCfg();
|
||||||
@ -2716,58 +2717,94 @@ function hideModes(txt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
function search(f,l=null)
|
function search(field, listId = null) {
|
||||||
{
|
field.nextElementSibling.style.display = (field.value !== '') ? 'block' : 'none';
|
||||||
f.nextElementSibling.style.display=(f.value!=='')?'block':'none';
|
if (!listId) return;
|
||||||
if (!l) return;
|
|
||||||
var el = gId(l).querySelectorAll('.lstI');
|
// clear filter if searching in fxlist
|
||||||
|
if (listId === 'fxlist' && field.value !== '') {
|
||||||
|
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { e.checked = false; });
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not search if filter is active
|
||||||
|
if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return;
|
||||||
|
|
||||||
|
const listItems = gId(listId).querySelectorAll('.lstI');
|
||||||
// filter list items but leave (Default & Solid) always visible
|
// filter list items but leave (Default & Solid) always visible
|
||||||
for (i = (l==='pcont'?0:1); i < el.length; i++) {
|
for (i = (listId === 'pcont' ? 0 : 1); i < listItems.length; i++) {
|
||||||
var it = el[i];
|
const listItem = listItems[i];
|
||||||
var itT = it.querySelector('.lstIname').innerText.toUpperCase();
|
const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase();
|
||||||
it.style.display = (itT.indexOf(f.value.toUpperCase())<0) ? 'none' : '';
|
const searchIndex = listItemName.indexOf(field.value.toUpperCase());
|
||||||
|
listItem.style.display = (searchIndex < 0) ? 'none' : '';
|
||||||
|
listItem.dataset.searchIndex = searchIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort list items by search index and name
|
||||||
|
const sortedListItems = Array.from(listItems).sort((a, b) => {
|
||||||
|
const aSearchIndex = parseInt(a.dataset.searchIndex);
|
||||||
|
const bSearchIndex = parseInt(b.dataset.searchIndex);
|
||||||
|
|
||||||
|
if (aSearchIndex !== bSearchIndex) {
|
||||||
|
return aSearchIndex - bSearchIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
const aName = a.querySelector('.lstIname').innerText.toUpperCase();
|
||||||
|
const bName = b.querySelector('.lstIname').innerText.toUpperCase();
|
||||||
|
|
||||||
|
return aName.localeCompare(bName);
|
||||||
|
});
|
||||||
|
sortedListItems.forEach(item => {
|
||||||
|
gId(listId).append(item);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function clean(c)
|
function clean(clearButton) {
|
||||||
{
|
clearButton.style.display = 'none';
|
||||||
c.style.display='none';
|
const inputField = clearButton.previousElementSibling;
|
||||||
var i=c.previousElementSibling;
|
inputField.value = '';
|
||||||
i.value='';
|
search(inputField, clearButton.parentElement.nextElementSibling.id);
|
||||||
i.focus();
|
|
||||||
i.dispatchEvent(new Event('input'));
|
|
||||||
if (i.parentElement.id=='fxFind') {
|
|
||||||
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e)=>{e.checked=false;});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterFocus(e)
|
function initFilters() {
|
||||||
{
|
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { e.checked = false; });
|
||||||
let f = gId("filters");
|
}
|
||||||
|
|
||||||
|
function filterFocus(e) {
|
||||||
|
const f = gId("filters");
|
||||||
if (e.type === "focus") f.classList.remove('fade'); // immediately show (still has transition)
|
if (e.type === "focus") f.classList.remove('fade'); // immediately show (still has transition)
|
||||||
// compute sticky top (with delay for transition)
|
// compute sticky top (with delay for transition)
|
||||||
setTimeout(()=>{
|
setTimeout(() => {
|
||||||
let sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')) + (e.type === "focus" ? 1 : -1) * f.offsetHeight;
|
const sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')) + (e.type === "focus" ? 1 : -1) * f.offsetHeight;
|
||||||
sCol('--sti', sti+"px");
|
sCol('--sti', sti + "px");
|
||||||
}, 252);
|
}, 252);
|
||||||
if (e.type === "blur") {
|
if (e.type === "blur") {
|
||||||
let t = e.relatedTarget ? e.relatedTarget : e.explicitOriginalTarget;
|
setTimeout(() => {
|
||||||
do {
|
if (e.target === document.activeElement && document.hasFocus()) return;
|
||||||
if (t.id && (t.id === "fxFind")) { setTimeout(()=>{t.firstElementChild.focus();},150); return; }
|
// do not hide if filter is active
|
||||||
t = t.parentElement;
|
if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return;
|
||||||
} while (t.tagName !== "BODY");
|
f.classList.add('fade');
|
||||||
setTimeout(()=>{f.classList.add('fade');},255); // wait with hiding
|
}, 255); // wait with hiding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterFx(o)
|
function filterFx() {
|
||||||
{
|
const inputField = gId('fxFind').children[0];
|
||||||
if (!o) return;
|
inputField.value = '';
|
||||||
let i = gId('fxFind').children[0];
|
inputField.focus();
|
||||||
i.value=!o.checked?'':o.dataset.flt;
|
clean(inputField.nextElementSibling);
|
||||||
i.focus();
|
const listItems = gId("fxlist").querySelectorAll('.lstI');
|
||||||
i.dispatchEvent(new Event('input'));
|
for (let i = 1; i < listItems.length; i++) {
|
||||||
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e)=>{if(e!==o)e.checked=false;});
|
const listItem = listItems[i];
|
||||||
|
const listItemName = listItem.querySelector('.lstIname').innerText;
|
||||||
|
let hide = false;
|
||||||
|
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = true; });
|
||||||
|
listItem.style.display = hide ? 'none' : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function preventBlur(e) {
|
||||||
|
if (e.target === gId("fxFind").children[0] || e.target === gId("filters")) return;
|
||||||
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure "dur" and "transition" are arrays with at least the length of "ps"
|
// make sure "dur" and "transition" are arrays with at least the length of "ps"
|
||||||
|
4086
wled00/html_ui.h
4086
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user