Filtering now works

This commit is contained in:
Simon Martens
2025-03-01 01:23:56 +01:00
parent ca33ec7be3
commit 3968f6b1b4
10 changed files with 408 additions and 127 deletions

View File

@@ -94,6 +94,7 @@ var CONTENTS_FTS5_FIELDS = []string{
ENTRIES_TABLE,
AGENTS_TABLE,
MUSENALMID_FIELD,
MUSENALM_INHALTE_TYPE_FIELD,
ANNOTATION_FIELD,
COMMENT_FIELD,
}
@@ -375,6 +376,11 @@ func FTS5ValuesContent(content *Content, entry *Entry, agents []*Agent) []string
entrystring += "; [o.J.]"
}
typestring := ""
for _, typ := range content.MusenalmType() {
typestring += typ + " "
}
return []string{
content.PreferredTitle(),
content.VariantTitle(),
@@ -392,6 +398,7 @@ func FTS5ValuesContent(content *Content, entry *Entry, agents []*Agent) []string
entrystring,
agentstring,
strconv.Itoa(content.MusenalmID()),
typestring,
datatypes.DeleteTags(content.Annotation()),
datatypes.DeleteTags(content.Comment()),
}

View File

@@ -15,6 +15,13 @@ func Sort_Series_Title(series []*Series) {
})
}
func Sort_Agents_Name(agents []*Agent) {
collator := collate.New(language.German)
slices.SortFunc(agents, func(i, j *Agent) int {
return collator.CompareString(i.Name(), j.Name())
})
}
func Sort_Entries_Title_Year(entries []*Entry) {
collator := collate.New(language.German)
slices.SortFunc(entries, func(i, j *Entry) int {

View File

@@ -76,12 +76,13 @@ func (p *SuchePage) SimpleSearchReihenRequest(app core.App, engine *templating.E
func (p *SuchePage) SearchBeitraegeRequest(app core.App, engine *templating.Engine, e *core.RequestEvent, params SearchParameters) error {
data := make(map[string]interface{})
result, err := NewSearchBeitraege(app, params)
filterparams := NewBeitraegeFilterParameters(e)
result, err := NewSearchBeitraege(app, params, filterparams)
if err != nil {
return engine.Response404(e, err, nil)
}
data["filters"] = filterparams
data["parameters"] = params
data["result"] = result
return engine.Response200(e, p.Template+params.Collection+"/", data, p.Layout)

View File

@@ -2,6 +2,9 @@ package pages
import (
"database/sql"
"maps"
"slices"
"sort"
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
"github.com/Theodor-Springmann-Stiftung/musenalm/helpers/datatypes"
@@ -10,8 +13,60 @@ import (
const (
DEFAULT_PAGESIZE = 80
FILTER_PARAM_BEIAEGE_AGENT = "agentfilter"
FILTER_PARAM_BEIAEGE_TYPE = "typefilter"
FILTER_PARAM_BEIAEGE_ONLYSCANS = "onlyscans"
FILTER_PARAM_BEIAEGE_YEAR = "yearfilter"
)
type BeitraegeFilterParameters struct {
Agent string
Type string
Year string
OnlyScans bool
}
func NewBeitraegeFilterParameters(ev *core.RequestEvent) BeitraegeFilterParameters {
agent := ev.Request.URL.Query().Get(FILTER_PARAM_BEIAEGE_AGENT)
typ := ev.Request.URL.Query().Get(FILTER_PARAM_BEIAEGE_TYPE)
year := ev.Request.URL.Query().Get(FILTER_PARAM_BEIAEGE_YEAR)
onlyscans := ev.Request.URL.Query().Get(FILTER_PARAM_BEIAEGE_ONLYSCANS) == "on"
return BeitraegeFilterParameters{
Agent: agent,
Type: typ,
Year: year,
OnlyScans: onlyscans,
}
}
func (p *BeitraegeFilterParameters) FieldSetBeitraege() []dbmodels.FTS5QueryRequest {
ret := []dbmodels.FTS5QueryRequest{}
if p.Agent != "" {
q := "\"" + p.Agent + "\""
que := dbmodels.NormalizeQuery(q)
req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE}, que)
ret = append(ret, req...)
}
if p.Type != "" {
q := "\"" + p.Type + "\""
que := dbmodels.NormalizeQuery(q)
req := dbmodels.IntoQueryRequests([]string{dbmodels.MUSENALM_INHALTE_TYPE_FIELD}, que)
ret = append(ret, req...)
}
if p.Year != "" {
q := "\"" + p.Year + "\""
que := dbmodels.NormalizeQuery(q)
req := dbmodels.IntoQueryRequests([]string{dbmodels.ENTRIES_TABLE}, que)
ret = append(ret, req...)
}
return ret
}
type SearchResultBeitraege struct {
Queries []dbmodels.FTS5QueryRequest
@@ -23,6 +78,10 @@ type SearchResultBeitraege struct {
ContentsAgents map[string][]*dbmodels.RContentsAgents // <- Key: Content ID
Pages []int
AgentsList []*dbmodels.Agent
TypesList []string
YearList []int
}
func EmptyResultBeitraege() *SearchResultBeitraege {
@@ -35,9 +94,11 @@ func EmptyResultBeitraege() *SearchResultBeitraege {
}
}
func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBeitraege, error) {
func NewSearchBeitraege(app core.App, params SearchParameters, filters BeitraegeFilterParameters) (*SearchResultBeitraege, error) {
contents := []*dbmodels.Content{}
queries := params.FieldSetBeitraege()
fqueries := filters.FieldSetBeitraege()
queries = append(queries, fqueries...)
if params.AlmString != "" {
e, err := dbmodels.Contents_MusenalmID(app, params.AlmString)
@@ -70,14 +131,33 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei
return nil, err
}
if filters.OnlyScans {
scans := []*dbmodels.Content{}
for _, c := range cs {
if len(c.Scans()) > 0 {
scans = append(scans, c)
}
}
cs = scans
}
contents = append(contents, cs...)
}
resultids := []any{}
resultentryids := []string{}
uniqueresultentryids := map[string]bool{}
types := make(map[string]bool)
for _, content := range contents {
resultids = append(resultids, content.Id)
resultentryids = append(resultentryids, content.Entry())
uniqueresultentryids[content.Entry()] = true
for _, typ := range content.MusenalmType() {
types[typ] = true
}
}
resultentryids := []any{}
for entryid, _ := range uniqueresultentryids {
resultentryids = append(resultentryids, entryid)
}
entries, err := dbmodels.Entries_IDs(app, datatypes.ToAny(resultentryids))
@@ -96,9 +176,14 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei
return nil, err
}
aids := []any{}
uniqueaids := map[string]bool{}
for _, a := range arels {
aids = append(aids, a.Agent())
uniqueaids[a.Agent()] = true
}
aids := []any{}
for aid, _ := range uniqueaids {
aids = append(aids, aid)
}
agents, err := dbmodels.Agents_IDs(app, aids)
@@ -111,6 +196,10 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei
contentsmap[c.Entry()] = append(contentsmap[c.Entry()], c)
}
for _, c := range contentsmap {
dbmodels.Sort_Contents_Numbering(c)
}
contentsagents := make(map[string][]*dbmodels.RContentsAgents)
for _, a := range arels {
contentsagents[a.Content()] = append(contentsagents[a.Content()], a)
@@ -122,8 +211,10 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei
}
entriesmap := make(map[string]*dbmodels.Entry)
years := make(map[int]bool)
for _, e := range entries {
entriesmap[e.Id] = e
years[e.Year()] = true
}
hits := []string{}
@@ -142,6 +233,14 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei
hits = hits[pages[params.Page-1]:pages[params.Page]]
}
tL := slices.Collect(maps.Keys(types))
sort.Strings(tL)
yL := slices.Collect(maps.Keys(years))
sort.Ints(yL)
dbmodels.Sort_Agents_Name(agents)
return &SearchResultBeitraege{
Queries: queries,
Hits: hits,
@@ -150,6 +249,9 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei
Contents: contentsmap,
ContentsAgents: contentsagents,
Pages: pages,
AgentsList: agents,
TypesList: tL,
YearList: yL,
}, nil
}

View File

@@ -22,6 +22,7 @@ const (
BAENDE_PARAM_REFS = "references"
BEITRAEGE_PARAM_ENTRY = "entry"
BEITRAEGE_PARAM_INCIPT = "incipit"
BEITRAEGE_PARAM_TYPE = "type"
)
type SearchParameters struct {
@@ -48,6 +49,7 @@ type SearchParameters struct {
YearString string
EntryString string
IncipitString string
TypeString string
Page int
}
@@ -61,7 +63,9 @@ func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters,
annotations := e.Request.URL.Query().Get(SEARCH_PARAM_ANNOTATIONS) == "on"
annotationsstring := e.Request.URL.Query().Get(SEARCH_PARAM_ANNOTATIONS + "string")
year := e.Request.URL.Query().Get(SEARCH_PARAM_YEAR) == "on"
yearstring := e.Request.URL.Query().Get(SEARCH_PARAM_YEAR + "string")
typestring := e.Request.URL.Query().Get(BEITRAEGE_PARAM_TYPE)
series := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES) == "on"
seriesstring := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES + "string")
@@ -125,6 +129,7 @@ func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters,
YearString: yearstring,
EntryString: entrystring,
IncipitString: incipitstring,
TypeString: typestring,
}, nil
}
@@ -151,6 +156,7 @@ func (p SearchParameters) AllSearchTermsBeitraege() string {
res = append(res, p.includedParams(p.YearString)...)
res = append(res, p.includedParams(p.EntryString)...)
res = append(res, p.includedParams(p.IncipitString)...)
res = append(res, p.includedParams(p.TypeString)...)
return strings.Join(res, " ")
}
@@ -199,6 +205,7 @@ func (p SearchParameters) ToQueryParamsBeitraege() string {
if p.Incipit {
q += "&incipit=on"
}
}
if p.YearString != "" {
@@ -225,6 +232,10 @@ func (p SearchParameters) ToQueryParamsBeitraege() string {
q += fmt.Sprintf("&incipitstring=%s", p.IncipitString)
}
if p.TypeString != "" {
q += fmt.Sprintf("&typestring=%s", p.TypeString)
}
return q
}
@@ -359,6 +370,12 @@ func (p SearchParameters) FieldSetBeitraege() []dbmodels.FTS5QueryRequest {
ret = append(ret, req...)
}
if p.TypeString != "" {
que := dbmodels.NormalizeQuery(p.TypeString)
req := dbmodels.IntoQueryRequests([]string{dbmodels.MUSENALM_INHALTE_TYPE_FIELD}, que)
ret = append(ret, req...)
}
return ret
}

View File

@@ -61,11 +61,8 @@ TODO danach:
- Cache?
- HTMX + Smooth scroll
- Personen: related
- Inhaltsliste: Personen sehen komisch aus
- V\Boosted links gen by webcomponents
- Sammlungen u. Querverweise müssen die URL als Parameter bekommen
- Sammlungen neuer versuch
- Inhaltsliste Personen
- Sortierung nach Band A-Z?

View File

@@ -37,6 +37,14 @@
EntryString string
IncipitString string
}
.filters
type BeitraegeFilterParameters struct {
Agent string
Type string
Year string
OnlyScans bool
}
*/}}
{{ $isAlm := false }}
@@ -76,33 +84,51 @@
{{ template "_searchboxsimple" Arr $model.parameters true $q }}
<fieldset class="selectgroup">
<div class="selectgroup-option">
<input type="checkbox" name="title" id="title"
{{ if or $isBase $isTitle -}}checked{{- end -}} />
<input
type="checkbox"
name="title"
id="title"
{{ if or $isBase $isTitle -}}checked{{- end -}} />
<label for="title">Titel</label>
</div>
<div class="selectgroup-option">
<input type="checkbox" name="incipit" id="incipit"
{{ if or $isBase $isIncipit -}}checked{{- end -}} />
<input
type="checkbox"
name="incipit"
id="incipit"
{{ if or $isBase $isIncipit -}}checked{{- end -}} />
<label for="incipit">Incipit</label>
</div>
<div class="selectgroup-option">
<input type="checkbox" name="persons" id="persons"
{{ if or $isBase $isPerson -}}checked{{- end -}} />
<input
type="checkbox"
name="persons"
id="persons"
{{ if or $isBase $isPerson -}}checked{{- end -}} />
<label for="person">Personen &amp; Pseudonyme</label>
</div>
<div class="selectgroup-option">
<input type="checkbox" name="entry" id="entry"
{{ if or $isBase $isEntry -}}checked{{- end -}} />
<input
type="checkbox"
name="entry"
id="entry"
{{ if or $isBase $isEntry -}}checked{{- end -}} />
<label for="entry">Bandtitel</label>
</div>
<div class="selectgroup-option">
<input type="checkbox" name="year" id="year"
{{ if or $isBase $isYear -}}checked{{- end -}} />
<input
type="checkbox"
name="year"
id="year"
{{ if or $isBase $isYear -}}checked{{- end -}} />
<label for="year">Jahr</label>
</div>
<div class="selectgroup-option">
<input type="checkbox" name="annotations" id="annotations"
{{ if or $isBase $isAnnotation -}}checked{{- end -}} />
<input
type="checkbox"
name="annotations"
id="annotations"
{{ if or $isBase $isAnnotation -}}checked{{- end -}} />
<label for="annotations">Anmerkungen</label>
</div>
</fieldset>
@@ -116,114 +142,37 @@
{{- if $model.parameters.IsBeitraegeSearch -}}
<div class="container-normal" id="searchresults">
<div class="border-b border-zinc-300 flex flex-row justify-between">
<div>
{{ if $model.parameters.Query -}}
Suche nach <b>»{{ $model.parameters.Query }}«</b> &middot;
{{- end -}}
{{- if $isAlm -}}
Inhaltsnummer <b>»{{ $model.parameters.AlmString }}«</b> &middot;
{{- end -}}
<i class="ri-book-line"></i>
{{ if eq $model.result.Count 1 -}}
Ein Beitrag
{{ else -}}
{{ $model.result.Count }} Beiträge
{{- end }}
in
{{ if eq ($model.result.Entries | len) 1 -}}
einem Band
{{ else -}}
{{ $model.result.Entries | len }} Bänden
{{- end -}}
</div>
{{- if gt (len $model.result.Pages) 1 }}
<div>
{{ if gt $model.parameters.Page 1 -}}
<a
href="{{- $model.parameters.ToQueryParamsBeitraege -}}&page={{ $model.parameters.Prev
}}" class="mr-1.5">
<i class="ri-arrow-left-long-line"></i>
</a>
{{ template "_filterlist" $model }}
{{ template "tablehead" $model }}
{{- if $model.result.Hits -}}
<div class="mt-8" id="almanachcontents">
{{- range $_, $hit := $model.result.Hits -}}
{{- $e := index $model.result.Entries $hit -}}
{{- $contents := index $model.result.Contents $e.Id -}}
<div
class="font-serif flex flex-row justify-between text-stone-800
font-bold border-b pb-0.5 mb-2 tab-list-head items-end">
<div>
{{ $e.PreferredTitle }}
</div>
<div
class="inline-block font-sans bg-slate-800 text-white h-max text-sm px-1.5 rounded">
{{- len $contents -}}
</div>
</div>
<div class="mb-7 tab-list-panel">
{{- range $i, $c := $contents -}}
{{- $rels := index $model.result.ContentsAgents $c.Id -}}
{{- template "_content" Arr $c $e $rels $model.result.Agents false true
$model.parameters
-}}
{{- end -}}
</div>
{{- end -}}
S. {{ $model.parameters.Page }} /
{{ $model.result.PagesCount }}
{{ if lt $model.parameters.Page ($model.result.PagesCount) -}}
<a
href="{{- $model.parameters.ToQueryParamsBeitraege -}}&page={{ $model.parameters.Next
}}" class="ml-1.5">
<i class="ri-arrow-right-long-line"></i>
</a>
{{- end -}}
</div>
{{- end -}}
{{- if not $isAlm -}}
<div>
<label
for="sort"
class="align-baseline h-min self-end pb-1 mr-2 text-sm font-sans
text-stone-700"
>Sortierung</label
>
{{/* INFO: We always redrect to letter = A bc some letters dont exist for other professions */}}
<select
class="h-min pb-1 border-b-4 border-zinc-300 px-1.5"
name="sort"
id="sort"
autocomplete="off"
hx-get="{{- $model.parameters.ToQueryParamsBeitraege -}}"
trigger="change"
hx-push-url="true"
hx-select="main"
hx-target="main">
<option
value="year"
{{ if eq $model.parameters.Sort "year" -}}
selected
{{- end -}}>
Jahr
</option>
<option value="entry" {{ if eq $model.parameters.Sort "entry" -}}selected{{- end -}}>
Bände A-Z
</option>
</select>
</div>
{{- end -}}
</div>
{{- if $model.result.Hits -}}
<div class="mt-8" id="almanachcontents">
{{- range $_, $hit := $model.result.Hits -}}
{{- $e := index $model.result.Entries $hit -}}
{{- $contents := index $model.result.Contents $e.Id -}}
<div
class="font-serif flex flex-row justify-between text-stone-800
font-bold border-b pb-0.5 mb-2 tab-list-head items-end">
<div>
{{ $e.PreferredTitle }}
</div>
<div
class="inline-block font-sans bg-slate-800 text-white h-max text-sm px-1.5 rounded">
{{- len $contents -}}
</div>
</div>
<div class="mb-7 tab-list-panel">
{{- range $i, $c := $contents -}}
{{- $rels := index $model.result.ContentsAgents $c.Id -}}
{{- template "_content" Arr $c $e $rels $model.result.Agents false true
$model.parameters
-}}
{{- end -}}
</div>
{{- end -}}
</div>
{{- end -}}
</div>
<script type="module">
let elements = document.querySelectorAll('.search-text');
let mark_instance = new Mark(elements);
@@ -235,5 +184,4 @@
}, 200);
</script>
</div>
{{- end -}}

View File

@@ -0,0 +1,119 @@
{{ $model := . }}
{{ $isAlm := false }}
{{ $isTitle := false }}
{{ $isYear := false }}
{{ $isPerson := false }}
{{ $isAnnotation := false }}
{{ $isIncipit := false }}
{{ $isEntry := false }}
{{- $isAlm = $model.parameters.AlmString -}}
{{- $isTitle = or $model.parameters.Title $model.parameters.TitleString -}}
{{- $isYear = or $model.parameters.Year $model.parameters.YearString -}}
{{- $isPerson = or $model.parameters.Persons $model.parameters.PersonsString -}}
{{- $isAnnotation = or $model.parameters.Annotations $model.parameters.AnnotationsString -}}
{{- $isIncipit = or $model.parameters.Incipit $model.parameters.IncipitString -}}
{{- $isEntry = or $model.parameters.Entry $model.parameters.EntryString -}}
{{- $isBase := not (or $isTitle $isYear $isPerson $isAnnotation $isIncipit $isEntry) -}}
<div class="border-b border-zinc-300 flex flex-row justify-between">
<div class="flex flex-row gap-x-2">
{{ if $model.parameters.Query -}}
<div>Suche nach <b>»{{ $model.parameters.Query }}«</b></div>
<div>&middot;</div>
{{- end -}}
{{- if $isAlm -}}
<div>Inhaltsnummer <b>»{{ $model.parameters.AlmString }}«</b></div>
<div>&middot;</div>
{{- end -}}
<div>
<i class="ri-book-line"></i>
{{ if eq $model.result.Count 1 -}}
Ein Beitrag
{{ else -}}
{{ $model.result.Count }} Beiträge
{{- end }}
in
{{ if eq ($model.result.Entries | len) 1 -}}
einem Band
{{ else -}}
{{ $model.result.Entries | len }} Bänden
{{- end -}}
</div>
{{- if gt (len $model.result.Pages) 1 }}
<div>&middot;</div>
<div class="[&>_a]:no-underline">
{{ if gt $model.parameters.Page 1 -}}
<a
href="{{- $model.parameters.ToQueryParamsBeitraege -}}&page={{ $model.parameters.Prev }}"
class="mr-1.5">
<i class="ri-arrow-left-long-line"></i>
</a>
{{- end -}}
Seite {{ $model.parameters.Page }} /
{{ $model.result.PagesCount }}
{{ if lt $model.parameters.Page ($model.result.PagesCount) -}}
<a
href="{{- $model.parameters.ToQueryParamsBeitraege -}}&page={{ $model.parameters.Next }}"
class="ml-1.5">
<i class="ri-arrow-right-long-line"></i>
</a>
{{- end -}}
</div>
{{- end -}}
</div>
{{- if not $isAlm -}}
<div>
<label
for="onlyscans"
class="align-baseline h-min self-end pb-1 mr-1 text-sm font-sans text-stone-700">
Nur Digitalisate
</label>
<input
class="mr-4"
type="checkbox"
id="onlyscans"
name="onlyscans"
autocomplete="off"
hx-get="{{- $model.parameters.ToQueryParamsBeitraege -}}"
trigger="change"
hx-push-url="true"
hx-select="main"
hx-target="main"
{{ if $model.filters.OnlyScans -}}checked{{- end -}} />
<label
for="sort"
class="align-baseline h-min self-end pb-1 mr-2 text-sm font-sans
text-stone-700"
>Sortierung</label
>
<select
class="h-min pb-1 border-b-4 border-zinc-300 px-1.5"
name="sort"
id="sort"
autocomplete="off"
hx-get="{{- $model.parameters.ToQueryParamsBeitraege -}}"
trigger="change"
hx-push-url="true"
hx-select="main"
hx-target="main">
<option
value="year"
{{ if eq $model.parameters.Sort "year" -}}
selected
{{- end -}}>
Jahr
</option>
<option value="entry" {{ if eq $model.parameters.Sort "entry" -}}selected{{- end -}}>
Bände A-Z
</option>
</select>
</div>
{{- end -}}
</div>

View File

@@ -0,0 +1,75 @@
{{ $model := . }}
<div class="flex flex-row gap-x-6 mb-4">
<filter-list
id="agent-list"
data-queryparam="personsstring"
data-url="{{ $model.parameters.ToQueryParamsBeitraege }}&agentfilter="
data-placeholder="Personen und Körperschaften filtern..."></filter-list>
<filter-list
id="year-list"
data-queryparam="yearstring"
data-url="{{ $model.parameters.ToQueryParamsBeitraege }}&yearfilter="
data-placeholder="Jahre filtern..."></filter-list>
<filter-list
id="types-list"
data-queryparam="type"
data-url="{{ $model.parameters.ToQueryParamsBeitraege }}&typefilter="
data-placeholder="Betragskategorien filtern..."></filter-list>
</div>
<script type="module">
let agentList = document.getElementById("agent-list");
if (agentList) {
agentList.items = {{ $model.result.AgentsList }};
agentList.setSearchTextFunc((item) => {
return item.name;
});
agentList.setHREFFunc((item) => {
return item.name;
});
agentList.setLinkTextFunc((item) => {
return `
<span class="filter-list-searchable">${item.name}</span>
<span class="text-xs text-stone-500 whitespace-nowrap font-sans">
${item.corporate_body ? "Verlag/Druck/Vertrieb" : item.biographical_data}
</span>
`;
});
}
let yearList = document.getElementById("year-list");
if (yearList) {
yearList.items = {{ $model.result.YearList }};
yearList.setHREFFunc((item) => {
return String(item);
});
yearList.setLinkTextFunc((item) => {
if (item === 0) return "ohne Jahr";
return String(item);
});
}
let typesList = document.getElementById("types-list");
if (typesList) {
typesList.items = {{ $model.result.TypesList }};
typesList.setHREFFunc((item) => {
return String(item);
});
typesList.setLinkTextFunc((item) => {
return item;
});
}
</script>

View File

@@ -146,6 +146,10 @@ class FilterList extends HTMLElement {
this.addEventListener("keydown", this.onEnter.bind(this));
this.addEventListener("focusin", this.onGainFocus.bind(this));
this.addEventListener("focusout", this.onLoseFocus.bind(this));
if (htmx) {
htmx.process(this);
}
}
attributeChangedCallback(name, oldValue, newValue) {
@@ -253,6 +257,10 @@ class FilterList extends HTMLElement {
return item.id;
}
getHREFEncoded(item) {
return encodeURIComponent(this.getHREF(item));
}
getSearchText(item) {
if (!item) {
return "";
@@ -351,7 +359,7 @@ class FilterList extends HTMLElement {
.map(
(item, index) => `
<a
href="${this._url}${this.getHREF(item)}"
href="${this._url}${this.getHREFEncoded(item)}"
class="${FILTER_LIST_ITEM} block px-2.5 py-0.5 hover:bg-slate-200 no-underline ${
index % 2 === 0 ? "bg-stone-100" : "bg-stone-50"
}"