HTML Suchfunktion mit Weiterleitung?

So, ich habe mich mal bei W3Schools bedient und zwar hier: https://www.w3schools.com/howto/howto_js_filter_dropdown.asp

Diese Suchfunktion kommt meinem Wunsch am nächsten. Was ich NICHT brauche ist dieser Dropdown Button. Daher habe ich den Code aus W3Schools etwas modifiziert und mir eine kleine Test-Seite gebaut, deren Quellcode ich hier veröffentliche. Ich bin schon zu 90% da.

Code:
<!DOCTYPE html>
<html lang="de">
<body>
<div id="myDropdown" class="dropdown-content">
    <input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
    <a href="#apfel">Apfel</a>
    <a href="#birne">Birne</a>
    <a href="#clementine">Clementine</a>
    <a href="#dattel">Dattel</a>
    <a href="#erdbeere">Erdbeere</a>
    <a href="#feige">Feige</a>
    <a href="#grapefruit">Grapefruit</a>
    <a href="#haselnuss">Haselnuss</a>
    <a href="#ingwer">Ingwer</a>
    <a href="#johannisbeere">Johannisbeere</a>
    <a href="#kiwi">Kiwi</a>
    <a href="#limette">Limette</a>   
</div>

<p><b><a id="apfel">Apfel</a></b></p>
<p>Dieser Abschnitt befasst sich mit Äpfeln.</p>
<br>
<p><b><a id="birne">Birne</a></b></p>
<p>Dieser Abschnitt befasst sich mit Birnen.</p>
<br>
<p><b><a id="clementine">Clementine</a></b></p>
<p>Dieser Abschnitt befasst sich mit Clementinen.</p>
<br>
<p><b><a id="dattel">Dattel</a></b></p>
<p>Dieser Abschnitt befasst sich mit Datteln.</p>
<br>
<p><b><a id="erdbeere">Erdbeere</a></b></p>
<p>Dieser Abschnitt befasst sich mit Erdbeeren.</p>
<br>
<p><b><a id="feige">Feige</a></b></p>
<p>Dieser Abschnitt befasst sich mit Feigen.</p>
<br>
<p><b><a id="grapefruit">Grapefruit</a></b></p>
<p>Dieser Abschnitt befasst sich mit Äpfeln.</p>
<br>
<p><b><a id="haselnuss">Haselnuss</a></b></p>
<p>Dieser Abschnitt befasst sich mit Haselnüssen.</p>
<br>
<p><b><a id="ingwer">Ingwer</a></b></p>
<p>Dieser Abschnitt befasst sich mit Ingwer.</p>
<br>
<p><b><a id="johannisbeere">Johannisbeere</a></b></p>
<p>Dieser Abschnitt befasst sich mit Johannisbeeren.</p>
<br>
<p><b><a id="kiwi">Kiwi</a></b></p>
<p>Dieser Abschnitt befasst sich mit Kiwis.</p>
<br>
<p><b><a id="limette">Limette</a></b></p>
<p>Dieser Abschnitt befasst sich mit Limetten.</p>
<br>

</body>
</html>


<style>
</style>


<script>
function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

function filterFunction() {
  var input, filter, ul, li, a, i;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  div = document.getElementById("myDropdown");
  a = div.getElementsByTagName("a");
  for (i = 0; i < a.length; i++) {
    txtValue = a[i].textContent || a[i].innerText;
    if (txtValue.toUpperCase().indexOf(filter) > -1) {
      a[i].style.display = "";
    } else {
      a[i].style.display = "none";
    }
  }
}
</script>

Erklärung:

Ich habe eine (potentiell) elendig lange Seite mit zigtausenden Einträgen (z.B. ein Glossar) und jede Überschrift ist eine eigene id, die von der Suchfunktion mittels a href angesteuert werden kann. Die Suchvorschläge sind dabei anklickbar und leiten den Anwender direkt runter zum passenden Kapitel (Bravo, exakt so wollte ich es haben).

So lang die Seite jedoch wird, so viele Suchvorschläge sind auch anzufertigen. In der jetzigen Konstellation, wie ich sie gepostet habe, sind sie noch alle gleichzeitig sichtbar und stehen blöd nebeneinander. Beim Tippen werden dann die nicht passenden Begriffe weggefiltert bis nur noch einige zutreffende stehen bleiben. Das sind jetzt nur eine Hand voll Begriffe, aber was wenn ich da mehrere 100e oder 1000e habe.

Mein Wunsch richtet sicht nun vermutlich an die CSS. Wie bei Navigationsleisten mit Unterpunkten möchte ich, dass alle Begriffe zunächst unsichtbar sind und erst beim Tippen schon die passenden ausgeworfen werden.

Ich verweise hier nochmal an die Suchfunktion von https://www.canon.de/support/ wo man beim Tippen schon die passenden Begriffe bekommt. Kriegt man das mittels CSS noch elegant hin? Ich habe einige der Methoden aus meiner Nav versucht wie

position: absolute
z-index: -999em;

etc aber noch nicht ins Schwarze getroffen.
 
Ich hab das mal umgebaut :)

Code:
<!DOCTYPE html>
<html lang="de">
<head>
    <style>
        #myDropdown
        {
        }
        
        #myDropdown .inner
        {
            display: flex;
            flex-direction: column;
            border: 1px solid;
            position: absolute;
            z-index: 1000;
            background: white;
            opacity: 0;
            transition: opacity .2s;
            pointer-events: none;
        }
        
        #myDropdown:focus-within .inner
        {
            opacity: 1;
            pointer-events: all;
        }
        
        #myDropdown .inner a
        {
            display: none;
        }
    </style>
</head>
<body>
<div id="myDropdown" class="dropdown-content">
    <input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
    <div class="inner">
        <a href="#apfel">Apfel</a>
        <a href="#birne">Birne</a>
        <a href="#clementine">Clementine</a>
        <a href="#dattel">Dattel</a>
        <a href="#erdbeere">Erdbeere</a>
        <a href="#feige">Feige</a>
        <a href="#grapefruit">Grapefruit</a>
        <a href="#haselnuss">Haselnuss</a>
        <a href="#ingwer">Ingwer</a>
        <a href="#johannisbeere">Johannisbeere</a>
        <a href="#kiwi">Kiwi</a>
        <a href="#limette">Limette</a>
    </div>
</div>

<p><b><a id="apfel">Apfel</a></b></p>
<p>Dieser Abschnitt befasst sich mit Äpfeln.</p>
<br>
<p><b><a id="birne">Birne</a></b></p>
<p>Dieser Abschnitt befasst sich mit Birnen.</p>
<br>
<p><b><a id="clementine">Clementine</a></b></p>
<p>Dieser Abschnitt befasst sich mit Clementinen.</p>
<br>
<p><b><a id="dattel">Dattel</a></b></p>
<p>Dieser Abschnitt befasst sich mit Datteln.</p>
<br>
<p><b><a id="erdbeere">Erdbeere</a></b></p>
<p>Dieser Abschnitt befasst sich mit Erdbeeren.</p>
<br>
<p><b><a id="feige">Feige</a></b></p>
<p>Dieser Abschnitt befasst sich mit Feigen.</p>
<br>
<p><b><a id="grapefruit">Grapefruit</a></b></p>
<p>Dieser Abschnitt befasst sich mit Äpfeln.</p>
<br>
<p><b><a id="haselnuss">Haselnuss</a></b></p>
<p>Dieser Abschnitt befasst sich mit Haselnüssen.</p>
<br>
<p><b><a id="ingwer">Ingwer</a></b></p>
<p>Dieser Abschnitt befasst sich mit Ingwer.</p>
<br>
<p><b><a id="johannisbeere">Johannisbeere</a></b></p>
<p>Dieser Abschnitt befasst sich mit Johannisbeeren.</p>
<br>
<p><b><a id="kiwi">Kiwi</a></b></p>
<p>Dieser Abschnitt befasst sich mit Kiwis.</p>
<br>
<p><b><a id="limette">Limette</a></b></p>
<p>Dieser Abschnitt befasst sich mit Limetten.</p>
<br>

</body>
</html>


<style>
</style>


<script>
function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

function filterFunction() {
  var input, filter, ul, li, a, i;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  div = document.getElementById("myDropdown");
  a = div.getElementsByTagName("a");
  for (i = 0; i < a.length; i++) {
    txtValue = a[i].textContent || a[i].innerText;
    if (filter.length > 0 && txtValue.toUpperCase().indexOf(filter) > -1) {
      a[i].style.display = "inline";
    } else {
      a[i].style.display = "none";
    }
  }
}
</script>
 
  • Gefällt mir
Reaktionen: Smartass und McMoneysack91
UPDATE 12.04.2023

Liebe Freunde,

Dank @floq0r arbeite ich mit höchster Zufriedenheit mit der Suchfunktion
Code:
<html lang="de">
<head>
    <link rel="stylesheet" href="css/format.css"
</head>
<body>
 <a id="pagetop"></a>
  <div id="myDropdown" class="dropdown-content">
    <input type="text" placeholder="Suchbegriff eingeben..." id="myInput" onkeyup="filterFunction()">
    <div class="inner" id="index">
        <a href="/beispiele/grün.html">Grün</a>
        <a href="/beispiele/rot">Rot</a>
    </div>
  </div>
 <footer>
     <p>Dieser Index beinhaltet bereits <span id="link_anzahl"></span> Einträge.</p>
 </footer>
</body>
</html>

<script>
document.getElementById('link_anzahl').innerText = document.querySelectorAll('#index a').length;

function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

function filterFunction() {
  var input, filter, ul, li, a, i, found;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  div = document.getElementById("myDropdown");
  a = div.getElementsByTagName("a");
  found=0;
  for (i = 0; i < a.length; i++) {
    txtValue = a[i].textContent || a[i].innerText;
    if (filter.length > 0 && txtValue.toUpperCase().indexOf(filter) > -1) {
      a[i].style.display = "inline";
      found++;
    } else {
      a[i].style.display = "none";
    }
  }
  document.getElementById('link_anzahl').innerText = document.querySelectorAll('#index a').length;
}
</script>

Der CSS Code zu dieser "Suchmaschine" sieht so aus:

Code:
/* The search field */
#myInput {
  box-sizing: border-box;
  font-size: 18px;
  padding: 15px 20px 12px 15px;
  border: none;
}

/* The search field when it gets focus/clicked on */
#myInput:focus {
  border: 1px solid #ddd;
}

/* The container <div> - needed to position the dropdown content */
.dropdown {
  position: absolute;
  top: auto;
  display: inline-block;
}


/* Links inside the dropdown */
.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

/* Change color of dropdown links on hover */
.dropdown-content a:hover {
  background-color: #f1f1f1;
}


body {
 background-color: #80AACC;
}


#myDropdown {
 align: center;
 width: 40%;
 margin: 0 auto;
 background-color: transparent;
}

#myInput {
 width: 100%;
 border: 1px solid;
}
        
#myDropdown .inner {
 display: flex;
 flex-direction: column;
 border: 1px solid;
 z-index: 1000;
 background: white;
 opacity: 20%;
 transition: opacity 1s;
 pointer-events: none;
}
        
#myDropdown:focus-within .inner {
 opacity: 1;
 pointer-events: all;
}
        
#myDropdown .inner a {
 display: none;
}


Dank dieser Konstellation braucht der Anwender nur einen Buchstaben in das Suchfeld eingeben, und die dazu passenden Zeichenfolgen innerhalb der Links werden eingeblendet. Sobald man weiterschreibt bleiben lediglich die übrig, die jeweils zum Eingegebenen passen.

In diesem Beispiel: tippt der Anwender "r" in die Suchleiste, werden beide Links "Grün" und "Rot" ausgeworfen. Fügt er dem "r" aber ein "o" hinzu, bleibt nur noch "Rot" stehen, kann angeklickt werden und leitet den Anwender zur Seite rot weiter.

Alles gut.



Nun kommt mein neuer Wunsch. Mal schauen, ob wir ihn hier umsetzen können. Ich möchte, dass die Begriffe (und NUR diese Hauptbegriffe) auch dann angezeigt werden, wenn man völlig andere Begriffe eingibt. Hier ein Beispiel zur Verdeutlichung:

Der Treffer "Grün" soll auch dann ausgeworfen werden, wenn der Anwender die Begriffe "fröhlich, Natur, Leben, Pflanze, frisch" eingibt. Aber diese "Synonyme" wie ich sie jetzt mal nenne sollen dabei NICHT angezeigt werden. Sprich, auch wenn ich "fröh" in die Suchleiste eingebe, soll bereits "Grün" ausgeworfen werden.

Bei "Rot" dasselbe Spiel nur mit den Synonymen "Achtung" "Gefahr" "Stop" "Feuer"

Ich habe eine Vermutung wie man das bewerkstelligen könnte und bitte euch um eure Einschätzung:

Ich kann mir vorstellen dass das mit den Linkzeilen selbst und dem dazugehörigen CSS realisierbar wäre. Dabei kriegt innerhalb der <a></a> stehende Hauptbegriff die Klasse "hauptbegriff" und die Synonyme die Klasse "synonym". Etwa so hier:


<a href="/beispiele/grün.html"><p class="hauptbegrifff">Grün</p><p class="synonym">fröhlich Natur Leben frisch</p></a>

< href="/beispiele/rot.html"><p class="hauptbegriff">Rot</p><p class="synonym">Achtung Gefahr Stop Feuer</p></a>

Und im CSS würde ich dann hingehen und .synonym irgendwie auf display:none oder ähnliches stellen sodass die einfach nicht angezeigt werden.

Dank des Javascripts wird bei einer Übereinstimmung sowieso der gesamte <a></a> als Ganzes angezeigt sprich da gäbe es keine Probleme, nur dass eben nur ein Teil davon sichtbar und der Rest unsichtbar wäre.


Ist das wirklich so simpel zu bewerkstelligen, wie ich als Laie mir das schon zusammengeschustert habe hier?
 
HTML hat extra Attribute um Daten im DOM zu hinterlegen, die sogenannten Data Attribute.
Damit muss man dann nicht erst irgendwelche unsichtbaren Nodes erfinden die den Dom zumüllen.

Funktioniert dann ähnlich wie a[i].textContent, damit fragt man den Text-Inhalt ab.
Wenn man Data-Attrs abfragen will kann man das mit a[i].getAttribute('data-synonym') machen (bzw. dataset wie in den MDN Docs beschrieben).

Dann muss nur noch die Display-Logik geupdated werden sodass die Links eingeblendet werden wenn eine der beiden Variablen einen Substring hat.

HTML:
<div class="inner" id="index">
  <a data-synonym="fröhlich Natur Leben frisch" href="/beispiele/grün.html">Grün</a>
  <a data-synonym="Achtung Gefahr Stop Feuer" href="/beispiele/rot">Rot</a>
</div>

<script>
function filterFunction() {
  ....
  for (i = 0; i < a.length; i++) {
    // und hier suchen wir nicht nur durch den Link-Text sondern auch durchs data-Attribut
    const aElement = a[i]
    const txtValue = aElement.textContent || aElement.innerText;
    const synonymValue = aElement.getAttribute('data-synonym')
    if (filter.length > 0 && (txtValue.toUpperCase().indexOf(filter) > -1 || synonymValue.toUpperCase().indexOf(filter) > -1)) {
      a[i].style.display = "inline";
      found++;
    } else {
      a[i].style.display = "none";
    }
  }
  document.getElementById('link_anzahl').innerText = document.querySelectorAll('#index a').length;
}
</script>
 
  • Gefällt mir
Reaktionen: McMoneysack91
Ich werd wieder irre. Ich habe deinen Code @Joshinator eingepflegt und es funktioniert tatsächlich zu 100% genau so wie ich es mir gewünscht habe. Was für ein Volltreffer!

Herzlichen Dank!
 
Liebe Freunde,

nun geht es in den Next Level. Die durch euch hier zusammengetragenen Ergebnisse gefallen so sehr, dass eine Idee geäußert wurde, die ich hier mal präsentieren möchte und zu schauen, ob sich das überhaupt so umsetzen lässt.

Derzeit ist es ja so, dass es eine Suchfunktion gibt, welche Ergebnisse ausspuckt je nachdem was man da eingibt. Auf diese Weise sind alle möglichen Treffer (also a href) in einer Liste und potentiell alle anwählbar.

Jetzt gehts aber darum, diese Treffer hinter Kategorien zu verstecken.

Wir haben ja im obigen Beispiel mit Farben gearbeitet:

<a data-synonym="fröhlich Natur Leben frisch" href="/beispiele/grün.html">Grün</a>
<a data-synonym="Achtung Gefahr Stop Feuer" href="/beispiele/rot.html">Rot</a>

Jetzt möchte ich diesem Trefferkatalog weitere Treffer hinzufügen, jedoch aus einer ganz anderen Kategorie...z.B. Obst:

<a data-synonym="sauer saftig rund" href="/beispiele/apfel.html">Apfel</a>
<a data-synonym="süß krumm" href="/beispiele/banane.html">Banane</a>


Die GUI, welche ich gebaut habe sieht so aus:
GUI.jpg


Die grauen Kästen verdecken eigentlich nur den Namen des "Programms" und die Logos.

Wie ihr seht habe ich an der Seite ein anklickbares Ordnersymbol mit "Text" daneben hingesetzt. Das sollen die Kategorien sein, welche jeweils nur bestimmte Suchtreffer beinhalten.

Stellt euch also vor, da ist ein Ordner mit "Farben" daneben und darunter ein Ordner mit "Obst".

Ziel:

Wenn ich als Nutzer den Ordner mit "Farben" anklicke, dann soll mir die Suchmaschine NUR meine Farbtreffer anzeigen. Wenn ich da anfange "sauer" "krumm" "rund" "süß" einzutippen, dann kommen KEINE Treffer, denn die Obsttreffer liegen ja in einer anderen Rubrik.

Klicke ich jedoch in eine andere Rubrik so verhält es sich genau umgekehrt. Ich kriege nur noch Treffer dieser Rubrik angezeigt aber keine anderen.


Ich habe das Gefühl, dass die Lösung hier genauso simpel ist, wie die Synonyme einzubauen. Ich gebe jedem Treffer eine "Tag" also eine Kennzeichnung der Kategorie. Ich weiß nicht, wie das wirklich im Code auszusehen hat, aber ich stelle mir sowas vor wie:

<a category="farben" data-synonym="fröhlich Natur Leben frisch" href="/beispiele/grün.html">Grün</a>
<a category="rarben" data-synonym="Achtung Gefahr Stop Feuer" href="/beispiele/rot.html">Rot</a>
<a category="obst" data-synonym="sauer saftig rund" href="/beispiele/apfel.html">Apfel</a>
<a category="obst" data-synonym="süß krumm" href="/beispiele/banane.html">Banane</a>

Dann müsste man die Links an der Seite sowie den Javascript Code dahingehend modifizieren, dass die auf einander reagieren.

Da fallen mir die Toggles ein, die ich mal bei W3Schools gesehen habe. Da war das so, dass ein Bild von einer ausgeschalteten Glühbirne angezeigt wurde, also z.B. "aus.jpg" und sobald man den "An" Button angeklickt hat, wurde das "ein.jpg" angezeigt, wo die Birne leuchtete, also auf Klick wurde ein anderes Bild geladen. Hat man wieder "Aus" angeklickt, wurde das "aus.jpg" angezeigt. So konnte man die Birne mit Knopfdrücken ein und ausschalten.

So in etwa stelle ich mir vor, dass die Kategorien an der Seite als Switches dienen, den Javascript Code dazu zu bewegen, nur bestimmte Kategorien anzuzeigen.

Sprich: "Lieber Java-Code, wenn ich links im Menü die Kategorie "Obst" anklicke, dann zeige mir bitte nur die a href aus dem Trefferkatalog, wo category="obst" zutrifft. Und wenn ich links im Menü die Kategorie "Farben" anklicke, dann verberge wiederum alles außer die a href, wo category="farben" zutrifft."

So in etwa. Ich hoffe, man kann mir folgen.
 
Auch wenn sich das jetzt fies anhört: du solltest dich mal selbst mit dem Code auseinander setzen.

Du hast ja schon richtig erkannt das so ein Filter quasi wie ein zweites Suchfeld funktioniert.
Der einzige wirkliche Unterschied ist das nicht nach einem Teilstring gesucht wird, sondern nach einem genauem Treffer.

Keinem ist geholfen wenn wir dir auf Ewigkeiten fertigen Code posten, sollst ja was lernen ;)
In dem Sinne:

Die Ordner kannst du ja erstmal mit Radio Groups bauen, in dem Link ist auch schon ein Beispiel für den Eventlistener. Die erlauben keine Mehrfach-Auswahl, aber im erstem Schritt ist das sogar ein Vorteil.

Die Filter-Logik sieht ja aktuell so aus:
Javascript:
eingabe = ""
for () {
    link_text = ""
    link_synonym = ""

    if (link_text.includes(eingabe) || link_synonym.includes(eingabe)) {
        // checke ob die Eingabe im Text oder Synonym ist
        // --> dann anzeigen
    } else {
        // sonst ausblenden

    }
}
was du brauchst ist:
Javascript:
eingabe = ""
filter = "" // der Eventlistener von der Radiogroup setzt die Variable

for () {
    link_text = ""
    link_synonym = ""
    link_filter = ""

    if (filter == "" && (link_text.includes(eingabe) || link_synonym.includes(eingabe))) {
        // der filter ist leer
        // also checke nur ob die Eingabe im Text oder Synonym ist
        // --> dann anzeigen
    } else if (filter == link_filter && (link_text.includes(eingabe) || link_synonym.includes(eingabe))) { // wenn der
        // der filter ist gesetzt
        // also checke ob der Filter der vom aktuellem Link-Element ist
        // und checke ob die Eingabe im Text oder Synonym ist
        // --> dann anzeigen
    } else {
        // sonst ausblenden

    }
}

Die Anpassung hält sich also in Grenzen, das solltest du aber selbst hinbekommen.
 
  • Gefällt mir
Reaktionen: McMoneysack91
"Auch wenn sich das jetzt fies anhört: du solltest dich mal selbst mit dem Code auseinander setzen." das hört sich überhaupt nicht fies an sondern ist ja der Soll-Zustand. Tatsächlich ist dieser Stups in die richtige Richtung sehr hilfreich und wahrscheinlich genau das was benötigt wird. Selbstverständlich gebe ich dir Recht, dass ich keineswegs euch um fertigen Code melken möchte.

In der Tat ist es auch sehr hilfreich "rückwärts" zu lernen, indem ich den bereits von dir geposteten Code anschaue und anhand des Ergebnisses Rückschlüsse darauf ziehe, warum bestimmte Parameter gesetzt wurden wie sie gesetzt wurden.

Parallel dazu klicke ich mich fleißig durch W3Schools und versuche Lektion für Lektion zu verstehen und umzusetzen :)

PS: Ich lese mich gerade zu den Radio Groups ein und das ist absolut der Wahnsinn, das wird die Lösung sein.
 
UPDATE

Liebe Freunde,

eine kleine Mammutaufgabe steht vor mir. Und wie immer bin ich der Lösung vermutlich schon so nah, jedoch nicht nicht zum Greifen nah.


Ist-Zustand:

Ich habe eine fantastische Suchfunktion (dank euch). Diese sieht wie folgt aus:
HTML:
<div id="myDropdown" class="dropdown-content">
    <input type="text" placeholder="Suchbegriff eingeben..." id="myInput" onkeyup="filterFunction()">
    <div class="inner" id="index">
        <a href="../fruit/apfel.html" target="_blank" title="Apfel" data-synonym="grün rund saftig">Apfel</a>
        <a href="../fruit/banane.html" target="_blank" title="Banane" data-synonym="gelb krumm süß">Banane</a>
    <a href="../fruit/mandarine" target="_blank" title="Mandarine" data-synonym="rund orange weihnachtlich">Mandarine</a>
    </div>
</div>

CSS:
#myInput {
  box-sizing: border-box;
  font-size: 20px;
  padding: 15px 20px 12px 15px;
  width: 100%;
  border: 1px solid;
}

/* The search field when it gets focus/clicked on */
#myInput:focus {
  border: 1px solid #ddd;
}

/* The container <div> - needed to position the dropdown content */
.dropdown {
  top: auto;
  display: inline-block;
}


/* Links inside the dropdown */
.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
  font-size: 20px;
  font-family: sans-serif;
}

/* Change color of dropdown links on hover */
.dropdown-content a:hover {
  background-color: #e1e1e1;
}


#myDropdown {
 align: center;
 width: 80%;
 margin: 0 auto;
 background-color: transparent;
 box-shadow: 5px 5px 10px #AAAAAA;
}

        
#myDropdown .inner {
 display: flex;
 flex-direction: column;
 border: 1px solid;
 z-index: 3;
 background: white;
 opacity: 20%;
 transition: opacity 1.2s;
 pointer-events: none;
 position: absolute;
 box-shadow: 1px 1px 5px;
}
        
#myDropdown:focus-within .inner {
 opacity: 1;
 pointer-events: all;
}
        
#myDropdown .inner a {
 display: none;
 cursor: pointer;
}

Javascript:
function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

function filterFunction() {
  var input, filter, ul, li, a, i, found;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  div = document.getElementById("myDropdown");
  a = div.getElementsByTagName("a");
  found=0;
  for (i = 0; i < a.length; i++) {
    const aElement = a[i]
    const txtValue = aElement.textContent || aElement.innerText;
    const synonymValue = aElement.getAttribute('data-synonym')
    if (filter.length > 0 && (txtValue.toUpperCase().indexOf(filter) > -1 || synonymValue.toUpperCase().indexOf(filter) > -1)) {
      a[i].style.display = "inline";
      found++;
    } else {
      a[i].style.display = "none";
    }
  }
  document.getElementById('link_anzahl').innerText = document.querySelectorAll('#index a').length;
}

function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

function filterFunction() {
  var input, filter, ul, li, a, i, found;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  div = document.getElementById("myDropdown");
  a = div.getElementsByTagName("a");
  found=0;
  for (i = 0; i < a.length; i++) {
    const aElement = a[i]
    const txtValue = aElement.textContent || aElement.innerText;
    const synonymValue = aElement.getAttribute('data-synonym')
    if (filter.length > 0 && (txtValue.toUpperCase().indexOf(filter) > -1 || synonymValue.toUpperCase().indexOf(filter) > -1)) {
      a[i].style.display = "inline";
      found++;
    } else {
      a[i].style.display = "none";
    }
  }
  document.getElementById('link_anzahl').innerText = document.querySelectorAll('#index a').length;
}

function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

Dadurch ist diese kleine Suchmaschine in der Lage, dem Anwender die passenden Treffer entweder beim Eingeben des exakten Treffernamens (hier Früchte) einzublenden, oder aber mittels Synonyme.

Okay, soweit haben wir das.


Soll-Zustand:

Jetzt ist die Suchfunktion hier im Echteinsatz prall gefüllt. Mit allerlei zig hunderten Einträgen. Irgendwann wirds unübersichtlich. Und eigentlich interessierten bei weitem nicht alle Einträge alle Anwender. Die Gemüseabteilung interessiert sich nicht für Früchte oder Werkzeuge. Und visa-versa.

Also ist das Ziel links in der Navigationsleiste eine kleine Kategorisierung durchzuführen. Dort kann jeder Anwender dann seine passende Kategorie anklicken und bekommt durch die Suchfunktion nur die Suchtreffer angezeigt, die auch wirklich das Label seiner Abteilung tragen.


Eigene Überlegungen und Lösungsansätze:

Hier kommt eine Funktion ins Spiel, die ich an anderer Stelle bereits verwende:

Ich habe eine Navigationsleiste mit unterschiedlichen Kategorien und einen großen Katalog an Einträgen. Und diese Einträge sind mit "class" versehen. Ein JavaScript-Code bewirkt, dass zunächst keine Einträge angezeigt werden und wenn man auf eine Kategorie klickt, nur die Einträge angezeigt werden, die auch die "class" dieser Kategorie entsprechen. Quasi wie ein Labeling.

So sieht es derzeit aus:
gui_cb.jpg


Die GUI ist natürlich zu demonstrationszwecken massiv verändert und fast alle übrigen Elemente rauseditiert. Wichtig ist zu sehen, dass test_showAll angeklickt ist und dadurch alle Kategorien angezeigt werden, weil test_showAll den JS-Befehl onclick="showItems('all') hat und die Einträge ebenfalls alle unter anderem die class="all" besitzen.

So sieht der Code dazu aus:
HTML:
<div class="navbox">
  <ul>
    <li><button onclick="showItems('fruit')"><img class="folder" src="../img/folder_open_blue.png">Früchte</button></li>
    <li><button onclick="showItems('veg')"><img class="folder" src="../img/folder_open_blue.png">Gemüse</button></li>
    <li><button onclick="showItems('tool')"><img class="folder" src="../img/folder_open_blue.png">Werkzeug</button></li>
    <li><button onclick="showItems('color')"><img class="folder" src="../img/folder_open_blue.png">Farben</button>
    <li><button onclick="showItems('all')"><img class="folder" src="../img/folder_open_blue.png">test_showAll</button></li>
    <li><button onclick="showItems('none')"><img class="folder" src="../img/folder_open_blue.png">test_showNone</button></li>
  </ul>
</div>

<div class="content">
  <ul id="itemList">
    <li class="all fruit" style="display:none;">Apfel</li>
    <li class="all fruit" style="display:none;">Banane</li> 
    <li class="all fruit" style="display:none;">Orange</li>
    <li class="all veg" style="display:none;">Karotte</li>
    <li class="all veg" style="display:none;">Tomate</li>
    <li class="all veg" style="display:none;">Zwiebel</li>
    <li class="all tool" style="display:none;">Schraubendreher</li>
    <li class="all tool" style="display:none;">Zange</li>
    <li class="all tool" style="display:none;">Bohrer</li>
    <li class="all color" style="display:none;">Grün</li>
    <li class="all color" style="display:none;">Rot</li>
    <li class="all color" style="display:none;">Blau</li>
  </ul>
</div>

CSS:
.maincat:hover .subcat {
 display: block;
}

.subcat {
 display: none;
 margin-left: 10px;
 font-size: 14px;
}

.catheader:hover .catcontent {
 display: block;
}

.catcontent {
 display: none;
}

.changelogtable {
 width: 60%;
 height: 600px;
}

embed {
 height: 100%;
 width: 100%;
}

#itemList ul {
 list-style: none;
}

#itemList li {
 font-size: 16px;
 font-family: sans-serif;
 padding: 5px;
 margin: 10px;
}

#itemList li:hover {
 background-color: #FBFBFB;
}

#itemList .catcontent {
 padding-left: 30px;
}

#itemList img {
 margin-right: 10px;
 width: 14px;
}

Bitte nicht wundern, warum mit maincat und subcat gearbeitet wurde, ich habe diese Kategorien nochmals unterteilt und rechts die Einträge (daher auch der Doppelpfeil nach unten) haben wiederum Einträge beim Hovern geöffnet. Ist aber für mein Vorhaben hier unerheblich.

Javascript:
function showItems(buttonId) {
      var itemList = document.getElementById('itemList');
      var items = itemList.getElementsByTagName('li');

      for (var i = 0; i < items.length; i++) {
        var item = items[i];
        if (item.classList.contains(buttonId)) {
          item.style.display = 'list-item';
        } else {
          item.style.display = 'none';
        }
      }
    }

Diese Lösung erlaub es mir also gigantische Listen hinter Buttons zu verstecken und somit thematische Einteilungen, beliebig fein aufgedröselt.


Die jeweiligen JS-Codes der beiden Funktionen (Suchfunktion und diese Listenfunktion) sind jetzt nicht weiß Gott wie lang oder groß. Wenn ich mir deren Logik anschaue, müsste man die Navigationsliste nehmen, die ja aus Buttons besteht, welche mit einem onclick=showItems('...') versehen sind und diese Einträge aus der Suchfunktion müssten in eine <ul class="itemList"> versteckt werden.

Und DIESE <ul class="itemList"> müsste dann wiederum in der Suchfunktion in den <div class="inner"> gepackt werden, wo Stand jetzt die Einträge noch frei und unkategorisiert herumfliegen.

Bin ich da mit meinen Gedanken auf der richtigen Spur? Wenn ja, werde ich direkt mal nachher versuchen diese Funktionen irgendwie zu vereinen.

ODER (das fiel mir gerade mal so ein) reicht es völlig aus, den jetzigen Suchmaschineneinträgen einfach eine class zu verpassen? Bislang haben sie ja nur einen title und eine data-synonym aber noch keine Klassen. Und dann würde doch der zweite JS-Code aus der Listenfunktion seine volle Wirkung entfalten, wenn ich ihn statt auf document.getElementById('itenList') dann auf document.getElementById('index') ansetze.
 
Update:

Ich kann schonmal bestätigen, dass die Links innerhalb der class="inner" wiederum jeweils mit Klassen zu versehen nicht gefruchtet hat. Meine erste Überlegung war es, die Ordner links im Navigationsmenü mit entsprechenden onClick-Funktionen zu versehen, um die NICHT passenden classes einfach auszublenden via display:none;.
 
Zurück
Oben