Widget:SearchBox: Unterschied zwischen den Versionen
Aus MediaWiki
Alex (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
Alex (Diskussion | Beiträge) Styling update: green button matching homepage, rounded cards, homepage overlay-compatible CSS |
||
| Zeile 2: | Zeile 2: | ||
<div id="api-search-widget"> | <div id="api-search-widget"> | ||
<form id="api-search-form"> | <form id="api-search-form"> | ||
<input type="text" id="api-search-input" placeholder=" | <input type="text" id="api-search-input" placeholder="z. B. Wochenmarkt, Bürgeramt, Aasee …" /> | ||
<button type="submit"> | <button type="submit">Suche</button> | ||
</form> | </form> | ||
<div id="api-search-results"></div> | <div id="api-search-results"></div> | ||
| Zeile 10: | Zeile 10: | ||
<style> | <style> | ||
#api-search-widget { | #api-search-widget { | ||
max-width: | max-width: 800px; | ||
margin: 0 auto; | |||
font-family: -apple-system, "system-ui", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; | font-family: -apple-system, "system-ui", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; | ||
color: #212529; | color: #212529; | ||
} | } | ||
/* --- Search form --- */ | |||
#api-search-form { | #api-search-form { | ||
display: flex; | display: flex; | ||
margin-bottom: 0; | |||
margin-bottom: | |||
} | } | ||
#api-search-input { | #api-search-input { | ||
| Zeile 23: | Zeile 25: | ||
padding: 10px 14px; | padding: 10px 14px; | ||
font-size: 16px; | font-size: 16px; | ||
border: | border: 1px solid #ccc; | ||
border-right: none; | border-right: none; | ||
border-radius: 4px 0 0 4px; | border-radius: 4px 0 0 4px; | ||
outline: none; | outline: none; | ||
transition: border-color 0.2s; | transition: border-color 0.2s, box-shadow 0.2s; | ||
color: #212529; | color: #212529; | ||
background: #fff; | background: #fff; | ||
} | } | ||
#api-search-input:focus { | #api-search-input:focus { | ||
border-color: # | border-color: #4CAF50; | ||
box-shadow: inset 0 1px 3px rgba(0,0,0,0.08); | |||
} | } | ||
#api-search-form button { | #api-search-form button { | ||
padding: 10px | padding: 10px 24px; | ||
font-size: 16px; | font-size: 16px; | ||
font-weight: 500; | font-weight: 500; | ||
cursor: pointer; | cursor: pointer; | ||
background: # | background: #4CAF50; | ||
color: #fff; | color: #fff; | ||
border: | border: none; | ||
border-radius: 0 4px 4px 0; | border-radius: 0 4px 4px 0; | ||
transition: background 0.2s; | transition: background 0.2s; | ||
white-space: nowrap; | |||
} | } | ||
#api-search-form button:hover { | #api-search-form button:hover { | ||
background: # | background: #43A047; | ||
} | } | ||
/* --- Results container --- */ | |||
#api-search-results { | #api-search-results { | ||
display: none; | display: none; | ||
margin-top: 16px; | |||
} | } | ||
#api-search-results.visible { | #api-search-results.visible { | ||
display: block; | display: block; | ||
} | } | ||
/* --- Status / loading / error --- */ | |||
.search-status { | .search-status { | ||
padding: 16px; | padding: 16px; | ||
| Zeile 62: | Zeile 70: | ||
} | } | ||
.search-status.error { | .search-status.error { | ||
color: # | color: #b00; | ||
background: #fef2f2; | background: #fef2f2; | ||
border: 1px solid #fca5a5; | border: 1px solid #fca5a5; | ||
border-radius: | border-radius: 6px; | ||
} | } | ||
@keyframes | @keyframes searchPulse { | ||
0%, 100% { opacity: 1; } | 0%, 100% { opacity: 1; } | ||
50% { opacity: 0. | 50% { opacity: 0.4; } | ||
} | } | ||
.search-loading { | .search-loading { | ||
animation: | animation: searchPulse 1.4s ease-in-out infinite; | ||
} | |||
/* --- Result count --- */ | |||
.search-result-count { | |||
font-size: 13px; | |||
color: #6c757d; | |||
margin-bottom: 10px; | |||
padding-left: 2px; | |||
} | } | ||
/* --- Result cards --- */ | |||
.search-result-card { | .search-result-card { | ||
padding: 16px; | padding: 14px 16px; | ||
margin-bottom: | margin-bottom: 8px; | ||
border: 1px solid # | border: 1px solid #e0e0e0; | ||
border-radius: | border-radius: 6px; | ||
background: #fff; | background: #fff; | ||
transition: box-shadow 0.15s; | transition: border-color 0.15s, box-shadow 0.15s; | ||
} | } | ||
.search-result-card:hover { | .search-result-card:hover { | ||
box-shadow: 0 2px | border-color: #b0b8c1; | ||
box-shadow: 0 2px 6px rgba(0,0,0,0.06); | |||
} | } | ||
.search-result-card h4 { | .search-result-card h4 { | ||
margin: 0 0 | margin: 0 0 4px 0; | ||
font-size: | font-size: 16px; | ||
font-weight: | font-weight: 600; | ||
line-height: 1.3; | |||
} | } | ||
.search-result-card h4 a { | .search-result-card h4 a { | ||
color: # | color: #00308D; | ||
text-decoration: none; | text-decoration: none; | ||
} | } | ||
.search-result-card h4 a:hover { | .search-result-card h4 a:hover { | ||
text-decoration: underline; | text-decoration: underline; | ||
color: #1a5276; | |||
} | } | ||
.search-result-snippet { | .search-result-snippet { | ||
font-size: | font-size: 13.5px; | ||
line-height: 1. | line-height: 1.55; | ||
color: # | color: #444; | ||
margin-bottom: | margin-bottom: 6px; | ||
} | } | ||
.search-result-meta { | .search-result-meta { | ||
display: flex; | display: flex; | ||
gap: | align-items: center; | ||
gap: 14px; | |||
font-size: 12px; | font-size: 12px; | ||
color: # | color: #888; | ||
} | } | ||
.search-result-meta span { | .search-result-meta > span { | ||
display: inline-flex; | display: inline-flex; | ||
align-items: center; | align-items: center; | ||
gap: | gap: 5px; | ||
} | } | ||
.search-score-bar { | .search-score-bar { | ||
display: inline-block; | display: inline-block; | ||
width: | width: 44px; | ||
height: | height: 5px; | ||
background: # | background: #e0e0e0; | ||
border-radius: 3px; | border-radius: 3px; | ||
overflow: hidden; | overflow: hidden; | ||
| Zeile 125: | Zeile 147: | ||
.search-score-fill { | .search-score-fill { | ||
height: 100%; | height: 100%; | ||
background: # | background: #4CAF50; | ||
border-radius: 3px; | border-radius: 3px; | ||
} | } | ||
.search-result-count { | |||
/* --- Adapt when inside the homepage hero overlay --- */ | |||
color: # | .overlay-content #api-search-widget { | ||
max-width: 100%; | |||
} | |||
.overlay-content #api-search-results { | |||
text-align: left; | |||
} | |||
.overlay-content .search-result-count { | |||
color: rgba(255,255,255,0.7); | |||
} | |||
.overlay-content .search-status { | |||
color: rgba(255,255,255,0.8); | |||
} | |||
.overlay-content .search-status.error { | |||
color: #fca5a5; | |||
background: rgba(180,0,0,0.2); | |||
border-color: rgba(252,165,165,0.4); | |||
} | } | ||
</style> | </style> | ||
| Zeile 150: | Zeile 186: | ||
function truncate(str, len) { | function truncate(str, len) { | ||
if (str.length <= len) return str; | if (str.length <= len) return str; | ||
return str.substring(0, len).replace(/\s+\S*$/, '') + ' | return str.substring(0, len).replace(/\s+\S*$/, '') + '\u2026'; | ||
} | } | ||
| Zeile 169: | Zeile 205: | ||
html += '<div class="search-result-card">' | html += '<div class="search-result-card">' | ||
+ '<h4><a href="' + wikiUrl + '">' + escapeHtml(r.page_title || 'Ohne Titel') + '</a></h4>' | + '<h4><a href="' + wikiUrl + '">' + escapeHtml(r.page_title || 'Ohne Titel') + '</a></h4>' | ||
+ '<div class="search-result-snippet">' + escapeHtml(truncate(r.content_text || '', | + '<div class="search-result-snippet">' + escapeHtml(truncate(r.content_text || '', 220)) + '</div>' | ||
+ '<div class="search-result-meta">' | + '<div class="search-result-meta">' | ||
+ '<span>Relevanz: <span class="search-score-bar"><span class="search-score-fill" style="width:' + pct + '%"></span></span> ' + pct + '%</span>' | + '<span>Relevanz: <span class="search-score-bar"><span class="search-score-fill" style="width:' + pct + '%"></span></span> ' + pct + '%</span>' | ||
| Zeile 185: | Zeile 221: | ||
results.className = 'visible'; | results.className = 'visible'; | ||
results.innerHTML = '<div class="search-status search-loading">Suche | results.innerHTML = '<div class="search-status search-loading">Suche l\u00e4uft\u2026</div>'; | ||
var url = location.protocol + '//' + apiHost + '/search?q=' + encodeURIComponent(query); | var url = location.protocol + '//' + apiHost + '/search?q=' + encodeURIComponent(query); | ||