Theo Wiehe: Mit 4 Auswahlmenüs eine Datei finden und öffnen

Hallo,
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|

Wenn man denn auf den Button auswählen klickt, sollte eine vorhandene Datei aus den mit den in den Auswahlmenüs eingegebenen Werten, z.B    01022002.gif (für die Grafik vom 13.Februar.2002) geöffnet werden.
Alle vorhandenen Tagesdateien sind gleichermassen aufgebaut.

Wo, also im gleichen Frame, also unterhalb der Abfrage oder anderswo, das werd ich wohl hoffentlich hinkriegen, die Auswahlmenüs hab ich mit select auch fertig. Aber nun steh ich völlig auf dem Schlauch.

Ich hab mal damit angefangen, und wäre für jede erdenklich
lösung dankbar, da ich wirklich kein Profi bin und nicht mehr weiter weiss.
Danke schon einmal und nun mein bisheriger Quelltext der Seite
und Gruß, Theo:

<!doctype html public "-//W3C//DTD HTML 4.0 //EN">
<html>
<head>

<script language="JavaScript">
<!--
function Go(x)
{
if(x == "nichts")
{
document.forms[0].reset();
document.forms[0].elements[0].blur();
return;
}
else
{
location.href = x;
document.forms[0].reset();
document.forms[0].elements[0].blur();
}
}
//-->
</script>

<title>Datenabfrage</title>
<meta name="author" content="wieua12">
<meta name="generator" content="Ulli Meybohms HTML EDITOR">
</head>
<body text="#000000" bgcolor="#FFFFFF" link="#FF0000" alink="#FF0000" vlink="#FF0000">
<tr><td>
<form name="form1">
Hier sind alle bisher verfügbaren Tagesmesswerte abrufbar:<br><br>
Messwerte von:
    Tag: <select name="ta" size=1>
<option>01
<option>02
<option>03
<option>04
<option selected>05
<option>06
<option>07
<option>08
<option>09
<option>10
<option>11
<option>12
<option>13
<option>14
<option>15
<option>16
<option>17
<option>18
<option>19
<option>20
<option>21
<option>22
<option>23
<option>24
<option>25
<option>26
<option>27
<option>28
<option>29
<option>30
<option>31
</select>
    Monat: <select name="mo" size=1>
<option>01
<option>02
<option selected>03
<option>04
<option>05
<option>06
<option>07
<option>08
<option>09
<option>10
<option>11
<option>12
</select>
    Jahr: <select name="ja" size=1>
<option>2001
<option selected>2002
</select>
    Grafik (gif) oder Tabelle (htm): <select name="format" size=1>
<option>gif
<option>htm
</select>
    <input type=button value="anzeigen"

onClick="image"ta"."mo"."ja"."format"">

</body>
</html>

  1. 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

    1. Hallo Sven

      [fast alles gesnippt, da sehr umfangreich, aber überaus lehrreich]

      erst einmal Danke für die ausführliche Hilfe, ich war ja echt erstaunt und zugleich erfreut, dass von Dir so schnell und vor allem so kompetent beantwortet wurde.

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

      ja, da kannst Du recht haben :)

      Und nun zu Deinem Lösungsansatz. Du hast zwar recht, dass dies Gefummele durch die Auswahlmenüs nicht sehr elegant ist. Da ich meine anfängliche Frage jedoch nicht aufblähen wollte, hatte ich nur dieses Beispiel mit dem Datum gebracht, um daraus für die anderen Abfrageseiten zu lernen. Denn es gibt genausogut Wochendateien, Monatsdateien und Jahresdaten (unterteilt in Temperatur verschiedener Fühler, ebeso verschiedene Luftfeuchtigkeitswerte, Luftdruck Wind usw.
      Eine Abfrage für die Jahresdaten sähe daher beispielsweise so aus:

      Messwerte vom Jahr:|2000|   Sensor:|Temperatur|  Format:|gif|
                          2002            Feuchte              htm
                                        Windrichtung
                                     Windgeschwindigkeit
                                            usw.

      Eine Beispielseite für die Tagesdaten hab' ich mal unter
      http://www.wiehe.purespace.de/Wetterstation/wetterdaten_anfordern.htm
      hochgeladen, die Auswahl funktioniert allerdings noch nicht, da das ja mein Problem und Grund für die Anfrage war.

      Fürs Datum könnte ich ja grundsätzlich Deine Version nehmen (habs lokal auch schol mal ausprobiert), aber ich habe noch immer ein Problem mit dem  input-Button, dass mir dann die entsprechende Datei geöffnet wird.

      Die Seite für die Abfrage der Wochen, Jahresdaten usw. wollte ich eigentlich genauso aufbauen, daher bleibt mein grundsätzliches Problem (für mich) weiterhin bestehen, da ich dort mit Textfeldern zum selber ausfüllen, wie bei obigen Beispiel mit dem Jahr, nicht mehr gebrauchen kann.

      Ich hoffe, dass war jetzt nicht zuviel,
      und danke nochmal für die sehr ausführliche Antwort von Dir

      Gruss Theo

      1. Moin!

        erst einmal Danke für die ausführliche Hilfe, ich war ja echt erstaunt und zugleich erfreut, dass von Dir so schnell und vor allem so kompetent beantwortet wurde.

        Bitteschön. Hatte schon Befürchtungen, du würdest dich wortlos mit dem Code verziehen, wie es hier so viele tun, ohne Danke zu sagen. (In diesem Zusammenhang freundliche Grüße an alle, die sich im Forum oder per Mail zurückmelden - es hilft wirklich sehr, wenn im Forum bekannt gemacht wird, daß das Problem gelöst ist, auch für nachfolgende Besucher, die den Thread im Archiv finden. Dann haben sie die Bestätigung, daß die Lösung funktioniert, und müssen nicht rätseln, ob die Lösung an sich oder die Anpassung falsch sind. Naja, und Mails im Postfach, die einfach kurz Danke sagen (gerne auch mit Bezug zum Thread) motivieren ganz einfach. Ende des Einschubs.)

        Und nun zu Deinem Lösungsansatz. Du hast zwar recht, dass dies Gefummele durch die Auswahlmenüs nicht sehr elegant ist. Da ich meine anfängliche Frage jedoch nicht aufblähen wollte, hatte ich nur dieses Beispiel mit dem Datum gebracht, um daraus für die anderen Abfrageseiten zu lernen. Denn es gibt genausogut Wochendateien, Monatsdateien und Jahresdaten (unterteilt in Temperatur verschiedener Fühler, ebeso verschiedene Luftfeuchtigkeitswerte, Luftdruck Wind usw.

        Regel Nummer 1 (oder 2, jedenfalls ganz weit vorne): Immer die ganze Story erzählen. Was du da jetzt hinterherschiebst, hätte die Lösung ja schließlich beeinflussen können - und es wäre zweimal Aufwand entstanden, wo einmal gereicht hätte.

        Eine Abfrage für die Jahresdaten sähe daher beispielsweise so aus:

        Messwerte vom Jahr:|2000|   Sensor:|Temperatur|  Format:|gif|
                            2002            Feuchte              htm
                                          Windrichtung
                                       Windgeschwindigkeit
                                              usw.

        Was die Ergonomie angeht: Tagesdaten per Dropdown auszuwählen ist nervig, aber "Temperatur" in ein Eingabefeld zu tippen ist nerviger, also ist die Liste schon in Ordnung.

        Was die URL angeht: Dir wird hoffentlich nicht entgangen sein, wie ich die Dateiendung am Schluß an die URL drangebastelt habe:

        Javascript:
        url = url + document.form1.format.options[document.form1.format.selectedIndex].value;

        HTML:
        <select name="format" size=1>
        <option value=".htm">HTM</option>
        <option value=".gif">GIF</option>
        </select>

        Bemerke, daß die einzelnen Optionen das Attribut value besitzen. Der Text zwischen den <option>-Tags wird im Browser angezeigt, aber der value wird zum Basteln der URL genommen.

        Eine Jahreszahlliste sieht ganz ähnlich aus:
        <select name="jahr" size=1>
        <option value="2001">2001</option>
        <option value="2002">2002</option>
        </select>

        Zugriff per Javascript:
        url = url + document.form1.jahr.options[document.form1.jahr.selectedIndex].value;

        Vergleiche die Select-Felder, und vergleiche die Zugriffsweise bei Javascript: Es ändert sich der name des Select-Feldes, und genau dieser Name steht im Zugriff auch drin (zweimal!).

        Wenn du also drei Select-Felder hast, und als value immer den jeweilgen Dateinamensbestandteil angibst, dann baut sich in solch einem einfachen Fall die URL so zusammen:

        url = document.form1.jahr.options[document.form1.jahr.selectedIndex].value + document.form1.daten.options[document.form1.daten.selectedIndex].value +  document.form1.format.options[document.form1.format.selectedIndex].value;

        Was in Kurzform bedeutet:
        url = jahr + daten + format
        Also
        url = '2002' + 'temp' + '.htm' = '2002temp.htm' (als Beispiel)

        Fürs Datum könnte ich ja grundsätzlich Deine Version nehmen (habs lokal auch schol mal ausprobiert), aber ich habe noch immer ein Problem mit dem  input-Button, dass mir dann die entsprechende Datei geöffnet wird.

        Ok, das ist ein anderes Problem. Du willst die neue Seite haben, wenn auf den Button geklickt wird. Das geht mit <input type="button" onclick="code für javascript" ...>.

        Der "Code für Javascript" ist ein Funktionsaufruf, um die neue Seite zu laden. Logischerweise steht da auf der einen Seite der Code zum Datum auseinandernehmen drin, und auf dieser Seite eben der simplere Code zum URL-Zusammensetzen.

        Die neue Seite lädst du in beiden Fällen mit:
        location.href = url;

        Wenn die Dateien sich in einem anderen Verzeichnis befinden, mußt du das Verzeichnis noch angeben. Wenn sie zum Beispiel im Unterverzeichnis "wetter" sind, wäre der URL-Aufruf so:
        location.href = 'wetter/'+url;

        Ich hoffe, dass war jetzt nicht zuviel,
        und danke nochmal für die sehr ausführliche Antwort von Dir

        Wenns zuviel wäre, hätte ich dir den Code nicht frei Haus geliefert. Ich denke, den Rest schaffst du jetzt allein. :)

        - Sven Rautenberg