diff --git a/html/README.md b/html/README.md
new file mode 100644
index 0000000..a4c8a7e
--- /dev/null
+++ b/html/README.md
@@ -0,0 +1,111 @@
+# Anzeigen der Wechselkurse
+
+
+Die Daten werden in aus einer MySQL-Datenbank gelesen und in Tabellenform angezeigt. Für eine Währung wird die Kursentwicklung grafisch veranschaulicht. Die Darstellung basiert auf der Bibliothek https://d3js.org/d3.v3.min.js.
+
+
+## Datenbankroutinen
+
+Für den Datenbankzugriff wird die Klasse db.php verwendet. Der Konstruktor
+verlangt nach dem Namen der Datenbank ("wechselkurse") sowi den Benutzerdaten
+(username+password).
+
+Folgende Schnittstellen stehen zur Verfügung:
+
+```
+class DB {
+
+ function getDBName() // liefert den Namen der Datenbank
+
+ // Liefert ein Array.
+ // Jeder Eintrag stelt eine Datenzeile dar, die ein assoziatives Array ist.
+ // wird intern verwendet
+ function get_Query($sql)
+
+ // liefert Abfrage im JSON-Format
+ function getJSON_Data($sql)
+
+ // Für eine sql-Abfrage mit einer Spalte wird der Quelltext für
+ // eine HTML-Dropbox generiert.
+ // - sql-Abfrage
+ // - Zu jeder Option ein Link erzeugt
+ // - es kann ein vordefinierter Wert ausgewählt werden
+ // - der Name der Select-Box
+ function getQueryAsHTMLDropDownBox($sql, $link, $default, $dropdownName)
+
+ // Eine SQL-Abfrage wird in einer Texttabelle erzeugt
+ // Das Format der Tabelle muss übergeben werden
+ function getQueryAsTEXTTable($sql,$format)
+
+ // Eine SQL-Abfrage wird als HTML-Tabelle zurückgegeben
+ function getQueryAsHTMLTable($sql)
+}
+```
+
+Beispielaufrufe:
+
+```
+/*------------------------------------------------------ */
+
+echo $db->getJSON_Data("SELECT * from kurse LIMIT 2;") . "\n";
+print_r ( $db->get_Query("SELECT * from kurse LIMIT 2;") );
+
+echo "getQueryAsDropDownBox \n";
+print_r ($db->getQueryAsHTMLDropDownBox("SELECT DISTINCT(waehrung) from kurse ORDER BY waehrung", "https://server.de/show.php?waehrung=", "JPY", "myDDF") );
+
+echo "getQueryAsTEXTTable \n";
+print_r ($db->getQueryAsTEXTTable("SELECT * from kurse LIMIT 4","%-4s %-12s %-5s %10f") );
+
+echo "getQueryAsHTMLTable \n";
+print_r ($db->getQueryAsHTMLTable("SELECT * from kurse LIMIT 4") );
+
+/*------------------------------------------------------ */
+```
+
+## Grafische Anzeige des Kursverlaufs
+
+Für die Bibliothek https://d3js.org/d3.v3.min.js wird eine angepasste Datei
+chart.js verwendet, die das Format auf deutsch umstellt und im Wesentlichen
+eine Methode enthält, die für die Anzeige verwendet wird.
+
+```
+// ************************************************************
+// Funktion zur Erzeugung einer Grafik (Linie)
+// Die Daten müssen zwei Spalten enthalten: (zeit | value)
+//
+// Parameter:
+// o titel Diagrammtitel oben
+// o sql wird z.Zt. nicht genutzt
+// o textX Beschrfitung der x-Achse
+// o textY Beschriftung der y-Achse
+// o breite Breite des Diagramms
+// o hoehe Höhe des Diagramms
+// o data Daten im JSON-Format
+// o scaleY 0=automatisch skalieren, 1=Prozent 0..100
+// o units Einheiten für die Tooltipps
+// o id id in css-Klasse
+// #id ............ Breite, Rand/farbe)
+// #id .title ...... Farbe, Größe des Titels
+// #id .y .......... Farbe der y-Beschriftung
+// #id .linecolor .. Linienfarbe
+// #id .tooltip .... Frarbe Tooltipps
+// ***********************************************************
+
+function showDiagram1Line(titel, sql, textX, textY, breite, hoehe, data, scaleY, units, id)
+```
+
+Beispielaufruf ("waehrung" wird als Parameter beim Aufruf mitgegen und muss
+ zuvor mit $_GET oder $_POST gelesen werden):
+```
+
+```
+
+
+
diff --git a/html/chart.js b/html/chart.js
new file mode 100644
index 0000000..01aad4d
--- /dev/null
+++ b/html/chart.js
@@ -0,0 +1,209 @@
+// ***********************************************************
+//
+// Globale Einstellungen
+// gültig für alle Diagramme
+//
+// ***********************************************************
+
+// Parse the date / time
+//var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
+var parseDate = d3.time.format("%Y-%m-%d").parse;
+
+// Einstellung auf deutsche Formate
+var de_DE = d3.locale({
+ "decimal": ",",
+ "thousands": ".",
+ "grouping": [3],
+ "currency": ["", "€"],
+ "dateTime": "%a %b %e %X %Y",
+ "date": "%d.%m.%Y",
+ "time": "%H:%M:%S",
+ "periods": ["AM", "PM"],
+ "days": ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
+ "shortDays": ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
+ "months": ["Januar", "Februar", "März", "April", "Mai", "Juni", "July", "August", "September", "Oktober", "November", "Dezember"],
+ "shortMonths": ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
+});
+
+// Zeit auf deutsches Format einstellen
+d3.time.format = de_DE.timeFormat;
+
+// Benutzerdefiniertes Zeitformat
+var customTimeFormat = d3.time.format.multi([
+ [".%L", function(d) { return d.getMilliseconds(); }],
+ [":%S", function(d) { return d.getSeconds(); }],
+ ["%H:%M", function(d) { return d.getMinutes(); }],
+ ["%H:%M", function(d) { return d.getHours(); }],
+ ["%a %d", function(d) { return d.getDay() && d.getDate() != 1; }],
+ ["%b %d", function(d) { return d.getDate() != 1; }],
+ ["%b", function(d) { return d.getMonth(); }],
+ ["%Y", function() { return true; }]
+]);
+
+// Zeitformat für Tooltipps
+var formatTimeTooltipp = d3.time.format("%e %B %H:%M");
+
+// ************************************
+// define grid line functions
+// ************************************
+function make_x_axis1(x) {
+ return d3.svg.axis()
+ .scale(x)
+ .orient("bottom")
+ .ticks(15)
+}
+
+function make_y_axis1(yy) {
+ return d3.svg.axis()
+ .scale(yy)
+ .orient("left")
+ .ticks(5)
+}
+
+
+
+// ************************************************************
+// Funktion zur Erzeugung einer Grafik (Linie)
+// Die Daten müssen zwei Spalten enthalten: (zeit | value)
+//
+// Parameter:
+// o titel Diagrammtitel oben
+// o sql wird z.Zt. nicht genutzt
+// o textX Beschrfitung der x-Achse
+// o textY Beschriftung der y-Achse
+// o breite Breite des Diagramms
+// o hoehe Höhe des Diagramms
+// o data Daten im JSON-Format
+// o scaleY 0=automatisch skalieren, 1=Prozent 0..100
+// o units Einheiten für die Tooltipps
+// o id id in css-Klasse
+// #id ............ Breite, Rand/farbe)
+// #id .title ...... Farbe, Größe des Titels
+// #id .y .......... Farbe der y-Beschriftung
+// #id .linecolor .. Linienfarbe
+// #id .tooltip .... Frarbe Tooltipps
+// ***********************************************************
+
+function showDiagram1Line(titel, sql, textX, textY, breite, hoehe, data, scaleY, units, id) {
+
+ var margin = {top: 30, right: 55, bottom: 30, left: 60},
+ width = breite - margin.left - margin.right,
+ height = hoehe - margin.top - margin.bottom;
+
+ document.write ("
" + titel + "
");
+
+ // specify the scales for each set of data
+ var x = d3.time.scale().range([0, width]);
+ var y = d3.scale.linear().range([height, 0]);
+
+ // dynamische Werte anzeigen
+ var div = d3.select("body").append("div")
+ .attr("class", "tooltip tooltippfarbe")
+ .style("opacity", 0);
+
+
+ // axis formatting
+ var xAxis = d3.svg.axis().scale(x)
+ .orient("bottom").ticks(6).tickFormat(customTimeFormat);;
+ var yAxis = d3.svg.axis().scale(y)
+ .tickFormat(d3.format(".4f"))
+ .orient("left").ticks(5);
+
+ // line functions
+ var valueLine = d3.svg.line()
+ .x(function(d) { return x(d.zeit); })
+ .y(function(d) { return y(d.value); });
+
+
+ // setup the svg area
+ var svg = d3.select(id)
+ .append("svg")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .append("g")
+ .attr("transform",
+ "translate(" + margin.left + "," + margin.top + ")");
+
+ // wrangle the data into the correct formats and units
+ data.forEach(function(d) {
+ d.zeit = parseDate(d.zeit);
+ d.value = +d.value;
+ });
+
+ // Scale the range of the data
+ x.domain(d3.extent(data, function(d) { return d.zeit; }));
+ if ( scaleY == 0 ) {
+ y.domain([
+ d3.min(data, function(d) {return Math.min(d.value); }),
+ d3.max(data, function(d) {return Math.max(d.value); })]);
+ //d3.min(data, function(d) {return Math.min(d.value); })-.25,
+ //d3.max(data, function(d) {return Math.max(d.value); })+.25]);
+ }
+ else {
+ y.domain([ 0,100 ]);
+ }
+
+ svg.append("path") // Add the value line.
+ .attr("class", "linecolor")
+ .attr("d", valueLine(data));
+
+ svg.append("g") // Add the X Axis
+ .attr("class", "x axis")
+ .attr("transform", "translate(0," + height + ")")
+ .call(xAxis);
+
+ svg.append("g") // Add the value axis
+ .attr("class", "y axis")
+ //.style("fill", "steelblue")
+ .call(yAxis);
+
+ svg.append("text") // Add the text label for the value axis
+ .attr("class", "y")
+ .attr("transform", "rotate(-90)")
+ .attr("x", 0)
+ .attr("y", -40)
+ //.style("fill", "steelblue")
+ .style("text-anchor", "end")
+ .text(textY);
+
+
+ svg.append("g")
+ .attr("class", "grid")
+ .attr("transform", "translate(0," + height + ")")
+ .call(make_x_axis1(x)
+ .tickSize(-height, 0, 0)
+ .tickFormat("")
+ );
+
+ svg.append("g")
+ .attr("class", "grid")
+ .call(make_y_axis1(y)
+ .tickSize(-width, 0, 0)
+ .tickFormat("")
+ )
+
+
+ // dynamische Wertanzeige
+ svg.selectAll("dot")
+ .data(data)
+ .enter().append("circle")
+ .attr("r", 3)
+ .attr("cx", function(d) { return x(d.zeit); })
+ .attr("cy", function(d) { return y(d.value); })
+ .on("mouseover", function(d) {
+ div.transition()
+ .duration(100)
+ .style("opacity", .9);
+ div .html(formatTimeTooltipp(d.zeit) + " " + d.value + units)
+ .style("left", (d3.event.pageX) + "px")
+ .style("top", (d3.event.pageY - 28) + "px");
+ })
+ .on("mouseout", function(d) {
+ div.transition()
+ .duration(500)
+ .style("opacity", 0);
+ });
+
+ return true;
+}
+
diff --git a/html/db.php b/html/db.php
new file mode 100644
index 0000000..ef9e833
--- /dev/null
+++ b/html/db.php
@@ -0,0 +1,155 @@
+db = $db;
+ $this->username = $u;
+ $this->password = $pw;
+ }
+
+
+ function getDBName() {
+ return $this->dbname;
+ }
+
+ // Liefert ein Array.
+ // Jeder Eintrag stelt eine Datenzeile dar, die ein assoziatives Array ist.
+ function get_Query($sql) {
+ try {
+ $dbh = new PDO("mysql:host=" . $this->hostname.";dbname=".$this->db, $this->username, $this->password);
+ $statement = $dbh->prepare($sql);
+ $statement->execute();
+ $dbh = null; // ** close the database connection *** /
+ }
+ catch(PDOException $e) {
+ echo $e->getMessage();
+ }
+ return $statement->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ // liefert Abfrage im JSON-Format
+ function getJSON_Data($sql) {
+ $result = $this->get_Query($sql);
+ $json_data = json_encode($result);
+ return $json_data;
+ }
+
+
+ function getQueryAsHTMLDropDownBox($sql, $link, $default, $dropdownName) {
+ $result = $this->get_Query($sql);
+ $html = "";
+ if ($result != null) {
+ $html .= "\n";
+ return $html;
+ }
+ else {
+ return "Error beim erstellen der Dropdown-Box.";
+ }
+ }
+
+
+ function getQueryAsTEXTTable($sql,$format) {
+ $result = $this->get_Query($sql);
+ $html = "