jQuery - Filter
Achot
- jquery
- php
Guten Morgen,
ich habe folgenden Code der auch wunderbar funktioniert
$(document).ready(function(){
$("#filter").keyup(function(){
var filter = $(this).val(), count = 0;
$("#ausgabe div").each(function(){
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut(10);
} else {
$(this).show();
}
});
});
});
Ich würde allerdings gerne folgendes erreichen:
Die Eingabe sollte gespeichert bleiben, auch wenn der User auf Enter drück und die Seite neu geladen wird. Den Werde müsste ich irgendwie Live in eine Session speichern?
Wenn die Seite neu geladen wird, oder der User später nochmals auf die Seite kommt, sollte der Filter direkt angewendet werden. Das würde heißen, ich muss irgendwie aus keyup (dieses reagiert ja nur auf Eingabe?) etwas anderes machen?
Ich bin gerade etwas ratlos. Vielleicht habt ihr eine Idee.
Tach!
Die Eingabe sollte gespeichert bleiben, auch wenn der User auf Enter drück und die Seite neu geladen wird. Den Werde müsste ich irgendwie Live in eine Session speichern?
localStorage oder sessionStorage.
Wenn die Seite neu geladen wird, oder der User später nochmals auf die Seite kommt, sollte der Filter direkt angewendet werden. Das würde heißen, ich muss irgendwie aus keyup (dieses reagiert ja nur auf Eingabe?) etwas anderes machen?
Mach aus der dortigen Funktion eine eigenständige, die du dann da angibst und auch noch von anderer Stelle aus aufrufen kannst.
dedlfix.
Hallo,
localStorage oder sessionStorage.
Ok, ich habe es mit localStorage umgesetzt
$(document).ready(function(){
$("#filter").keyup(function(){
var filter = $(this).val(), count = 0;
localStorage.setItem("filter",$(this).val());
$("#ausgabe div").each(function(){
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut(10);
} else {
$(this).show();
localStorage.clear();
}
});
});
});
Wenn ich
document.write(localStorage.filter);
aufrufe, erhalte ich den Wert, den ich gerade eingetragen habe.
Mach aus der dortigen Funktion eine eigenständige, die du dann da angibst und auch noch von anderer Stelle aus aufrufen kannst.
Das verstehe ich leider noch nicht ganz. Ich muss .keyup durch etwas ersetzten, richtig?
Tach!
Mach aus der dortigen Funktion eine eigenständige, die du dann da angibst und auch noch von anderer Stelle aus aufrufen kannst.
Das verstehe ich leider noch nicht ganz. Ich muss .keyup durch etwas ersetzten, richtig?
Das keyup() selbst bleibt dort, denn auf das Tastaturereignis willst du ja auch weiterhin generell reagieren - nachdem die dort angesprochenen Elemete im DOM erschienen sind. Aber die function, die dort als Parameter übergeben wurde, muss nicht dort stehen, du kannst da auch eine Referenz auf eine Function übergeben.
Das
foo(function () {...});
ist äquivalent zu dem
function bar() {...}
foo(bar);
und dann kannst du bar()
auch von anderer Stelle aus aufrufen. Die Funktionsdeklaration (function bar() {...}) kann selbstverständlich auch anderswo stehen, sie muss weder direkt davor noch - bezogen auf deinen Fall - innerhalb des DOM-Ready-Handlers stehen.
dedlfix.
Hallo,
also meinst du so?
$(document).ready(function(){
mitEingabe(function () {
$("#filter").keyup(function(){
var filter = $(this).val(), count = 0;
localStorage.setItem("filter",$(this).val());
$("#ausgabe div").each(function(){
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut(10);
} else {
$(this).show();
}
});
});
});
ohneEingabe(function () {
var filter = localStorage.filter, count = 0;
$("#ausgabe div").each(function(){
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut(10);
} else {
$(this).show();
}
});
});
});
Tach!
also meinst du so?
Nein, denn damit verdoppelst du den Code und rahmst ihn noch zusätzlich unnötig ein.
Grundlagen von Javascript: Eine Funktion ist in Javascript ein First-Class-Citizen. Das heißt, sie ist unter anderem genauso als Parameter übergebbar wie andere Werte. Du kannst eine Funktion aufrufen und 42
übergeben oder 'einen String'
oder eine anonyme function() {...}
oder eine Variable, die diese Werte enthält oder darauf verweist. Du kannst genausogut eine Variable erstellen und dieser beliebige Werte zuweisen, inklusive Funktionen:
var foo = 42;
var bar = 'ein String';
var qux = function () {...}
Funktionen können aber auch herkömmlich erstellt und mit einem Namen versehen sein.
function qux() {...}
Im Prinzip ist es egal welche der beiden Arten du verwendest, um eine Funktion zu erstellen. Wenn nun eine Funktion eine andere Funktion übergeben haben möchte, die sie später aufrufen kann, ist es auch egal, ob du die Funktion direkt an der Stalle als anonyme Funktion erstellst oder sie irgendwoanders erstellst und nur einen Verweis auf die Funktion übergibst. Ein solcher Verweis ist entweder der Name der Funktion oder der Name einer Variablen, der diese Funktion zugewiesen wurde.
In deinem Fall hast du einen Funktionsaufruf keyup()
, der im Hintergrund einen Eventhandler erstellt und dafür eine Funktion übergeben haben möchte, die im Falle des Ereignisses aufgerufen werden soll. Diese zu übergebende Funktion kann nun eine sofort notierte anonyme Funktion sein, oder der Verweis auf eine anderenorts definierte Funktion. Und letzteres ist, was du dir zunutze machen solltest.
Teil 1: steht irgendwo, muss nicht unbedingt innerhalb von $(document).ready()
sein.
function doSomethingWithAusgabe() { // hier einen sprechenderen Namen wählen, der beschreibt, was die Funktion macht
$("#ausgabe div").each(function(){
...
});
}
Teil 2: für den DOM-Ready-Handler
$(document).ready(function(){
$("#filter").keyup(doSomethingWithAusgabe);
});
Das war zumindest das, was ich dir eigentlich sagen wollte. Nun sehe ich aber gerade, dass der keyup-Eventhandler doch etwas anderes machen soll, als das was einmalig zum Programmstart geschehen soll. Zu ersterem kommt noch das Schreiben in den localStorage hinzu und letzeres braucht den Wert aus dem localStorage. In dem Fall muss die Strategie geändert werden, und meine Vorgehensweise wäre:
function doSomethingWithAusgabe() {
var filter = localStorage.filter || 'defaultValue'; // defaultValue nach Bedarf anpassen
$("#ausgabe div").each(function(){
...
});
}
$(document).ready(function(){
$("#filter").keyup(function () {
localStorage.filter = $(this).val();
doSomethingWithAusgabe();
});
});
Auf diese Weise ist doSomethingWithAusgabe()
für beide Vorgänge nutzbar. Sie holt sich den Wert aus dem localStorage und macht was damit. Im Falle des keyup-Events wird vorher zusätzlich noch dieser Wert geschrieben.
Zu beachten ist noch der Fall des Erstaufrufs der Seite, wenn doSomethingWithAusgabe()
aufgerufen wird, aber vorher noch kein localStorage beschrieben wurde. Dafür solltest du einen sinnvollen 'defaultValue' setzen, oder du fängst diesen Fall auf andere Weise ab.
dedlfix.
Alles soweit korrekt, aber:
function doSomethingWithAusgabe(): steht irgendwo, muss nicht unbedingt innerhalb von
$(document).ready()
sein.
Muss nicht, wäre in .ready() aber überaus angebracht. Oder anders: Es ist sinnlos, doSomethingWithAusgabe() "irgendwo" hinzuschreiben, wo es gar nicht benötigt wird, und benötigt wird es in diesem Falle nur in .ready(), denn dort wird der Filter beim Laden der Seite einmalig durchlaufen und dort wird keyup() eingerichtet.
doSomethingWithAusgabe() außerhalb von .ready() abzulegen müllt nur den Namensraum voll. Das stört hier (und meistens) sicher nicht, ist aber, rein der Schönheit und Eleganz nach, trotzdem bäh und doof und blöd, wie ich finde. So ist es hübscher:
$(document).ready(function(){
function doSomethingWithAusgabe() {
var filter = localStorage.filter || 'defaultValue'; // defaultValue nach Bedarf anpassen
$("#ausgabe div").each(function(){
...
});
}
$("#filter").keyup(function () {
localStorage.filter = $(this).val();
doSomethingWithAusgabe();
});
});
Auch ganz allgemein scheinen es mir nur seltene Ausnahmen zu sein, in denen überhaupt irgendwas außerhalb von .ready() und seiner Geschwister gesetzt werden muss.
Tach!
doSomethingWithAusgabe() außerhalb von .ready() abzulegen müllt nur den Namensraum voll. Das stört hier (und meistens) sicher nicht,
Genau das ist der Punkt: Es stört nicht. Es ist bedeutend wichtiger, wenn man Bibliotheken schreibt, die sich mit anderer Software vertragen muss.
ist aber, rein der Schönheit und Eleganz nach, trotzdem bäh und doof und blöd, wie ich finde.
Wenn man sich aber in einem eigenen Projekt austoben kann, und niemand anderes damit arbeiten muss, muss man auf die Gefühle anderer keine Rücksicht nehmen.
So ist es hübscher:
Kann man so sehen, kann man aber auch anders sehen. Warum soll mit dem Erstellen der Funktion gewartet werden, bis das DOM ready ist? Warum kann der Code nicht bereits früher ausgeführt werden? Anstatt sich den globalen Raum zuzumüllen müllt man sich nun den DOM-Ready-Handler zu. Wo ist da der Unterschied? Meiner Meinung nach sollte man über Module nachdenken, wenn man es besser machen möchte. Das vereint beides. Kein Vollmüllen des globalen Namensraumes und kein Vollmüllen eines anderen Raumes mit Code, der dort nicht zwingend benötigt wird. Aber auch diese Ordnung kommt nicht kostenlos daher. Es ist wie in einer Wohnung. Möchte man alles schön sauber getrennt aufbewahren, braucht man viele Schränke, Schubladen und Kisten.
Wenn allerdings das Projekt klein genug bleibt, dann lohnen sich diese Betrachtungen kaum. Man kann sie aber trotzdem anstellen und den einen oder anderen Weg umzusetzen versuchen, um damit im kleinen Rahmen bereits Erfahrungen zu sammeln.
dedlfix.
Warum soll mit dem Erstellen der Funktion gewartet werden, bis das DOM ready ist? Warum kann der Code nicht bereits früher ausgeführt werden?
Wenn du die Frage nach dem Erstellungszeitpunkt einbringst, solltest du erstmal selber beantworten, warum das denn unbedingt früher gemacht werden müsste. Den früheren Erstellungszeitpunkt als Grund anführen zu wollen, die Funktion besser global zu halten, ist meines Erachtens jedenfalls völlig neben der Spur, das hat rein gar nichts mit dem zu tun, worauf ich hinweisen wollte. Da könntest du auch einwenden, dass die zusätzlichen Leerzeichen für die Codeeinrückung Zeit verschwenden.
Anstatt sich den globalen Raum zuzumüllen müllt man sich nun den DOM-Ready-Handler zu. Wo ist da der Unterschied?
Zumüllen ist nicht identisch mit Ablegen, zumüllen bedeutet, Dinge an Orten abzulegen, wo sie unnötig sind. Und hier müllt man mitnichten .ready() zu, denn in .ready() wird die Funktion benötigt, zweimal. Globale Sichtbarkeit ist für sie hingegen überflüssig.
Die Sichtbarkeit in kleineren Bereichen zu halten, anstatt alles global anzulegen, macht sich in aller Regel bezahlt, wenn ein Projekt mit der Zeit wächst. Gleiches gilt für eine Reihe anderer Dinge, die man so gemeinhin unter gutem Stil und vorausschauendem Programmieren zusammenfasst.
Wenn allerdings das Projekt klein genug bleibt, dann lohnen sich diese Betrachtungen kaum.
Und du weisst genau, dass dieses und alle anderen Projekte klein genug bleiben. Nein? Dann wäre es sinnvoll, entsprechend zu antworten.
Tach!
Warum soll mit dem Erstellen der Funktion gewartet werden, bis das DOM ready ist? Warum kann der Code nicht bereits früher ausgeführt werden?
Wenn du die Frage nach dem Erstellungszeitpunkt einbringst, solltest du erstmal selber beantworten, warum das denn unbedingt früher gemacht werden müsste.
"Muss" war nicht meine Wortwahl und "muss" war auch nicht gemeint. Da das Anlegen der Funktion ohne das DOM auskommt, kann sie auch außerhalb stehen. Der beabsichtige Lerneffekt war nicht, Best Practice für Großprojekte zu vermitteln, sondern das anscheinend ausbaufähige Wissen um die Möglichkeiten der Platzierung zu erweitern.
Aber um auf die Entscheidungsfindung zurückzukommen, ob es im DOM-Ready oder nicht untergebracht werden sollte: Der Browser kann bereits Javascript-Code ausführen, während er noch auf den Rest des für die DOM-Fertigstellung notwendigen Codes wartet. Zu viel nicht unbedingt benötigtes erst im DOM-Ready auszuführen, kann ich mir auch als ungünstig für eine fluffig ablaufende Anwendung vorstellen. Für diese eine Funktion hat das keine Auswirkungen, aber du wolltest ja auch für größere Anwendungen vorsorgen. Deshalb sei die Überlegung gestattet, ob da nicht auch Teile aus dem DOM-Ready ausgelagert werden können.
Den früheren Erstellungszeitpunkt als Grund anführen zu wollen, die Funktion besser global zu halten, ist meines Erachtens jedenfalls völlig neben der Spur, das hat rein gar nichts mit dem zu tun, worauf ich hinweisen wollte.
Nunja, ich hab eine globale Ablage auch nicht als "besser" bezeichnet. Die bessere Möglichkeit führte ich danach an. Meine ursprüngliche Aussage war auch "muss nicht unbedingt innerhalb von $(document).ready() sein.", was nicht zwangsläufig bedeutet, dass das dann nur noch global zu liegen kommen kann.
Da könntest du auch einwenden, dass die zusätzlichen Leerzeichen für die Codeeinrückung Zeit verschwenden.
Na, jetzt begibst du dich aber in große Gefahr, die Spur zu verlassen. Wir sollten schon realistisch bleiben.
Wenn allerdings das Projekt klein genug bleibt, dann lohnen sich diese Betrachtungen kaum.
Und du weisst genau, dass dieses und alle anderen Projekte klein genug bleiben. Nein? Dann wäre es sinnvoll, entsprechend zu antworten.
Natürlich weiß ich das nicht. Aber ich weiß auch nicht, was für den Fall "entsprechend" ist. "Entsprechend" kann jedenfalls nicht sein, alles auf das größtmögliche Projekt auszulegen.
Ich bin auch nicht in der Position, das für dieses Projekt absolut richtige antworten zu können oder gar zu müssen. Natürlich werde ich nichts absichtlich falsches antworten und meine Antworten anpassen, wenn mir neue Anforderungen offenbart werden oder ich das Problem besser verstehe. Gleichwohl liegt es in meiner Absicht, dass der Probleminhaber nicht nur eine kopierfertige Lösung bekommt, sondern vor allem die Möglichkeiten kennenlernt und selbst den Weg zu seinem Ziel geht. Dazu zählt auch, dass Verständnis, dass Dinge auch anderswo liegen können als im DOM-Ready. Letztlich jedenfalls muss es die Entscheidung des Anwendungserstellers bleiben, was wo liegt und wie schön das dann aussieht. Wenn er sich in Punkto Code-Qualität verbessern möchte, sollte er das auch zum Ausdruck bringen, sonst stecke ich in den Aspekt auch nicht übermäßig Herzblut rein. Ist ja nicht mein Projekt. Am Ende interessiert es ihn vielleicht gar nicht, dass es schön aussieht. (Wahrscheinlich muss ich auch hier wieder den Disclaimer anbringen, dass ich auch nicht absichtlich schlechte Vorschläge unterbreite.)
dedlfix.
Hallo,
erst einmal vielen vielen vielen Dank für deine sehr ausführliche Erklärung und Hilfe. Ich habe meine Funktion nach deinen Vorgaben angepasst:
$(document).ready(function(){
function doSomethingWithAusgabe() {
var filter = localStorage.filter || 'defaultValue'; // defaultValue nach Bedarf anpassen
$("#ausgabe div").each(function(){
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut(10);
} else {
$(this).show();
}
});
$("#filter").keyup(function(){
localStorage.filter = $(this).val();
doSomethingWithAusgabe();
});
});
Wenn ich mir localStorage ausgeben lasse
document.write(localStorage.filter);
Erhalte ich auch den Wert, den ich in das Feld eingegeben habe. Allerdings, wenn ich die Seite neu lade werden mir sofort wieder alle Einträge angezeigt, irgendetwas stimmt da noch nicht. Siehst du zufällig den Fehler?
Meine Idee war, dass die Funktion direkt mit dem Seitenaufruf gestartet wird
<body onLoad="doSomethingWithAusgabe()">
Bringt auch keine Wirkung.
EDIT: Ok, ich muss die erste Funktion doch außerhalb von
$(document).ready(function()
platzieren, dann klappt der Aufruf. Jetzt noch eine Frage, wie kann ich die Suche wieder löschen und wie kann ich mein Input-Feld mit dem Wert belegen?
Tach!
Meine Idee war, dass die Funktion direkt mit dem Seitenaufruf gestartet wird
<body onLoad="doSomethingWithAusgabe()">
Kann man machen, ist aber nicht unbedingt guter Stil, die on...-Attribute mit Code zu befüllen. Mit dem DOM-Ready-Handler von jQuery hast du in diesem Fall bereits eine Stelle, die du verwenden kannst, um den Funktionsaufruf unterzubringen. Schau dazu erstmal meine andere Antwort an und wenn da noch Fragen offenbleiben, nur zu.
EDIT: Ok, ich muss die erste Funktion doch außerhalb von
$(document).ready(function()
platzieren, dann klappt der Aufruf.
Das ist eine Frage des Scopes. Das onload vom body führt den Code im globalen Scope aus. Wenn die Funktion allerdings im Scope von jQuerys DOM-Ready-Handler steht, ist sie ja nicht global und body-onload kann sie nicht finden.
Jetzt noch eine Frage, wie kann ich die Suche wieder löschen und wie kann ich mein Input-Feld mit dem Wert belegen?
Versuch das mal bitte etwas detaillierter zu formulieren. Was muss denn getan werden für das "Löschen der Suche"? Ist es, dass der Value vom Element mit der ID #filter auf Leerstring gesetzt werden muss? Ist es, dass der gemerkte Wert im localStorage entfernt oder auf Leerstring gesetzt werden muss? Ergibt sich bereits aus dieser detaillierteren Fragestellung, was genau für Code benötigt wird?
dedlfix.
Hallo,
Jetzt noch eine Frage, wie kann ich die Suche wieder löschen und wie kann ich mein Input-Feld mit dem Wert belegen?
Versuch das mal bitte etwas detaillierter zu formulieren. Was muss denn getan werden für das "Löschen der Suche"? Ist es, dass der Value vom Element mit der ID #filter auf Leerstring gesetzt werden muss? Ist es, dass der gemerkte Wert im localStorage entfernt oder auf Leerstring gesetzt werden muss? Ergibt sich bereits aus dieser detaillierteren Fragestellung, was genau für Code benötigt wird?
dank deiner Hilfe und sehr ausführlichen Erklärung verstehe ich so langsam das Prinzip und verstehe auch was ich da schreibe bzw. wie der Ablauf ist. Vielen Dank dafür.
Wenn ich nach Sommer suche, wird mir die Liste verfeinert, genauso wie ich es mir vorgestellt habe. Den Wert, der in localStorage.filter sollte, wenn die Seite neu geladen wird im Inputfeld mit der ID filter stehen. Dieses erledige ich mit dieser Zeile:
$('#filter').val(localStorage.filter);
bevor die erste Funktion aufgerufen wird. Klappt auch, der Wert steht drin.
Jetzt möchte ich diesen wieder löschen, also localStorage leeren. Wenn ich versuch das Inputfeld zu löschen, also einfach den Text mit der Entferntaste zu löschen wird dieser zwar gelöscht, aber ich sehe unten überhaupt keine Einträge mehr. Eigentlich sollten jetzt wieder alle dastehen und beim neuen Aufruf der Seite localStorage leer sein, dass alle Einträge zu sehen sind.
Tach!
Wenn ich nach Sommer suche, wird mir die Liste verfeinert, genauso wie ich es mir vorgestellt habe.
Versuch bitte auch mal auf mich mehr Rücksicht zu nehmen, ich bin nämlich schon etwas älter und meine Fähigkeiten zum Hellsehen lassen langsam nach. Spaß beiseite. Was ich eigentlich sagen möchte, wenn du etwas zu beschreiben versuchst, solltest du das so tun, dass ich oder wer auch immer das liest, das aus den bisher genannten Fakten nachvollziehen kann. Von einer Liste beispielsweise weiß ich nichts. In deinem Code stehen nur zwei IDs und ein div. Nix Liste. Ich rate da mal, dass #ausgabe die Liste sein soll.
Den Wert, der in localStorage.filter sollte, wenn die Seite neu geladen wird im Inputfeld mit der ID filter stehen. [...] Klappt auch, der Wert steht drin.
Wenn dann noch Wörter und/oder Kommas fehlen, macht es das Verstehen nicht unbedingt einfacher. Aber egal, wenns klappt, ist ja gut. Ich glaube auch, die fehlenden Teile richtig interpoliert zu haben. Haken dran.
Jetzt möchte ich diesen wieder löschen, also localStorage leeren. Wenn ich versuch das Inputfeld zu löschen, also einfach den Text mit der Entferntaste zu löschen wird dieser zwar gelöscht, aber ich sehe unten überhaupt keine Einträge mehr.
Dann stimmt da wohl etwas mit dem Wert nicht, den du da in dem Fall dem RegExp übergibst, wäre meine Vermutung. Die muss aber nicht unbedingt richtig sein. Es kann auch an was anderem liegen. Das wäre nun ein Fall fürs Debugging. Die Browser haben heutzutage ja Entwicklertools eingebaut, und da gibt es auch einen Teil, um Javascript schrittweise auszuführen, und dabei in die Variablen reinzuschauen. Je nach Browser sehen die Entwicklertools anders aus und unterscheiden sich auch in den Bediendetails, aber grundlegend funktionieren Debugger üblicherweise recht gleich. In deinem Fall würde ich einen Breakpoint auf die erste Zeile innerhalb der keyup-Handler-Funktion setzen, mich von dort aus schrittweise vorarbeiten, und dabei zu schauen, ob das alles so abläuft, wie es vorgesehen ist. Für die Anzeige der Werte in den Variablen genügt meist Mausdraufhalten. Für das Vorwärtsbewegen im Code gibt es Buttons. Wenn du Code untersuchen möchtest, der beim Laden der Seite ausgeführt wird, setz den Breakpoint und mach einen Reload (z.B. F5).
Jedenfalls, wenn sich mit einfachem Durchlaufen der Fehler noch nicht offenbart, versuch mal zu vergleichen, was im Gut-Fall passiert und welche Werte dabei in den Variablen stehen mit dem, was im Fehlerfall der Fall ist.
dedlfix.
Hallo,
mit Liste meine ich die Auflistung die ich durch den Filter filtern möchte. Ich versuche es ja so gut wie möglich zu beschreiben, nur mir fällt dieses alles ein wenig schwer. Da ich oft mal nicht weiß wie es genau funktionieren soll.
Naja wenn ich meine erste Version nehme und etwas in das Feld #filter schreibe, dann wird die Ausgabe verfeinert. Wenn ich den Wert im #filter Feld wieder lösche, dann kommen die Einträge auch wieder zurück.
Wenn ich jetzt den Code von dir einsetzte, z.B. Sonne schreibe dann wird die Ausgabe verfeinert, nehme ich das Wort wieder raus, habe ich unten eine leere Liste und nicht wie früher alle Einträge.
EDIT: Es liegt an dieser Zeile
var filter = localStorage.filter || 'defaultValue';
Wenn ich am Ende || 'defaultValue' entferne, dann klappt es auch wieder. Kannst du mir sagen, was das defaultValue macht und benötige ich diesen?
Edit 2: Dieser Rahmen kommt nicht von mir, es werden die senkrechten Striche nicht angezeigt.
Tach!
Ich versuche es ja so gut wie möglich zu beschreiben, nur mir fällt dieses alles ein wenig schwer. Da ich oft mal nicht weiß wie es genau funktionieren soll.
Ja, das kenne ich. Das erfordert Übung.
var filter = localStorage.filter || 'defaultValue';
Wenn ich am Ende || 'defaultValue' entferne, dann klappt es auch wieder. Kannst du mir sagen, was das defaultValue macht und benötige ich diesen?
Ja, hab ich schon, da.
Dieser Rahmen kommt nicht von mir, es werden die senkrechten Striche nicht angezeigt.
Die müssen hier im Forum wegen der Markdown-Syntax maskiert werden. Schreib sie als \|
. Auch in einem mit Backticks als Code
ausgezeichneten Teil werden sie ohne Maskierung "richtig" erkannt.
dedlfix.
Tach!
Ich habe meine Funktion nach deinen Vorgaben angepasst:
Bitte als Vorschläge, nicht als Vorgaben ansehen.
function doSomethingWithAusgabe() {
"Es gibt nur zwei schwierige Dinge beim Programmieren: Cache-Invalidation, Naming Things und Off-By-One-Fehler." - Ein Spruch, den ich hier nur zitiere.
Hier hätten wir den Vertreter Naming Things. Als ich die Funktion so benannt habe, war es nicht meine Absicht, dass du die mit diesem Namen übernehmen sollst. Deswegen stand da ja auch noch ein Kommentar dahinter. Vielmehr hätte ich es gern gesehen, wenn du dir selbst Gedanken machst, was die Funktion eigentlich macht und wie man das möglichst prägnant in Worte fassen kann, damit sich daraus ein für den Code-Leser verständlicher Name ergibt, aus dem er bereits entnehmen kann, was der Zweck dieser Funktion ist. Das ist mitunter eines der schwersten Unterfangen beim Programmieren, weswegen es ja den obigen Spruch gibt.
var filter = localStorage.filter || 'defaultValue'; // defaultValue nach Bedarf anpassen
Auch da gibts noch Veränderungsbedarf. defaultValue
ist wohl eher nicht der Wert, der von deiner Anwendung benötigt wird. Da musst du schon das nehmen, was sinnvoll ist. Der String defaultValue war nur als Beispiel gedacht, dass da eigentlich was hinkommen sollte. Das Problem hier ist, dass du den Inhalt von localStorage.filter auch dann liest, wenn noch keiner vorhanden ist (erster Besuch mit einem Browser, der noch nie auf der Seite war). Den Fall musst du berücksichtigen und entweder so wie gezeigt einen Default-Wert angeben, der in dem Fall einspringt, oder du sorgst über ein if-else-Konstrukt, dass der Filter so angewendet wird, wie es dir angemessen erscheint. (Das "muss" ist keine Forderung von mir, sondern eine Notwendigkeit, die sich ergibt, wenn du ein robustes Programm schreiben möchtest.) Welcher Wert der Default-Wert sein soll, musst du dir überlegen. Ich kann dir nicht sagen, ob ein Leerstring oder irgendwas anderes sinnvoll ist.
Aber kommen wir zur eigentlichen Frage. Ich sehe, dass du wohl noch nicht so richtig verstanden hast, wie der Ablauf am Ende vonstatten gehen soll. Macht nichts, ich formuliere das mal als vollständiges Beispiel (gekürzt auf das Wesentliche und ohne die oben genannten Punkte zu berücksichtigen).
$(document).ready(function(){
// erstens
function doSomethingWithAusgabe() {
var filter = localStorage.filter || 'defaultValue'; // defaultValue nach Bedarf anpassen
$("#ausgabe div").each(function(){ ... });
}
// zweitens
$("#filter").keyup(function() {
localStorage.filter = $(this).val();
doSomethingWithAusgabe();
});
// drittens
doSomethingWithAusgabe();
});
Als erstes brauchst du die Funktion doSomethingWithAusgabe, in der das drinsteht, was zum einen einmalig zum Seitenstart zu tun ist und was bei jedem Keyup ausgeführt werden muss. Nur das kommt da rein.
Der nächste Punkt ist, dass du einen Keyup-Handler brauchst, der die Funktion nach dem Schreiben in den localStorage aufruft.
Und als Drittes soll die Funktion auch noch einmalig zum Seitenstart ausgeführt werden, um die gemerkten Werte einzutragen.
Die Kommentare (erstens, zweitens, drittens) dienen jetzt nur um die Erklärungen zuzuordnen. In deinem eigentlichen Code kannst und solltest du sie entfernen, oder durch einen sinnvollen Hinweis für den Code-Leser ersetzen.
In meiner Diskussion mit Wumpelbär geht es übrigens um den Teil "erstens". Den kannst du dort stehen lassen, wo er jetzt steht. Theoretisch kann er aber auch außerhalb von $(document).ready(function(){...}
stehen, also davor oder danach, und es würde genauso funktionieren. Der Punkt ist, dass man es möglichst vermeiden sollte, Dinge im globalen Raum abzulegen. Für kleine Anwendungen spielt das keine Rolle, aber stell dir mal vor, jQuery würde all seinen Kram im globalen Raum ablegen. Du müsstest dann berücksichtigen, welche Bezeicher jQuery bereits verwendet hat, oder sie würden mit deinen in Konflikt kommen, wenn du diese Namen ebenfalls verwendest. Für kleine Anwendungen spielt es keine große Rolle, inwieweit du den globalen Namensraum mit deinen Bezeichnern belegst, solange du die Übersicht behältst. Das Problem offenbart sich meist erst bei größeren Anwendungen, wenn es sich ergibt, dass der Programmierer für zwei Dinge denselben Namen zu vergeben versucht. Deshalb versucht man, die Dinge zu ordnen und in eigenen Scopes und damit eigenen Namensräumen unterzubringen. Mitunter artet das dann auch so aus, dass man den globalen Raum meidet, als wäre es der Teufel. Aber das will ich jetzt nicht weiter ausführen, die "richtige" Ordnung im Code ist ein anderes abendfüllendes Thema.
dedlfix.