improve responsive layout of search results

This commit is contained in:
Harald Bamberger
2024-11-19 16:16:46 +01:00
parent 9c6509b32a
commit 4e4e8a0a5c
9 changed files with 144 additions and 66 deletions
+41
View File
@@ -473,4 +473,45 @@ html {
transition-property: background,color;
transition-duration: 0.3s,0.2s;
transition-timing-function: ease-out,ease-out;
}
@media screen and ( max-width: 767px ) {
#nav-search {
position: static;
}
#nav-search .searchbar_results {
top: 100%;
width: 98vw !important;
left: 1vw !important;
right: 1vw !important;
}
}
@media screen and ( max-width: 576px ) {
.searchbar_icon img {
max-width: 65px !important;
}
.searchbar_icon i {
font-size: 3em !important;
}
.searchbar_grid {
grid-template-columns: [icon] 75px [data] auto;
}
.searchbar_table,
.searchbar_tablerow,
.searchbar_tablecell {
display: block;
}
.searchbar_tablecell.searchbar_label {
font-weight: bold;
}
.searchbar_tablecell.searchbar_value {
padding-left: 2.5rem;
overflow-wrap: break-word;
}
}
@@ -21,14 +21,17 @@
z-index: 9998;
background-color: #fff;
border: 1px solid lightgrey;
padding: 1rem;
overflow-y: auto;
padding: .5rem;
top: 100%;
width: 100%;
left: 0;
right: 0;
}
.searchbar_results_scroller {
overflow-y: auto;
}
.searchbar_result {
border-bottom: 1px solid lightgrey;
margin-bottom: 1rem;
@@ -104,4 +107,4 @@
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
}
}
+10 -2
View File
@@ -15,6 +15,7 @@ const app = Vue.createApp({
return {
searchbaroptions: {
cssclass: "",
calcheightonly: true,
types: [
"mitarbeiter",
"raum",
@@ -75,9 +76,16 @@ const app = Vue.createApp({
},
organisationunit: {
defaultaction: {
type: "function",
type: "link",
renderif: function(data) {
if(data.mailgroup) {
return true;
}
return false;
},
action: function(data) {
alert('organisationunit defaultaction ' + JSON.stringify(data));
const link = 'mailto:' + data.mailgroup;
return link;
}
},
childactions: []
+8 -8
View File
@@ -30,8 +30,8 @@ export default {
<div class="searchbar_table">
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Standard-Kostenstelle</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Standard-Kostenstelle</div>
<div class="searchbar_tablecell searchbar_value">
<ul class="searchbar_inline_ul" v-if="res.standardkostenstelle.length > 0">
<li v-for="(stdkst, idx) in res.standardkostenstelle" :key="idx">{{ stdkst }}</li>
</ul>
@@ -40,8 +40,8 @@ export default {
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Organisations-Einheit</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Organisations-Einheit</div>
<div class="searchbar_tablecell searchbar_value">
<ul class="searchbar_inline_ul" v-if="res.organisationunit_name.length > 0">
<li v-for="(oe, idx) in res.organisationunit_name" :key="idx">{{ oe }}</li>
</ul>
@@ -50,8 +50,8 @@ export default {
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">EMail</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">EMail</div>
<div class="searchbar_tablecell searchbar_value">
<a :href="this.mailtourl">
{{ res.email }}
</a>
@@ -59,8 +59,8 @@ export default {
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Telefon</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Telefon</div>
<div class="searchbar_tablecell searchbar_value">
<a :href="this.telurl">
{{ res.phone }}
</a>
@@ -28,24 +28,25 @@ export default {
<div class="searchbar_table">
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">übergeordnete OrgEinheit</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">übergeordnete OrgEinheit</div>
<div class="searchbar_tablecell searchbar_value">
{{ res.parentoe_name }}
</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Gruppen-EMail</div>
<div class="searchbar_tablecell">
<a :href="this.mailtourl">
<div class="searchbar_tablecell searchbar_label">Gruppen-EMail</div>
<div class="searchbar_tablecell searchbar_value">
<a :href="this.mailtourl" v-if="res.mailgroup">
{{ res.mailgroup }}
</a>
<span v-else>-</span>
</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Leiter</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Leiter</div>
<div class="searchbar_tablecell searchbar_value">
<ul class="searchbar_inline_ul" v-if="res.leaders.length > 0">
<li v-for="(leader, idx) in res.leaders" :key="idx">{{ leader.name }}</li>
</ul>
@@ -54,8 +55,8 @@ export default {
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Mitarbeiter-Anzahl</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Mitarbeiter-Anzahl</div>
<div class="searchbar_tablecell searchbar_value">
{{ res.number_of_people }}
</div>
</div>
@@ -64,7 +65,7 @@ export default {
<actions :res="this.res" :actions="this.actions.childactions" @actionexecuted="$emit('actionexecuted')"></actions>
</div>
</div>
</div>
</div>
+2 -2
View File
@@ -29,8 +29,8 @@ export default {
<div class="searchbar_table">
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">EMail</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">EMail</div>
<div class="searchbar_tablecell searchbar_value">
<a :href="this.mailtourl">
{{ res.mail }}
</a>
+10 -10
View File
@@ -31,36 +31,36 @@ export default {
<div class="searchbar_table">
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Prestudent_id</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Prestudent_id</div>
<div class="searchbar_tablecell searchbar_value">
{{ res.prestudent_id }}
</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Student_uid</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Student_uid</div>
<div class="searchbar_tablecell searchbar_value">
{{ res.uid }}
</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Person_id</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Person_id</div>
<div class="searchbar_tablecell searchbar_value">
{{ res.person_id }}
</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Studiengang</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">Studiengang</div>
<div class="searchbar_tablecell searchbar_value">
{{ res.bezeichnung }}
</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">EMail</div>
<div class="searchbar_tablecell">
<div class="searchbar_tablecell searchbar_label">EMail</div>
<div class="searchbar_tablecell searchbar_value">
<a :href="this.mailtourl">
{{ res.email }}
</a>
+8 -8
View File
@@ -25,20 +25,20 @@ export default {
<div class="searchbar_table">
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Standort</div>
<div class="searchbar_tablecell">{{ res.standort }}</div>
<div class="searchbar_tablecell searchbar_label">Standort</div>
<div class="searchbar_tablecell searchbar_value">{{ res.standort }}</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Sitzplätze</div>
<div class="searchbar_tablecell">{{ res.sitzplaetze }}</div>
<div class="searchbar_tablecell searchbar_label">Sitzplätze</div>
<div class="searchbar_tablecell searchbar_value">{{ res.sitzplaetze }}</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Gebäude</div>
<div class="searchbar_tablecell">{{ res.building }}</div>
<div class="searchbar_tablecell searchbar_label">Gebäude</div>
<div class="searchbar_tablecell searchbar_value">{{ res.building }}</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Zusatz Informationen</div>
<div class="searchbar_tablecell"><div v-html="res.austattung.replace('<br />','')"></div></div>
<div class="searchbar_tablecell searchbar_label">Zusatz Informationen</div>
<div class="searchbar_tablecell searchbar_value"><div v-html="res.austattung.replace('<br />','')"></div></div>
</div>
</div>
+48 -23
View File
@@ -36,30 +36,33 @@ export default {
<form ref="searchform" class="d-flex me-3" :class="searchoptions.cssclass" action="javascript:void(0);"
@focusin="this.searchfocusin" @focusout="this.searchfocusout">
<div class="h-100 input-group me-2 bg-white">
<input ref="searchbox" @keyup="this.search" @focus="this.showsearchresult"
<div ref="searchbox" class="h-100 input-group me-2 bg-white">
<input @keyup="this.search" @focus="this.showsearchresult"
v-model="this.searchsettings.searchstr" class="form-control"
type="search" :placeholder="'Search: '+ searchsettings.types.join(' / ')" aria-label="Search">
<button data-bs-toggle="collapse" data-bs-target="#searchSettings" aria-expanded="false" aria-controls="searchSettings" ref="settingsbutton" class="btn btn-outline-secondary" type="button" id="search-filter"><i class="fas fa-cog"></i></button>
</div>
<div v-show="this.showresult" ref="result"
<div v-show="this.showresult"
class="searchbar_results" tabindex="-1">
<div v-if="this.searching">
<i class="fas fa-spinner fa-spin fa-2x"></i>
</div>
<div v-else-if="this.error !== null">{{ this.error }}</div>
<div v-else-if="searchresult.length < 1">Es wurden keine Ergebnisse gefunden.</div>
<template v-else="" v-for="res in searchresult">
<person v-if="res.type === 'person'" :res="res" :actions="this.searchoptions.actions.person" @actionexecuted="this.hideresult"></person>
<student v-else-if="res.type === 'student'" :res="res" :actions="this.searchoptions.actions.student" @actionexecuted="this.hideresult"></student>
<prestudent v-else-if="res.type === 'prestudent'" :res="res" :actions="this.searchoptions.actions.prestudent" @actionexecuted="this.hideresult"></prestudent>
<employee v-else-if="res.type === 'mitarbeiter' || res.type === 'mitarbeiter_ohne_zuordnung'" :res="res" :actions="this.searchoptions.actions.employee" @actionexecuted="this.hideresult"></employee>
<organisationunit v-else-if="res.type === 'organisationunit'" :res="res" :actions="this.searchoptions.actions.organisationunit" @actionexecuted="this.hideresult"></organisationunit>
<raum v-else-if="res.type === 'raum'" :res="res" :actions="this.searchoptions.actions.raum" @actionexecuted="this.hideresult"></raum>
<div v-else="">Unbekannter Ergebnistyp: '{{ res.type }}'.</div>
</template>
<div class="searchbar_results_scroller" ref="result">
<div class="searchbar_results_wrapper" ref="results">
<div v-if="this.searching">
<i class="fas fa-spinner fa-spin fa-2x"></i>
</div>
<div v-else-if="this.error !== null">{{ this.error }}</div>
<div v-else-if="searchresult.length < 1">Es wurden keine Ergebnisse gefunden.</div>
<template v-else="" v-for="res in searchresult">
<person v-if="res.type === 'person'" :res="res" :actions="this.searchoptions.actions.person" @actionexecuted="this.hideresult"></person>
<student v-else-if="res.type === 'student'" :res="res" :actions="this.searchoptions.actions.student" @actionexecuted="this.hideresult"></student>
<prestudent v-else-if="res.type === 'prestudent'" :res="res" :actions="this.searchoptions.actions.prestudent" @actionexecuted="this.hideresult"></prestudent>
<employee v-else-if="res.type === 'mitarbeiter' || res.type === 'mitarbeiter_ohne_zuordnung'" :res="res" :actions="this.searchoptions.actions.employee" @actionexecuted="this.hideresult"></employee>
<organisationunit v-else-if="res.type === 'organisationunit'" :res="res" :actions="this.searchoptions.actions.organisationunit" @actionexecuted="this.hideresult"></organisationunit>
<raum v-else-if="res.type === 'raum'" :res="res" :actions="this.searchoptions.actions.raum" @actionexecuted="this.hideresult"></raum>
<div v-else="">Unbekannter Ergebnistyp: '{{ res.type }}'.</div>
</template>
</div>
</duv>
</div>
<div id="searchSettings" ref="settings" @[\`show.bs.collapse\`]="$emit('showSettings','settings')"
@@ -91,6 +94,13 @@ export default {
toggle: false
});
},
updated() {
if(this.showresult) {
Vue.nextTick(() => {
this.calcSearchResultHeight();
});
}
},
methods: {
updateSearchOptions: function() {
this.searchsettings.types = [];
@@ -98,12 +108,26 @@ export default {
this.searchsettings.types.push(this.searchoptions.types[idx]);
}
},
calcSearchResultHeight: function() {
const rect = this.$refs.results.getBoundingClientRect();
if( rect.height > 0 && rect.height < (window.innerHeight * 0.8) ) {
this.$refs.result.style.height = Math.ceil(rect.height) + 'px';
} else {
this.$refs.result.style.height = Math.floor(window.innerHeight * 0.8) + 'px';
}
},
calcSearchResultExtent: function() {
var rect = this.$refs.searchbox.getBoundingClientRect();
this.$refs.result.style.top = Math.floor(rect.bottom + 3) + 'px';
this.$refs.result.style.right = Math.floor(window.innerWidth - rect.right) + 'px';
this.$refs.result.style.width = Math.floor(window.innerWidth * 0.75) + 'px';
this.$refs.result.style.height = Math.floor(window.innerHeight * 0.75) + 'px';
if(!this.showresult) {
return;
}
if(this.searchoptions?.calcheightonly === undefined
|| this.searchoptions.calcheightonly === false) {
var rect = this.$refs.searchbox.getBoundingClientRect();
this.$refs.result.style.top = Math.floor(rect.bottom + 3) + 'px';
this.$refs.result.style.right = Math.floor(rect.right) + 'px';
this.$refs.result.style.width = Math.floor(rect.width) + 'px';
}
this.calcSearchResultHeight();
},
search: function() {
if( this.searchtimer !== null ) {
@@ -159,6 +183,7 @@ export default {
if( this.searchsettings.searchstr.length >= 2 ) {
this.showresult = true;
window.addEventListener('resize', this.calcSearchResultExtent);
this.calcSearchResultExtent();
}
},
searchfocusin: function(e) {