
Marko Draisma


Open het bestand 'item.html'. Maak hierin een JavaScript blok met code (in de <head>) en maak daarin:
a) Een variabele waar wij straks een product object gaan plaatsen
b) Een variabele waar wij straks een datum in gaan zetten (de login tijd van de gebruiker)
 
Open het bestand 'producten.html'. Maak hierin een JavaScript blok met code (in de <head>) en maak daarin:
c) Een variabele waar wij straks een reeks (array) in gaan zetten met product prijzen


var invoer1 = 10
var invoer2 = 20

if (invoer1 == invoer2)
{
  alert("Invoer gelijk!");   // window.alert() mag ook    
}


var invoer1 = 10
var invoer2 = 20

if (invoer1 == invoer2)
{
  alert("Invoer gelijk!");   // window.alert() mag ook    
}
else
{
  alert("Invoer verschillend!")
}


De opdracht(en) na de controle van een if statement moeten we altijd tussen accolades {} opnemen wanneer het om meerdere opdrachten op verschillende regels gaat. 
Betreft het één opdracht dan kunnen de accolades achterwege blijven.

Het correcte antwoord is: Juist
Accolades MOETEN we binnen een if statement alleen toevoegen wanneer MEERDERE statements na controle van de conditie moeten worden uitgevoerd op verschillende regels. 
Anders gaat de browser er vanuit dat alleen de eerste opdracht bij het if statement behoort en niet de tweede en (eventueel) volgende statements. Bij het opnemen van 
een enkel statement is het niet verplicht. Onderstaande DRIE syntaxen zijn dus goed:

if (contole)			
   statement; statement		   

if (controle)
   statement

if (contole)
   {statement;
     statement}


De opdracht(en) na de controle van een if statement moeten we altijd tussen accolades {} opnemen. Anders geeft de browser een foutmelding bij het openen van de pagina.

Het correcte antwoord is: Onjuist
Accolades MOETEN we binnen een if statement alleen toevoegen wanneer MEERDERE statements na controle van de conditie moeten worden uitgevoerd, anders gaat de browser er 
vanuit dat alleen de eerste opdracht bij het if statement behoort en niet de tweede en (eventueel) volgende statements. Bij het opnemen van een enkel statement zijn 
accolades niet nodig. Onderstaande syntaxen zijn dus beide goed:

if (controle)			           
   {statement; statement}		    

if (controle)
   statement
   
   
Het switch statement, ook wel case statement genoemd, is een soort if statement met meerdere alternatieven. 

var geslacht = prompt("Bent u een man of een vrouw? (M/V)");
switch(geslacht.toUpperCase()){
    case "M": console.log("Dag meneer");
              break;
    case "V": console.log("Dag mevrouw");
              break;
    default: console.log("Dag persoon");
}



Welke opdrachten van de onderstaande code worden uitgevoerd?

var t = 'x';
switch(t){
  case 'y' : document.write(a);
  case 'x' : document.write(b);
  case 'w' : document.write(c);}
  
Het correcte antwoord is: document.write(b); en document.write(c); Opdrachten document.write(b); endocument.write(c); worden uitgevoerd, er staat namelijk 
GEEN break statement onder statement opdracht2


Code in een loop wordt herhaald uitgevoerd aan de hand van één of meer voorwaarden. Er bestaan meerdere soorten loops die we allemaal gaan bespreken;
while loop   
do while loop 
for-loop  
for-in (wordt afgeraden bij gebruik ES6, liever for-of)  
for-of loop  


Naast while loops kunnen we ook gebruik maken van for-loops.

For, for in en for of loops
Naast while loops kunnen we ook gebruik maken van for-loops. Lees hiervoor pagina 114 (bovenaan de pagina) óf bekijk de volgende opname over for-loops van Quentin Watt:

In onderstaand voorbeeld staat de traditionele for loop. Achter het keyword for staan drie onderdelen tussen haakjes: 
een startwaarde, de voorwaarde om de loop te herhalen, en een statement om de voorwaarde uiteindelijk op false uit te laten komen. 
Zonder dat laatste statement zou een oneindige loop kunnen ontstaan.


var klassen = ["Warrior","Mage","Druid","Priest","Hunter","Bard"];

// for-loop:
for (var index=0; index<klassen.length; index++)
{
  console.log("Item " + index + " met waarde: " + klassen[index]);
}


Hieronder staan twee andere loops, de for ... in loop om de eigenschappen van een object uit te lezen, en de for ... of loop om de waarden van een array uit te lezen. 
 
Met een zogeheten for... in loop kunnen we door de eigenschappen van een object heen lopen. Later zullen objecten nader worden toegelicht. 
Hier is vast te zien dat een object bestaat uit eigenschappen (voor de dubbele punt) met waarden (achter de dubbele punt).
 
for ... of loop : een nieuwe manier om een array te doorlopen. 

let spel = {
  naam: "schaak",
  type: "bordspel",
  vakjes: 64
};

// for in loop: eigenschappen zijn naam, type en vakjes
// spel[eigenschap] zijn de waarden: schaak, bordspel, 64
for(let eigenschap in spel){
  console.log(eigenschap, spel[eigenschap]);
}


let klassen = ["Warrior","Mage","Druid","Priest","Hunter","Bard"];

// for-of loop: geen index, alleen de waarden
for (let waarde of klassen) {
  console.log(waarde); 
}


Voor nu is het goed om te onthouden dat we een for-in loop NIET op arrays moeten gebruiken. Dat zijn verzamelingen van waarden (in een verder hoofdstuk daarover meer). 
Deze loop zal bijvoorbeeld lege elementen van een array niet tonen, terwijl we vaak juist alle elementen willen doorlopen. Ook gaat het mis zodra we een eigenschap aan een array toekennen.


For of loop
Met de komst van ES6, kunnen we ook gebruik maken van een zogeheten for-of loop. Deze loop is wel bedoeld om een array mee te doorlopen.
In het volgende voorbeeld worden alle waarden van een array doorlopen. 


var klassen = ["Warrior","Mage","Druid","Priest","Hunter","Bard"];

// for-of loop:
for (waarde of klassen)
{
  console.log(waarde);    
}


// tafel van 3 met while lus
console.group("tafel van 3 met while loop");
var x = 3;
var i = 1;

while(i > 10){
  // Onderstaande code wordt nu NIET uitgevoerd,
  // immers: de i>10 conditie is false.
  console.log(i + " * " + x + " = " + (i * x));   
  i++;
}
console.groupEnd();


// tafel van 3 met do while lus
console.group("tafel van 3 met do while loop");
var x = 3;
var i = 1;

do {
  // Onderstaande code wordt nu WEL (1x) uitgevoerd,
  // immers: de i>10 conditie wordt pas na het codeblok gesteld.
  console.log(i + " * " + x + " = " + (i * x));    
  i++;
} while (i > 10)
console.groupEnd();



Om vroegtijdig uit een loop te kunnen 'springen' kunnen we het commando 'break' gebruiken. Daarnaast bestaat de mogelijkheid al (bijvoorbeeld aan het begin van de code) 
in de loop aan te geven dat we met de volgende iteratie (herhaling) verder te gaan.


We kunnen ook aan de for lus meerdere voorwaarden (en ook initialisatiewaarden en ophogingen) meegeven, gescheiden door een komma. Voorbeeld:

    for ( teller=1, getal=8 ; teller<=10, getal>0; teller++, getal=teller-2 )

Er zijn hier twee initialisatiewaarden, twee voorwaarde en twee ophogingen.



<script type="text/javascript">
t = 0;
while (t>100)
{
  document.write(t); t-=1;
}
</script>

Hoe vaak wordt de waarde van t in het document geschreven?

0 keer : Aangezien de voorwaarde van de loop niet waar is, zal t nooit naar het scherm geschreven worden.



Een functie is een blok code met accolades er omheen en een naam, zodat we later kunnen terug verwijzen naar dat blok. Een voordeel van het plaatsen van code in een functie, 
is dat de code niet direct uitgevoerd wordt, maar pas zodra de functie bij naam wordt aangeroepen. Daarnaast zit er geen limiet aan het aantal keer dat een functie aangeroepen 
kan worden.



function eenvoudig()
{
  console.log("Dit is een eenvoudige functie");
}

function returnWaarde()
{
  var a = 10;
  var b = 2;
  return a*b;  
}

function parameterWaarde(invoer1,invoer2)
{
  console.log(invoer1*invoer2);
} 

// Aanroep eerste eenvoudige functie:
eenvoudig();

// Aanroep tweede functie, die waarde teruggeeft:
var uitkomst = returnWaarde();
console.log("Resultaat:" + uitkomst);

// Aanroep derde functie, die waarde mee krijgt:
parameterWaarde(20,3);



console.clear();
console.group("vier functies");
var add = function(a, b){
  return a + b;   
};
console.log(add(3,4));

var subtract = function(a, b){
  return a - b;   
};
console.log(subtract(3,4));

var multiply = function(a, b){
  return a * b;   
};
console.log(multiply(3,4));

var divide = function(a, b){
    if(b === 0) { 
        throw "Delen door nul is niet toegestaan"; // het zogeheten opgooien van een fout
                                                   // dit hoeven wij nog niet te kennen
    }
    else
    return a / b;
};
console.log(divide(3,4));  

// Onderstaande 'try' en 'catch' blokken hoeft u nog niet te kennen
try {
  console.log(divide(3,0));
} 
catch(error){
  console.log(error);
}

console.groupEnd();


console.group("voornaam en achternaam");
function concat(a, b){
    if( typeof a == "string" && typeof b == "string" )
    return a + " " + b;
}
var voornaam = prompt("wat is uw voornaam? ");
var achternaam = prompt("wat is uw achternaam? ");
console.log("Welkom " + concat(voornaam, achternaam));
console.groupEnd();


Tegenwoordig wordt ook vaak een alternatief gebruikt: de "rest parameter".
Deze laatste parameter krijgt drie puntjes voor de naam, en vangt de waarden op die na de voorgedefinieerde parameters komen.  
Bijvoorbeeld: 

function telop(eerste, tweede, ...overige){
  var resultaat = eerste + tweede;
  for(let getal of overige){
    resultaat+=getal;
  }
  return resultaat;
}
console.log(telop(2,3));     // 5
console.log(telop(2,3,4));   // 9
console.log(telop(2,3,4,5)); // 14



Een functie wordt vaak uitgevoerd bij de uitvoering van een zogeheten 'event'. Events gaan af (triggeren) op bijvoorbeeld het moment dat:
de gebruiker op een knop klikt
de pagina geladen is
een invoerveld de focus heeft gekregen
wanneer we de huidige pagina willen verlaten
enzovoorts. Meer hierover in een later hoofdstuk
Een veel gebruikte toepassing van de uitvoering van een functie is na het 'onload' event. Dit event gaat af zodra de pagina (het 'window' object) klaar is met laden. 
Vaak wil je met behulp van een JavaScript functie iets aanpassen op je pagina. Uiteraard kan dergelijke code pas goed werken als de pagina klaar is met laden 
(en alle benodigde elementen zichtbaar en bruikbaar zijn).
 
In het volgende voorbeeld gebruikten wij dit 'onload' event om met een functie de achtergrondkleur groen te maken: 

console.group("Anonieme functies");
window.onload=function(){
    document.body.style.backgroundColor="green";
}
console.groupEnd();



Gegeven is de volgende beweringen:

Een functie eindigt altijd met een return statement;

Onjuist : Het toevoegen van een return statement aan een functie is optioneel.


Gegeven is de volgende bewering:

Aan een functie moeten we altijd een parameter toevoegen.

Is deze bewering juist of onjuist?

Onjuist : In een functie kunnen we een parameter opnemen, als we van buiten de functie  een waarde aan de functie willen meegeven. Dit is echter niet verplicht.







function telop(a, b){
   if(typeof a !== 'number' || typeof b!== 'number'){
     throw 'foute invoer, gebruik getallen';
   }
   return a + b;
}
console.log(telop('test', 4));





function telop(a, b){
   if(typeof a !== 'number' || typeof b!== 'number'){
     throw 'foute invoer, gebruik getallen';
   }
   return a + b;
}

try {  // iets wat mis kan gaan:
   console.log(3,4);                // gaat goed
   console.log(telop('test', 4));   // gaat mis: spring naar catch block
   console.log(5,6);                // wordt niet meer uitgevoerd
} 
catch (fout){ // als er iets mis gaat:
   console.log("Er ging iets mis: " + fout);
}





function minMax(a,b){
  let minWaarde = a<b ? a : b;
  let maxWaarde = a>b ? a : b;
  return {
    min: minWaarde,
    max: maxWaarde
  };
}


let test = minMax(3,4);
console.log(test.min); // 3
console.log(test.max); // 4





console.group("Anonieme functies");
window.onload=function(){
    document.body.style.backgroundColor="green";
}
console.groupEnd();





Closures
Een functie kan een andere functie retourneren. Deze geretourneerde functie blijft dan toegang houden tot de "context" waarin deze functie is aangemaakt. Zie ook MDN over closures.
 
In het volgende voorbeeld wordt een functie aangemaakt die toegang houdt tot een teller. Elke keer als de geretourneerde functie wordt aangeroepen, wordt de teller verhoogd.

function counter(startWith, step){
   var result;
   return function(){
     result= result==undefined? // bestaat result nog niet?
             startWith:         // begin dan met startwaarde
             (result+step);      // hoog anders op met step
     return result;
   };
}
var teller = counter(0,2); // teller is een functie
                           // die bij elke aanroep de
                           // variabele result kan lezen 
console.log(teller()); // 0
console.log(teller()); // 2
console.log(teller()); // 4)
Wat gebeurt hier precies?
 
De buitenste functie heeft een variabele result, en twee parameters: startWith en step. 
Deze variabele en parameters vormen de context van de binnenste functie.
 
De binnenste functie wordt geretourneerd. In dit geval wordt deze functie toegekend aan de variabele teller. 
Met andere woorden: teller is nu een functie, die toegang houdt tot de variabele result, en tot de parameters startWith en step, die hier gevuld zijn met de waarden 0 en 2.
 
Vanaf het moment dat teller() wordt aangeroepen wordt result aangepast: als result nog undefined is krijgt deze de waarde van startWith, anders wordt result opgehoogd met step.  





Er volgt nu een nog voorbeeld die gebruik maakt van een closure:  

var BankRekening = function(nr, sal) {
  var nummer = nr;
  var saldo = sal;
  
  return {
    getSaldo: function() {
      return saldo; // geen this, want we zitten in een object.
    },  
    getNummer: function(){
      return nummer; // geen this, want we zitten in een object.
    }
  }
}

// de functie achter 'var BankRekening =' levert dus een object op met twee eigenschappen.

var mijnRekening = new BankRekening(1234,100);
console.log(mijnRekening.getSaldo());


Met een closure kun je juist specifieke code onzichtbaar maken voor de 'buiten wereld'. Wél is het vervolgens mogelijk met get en set methoden de toegankelijkheid naar de lokale variabelen te regelen.



Een IIFE (spreek uit: iffy: Immediately Invoked Function Expression) is een anonieme functie die meteen wordt aangeroepen, zodat in het vervolg alleen nog met het resultaat van die anonieme functie kan worden gewerkt.
Dit wordt onder meer gebruikt om de "global scope" schoon te houden: variabelen, functies, objecten en dergelijke die niet deel uitmaken van een functie, worden automatisch aan het window-object toegekend. Het is good practice om op dat niveau zo weinig mogelijk aan te maken.
 
Een IIFE is vaak ook een closure. Het volgende voorbeeld hebben we eerder behandeld. In dit voorbeeld wordt de context van de geretourneerde functie echter gevormd door een IIFE.
   var teller = (function (startWith, step){
   var started = false;
   return function(){
     if(started) return startWith+=step;
     started=true;
     return startWith;
   };
})(1,2);  // de anonieme functie wordt meteen aangeroepen,
                 // in dit geval met startWith=1 en step=2
                 
// nu bestaat alleen de functie teller in global scope
console.log(teller()); // 1
console.log(teller()); // 3
console.log(teller()); // 5

In het volgende voorbeeld maken we een IIFE aan die een object terug geeft. Hiervoor gelden dezelfde regels; lokalen variabelen in de IIFY functie zijn alleen bekend in de geneste functie of het geneste object. 

mijnApp = function(){
    var naam;
    var leeftijd;
  
    return {
        setNaam: function(n){
          naam = n; // this.naam?
        },
        getNaam: function(){
          return naam; 
        },                 
        setLeeftijd: function(l){
          leeftijd = l;
        },
        getLeeftijd: function(){
          return leeftijd;
        }                   
      }
}();

window.onload=function(){
  console.log(mijnApp.getNaam());
  mijnApp.setNaam("Gamer");
  mijnApp.setLeeftijd("34");
  console.log(mijnApp.getNaam());
  console.log(mijnApp.getLeeftijd());
}




new Date() zorgt ervoor dat een datumobject wordt aangemaakt. De waarde van het object is de huidige datum. Met methoden als getMonth, getMinutes en getSeconds kan de waarde worden uitgelezen. Met methoden als setMonth, setDay en setSeconds kunnen we de objectwaarde aanpassen.
In objecten zijn eigenschappen en functies voor een bepaald onderdeel (zichtbaar of achter de schermen in JavaScript) van de webpagina samengevoegd. De eigenschappen zeggen iets over het object en met de functies (=methoden) kunnen we het object iets uit laten voeren.

Wat is het resultaat in de browser wanneer de volgende JavaScript-code wordt uitgevoerd:

<script type="text/javascript">
   tekst="Dit is hoofdstuk 6 van de cursus JavaScript"
   alert(tekst.substring(7,15).charAt(4))
</script>

Bij elk karakter van een tekst hoort een indexnummer, te beginnen bij indexnummer 0.
Op de getoonde tekst worden twee methoden toegepast. De eerste methode na het String object tekst zal ook als eerste worden uitgevoerd.
tekst.substring(7,15) heeft als resultaat het 8e t/m het 16e karakter: "hoofdstuk".
Vervolgens haalt methode charAt(4) het 5e karakter op uit de nieuwe string . Het resultaat is dus "d".





Bij het doorlopen van een Array met een normale for-loop, geven we zelf als eindwaarde van onze teller de 'lengte' van onze Array op. Bekijk hierover volgende voorbeeld:

var klassen = ["Warrior","Mage","Druid","Priest","Hunter","Bard"];

// for-loop:
for (var index=0; index<klassen.length; index++)
{
  console.log("Item " + index + " met waarde: " + klassen[index]);
}


Het aanmaken van een nieuwe array kunnen we opgeven uit hoeveel elementen de array gaat bestaan. Is dit tevoren niet bekend, dan kunnen we ook een lege array aanmaken en deze later vullen.

Het vullen en uitlezen van een array kan inderdaad plaats vinden met behulp van het indexnummer. Houdt er hierbij rekening mee dat het eerste element indexnummer 0 heeft.
KANTOREN[3] is bijvoorbeeld het 4e element uit de array met de naam KANTOREN.

Hiernaast is het ook mogelijk een array middels een loop (zoals FOR IN of FOR EACH) uit te lezen.





We zien in het volgende voorbeeld hoe we objecten kunnen creeren. We zien in de code soms een waarde uitlezen behulp van blokhaken []. Dit is een alternatieve manier van uitlezen van eigenschappen van een object. Daarnaast is er de mogelijkheid om met blokhaken [] een zogeheten array aan te maken, ofwel een verzameling waarden. Wat dat precies inhoudt en hoe wij ermee kunnen werken lezen wij verderop in dit hoofdstuk.

console.clear();
var artikel1 = new Object();
artikel1.naam="pen";
artikel1["prijs"]=1.5;

var artikel2 = { 
  naam: "potlood", 
  prijs: 0.8 
};

artikel1.totaal = function(aantal){
    return this.prijs*aantal;
};

artikel1.eigenschappen = 
  {
    kleur: "blauw", 
    punt: "fijn"
  };

console.log(artikel1.eigenschappen["kleur"]);
console.log(artikel1["eigenschappen"].punt);

console.log(artikel1.totaal(2));

artikel2.totaal = artikel1.totaal;

console.log(artikel2.totaal(2));


var Artikel = function (naam, prijs){
    this.naam=naam;
    this.prijs=prijs;
}

var artikel1 = new Artikel("Appel","0.50");
artikel1.totaal = function(aantal){
    return this.prijs*aantal;
};

Artikel.prototype.totaal = artikel1.totaal;
Artikel.prototype.toString = function(){
   return this.naam + ": " + this.prijs;   
}

var artikel2 = new Artikel("Peer","0.60");
console.log(artikel2.toString());





Doorlopen van een object
Het uitlezen van objecten wordt doorgaans gedaan met behulp van een loop. Denk aan het doorlopen van een <SELECT> element met alle genestte <OPTION> elementen:



Je zou bijvoorbeeld ook alle mogelijke waarden van een zelf gemaakt object kunnen uitlezen:

console.clear();

speler1 = {
  naam:"Marco van Basten",
  sport:"voetbal",
};

speler2 = {
  naam:"Anton Geesink",
  sport:"judo",
}

for (eigenschap in speler1)
{
  console.log(eigenschap + " = " + speler1[eigenschap]);
}

for (eigenschap in speler2)
{
  console.log(eigenschap + " = " + speler2[eigenschap]);
}





Nu wij hebben gezien hoe verschillende Array methoden werken, zien wij onderstaand een aantal voorbeelden over het werken met methoden én gaan wij daarna zélf ermee aan de slag. Het volgende voorbeeld toont methoden waarmee wij de inhoud van een array kunnen aanpassen: 

console.clear();
var klassen = ["Warrior","Mage","Druid","Priest","Hunter","Bard"];

// Voeg element aan einde toe
klassen.push("Ranger");

console.log(klassen);

// Verwijder laatste element
klassen.pop();

console.log(klassen);

// Verwijder 1e element (en her-indexeer)
klassen.shift();

console.log(klassen);

// Voeg element aan begin toe
klassen.unshift("Paladin");

console.log(klassen);

// Voeg element(en) op gewenste positie toe en/of verwijder elementen op gewenste positie
/* Syntax: 
  - op welke positie toevoegen
  - hoeveel elementen verwijderen
  - (variabel) toe te voegen elementen 
*/
klassen.splice(2,0,"Necromancer","Cleric");
console.log(klassen);

// Verwijder elementen op gewenste positie
klassen.splice(5,1);
console.log(klassen);


Nu volgt er een voorbeeld met andere array hulpmethoden en -eigenschappen:

console.clear();
var klassen = ["Warrior","Mage","Druid","Priest","Hunter","Bard"];

// Lengte van de array ophalen (aantal elementen)
console.log(klassen.length);

// Nieuwe array maken van (deel van) andere array
var andereKlassen = klassen.slice(0,3)
console.log(andereKlassen);
console.log(klassen);

// Sorteren van deze array (alfabetisch)
console.log(klassen.sort());

// BONUS:
// We maken een array met objecten
// We gaan deze array sorteren op basis van levenspunten van de objecten.

// Eerst maken we een Speler constructor aan om vervolgens instanties van te kunnen maken
Speler = function(naam, punten){
  this.naam = naam;
  this.levenspunten = punten;
}

// We voegen een methode toe die een representatieve weergave van een instantie teruggeeft
Speler.prototype.toString = function(){
  return this.naam + " met " + this.levenspunten + " levenspunten!";
}

// Array met speler objecten (instanties) maken
echteSpelers = [
  new Speler("henk","50"),
  new Speler("pieter","40"),
  new Speler("jan","75")
];

for (spelertje of echteSpelers)
{
  console.log(spelertje.toString());
}

// Sorteer methode aanroepen met meegegeven een anonieme functie
// Had ook een gewone functie mogen zijn


We kunnen arrays ook sorteren. We gebruiken daar de sort() functie voor, eventueel voorzien van een anonieme functie die een zelf gedefinieerde sortering oplegt: MDN Array sortering. Dit is erg interessante en krachtige code, maar wat complexer, doordat we een anonieme functie gebruiken.






var naam = 'Qwin'
var leeftijd = 20;
var hobby = 'Netflixen'

function geefStudie()
{
  return 'Artificial intelligence';
}

var resultaat = `Hij heet ${naam}, is ${leeftijd} jaar oud en houdt van ${hobby}. Hij is zojuist begonnen met een studie ${geefStudie()}`;
document.body.innerHTML = resultaat;





Correcte JSON object notatie:

{ 
  "moederbordsocket" : "2011s3",
  "processor" : "E3-1220v3",
  "geheugen" : "16gb" 
}





Wat doet het XMLHttpRequest?
1) sends data in the background
2) receives data
3) updates data without reloading the page




We hebben gaan nu met een voorbeeld de DOM van een webpagina doorzoeken:

HTML: 

<body>
  <div>Eerste div element met tekst als inhoud</div>
  <div>Tweede div element met een blauwe kleur</div>
  <div id="derde">Derde div element met rode tekst</div>
</body>

CSS:

div:nth-child(2){
  background-color: lightgray;
}

div:last-child {
  color: red;
}

Javascript:

console.clear();

console.group("zoeken met getElementsByTagName()");
// Ophalen van de inhoud van de 2e div; eerst halen we een array op met alle div elementen in de body
divs = document.getElementsByTagName("div");

// De tweede div is de div met index 1 in de array
huidigeDiv = divs[1];
resultaat = huidigeDiv.innerText;
console.log(resultaat);
console.groupEnd();


console.group("zoeken met getElementById()");
// Ophalen van de inhoud van de 3e div; door hem op te zoeken op basis van het 'id' attribuut. Let op het enkelvoud van de methode:
huidigeDiv = document.getElementById("derde");
resultaat = huidigeDiv.innerText;
console.log(resultaat);
console.groupEnd();

console.group("zoeken met querySelectorAll()");
// Ophalen van de inhoud van de 1e div; door hem op te zoeken op basis van de querySelectorAll, middels een CSS query. Middels [0] halen wij het eerste element van de array op:
huidigeDiv = document.querySelectorAll("div:first-child")[0];
resultaat = huidigeDiv.innerText;
console.log(resultaat);
console.groupEnd();





Er volgt nu een voorbeeld waarmee wij zelf de DOM gaan wijzgen door een functie die een link (<a> element) kan maken:

HTML:

<div class="voorbeeld">div voorbeeld</div>
<div id="test" class="voorbeeld">test</div>
<span class="voorbeeld">span voorbeeld</span>
<div id="result"></div>

CSS:

#test {
  color:red;
}
div {
  color:blue;
}

Javascript:

function createLink(href, tekst){
   var link = document.createElement("a");
   var text = document.createTextNode(tekst);
   link.appendChild(text);
   link.setAttribute("href", href);
   return link;
}

var mijnLink = createLink("http://www.google.com", "google");
var result = document.getElementById("result");
result.appendChild(mijnLink);


Met createElement("div") wordt een nieuw DIV element aangemaakt. 
Om syntactisch juist te zijn zal hij moeten aangeroepen worden vanuit het body object:
document.createElement("div")

Syntactisch niet nodig maar om nuttig te zijn wel zal de waarde die dat oplevert moeten worden opgevangen. bv in een variabele:
div = document.createElement("div")


Welke code wordt gebruikt voor het toekennen van een attribuut aan een element?
elementnaam.setAttribute("attribuutnaam","waarde")
setAttribute is een mehode van het element. Dus deze wordt met een punt (.) gescheiden van het element, in plaats van met haakjes ().


Voor het aanmaken van een nieuwe DIV htmltag in JavaScript, gebruiken we volgens de DOM methode de volgende code:
eDiv = document.createElement("div")
Met createElement("div") wordt een nieuw DIV element aangemaakt. Deze moet nog wel gekoppeld worden aan een parent zoals de BODY.


Welke code wordt gebruikt voor het toekennen van een attribuut aan een element?
1. elementnaam.setAttribute("attribuutnaam","waarde")
2. elementnaam.attribuutnaam = "waarde"
 Antwoord één wordt vooral gebruikt als er zelf gemaakte attributen in het spel zijn (buiten de standaard HTML attributen om).





Onderstaand volgt een voorbeeld met een klik, ofwel: 'click' event.
 
We zijn geïnteresseerd in het "click" event voor een div element. Als deze optreedt geven we een melding: daarvoor gebruiken we een callback functie. Deze functie wordt aangeroepen door de event listener zodra het click event op de div optreedt. 
 
In code ziet dat er als volgt uit. 

HTML:
<div>Klik hier</div>

Javascript:
// Onderstaande code werkt enkel omdat de pagina al is geladen. 
// Normaliter zou je deze code in de functie van de 'body.onload' moeten zetten



// We halen het div element op en stellen de 'onclick' eigenschap in op een functie
document.getElementsByTagName("div")[0].onclick = function() {
    alert('click');
}

// Mooiere manier:
document.getElementsByTagName("div")[0].addEventListener("click", function() { alert('click'); }, false);
// We maken hierbij gebruik van de 'addEventListener' methode. Dit zorgt ervoor dat wij o.a. kunnen aangeven met 'false' dat het event niet omhoog moet 'bubblen'


Ook in formulieren worden events veel afgevangen. Denk alleen al een invoer controle:

HTML:

<form>
  <div>
    <h2>Registratie formulier</h2>
    <span><label for="naam">Naam: </label></span>
    <input type="text" id="naam" placeholder="Vul uw naam in"/>
    <br/>
    <span><label for="geboortejaar">Geboortejaar:</label></span>
    <input type="number" id="geboortejaar" placeholder="YYYY" />
    <br/>
    <br/>
    <button id="verzend">Registreer</button>
  </div>
</form>

CSS:

div {
  background-color: lightgray;
  width: 40vw;
  padding: 20px;
}

h2 { 
   margin: 0px; 
   margin-bottom: 20px;
}

span { 
 display: inline-block;
 width: 100px;
}

button {
  margin-left: 103px;
}

label {
  font-weight: 600;
}

Javascript:

// De officieel correcte manier om een functie te koppelen aan een event
// zodra de elementen zelf geladen zijn:
document.body.onload=function(){
    document.getElementById("verzend").addEventListener(
        "click",
        function(event){
          /* Onderstaande regel zorgt ervoor dat het standaard gedrag van een button (versturen / submitten)          
          van een formulier, niet gebeurd. Indien je deze regel zou weghalen, 
          en we vullen maar één waarde in, worden beide velden na klikken gereset (pagina ververst). */
          event.preventDefault();
          
          var naam = document.getElementById("naam").value;
          var jaar = document.getElementById("geboortejaar").value;
          if (naam=="" || jaar=="")
          {
            alert("Graag beide velden invullen");    
          }
          else{                            
            var waarden = `Naam: ${naam} en geboortejaar: ${jaar}`;
            alert("Data wordt verzonden: " + waarden);
          }
        }, false
    );
}


In JavaScript kunnen wij events afvangen met de addEventListener() methode. Wat zijn voorbeelden van geldige events om mee te geven aan de addEventListener methode?
click, keydown, focus, blur Events mogen in JavaScript niet beginnen met 'on'. Dat is de oude HTML schrijfwijze voor events.
Daarnaast is het 'move' event geen geldig event. 'mousemove' zou dat bijvoorbeeld wel zijn.
Met keydown vangen wij het indrukken (en nog niet loslaten) van een toets op het toetsenbord af.


HTML:

<form>
  <div>
    <h2>Registratie formulier</h2>
    <span><label for="naam">Naam: </label></span>
    <input type="text" id="naam" placeholder="Vul uw naam in"/>
    <br/>
    <span><label for="geboortejaar">Geboortejaar:</label></span>
    <input type="number" id="geboortejaar" placeholder="YYYY" />
    <br/>
    <br/>
    <button id="verzend">Registreer</button>
  </div>
</form>

CSS:

div {
  background-color: lightgray;
  width: 40vw;
  padding: 20px;
}

h2 { 
   margin: 0px; 
   margin-bottom: 20px;
}

span { 
 display: inline-block;
 width: 100px;
}

button {
  margin-left: 103px;
}

label {
  font-weight: 600;
}

Javascript:

// De officieel correcte manier om een functie te koppelen aan een event
// zodra de elementen zelf geladen zijn:
document.body.onload=function(){
    document.getElementById("verzend").addEventListener(
        "click",
        function(event){
          /* Onderstaande regel zorgt ervoor dat het standaard gedrag van een button (versturen / submitten)          
          van een formulier, niet gebeurd. Indien je deze regel zou weghalen, 
          en we vullen maar één waarde in, worden beide velden na klikken gereset (pagina ververst). */
          event.preventDefault();
          
          var naam = document.getElementById("naam").value;
          var jaar = document.getElementById("geboortejaar").value;
          if (naam=="" || jaar=="")
          {
            alert("Graag beide velden invullen");    
          }
          else{                            
            var waarden = `Naam: ${naam} en geboortejaar: ${jaar}`;
            alert("Data wordt verzonden: " + waarden);
          }
        }, false
    );
}



































