<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.muenster4you.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Alex</id>
	<title>MediaWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.muenster4you.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Alex"/>
	<link rel="alternate" type="text/html" href="https://www.muenster4you.de/wiki/Spezial:Beitr%C3%A4ge/Alex"/>
	<updated>2026-05-27T20:25:01Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Hauptseite&amp;diff=1082</id>
		<title>Hauptseite</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Hauptseite&amp;diff=1082"/>
		<updated>2026-04-23T14:20:43Z</updated>

		<summary type="html">&lt;p&gt;Alex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Willkommen in Münster==&lt;br /&gt;
Münster4you ist eine Plattform, die allen Menschen in Münster ermöglicht, Informationen schnell und unkompliziert abzurufen. Mit der Integration einer künstlichen Intelligenz, ähnlich wie eine Chat-Funktion, können alle Fragen stellen und erhalten Antworten für Münster, gleichzeitig findet sich neues und altbekanntes Wissen strukturiert aufbereitet.&lt;br /&gt;
&lt;br /&gt;
{{#widget:ChatBox}}&lt;br /&gt;
&lt;br /&gt;
== Bereiche dieser Seite ==&lt;br /&gt;
{{#widget:StartseitenBild|bildUrl=/w/images/6/64/Pexels-cottonbro-5137967.jpeg|link=Ankommen|text=Ankommen in Münster}}&lt;br /&gt;
&lt;br /&gt;
{{#widget:StartseitenBild|bildUrl=/w/images/f/f8/Aasee-Herbst-03-Philipp-Foelting-CC-BY-SA.jpg|link=Freizeit|text=Die funtastische Landingpage &amp;quot;Freizeit &amp;amp; Socializing&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
{{#widget:StartseitenBild|bildUrl=/w/images/c/c2/Münster_oben.jpg|link=Stadtteile|text=Stadtteil-Infoseiten}}&lt;br /&gt;
&lt;br /&gt;
== Karte von Münster == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;display_map height=&amp;quot;300px&amp;quot; scrollwheelzoom=&amp;quot;off&amp;quot; service=&amp;quot;leaflet&amp;quot;&amp;gt;&lt;br /&gt;
  Münster, Germany~Die Stadt Münster~Mein schönes Münster~ ~ ~Münster&lt;br /&gt;
  Mauritz-Lindenweg 95, 48145 Münster~Münster 08~Bester Sportverein~ ~ ~Münster 08&lt;br /&gt;
&amp;lt;/display_map&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:ChatBox&amp;diff=1080</id>
		<title>Widget:ChatBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:ChatBox&amp;diff=1080"/>
		<updated>2026-04-23T13:37:10Z</updated>

		<summary type="html">&lt;p&gt;Alex: fix: avoid &amp;amp;&amp;amp; and &amp;amp;middot; entities that MediaWiki HTML-encodes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;chat-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-messages&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-sources-panel&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;chat-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;chat-input&amp;quot; placeholder=&amp;quot;Stelle eine Frage über Münster …&amp;quot; autocomplete=&amp;quot;off&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot; id=&amp;quot;chat-send&amp;quot;&amp;gt;Fragen&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-footer&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;span id=&amp;quot;chat-status&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;button id=&amp;quot;chat-new&amp;quot; type=&amp;quot;button&amp;quot;&amp;gt;Neue Unterhaltung&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#chat-widget {&lt;br /&gt;
  max-width: 800px;&lt;br /&gt;
  margin: 0 auto;&lt;br /&gt;
  font-family: -apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, sans-serif;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
}&lt;br /&gt;
#chat-messages {&lt;br /&gt;
  min-height: 120px;&lt;br /&gt;
  max-height: 500px;&lt;br /&gt;
  overflow-y: auto;&lt;br /&gt;
  padding: 8px 0;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
  gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
#chat-messages:empty::before {&lt;br /&gt;
  content: &amp;quot;Stelle eine Frage und erhalte Antworten basierend auf dem Münster Wiki.&amp;quot;;&lt;br /&gt;
  display: block;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  color: #999;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  padding: 40px 16px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg {&lt;br /&gt;
  max-width: 85%;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  border-radius: 10px;&lt;br /&gt;
  font-size: 14.5px;&lt;br /&gt;
  line-height: 1.55;&lt;br /&gt;
  word-wrap: break-word;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-user {&lt;br /&gt;
  align-self: flex-end;&lt;br /&gt;
  background: #00308D;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border-bottom-right-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant {&lt;br /&gt;
  align-self: flex-start;&lt;br /&gt;
  background: #f0f2f5;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  border-bottom-left-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant p {&lt;br /&gt;
  margin: 0 0 8px 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant p:last-child {&lt;br /&gt;
  margin-bottom: 0;&lt;br /&gt;
}&lt;br /&gt;
@keyframes chatDots {&lt;br /&gt;
  0%, 80%, 100% { opacity: 0.3; }&lt;br /&gt;
  40% { opacity: 1; }&lt;br /&gt;
}&lt;br /&gt;
.chat-loading-dots span {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  width: 7px;&lt;br /&gt;
  height: 7px;&lt;br /&gt;
  margin: 0 2px;&lt;br /&gt;
  background: #999;&lt;br /&gt;
  border-radius: 50%;&lt;br /&gt;
  animation: chatDots 1.2s ease-in-out infinite;&lt;br /&gt;
}&lt;br /&gt;
.chat-loading-dots span:nth-child(2) { animation-delay: 0.15s; }&lt;br /&gt;
.chat-loading-dots span:nth-child(3) { animation-delay: 0.3s; }&lt;br /&gt;
#chat-sources-panel {&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
#chat-sources-panel.visible {&lt;br /&gt;
  display: block;&lt;br /&gt;
  margin: 4px 0 8px 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-toggle {&lt;br /&gt;
  background: none;&lt;br /&gt;
  border: 1px solid #ddd;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  padding: 6px 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  transition: background 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-toggle:hover {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-list {&lt;br /&gt;
  display: none;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-list.open {&lt;br /&gt;
  display: block;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item {&lt;br /&gt;
  padding: 10px 12px;&lt;br /&gt;
  margin-bottom: 6px;&lt;br /&gt;
  border: 1px solid #e0e0e0;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
  transition: border-color 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item:hover {&lt;br /&gt;
  border-color: #b0b8c1;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 {&lt;br /&gt;
  margin: 0 0 3px 0;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  font-weight: 600;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 a {&lt;br /&gt;
  color: #00308D;&lt;br /&gt;
  text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 a:hover {&lt;br /&gt;
  text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item .chat-source-snippet {&lt;br /&gt;
  font-size: 12.5px;&lt;br /&gt;
  line-height: 1.45;&lt;br /&gt;
  color: #666;&lt;br /&gt;
  margin: 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item .chat-source-meta {&lt;br /&gt;
  font-size: 11px;&lt;br /&gt;
  color: #999;&lt;br /&gt;
  margin-top: 3px;&lt;br /&gt;
}&lt;br /&gt;
#chat-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
#chat-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-right: none;&lt;br /&gt;
  border-radius: 4px 0 0 4px;&lt;br /&gt;
  outline: none;&lt;br /&gt;
  transition: border-color 0.2s;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
}&lt;br /&gt;
#chat-input:focus {&lt;br /&gt;
  border-color: #4CAF50;&lt;br /&gt;
}&lt;br /&gt;
#chat-input:disabled {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
  color: #999;&lt;br /&gt;
}&lt;br /&gt;
#chat-send {&lt;br /&gt;
  padding: 10px 20px;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  background: #4CAF50;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border: none;&lt;br /&gt;
  border-radius: 0 4px 4px 0;&lt;br /&gt;
  transition: background 0.2s;&lt;br /&gt;
  white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
#chat-send:hover {&lt;br /&gt;
  background: #43A047;&lt;br /&gt;
}&lt;br /&gt;
#chat-send:disabled {&lt;br /&gt;
  background: #a5d6a7;&lt;br /&gt;
  cursor: not-allowed;&lt;br /&gt;
}&lt;br /&gt;
#chat-footer {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  justify-content: space-between;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
}&lt;br /&gt;
#chat-status {&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #888;&lt;br /&gt;
}&lt;br /&gt;
#chat-new {&lt;br /&gt;
  display: none;&lt;br /&gt;
  background: none;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
  padding: 4px 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  transition: background 0.15s;&lt;br /&gt;
}&lt;br /&gt;
#chat-new:hover {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
}&lt;br /&gt;
#chat-new.visible {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-error {&lt;br /&gt;
  align-self: center;&lt;br /&gt;
  background: #fef2f2;&lt;br /&gt;
  color: #b00;&lt;br /&gt;
  border: 1px solid #fca5a5;&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  padding: 8px 14px;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;chat-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;chat-input&#039;);&lt;br /&gt;
  var sendBtn = document.getElementById(&#039;chat-send&#039;);&lt;br /&gt;
  var messagesEl = document.getElementById(&#039;chat-messages&#039;);&lt;br /&gt;
  var sourcesPanel = document.getElementById(&#039;chat-sources-panel&#039;);&lt;br /&gt;
  var statusEl = document.getElementById(&#039;chat-status&#039;);&lt;br /&gt;
  var newBtn = document.getElementById(&#039;chat-new&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  var conversationId = null;&lt;br /&gt;
  var isLoading = false;&lt;br /&gt;
&lt;br /&gt;
  function escapeHtml(str) {&lt;br /&gt;
    var d = document.createElement(&#039;div&#039;);&lt;br /&gt;
    d.textContent = str;&lt;br /&gt;
    return d.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function truncate(str, len) {&lt;br /&gt;
    if (str.length &amp;lt;= len) return str;&lt;br /&gt;
    return str.substring(0, len).replace(/\s+\S*$/, &#039;&#039;) + &#039;\u2026&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function formatAnswer(text) {&lt;br /&gt;
    var html = escapeHtml(text);&lt;br /&gt;
    html = html.replace(/\*\*(.+?)\*\*/g, &#039;&amp;lt;strong&amp;gt;$1&amp;lt;/strong&amp;gt;&#039;);&lt;br /&gt;
    var paragraphs = html.split(/\n{2,}/);&lt;br /&gt;
    if (paragraphs.length &amp;gt; 1) {&lt;br /&gt;
      html = paragraphs.map(function(p) { return &#039;&amp;lt;p&amp;gt;&#039; + p.replace(/\n/g, &#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/p&amp;gt;&#039;; }).join(&#039;&#039;);&lt;br /&gt;
    } else {&lt;br /&gt;
      html = html.replace(/\n/g, &#039;&amp;lt;br&amp;gt;&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    return html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addUserMessage(text) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-user&#039;;&lt;br /&gt;
    div.textContent = text;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addAssistantMessage(text) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-assistant&#039;;&lt;br /&gt;
    div.innerHTML = formatAnswer(text);&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addLoadingIndicator() {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-assistant chat-loading-dots&#039;;&lt;br /&gt;
    div.id = &#039;chat-loading&#039;;&lt;br /&gt;
    div.innerHTML = &#039;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&#039;;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeLoadingIndicator() {&lt;br /&gt;
    var el = document.getElementById(&#039;chat-loading&#039;);&lt;br /&gt;
    if (el) el.remove();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addError(msg) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-error&#039;;&lt;br /&gt;
    div.textContent = msg;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function scrollToBottom() {&lt;br /&gt;
    messagesEl.scrollTop = messagesEl.scrollHeight;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function renderSources(sources) {&lt;br /&gt;
    if (!sources || sources.length === 0) {&lt;br /&gt;
      sourcesPanel.className = &#039;&#039;;&lt;br /&gt;
      sourcesPanel.innerHTML = &#039;&#039;;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    sourcesPanel.className = &#039;visible&#039;;&lt;br /&gt;
    var listId = &#039;src-list-&#039; + Date.now();&lt;br /&gt;
    var html = &#039;&amp;lt;button class=&amp;quot;chat-sources-toggle&amp;quot; onclick=&amp;quot;var l=document.getElementById(\&#039;&#039; + listId + &#039;\&#039;);l.classList.toggle(\&#039;open\&#039;);this.textContent=l.classList.contains(\&#039;open\&#039;)?\&#039;▲ Quellen verbergen\&#039;:\&#039;▼ &#039; + sources.length + &#039; Quellen anzeigen\&#039;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
      + &#039;▼ &#039; + sources.length + &#039; Quellen anzeigen&amp;lt;/button&amp;gt;&#039;;&lt;br /&gt;
    html += &#039;&amp;lt;div class=&amp;quot;chat-sources-list&amp;quot; id=&amp;quot;&#039; + listId + &#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
    sources.forEach(function(s) {&lt;br /&gt;
      var pct = Math.round((s.similarity_score || 0) * 100);&lt;br /&gt;
      var wikiUrl = &#039;/wiki/&#039; + encodeURIComponent((s.page_title || &#039;&#039;).replace(/ /g, &#039;_&#039;));&lt;br /&gt;
      html += &#039;&amp;lt;div class=&amp;quot;chat-source-item&amp;quot;&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;h5&amp;gt;&amp;lt;a href=&amp;quot;&#039; + wikiUrl + &#039;&amp;quot;&amp;gt;&#039; + escapeHtml(s.page_title || &#039;&#039;) + &#039;&amp;lt;/a&amp;gt;&amp;lt;/h5&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;p class=&amp;quot;chat-source-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(truncate(s.content_text || &#039;&#039;, 150)) + &#039;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;div class=&amp;quot;chat-source-meta&amp;quot;&amp;gt;Relevanz: &#039; + pct + &#039;% · &#039; + escapeHtml(s.source || &#039;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    });&lt;br /&gt;
    html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    sourcesPanel.innerHTML = html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function setLoading(loading) {&lt;br /&gt;
    isLoading = loading;&lt;br /&gt;
    input.disabled = loading;&lt;br /&gt;
    sendBtn.disabled = loading;&lt;br /&gt;
    if (loading) {&lt;br /&gt;
      addLoadingIndicator();&lt;br /&gt;
    } else {&lt;br /&gt;
      removeLoadingIndicator();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function updateStatus(remaining) {&lt;br /&gt;
    if (remaining &amp;gt; 0) {&lt;br /&gt;
      statusEl.textContent = remaining + &#039; R\u00fcckfrage&#039; + (remaining !== 1 ? &#039;n&#039; : &#039;&#039;) + &#039; verbleibend&#039;;&lt;br /&gt;
    } else if (remaining === 0) { if (conversationId) {&lt;br /&gt;
      statusEl.textContent = &#039;Keine R\u00fcckfragen mehr m\u00f6glich&#039;;&lt;br /&gt;
      input.disabled = true;&lt;br /&gt;
      sendBtn.disabled = true;&lt;br /&gt;
      input.placeholder = &#039;Starte eine neue Unterhaltung&#039;;&lt;br /&gt;
    } }&lt;br /&gt;
    newBtn.className = conversationId ? &#039;visible&#039; : &#039;&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function resetConversation() {&lt;br /&gt;
    conversationId = null;&lt;br /&gt;
    messagesEl.innerHTML = &#039;&#039;;&lt;br /&gt;
    sourcesPanel.className = &#039;&#039;;&lt;br /&gt;
    sourcesPanel.innerHTML = &#039;&#039;;&lt;br /&gt;
    statusEl.textContent = &#039;&#039;;&lt;br /&gt;
    newBtn.className = &#039;&#039;;&lt;br /&gt;
    input.disabled = false;&lt;br /&gt;
    sendBtn.disabled = false;&lt;br /&gt;
    input.placeholder = &#039;Stelle eine Frage \u00fcber M\u00fcnster \u2026&#039;;&lt;br /&gt;
    input.focus();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  newBtn.addEventListener(&#039;click&#039;, resetConversation);&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    if (isLoading) return;&lt;br /&gt;
    var message = input.value.trim();&lt;br /&gt;
    if (!message) return;&lt;br /&gt;
&lt;br /&gt;
    input.value = &#039;&#039;;&lt;br /&gt;
    addUserMessage(message);&lt;br /&gt;
    setLoading(true);&lt;br /&gt;
&lt;br /&gt;
    var body = { message: message };&lt;br /&gt;
    if (conversationId) {&lt;br /&gt;
      body.conversation_id = conversationId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/chat&#039;;&lt;br /&gt;
&lt;br /&gt;
    fetch(url, {&lt;br /&gt;
      method: &#039;POST&#039;,&lt;br /&gt;
      headers: { &#039;Content-Type&#039;: &#039;application/json&#039; },&lt;br /&gt;
      body: JSON.stringify(body)&lt;br /&gt;
    })&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) {&lt;br /&gt;
          return res.json().then(function(data) {&lt;br /&gt;
            throw new Error(data.detail || &#039;HTTP &#039; + res.status);&lt;br /&gt;
          });&lt;br /&gt;
        }&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        setLoading(false);&lt;br /&gt;
        conversationId = data.conversation_id;&lt;br /&gt;
        addAssistantMessage(data.answer);&lt;br /&gt;
        renderSources(data.sources);&lt;br /&gt;
        updateStatus(data.remaining_followups);&lt;br /&gt;
        input.focus();&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        setLoading(false);&lt;br /&gt;
        addError(&#039;Fehler: &#039; + err.message);&lt;br /&gt;
        input.focus();&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=ChatBox&amp;diff=1078</id>
		<title>ChatBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=ChatBox&amp;diff=1078"/>
		<updated>2026-04-23T13:31:23Z</updated>

		<summary type="html">&lt;p&gt;Alex: Create ChatBox demo page with RAG chat widget&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#widget:ChatBox}}&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:ChatBox&amp;diff=1077</id>
		<title>Widget:ChatBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:ChatBox&amp;diff=1077"/>
		<updated>2026-04-23T13:31:00Z</updated>

		<summary type="html">&lt;p&gt;Alex: Create ChatBox widget for multi-turn RAG chat&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;chat-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-messages&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-sources-panel&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;chat-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;chat-input&amp;quot; placeholder=&amp;quot;Stelle eine Frage über Münster …&amp;quot; autocomplete=&amp;quot;off&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot; id=&amp;quot;chat-send&amp;quot;&amp;gt;Fragen&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-footer&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;span id=&amp;quot;chat-status&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;button id=&amp;quot;chat-new&amp;quot; type=&amp;quot;button&amp;quot;&amp;gt;Neue Unterhaltung&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#chat-widget {&lt;br /&gt;
  max-width: 800px;&lt;br /&gt;
  margin: 0 auto;&lt;br /&gt;
  font-family: -apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, sans-serif;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
}&lt;br /&gt;
#chat-messages {&lt;br /&gt;
  min-height: 120px;&lt;br /&gt;
  max-height: 500px;&lt;br /&gt;
  overflow-y: auto;&lt;br /&gt;
  padding: 8px 0;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
  gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
#chat-messages:empty::before {&lt;br /&gt;
  content: &amp;quot;Stelle eine Frage und erhalte Antworten basierend auf dem Münster Wiki.&amp;quot;;&lt;br /&gt;
  display: block;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  color: #999;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  padding: 40px 16px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg {&lt;br /&gt;
  max-width: 85%;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  border-radius: 10px;&lt;br /&gt;
  font-size: 14.5px;&lt;br /&gt;
  line-height: 1.55;&lt;br /&gt;
  word-wrap: break-word;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-user {&lt;br /&gt;
  align-self: flex-end;&lt;br /&gt;
  background: #00308D;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border-bottom-right-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant {&lt;br /&gt;
  align-self: flex-start;&lt;br /&gt;
  background: #f0f2f5;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  border-bottom-left-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant p {&lt;br /&gt;
  margin: 0 0 8px 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant p:last-child {&lt;br /&gt;
  margin-bottom: 0;&lt;br /&gt;
}&lt;br /&gt;
@keyframes chatDots {&lt;br /&gt;
  0%, 80%, 100% { opacity: 0.3; }&lt;br /&gt;
  40% { opacity: 1; }&lt;br /&gt;
}&lt;br /&gt;
.chat-loading-dots span {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  width: 7px;&lt;br /&gt;
  height: 7px;&lt;br /&gt;
  margin: 0 2px;&lt;br /&gt;
  background: #999;&lt;br /&gt;
  border-radius: 50%;&lt;br /&gt;
  animation: chatDots 1.2s ease-in-out infinite;&lt;br /&gt;
}&lt;br /&gt;
.chat-loading-dots span:nth-child(2) { animation-delay: 0.15s; }&lt;br /&gt;
.chat-loading-dots span:nth-child(3) { animation-delay: 0.3s; }&lt;br /&gt;
#chat-sources-panel {&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
#chat-sources-panel.visible {&lt;br /&gt;
  display: block;&lt;br /&gt;
  margin: 4px 0 8px 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-toggle {&lt;br /&gt;
  background: none;&lt;br /&gt;
  border: 1px solid #ddd;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  padding: 6px 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  transition: background 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-toggle:hover {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-list {&lt;br /&gt;
  display: none;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-list.open {&lt;br /&gt;
  display: block;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item {&lt;br /&gt;
  padding: 10px 12px;&lt;br /&gt;
  margin-bottom: 6px;&lt;br /&gt;
  border: 1px solid #e0e0e0;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
  transition: border-color 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item:hover {&lt;br /&gt;
  border-color: #b0b8c1;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 {&lt;br /&gt;
  margin: 0 0 3px 0;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  font-weight: 600;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 a {&lt;br /&gt;
  color: #00308D;&lt;br /&gt;
  text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 a:hover {&lt;br /&gt;
  text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item .chat-source-snippet {&lt;br /&gt;
  font-size: 12.5px;&lt;br /&gt;
  line-height: 1.45;&lt;br /&gt;
  color: #666;&lt;br /&gt;
  margin: 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item .chat-source-meta {&lt;br /&gt;
  font-size: 11px;&lt;br /&gt;
  color: #999;&lt;br /&gt;
  margin-top: 3px;&lt;br /&gt;
}&lt;br /&gt;
#chat-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
#chat-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-right: none;&lt;br /&gt;
  border-radius: 4px 0 0 4px;&lt;br /&gt;
  outline: none;&lt;br /&gt;
  transition: border-color 0.2s;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
}&lt;br /&gt;
#chat-input:focus {&lt;br /&gt;
  border-color: #4CAF50;&lt;br /&gt;
}&lt;br /&gt;
#chat-input:disabled {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
  color: #999;&lt;br /&gt;
}&lt;br /&gt;
#chat-send {&lt;br /&gt;
  padding: 10px 20px;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  background: #4CAF50;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border: none;&lt;br /&gt;
  border-radius: 0 4px 4px 0;&lt;br /&gt;
  transition: background 0.2s;&lt;br /&gt;
  white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
#chat-send:hover {&lt;br /&gt;
  background: #43A047;&lt;br /&gt;
}&lt;br /&gt;
#chat-send:disabled {&lt;br /&gt;
  background: #a5d6a7;&lt;br /&gt;
  cursor: not-allowed;&lt;br /&gt;
}&lt;br /&gt;
#chat-footer {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  justify-content: space-between;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
}&lt;br /&gt;
#chat-status {&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #888;&lt;br /&gt;
}&lt;br /&gt;
#chat-new {&lt;br /&gt;
  display: none;&lt;br /&gt;
  background: none;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
  padding: 4px 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  transition: background 0.15s;&lt;br /&gt;
}&lt;br /&gt;
#chat-new:hover {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
}&lt;br /&gt;
#chat-new.visible {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-error {&lt;br /&gt;
  align-self: center;&lt;br /&gt;
  background: #fef2f2;&lt;br /&gt;
  color: #b00;&lt;br /&gt;
  border: 1px solid #fca5a5;&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  padding: 8px 14px;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;chat-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;chat-input&#039;);&lt;br /&gt;
  var sendBtn = document.getElementById(&#039;chat-send&#039;);&lt;br /&gt;
  var messagesEl = document.getElementById(&#039;chat-messages&#039;);&lt;br /&gt;
  var sourcesPanel = document.getElementById(&#039;chat-sources-panel&#039;);&lt;br /&gt;
  var statusEl = document.getElementById(&#039;chat-status&#039;);&lt;br /&gt;
  var newBtn = document.getElementById(&#039;chat-new&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  var conversationId = null;&lt;br /&gt;
  var isLoading = false;&lt;br /&gt;
&lt;br /&gt;
  function escapeHtml(str) {&lt;br /&gt;
    var d = document.createElement(&#039;div&#039;);&lt;br /&gt;
    d.textContent = str;&lt;br /&gt;
    return d.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function truncate(str, len) {&lt;br /&gt;
    if (str.length &amp;lt;= len) return str;&lt;br /&gt;
    return str.substring(0, len).replace(/\s+\S*$/, &#039;&#039;) + &#039;\u2026&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function formatAnswer(text) {&lt;br /&gt;
    var html = escapeHtml(text);&lt;br /&gt;
    html = html.replace(/\*\*(.+?)\*\*/g, &#039;&amp;lt;strong&amp;gt;$1&amp;lt;/strong&amp;gt;&#039;);&lt;br /&gt;
    var paragraphs = html.split(/\n{2,}/);&lt;br /&gt;
    if (paragraphs.length &amp;gt; 1) {&lt;br /&gt;
      html = paragraphs.map(function(p) { return &#039;&amp;lt;p&amp;gt;&#039; + p.replace(/\n/g, &#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/p&amp;gt;&#039;; }).join(&#039;&#039;);&lt;br /&gt;
    } else {&lt;br /&gt;
      html = html.replace(/\n/g, &#039;&amp;lt;br&amp;gt;&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    return html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addUserMessage(text) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-user&#039;;&lt;br /&gt;
    div.textContent = text;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addAssistantMessage(text) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-assistant&#039;;&lt;br /&gt;
    div.innerHTML = formatAnswer(text);&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addLoadingIndicator() {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-assistant chat-loading-dots&#039;;&lt;br /&gt;
    div.id = &#039;chat-loading&#039;;&lt;br /&gt;
    div.innerHTML = &#039;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&#039;;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeLoadingIndicator() {&lt;br /&gt;
    var el = document.getElementById(&#039;chat-loading&#039;);&lt;br /&gt;
    if (el) el.remove();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addError(msg) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-error&#039;;&lt;br /&gt;
    div.textContent = msg;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function scrollToBottom() {&lt;br /&gt;
    messagesEl.scrollTop = messagesEl.scrollHeight;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function renderSources(sources) {&lt;br /&gt;
    if (!sources || sources.length === 0) {&lt;br /&gt;
      sourcesPanel.className = &#039;&#039;;&lt;br /&gt;
      sourcesPanel.innerHTML = &#039;&#039;;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    sourcesPanel.className = &#039;visible&#039;;&lt;br /&gt;
    var listId = &#039;src-list-&#039; + Date.now();&lt;br /&gt;
    var html = &#039;&amp;lt;button class=&amp;quot;chat-sources-toggle&amp;quot; onclick=&amp;quot;var l=document.getElementById(\&#039;&#039; + listId + &#039;\&#039;);l.classList.toggle(\&#039;open\&#039;);this.textContent=l.classList.contains(\&#039;open\&#039;)?\&#039;▲ Quellen verbergen\&#039;:\&#039;▼ &#039; + sources.length + &#039; Quellen anzeigen\&#039;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
      + &#039;▼ &#039; + sources.length + &#039; Quellen anzeigen&amp;lt;/button&amp;gt;&#039;;&lt;br /&gt;
    html += &#039;&amp;lt;div class=&amp;quot;chat-sources-list&amp;quot; id=&amp;quot;&#039; + listId + &#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
    sources.forEach(function(s) {&lt;br /&gt;
      var pct = Math.round((s.similarity_score || 0) * 100);&lt;br /&gt;
      var wikiUrl = &#039;/wiki/&#039; + encodeURIComponent((s.page_title || &#039;&#039;).replace(/ /g, &#039;_&#039;));&lt;br /&gt;
      html += &#039;&amp;lt;div class=&amp;quot;chat-source-item&amp;quot;&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;h5&amp;gt;&amp;lt;a href=&amp;quot;&#039; + wikiUrl + &#039;&amp;quot;&amp;gt;&#039; + escapeHtml(s.page_title || &#039;&#039;) + &#039;&amp;lt;/a&amp;gt;&amp;lt;/h5&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;p class=&amp;quot;chat-source-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(truncate(s.content_text || &#039;&#039;, 150)) + &#039;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;div class=&amp;quot;chat-source-meta&amp;quot;&amp;gt;Relevanz: &#039; + pct + &#039;% &amp;amp;middot; &#039; + escapeHtml(s.source || &#039;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    });&lt;br /&gt;
    html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    sourcesPanel.innerHTML = html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function setLoading(loading) {&lt;br /&gt;
    isLoading = loading;&lt;br /&gt;
    input.disabled = loading;&lt;br /&gt;
    sendBtn.disabled = loading;&lt;br /&gt;
    if (loading) {&lt;br /&gt;
      addLoadingIndicator();&lt;br /&gt;
    } else {&lt;br /&gt;
      removeLoadingIndicator();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function updateStatus(remaining) {&lt;br /&gt;
    if (remaining &amp;gt; 0) {&lt;br /&gt;
      statusEl.textContent = remaining + &#039; R\u00fcckfrage&#039; + (remaining !== 1 ? &#039;n&#039; : &#039;&#039;) + &#039; verbleibend&#039;;&lt;br /&gt;
    } else if (remaining === 0 &amp;amp;&amp;amp; conversationId) {&lt;br /&gt;
      statusEl.textContent = &#039;Keine R\u00fcckfragen mehr m\u00f6glich&#039;;&lt;br /&gt;
      input.disabled = true;&lt;br /&gt;
      sendBtn.disabled = true;&lt;br /&gt;
      input.placeholder = &#039;Starte eine neue Unterhaltung&#039;;&lt;br /&gt;
    }&lt;br /&gt;
    newBtn.className = conversationId ? &#039;visible&#039; : &#039;&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function resetConversation() {&lt;br /&gt;
    conversationId = null;&lt;br /&gt;
    messagesEl.innerHTML = &#039;&#039;;&lt;br /&gt;
    sourcesPanel.className = &#039;&#039;;&lt;br /&gt;
    sourcesPanel.innerHTML = &#039;&#039;;&lt;br /&gt;
    statusEl.textContent = &#039;&#039;;&lt;br /&gt;
    newBtn.className = &#039;&#039;;&lt;br /&gt;
    input.disabled = false;&lt;br /&gt;
    sendBtn.disabled = false;&lt;br /&gt;
    input.placeholder = &#039;Stelle eine Frage \u00fcber M\u00fcnster \u2026&#039;;&lt;br /&gt;
    input.focus();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  newBtn.addEventListener(&#039;click&#039;, resetConversation);&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    if (isLoading) return;&lt;br /&gt;
    var message = input.value.trim();&lt;br /&gt;
    if (!message) return;&lt;br /&gt;
&lt;br /&gt;
    input.value = &#039;&#039;;&lt;br /&gt;
    addUserMessage(message);&lt;br /&gt;
    setLoading(true);&lt;br /&gt;
&lt;br /&gt;
    var body = { message: message };&lt;br /&gt;
    if (conversationId) {&lt;br /&gt;
      body.conversation_id = conversationId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/chat&#039;;&lt;br /&gt;
&lt;br /&gt;
    fetch(url, {&lt;br /&gt;
      method: &#039;POST&#039;,&lt;br /&gt;
      headers: { &#039;Content-Type&#039;: &#039;application/json&#039; },&lt;br /&gt;
      body: JSON.stringify(body)&lt;br /&gt;
    })&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) {&lt;br /&gt;
          return res.json().then(function(data) {&lt;br /&gt;
            throw new Error(data.detail || &#039;HTTP &#039; + res.status);&lt;br /&gt;
          });&lt;br /&gt;
        }&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        setLoading(false);&lt;br /&gt;
        conversationId = data.conversation_id;&lt;br /&gt;
        addAssistantMessage(data.answer);&lt;br /&gt;
        renderSources(data.sources);&lt;br /&gt;
        updateStatus(data.remaining_followups);&lt;br /&gt;
        input.focus();&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        setLoading(false);&lt;br /&gt;
        addError(&#039;Fehler: &#039; + err.message);&lt;br /&gt;
        input.focus();&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1076</id>
		<title>Widget:SearchBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1076"/>
		<updated>2026-04-23T13:07:10Z</updated>

		<summary type="html">&lt;p&gt;Alex: Styling update: green button matching homepage, rounded cards, homepage overlay-compatible CSS&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;api-search-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;api-search-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;api-search-input&amp;quot; placeholder=&amp;quot;z. B. Wochenmarkt, Bürgeramt, Aasee …&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Suche&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;api-search-results&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#api-search-widget {&lt;br /&gt;
  max-width: 800px;&lt;br /&gt;
  margin: 0 auto;&lt;br /&gt;
  font-family: -apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, sans-serif;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* --- Search form --- */&lt;br /&gt;
#api-search-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  margin-bottom: 0;&lt;br /&gt;
}&lt;br /&gt;
#api-search-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  font-size: 16px;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-right: none;&lt;br /&gt;
  border-radius: 4px 0 0 4px;&lt;br /&gt;
  outline: none;&lt;br /&gt;
  transition: border-color 0.2s, box-shadow 0.2s;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
}&lt;br /&gt;
#api-search-input:focus {&lt;br /&gt;
  border-color: #4CAF50;&lt;br /&gt;
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.08);&lt;br /&gt;
}&lt;br /&gt;
#api-search-form button {&lt;br /&gt;
  padding: 10px 24px;&lt;br /&gt;
  font-size: 16px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  background: #4CAF50;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border: none;&lt;br /&gt;
  border-radius: 0 4px 4px 0;&lt;br /&gt;
  transition: background 0.2s;&lt;br /&gt;
  white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form button:hover {&lt;br /&gt;
  background: #43A047;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* --- Results container --- */&lt;br /&gt;
#api-search-results {&lt;br /&gt;
  display: none;&lt;br /&gt;
  margin-top: 16px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-results.visible {&lt;br /&gt;
  display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* --- Status / loading / error --- */&lt;br /&gt;
.search-status {&lt;br /&gt;
  padding: 16px;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
}&lt;br /&gt;
.search-status.error {&lt;br /&gt;
  color: #b00;&lt;br /&gt;
  background: #fef2f2;&lt;br /&gt;
  border: 1px solid #fca5a5;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
}&lt;br /&gt;
@keyframes searchPulse {&lt;br /&gt;
  0%, 100% { opacity: 1; }&lt;br /&gt;
  50% { opacity: 0.4; }&lt;br /&gt;
}&lt;br /&gt;
.search-loading {&lt;br /&gt;
  animation: searchPulse 1.4s ease-in-out infinite;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* --- Result count --- */&lt;br /&gt;
.search-result-count {&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  color: #6c757d;&lt;br /&gt;
  margin-bottom: 10px;&lt;br /&gt;
  padding-left: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* --- Result cards --- */&lt;br /&gt;
.search-result-card {&lt;br /&gt;
  padding: 14px 16px;&lt;br /&gt;
  margin-bottom: 8px;&lt;br /&gt;
  border: 1px solid #e0e0e0;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
  transition: border-color 0.15s, box-shadow 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card:hover {&lt;br /&gt;
  border-color: #b0b8c1;&lt;br /&gt;
  box-shadow: 0 2px 6px rgba(0,0,0,0.06);&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 {&lt;br /&gt;
  margin: 0 0 4px 0;&lt;br /&gt;
  font-size: 16px;&lt;br /&gt;
  font-weight: 600;&lt;br /&gt;
  line-height: 1.3;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 a {&lt;br /&gt;
  color: #00308D;&lt;br /&gt;
  text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 a:hover {&lt;br /&gt;
  text-decoration: underline;&lt;br /&gt;
  color: #1a5276;&lt;br /&gt;
}&lt;br /&gt;
.search-result-snippet {&lt;br /&gt;
  font-size: 13.5px;&lt;br /&gt;
  line-height: 1.55;&lt;br /&gt;
  color: #444;&lt;br /&gt;
  margin-bottom: 6px;&lt;br /&gt;
}&lt;br /&gt;
.search-result-meta {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  gap: 14px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #888;&lt;br /&gt;
}&lt;br /&gt;
.search-result-meta &amp;gt; span {&lt;br /&gt;
  display: inline-flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  gap: 5px;&lt;br /&gt;
}&lt;br /&gt;
.search-score-bar {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  width: 44px;&lt;br /&gt;
  height: 5px;&lt;br /&gt;
  background: #e0e0e0;&lt;br /&gt;
  border-radius: 3px;&lt;br /&gt;
  overflow: hidden;&lt;br /&gt;
  vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.search-score-fill {&lt;br /&gt;
  height: 100%;&lt;br /&gt;
  background: #4CAF50;&lt;br /&gt;
  border-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* --- Adapt when inside the homepage hero overlay --- */&lt;br /&gt;
.overlay-content #api-search-widget {&lt;br /&gt;
  max-width: 100%;&lt;br /&gt;
}&lt;br /&gt;
.overlay-content #api-search-results {&lt;br /&gt;
  text-align: left;&lt;br /&gt;
}&lt;br /&gt;
.overlay-content .search-result-count {&lt;br /&gt;
  color: rgba(255,255,255,0.7);&lt;br /&gt;
}&lt;br /&gt;
.overlay-content .search-status {&lt;br /&gt;
  color: rgba(255,255,255,0.8);&lt;br /&gt;
}&lt;br /&gt;
.overlay-content .search-status.error {&lt;br /&gt;
  color: #fca5a5;&lt;br /&gt;
  background: rgba(180,0,0,0.2);&lt;br /&gt;
  border-color: rgba(252,165,165,0.4);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;api-search-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;api-search-input&#039;);&lt;br /&gt;
  var results = document.getElementById(&#039;api-search-results&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  function escapeHtml(str) {&lt;br /&gt;
    var d = document.createElement(&#039;div&#039;);&lt;br /&gt;
    d.textContent = str;&lt;br /&gt;
    return d.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function truncate(str, len) {&lt;br /&gt;
    if (str.length &amp;lt;= len) return str;&lt;br /&gt;
    return str.substring(0, len).replace(/\s+\S*$/, &#039;&#039;) + &#039;\u2026&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function renderResults(data) {&lt;br /&gt;
    if (!data.results || data.results.length === 0) {&lt;br /&gt;
      results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status&amp;quot;&amp;gt;Keine Ergebnisse gefunden.&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    var html = &#039;&amp;lt;div class=&amp;quot;search-result-count&amp;quot;&amp;gt;&#039; + data.results.length + &#039; Ergebnis&#039; + (data.results.length !== 1 ? &#039;se&#039; : &#039;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    data.results.forEach(function(r) {&lt;br /&gt;
      if (typeof r === &#039;string&#039;) {&lt;br /&gt;
        html += &#039;&amp;lt;div class=&amp;quot;search-result-card&amp;quot;&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;div class=&amp;quot;search-result-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(r) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      } else {&lt;br /&gt;
        var pct = Math.round((r.similarity_score || 0) * 100);&lt;br /&gt;
        var wikiUrl = &#039;/wiki/&#039; + encodeURIComponent((r.page_title || &#039;&#039;).replace(/ /g, &#039;_&#039;));&lt;br /&gt;
        html += &#039;&amp;lt;div class=&amp;quot;search-result-card&amp;quot;&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;h4&amp;gt;&amp;lt;a href=&amp;quot;&#039; + wikiUrl + &#039;&amp;quot;&amp;gt;&#039; + escapeHtml(r.page_title || &#039;Ohne Titel&#039;) + &#039;&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;div class=&amp;quot;search-result-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(truncate(r.content_text || &#039;&#039;, 220)) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;div class=&amp;quot;search-result-meta&amp;quot;&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;span&amp;gt;Relevanz: &amp;lt;span class=&amp;quot;search-score-bar&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;search-score-fill&amp;quot; style=&amp;quot;width:&#039; + pct + &#039;%&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &#039; + pct + &#039;%&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
          + (r.source ? &#039;&amp;lt;span&amp;gt;Quelle: &#039; + escapeHtml(r.source) + &#039;&amp;lt;/span&amp;gt;&#039; : &#039;&#039;)&lt;br /&gt;
          + &#039;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      }&lt;br /&gt;
    });&lt;br /&gt;
    results.innerHTML = html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    var query = input.value.trim();&lt;br /&gt;
    if (!query) return;&lt;br /&gt;
&lt;br /&gt;
    results.className = &#039;visible&#039;;&lt;br /&gt;
    results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status search-loading&amp;quot;&amp;gt;Suche l\u00e4uft\u2026&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/search?q=&#039; + encodeURIComponent(query);&lt;br /&gt;
&lt;br /&gt;
    fetch(url)&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) throw new Error(&#039;HTTP &#039; + res.status);&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        renderResults(data);&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status error&amp;quot;&amp;gt;Fehler: &#039; + escapeHtml(err.message) + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1074</id>
		<title>Widget:SearchBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1074"/>
		<updated>2026-03-06T12:40:56Z</updated>

		<summary type="html">&lt;p&gt;Alex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;api-search-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;api-search-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;api-search-input&amp;quot; placeholder=&amp;quot;Suche…&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Suchen&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;api-search-results&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#api-search-widget {&lt;br /&gt;
  max-width: 720px;&lt;br /&gt;
  font-family: -apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, sans-serif;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  gap: 0;&lt;br /&gt;
  margin-bottom: 16px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  font-size: 16px;&lt;br /&gt;
  border: 2px solid #a2a9b1;&lt;br /&gt;
  border-right: none;&lt;br /&gt;
  border-radius: 4px 0 0 4px;&lt;br /&gt;
  outline: none;&lt;br /&gt;
  transition: border-color 0.2s;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
}&lt;br /&gt;
#api-search-input:focus {&lt;br /&gt;
  border-color: #355B84;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form button {&lt;br /&gt;
  padding: 10px 20px;&lt;br /&gt;
  font-size: 16px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  background: #355B84;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border: 2px solid #355B84;&lt;br /&gt;
  border-radius: 0 4px 4px 0;&lt;br /&gt;
  transition: background 0.2s;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form button:hover {&lt;br /&gt;
  background: #2a4a6b;&lt;br /&gt;
  border-color: #2a4a6b;&lt;br /&gt;
}&lt;br /&gt;
#api-search-results {&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
#api-search-results.visible {&lt;br /&gt;
  display: block;&lt;br /&gt;
}&lt;br /&gt;
.search-status {&lt;br /&gt;
  padding: 16px;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
}&lt;br /&gt;
.search-status.error {&lt;br /&gt;
  color: #a00;&lt;br /&gt;
  background: #fef2f2;&lt;br /&gt;
  border: 1px solid #fca5a5;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
@keyframes pulse {&lt;br /&gt;
  0%, 100% { opacity: 1; }&lt;br /&gt;
  50% { opacity: 0.5; }&lt;br /&gt;
}&lt;br /&gt;
.search-loading {&lt;br /&gt;
  animation: pulse 1.5s ease-in-out infinite;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card {&lt;br /&gt;
  padding: 16px;&lt;br /&gt;
  margin-bottom: 12px;&lt;br /&gt;
  border: 1px solid #dee2e6;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
  transition: box-shadow 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card:hover {&lt;br /&gt;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 {&lt;br /&gt;
  margin: 0 0 6px 0;&lt;br /&gt;
  font-size: 17px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 a {&lt;br /&gt;
  color: #1B599B;&lt;br /&gt;
  text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 a:hover {&lt;br /&gt;
  text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
.search-result-snippet {&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  line-height: 1.5;&lt;br /&gt;
  color: #333;&lt;br /&gt;
  margin-bottom: 8px;&lt;br /&gt;
}&lt;br /&gt;
.search-result-meta {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  gap: 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #6c757d;&lt;br /&gt;
}&lt;br /&gt;
.search-result-meta span {&lt;br /&gt;
  display: inline-flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  gap: 4px;&lt;br /&gt;
}&lt;br /&gt;
.search-score-bar {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  width: 40px;&lt;br /&gt;
  height: 6px;&lt;br /&gt;
  background: #dee2e6;&lt;br /&gt;
  border-radius: 3px;&lt;br /&gt;
  overflow: hidden;&lt;br /&gt;
  vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.search-score-fill {&lt;br /&gt;
  height: 100%;&lt;br /&gt;
  background: #355B84;&lt;br /&gt;
  border-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.search-result-count {&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  color: #6c757d;&lt;br /&gt;
  margin-bottom: 12px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;api-search-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;api-search-input&#039;);&lt;br /&gt;
  var results = document.getElementById(&#039;api-search-results&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  function escapeHtml(str) {&lt;br /&gt;
    var d = document.createElement(&#039;div&#039;);&lt;br /&gt;
    d.textContent = str;&lt;br /&gt;
    return d.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function truncate(str, len) {&lt;br /&gt;
    if (str.length &amp;lt;= len) return str;&lt;br /&gt;
    return str.substring(0, len).replace(/\s+\S*$/, &#039;&#039;) + &#039;…&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function renderResults(data) {&lt;br /&gt;
    if (!data.results || data.results.length === 0) {&lt;br /&gt;
      results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status&amp;quot;&amp;gt;Keine Ergebnisse gefunden.&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    var html = &#039;&amp;lt;div class=&amp;quot;search-result-count&amp;quot;&amp;gt;&#039; + data.results.length + &#039; Ergebnis&#039; + (data.results.length !== 1 ? &#039;se&#039; : &#039;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    data.results.forEach(function(r) {&lt;br /&gt;
      if (typeof r === &#039;string&#039;) {&lt;br /&gt;
        html += &#039;&amp;lt;div class=&amp;quot;search-result-card&amp;quot;&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;div class=&amp;quot;search-result-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(r) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      } else {&lt;br /&gt;
        var pct = Math.round((r.similarity_score || 0) * 100);&lt;br /&gt;
        var wikiUrl = &#039;/wiki/&#039; + encodeURIComponent((r.page_title || &#039;&#039;).replace(/ /g, &#039;_&#039;));&lt;br /&gt;
        html += &#039;&amp;lt;div class=&amp;quot;search-result-card&amp;quot;&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;h4&amp;gt;&amp;lt;a href=&amp;quot;&#039; + wikiUrl + &#039;&amp;quot;&amp;gt;&#039; + escapeHtml(r.page_title || &#039;Ohne Titel&#039;) + &#039;&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;div class=&amp;quot;search-result-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(truncate(r.content_text || &#039;&#039;, 250)) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;div class=&amp;quot;search-result-meta&amp;quot;&amp;gt;&#039;&lt;br /&gt;
          + &#039;&amp;lt;span&amp;gt;Relevanz: &amp;lt;span class=&amp;quot;search-score-bar&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;search-score-fill&amp;quot; style=&amp;quot;width:&#039; + pct + &#039;%&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &#039; + pct + &#039;%&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
          + (r.source ? &#039;&amp;lt;span&amp;gt;Quelle: &#039; + escapeHtml(r.source) + &#039;&amp;lt;/span&amp;gt;&#039; : &#039;&#039;)&lt;br /&gt;
          + &#039;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      }&lt;br /&gt;
    });&lt;br /&gt;
    results.innerHTML = html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    var query = input.value.trim();&lt;br /&gt;
    if (!query) return;&lt;br /&gt;
&lt;br /&gt;
    results.className = &#039;visible&#039;;&lt;br /&gt;
    results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status search-loading&amp;quot;&amp;gt;Suche läuft…&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/search?q=&#039; + encodeURIComponent(query);&lt;br /&gt;
&lt;br /&gt;
    fetch(url)&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) throw new Error(&#039;HTTP &#039; + res.status);&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        renderResults(data);&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status error&amp;quot;&amp;gt;Fehler: &#039; + escapeHtml(err.message) + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1073</id>
		<title>Widget:SearchBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1073"/>
		<updated>2026-03-06T12:38:48Z</updated>

		<summary type="html">&lt;p&gt;Alex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;api-search-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;api-search-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;api-search-input&amp;quot; placeholder=&amp;quot;Suche…&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Suchen&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;api-search-results&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#api-search-widget {&lt;br /&gt;
  max-width: 720px;&lt;br /&gt;
  font-family: -apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, sans-serif;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  gap: 0;&lt;br /&gt;
  margin-bottom: 16px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  font-size: 16px;&lt;br /&gt;
  border: 2px solid #a2a9b1;&lt;br /&gt;
  border-right: none;&lt;br /&gt;
  border-radius: 4px 0 0 4px;&lt;br /&gt;
  outline: none;&lt;br /&gt;
  transition: border-color 0.2s;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
}&lt;br /&gt;
#api-search-input:focus {&lt;br /&gt;
  border-color: #355B84;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form button {&lt;br /&gt;
  padding: 10px 20px;&lt;br /&gt;
  font-size: 16px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  background: #355B84;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border: 2px solid #355B84;&lt;br /&gt;
  border-radius: 0 4px 4px 0;&lt;br /&gt;
  transition: background 0.2s;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form button:hover {&lt;br /&gt;
  background: #2a4a6b;&lt;br /&gt;
  border-color: #2a4a6b;&lt;br /&gt;
}&lt;br /&gt;
#api-search-results {&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
#api-search-results.visible {&lt;br /&gt;
  display: block;&lt;br /&gt;
}&lt;br /&gt;
.search-status {&lt;br /&gt;
  padding: 16px;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
}&lt;br /&gt;
.search-status.error {&lt;br /&gt;
  color: #a00;&lt;br /&gt;
  background: #fef2f2;&lt;br /&gt;
  border: 1px solid #fca5a5;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
@keyframes pulse {&lt;br /&gt;
  0%, 100% { opacity: 1; }&lt;br /&gt;
  50% { opacity: 0.5; }&lt;br /&gt;
}&lt;br /&gt;
.search-loading {&lt;br /&gt;
  animation: pulse 1.5s ease-in-out infinite;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card {&lt;br /&gt;
  padding: 16px;&lt;br /&gt;
  margin-bottom: 12px;&lt;br /&gt;
  border: 1px solid #dee2e6;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
  transition: box-shadow 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card:hover {&lt;br /&gt;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 {&lt;br /&gt;
  margin: 0 0 6px 0;&lt;br /&gt;
  font-size: 17px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 a {&lt;br /&gt;
  color: #1B599B;&lt;br /&gt;
  text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
.search-result-card h4 a:hover {&lt;br /&gt;
  text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
.search-result-snippet {&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  line-height: 1.5;&lt;br /&gt;
  color: #333;&lt;br /&gt;
  margin-bottom: 8px;&lt;br /&gt;
}&lt;br /&gt;
.search-result-meta {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  gap: 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #6c757d;&lt;br /&gt;
}&lt;br /&gt;
.search-result-meta span {&lt;br /&gt;
  display: inline-flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  gap: 4px;&lt;br /&gt;
}&lt;br /&gt;
.search-score-bar {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  width: 40px;&lt;br /&gt;
  height: 6px;&lt;br /&gt;
  background: #dee2e6;&lt;br /&gt;
  border-radius: 3px;&lt;br /&gt;
  overflow: hidden;&lt;br /&gt;
  vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.search-score-fill {&lt;br /&gt;
  height: 100%;&lt;br /&gt;
  background: #355B84;&lt;br /&gt;
  border-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.search-result-count {&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  color: #6c757d;&lt;br /&gt;
  margin-bottom: 12px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;api-search-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;api-search-input&#039;);&lt;br /&gt;
  var results = document.getElementById(&#039;api-search-results&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  function escapeHtml(str) {&lt;br /&gt;
    var d = document.createElement(&#039;div&#039;);&lt;br /&gt;
    d.textContent = str;&lt;br /&gt;
    return d.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function truncate(str, len) {&lt;br /&gt;
    if (str.length &amp;lt;= len) return str;&lt;br /&gt;
    return str.substring(0, len).replace(/\s+\S*$/, &#039;&#039;) + &#039;…&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function renderResults(data) {&lt;br /&gt;
    if (!data.results || data.results.length === 0) {&lt;br /&gt;
      results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status&amp;quot;&amp;gt;Keine Ergebnisse gefunden.&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    var html = &#039;&amp;lt;div class=&amp;quot;search-result-count&amp;quot;&amp;gt;&#039; + data.results.length + &#039; Ergebnis&#039; + (data.results.length !== 1 ? &#039;se&#039; : &#039;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    data.results.forEach(function(r) {&lt;br /&gt;
      var pct = Math.round(r.similarity_score * 100);&lt;br /&gt;
      var wikiUrl = &#039;/wiki/&#039; + encodeURIComponent(r.page_title.replace(/ /g, &#039;_&#039;));&lt;br /&gt;
      html += &#039;&amp;lt;div class=&amp;quot;search-result-card&amp;quot;&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;h4&amp;gt;&amp;lt;a href=&amp;quot;&#039; + wikiUrl + &#039;&amp;quot;&amp;gt;&#039; + escapeHtml(r.page_title) + &#039;&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;div class=&amp;quot;search-result-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(truncate(r.content_text, 250)) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;div class=&amp;quot;search-result-meta&amp;quot;&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;span&amp;gt;Relevanz: &amp;lt;span class=&amp;quot;search-score-bar&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;search-score-fill&amp;quot; style=&amp;quot;width:&#039; + pct + &#039;%&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &#039; + pct + &#039;%&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;span&amp;gt;Quelle: &#039; + escapeHtml(r.source) + &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    });&lt;br /&gt;
    results.innerHTML = html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    var query = input.value.trim();&lt;br /&gt;
    if (!query) return;&lt;br /&gt;
&lt;br /&gt;
    results.className = &#039;visible&#039;;&lt;br /&gt;
    results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status search-loading&amp;quot;&amp;gt;Suche läuft…&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/search?q=&#039; + encodeURIComponent(query);&lt;br /&gt;
&lt;br /&gt;
    fetch(url)&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) throw new Error(&#039;HTTP &#039; + res.status);&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        renderResults(data);&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        results.innerHTML = &#039;&amp;lt;div class=&amp;quot;search-status error&amp;quot;&amp;gt;Fehler: &#039; + escapeHtml(err.message) + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1072</id>
		<title>Widget:SearchBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1072"/>
		<updated>2026-02-17T14:11:32Z</updated>

		<summary type="html">&lt;p&gt;Alex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;api-search-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;api-search-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;api-search-input&amp;quot; placeholder=&amp;quot;Suche…&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Suchen&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;api-search-results&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#api-search-widget {&lt;br /&gt;
  max-width: 600px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  gap: 8px;&lt;br /&gt;
  margin-bottom: 12px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 8px;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  border: 1px solid #a2a9b1;&lt;br /&gt;
  border-radius: 2px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form button {&lt;br /&gt;
  padding: 8px 16px;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
}&lt;br /&gt;
#api-search-results {&lt;br /&gt;
  white-space: pre-wrap;&lt;br /&gt;
  font-family: monospace;&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  background: #f8f9fa;&lt;br /&gt;
  padding: 12px;&lt;br /&gt;
  border: 1px solid #eaecf0;&lt;br /&gt;
  border-radius: 2px;&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;api-search-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;api-search-input&#039;);&lt;br /&gt;
  var results = document.getElementById(&#039;api-search-results&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    var query = input.value.trim();&lt;br /&gt;
    if (!query) return;&lt;br /&gt;
&lt;br /&gt;
    results.style.display = &#039;block&#039;;&lt;br /&gt;
    results.textContent = &#039;Laden…&#039;;&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/search?q=&#039; + encodeURIComponent(query);&lt;br /&gt;
&lt;br /&gt;
    fetch(url)&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) throw new Error(&#039;HTTP &#039; + res.status);&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        results.textContent = JSON.stringify(data, null, 2);&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        results.textContent = &#039;Fehler: &#039; + err.message;&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=SearchBox&amp;diff=1071</id>
		<title>SearchBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=SearchBox&amp;diff=1071"/>
		<updated>2026-02-17T14:09:10Z</updated>

		<summary type="html">&lt;p&gt;Alex: Die Seite wurde neu angelegt: „{{#widget:SearchBox}}“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#widget:SearchBox}}&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1070</id>
		<title>Widget:SearchBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:SearchBox&amp;diff=1070"/>
		<updated>2026-02-17T14:08:08Z</updated>

		<summary type="html">&lt;p&gt;Alex: Die Seite wurde neu angelegt: „&amp;lt;includeonly&amp;gt; &amp;lt;div id=&amp;quot;api-search-widget&amp;quot;&amp;gt;   &amp;lt;form id=&amp;quot;api-search-form&amp;quot;&amp;gt;     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;api-search-input&amp;quot; placeholder=&amp;quot;Suche…&amp;quot; /&amp;gt;     &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Suchen&amp;lt;/button&amp;gt;   &amp;lt;/form&amp;gt;   &amp;lt;div id=&amp;quot;api-search-results&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt;  &amp;lt;style&amp;gt; #api-search-widget {   max-width: 600px; } #api-search-form {   display: flex;   gap: 8px;   margin-bottom: 12px; } #api-search-input {   flex: 1;   padding: 8px;   font-size: 14px;   border: 1px solid #a2a9b1…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;api-search-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;api-search-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;api-search-input&amp;quot; placeholder=&amp;quot;Suche…&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Suchen&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;api-search-results&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#api-search-widget {&lt;br /&gt;
  max-width: 600px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  gap: 8px;&lt;br /&gt;
  margin-bottom: 12px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 8px;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  border: 1px solid #a2a9b1;&lt;br /&gt;
  border-radius: 2px;&lt;br /&gt;
}&lt;br /&gt;
#api-search-form button {&lt;br /&gt;
  padding: 8px 16px;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
}&lt;br /&gt;
#api-search-results {&lt;br /&gt;
  white-space: pre-wrap;&lt;br /&gt;
  font-family: monospace;&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  background: #f8f9fa;&lt;br /&gt;
  padding: 12px;&lt;br /&gt;
  border: 1px solid #eaecf0;&lt;br /&gt;
  border-radius: 2px;&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;api-search-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;api-search-input&#039;);&lt;br /&gt;
  var results = document.getElementById(&#039;api-search-results&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    var query = input.value.trim();&lt;br /&gt;
    if (!query) return;&lt;br /&gt;
&lt;br /&gt;
    results.style.display = &#039;block&#039;;&lt;br /&gt;
    results.textContent = &#039;Laden…&#039;;&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/search?query=&#039; + encodeURIComponent(query);&lt;br /&gt;
&lt;br /&gt;
    fetch(url)&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) throw new Error(&#039;HTTP &#039; + res.status);&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        results.textContent = JSON.stringify(data, null, 2);&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        results.textContent = &#039;Fehler: &#039; + err.message;&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Searchtest&amp;diff=1069</id>
		<title>Searchtest</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Searchtest&amp;diff=1069"/>
		<updated>2026-02-17T11:15:49Z</updated>

		<summary type="html">&lt;p&gt;Alex: Die Seite wurde neu angelegt: „Hello world“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hello world&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
</feed>