2023-02-11 21:16:48 +00:00
|
|
|
|
{{ define "hidden-field" -}}
|
2023-02-12 20:06:48 +00:00
|
|
|
|
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InputField*/ -}}
|
|
|
|
|
<input type="hidden" name="{{ .Name }}"
|
2023-02-11 21:16:48 +00:00
|
|
|
|
{{- range $attribute := .Attributes }} {{$attribute}} {{ end }}
|
2023-02-12 20:06:48 +00:00
|
|
|
|
value="{{ .Val }}">
|
2023-02-11 21:16:48 +00:00
|
|
|
|
{{- end }}
|
|
|
|
|
|
2023-01-31 14:40:12 +00:00
|
|
|
|
{{ define "input-field" -}}
|
2023-02-12 20:06:48 +00:00
|
|
|
|
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InputField*/ -}}
|
2023-01-31 14:40:12 +00:00
|
|
|
|
<div class="input {{ if .Errors }}has-errors{{ end }}">
|
2023-02-07 14:28:22 +00:00
|
|
|
|
{{ if eq .Type "textarea" }}
|
2023-02-08 12:47:36 +00:00
|
|
|
|
<textarea name="{{ .Name }}" id="{{ .Name }}-field"
|
2023-02-07 14:28:22 +00:00
|
|
|
|
{{- range $attribute := .Attributes }} {{$attribute}} {{ end }}
|
2023-02-08 12:47:36 +00:00
|
|
|
|
{{ if .Required }}required="required"{{ end }} placeholder="{{ .Label }}"
|
|
|
|
|
>{{ .Val }}</textarea>
|
2023-02-07 14:28:22 +00:00
|
|
|
|
{{ else }}
|
|
|
|
|
<input type="{{ .Type }}" name="{{ .Name }}" id="{{ .Name }}-field"
|
|
|
|
|
{{- range $attribute := .Attributes }} {{$attribute}} {{ end }}
|
|
|
|
|
{{ if .Required }}required="required"{{ end }} value="{{ .Val }}" placeholder="{{ .Label }}">
|
|
|
|
|
{{ end }}
|
2023-01-31 14:40:12 +00:00
|
|
|
|
<label for="{{ .Name }}-field">{{ .Label }}</label>
|
2023-02-01 10:02:32 +00:00
|
|
|
|
{{- if .Errors }}
|
2023-01-31 14:40:12 +00:00
|
|
|
|
<ul>
|
|
|
|
|
{{- range $error := .Errors }}
|
|
|
|
|
<li>{{ . }}</li>
|
|
|
|
|
{{- end }}
|
|
|
|
|
</ul>
|
2023-02-01 10:02:32 +00:00
|
|
|
|
{{- end }}
|
2023-01-31 14:40:12 +00:00
|
|
|
|
</div>
|
|
|
|
|
{{- end }}
|
|
|
|
|
|
2023-02-12 20:06:48 +00:00
|
|
|
|
{{ define "hidden-select-field" -}}
|
|
|
|
|
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.SelectField*/ -}}
|
|
|
|
|
{{- range $selected := .Selected }}
|
|
|
|
|
<input type="hidden" name="{{ $.Name }}"
|
|
|
|
|
{{- range $attribute := $.Attributes }} {{$attribute}} {{ end }}
|
|
|
|
|
value="{{ . }}">
|
|
|
|
|
{{- end }}
|
|
|
|
|
{{- end }}
|
|
|
|
|
|
2023-01-31 14:40:12 +00:00
|
|
|
|
{{ define "select-field" -}}
|
2023-02-12 20:06:48 +00:00
|
|
|
|
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.SelectField*/ -}}
|
2023-03-15 10:44:18 +00:00
|
|
|
|
<div class="input{{ if .Errors }} has-errors{{ end }}"
|
|
|
|
|
{{- if .Multiple }}
|
2023-03-16 11:52:44 +00:00
|
|
|
|
@focusin.window="! $el.contains($event.target) && close() "
|
|
|
|
|
@click.away="close()"
|
2023-03-15 10:44:18 +00:00
|
|
|
|
x-data="{
|
2023-03-16 11:52:44 +00:00
|
|
|
|
options: [],
|
|
|
|
|
name: '',
|
|
|
|
|
filter: '',
|
2023-03-15 10:44:18 +00:00
|
|
|
|
open: false,
|
|
|
|
|
init() {
|
2023-03-16 11:52:44 +00:00
|
|
|
|
const select = $el.querySelector('select');
|
|
|
|
|
this.name = select.name;
|
|
|
|
|
for (const option of select.options) {
|
|
|
|
|
this.options.push({
|
|
|
|
|
value: option.value,
|
|
|
|
|
label: option.innerText,
|
|
|
|
|
search: this.normalize(option.innerText),
|
|
|
|
|
selected: option.getAttribute('selected') !== null,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
select.remove();
|
|
|
|
|
const template = $el.querySelector('template');
|
|
|
|
|
const input = template.content.querySelector('input');
|
|
|
|
|
const label = $el.querySelector('label');
|
|
|
|
|
input.after(label);
|
|
|
|
|
},
|
|
|
|
|
selected() {
|
|
|
|
|
return this.options.filter(option => option.selected);
|
|
|
|
|
},
|
|
|
|
|
normalize(s) {
|
|
|
|
|
return s.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase();
|
|
|
|
|
},
|
|
|
|
|
unselected() {
|
|
|
|
|
const filter = this.normalize(this.filter);
|
|
|
|
|
return this.options.filter(option => !option.selected && (filter === '' || option.search.includes(filter)));
|
|
|
|
|
},
|
|
|
|
|
empty() {
|
|
|
|
|
return this.selected().length === 0;
|
|
|
|
|
},
|
|
|
|
|
selectOption(option) {
|
|
|
|
|
option.selected = true;
|
|
|
|
|
this.filter = '';
|
|
|
|
|
},
|
|
|
|
|
selectFirst() {
|
|
|
|
|
if (!this.open) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const all = this.unselected();
|
|
|
|
|
if (all.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.selectOption(all[0]);
|
|
|
|
|
},
|
|
|
|
|
unselectLast() {
|
|
|
|
|
if (this.filter !== '') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const all = this.selected();
|
|
|
|
|
if (all.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
all[all.length - 1].selected = false;
|
|
|
|
|
},
|
|
|
|
|
toggle() {
|
|
|
|
|
if (this.open) {
|
|
|
|
|
return this.close();
|
|
|
|
|
}
|
|
|
|
|
this.open = true;
|
|
|
|
|
},
|
|
|
|
|
close() {
|
|
|
|
|
this.open = false;
|
2023-03-15 10:44:18 +00:00
|
|
|
|
},
|
|
|
|
|
}"
|
|
|
|
|
{{- end -}}
|
|
|
|
|
>
|
2023-02-01 13:15:02 +00:00
|
|
|
|
<select id="{{ .Name }}-field" name="{{ .Name }}"
|
2023-02-05 13:06:33 +00:00
|
|
|
|
{{- range $attribute := .Attributes }} {{$attribute}} {{ end -}}
|
2023-03-01 10:40:23 +00:00
|
|
|
|
{{ if .Multiple }} multiple="multiple"{{ end -}}
|
|
|
|
|
{{ if .Required }} required="required"{{ end -}}
|
2023-02-01 13:15:02 +00:00
|
|
|
|
>
|
2023-02-05 13:06:33 +00:00
|
|
|
|
{{- with .EmptyLabel }}
|
|
|
|
|
<option value="">{{ . }}</option>
|
|
|
|
|
{{- end}}
|
2023-03-01 10:40:23 +00:00
|
|
|
|
{{- $withinGroup := "" -}}
|
2023-02-05 13:06:33 +00:00
|
|
|
|
{{- range $option := .Options }}
|
2023-03-01 10:40:23 +00:00
|
|
|
|
{{- if ne .Group $withinGroup }}
|
|
|
|
|
{{- if ne $withinGroup "" }}
|
|
|
|
|
</optgroup>
|
|
|
|
|
{{ end }}
|
|
|
|
|
<optgroup label="{{ .Group }}">
|
|
|
|
|
{{- $withinGroup = .Group -}}
|
|
|
|
|
{{ end }}
|
2023-02-05 13:06:33 +00:00
|
|
|
|
<option value="{{ .Value }}"
|
2023-02-08 12:47:36 +00:00
|
|
|
|
{{- if $.IsSelected .Value }} selected="selected"{{ end }}>{{ .Label }}</option>
|
2023-03-01 10:40:23 +00:00
|
|
|
|
{{- end }}
|
|
|
|
|
{{- if ne $withinGroup "" }}
|
|
|
|
|
</optgroup>
|
2023-02-05 13:06:33 +00:00
|
|
|
|
{{- end }}
|
2023-01-31 14:40:12 +00:00
|
|
|
|
</select>
|
2023-03-15 10:44:18 +00:00
|
|
|
|
{{- if .Multiple }}
|
|
|
|
|
<template x-if="true">
|
|
|
|
|
<div class="multiselect">
|
2023-03-16 11:52:44 +00:00
|
|
|
|
<div class="tags" :class="{'empty': empty()}"
|
|
|
|
|
@click="toggle()"
|
|
|
|
|
>
|
|
|
|
|
<template x-for="option in selected()">
|
|
|
|
|
<div class="tag">
|
|
|
|
|
<input type="hidden" :name="name" :value="option.value">
|
2023-03-15 10:44:18 +00:00
|
|
|
|
<span x-text="option.label"></span>
|
|
|
|
|
<button type="button" @click.stop="option.selected = false">×</button>
|
2023-03-16 11:52:44 +00:00
|
|
|
|
</div>
|
2023-03-15 10:44:18 +00:00
|
|
|
|
</template>
|
2023-03-16 11:52:44 +00:00
|
|
|
|
<input id="{{ .Name }}-field" :placeholder="empty() && '{{ .Label }}'" x-model="filter"
|
|
|
|
|
@input="open = true"
|
|
|
|
|
@keydown.escape="close()"
|
|
|
|
|
@keydown.prevent.enter="selectFirst()"
|
|
|
|
|
@keydown.backspace="unselectLast()"
|
|
|
|
|
>
|
|
|
|
|
</div>
|
2023-03-15 10:44:18 +00:00
|
|
|
|
<ul class="options" x-show.transition="open">
|
2023-03-16 11:52:44 +00:00
|
|
|
|
<template x-for="option in unselected()">
|
2023-03-15 10:44:18 +00:00
|
|
|
|
<li
|
|
|
|
|
x-text="option.label"
|
2023-03-16 11:52:44 +00:00
|
|
|
|
@click.stop="selectOption(option)"
|
2023-03-15 10:44:18 +00:00
|
|
|
|
></li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
{{ end -}}
|
2023-01-31 14:40:12 +00:00
|
|
|
|
<label for="{{ .Name }}-field">{{ .Label }}</label>
|
2023-02-01 13:15:02 +00:00
|
|
|
|
{{- if .Errors }}
|
2023-01-31 14:40:12 +00:00
|
|
|
|
<ul>
|
|
|
|
|
{{- range $error := .Errors }}
|
|
|
|
|
<li>{{ . }}</li>
|
|
|
|
|
{{- end }}
|
|
|
|
|
</ul>
|
2023-02-01 13:15:02 +00:00
|
|
|
|
{{- end }}
|
2023-01-31 14:40:12 +00:00
|
|
|
|
</div>
|
|
|
|
|
{{- end }}
|