martinmiethke: JS: Alternative für eval() zum Auslesen einer Variablen

Hallo miteinander,

zunächst vorab: meine Website habe ich vor vielen Jahren aufgebaut und dann lange Zeit nur noch Texte und Bilder ergänzt; der Code ist also ziemlich veraltet.

Worum es geht: Klick auf ein Icon in einer Tabelle mit Vogelarten soll ein kleines Fenster öffnen, in dem ein MP3 abgespielt und ein erklärender Text dazu angezeigt wird. Dem Icon ist ein Link zugewiesen, der je nach Tabellenzeile z.B. so aussehen kann:

<a href="javascript:ops('v/cygcyg')"><img ></a>

"v" ist der Ordner, in dem die MP3-Dateien mit Vogelstimmen liegen (es gibt auch noch Ordner für Amphibien und Heuschrecken); "cygcyg" ist das Kürzel für den Singschwan.

Mit der Funktion ops() wird eine HTML-Datei aufgerufen:

function ops(daten) {
url = "spsnd.htm?art=" + daten;
popsnd = window.open(url, "snd", "status=no,width=300,height=160,left=60,top=60");
popsnd.focus();
}

Ein JS innerhalb des Dokuments soll dann den Inhalt der Seite „zusammenbauen“:

<head>
<meta charset="utf-8" />
<title>Tonaufnahme</title>
<script type="text/javascript" language="JavaScript" src="scripts/busnd.js"></script>
</head>
<script language="JavaScript">
<!--
str = window.location.search;	// String ab dem Fragezeichen (Beispiel: ?art=v/cygcyg)
tmp = str.split("=");			// teilt str am Gleichheitszeichen
path = tmp[1];					// String nach dem Gleichheitszeichen
art = path.substr(2);			// String nach dem 2. Zeichen (Beispiel: cygcyg)
mp3 = "sound/arten/" + path + ".mp3";
text = eval(art);
document.writeln('<p>' + text + '</p>'); // Beschreibungstext
document.write('<audio autoplay controls src="' + mp3 + '" type="audio/mp3"></audio>');
// -->
</script>

In busnd.js sind die Erklärtexte jeweils einer Variablen zugeordnet, die genauso benannt ist wie das zugehörige MP3, also z.B.:

cygcyg = "Singschwan, Flugrufe";

Das hat auch mal funktioniert – aber eine Überprüfung nach einer längeren Pause ergab, dass jetzt nur noch ein leeres Fenster geöffnet wird. Durch Testen konnte ich herausfinden, dass das an der eval-Funktion liegt (die ja, wie ich inzwischen weiß, nicht mehr verwendet werden soll). Nun suche ich nach einer Alternative und habe auch schon im Netz danach gesucht, konnte aber nichts passendes finden.

Weiß jemand Rat?

Herzliche Grüße Martin

  1. Ein Map-Objekt definieren, das die Zuordnungen enthält:

    const verzeichnis = new Map();
    const.set("cygcyg", "Singschwan, Flugrufe");
    // usw.
    

    Im Skript auf der HTML-Seite dann per get-Methode den Wert für den in der Variable "text" hinterlegten Schlüsselwert zurückgeben lassen:

    document.writeln('<p>' + text + '</p>'); // Beschreibungstext
    document.writeln('<p>' + verzeichnis.get(text) + </p>); 
    

    Wobei document.writeln eigentlich auch zu vermeiden ist.

    1. const verzeichnis = new Map();
      const.set("cygcyg", "Singschwan, Flugrufe");
      // usw.
      

      Das muss natürlich in der zweiten Zeile verzeichnis.set() heißen.

    2. Ein Map-Objekt definieren, das die Zuordnungen enthält:

      Aah … super, Danke! Muss ich gleich ausprobieren …

      Map-Objekt, kannte ich noch gar nicht. Wird wirklich höchste Zeit, dass ich mir mal ein vernünftiges Buch über JS zulege. Die Bücher vom Rheinwerk-Verlag fand ich bisher sehr gut – würdet ihr „JavaScript“ von Philip Ackermann empfehlen?

      Wobei document.writeln eigentlich auch zu vermeiden ist.

      Hmm … würde es zu weit führen, da auch wieder nach einer Alternative zu fragen? 😬

      1. Lieber martinmiethke,

        Map-Objekt, kannte ich noch gar nicht.

        gleich in unserem Wiki nachlesen!

        Wird wirklich höchste Zeit, dass ich mir mal ein vernünftiges Buch über JS zulege.

        Keine schlechte Idee. Aber vielleicht nützt Dir für's erste auch unser Wiki?

        Die Bücher vom Rheinwerk-Verlag fand ich bisher sehr gut – würdet ihr „JavaScript“ von Philip Ackermann empfehlen?

        Wenn es um Web-Sachen geht bin ich nicht der Typ, der das als Buch im Regal stehen haben will. Mir ist die Suchfunktion in unserem Wiki viel nützlicher. Und dann kommt da noch eine Web-Suchmaschine dazu, die auch konkrete Fragestellungen mit Treffern auf anderen Seiten beantworten kann. Das kann kein Buch.

        Wobei document.writeln eigentlich auch zu vermeiden ist.

        Hmm … würde es zu weit führen, da auch wieder nach einer Alternative zu fragen? 😬

        Nö. Wir hätten da so einen Artikel zu Ergebnisausgabe. Vielleicht hilft der schon?

        Liebe Grüße

        Felix Riesterer

        1. Hallo Felix,

          gleich in unserem Wiki nachlesen!

          Schon passiert :-)

          Wird wirklich höchste Zeit, dass ich mir mal ein vernünftiges Buch über JS zulege.

          Keine schlechte Idee. Aber vielleicht nützt Dir für's erste auch unser Wiki?

          Zum mal eben Nachschlagen finde ich das prima und werde es auch weiterhin nutzen. Aber das hilft mir nur für schon bekannte Techniken (bin einfach noch zu wenig „drin“ in JS) – und außerdem lese ich einfach gerne Bücher :‑)

          Wobei document.writeln eigentlich auch zu vermeiden ist.

          Hmm … würde es zu weit führen, da auch wieder nach einer Alternative zu fragen? 😬

          Nö. Wir hätten da so einen Artikel zu Ergebnisausgabe. Vielleicht hilft der schon?

          Ich schau gleich nach :-)

          Herzliche Grüße – Martin

    3. Ein Map-Objekt definieren, das die Zuordnungen enthält:

      Super – das klappt bestens!

      (Wobei die Abfrage verzeichnis.get(art) heißen muss, nicht verzeichnis.get(text)) – der Map-Schlüssel steht ja in der Variablen art :‑)

      Nochmal vielen Dank für die Rückmeldungen!

      Herzliche Grüße Martin

      1. Super – das klappt bestens!

        Ja Pustekuchen! Auf meinem Rechner funktioniert die Sache, aber vom Server nicht :-(

        Woran kann das denn nun liegen?

        1. Was sagt denn die Konsole (F12)?

          1. Was sagt denn die Konsole (F12)?

            F12? Da passiert auf dem Mac nix :-)

            Aber eine Konsole gibt’s trotzdem – dort heißt es:

            ReferenceError: Can't find variable: cygcyg / Globaler Code – spsnd.htm:19

            Hier nochmal der betreffende Code, mit Zeilennummern:

            13 str = window.location.search;	// String ab dem Fragezeichen (Beispiel: ?art=v/cygcyg)
            14 tmp = str.split("=");			// teilt str am Gleichheitszeichen
            15 path = tmp[1];					// String nach dem Gleichheitszeichen
            16 art = path.substr(2);			// String nach dem 2. Zeichen (Beispiel: cygcyg)
            17 mp3 = "sound/arten/" + path + ".mp3";
            18 text = sndtxt.get(art);
            19 document.writeln('<p>' + text + '</p>'); // Beschreibungstext
            20 document.write('<audio autoplay controls src="' + mp3 + '" type="audio/mp3"></audio>');
            

            Das seltsame ist nun: Nur beim Singschwan funktioniert die Sache nicht! Ich kann’s einfach nicht verstehen, denn die Variablendeklaration sieht für ihn nicht anders aus als alle anderen. Hier die ersten Zeilen der betreffenden Datei:

            const sndtxt = new Map();
            
            sndtxt.set("cygolo", "Höckerschwan, Rufe (im&nbsp;Hintergrund Bruchwasserläufer, Wasserralle und Kreuzkröten)");
            sndtxt.set("cygcyg", "Singschwan, Flugrufe");
            sndtxt.set("braleu", "Weißwangengans, Rufe eines gerade vom Schlafplatz aufgebrochenen Trupps (außerdem Graugänse und eine Bachstelze)");
            sndtxt.set("ansfab", "(Tundra-)Saatgans, Kontaktrufe eines fliegenden Trupps");
            

            Auf dem Windows-Rechner meiner Frau meldet die Konsole übrigens viel mehr:

            Das Öffnen mehrerer Popups wurde aufgrund fehlender Benutzeraktivierung blockiert. 	popsnd.js:4:7
            Uncaught SyntaxError: "" string literal contains an unescaped line break	busnd.js:20:114
            Uncaught ReferenceError: cygcyg is not defined	spsnd.htm:1:1
                <anonymous> http://www.untere-havel.info/spsnd.htm?art=v/cygcyg line 19 > eval:1
                <anonymous> http://www.untere-havel.info/spsnd.htm?art=v/cygcyg:19
            

            Auch hier wird auf Zeile 19 hingewiesen – ansonsten verstehe ich da nicht viel …

            1. Hallo martinmiethke,

              danke für die URL, da kann man endlich live gucken, was Du tust.

              Das könnte jetzt ein Caching-Problem sein. Denn wenn ich das aufrufe, kommt keine Fehlermeldung zur undefinierten Variablen.

              Ich hatte kurz überlegt, ob Du ein Timing-Problem haben könntest, denn Du bindest im head ein Script ein und verwendest im Body Inline-Script. Würde das busnd.js asynchron geladen, wären die Werte erst da, wenn dein Inline-Script schon längst vorbei ist. Aber das ist nicht so, solange da nicht explizit async oder defer steht, oder type="module", wartet der Browser mit dem Aufbau des DOM, bis das Script geladen und ausgeführt ist.

              Die FM mit den "mehreren Popups" verstehe ich auch nicht, du öffnest ja nur eins. Und bei späteren Starts der Seite sehe ich das auch nicht mehr. Keine Ahnung.

              Dass der Autostart des Audio nicht gelingt, ist eine Folge des neuen Fensters. Popup- und Autostart-Features sind zu oft missbraucht worden, um Leute mit Werbung zuzududeln, deshalb ist ein Autostart nur als direkte Reaktion auf einen Klick zulässig. Oder wenn die Lautstärke auf 0 steht - haha. Du solltest also ggf. überlegen, von einen Popup-Window auf ein Popup-Element auf deiner Seite umzusteigen. Dafür brauchst Du allerdings etwas mehr JavaScript. Am einfachsten geht es mit einem <dialog> Element, damit schließt Du allerdings die Internet Explorer Anwender aus; der kennt das nicht. Unser Wiki hat ein kurzes Tutorial zu Dialogen, aber bevor Du Dich da hinein vertiefst - das braucht noch eine Überarbeitung. Dialoge gehen einfacher als da gezeigt.

              Rolf

              --
              sumpsi - posui - obstruxi
              1. Hallo Rolf, Danke für deinen ausführlichen Kommentar!

                Das könnte jetzt ein Caching-Problem sein. Denn wenn ich das aufrufe, kommt keine Fehlermeldung zur undefinierten Variablen.

                Auch nicht beim Singschwan? Das ist ja das Merkwürdige, dass nur hier ein leeres Fenster geöffnet wird …

                Popup- und Autostart-Features sind zu oft missbraucht worden, um Leute mit Werbung zuzududeln, deshalb ist ein Autostart nur als direkte Reaktion auf einen Klick zulässig.

                … womit es genaugenommen kein Autostart mehr ist. Aber gut, damit kann ich leben :-)

                Du solltest also ggf. überlegen, von einen Popup-Window auf ein Popup-Element auf deiner Seite umzusteigen. Dafür brauchst Du allerdings etwas mehr JavaScript.

                Das hatte ich ohnehin schon überlegt (überhaupt müsste die Website eigentlich komplett neu aufgebaut werden – ohne Frames und Popup-Fenster und im Hinblick auf kleinere Bildschirmformate). Aber da muss ich mich erstmal etwas mehr in JS einlesen …

                Herzliche Grüße – Martin

                1. Hallo martinmiethke,

                  wir reden von www.unter-havel.info, dort klicke ich links auf "Tierarten" und dann auf das Lautsprechersymbol rechts beim Singschwan (Zeile 3)? Sieht bei mir dann so aus:

                  Autoplay kann man im Firefox übrigens als Benutzer einschalten, und Chrome scheint gelernt zu haben, dass ich Audio von Deiner Seite hören will (chrome://media-engagement/) - er macht jetzt Autoplay.

                  Rolf

                  --
                  sumpsi - posui - obstruxi
                  1. wir reden von www.unter-havel.info, dort klicke ich links auf "Tierarten" und dann auf das Lautsprechersymbol rechts beim Singschwan (Zeile 3)?

                    Ja genau.

                    Es war übrigens tatsächlich ein Cache-Problem. Nach Leeren des Caches klappt der Singschwan auch bei mir :-)

                    Sieht bei mir dann so aus:

                    BTW: Wieso wird denn da eine Adresszeile eingeblendet, obwohl das Attribut "location=no" doch angeblich default sein soll?

                    Autoplay kann man im Firefox übrigens als Benutzer einschalten, und Chrome scheint gelernt zu haben, dass ich Audio von Deiner Seite hören will (chrome://media-engagement/) - er macht jetzt Autoplay.

                    Ja dann :-)

                    1. Hallo,

                      BTW: Wieso wird denn da eine Adresszeile eingeblendet, obwohl das Attribut "location=no" doch angeblich default sein soll?

                      weil der Firefox Angaben zum Ausblenden bestimmter Controls in Popup-Fenstern schon seit langem ignoriert. Es gelten die anwenderseitigen Einstellungen.

                      Live long and pros healthy,
                       Martin

                      --
                      Wer respektiert werden will, sollte zunächst damit anfangen, andere zu respektieren.
                      1. weil der Firefox Angaben zum Ausblenden bestimmter Controls in Popup-Fenstern schon seit langem ignoriert. Es gelten die anwenderseitigen Einstellungen.

                        Ah, ok. Noch ein Grund für eine Alternative zum Popup-Fenster …

                        1. Lieber martinmiethke,

                          Noch ein Grund für eine Alternative zum Popup-Fenster …

                          aber sowas von! Im Grunde stellt sich nur die Frage, was Du erreichen möchtest. Da sehe ich zwei grundsätzliche Denkweisen:

                          1. Jedes Viech macht seinen Krach auf einer eigenen Seite. Darauf wird jeweils verlinkt.
                          2. Die Umständlichkeit von 1. wird mit JavaScript durch eine schön gemachte Einblendung auf ein und derselben Seite angenehm verhindert.

                          Man kann mit JavaScript auch ein HTML-Dokument laden und auswerten - oder dessen Inhalt mit JavaScript "nachbilden", wenn man den Komfort erhöhen möchte.

                          Wenn wir die Idee hinter einem CMS dazu nehmen, nämlich die Inhalte zentral zu verwalten und auf entsprechende Anfragen hin Inhalte entsprechend auszuliefern, dann könnte man sogar so vorgehen:

                          1. Alle wesentlichen Daten stehen in einer zentralen Datei, z.B. im JSON-Format. Dort können z.B. auch Referenzen auf Klangdateien stehen.
                          2. Eine serverseitige Logik liefert auf entsprechende Anfragen hin die Inhalte auf Detailseiten aus, oder zeigt eine Übersichtsseite ("homepage").
                          3. Ein JavaScript kann sich die zentrale Datei vom Server laden und mit ihren Inhalten das Wechseln auf eine Detailseite durch Einblendungen auf der aktuellen Seite (Homepage?) ersetzen, um den Komfort des Seitenbesuchers zu erhöhen.

                          Liebe Grüße

                          Felix Riesterer

                          1. Im Grunde stellt sich nur die Frage, was Du erreichen möchtest. Da sehe ich zwei grundsätzliche Denkweisen:

                            1. Jedes Viech macht seinen Krach auf einer eigenen Seite. Darauf wird jeweils verlinkt.
                            2. Die Umständlichkeit von 1. wird mit JavaScript durch eine schön gemachte Einblendung auf ein und derselben Seite angenehm verhindert.

                            Hallo Felix,

                            Nr. 2 hört sich an wie das, was ich mir vorstelle :-)

                            Im Grunde wäre ja das einfachste, wenn nach Klick auf das Lautsprecher-Symbol einfach der Sound abgespielt wird. Das „Problem“ ist eben, dass ich zusätzlich noch einen kurzen Erklärungstext einblenden möchte. Am besten gleich links neben dem Symbol. Und wenn schon was eingeblendet wird, warum dann nicht gleich mit Audio-Bedienelement?

                            Ließe sich das z.B. mit einem Tooltip realisieren? Natürlich erst nach Klick – nicht schon, wenn die Maus drüberfährt.

                            Herzliche Grüße – Martin

                            1. Lieber martinmiethke,

                              Im Grunde wäre ja das einfachste, wenn nach Klick auf das Lautsprecher-Symbol einfach der Sound abgespielt wird.

                              dann ist das Lautsprechersymbol ein Button. Der wird von JavaScript dort hingesetzt. Wenn JavaScript nicht tut (warum auch immer), ist das ein Link, der zur entsprechenden Detail-Seite führt. Ansonsten klappt da etwas auf mit Erklärbärtext und einem automatisch abspielenden audio-Element.

                              Das „Problem“ ist eben, dass ich zusätzlich noch einen kurzen Erklärungstext einblenden möchte. Am besten gleich links neben dem Symbol. Und wenn schon was eingeblendet wird, warum dann nicht gleich mit Audio-Bedienelement?

                              Aber sicherlich doch erst auf die Benutzeraktion hin?

                              Ließe sich das z.B. mit einem Tooltip realisieren? Natürlich erst nach Klick – nicht schon, wenn die Maus drüberfährt.

                              Das, was Du Tooltip nennst, soll wohl nicht das vom Browser auf ein title-Attribut hin eingeblendete Tooltip sein, sondern eine eigene Lösung, die auf den Hover-Effekt hin bislang ausgeblendete Inhalte einblendet? Hmm. Hover ist mit reiner Touchbedienung nicht möglich und sollte von daher ausscheiden.

                              Sag doch mal, mit welcher serverseitigen Umgebung Du hantierst. Benutzt Du ein CMS? Hast Du auf Deinem Webspace eine serverseitige Scriptsprache (z.B. PHP) im Einsatz? Wie kommen Deine Inhalte auf Deinen Webspace?

                              Liebe Grüße

                              Felix Riesterer

                              1. Hallo Felix,

                                aktuell ist es kein Button, sondern ein Link, der über ein JS ein kleines Fenster öffnet (wie weiter oben beschrieben). Diese Lösung gefällt mir aber nicht mehr.

                                Ansonsten klappt da etwas auf mit Erklärbärtext und einem automatisch abspielenden audio-Element.

                                So in etwa stelle ich mir das vor :-)

                                Und ja, mit Tooltip meinte ich die JS-Variante (und mit CSS gibt’s glaube ich auch eine Möglichkeit. Da muss ich mich erst einlesen). Nur eben nicht mit onmouseover, sondern mit onclick.

                                Zur letzten Frage: nein, kein CMS, kein PHP. Der Code entstand in den ersten Jahren mit GoLive, später mit Nvu bzw. KompoZer. Mir gefällt diese Kombination von HTML-Editor und WYSIWYG-Funktion. BlueGriffon wäre das richtige Programm für mich, aber auch der wird nicht mehr weiterentwickelt und stürzt bei mir außerdem ständig ab. Also schreibe ich jetzt in BBEdit und schaue mir das Ergebnis in Safari an.

                                Herzliche Grüße – Martin

                                1. Lieber martinmiethke,

                                  aktuell ist es kein Button, sondern ein Link, der über ein JS ein kleines Fenster öffnet (wie weiter oben beschrieben). Diese Lösung gefällt mir aber nicht mehr.

                                  die ist auch nicht gut. Ein Link sollte zu einer anderen Seite führen. Egal ob mit oder ohne JavaScript.

                                  Prinzipiell kann der Link aber so gestaltet sein, dass er wie ein Button aussieht. Mit JavaScript kann man dann einen Klick auf diesen Link abfangen, um die besprochene Einblendung anzuzeigen. Mit Rechtsklick und neues Tab/Fenster würde der Link dann seiner ursprünglichen Funktion noch immer gerecht. Auch die Inhalte hinter dem Link würden für Suchmaschinen erreichbar.

                                  Ansonsten klappt da etwas auf mit Erklärbärtext und einem automatisch abspielenden audio-Element.

                                  So in etwa stelle ich mir das vor :-)

                                  Na, dann los!

                                  Zur letzten Frage: nein, kein CMS, kein PHP. Der Code entstand in den ersten Jahren mit GoLive, später mit Nvu bzw. KompoZer.

                                  Also gut. Dann machen wir das mit den Mitteln eines Texteditors.

                                  Hier ist ein Vorschlag, wie man das machen könnte. Keine Verpflichtungen!

                                  Verzeichnis "Website" hat diese Struktur:

                                  |
                                  +-- audio
                                  |    |
                                  |    +--singschwan.mp3
                                  |    +--hoeckerschwan.mp3
                                  |
                                  +-- img
                                  |    |
                                  |    +--singschwan.png
                                  |    +--hoeckerschwan.png
                                  |
                                  +-- pages
                                  |    |
                                  |    +--singschwan.html
                                  |    +--hoeckerschwan.html
                                  |
                                  +-- data.json
                                  +-- index.html
                                  +-- script.js
                                  

                                  Die Datei data.json könnte diese Struktur widerspiegeln und in etwa so aussehen:

                                  {
                                    "cygcyg": {
                                      "audio": "./mp3/singschwan.mp3",
                                      "description": "Singschwan, Flugrufe",
                                      "image": "./img/singschwan.png",
                                      "page": "./pages/singschwan.html",
                                      "title": "Der Singschwan"
                                    },
                                    "cygolo": {
                                      "audio": "./mp3/hoeckerschwan.mp3",
                                      "description": "Höckerschwan, Rufe (im Hintergrund Bruchwasserläufer, Wasserralle und Kreuzkröten)",
                                      "image": "./img/hoeckerschwan.png",
                                      "page": "./pages/hoeckerschwan.html",
                                      "title": "Der Höckerschwan"
                                    }
                                  }
                                  

                                  In der Datei script.js müsste dann die Intelligenz stecken, die Links auf die Unterseiten "erkennt" und Klicks darauf abfängt, um die Tooltip-artige Anzeige zu realisieren. Mit den Daten aus data.json kann sie wissen, welche Informationen zu welchen Links gehören.

                                  In der JSON-Datei könnte man auch den Dateinamen der HTML-Datei als "Schlüssel" verwenden, also nicht "cygcyg": {...}, sondern "./pages/singschwan.html": {} schreiben. Damit entfiele der Eintrag "page" in allen Datensätzen.

                                  Für die Intelligenz im JavaScript müssten wir neu quatschen. Da will ich Dir keine fertige Lösung vorsetzen.

                                  Liebe Grüße

                                  Felix Riesterer

                                  1. Hallo Felix,

                                    Prinzipiell kann der Link aber so gestaltet sein, dass er wie ein Button aussieht. Mit JavaScript kann man dann einen Klick auf diesen Link abfangen, um die besprochene Einblendung anzuzeigen. Mit Rechtsklick und neues Tab/Fenster würde der Link dann seiner ursprünglichen Funktion noch immer gerecht. Auch die Inhalte hinter dem Link würden für Suchmaschinen erreichbar.

                                    das ist ein sehr guter Punkt. Viele Sites mit einer auf Javascript basierten Navigation geben dem Besucher nämlich gar nicht die Möglichkeit, verlinkte Seiten (ich schrieb bewusst nicht Links) auch in einem neuen Tab zu öffnen.

                                    Das finde ich ärgerlich, weil das Öffnen von Linkzielen in einem neuen Tab für mich der Normalfall ist. Ich bin es gewöhnt, Links mit der mittleren Maustaste anzuklicken. Das hat den Vorteil, dass ich ein ganzes Rudel weiterführender Links in Hintergrund-Tabs öffnen kann, um mir die verlinkten Seiten dann eine nach der anderen in Ruhe anzusehen - und wenn ich sie alle gelesen und geschlossen habe, bin ich ganz automatisch wieder da, wo ich eigentlich herkam. Deswegen fristet der Back-Button des Browsers bei mir auch ein Schattendasein; ich brauche ihn so gut wie nie, weil ich dem sprichwörtlichen Faden der Ariadne folgend immer zum Ausgangspunkt zurückkomme.

                                    Verzeichnis "Website" hat diese Struktur:

                                    |
                                    +-- audio
                                    |    |
                                    |    +--singschwan.mp3
                                    |    +--hoeckerschwan.mp3
                                    |
                                    +-- img
                                    |    |
                                    |    +--singschwan.png
                                    |    +--hoeckerschwan.png
                                    |
                                    +-- pages
                                    |    |
                                    |    +--singschwan.html
                                    |    +--hoeckerschwan.html
                                    |
                                    +-- data.json
                                    +-- index.html
                                    +-- script.js
                                    

                                    Der inhaltlichen Gliederung zuliebe würde ich eher Verzeichnisse für die einzelnen Tierarten machen und dann alle zu dieser Art gehörenden Ressourcen (HTML-Dokument, Bild(er), Audio, später evtl. ein Video) in diesem Verzeichnis zusammenhalten. Ist aber letztendlich Jacke wie Hose, für die Realisierung macht es keinen wirklichen Unterschied.

                                    In der Datei script.js müsste dann die Intelligenz stecken, die Links auf die Unterseiten "erkennt"

                                    Das könnte sie zum Beispiel dadurch, dass diese Links alle einer bestimmten Klasse angehören.

                                    In der JSON-Datei könnte man auch den Dateinamen der HTML-Datei als "Schlüssel" verwenden, also nicht "cygcyg": {...}, sondern "./pages/singschwan.html": {} schreiben. Damit entfiele der Eintrag "page" in allen Datensätzen.

                                    Viele Wege führen nach Rom. 😀

                                    Live long and pros healthy,
                                     Martin

                                    --
                                    Wer respektiert werden will, sollte zunächst damit anfangen, andere zu respektieren.
                                  2. Hier ist ein Vorschlag, wie man das machen könnte. Keine Verpflichtungen!

                                    Hallo Felix, da hast du dir ja richtig Mühe gemacht – Danke!

                                    Allerdings habe ich mich bisher noch gar nicht mit JSON befasst. Scheint aber ein interessanter Ansatz zu sein …

        2. Hallo,

          Ja Pustekuchen! Auf meinem Rechner funktioniert die Sache, aber vom Server nicht :-(

          Woran kann das denn nun liegen?

          Oft hat der Server ein anderes Dateisystem als der eigene Rechner, das dann weniger tolerant als das unter Windows ist. Bist du dir mit den Pfaden 100% sicher? Groß/Kleinschreibung wäre ein Kandidat für das Phänomen oder unterschiedliche Slashe…

          Gruß
          Kalk

          1. Hi,

            Woran kann das denn nun liegen?

            Oft hat der Server ein anderes Dateisystem als der eigene Rechner, das dann weniger tolerant als das unter Windows ist. Bist du dir mit den Pfaden 100% sicher? Groß/Kleinschreibung wäre ein Kandidat für das Phänomen oder unterschiedliche Slashe…

            oder Umlaute/andere Zeichen außerhalb von ASCII …

            cu,
            Andreas a/k/a MudGuard

            1. oder Umlaute/andere Zeichen außerhalb von ASCII …

              In Datei- oder Ordnernamen? Nee, ganz sicher nicht.

          2. Oft hat der Server ein anderes Dateisystem als der eigene Rechner, das dann weniger tolerant als das unter Windows ist. Bist du dir mit den Pfaden 100% sicher? Groß/Kleinschreibung wäre ein Kandidat für das Phänomen

            Das ist mir durchaus bewusst – deshalb sind bei mir Dateinamen grundsätzlich klein geschrieben.

            oder unterschiedliche Slashe…

            Backslashes gibt’s bei mir nicht …

      2. Ein Map-Objekt definieren, das die Zuordnungen enthält:

        Super – das klappt bestens!

        (Wobei die Abfrage verzeichnis.get(art) heißen muss, nicht verzeichnis.get(text)) – der Map-Schlüssel steht ja in der Variablen art :‑)

        Freut mich :)

        Das mit "art" statt "text" ist mir im Nachhinein auch aufgefallen. Das sind einfach viele Variablen in Deinem Skript um da den Überblick zu behalten. Wenn Du die ganzen Zwischenvariablen nicht brauchst, könntest Du da auch einiges zusammenfassen. Z.B.:

        art = str.split("=")[1].substr(2);
        

        Ansonsten sei auf das URLSearchParams-API verwiesen. Vielleicht musst Du deinen String gar nicht von Hand zerlegen.

    4. Ein Map-Objekt definieren, das die Zuordnungen enthält:

      const verzeichnis = new Map();
      const.set("cygcyg", "Singschwan, Flugrufe");
      // usw.
      

      Nochmal zur Map-Deklaration: Laut Wiki wäre auch diese etwa einfachere Syntax möglich:

      const verzeichnis = new Map([
          ["cygcyg", "Singschwan, Flugrufe"],
          … usw.
      ]);
      

      Gibt es einen Grund, die hier nicht zu verwenden?

      1. Hallo martinmiethke,

        na, ob das wirklich einfacher ist? JavaScript muss hierfür zuerst ein Array von Arrays aufbauen und dieses dann wieder durchlaufen. Intern ruft er dann für jeden Eintrag im Array die set-Methode auf. Vielleicht ist es etwas effizienter, weil Sicherheitsabfragen gebündelt werden können.

        Wenn man die Daten ohnehin schon als Array vorliegen hat, ist die Konstruktion mit einem Array aus Key-Value Paaren sicher sinnvoll.

        Andernfalls ist ein mehrfacher Aufruf von set genauso lesbar, finde ich.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Andernfalls ist ein mehrfacher Aufruf von set genauso lesbar, finde ich.

          OK, Danke!

  2. Hallo Martin,

    <a href="javascript:ops('v/cygcyg')"><img ></a>
    

    "v" ist der Ordner, in dem die MP3-Dateien mit Vogelstimmen liegen (es gibt auch noch Ordner für Amphibien und Heuschrecken); "cygcyg" ist das Kürzel für den Singschwan.

    Das Argument an die Funktion ops ist also Teil eines Pfads.

    Mit der Funktion ops() wird eine HTML-Datei aufgerufen:

    function ops(daten) {
        url = "spsnd.htm?art=" + daten;
        popsnd = window.open(url, "snd", "status=no,width=300,height=160,left=60,top=60");
        popsnd.focus();
    }
    

    Der Pfad wird hier als Inhalt der Variablen daten also als Wert des URL-Parameters art Teil des Querystrings.

    Ein JS innerhalb des Dokuments soll dann den Inhalt der Seite „zusammenbauen“:

    <head>
    <meta charset="utf-8" />
    <title>Tonaufnahme</title>
    <script type="text/javascript" language="JavaScript" src="scripts/busnd.js"></script>
    </head>
    <script language="JavaScript">
    <!--
    str = window.location.search;	// String ab dem Fragezeichen (Beispiel: ?art=v/cygcyg)
    tmp = str.split("=");			// teilt str am Gleichheitszeichen
    

    tmp ist ein Array: tmp = ['?art', 'v/cygcyg']

    path = tmp[1];					// String nach dem Gleichheitszeichen
    art = path.substr(2);			// String nach dem 2. Zeichen (Beispiel: cygcyg)
    mp3 = "sound/arten/" + path + ".mp3";
    text = eval(art);
    

    Sofern die Content-Security-Policy (CSP) das zulässt, würde hier der Inhalt der Variablen art ausgewertet, in deinem Fall der Inhalt der Variablen cygcyg zurückgegeben.

    Neben dem Punkt mit der CSP frage ich mich gerade, was passiert, wenn ich die Seite mit ?art=alert(%22XSS%22) aufrufe …

    Das hat auch mal funktioniert – aber eine Überprüfung nach einer längeren Pause ergab, dass jetzt nur noch ein leeres Fenster geöffnet wird. Durch Testen konnte ich herausfinden, dass das an der eval-Funktion liegt (die ja, wie ich inzwischen weiß, nicht mehr verwendet werden soll). Nun suche ich nach einer Alternative und habe auch schon im Netz danach gesucht, konnte aber nichts passendes finden.

    Was zeigt dir eigentlich die JavaScript-Konsole der Browser-Entwicklertools (Drücken der Taste F12) dazu an? Ansonsten gibt es ja schon eine Idee.

    Viele Grüße
    Robert

    1. Sofern die Content-Security-Policy (CSP) das zulässt, würde hier der Inhalt der Variablen art ausgewertet, in deinem Fall der Inhalt der Variablen cygcyg zurückgegeben.

      Genau – ursprünglich funktionierte das ja auch so.

      Ansonsten gibt es ja schon eine Idee.

      … und die werde ich gleich ausprobieren :-)