Table of Contents

24.6.2.4 Project 4

In the fourth project `webapp4`, a further 6 websites are created as an extension of the `webapp3` project on the basis of the Webpage class. You can see the website with a (SQLite) database report here:

DB-REPORT

Figure 24.6.2.4.1: (SQLite) database report (excerpt)

24.6.2.4.1 Template file Main.webpage

The webpage Main.webpage is also the most important file of the template in this project, as it contains a Gambas block at the beginning for reading the language set in the web browser and the requested website and then the head area with a placeholder. This is followed by HTML with further placeholders for the layout areas header, navigation, content and 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>

The Gambas class file main.class contains an extended list of the currently available websites, which is saved in the variable `SiteList`:

' Gambas class file

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

Comment

 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 file IncContent.webpage

The webpage IncContent.webpage contains, among other things, 9 placeholders that are replaced by the content of the individual webpages depending on the requested webpage (request query).

 [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 -->

The Gambas class file IncContent.class is empty.

Comment

Note:

The content of the webpage IncNavigation.webpage is the same as in the web project `webapp3` and is adopted 1:1.

24.6.2.4.3 Extensions

In the following six paragraphs, the HTML source text for the 'Content' area of the web pages Time, Date, Multimedia, DBReport, Form and FPlotter is specified and commented.

24.6.2.4.3.1 Template file IncTime.webpage

The webpage IncTime.webpage contains a placeholder (line 5) for the current time to be inserted:

 [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>

The Gambas class file IncTime.class is empty.

Comment

UHRZEIT

Figure 24.6.2.4.2: Display of the current time

24.6.2.4.3.2 Template file IncDate.webpage

The webpage IncDate.webpage contains a placeholder for the date to be inserted in a specific format in line 5:

 [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>

Comment

24.6.2.4.3.3 Template file IncMultimedia.webpage

What would a website be without images and other multimedia elements such as sound or video? Exactly these three elements are inserted into the website IncMultimedia.webpage one after the other:

 [1] <h1>Multimedia</h1>
 [2]
 [3] <!-- INSERT IMAGE  -->
 [4] <div class="thin-box">
 [5]   <h3>Insert images flexibly</h3>
 [6]   <hr>
 [7]   <figure>
 [8]     <img src="./images/tom_780x1012.png" alt="Tom" width="343" height="445">
 [9]     <figcaption>Tom at the rock concert in Berlin</figcaption>
 [10]   </figure>
 [11] </div>
 [12] <!-- INSERT AUDIO -->
 [13] <div class="thin-box">
 [14]   <h3>Insert audio files</h3>
 [15]   <hr>
 [16]   <figure>
 [17]     <!-- Display control elements and load metadata -->
 [18]     <audio src="./audiovideo/tom.mp3" type="audio/mp3" controls></audio>
 [19]     <figcaption>Singer: Tom -> The Berliner</figcaption>
 [20]   </figure>
 [21] </div>
 [22] <!-- INSERT VIDEO -->
 [23] <div class="thin-box">
 [24]   <h3>Insert video files</h3>
 [25]   <hr>
 [26]   <figure>
 [27]     <video src="./audiovideo/viehscheid.mp4" controls></video>
 [28]     <figcaption>Cattle drive in Gunzesried (Allgäu)</figcaption>
 [29]   </figure>
 [30] </div>

Comment

TOM

Figure 24.6.2.4.3: Image display

SOUND

Figure 24.6.2.4.4: Sound control elements

VIDEO

Figure 24.6.2.4.5: Video controls (and footer)

The Gambas class file IncMultimedia.class is empty.

24.6.2.4.3.4 Template file IncDBReport.webpage

The webpage IncDBReport.webpage is remarkably short and contains a placeholder for the database report to be inserted:

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

The generation of the (SQLite) database report is outsourced to the Gambas class file IncDBReport.class:

 [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] '-- Output of the complete HTML source text as an HTML block
 [75]     Return sHTML
 [76]
 [77]     Catch
 [78]     Return Error.Text
 [79]
 [80] End

Comment

DATABASE

Figure 24.6.2.4.6: (SQLite) database report (excerpt)

24.6.2.4.3.5 Template file IncFormular.webpage

Only one specific form, the processing of the form data and its evaluation are described here. The structure of forms and the syntax of (HTML) forms and their fields are not the subject of this description. Interested readers are advised to do their own research. A good starting point is https://wiki.selfhtml.org/wiki/HTML/Tutorials/Formulare/Was_ist_ein_Webformular%3F#Buttons.

Source code of the 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>

Comment

QUITTUNG

Figure 24.6.2.4.7: Form receipt

Notes

Form fields of type 'radio' and 'checkbox' must be evaluated with particular care. The reason for this is that field names of these types are not included in the Request.Post.Fields string array if they have not been selected or marked! An empty text field, on the other hand, is included in the Request.Post.Fields string array with the field name, but an empty string as the field value.

Example:

The form in the `webapp4` project has 9 form fields - one of them of type `hidden` with the fixed field value `ok`. The form fields `material`, `confirmation_gdpr` (type `checkbox`) and `os_version` (type `radio`) are not selected and the (text) field `message` remains empty.

After submitting the form, display the field names and field values of all form fields:

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

results in this exemplary list with the field names and their field values:

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 =

3 fields are missing in Request.Post.Fields and therefore in the field list! One approach to rectify this shortcoming is to define a variable cData of type Collection and initialize it with suitable values:

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

In a control structure, all fields in Request.Post.Fields are read out and assigned suitable values:

    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

This means that each field has a value. This allows you to display all 9 key-value pairs of the collection `cData` for checking purposes:

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

Output in the IDE console:

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

The following method is suggested for fields of type 'radio': As radio buttons are a group of labeled buttons from which the user can select exactly one, a specific selection is preselected via the checked attribute with checked=“checked”. This means that the 'os_version' field will always be present in the Request.Post.Fields string array:

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

However, the user can change this default selection at any time.

There are two strategies to ensure that all fields marked as mandatory have actually been filled in with a value. One is to first check whether a value exists for the field after the form has been sent and then present the partially completed form to the user with a suitable comment until all values are available. The other is to use selected form attributes. Mandatory fields are given the required attribute:

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

As long as the entries are not valid, the form is prevented from being sent and a message such as “Please complete this field” is displayed.

In addition, you can use the 'pattern' and 'title' attributes for selected fields such as (text) fields, whereby regular expressions are used for the 'pattern' attribute in the following two examples:

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

or for an input field for an email address:

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

The text of the title appears as a tool tip if you hover the mouse over the field for a moment.

24.6.2.4.3.6 Template file IncFPlotter.webpage

The function plotter is an adaptation of the JS plotter example on the website https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Funktionsplotter. The complete source code for generating the graphs of three (different) functions is provided, which you can define freely or select from the list of predefined functions:

 [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>

The complete functionality of the plotter is contained in three JavaScript scripts. The style of the function screens can be changed if you change the corresponding JavaScript scripts.

PLOTTER

Figure 24.6.2.4.8: Function screens in a special style

24.6.2.4.4 Transferring the web application to the web server

The web pages of project 4 were developed by the author on his workstation computer. The Lighttpd web server was also installed and configured on this computer. Since the web pages are also to be accessed on the intranet, a way was found to copy the executable Gambas file index.gambas as a web server program and the required resource files from the project folder `webapp4` to the web folder '/usr/lib/cgi-bin/webapp3' on the workstation computer:

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

You can copy the required folders and files with elevated rights in the file manager or use the following bash script:

#!/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

The bash script is called by the author in the project folder in a console:

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 Calling up the web pages

You can then call up the web pages on the intranet from the web server and display them in your web browser:

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

Download

Project

Download