Sven Rautenberg: Mit 4 Auswahlmenüs eine Datei finden und öffnen

Beitrag lesen

Moin!

für eine private Wetterstation bräuchte ich Hilfe von Experten.
Mittels 4 Auswahlmenüs soll man auf vorhandene Tagesgrafiken oder htm-Tabellen zugreifen können, zb.
                   __           __          ____            ___
Messwerte vom Tag:|01|   Monat:|01|   Jahr:|2000|   Format:|htm|
                   bis          bis         bis             gif
                   31           12          2002

_________________
|Button: auswählen|

Ein kleiner Ausflug in die Softwareergonomie gefällig? Auch wenn du nicht willst: Da mußt du jetzt durch.

Das, was du hier vorhast, ist zwar für dich als Programmierer ziemlich angenehm, aber keinesfalls für den Benutzer. Denn der kriegt bei der Tagesauswahl eine ziemlich lange Tageszahlliste, aus der er sich ein Datum raussuchen kann - per Mausklick. Dann muß er sich der Monatsliste widmen, und dort wieder mindestens zweimal klicken, dann noch das Jahr auswählen...

Es gibt in der "Interface Hall of Shame" unter http://www.iarchitect.com ein besonders krasses Beispiel (zwar nicht im Browser, sondern in einem normalen Programm, aber immerhin zeigt es, was falsch ist):

Enter Insurance Number:
  _   _   _   _      _   _   _   _   _
 |0| |0| |0| |0| -  |0| |0| |0| |0| |0|
 bis bis bis bis    bis bis bis bis bis
  9   9   9   9      9   9   9   9   9

Da hat es also tatsächlich jemand geschafft, den Mitarbeitern Tipparbeit abzunehmen und durch Klickarbeit zu ersetzen. Man sollte doch meinen, der numerische Tastaturblock ist viel besser zur Eingabe einer Nummer geeignet.

Das gleiche gilt für dein Beispiel: Es ist viel leichter für den Benutzer, einfach eine Nummer in ein Textfeld zu tippen, als umständlich aus drei Selectlisten ein Datum auszuwählen.

Was verlierst du dadurch? Der User kann auch den 36.15.99999 eingeben, ein sicherlich sehr ungültiges Datum. Du mußt also zusätzliche Abfragen gegen Fehleingaben einbauen. Allerdings: Die Select-Felder schützen dich davor auch nicht! Jedermann könnte das Formular zuhause speichern, kurz abändern (eben den 36. einfügen) und dann abschicken. Dann hast du das gleiche Problem.

Zweiter Nachteil: Einstellige Daten können entweder mit oder ohne führende Null eingegeben werden. Doch auch das ist kein großes Problem: Nimm das Datum an den Punkten (oder sonstigen Trennzeichen, die keine Zahlen sind) auseinander, betrachte jeden Teil, ob er zwei oder vier Stellen hat, und reagier entsprechend. Setze z.B. einfach eine Null davor, falls sie fehlt, oder weise den Benutzer auf seinen Fehler hin, wenn das Datum nicht 10 Zeichen lang ist (2 Tagesziffern + 2 Monatsziffern + 4 Jahresziffern + 2 Trennzeichen).

Das Javascript-Objekt "Date" ist in diesem Zusammenhang sicher dein Freund. (</selfhtml/javascript/objekte/date.htm>)

Wie man dort sieht: Variante 3 ist ganz brauchbar.
Objektname = new Date(Jahr,Monat,Tag);

Du brauchst also ein Textfeld, welches du auseinandernimmst, um die drei Variablen Jahr, Monat und Tag zu erhalten.

Stringoperationen stehen hier: </selfhtml/javascript/objekte/string.htm>

Da du aber nicht genau weißt, was der Benutzer so eingibt, sind reguläre Ausdrücke angebracht. Und in Javascript ist dafür das "RegExp"-Objekt zuständig: </selfhtml/javascript/objekte/regexp.htm>

Basteln wir mal einen regulären Ausdruck für ein Datum. Wie sieht ein Datum generell aus? In Deutschland so:
ein oder zwei Ziffern, dann ein Trennzeichen, dann ein oder zwei Ziffern, dann wieder ein Trennzeichen, und dann vier Ziffern.

Als regulärer Ausdruck:
\d{1,2}\D\d{1,2}\D\d{4}
\d steht dabei für eine Zahl, \D steht für eine Nicht-Zahl.

Wenn man die Zahlen hinterher extrahieren will, muß man sie im regulären Ausdruck einklammern:
(\d{1,2})\D(\d{1,2})\D(\d{4})

In Javascript (basierend auf dem Beispiel zu $1..$9:

var datum = "10.5.2001";
 var datumregexp = /(\d{1,2})\D(\d{1,2})\D(\d{4})/;
 datumregexp.exec(datum);
 alert('Das folgende Datum: '+datum+' wurde in diese Bestandteile zerlegt:\nTag: '+RegExp.$1+'\nMonat: '+ RegExp.$2+'\nJahr: '+RegExp.$3);

Zwei Dinge fehlen noch:
1. Woher kommt das Datum?
2. Wie kriegt man es mit dem Laden der richtigen Datei verbunden?

1. kommt später.

Punkt 2: Wie kriegt man das Datum mit der Datei verknüpft?
Ich hatte ganz oben das Date-Objekt angesprochen. Dieses Objekt hat die angenehme Eigenschaft, daß es nur korrekte Daten zurückliefert, auch wenn man völligen Unsinn eingegeben hat. Der 15. Monat wird umgerechnet in 12 + 3 Monate, 12 Monate sind ein Jahr, also wird die Monatszahl drei Monate weitergezählt, und die Jahreszahl ein Jahr. Wenn sowohl Tag als auch Monat falsch sind, wird möglicherweise nicht so weitergezählt, wie du meinst, aber mit Sicherheit kommt ein korrektes Datum raus, für das du eine Datei haben könntest.

So setzt du das Datum (anstatt der alert-Zeile oben).
 var Testdatum = new Date(RegExp.$3,RegExp.$2,RegExp.$1);
 alert (Testdatum);

Jetzt kriegt du im Alert das Datum raus, was der Computer verstanden hat. Experimentiere mit verschiedenen Daten in der Variablen. :)

Ok, das Date-Objekt gibt die Zahlen natürlich auch wieder heraus. mit getIrgendwas kriegt man z.B. Tag, Monat und Jahr. Leider auch einstellig ohne führende Null. Aber kein Thema. Erstmal die Bestandteile rausholen:

tag = Testdatum.getDate();
 monat = Testdatum.getMonth();
 jahr = Testdatum.getYear();

Dann prüfen, ob die Tag- und Monat-Angabe kleiner als 10 ist. Wenn ja, eine Null davorsetzen und in einen String wandeln, sonst direkt in einen String wandeln.
 if (tag<10) { tag='0'+tag; } else {tag = ''+tag;}
 if (monat<10) { monat='0'+monat; } else {monat = ''+monat;}

Die Jahreszahl ist bei manchen Browsern, was man erwartet, bei anderen Browsern war sie im letzten Jahrhundert zweistellig (...97,98,99...), und man hat einfach 1900 hinzuaddiert, um die vierstellige Jahreszahl zu erhalten. Das klappt heutzutage auch noch, die Jahresfunktion gibt nämlich jetzt 102 als Jahreszahl aus. :)
 if (jahr < 1900) {jahr=1900+jahr;}

Zusammensetzen zu einem String:
 url = tag+monat+jahr;
 alert (url);

Sieht fertig aus. Hier nochmal das fertige Skript bis hierher:
<script type="text/javascript">
 var datum = "3.13.2001";
 var datumregexp = /(\d{1,2})\D(\d{1,2})\D(\d{4})/;
 datumregexp.exec(datum);
 var Testdatum = new Date(RegExp.$3,RegExp.$2,RegExp.$1);
 tag = Testdatum.getDate();
 monat = Testdatum.getMonth();
 jahr = Testdatum.getYear();
 if (tag<10) { tag='0'+tag; } else {tag = ''+tag;}
 if (monat<10) { monat='0'+monat; } else {monat = ''+monat;}
 if (jahr < 1900) {jahr=1900+jahr;}
 url = tag+monat+jahr;
 alert (url);
</script>

Eine Sache war auf später verschoben, nämlich: Woher kommt das Datum?

Das Datum kommt aus einem Textfeld.
Du schreibst also statt
 var datum = "10.5.2001";
einfach
 var datum = document.FORMULARNAME.TEXTFELDNAME.value;

und in das Formular kommt ein solches Feld:
<input type="text" maxsize="10" size="10" name="TEXTFELDNAME">

TEXTFELDNAME kannst du dir frei ausdenken, ebenso den FORMULARNAMEn bei <form name="FORMULARNAME" ...>. Ich sehe an deinem Quelltext, daß du dich für den Namen "form1" entschieden hast. Auch gut.

Ich schätze, es dürfte jetzt nicht mehr schwer sein, das Skript in eine Funktion zu verpacken und onsubmit oder onclick aufzurufen.

Was fehlt noch? Du solltest Fehler nach Möglichkeit abfangen. Der reguläre Ausdruck findet nur Daten, die eine vierstellige Jahreszahl haben. Also solltest du testen, ob die RegExp.$1 bis $3 tatsächlich einen String enthalten, bevor du weitermachst. Wenn das nicht der Fall ist, hat der Benutzer irgendwas falsches eingegeben. Sonst kommt als URL nämlich "NaNNaNNaN" heraus. Das kann man natürlich auch abfragen und reagieren. :)

Die Frage, ob GIF oder HTM-Datei läßt sich ebenso leicht entscheiden:
Einfach zusätzlich noch dies hinten ans Skript dranhängen:
url = url + document.form1.format.options[document.form1.format.selectedIndex].value;

Im Formular definierst du dann:
<select name="format" size=1>
<option value=".htm">HTM</option>
<option value=".gif">GIF</option>
</select>

Ich denke, das Posting wird dich eine Weile beschäftigen. :) Genug selberbasteln kannst du ja noch.

- Sven Rautenberg