Wie kann man zwei Bedingungen in einen JQuery schreiben?

1 Antwort

Erstelle einfach nur einen Event Handler für die focusin- und click-Events deines Dokuments. Die anderen Handler für focusin/focusout kommen dafür raus.

In neuen Event Handler prüfst du, ob das Element, welches das Ereignis gerade ausgelöst hat, innerhalb des Containers für dein Suchfeld enthalten ist oder nicht und setzt je nachdem den Sichtbarkeitszustand deiner Ergebnisliste.

const searchResultsListElement = $("#Ergebnisse");

$(document).on("focusin click", evt => {
  const isSearchField = $(evt.target).parent(".Suchfeld").length;
  searchResultsListElement.css("display", isSearchField ? "block" : "none");
});

Übrigens lässt du derzeit bei jeder Eingabe neue Event Handler an dein Eingabefeld hängen. Entweder solltest du noch irgendeine Prüfung ergänzen, ob sie bereits existieren und bei leerem Feld die Listener wieder entfernen oder du hängst den Handler wie bei deinem Click-Handler global/initial an das Feld und prüfst innerhalb des Handlers, ob es eine Eingabe gibt.


Reyana 
Fragesteller
 24.05.2023, 02:07

Hallo :)
Danke für deine Antwort, leider hat es nur teilweise geholfen. Ich habe zwar nun den gewünschten Effekt, dass ich auf die Namen draufklicken kann und wenn ich woanders hinklicke, das Dropdown geschlossen wird, allerdings sind da nun zwei neue Probleme sage ich mal.

Erstmal ist es irgendwie langsamer als das andere, ich weiß nicht ob das mit meinem restlichen Code oder mit der Lösung zu tun hat. Vielleicht kanns du was dazu sagen.

Hinzu kommt, dass das schließen des Dropdown Menüs nun nicht mehr wie zuvor mit Tabulator funktioniert. Vorher konnte ich ja TAB drücken, dadurch zum nächsten Element springen und das Dropdown schließen. Und SHIFT + TAB um wieder ins Input zu kommen und zack ist das Dropdown wieder da. Nur hier funktioniert das nicht.

Dann meine nächste Frage, könntest du mir das mit den Event Handlern die dran gehängt werden und dem Listener etwas erläutern? Ich bin eigentlich kein JavaScript / JQuery Experte, ich wollte nur gerne diese Funktion mit der Live Suche in einem Input haben und habe gegoogelt, da habe ich etwas gefunden, was ich eingebaut und etwas modifiziert habe, aber es selbst schreiben könnte ich nicht.

Danke und Liebe Grüße

0
regex9  25.05.2023, 21:00
@Reyana
Erstmal ist es irgendwie langsamer (...)

Stelle zuerst einmal sicher, dass du nicht bei jeder Eingabe neue Event Handler anhängst (oben bereits erwähnt). Sie einmal (nach Laden der Seite) anzulegen, genügt.

Statt einem Listener könnte man zusätzlich noch eine Aufteilung in zwei Listener vornehmen. Der Listener für das focusin-Element wird nur an Eingabefelder gehängt.

const searchResultsListElement = $("#Ergebnisse");

function showSearchOptions(element) {
const isSearchField = element.parent(".Suchfeld").length;
  searchResultsListElement.css("display", isSearchField ? "block" : "none");
}

$(document).on("click", evt => showSearchOptions($(evt.target)));
$("input").on("focusin", evt => showSearchOptions($(evt.target)));

Abseits davon lässt du teils ziemlich teure Aktionen zu oft ausführen:

1) Du lauschst auf keyup- und input-Event. Sobald nur eines von beiden ausgelöst wird, wird auch der nachfolgende Callback ausgeführt. Wären das zwei Events, die unterschiedliche Aktionen abdecken (so wie ein Mausklick und eine Tastatureingabe), wäre das nicht so problematisch. In diesem Fall hast du aber stets eine doppelte Ausführung des Callbacks. Für eine Eingabe muss der Nutzer eine Taste drücken und wieder loslassen (keyup) und in dem Zuge wird auch das input-Event ausgelöst.

Ich würde dir empfehlen, nur das input-Event zu berücksichtigen.

2) Bei jeder Änderung des Textfeldes wird, sofern es mindestens ein Zeichen im Feld gibt, ein HTTP-Request an den Server geschickt. Das sowie das Warten auf die Antwort braucht natürlich Zeit und Ressourcen.

Zum einen würde ich hinterfragen, ob man den Filter nicht restriktiver setzen kann. Man könnte Leerzeichen bei der Prüfung ignorieren:

if (inputVal.trim().length) {

und überlegen, ob die Suche wirklich schon bei einem Zeichen beginnen soll. Ganze Wörter bilden sich in der Regel erst ab 2-3 Zeichen.

if (inputVal.trim().length > 2) {

3) Nutzer ändern ihre Eingaben rasant. Wenn sie sich zum Beispiel vertippen oder ihre Meinung mittendrin ändern. Auf diese schnellen Änderungen kann der AJAX-Request jedoch nicht so schnell reagieren. Gebe ich bspw. aa ein, wird ein Request an den Server mit dem Keyword aa geschickt. Nun ändere ich meine Eingabe zu ab und feure somit den nächsten Request. Die vorherige Anfrage ist somit obsolet geworden, läuft aber womöglich noch.

Mit einem AbortController könnte man den obsoleten Vorgang vorzeitig abbrechen.

let request = null;

$('.Suchfeld input[type="text"]').on("input", function() {
  /* ... */

  if (request) {
    try {
      request.abort();
    }
    catch (ex) {
    }
  }

  request = $.get("daten.php", { s: inputVal })
    .done(data => {
      resultDropdown.html(data);
      request = null;
    });

  /* ... */

4) Diese Zeile:

var resultDropdown = $(this).siblings(".Ergebnisse")

liest sich so, als gäbe es mehrere Suchfelder. Da du im HTML jedoch mit IDs arbeitest, kann das nicht sein. Statt das Dropdown bei jedem Event-Aufruf neu zu suchen, kann es global gespeichert werden (so, wie ich es auch bei searchResultsListElement bereits mache).

Generell könntest du bei deinen Selektoren direkt mit den IDs arbeiten, denn das vereinfacht die Suche im DOM.

const resultDropdown = $("#Ergebnisse");

$("#Suchfeld").on("input", function() {
  /* ... */
Hinzu kommt, dass das schließen des Dropdown Menüs nun nicht mehr wie zuvor mit Tabulator funktioniert.

Das kann ich nicht reproduzieren: https://jsfiddle.net/aLgstpe8/.

Dann meine nächste Frage, könntest du mir das mit den Event Handlern die dran gehängt werden und dem Listener etwas erläutern?

Grundsätzlich kann jedes sichtbare HTML-Element auf der Webseite verschiedene Events feuern, je nachdem wie man mit ihnen agiert. Das click-Event ist so ein typisches Beispiel für ein Event, welches auf so gut wie jedem Element durch einen Mausklick getriggert werden kann. Das input-Event wiederum ist ein Gegenbeispiel, denn es wird nur bei Wertänderung eines Eingabefelds (input / textarea / select) ausgelöst.

Nun hat man in JavaScript die Möglichkeit, einen Listener zu definieren, der für ein bestimmtes Element auf ein bestimmtes Event lauscht und, sollte es gefeuert werden, eine Funktion (= Callback; den Event Handler) ausführt.

Die jQuery-Syntax sieht dafür so aus:

$("selector").on("event name(s)", function(evt) {
  /* do something ... */
});

Je nach Fall kann sie noch etwas abweichen (es gibt Verkürzungen, u.ä.), doch die obige Variante passt als Grundlage immer.

Ein konkretes Beispiel:

$("button").on("click", function(evt) { console.log("Hello"); });

Hier wir jedem Button im HTML ein Event Handler angehängt, der bei Mausklick auf den Button ausgeführt wird. Dann wird eine Nachricht in die Browserkonsole geschrieben.

Man kann auf mehrere Events lauschen. Diese werden via Leerzeichen separiert aufgelistet. Der Handler wird pro getriggertem Event aufgerufen. Hier bei Doppelklick also dreimal:

$("button").on("click dblclick", function(evt) { console.log("Hello"); });

Des Weiteren kann man mehrere Event Handler an ein Event hängen.

0