User Tools

Site Tools


Sidebar

Network and communication

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

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

  • In lines 39, 41, 44 and 46, the placeholders for the header, navigation, content and footer areas are updated depending on the requested website.
  • In contrast to the `webapp3` web project, the placeholder for the header (line 39) is not given a string “Create web pages with Gambas webpage”. The corresponding text is inserted directly in the file IncHeader.webpage (line 4):
 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

  • In a select case control structure (<%Select Request.Query … %>…<%End Select%>) in lines 2 to 21, the content for the 'Content' area of the requested web page is generated by replacing the placeholder «IncFPlotter» with the corresponding HTML source code, such as for the web page FPlotter.
  • As the URL parameter is empty when the web pages are first called up, the content for the 'Start' area of the start page is automatically generated (line 20). Only then does the creation of the menu with the appropriate URL parameters in the 9 links in the navigation take effect.

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

  • In line 5, the text output by the JavaScript function 'set_time' is displayed in css format as the current time.
  • The text is regenerated in the web browser every second by the JS timer implemented in the set_time.js JavaScript script.

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

  • Note the equals sign in front of the Format() function!
  • The Gambas class file IncDate.class is empty.

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

  • The CSS instructions in lines 8, 18 and 27 ensure the same style for all three multimedia elements in the respective enclosing DIV container.
  • A description/caption is displayed in the figcaption tag for all three multimedia elements in lines 9, 19 and 28.
  • While the image is displayed immediately, only the appropriate control elements are displayed for the sound and video file, through which the sound or video is played after clicking on the start button.

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

  • The database for the report is the (SQLite) database contacts.sqlite (lines 14 to 16) with the database table contacts.
  • All fields of the database table contacts (lines 27/29) are read.
  • Lines 40 and 43 contain inline CSS instructions that have not yet been transferred to a CSS file in the CSS StyleSheet.
  • The database data is processed in lines 39 to 72.
  • The date of birth is formatted in line 61.

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

  • First, variables are defined in a Gambas block (lines 2 to 6) and partially initialized with suitable values (lines 8 to 17).
  • Then, when the web page 'Form' is called up in line 19, it is determined whether form data has already been sent or not.
  • Case 1: No form data has yet been sent, which is always the case when the 'Form' web page is called up for the first time. Therefore, the empty form is displayed for completion. The form can then be sent. Prerequisites: All mandatory fields contain values and these values are valid. It must therefore be clearly described for the fields whether an entry is mandatory (marked with * and then explanation of *) or not. In the latter case, mark the field with 'Input optional' as with the date of birth or the message to the course management. Then all other form fields are mandatory.
  • Case 2: Form data was sent using the post method and the value in the hidden field `token` has the value 'ok'. The value 'ok' ensures that the form data sent actually originates from the form. The names of the individual form fields are stored in the Request.Post.Fields string array. The values associated with the fields can be read with fieldvalue = Request.Post[fieldname] and saved with the field name and the field value (Value) in a collection. This allows you to process and evaluate the values of the individual form fields, for example to save selected data from the form in a database table. Or you can present the partially completed form to the user again after the evaluation in the event that - as in our case - the necessary consent for the collection, storage and processing of the data is still missing until the course is completed by calling up the form itself or you can issue a message informing the user that the required data has been successfully sent:

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
  • If, for example, the field 'material' of type 'checkbox' is missing, then the initialization with cData.Add(“off”, “material”) takes effect. If, on the other hand, the checkbox was selected for the field 'material', the value is overwritten with 'on' using cData.Add(“on”, “material”). The same applies to the field `confirmation_gdpr`.
  • For an empty field `message`, the value 'empty' is saved in the collection, otherwise the text.
  • The existing value-field pair is saved for all other fields.

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

The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k24/k24.6/k24.6.2/k24.6.2.4/start.txt · Last modified: 07.04.2024 by emma

Page Tools