Sorry, vertaling naar het Nederlands moet nog worden afgemaakt!
Website ontwerp structuur en twee talen (Aug 2020)
17-Nov-20: Logo toegevoegd van de green webfoundation aan de index en onderwerp pagina's. Het logo staat in de page link area aan de rechter kant, dus alleen zichtbaar voor het breedste scherm.
25-Aug-20: Website layout stelt zich nu in op de schermbreedte van de browser window. Er zijn 3 verschillende layouts waar tussen geschakeld wordt, zie sectie hieronder over website layout design. Bekijk zelf het resultaat door het browser window aan te passen. Zie ook sectie Media query.
- Groot scherm (breedte > 1400px). Deze heeft het menu aan de linker zijde, inhoud in het midden en ruimte voor een pagina menu aan de rechterzijde. Bovenaan een koptekst.
- Gemiddeld scherm (900 < breedte < 1400px. Deze heeft het menu bovenaan om meer ruimte te maken voor de inhoud. De ruimte voor het pagina menu is hier weggelaten.
- Klein scherm (breedte < 900px). Deze heeft een dubbele rij menu knoppen boven het scherm, gevold door een koptekst en daaronder de inhoud.
22-Aug-20: Gebruik CSS grid voor de site layout. Toegevoegd in deze pagina enkele (onverwachte) test resultaten met de CSS grid.
16-Aug-20: Gestart met gebruiken van prism, zie prismjs.com, om de opgenomen code in te kleuren voor een betere leesbaarheid van CSS, HTML, Javascript, PHP en Visual Basic. Zie ook sectie Code markering prism beneden voor mijn implementatie hiervan.
17-Jul-20: Herontwerp site menu. Gebruik gemaakt van flex box voor het site menu.
Inhoudsopgave
Folder structuur
Omdat ik verschillende en grotendeels onafhankelijke onderwerpen heb voor de website, besloot ik al in een vroeg stadium om elke categorie / onderwerp een eigen map te geven. Voor onderdelen die door meerdere onderwerpen worden gebruikt heb ik een map gemaakt met de naam 'General'. Momenteel bevinden zich in de map General de CSS (cascading style sheet), Javascript en PHP (Hypertext Preprocessor) bestanden. Deze worden in de secties hieronder verder toegelicht. Voor onderwerpen die deel-onderwerpen bevatten, heb ik sub-mappen gemaakt om alles netjes bij elkaar te houden.
Sommige van mijn onderwerpen waren aanvankelijk in de Nederlandse taal opgesteld en sommige in het Engels. De naam van de mappen is daarom een mix van Nederlands en Engels, een en ander afhankelijk van de taal waarin het onderwerp in eerste instantie is gemaakt. De map naam is zichtbaar voor de gebruiker in de url in de adresbalk. Een gebruiker kan dus een map naam zien in een voor hem vreemde taal. Bijvoorbeeld "rjut.nl/Stamboom/heritage.en.html" voor een niet nederlandse gebruiker. Voor mij is dit acceptabel. Ik maak ook duidelijk op de webpagina in welk deel van de site de gebruiker momenteel is. Dit is duidelijker zichtbaar dan de url in de adresbalk. Zie geel gemarkeerde tekst en de pagina kopteksten in de onderstaande schermafbeelding:
Website layout design
Vertaling is werk in uitvoering!
Ik wilde een eenvoudig site design met een centrale koptekst bovenaan de pagina en een menu aan de linkerkant. De inhoud in het midden and eventueel een pagina navigatie menu aan de rchterkant. Grafisch kan dat er zo uit zien:
Om dit te bereiken heb ik gebruik gemaakt van de nieuw beschikbare grid functionaliteit in CSS. Hiermee zou het makkelijker zijn om de layout te herschikken voor kleinere scherm afmetingen. Bijvoorbeeld kun je dan het menu niet meer links maar boven aan de pagina zetten zodat je meer ruimte hebt voor de inhoud. Ook de pagina snelkoppelingen aan de rechterkant kun je bijvoorbeeld weglaten voor kleine schermen:
CSS grid
Vertaling is werk in uitvoering!
Voordat ik alles op de schop gooide wilde ik eerst wat ervaring opdoen met CSS grids. Ook artikelen gelezen over grids. Zie bijvoorbeeld css-tricks.com voor een goede introductie en csswg.org voor de officiele definitie beschrijving van de CSS grid. Hierna heb ik mijn eigen test grid gemaakt dat mijn site ontwerp weergeeft:
Dit is een 5 kolom grid met 4 rijen. De eerste rij is bedoeld voor de koptekst. Het menu gebied heeft 2 kolommen. In het daadwerkelijke ontwerp van de site zal dit waarschijnlijk maar 1 kolom worden. Om dit grid te vullen met inhoud in html kun je de volgende code gebruiken:
Ik gebruik hier CSS code binnin in de HTML file om alles overzichtelijk bij elkaar te houden. In de praktijk zal de CSS code in een separate file staan. De grid is opgebouwd uit 5 kolommen van 100px breed en 4 rijen van 50px hoog. Ik gebruik het body element als container voor de grid. Binnen het body element zijn er 20 zg kinder elementen die de inhoud in het grid plaatsen. Dit gebeurd door het zogenaamde automatische plaatsing mechanisme van het grid. Ik gebruik het <span>
element voor de kinderen. Dit had ook een ander element kunnen zijn. Ik gebruik deze omdat het een zogenaamd inline element is. Let op de volgorde van de kinder elementen. Dit heeft te maken met het automatisch plaatsing mechanisme die van links naar recht en van boven naar beneden werkt. In de verkenner ziet dit er als volgt uit:
Dus hoewel het resultaat goed is, is de volgorde van coderen in de html file niet logisch.
Je kunt de richting van het automatisch plaatsing mechanisme beïnvloeden door middel van de CSS. Dit kun je doen door de volgende regel toe te voegen aan de CSS grid-auto-flow: column
. Met deze parameter en dezelfde volgorde van de inhoud in de cellen wordt de HTML code:
Het uiteindelijke resultaat is hetzelfde. Klik op de code om het in je eigen verkenner te zien. Er is dus een extra regel in de grid definitie. Let ook op de volgorde van de HTML code. Dit is dus omdat de plaatsing machine nu vertikaal werkt. Onnodig om te zeggen dat ook deze manier niet echt handig is.
Daarom begonnen om area namen te geven aan het CSS grid zodat je de inhoud makkelijker kunt positioneren. Hierbij ook de kinder elementen gereorganiseerd zodat deze logischer gegroepeerd bij elkaar staan. Dit resulteerd in de volgende code:
In de grid definitie is nu een attribuut toegevoegd grid-template-areas
. Hiermee kun je aangeven tot welk gebied een cel toebehoord. Daarnaast kun je een zg class header (.header { grid-area: header;}
) definiëren die naar dat gebied verwijst. In de HTML code ken je de betreffende kinder element toe aan de juiste klasse. Maar het result is weer niet direct wat ik had verwacht:
De elementen van dezelfde klasse/gebied staan nu achter elkaar in dezelfde cel in plaats van in afzonderlijke cellen.!
Next I tried to assign each child directly to the class of the grid area (eg <span class="header">h1</span>
). This results in the following code:
Which gives the following result:
This made it even worse!! All the elements of the same type are now stacked on top of each other in the same cell.
The following example demonstrates that you can fill multiple columns in a grid using the auto placement function. This is the HTML/CSS code:
Notice that I used grid-auto-flow: column;
for the auto placement function to work vertically. In the assignments of the class .menu, .content and .link I have now used grid-column
in stead of grid-area
. For the content class if have used line numbers in the column assignment. This to demonstrate that using an area name or line numbers gives the same result. In the HTML code. the children elements for the content, link and menu column are mixed. This to demonstrate that due to grid-auto-flow: column;
the auto place function will (re)start from the top of each column.
You could use the same to fill multiple rows. In that case you use grid-auto-flow: row;
and of course use grid-row
in the classes.
The result of Gridtest4:
Even though the menu area is 2 columns wide the m1 through m5 are all stacked in one column. m5 does not spill into the second column of the grid area in stead the grid expanded with an additional row. Notice that m1, c1 and l1 all start in the header row.
After some head scratching, re-reading the information and more testing I came to the conclusion that:
- The grid uses 4 boundaries to mark a single location / column / row / area in the grid. These are the grid-row-start, grid-column-start, grid-row-end and grid-column-end. For the auto placement function to kick in you need at least the grid-row-start and grid-row-end combination or the grid-column-start and grid-column-end combination to be auto i.e. not set. The auto placement also works when all 4 boundaries are auto i.e. not explicitly set.
- By using
grid-area : xxxx
you set all 4 boundaries at once. So the auto placement function will not kick in. - By using
grid-column: xxxx
orgrid-row: xxxx
you set only 2 boundaries and leave the others auto. This enables the auto placement function to do its work. The auto place function will use the whole row or column to place elements. Additional rows or columns will be created if there are more child elements than fit the grid. - Even though an area has several cells you refer to a named area as a whole with e.g.
grid-area: menu;
. The child element will be placed in the top left corner. - Subsequent children with a class to the same named area will either be added to the area as a whole (in case of a wrapper such as the div in gridtest3) or in the top left cell of the area (when each child refers to the area such as in gridtest3b).
- You can only define one
grid-auto-flow
direction, either column or row for one grid. This means you cannot auto fill a mix of columns and rows in a grid. - There is only one auto placement function for each grid. And it remembers the last used cell. This may be used as starting point to look for an empty cell for subsequent placements. This can give unexpected results. See for instance Gridtest4b where I changed
grid-auto-flow: column;
togrid-auto-flow: row;
. Now there are gaps in the columns. - Auto placement cannot fill a sub area (wider than 1 column or higher than 1 row) of a grid, only the whole grid.
I could not find a solution on the internet to auto fill and area so I decided to try a grid in grid, or nested grid. In the top level grid I create 1 cell for the menu, content and link area. Then I made classes for the header, menu, content and link area. But these classes in themselves are also grids. The header is a 5 columns single row grid that fits into the top level grid. The menu resp content is a 2 column 3 row grid that fits in the menu resp content area of the top level grid. The link area is a single column with 3 rows. Notice that the top level column widths and row heights are increased to fit the columns of the nested grids. In the HTML code I use a wrapper for the children which holds the nested grid. The children can be placed in an area cell by the auto placement function. This results in the code below:
The container class is the top level grid with names of the areas. The header, menu, content and link classes are also grids that sit inside the named cell of the container grid. Because the column and row dimensions match it looks like one grid in the browser. The HTML code is identical to that of gridtest3. The difference is that the class now refers to a grid instead of an area within a grid. The result / output now is:
As you can see the result is now the same as in the gridtest1 and gridtest2 but with the advantage that the HTML code is in a more logical order. I now use this technique for the menu in this site.
Conclusion: To auto place elements in a named area or sub area or section on a grid you have to use a grid-in-grid or nested grid technique.
Note that grid-in-grid or nested grid is NOT the same as the so-called sub-grids that are part of level2 grid specifications (not supported by browsers yet). See the w3.org website for the level2 grid specification.
Site menu
Om het de gebruiker makkelijker te maken om door de site te bladeren maakte ik in eerste instantie gebruik van een iframe. Het voordeel van zo'n iframe is dat je daarin een pagina kunt openen. Bijvoorbeeld een pagina die het site menu bevat. Het iframe heeft een attribuut 'src' waarmee je kunt aangeven welke pagina geladen moet worden, bv src="topicpage.html". Het bleek dat de grootte van het iframe gedeeltelijk absoluut is. Wat ik bedoel is dat het iframe een attribuut breedte van 100% kan krijgen, dus het schaalt mee met de breedte van het venster. Maar de hoogte kan niet worden ingesteld op de hoogte van het venser. Een hoogte van 100% zorgt ervoor dat de verkenner overschakelt naar een iframe-hoogte van 150 pixels. Dit is de standaardhoogte van het iframe. Bovendien neemt een vast site menu ook altijd ruimte in op het scherm. Zeker voor kleinere schermen is dit vervelend. Ik ben niet van mening dat de site gemakkelijk zichtbaar moet zijn op een mobiele telefoon, maar enige flexibiliteit voor kleinere schermen dan 1900 x 1080 lijkt mij wenselijk.
Daarom maar overgestapt naar zogenaamde zwevende links bovenaan de pagina. Dit werkte wel goed maar eigenlijk wilde ik het menu links op het scherm hebben.
Tegenwoordig maak ik gebruik van de nieuwe CSS grid functie voor de site layout. Zie sectie hierboven over mijn ervaringen met CSS grid.
Om de site menu-code op elke onderwerppagina te minimaliseren en om te voldoen aan HTML-coderingsnormen, die zeggen dat HTML alles te maken heeft met inhoud en CSS alles te maken heeft met design, koos ik uiteindelijk voor:
- Voeg verwijzingen toe voor het site menu op elke onderwerp pagina.
- Gebruik CCS grid om de menu links te positioneren
- Gebruik CSS om de links te visualiseren als drukknoppen
- Gebruik CSS voor omschakeling naar andere layout
In het HTML-bestand staat voor elke link één regel. Inclusief de tekst voor de link en tekst voor hint die je ziet als je met de muis over de link beweegt. Om een indruk te geven van de code voor het sitemenu:
De meeste van de bovenstaande code is identiek voor elke onderwerppagina. Alleen de vet gemarkeerde stukken moeten voor elke pagina worden gewijzigd. Het nadeel van deze aanpak is natuurlijk dat als het menu verandert, elke onderwerppagina moet worden bijgewerkt. Met de optie 'sessie optie' in Notepad++ en met het beperkte aantal onderwerpen van mijn site is dit relatief eenvoudig en sneld te doen. In een Notepad++ -sessie voegt je alle gewenste bestanden toe en open je alle relevante onderwerppagina's tegelijk.
De CCS code die verantwoordelijk is voor de opmaak van het site menu is als volgt:
Aan het begin zijn enkele kleuren gedefinieerd die in de CCS worden gebruikt. Dit zijn de 4 tinten blauw, niveau 1 is de donkerste tint.
Het 'nav' deel definieert de achtergrond, positie en lettertype in het menu.
Het 'nav span' deel definieert de samenstelling van de paginatitel binnen het 'span' element in de HTML-code.
De 'nav a' definieert de opmaak van de links naar de onderwerppagina's. 'float' betekent dat de tekst op dezelfde regel naar rechts wordt uitgelijnd tegen het vorige element aan.
De 'nav a: hover' toont de opmaak wanneer de gebruiker met de muis over de link zweeft. Met deze eigenschappen krijg je een drukknop-achtig effect. De 'border-radius' geeft de normaal vierkante achtergrond van de link een afgerond hoekeffect. Door de 'overgangsduur' verandert de vorm langzaam van een rechthoek in een afgeronde rechthoek. Dit heeft geen functionele betekenis, ik vond het gewoon leuk.
Opmerking: 'Margin' is de ruimtebuiten het huidige element naar andere elementen. 'Padding' (opvullling) is de ruimte binnen het huidige element tussen de rand en de tekst.
Opmerking: voor een 'p' element die zich in een' body' element bevindt, is de marge van het 'p' element vanaf de marge van het 'body' element. Je zou kunnen zeggen dat de 2 marges bij elkaar optellen. Dit geldt voor zowel de linker, boven, rechter als onder marge. De Chrome en Edge (Chromium) verkenners Ontwikkelaars Tools (F12 or Ctrl-Shift-i) is hier heel handig bij. Deze kan je duidelijk tonen wat de margins en padding zijn van een geselecteerd element.
Media query
Vertaling is werk in uitvoering!
A media query can be used in the CSS code to conditionally execute statements and is comparable to a IF (condition) THEN (do something)
statement. The media query condition can check device properties such as screen size. The section following the media query is executed when the condition is true. The media query to check the screen size used in this website is as follows:
@media screen and (max-width: 1400px)
The condition is true if the screen size is smaller than 1400px. In the media query only the main grid and the menu grid is modified. But modifications are quit subtle.
This is the default CSS for the grids for the large screen. Main grid of 3 cols (line 5) and 2 rows (line 6). Header on the first row (line 8). Menu grid of 1 col by 11 rows (line 14) and to the left of the screen (line 9). Content in the middle and page links to the right (line 9).
For the medium screen size only the main grid and the menu grid CSS changes. The header remains the same.
Meerdere talen
Omdat sommige onderwerpen in het Engels en sommige in het Nederlands waren, dacht ik dat het beter zou zijn als de gebruiker een taal kon selecteren en de pagina's alleen in de geselecteerde taal aan de gebruiker zou presenteren. Daarvoor moest ik de onderwerpen in 2 talen vertalen en van taal kunnen wisselen. De uitdaging was hoe de site opgezet moest worden om een tweetalige ervaring te bereiken. Na een zoektocht op internet kwam ik met de volgende opties:
- Gebruik PHP om de juiste taal te laden en cookies om de geselecteerde taal op te slaan
- Gebruik Javascript om van taal te wisselen en gebruik en lokale opslag om de geselecteerde taal te onthouden.
- Gebruik alleen HTML-links om te schakelen tussen talen, maar hierbij geen mogelijkheid om de geselecteerde taal te onthouden.
Wilde graag vasthouden aan de volgende uitgangspunten:
- Houd het simpel. Ik heb alleen basisvaardigheden voor HTML, CCS, Javascript en PHP.
- Houd de site zoekmachine vriendelijk (SEO = Search Engine Optimization)
- Het laden en wisselen van pagina's moet snel zijn voor de gebruiker.
- Onthoud de geselecteerde taal voor een volgend bezoek. Als er geen taal is opgeslagen, stop dan het beste met de taal van de gebruiker
Ik ben nog niet bereid om software zoals wordpress.org te gebruiken om de site te bouwen. Ik begrijp graag hoe alles precies werkt. Met zo'n tool heb ik het gevoel dat ik er niet langer de controle over heb.
Daarom besloot ik HTML te gebruiken om van taal te veranderen en Javascript te gebruiken om de geselecteerde taal te onthouden en de taal zo nodig 'te detecteren'.
Om de geselecteerde taal op te slaan zijn er 2 mogelijkheden:
- koekjes
- lokale storage
Koekjes (Engels: Cookies) zijn kleine pakketten die zijn opgeslagen op de lokale computer van de gebruiker. Ze bevatten informatie die relevant is voor de specifieke website, bijvoorbeeld aanmeldingsinformatie. Cookies worden vanaf de computer van de gebruiker naar de server gestuurd met elke pagina die wordt opgevraagd bij de server. Om de extra overhead laag te houden, zijn cookies beperkt in omvang. Voor deze toepassing is dit geen probleem. Cookies worden voornamelijk gebruikt in combinatie met PHP die ook op de server draait. In mijn geval wilde ik geen PHP gebruiken, dus cookies zijn voor mij geen goede optie.
De tweede optie is lokale opslag. Lokale opslag is ook op de computer van de gebruiker, maar wordt uitsluitend lokaal gehouden (vandaar de naam). Dit betekent dat het niet naar de server wordt gestuurd. Lokale opslag mag veel groter zijn dan cookies (Mb in plaats van Kb). Javascript kan worden gebruikt om de informatie te definieren en op te halen. De informatie is opgeslagen als een set / paar met een naam en een waarde. In mijn geval kan de naam 'siteLanguage' zijn en de waarde 'en' of 'nl'. Lokale opslag wordt opgeslagen als strings. Voor een taal is dit perfect. Voor binaire data is een conversie nodig. Bij lokale opslag zijn er 2 smaken, één heet sessie opslag en de andere lokale opslag. Sessie opslag wordt verwijderd wanneer de gebruiker de verkenner af sluit. Lokale opslag wordt op de computer bewaard, zelfs nadat de verkenner is afgesloten. In mijn geval heb ik dus de lokale opslag nodig. De lokale opslagoptie is beschikbaar in verkenners die HTML5 ondersteunen. De meeste moderne verkenners ondersteunen lokale opslag.
Zoek machine optimalisatie
Zoekmachine optimalisatie (English: SEO = Search Engine Optimization) is een reeks acties die nodig zijn om hoger te scoren in de zoekresultaten die aan een gebruiker gepresenteerd worden. Dit geeft een grotere kans dat de site wordt bezocht. Wat je kunt doen om een site te optimaliseren, is niet helemaal duidelijk. Sommige partijen beweren dat ze de ranking kunnen verhogen als je ze betaalt. Of dat ook zo is weet ik niet, maar voor deze niet-commerciële site is dat uiteraard geen optie. Ik heb de volgende tips / richtlijnen voor zoekmachine optimalisatie gevonden die mij logisch leken:
- Gebruik een site overzicht
Zie hieronder voor uitleg. - Gebruik een
titel
element in het koptekst gedeelte van de html pagina.
<Title>Website structuur en meertalig ontwerp<title>
- Gebruik een meta element met zoekwoorden
<Meta name = "keywords" content = "html javascript css php meertalig tweetalig" />
- Herhaal de sleutelwoorden verschillende keren op de pagina
- High-light sleutelwoorden
- Gebruik een metaelement met een beschrijving
<Meta name = "description" content = "Overwegingen, keuzes en beslissingen gemaakt tijdens het ontwerp van mijn website, vooral voor meerdere talen Engels en Nederlands" />
- Gebruik links tussen de pagina's op de site
Dit heb je vanzelf als je het sitemenu als HTML code toevoegt aan elk onderwerp en elke indexpagina. - Ververs de inhoud regelmatig
- Gebruik bij het verwijzen naar een andere site de volledige URL-link .
In plaats van 'zie deze site gebruik 'zie modernizr.com'
Site overzicht
Een site overzicht (Engels: site map) is een XML-structuurbestand met een lijst van alle relevante pagina's van de site. Zie de website sitemaps.org voor een meer gedetailleerde beschrijving van een site map. Een site map kan worden gegenereerd door een aantal online tools, zie bijvoorbeeld xml-sitemaps.com . De gratis online tools lijken beperkt te zijn voor het aantal pagina's. Deze site heeft veel (100.000+) html-bestanden in de stamboom sectie. De online tool heeft voor mij dus niet alle onderwerppagina's vermeld. Ik heb het xml-bestand zelf aangepast en alle niet-relevante pagina's verwijderd en de belangrijskte laten staan waaronder alle indexen en onderwerp pagina's. Zie hieronder voor een uittreksel van de site map voor deze site. Gemakshalve is het bestand ingekort tot slechts een paar links.
Voor een uitleg van de betekenis van de elementen 'changefreq' en 'priority', zie de sitemaps.org site.
Nadat u een site map bestand heeft gemaakt, moet u dit op de website opslaan en ter verwerking naar de zoekmachine sturen. Je kunt het opslaan in de map op het hoogste niveau. Verzenden naar Google gaat via de google zoek console. De zoekconsole rapporteert over de status van de verwerking, zie hieronder. Dit kan enkele dagen duren.
Pagina structuur
Met behulp van de bovenstaande overwegingen en analyse kwam ik tot de volgende structuur en links tussen de pagina's:
Als de gebruiker het adres van de website invoert, wordt de pagina 'index.html' door de server geladen. Vanaf de 'index.html' wordt de gebruiker automatisch en onmiddelijk doorverwezen naar de juiste taal, of de 'index.en.html' pagina of de 'index.nl.html' pagina. Hiervoor wordt Javascript gebruikt. Hoe dit wordt gedaan, wordt hieronder uitgelegd in de sectie Javascript.
Vanaf de pagina 'index.xx.html' bladert de gebruiker door de site met behulp van de menu verwijzingen. Hij kan ook van taal wisselen. Het enige dat dit doet, is dezelfde onderwerppagina in de andere taal laden. Het sitemenu verandert afhankelijk van de gekozen taal. Als het sitemenu 'nl' actief is, wordt de gebruiker alleen doorgestuurd naar andere 'nl'-pagina's en zo ook met de' en'-taal. Het Nederlandse site menu biedt een verwijzing om over te schakelen naar het Engels en het Engelse site menu biedt een verwijzing om over te schakelen naar de Nederlandse taal. Dit alles gebeurt met aleen HTML-code, hiervoor wordt dus geen Javascript gebruikt.
Een ander voordeel van deze benadering is naar mijn mening dat wanneer de gebruiker rechtstreeks op een onderwerpspagina terechtkomt zonder de 'index.html'-pagina te passeren, de gebruiker de site nog steeds zoals gewoonlijk zou zien, inclusief het sitemenu.
Modernizr eigenschap detectie
Omdat gebruikers oudere verkenners kunnen gebruiken wanneer ze mijn site bezoeken, had ik een manier nodig om te detecteren of de verkenner lokale opslag ondersteunt. Dit is waar modernizr komt kijken. Modernizr is een verzameling javasript code die verkenner functies kan detecteren. Om erachter te komen of lokale opslag wordt ondersteund, wordt het met behulp van Modernizr zo simpel als testen of modernizr.localstorage waar is of niet. Om de modernizr javasript te downloaden, ga naar de modernizr.com website, selecteer de functies die je nodig hebt en druk op download. Omdat alleen de geselecteerde functies zijn opgenomen in de download, is het resulterende JavaScript bestand erg klein. Voeg het bestand toe aan de website (in mijn geval de map 'General') Voeg een verwijzing naar het bestand toe aan de HTML-pagina en u kunt de genoemde test gebruiken voor lokale opslag. Modernizr heeft helaas geen optie voor taaldetectie.
Javascript
Het hierboven genoemde Javascript wordt op deze website gebruikt om:
- Doorverwijzen vanaf de start pagina 'index.html' naar de juiste taal.
- Opslaan van de geselecteerde taal tbv volgende bezoeken aan deze site.
Met de donker gearceerde tekstvakken in de onderstaande afbeelding wordt getoond waar Javascript wordt gebruikt op deze website:
De javascript code is relatief kort, eenmaal geschreven en opgeslagen in een bestand met de extensie .js. Dit bestand wordt geladen door elke pagina die het nodig heeft. Dit is eigenlijk elke onderwerppagina. Ook de Modernizer javascript wordt opgeslagen als een .js-bestand en ook geladen door elke pagina die het nodig heeft. Dus in de koptekst en onderwerppagina's is deze HTML code te zien:
De naam van het modernizr javascript-bestand is een beetje cryptisch. Dit komt omdat ik de functies 1) lokale opslag, 2) video en 3) xhr2 heb geselecteerd voordat ik het bestand downloadde. Ik heb het gedownloade bestand gewijzigd in de opgegeven naam om gemakkelijk te kunnen zien welke functies zijn opgenomen in het modernizr javascript-bestand. Ik zal niet eens proberen de inhoud van het modernizr javascript-bestand uit te leggen. Dit gaat mijn programmeermogelijkheden ver te boven.
Hieronder staat de code voor het javascript-bestand om de taal op te slaan en om de juiste taal indexpagina te laden:
Dit javascript bevat in feite 3 functies. Deze worden hieronder uitgelegd.
functie StoreLanguage (lan)
Deze functie wordt aangeroepen wanneer een pagina wordt geladen. Een Nederlandstalige pagina roept deze functie aan met de parameter 'nl' en een Engelse pagina roept deze functie aan met de parameter 'en'. Eerst controleert het of er een geldige taal wordt gevraagd. Dit is slechts een voorzorgsmaatregel, maar zou altijd het geval moeten zijn. Het stelt de taal in op "none" als het niet 'nl' of 'en' is. Vervolgens wordt gecontroleerd of lokale opslag door de verkenner wordt ondersteund. Vervolgens stelt het de variabele SiteLanguage in op de opgegeven taal. Ten slotte voert het de taal uit naar de console voor probleemoplossing. In Chrome of Edge Chromium worden de ontwikkelaarstools met HTML-inspector en console geopend met het commando F12 of Ctrl-Shift-i.
Deze functie wordt aangeroepen wanneer een onderwerppagina wordt geladen. Dit wordt gedaan in de body element met:
<body onload="StoreLanguage('en')">
functie LoadLanguage ()
Deze functie leest de taal uit vanaf de lokale opslag of selecteert de taal op basis van een beste schatting. Eerst probeert het de taal uit te lezen van de lokale opslag. Als dit lukt, krijgt de variabele taal een waarde 'en' of 'nl' en wordt de functie GetLanguage () niet aangeroepen. Ten slotte laadt de functie de juiste pagina met de opdracht: window.location.href = "index.en.html"
. Dit heeft hetzelfde effect als wanneer de gebruiker op een link zou klikken, het laadt de pagina 'index.en.html. in het huidige venster. Dit gebeurt allemaal zo snel dat de gebruiker dit niet merkt en alleen 'index.nl.html' of 'index.en.html' in de adresbalk zal zien.
Deze functie wordt alleen aangeroepen door de site 'index.html' wanneer deze is geladen. Dit wordt gedaan in de body-element met:
<body onload="LoadLanguage('en')">
functie GetLanguage (lan)
Dit stuk code dat ik op internet heb gevonden, het zou de beste manier zijn om de juiste taal te raden. Dit is dus geen exacte wetenschap. De gebruiker is mogelijk Nederlands, maar gebruikt een Engelse taalinstelling in de verkenner (zoals ik gewoonlijk doe). Als de verkeerde taal is geladen, kan de gebruiker altijd de verwijzing in het menu selecteren en wordt de nieuwe instelling opgeslagen. Deze functie wordt niet aangeroepen vanaf de HTML pagina's, maar alleen vanuit de functie LoadLanguage()
wanneer lokale opslag niet wordt ondersteund.
PHP contact formulier
Voor het contactformulier op de site gebruik ik PHP om de e-mail te verzenden. Hiervoor is PHP taal code ingebed in de 'contact.en.php' pagina. PHP werkt alleen aan de serverkant. Wanneer een pagina wordt opgevraagd door de verkenner van de gebruiker, controleert PHP eerst of de pagina PHP code bevat en verwerkt dat als dat het geval is. Na verwerking wordt de pagina naar de verkenner gestuurd (exclusief de PHP code, maar inclusief eventuele output van PHP verwerking). De PHP code wordt dus verwerkt en verwijderd voordat de pagina door de verkenner wordt ontvangen. Vandaar de verwijzing vóór-verwerker in de naam Hypertext Preprocessor. Wanneer de gebruiker op de verzendknop klikt, vraagt de verkenner een pagina op bij de server. In het geval van mijn contactformulier is de gevraagde pagina hetzelfde als de pagina die wordt bekeken. De PHP verwerker kan zien of het formulier iets heeft gepost door het verzoek van de verkenner te controleren. Als een zogenaamd berichtverzoek wordt gedetecteerd, wordt de email actie uitgevoerd en wordt er een tekst aan de HTML-code toegevoegd om de gebruiker te informeren dat de e-mail is verzonden.
De contactpagina heeft een menu zoals alle andere onderwerppagina's en heeft 2 formulieren, één voor elk type bericht. Eenvoudigheidshalve geef ik hieronder de tekst van de contactpagina zonder het menu en slechts voor één formulier.
Aanvankelijk verwerkt PHP deze pagina, maar er wordt niets ondernomen omdat er niets wordt gepost. De verkenner geeft het formulier weer. De opmaak van het formulier wordt gedefinieerd in het CSS-bestand.
/* Used in the forms of the contact page */
label {
display: inline-block;
width: 200px;
}
legend {
background-color: var(--level3blue);
font-size:1.2em;
}
textarea {
vertical-align: top;
}
De volgende regel definieert dat de verkenner de informatie die in de velden is ingevoerd als een postverzoek naar de server moet sturen. De informatie die is ingevoerd in de onderwerp email en berichten velden is allemaal opgenomen in het berichtverzoek en kan worden opgevraagd door de PHP verwerker met de regel $message = $_POST['message1'];
. Dit definieert een variabele $message dat de waarde krijgt die is ingevoerd in het berichtvenster van het formulier. Het deel action = "contact.en.php"
vertelt de verkenner welke pagina moet worden aangevraagd in het berichtverzoek.
<form name = "email1" method = "post" action = "Contact.php">
PHP code kan overal in het HTML document staan, mits deze is ingesloten met de juiste begin- en eind elementen. Om een bericht van de PHP-code naar de gebruiker te sturen, wordt deze regel in het 'body' element geplaatst. Tekst wordt tussen de formulieren en onder het sitemenu weergegeven. De variabele $msg krijgt een waarde wanneer een email wordt verzonden door de PHP verwerker of wanneer er een fout is opgetreden:
<?php echo $msg ?>
De volgende regel definieert een invoerveld dat wordt gebruikt om het berichtverzoek naar de server te activeren. Het krijgt een naam die kan worden getest door de PHP-engine.
<input value="Submit" type="submit" name="submit1">
De test voor een berichtverzoek wordt gedaan in de allereerste regel van de PHP-code:
if(isset($_POST['submit1']))
Code markering prism
Vertaling is werk in uitvoering!
A code highlighter colors a piece of code dependent on the used language. It can format different parts / elements / keywords of the code in different colors. The result is more pleasing to the eye and better to read. A search on the internet showed that there are different ways of achieving this. I choose a so-called client side javascript highlighter. This means that the highlighting work is done by javascript on the users side after download. This adds some overhead to the loading time and the processing also takes some time. It looked to me that there were 2 big players using this principle, 'highlight' (see highlightjs.org) and 'prism' (see prismjs.com). I selected prism because the download page was a bit clearer to me and I liked the coy theme. In the download page you can select only the option you want. For me this was:
- Markup + HTML + XML + SVG + MathML + SSML + Atom + RSS 2.15KB
- CSS 1.23KB
- C-like 0.68KB
- JavaScript 3.19KB
- PHP milesj2.41KB
- Visual Basic + VBA Golmote1.93KB
- Theme: Coy tshedor3.93KB
- Plugin: Line Numbers kuba-kubula3.28KB
- Plugin: Unescaped Markup 1.47KB
The download is actually 2 files. One CSS file for the theme, 'coy' in my case and one file for the code highlighter for all the selected languages and plugins. In the download you can opt for a minified version and a developer version for the javascript. Normally you would select the minified version. In case you want to temper with the highlighting function you need the developer version. For me this is not needed. The minimized version is in my case 20kb and the CSS is 6kb. Does not seem to match the predicted file size on the download page, but both are quit small and comparable to a picture.
You need to add these 2 files to each page where you want to use the code highlighter. You do this by adding 2 lines to the <head>
section in the html file:
You do not need to call the prism.js code from within the html to activate it. Apparently the prismjs code activates itself during page load and page refresh.
Now ,where ever you need to highlight some inline code you need to wrap the code with the <code class="language-xxxx">... some escaped inline code ...</code>
tags in the html:
The xxxx need to be replaced with the code for the language used. In my case I have:
- 'markup' for HTML, XML
- 'html'
- 'xml'
- 'css'
- 'javascript'
- 'clike' for code languages looking like C++ (Arduino code).
- 'php'
- 'visual-basic' for Visual Basic and (EXCEL) VBA code.
Note the missing hyphen in 'clike'. The prism site could be clearer on what xxxx you need to use for each selected language. I had to look in the minified prismjs file to find out I needed to leave out the hyphen. Luckily the first line of the prism.js file already reveals this:
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+markup-templating+php+visual-basic&plugins=line-numbers+unescaped-markupNote that for xml and html code you can use either 'markup' or 'xml' resp 'html' for the language code.
'escaped code' means that at least all the < are replaced with <
. Optionally you can also replace all the > with >
. This is needed otherwise the html is messed up. Replacement makes the code in the HTML file difficult to read. And replacing could lead to mistakes. Would it not be better if you could leave in the < and >? Well, you can. You can use the plugin 'Unescaped Markup' for that. See the info page on prismjs.org for more info.
If you want to highlight a code snippet with more lines as a separate block you need to wrap the code with the <pre class="language-xxxx"><code>... some escaped multi line code snippet ...</code></pre>
tags in the html.
What the prism.js code does is to search for <code>
tags and <pre><code>
tag combinations, check the language used and use a search & replace function to add html tags around the code elements. See below a screenshot from the Edge developer tool where you can see the markup added. This is only for 1 single line of HTML code:
The search and replace is done with so-called RegEx functions. See my explanation on RegEx functions in the EXCEL section of this site. The RegEx search strings are stored in the prism.js file. You could modify these if you know you way around RegEx functions. The prism.css file will then make sure that the tags are presented in the chosen theme. You can modify the prism.css file to modify the theme. I have changed the blue left margin color of the code box to match the blue used on the site. Also changed the width of the code box and restricted the height to max 400px.
Switching to another theme means that you only replace the CSS file. It is advisable to leave out any html for the <code>
and <pre>
tags in your own CSS file.
Because I have also downloaded the 'unescaped-markup' plugin I prefer to use the following for HTML code snippets:
You only still need to escape any <script>
and </script>
in you snippet. I discovered it is enough to only escapre the < of the closing script tag.
So what about the performance of the page? This page has the most code snippets of all my pages. So I did a load test with and without the prism.js file included. I used the Edge developer network tab to reveal the loading time for the page.
Note that I still include the prism.css file. Otherwise the code snippets would no longer be visible at all. The load time for the page is about 300mSec. This is the load time from the website to your browser and includes any processing on the client side. This will depend on your location and internet connection speed.
Now the load time is about 600 mSec. So this is 300 mSec longer than without prism.js. This shows to me that the prism.js needs 300 mSec to process all the code snippets in my file. For me this is acceptable. The 300 mSec would depend I guess on the processor used for the browser. In this case it was measured on my desktop with an i7 (Intel Core i7 3770 @ 3.40GHz) processor. With CPU throttling at 4x in the performance tab the load time goes up to 2250 mSec. This is probably more realistic for mobile and tablet devices.