Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

Kommunikation und Netzwerk

k24:k24.6:k24.6.2:k24.6.2.4:start

24.6.2.4 Projekt 4

Im vierten Projekt `webapp4` werden weitere 6 Webseiten als Erweiterung des Projektes `webapp3` auf der Basis der Klasse Webpage erzeugt. Die Webseite mit einem (SQLite-)Datenbank-Report sehen Sie hier:

DB-REPORT

Abbildung 24.6.2.4.1: (SQLite-)Datenbank-Report (Ausschnitt)

24.6.2.4.1 Template-Datei Main.webpage

Die Webpage Main.webpage ist auch in diesem Projekt die wichtigste Datei des Templates, denn sie enthält am Anfang einen Gambas-Block für das Auslesen der im Webbrowser gesetzten Sprache sowie der angeforderten Webseite und dann den Head-Bereich mit einem Platzhalter. Danach folgt HTML mit weiteren Platzhaltern für die Layout-Bereiche Header, Navigation, Content und Footer:

 [1] <%
 [2] '-- Variable declaration must come before any HTML
 [3]     Dim sCurSite As String
 [4]     Dim aSiteList As New String[]
 [5]
 [6] '-- The browser tells the server which language (locale) it is set to via Request.Language.
 [7]     System.Language = Request.Language ' Example: de_DE.UTF8
 [8] '-- Insert a list to filter the pages
 [9]     aSiteList = Main.SiteList
 [10]
 [11]     If Request.Query Then
 [12]        If aSiteList.Exist(Request.Query) Then
 [13]           sCurSite = Request.Query
 [14]        Endif
 [15]     Else
 [16]        sCurSite = aSiteList[0]
 [17]     Endif
 [18] %>
 [19] <!DOCTYPE html>
 [20] <html lang="de">
 [21]   <!-- BEGIN SITE-HEAD -->
 [22]   <head>
 [23]     <meta charset="UTF-8">
 [24]     <!-- Setting for display on mobile devices | MediaQueries -->
 [25]     <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
 [26]     <!-- The description is used for display in search engines! -->
 [27]     <meta name="description" content="TEMPLATE: WEBPAGE GAMBAS HTML CSS JS">
 [28]     <!-- The title of the web page is displayed in the browser tab! -->
 [29]     <title><%=sCurSite%></title> <!--  < 30 Zeichen -->
 [30]     <!-- Reference to an icon. The favicon is displayed in the browser tab! -->
 [31]     <link rel="icon" type="image/png" href="./favicon/favicon_blue_32.ico">
 [32]     <!-- Reference to a central CSS file in the /css folder -->
 [33]     <link rel="stylesheet" type="text/css" href="./css/style.css">
 [34]     <!-- Reference to a JavaScript file in the /js folder -->
 [35]     <script src="./js/set_time.js"></script>
 [36]   </head>
 [37]   <!-- END SITE-HEAD -->
 [38]   <body onload="JSTimer1();">
 [39]     <<IncHeader>>
 [40]     <br>
 [41]     <<IncNavigation>>
 [42]     <br>
 [43]     <main>
 [44]       <<IncContent>>
 [45]     </main>
 [46]     <<IncFooter>>
 [47]   </body>
 [48] </html>

Die Gambas-Klassen-Datei main.class enthält eine erweiterte Liste der aktuell verfügbaren Webseiten, die in der Variablen `SiteList` gespeichert wird:

' Gambas class file

  Public SiteList As String[] = ["Start", "Umgebung", "Zeit", "Datum", "Multimedia", "DBReport", "Formular", "FPlotter", "Impressum"]

Kommentar

  • In den Zeilen 39, 41, 44 und 46 werden die Platzhalter für die Bereiche Header, Navigation, Content und Footer in Abhängigkeit von der angefragten Webseite aktualisiert.
  • Dem Platzhalter für den Header (Zeile 39) wird – im Gegensatz zum Web-Projekt `webapp3` – keine Zeichenkette „Webseiten mit Gambas-Webpage erzeugen“ mitgegeben. Der entsprechende Text wird direkt in der Datei IncHeader.webpage (Zeile 4) eingefügt:
 1. <!--BEGIN SITE-HEADER -->
 2. <header class="site-header">
 3.   <img class="site-logo" src="./icons/logo3_256x256.png" alt="Gambas-Logo">
 4.   <p class="site-slogan">Webseiten mit Gambas-Webpage erzeugen</p>
 5. </header>
 6. <!-- END SITE-HEADER -->

24.6.2.4.2 Template-Datei IncContent.webpage

Die Webpage IncContent.webpage enthält u.a. 9 Platzhalter, die in Abhängigkeit von der angeforderten Webseite (Request-Query) durch den Inhalt der einzelnen Webseiten ersetzt werden.

 [1] <!-- START: INSERT SELECTED CONTENT -->
 [2]   <%Select Request.Query
 [3]      Case "Umgebung"%>
 [4]        <<IncEnvironment>>
 [5]      <% Case "Zeit"%>
 [6]        <<IncTime>>
 [7]      <%Case "Datum"%>
 [8]        <<IncDate>>
 [9]      <%Case "Multimedia"%>
 [10]        <<IncMultimedia>>
 [11]      <%Case "DBReport"%>
 [12]        <<IncDBReport>>
 [13]      <%Case "Formular"%>
 [14]        <<IncFormular>>
 [15]      <%Case "FPlotter"%>
 [16]        <<IncFPlotter>>
 [17]      <%Case "Impressum"%>
 [18]        <<IncImpressum>>
 [19]      <%Default%>
 [20]        <<IncHome>>
 [21]   <%End Select%>
 [22] <!-- END: INSERT CONTENT -->

Die Gambas-Klassen-Datei IncContent.class ist leer.

Kommentar

  • In einer Select-Case-Kontrollstruktur (<%Select Request.Query … %>…<%End Select%>) in den Zeilen 2 bis 21 wird der Inhalt für den Bereich 'Content' der angeforderten Webseite erzeugt, indem der Platzhalter «IncFPlotter» durch den entsprechenden HTML-Quelltext wie zum Beispiel für die Webseite FPlotter ersetzt wird.
  • Da beim ersten Aufruf der Webseiten der URL-Parameter leer ist, wird automatisch der Inhalt für den Bereich 'Start' der Startseite erzeugt (Zeile 20). Erst danach greift die Erzeugung des Menüs mit den passenden URL-Parametern in den 9 Links in der Navigation.

Hinweis:

Der Inhalt der Webpage IncNavigation.webpage ist der gleiche wie im Web-Projekt `webapp3` und wird 1:1 übernommen.

24.6.2.4.3 Erweiterungen

In den folgenden sechs Absätzen wird der HTML-Quelltext für den Bereich 'Content' der Webseiten Zeit, Datum, Multimedia, DBReport, Formular und FPlotter angegeben und kommentiert.

24.6.2.4.3.1 Template-Datei IncTime.webpage

Die Webpage IncTime.webpage enthält u.a. einen Platzhalter (Zeile 5) für die einzufügende aktuelle Uhrzeit:

 [1] <!-- INSERT TIME  -->
 [2] <h1>Aktuelle Zeit</h1>
 [3] <div class="thin-box">
 [4]   <figure>
 [5]     <h2 id="set_time"></h2>
 [6]   </figure>
 [7] </div>

Die Gambas-Klassen-Datei IncTime.class ist leer.

Kommentar

  • In der Zeile 5 wird der von der JavaScript-Funktion 'set_time' ausgegebene Text als aktuelle Uhrzeit css-formatiert angezeigt.
  • Der Text wird durch den im JavaScript-Skript set_time.js implementierten JS-Timer im Sekundentakt im Webbrowser neu erzeugt.

UHRZEIT

Abbildung 24.6.2.4.2: Anzeige der aktuellen Uhrzeit

24.6.2.4.3.2 Template-Datei IncDate.webpage

Die Webpage IncDate.webpage enthält in der Zeile 5 u.a. einen Platzhalter für das einzufügende Datum in einem bestimmten Format:

 [1] <!-- INSERT DATE  -->
 [2] <h1>Aktuelles Datum</h1>
 [3] <div class="thin-box">
 [4]   <figure>
 [5]     <h2><%=Format(Now, "dddd - d. mmmm yyyy")%></h2>
 [6]   </figure>
 [7] </div>

Kommentar

  • Beachten Sie das Gleichheitszeichen vor der Format()-Funktion!
  • Die Gambas-Klassen-Datei IncDate.class ist leer.

24.6.2.4.3.3 Template-Datei IncMultimedia.webpage

Was wäre eine Webseite ohne Bilder und andere multimediale Elemente wie Sound- oder Video? Genau diese drei Elemente werden in die Webseite IncMultimedia.webpage nacheinander eingefügt:

 [1] <h1>Multimedia</h1>
 [2]
 [3] <!-- INSERT IMAGE  -->
 [4] <div class="thin-box">
 [5]   <h3>Bilder flexibel einfügen</h3>
 [6]   <hr>
 [7]   <figure>
 [8]     <img src="./images/tom_780x1012.png" alt="Tom" width="343" height="445">
 [9]     <figcaption>Tom im Rockkonzert in Berlin</figcaption>
 [10]   </figure>
 [11] </div>
 [12] <!-- INSERT AUDIO -->
 [13] <div class="thin-box">
 [14]   <h3>Audio-Dateien einfügen</h3>
 [15]   <hr>
 [16]   <figure>
 [17]     <!-- Bedienelemente anzeigen und Metadaten laden -->
 [18]     <audio src="./audiovideo/tom.mp3" type="audio/mp3" controls></audio>
 [19]     <figcaption>Sänger: Tom -> Der Berliner</figcaption>
 [20]   </figure>
 [21] </div>
 [22] <!-- INSERT VIDEO -->
 [23] <div class="thin-box">
 [24]   <h3>Video-Dateien einfügen</h3>
 [25]   <hr>
 [26]   <figure>
 [27]     <video src="./audiovideo/viehscheid.mp4" controls></video>
 [28]     <figcaption>Viehscheid in Gunzesried (Allgäu)</figcaption>
 [29]   </figure>
 [30] </div>

Kommentar

  • Die CSS-Anweisungen in den Zeilen 8, 18 und 27 sorgen im jeweils umschließenden DIV-Container für alle drei multimedialen Elemente für den gleichen Style.
  • Für alle drei multimedialen Elemente wird in den Zeilen 9, 19 sowie 28 eine Beschreibung/Unterschrift im figcaption-Tag angezeigt.
  • Während das Bild sofort angezeigt wird, werden für die Sound- und Video-Datei nur die passenden Bedienelemente eingeblendet, durch die der Sound oder das Video nach einem Klick auf den Start-Button abgespielt werden.

TOM

Abbildung 24.6.2.4.3: Bild-Anzeige

SOUND

Abbildung 24.6.2.4.4: Bedienelemente Sound

VIDEO

Abbildung 24.6.2.4.5: Bedienelemente Video (und Fußzeile)

Die Gambas-Klassen-Datei IncMultimedia.class ist leer.

24.6.2.4.3.4 Template-Datei IncDBReport.webpage

Die Webpage IncDBReport.webpage ist nennenswert kurz und enthält einen Platzhalter für den einzufügenden Datenbank-Report:

 [1]  <% Print DBReport(); %>
 [2]  <br>

Die Erzeugung des (SQLite-)Datenbank-Reports wird in die Gambas-Klassendatei IncDBReport.class ausgelagert:

 [1] ' Gambas class file
 [2]
 [3] Public rDBResult As Result
 [4] Public cDBConnection As New Connection
 [5]
 [6] Public Function DBReport() As String
 [7]
 [8]     Dim iRecord, iField As Integer
 [9]     Dim sSQL, sHTML As String
 [10]     Dim aFieldNamesDisplayed As String[]
 [11]
 [12]     aFieldNamesDisplayed = ["ID", "Vorname", "Nachname", "Wohnort", "PLZ", "Straße", "Geburtstag",
                            "Festnetz", "Mobil", "EMail"]
 [13]
 [14]     cDBConnection.Type = "sqlite3"
 [15]     cDBConnection.Host = Application.Path &/ ".public/db"
 [16]     cDBConnection.Name = "contacts.sqlite"
 [17]
 [18]     Try cDBConnection.Open()
 [19]     If Error Then
 [20]   '-- Option: sHTML &= "<h1>A DB connection could not be established!</h1>"
 [21]       CGI.Error("A DB connection could not be established!")
 [22]       Return
 [23]     Endif
 [24]
 [25]     cDBConnection.Exec("PRAGMA short_column_names = ON")
 [26]
 [27]     sSQL = "SELECT * FROM contacts"
 [28]
 [29]     Try rDBResult = cDBConnection.Exec(sSQL)
 [30]     If Error Then
 [31]       Error.Raise("<h1>Error!<br>" & Error.Text & "</h1>")
 [32]     Endif
 [33]
 [34]     If rDBResult.Count = 0 Then
 [35]       Error.Raise("<h1>The number of selected records is zero!</h1>")
 [36]     Endif
 [37]
 [38] '-- Enter the field names in the table header
 [39]     If rDBResult.Available Then
 [40]       sHTML &= "<h1 style=\"margin-bottom:0.6rem;\">"
 [41]       sHTML &= "Datenbank-Report"
 [42]       sHTML &= "</h1>"
 [43]       sHTML &= "<h3 style=\"margin-bottom:1.4rem;\">"
 [44]       sHTML &= Format(Now, "dddd - d. mmmm yyyy") & " - " & Format$(Now, "hh:nn") & " Uhr"
 [45]       sHTML &= "</h3>"
 [46]       sHTML &= ""
 [47]       sHTML &= "<table>"
 [48]       sHTML &= "<tr>"
 [49]       For iField = 0 To rDBResult.Fields.Count - 1
 [50]         sHTML &= "<th>" & aFieldNamesDisplayed[iField] & "</th>"
 [51]       Next
 [52]       sHTML &= "</tr>"
 [53]
 [54]   '-- Fill the (HTML)table with the DB data
 [55]       For iRecord = 0 To rDBResult.Count - 1
 [56]         sHTML &= "<tr>"
 [57]         rDBResult.MoveTo(iRecord)
 [58]
 [59]         For iField = 0 To rDBResult.Fields.Count - 1
 [60]           If rDBResult.Fields[iField].Name = "gebdatum" Then
 [61]             sHTML &= "<td>" & Format(rDBResult[iField], "dd.mm.yyyy") & "</td>"
 [62]           Else
 [63]             sHTML &= "<td>" & rDBResult[iField] & "</td>"
 [64]           Endif
 [65]         Next '-- Column
 [66]         sHTML &= "</tr>"
 [67]       Next   '-- DB-Record
 [68]
 [69]       sHTML &= "</table>"
 [70]       sHTML &= gb.Lf
 [71]
 [72]     Endif
 [73]
 [74] '-- Ausgabe des kompletten HTML als HTML-Block
 [75]     Return sHTML
 [76]
 [77]     Catch
 [78]     Return Error.Text
 [79]
 [80] End

Kommentar

  • Die Datenbasis für den Report ist die (SQLite-)Datenbank contacts.sqlite (Zeilen 14 bis 16) mit der Datenbank-Tabelle contacts.
  • Es werden alle Felder der Datenbank-Tabelle contacts (Zeile 27/29) ausgelesen.
  • In den Zeilen 40 und 43 stehen Inline-CSS-Anweisungen, die noch nicht in eine CSS-Datei im CSS-StyleSheet übernommen worden sind.
  • Die Verarbeitung der Datenbankdaten erfolgt in den Zeilen 39 bis 72.
  • In der Zeile 61 wird das Geburtsdatum formatiert ausgegeben.

DATABASE

Abbildung 24.6.2.4.6: (SQLite-)Datenbank-Report (Ausschnitt)

24.6.2.4.3.5 Template-Datei IncFormular.webpage

An dieser Stelle werden nur ein bestimmtes Formular, die Verarbeitung der Formulardaten sowie deren Auswertung beschrieben. Die Struktur von Formularen und die Syntax von (HTML-)Formularen sowie deren Felder sind nicht Gegenstand dieser Beschreibung. Dem interessierten Leser sei die Recherche selbst nahegelegt. Ein guter Startpunkt ist https://wiki.selfhtml.org/wiki/HTML/Tutorials/Formulare/Was_ist_ein_Webformular%3F#Buttons.

Quelltext der Webpage IncFormular.webpage:

 [1] <%
 [2]     Dim i As Integer
 [3]     Dim sField, sErrorMessage As String
 [4]     Dim vValue As Variant
 [5]     Dim aRequestFields, aFieldList As New String[]
 [6]     Dim cData, cRadioList As New Collection
 [7]
 [8]     cData.Add("off", "material")
 [9]     cData.Add("off", "confirmation_gdpr")
 [10]
 [11]     cRadioList.Add("Ubuntu", "ubuntu")
 [12]     cRadioList.Add("Mint", "mint")
 [13]     cRadioList.Add("Eine andere Distribution", "another")
 [14]
 [15]     aFieldList = ["token", "firstname", "lastname", "birthday", "email", "material",
                  "os_version", "message", "confirmation_gdpr"]
 [16]
 [17]     aRequestFields = Request.Post.Fields
 [18]
 [19]     If Request.Method = "POST" And Request.Post["token"] = "ok" Then
 [20]        For Each sField In aRequestFields
 [21]          Select sField
 [22]            Case "material"
 [23]              cData.Add("on", "material")
 [24]            Case "confirmation_gdpr"
 [25]              cData.Add("on", "confirmation_gdpr")
 [26]            Case "message"
 [27]               If Request.Post[sField] = "" Then
 [28]                  cData.Add("empty", "message")
 [29]               Else
 [30]                  cData.Add(Request.Post[sField], sField)
 [31]               Endif
 [32]            Default
 [33]              cData.Add(Request.Post[sField], sField)
 [34]          End Select
 [35]        Next
 [36]
 [37]        For Each vValue In cData
 [38]          Select Case cData.Key
 [39]            Case "confirmation_gdpr"
 [40]              If Html(vValue) = "off" Then
 [41]                 sErrormessage = "Ohne Ihre Einwilligung zur Erfassung, Speicherung ... .<br><br>"
 [42]              Endif
 [43]          End Select
 [44]        Next
 [45]
 [46]        If sErrorMessage = "" Then
 [47] %>
 [48]           <br>
 [49]           <h3>Anmeldung zum Gambas-Grundkurs</h3>
 [50]           <p>Hallo <%=cData["firstname"]%>!<br><br>Sie haben sich erfolgreich angemeldet. ... .</p>
 [51] <%
 [52]        Else
 [53] %>
 [54]           <h3>Hinweis zur Online-Anmeldung zum Gambas-Grundkurs</h3>
 [55] <%
 [56]           Print sErrorMessage
 [57]           Print "<br>"
 [58] %>
 [59]           <button onclick=" history.back()">Zurück zum Formular</button>
 [60] <%
 [61]        Endif
 [62]     Else
 [63] %>
 [64]        <h1>Anmeldung zum Gambas-Grundkurs</h1>
 [65]        <p></p>
 [66]
 [67]        <form action=<%=Application.Root%>?Formular method="post" accept-charset="UTF-8">
 [68]
 [69]          <fieldset>
 [70]            <legend>Persönliche Daten</legend>
 [71]              <!-- Verstecktes Feld zum Nachweis, dass die Daten aus diesem Formular stammen -->
 [72]              <input type="hidden" id="token" name="token" value="ok">
 [73]
 [74]              <label for="firstname">Ihr Vorname</label>
 [75]              <input type="text" id="firstname" name="firstname" required autofocus>
 [76]
 [77]              <label for="lastname">Ihr Nachname</label>
 [78]              <input type="text" id="lastname" name="lastname" required>
 [79]
 [80]              <label for="birthday">Ihr Geburtsdatum (optional)</label>
 [81]              <input type="date" id="birthday" name="birthday">
 [82]
 [83]              <label for="email">Ihre EMail-Adresse</label>
 [84]              <input type="email" id="email" name="email" required>
 [85]          </fieldset>
 [86]
 [87]          <fieldset>
 [88]            <legend>Kursmaterial</legend>
 [89]            <input type="checkbox" id="material" name="material">
 [90]            <label>Soll das Kurs-Material schon vor dem Kurs zugeschickt werden?</label>
 [91]          </fieldset>
 [92]
 [93]          <fieldset>
 [94]            <legend>Welche Linux-Distribution nutzen Sie aktuell?</legend>
 [95]            <div class="radiobox">
 [96]              <input type="radio" id="ubuntu" name="os_version" value="ubuntu">
 [97]              <label>Ubuntu</label>
 [98]            </div>
 [99]            <div class="radiobox">
 [100]              <input type="radio" id="mint" name="os_version" value="mint" checked="checked">
 [101]              <label>Mint</label>
 [102]            </div>
 [103]            <div class="radiobox">
 [104]              <input type="radio" id="another" name="os_version" value="another">
 [105]              <label>Eine andere Distribution</label>
 [106]            </div>
 [107]          </fieldset>
 [108]
 [109]          <fieldset>
 [110]            <legend>Grundkurs</legend>
 [111]            <label for="message">Ihre Nachricht an die Kursleitung (optional)</label>
 [112]            <textarea id="message" name="message"></textarea>
 [113]          </fieldset>
 [114]
 [115]          <fieldset>
 [116]            <legend>DSGVO</legend>
 [117]            <!-- General Data Protection Regulation (gdpr) - Datenschutz-Grundverordnung -->
 [118]            <input type="checkbox" id="confirmation_gdpr" name="confirmation_gdpr" checked>
 [119]            <label>Mit der Nutzung dieses Formulars erklären Sie sich mit der Erfassung, Speicherung und Verarbeitung Ihrer Daten bis zum Abschluss des Kurses einverstanden.</label>
 [120]          </fieldset>
 [121]
 [122]          <button type="submit">Zum Gambas-Kurs verbindlich anmelden</button>
 [123]
 [124]        </form>
 [125] <%
 [126]      Endif
 [127] %>
 [128]      <br>

Kommentar

  • Zuerst werden in einem Gambas-Block Variablen definiert (Zeilen 2 bis 6) und teilweise mit geeigneten Werten (Zeilen 8 bis 17) initialisiert.
  • Dann wird beim Aufruf der Webseite 'Formular' in der Zeile 19 ermittelt, ob bereits Formulardaten gesendet worden sind oder nicht.
  • Fall 1: Es wurden noch keine Formulardaten gesendet, was beim ersten Aufruf der Webseite `Formular` immer gegeben ist. Deshalb wird das leere Formular zum Ausfüllen angezeigt. Anschließend kann das Formular abgeschickt werden. Voraussetzungen: Alle verbindlichen Felder enthalten Werte und diese Werte sind gültig. Daher ist bei den Feldern klar zu beschreiben, ob eine Eingabe zwingend erforderlich ist (Markierung mit * und dann Erklärung zu *) oder nicht. In letzterem Fall kennzeichnen Sie das Feld mit `Eingabe optional` wie beim Geburtsdatum oder der Nachricht an die Kursleitung. Dann sind alle anderen Formular-Felder verpflichtend auszufüllen.
  • Fall 2: Es wurden Formulardaten mit der Post-Methode gesendet und der Wert im versteckten Feld `token` hat den Wert 'ok'. Mit dem Wert 'ok' wird sicher gestellt, dass die gesendeten Formulardaten tatsächlich aus dem Formular stammen. Die Namen der einzelnen Formularfelder sind im String-Array Request.Post.Fields gespeichert. Die zu den Feldern gehörenden Werte können mit feldwert = Request.Post[feldname] ausgelesen werden und mit dem Feldnamen sowie dem Feldwert (Value) in einer Collection gespeichert werden. Damit haben Sie etwa die Möglichkeit, die Werte der einzelnen Formularfelder zu verarbeiten und auszuwerten, um zum Beispiel ausgewählte Daten aus dem Formular in einer Datenbank-Tabelle abzuspeichern. Oder Sie legen nach der Auswertung das nur teilweise ausgefüllte Formular dem Nutzer noch einmal vor für den Fall, dass – wie in unserem Fall – die notwendige Zustimmung zur Erfassung, Speicherung und Verarbeitung der Daten bis zum Abschluss des Kurses noch fehlt, indem sich das Formular selbst aufruft oder Sie geben eine Meldung heraus, die den Nutzer über das erfolgreiche Senden der geforderten Daten informiert:

QUITTUNG

Abbildung 24.6.2.4.7: Formular-Quittung

Hinweise

Formular-Felder vom Typ 'radio' und 'checkbox' sind mit besonderer Sorgfalt auszuwerten. Der Grund liegt darin, dass Feldnamen von diesen Typen nicht in das String-Array Request.Post.Fields aufgenommen werden, wenn sie nicht ausgewählt oder markiert wurden! Ein leeres Text-Feld dagegen wird mit dem Feldnamen in das String-Array Request.Post.Fields aufgenommen, aber einem leeren String als Feldwert.

Beispiel:

Das Formular im Projekt `webapp4` hat 9 Formular-Felder – eines davon vom Typ 'hidden' mit dem festen Feldwert 'ok'. Die Formular-Felder `material`, `confirmation_gdpr` (Typ 'checkbox') und `os_version` (Typ 'radio') werden nicht ausgewählt und das (Text-)Feld `message` bleibt leer.

Lassen Sie sich nach dem Abschicken des Formulars die Feldnamen und Feldwerte aller Formularfelder ausgeben:

aRequestFields = Request.Post.Fields

If Request.Method = "POST" And Request.Post["token"] = "ok" Then
   For i = 0 To aRequestFields.Max
     Print "Field " & (i+1) & " => " & aRequestFields[i] & " --->  Field_Value = " & Html(Request.Post[aRequestFields[i]]) & "<br>"
   Next
   ...
EndIf

ergibt sich exemplarisch diese Liste mit den Feldnamen und deren Feldwerte:

Field 1 => token 		---> Field_Value = ok
Field 2 => firstname 	        ---> Field_Value = Klaus
Field 3 => lastname 		---> Field_Value = Mayer
Field 4 => birthday 		---> Field_Value = 1999-11-03
Field 5 => email 		---> Field_Value = klaus.mayer.99@web.de
Field 6 => message 		---> Field_Value =

Es fehlen 3 Felder in Request.Post.Fields und damit in der Feldliste! Ein Ansatz, um diesen Mangel zu beheben besteht darin, eine Variable cData vom Typ Collection zu definieren und mit passenden Werten zu initialisieren:

cData.Add("off", "material")
cData.Add("off", "confirmation_gdpr")

In einer Kontrollstruktur werden alle Felder in Request.Post.Fields ausgelesen und passende Werte zugewiesen:

    aRequestFields = Request.Post.Fields

    If Request.Method = "POST" And Request.Post["token"] = "ok" Then
       For Each sField In aRequestFields
         Select sField
           Case "material"
             cData.Add("on", "material")
           Case "confirmation_gdpr"
             cData.Add("on", "confirmation_gdpr")
           Case "message"
              If Request.Post[sField] = "" Then
                 cData.Add("empty", "message")
              Else
                 cData.Add(Request.Post[sField], sField)
              Endif
           Default
             cData.Add(Request.Post[sField], sField)
         End Select
       Next
  • Fehlt zum Beispiel das Feld `material` vom Typ 'checkbox', dann greift die Initialisierung mit cData.Add(„off“, „material“). Wurde dagegen für das Feld `material` die Checkbox angekreuzt, dann wird der Wert mit cData.Add(„on“, „material“) mit 'on' überschrieben. Ähnliches gilt für das Feld `confirmation_gdpr`.
  • Für ein leeres Feld `message` wird der Wert 'empty' in der Collection gespeichert, sonst der Text.
  • Für alle anderen Felder wird das existierende Wert-Feld-Paar gespeichert.

Damit besitzt jedes Feld einen Wert. So können Sie sich zur Kontrolle alle 9 Schlüssel-Wert-Paare der Collection `cData` anzeigen lassen:

For Each vValue In cData
  Print cData.Key & "   " & String.Chr(187) & "   " & Html(vValue) & "<br>"
Next

Ausgabe in der IDE-Konsole:

material 		» off
confirmation_gdpr 	» off
token 			» ok
firstname 		» Klaus
lastname 		» Mayer
birthday 		» 1999-11-03
email 			» klaus.mayer.99@web.de
os_version 	        » mint
message 		» empty

Für Felder vom Typ 'radio' wird folgender Weg vorgeschlagen: Da Radio-Button eine Gruppe von beschrifteten Button sind, von denen der Anwender genau einen auswählen kann, wird eine bestimmte Auswahl über das checked-Attribut mit checked=„checked“ vorselektiert. Damit wird das Feld 'os_version' stets im String-Array Request.Post.Fields vorhanden sein:

   <fieldset>
     <legend>Welche Linux-Distribution nutzen Sie aktuell?</legend>
     <div class="radiobox">
       <input type="radio" id="ubuntu" name="os_version" value="ubuntu">
       <label>Ubuntu</label>
     </div>
     <div class="radiobox">
       <input type="radio" id="mint" name="os_version" value="mint" checked="checked">
       <label>Mint</label>
     </div>
     <div class="radiobox">
       <input type="radio" id="another" name="os_version" value="another">
       <label>Eine andere Distribution</label>
     </div>
   </fieldset>

Diese vorgegebene Auswahl kann der Anwender allerdings jederzeit ändern.

Um sicherzustellen, dass alle als verpflichtend ausgewiesenen Felder auch tatsächlich mit einem Wert ausgefüllt wurden, gibt es zwei Strategien. Eine prüft erst nach dem Absenden des Formulars, ob zu dem Feld auch ein Wert existiert und legt dann dem Nutzer das teilweise ausgefüllte Formular so lange mit einem passenden Kommentar vor, bis alle Werte vorliegen. Die andere besteht darin, ausgewählte Formular-Attribute zu verwenden. Pflichtfelder erhalten das required-Attribut:

<input type="text" id="firstname" name="firstname" required autofocus>

Solange die Eingaben nicht valide sind, wird ein Absenden des Formulars verhindert und eine Meldung ausgegeben wie „Bitte füllen Sie dieses Feld aus“.

Zusätzlich können Sie für ausgewählte Felder wie (Text-)Felder die Attribute 'pattern' und 'title' verwenden, wobei für das Attribut 'pattern' in den folgenden zwei Beispielen reguläre Ausdrücke verwendet werden:

pattern="^[A-Za-z]+$" title="Nur Buchstaben sind gültige Zeichen!"

oder bei einem Eingabefeld für eine EMail-Adresse:

pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" title="Muster: localpart@domain.tld"

Der Text des Titels erscheint als Tool-Tipp, wenn Sie mit der Maus einen Augenblick über dem Feld bleiben.

24.6.2.4.3.6 Template-Datei IncFPlotter.webpage

Der Funktionsplotter ist eine Adaption des JS-Plotterbeispiels auf der Webseite https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Funktionsplotter. Angegeben wird der komplette Quelltext für die Erzeugung der Graphen von drei (unterschiedlichen) Funktionen, die Sie frei definieren können oder aus der Liste der vordefinierten Funktionen auswählen:

 [1]   <!-- Functionality of the plotter -->
 [2]   <script src="./js/pl.cs.js" charset="utf-8"></script>
 [3]   <script src="./js/pl.plot.js" charset="utf-8"></script>
 [4]   <script src="./js/pl.plotter.js" charset="utf-8"></script>
 [5]
 [6]   <h1>Funktionsplotter</h1>
 [7]
 [8]   <figure id="plotarea"></figure>
 [9]   <div hidden id="wertetabelle" aria-live="polite"></div>
 [10]
 [11]   <fieldset id="plotter">
 [12]     <div aria-live="polite">
 [13]       <label id="f1">f<sub>1</sub>(x) = <input type="text" id="fkt1" value="sin(x)/x"></label>
 [14]       <label id="f2">f<sub>2</sub>(x) = <input type="text" id="fkt2" value="sin(x)"></label>
 [15]       <label id="f3">f<sub>3</sub>(x) = <input type="text" id="fkt3" value="cos(x)"></label>
 [16]     </div>
 [17]     <div>
 [18]       <label style="padding-left: 1rem">x<sub>min</sub> = <input type="number" step="any" id="idxmin" value="-6.8"></label>
 [19]       <label style="padding-left: 2rem">x<sub>max</sub> = <input type="number" step="any" id="idxmax" value="7.8"></label>
 [20]       <button style="padding-left: 1rem" id="plotbutton">Funktionsschar zeichnen</button>
 [21]     </div>
 [22]   </fieldset>
 [23]
 [24]   <p id="vdeffkt">Vordefinierte Funktionen:<br>
 [25]     <button>AM</button>,
 [26]     <button>PM</button>,
 [27]     <button>sin(x)/x</button>,
 [28]     <button>sinh</button>,
 [29]     <button>cosh</button>,
 [30]     <button>tanh</button> und
 [31]     <button>Puls</button>.
 [32]   </p>
 [33]
 [34]   <p id="jsfkt">Javascript unterstützt die folgenden Funktionen:<br>
 [35]     <button>abs</button>,
 [36]     <button>acos</button>,
 [37]     <button>asin</button>,
 [38]     <button>atan</button>,
 [39]     <button>cos</button>,
 [40]     <button>exp</button>,
 [41]     <button>log</button>,
 [42]     <button>pow</button>,
 [43]     <button>sin</button>,
 [44]     <button>sqrt</button> und
 [45]     <button>tan</button>.
 [46]   </p>
 [47]   <p>Bitte den Definitionsbereich der Funktionen beachten!</p>
 [48]   <hr>
 [49]   <p style="font-size: 0.9rem; color: gray;">Der Funktionsplotter ist eine Adaption des JS-Plotterbeispiels auf der Webseite  https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Funktionsplotter</p>

Die komplette Funktionalität des Plotters steckt in drei JavaScript-Skripten. Den Style der Funktionsbilder können geändert werden, wenn Sie die entsprechenden JavaScript-Skripte verändern.

PLOTTER

Abbildung 24.6.2.4.8: Funktionsbilder in einem besonderen Style

24.6.2.4.4 Übertragung der Web-Applikation auf den Webserver

Die Webseiten des Projektes 4 wurden beim Autor auf seinem Arbeitsplatz-Computer entwickelt. Auf diesem wurde auch der Webserver Lighttpd installiert und konfiguriert. Da die Webseiten auch im Intranet aufgerufen werden sollen, wurde nach einer Möglichkeit gesucht, die ausführbare Gambas-Datei index.gambas als Webserver-Programm sowie die benötigten Ressourcen-Dateien aus dem Projekt-Ordner `webapp4` in den Web-Ordner '/usr/lib/cgi-bin/webapp3' auf dem Arbeitsplatz-Computer zu kopieren:

hans@pc:~/GB3BUCH/24K_NetzwerkN/24.6.2.4_WP4/BuchProjekt/webapp4$
.
├── index.gambas
├── .public
│   ├── audiovideo
│   ├── css
│   ├── db
│   ├── favicon
│   ├── icons
│   ├── images
│   └── js
...

hans@pc:/usr/lib/cgi-bin/webapp4$
.
├── index.gambas
├── audiovideo
├── css
├── favicon
├── icons
├── images
├── js
└── .public
    └── db

Sie können die erforderlichen Ordner und Dateien mit erhöhten Rechten im Dateimanager kopieren oder nutzen das folgende Bash-Skript:

#!/bin/bash
#
# -- Definition of colour values in the terminal
#--------------------------------------------------------------------------------------
RE="\033[0;31m"                 # red
GR="\033[0;32m"                 # green
BL="\033[0;34m"                 # blue
REB="\033[1;31m"                # red bold
GRB="\033[1;32m"                # green bold
BLB="\033[1;34m"                # blue bold
FGB="\033[1m\033[42m\033[37m"   # bold + withe + green background
NO="\033[0m"                    # normal
#--------------------------------------------------------------------------------------

if [ -z "$1" ]; then
   echo "ERROR! The parameter string is an empty string."
   exit 99
else
   pass=$1
fi

echo
webserver="lighttpd"
echo "WEBSERVER = ${webserver}"

target_basic_path="/usr/lib/cgi-bin"
echo "TARGET-BASIC-PATH = ${target_basic_path}"

pwd="${PWD##*/}"
echo "PWD = ${pwd}"

target_site_path=${target_basic_path}/${pwd}
echo "TARGET-SITE-PATH = ${target_site_path}"

#IP address of the local (web) server
ipaddress="192.168.0.4"
echo "IP-ADDRESS = ${ipaddress}"

source_path=$(pwd)
echo "SOURCE-PATH = ${source_path}"

output=$(ping -c 1  ${ipaddress})

substring="min/avg/max/mdev"

if [[ ${output} =~ ${substring} ]]; then
   echo
   echo -e "${BLB}» The web server on the intranet with the IP address '${ipaddress}' can be reached.${NO}"
 #  echo
else
   echo
   echo -e "${REB}» ERROR\n» The web server in the intranet with IP '${ipaddress}' is not accessible!${NO}"
   echo
   exit 99
fi

#--------------------------------------------------------------------------------------

echo ${pass} | sudo -S mkdir ${target_site_path} 2>/dev/null
echo ${pass} | sudo -S chmod 777 ${target_site_path}

echo -e "${BLB}» The directories and files are copied ...${NO}"
echo

echo ${pass} | sudo -S cp ${source_path}/index.gambas ${target_site_path}

cd ${source_path}/.public/audiovideo
find . -print | cpio -pdmu ${target_site_path}/audiovideo

cd ${source_path}/.public/css
find . -print | cpio -pdmu ${target_site_path}/css

cd ${source_path}/.public/favicon
find . -print | cpio -pdmu ${target_site_path}/favicon

cd ${source_path}/.public/icons
find . -print | cpio -pdmu ${target_site_path}/icons

cd ${source_path}/.public/images
find . -print | cpio -pdmu ${target_site_path}/images

cd ${source_path}/.public/js
find . -print | cpio -pdmu ${target_site_path}/js

cd ${source_path}/.public/db
find . -print | cpio -pdmu ${target_site_path}/.public/db

echo ${pass} | sudo -S chmod 755 ${target_site_path}

#--------------------------------------------------------------------------------------

echo
echo -e "${REB}Continue with <ENTER>${NO}"
read e

Der Aufruf des Bash-Skriptes beim Autor erfolgt im Projektordner in einer Konsole:

hans@pc-a-mint20:~/GB3BUCH/24K_NetzwerkN/24.6.2.4_WP4/BuchProjekt/webapp4$ ./cpwp2server.sh <user.passwort>

WEBSERVER = lighttpd
TARGET-BASIC-PATH = /usr/lib/cgi-bin
PWD = webapp4
TARGET-SITE-PATH = /usr/lib/cgi-bin/webapp4
IP-ADDRESS = 192.168.0.4
SOURCE-PATH = /home/hans/GB3BUCH/24K_NetzwerkN/24.6.2.4_WP4/BuchProjekt/webapp4

» The web server on the intranet with the IP address '192.168.0.4' can be reached.
» The directories and files are copied ...

27373 Blöcke
19 Blöcke
11 Blöcke
87 Blöcke
2268 Blöcke
203 Blöcke
44 Blöcke

Continue with <ENTER>

hans@pc-a-mint20:~/GB3BUCH/24K_NetzwerkN/24.6.2.4_WP4/BuchProjekt/webapp4$

24.6.2.4.5 Aufruf der Webseiten

Danach können Sie die Webseiten im Intranet vom Webserver abrufen und in Ihrem Webbrowser anzeigen:

http://192.168.0.4/cgi-bin/webapp4/index.gambas

Download

Die Website verwendet zwei temporäre Session-Cookies. Diese technisch notwendigen Cookies werden gelöscht, wenn der Web-Browser geschlossen wird! Informationen zu Cookies erhalten Sie in der Datenschutzerklärung.
k24/k24.6/k24.6.2/k24.6.2.4/start.txt · Zuletzt geändert: 21.02.2023 (Externe Bearbeitung)

Seiten-Werkzeuge