Johdatus ohjelmointiin

Sorakuilu

DOM demokokoelma

Tavallisimman tapahtumat

Tapahtumia on siis tusinoittain ....

Events (tapahtumat)

Tapahtumaan reagoidaan luomassa käsittelijä (handler) - funktio, joka ajetaan, kun tapahtuma tapahtuu.

Se sijoitetaan HTML:n sekaan laittamalla tapahtuman eteen on (siis onclick, onload jne).

Esimerkiksi:

Koodi

<input value="Klikkaa" onclick="alert('Click!')" type="button">

Huomaa lainaus- ja heittomerkkien käyttö: onclickin jälkeen käytetään samalla tavalla kuin muissakin HTML-attribuuteissa lainausmerkkiä " ja funktiossa tai kutsuttavassa ohjelmassa '-merkkiä.

Kohta A: Perinteinen malli

Siis yksinkertaisin tapa saada elementti vastaamaan tapahtumaan funktiolla on elementin .onclick -ominaisuus. Kun elementtiä klikataan , funktio suoritetaan. Funktion sisällä tärkeä muuttuja on elementti, jota klikattiin.

Tässä on HTML 'Suorita' buttonille:

<button id="first">Suorita</button>

Yleensä on selkeämpää käyttää funktiota kuin sijoittaa koodia attribuutin sisälle.

Kirjoita JavaScriptiä, joka hakee buttonin getElementById-metodilla ja asettaa elementin .onclick -ominaisuudella kutsumaan anonyymiä funktiota.

Funktiota käytetään vain kerran, joten ei ole syytä antaa sille erikseen nimeä, vaan se kirjoitetaan suoraan samalle paikalle kuin funktion kutsukin tulisi.

Tämä funktio vaihtaa buttonin style.background ominaisuuden '#ff8':ksi.

<script>
  document.getElementById('first').onclick = function() {
  this.style.background = '#ff8';
};
</script>

Kohta B: WC3 Event Model (tapahtumamalli)

Yläpuolinen perinteinen malli voi aiheuttaa pahoja virhetilanteita (esim. kaksi eri kirjastoa voi yrittää asettaa tapahtumankäsittelijän samalle elementille). Ongelma tulee esille isoissa sovelluksissa.

addEventListener funktio tarjoaa joustavamman metodin tapahtumankäsittelyyn.

element.addEventListener('click', yourFunction, false)

Ensimmäinen parametri on tapahtuma (event), toinen funktio, jota tapahtuma kutsuu ja kolmas, ei-pakollinen vaikuttaa tapaan, jolla tapahtuma vaikuttaa elementin esi-isiin. Sen oletusarvo ja tavllisin arvo on false.

Tässä on HTML 'Suorita' buttonille:
<button id="w3c">Suorita</button>

Kirjoita JavaScriptiä, joka käyttää addEventListener:iä muuttamaan buttonin style.background ominaisuutta to '#ff8':ksi, kun sitä klikataan. Ja bonuksena, yritä lisätä toinen, erillinen klikkauksen käsittelijä, joka kutsuu ikkunaa: alert('Hello')

Kohta C: removeEventListener

Kun olet lisännyt tapahtumankuuntelijan, se toimii jokaisella tapahtuman kerralla. Jotta saat kuuntelun loppumaan, käytä element.removeEventListener('click', yourFunction, false) funktiota. Huomaa, että removeEventListener täytyy osoittaa samaa funktiota, jota käytit tehdessäsi addEventListener:in.

HTML

<img id="once_star" src="./kuvat/star_on.gif">

Kirjoita JavaScriptiä, joka käyttää addEventListener:iä avamaan alert('Hello') dialogin, kun tähteä klikataan. Tämän käsittelijän tulee myös olla itsensätuhoava, siis siinä on removeEventListener, joka estää sen suorittamisen jatkossa.

Kuinka kutsun funktiota?

Voimme kutsua olemassaolevaa funktiota tapahtumasta.


function sayThanks() {
  alert('Thanks!');
}

elem.onclick = sayThanks;


// right
button.onclick = sayThanks;

// wrong
button.onclick = sayThanks();

Pistenotaatioon ei sulkuja

Pistenotaatiossa kutsu tehdään ilman funktion sulkuosaa. Tämä sen takia, että sulut lisäämällä kutsusta tulee funktion kutsu ja vastaukseksi odotetaan funktion palauttamaa arvoa. Koska funktio ei palauta mitään, tulee virhetilanne.

HTML-merkkaukseen sulut

Toisaalta HTML-merkkauksessa tarvitsemme sulut:


<input type="button" id="button" onclick="sayThanks()">

Syy eroon on seuraava: kun selainohjelma lukee attribuutin, se luo samalla käsittelijäfunktion, jonka runko on attribuutin sisältö.

Siis merkkaus luo tämän ominaisuuden:


button.onclick = function() {
  sayThanks(); // <-- attribuutin sisältö menee tähän
};

Kohta D: Event object (tapahtumaolio)

Pari olion ominaisuuttaa:

Lisää ominaisuuksia.

Kun tapahtumankäsittelijää kutsutaan, se saa yhden argumentin, Event-olion. Tämä olio sisältää paljon hyödyllistä tietoa tapahtumasta, esim. mitä hiiren painiketta käytettiin, oliko Shif- tai Control-painike alhaalla jne. Klikkaa tähteä ja tarkista konsolista siitä seuraavaa tapahtumaoliota:

<img id="event_star" src="star_on.gif">

Tässä JavaScript koodi ylläolevalle tähdelle:

<script>
var handler = function(e) {
  console.log(e);
};
document.getElementById('event_star').addEventListener('click', handler, false);
</script>

Yksi hyödyllisimmistä ominaisuuksista on target, joka kertoo, mitä DOM nodea klikattiin (tai muuten manipuloitiin). Se mahdollistaa sen, että parent nodelle voi lisätä yksittäisen tapahtumankäsittelijän ja sitten käsitellä sopivaa nodea, kun tapahtuma on jo suoritettu.

Tässä on tähtiä sisältävän taulukko ja sen HTML:

<table id="star_table">
  <tr>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
  <tr>
  </tr>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
  <tr>
    </tr>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
  <tr>
    </tr>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
  <tr>
</table>

Tavoitteena on tehdä ohjelma, joka "sammuttaa" tähdet, kun hiiri kulkee tähden yli (mouseover). Mutta jotta ei tehtäisi 100:a tapahtumankäsittelijää, luodaan taulukolle yksi käsittelijä, joka käyttää tapahtuman target-ominaisuutta hyväksi muuttamaan oikean tähden src-attribuuttia.

Kohta E: preventDefault

Tapahtumaolio, joka välietään käsittelijäfunktioille sisältää myös joitakin hyödyllisiä metodeja, joilla voi vaikuttaa siihen, mitä tapahtuu sen jälkeen kun käsittelijä lopettaa suorituksen. Yksi näsitä metodeista on preventDefault. Metodia kutsuttaessa se estää selaimelta sen normaalit tapahtumanvastaustoiminnot. Yksi esimerkki on vaikuttaa selaimen sisältövalikona ulkoasuun.

<form>
 <p>Puhelinumero:</p>
 <input type="text" id="phone">
</form>

Kirjoita JavaScript-ohjelma, joka lisää näppäimen painamiselle tekstikentässä "phone" tapahtumankäsittelijän: Jos käyttäjä kirjoittaa muuta kuin numeroita (ohjelma tarkistaa tapahtuman merkkikoodin ASCII-arvon) ja peruu tapahtuman kutsumalla preventDefault.

bubbling and capturing

Edellisen tehtävän koodissa eventListeneriin laitettiin kolmas parametri (false). Parametrillä vaikutetaan eventin vaikutusalueeseen (capture), elementin vanhempiin ja esivanhempiin. artikkeli https://javascript.info/bubbling-and-capturing kertoo tarkemmin, mistä on kyse.

Oletusarvo on false, siis capturea ei tehdä (harvinainen). Koska arvo on oletusarvo, sen saa jättää pois.


Lähdekoodi

<!DOCTYPE html>
<html lang="fi">
<head>
    <title>
        DOM demot 4
    </title>
    <meta charset="UTF-8">
</head>
<body>

    <h2>Kohta B</h2>

    <button id="w3c">Suorita</button>
    <!-- Kirjoita JavaScriptiä, joka käyttää addEventListener:iä muuttamaan buttonin style.background ominaisuutta to '#ff8':ksi, kun sitä klikataan. Ja bonuksena, yritä lisätä toinen, erillinen klikkauksen käsittelijä, joka kutsuu ikkunaa: alert('Hello')-->

    <script>
        var button = document.getElementById('w3c');
        button.addEventListener('click',function() {
            this.style.background = '#ff8';
        }, false);
        button.addEventListener('click', function() {
            alert('Hello!');
        }, false);
    </script>

    <h2>Kohta C</h2>

    <img id="once_star" src = "./kuvat/star_on.gif">
    <!-- Kirjoita JavaScriptiä, joka käyttää addEventListener:iä avamaan alert('Hello') dialogin, kun tähteä klikataan. Tämän käsittelijän tulee myös olla itsensätuhoava, siis siinä on removeEventListener, joka estää sen suorittamisen jatkossa.-->

    <script>
        var image = document.getElementById('once_star');
        var clickFunc = function() {
            alert('Hello');
            image.removeEventListener('click', clickFunc, false);
        }
        image.addEventListener('click', clickFunc, false);
    </script>

<h2>Kohta D</h2>
<table id="star_table">
    <tr>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
    <tr>
    </tr>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
    <tr>
      </tr>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
    <tr>
      </tr>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
      <td><img src="./kuvat/star_off.gif"><td>
    <tr>
  </table>

  <script>
      var func = function(e) {
          if(e.target.src) {
              e.target.src='./kuvat/star_on.gif';
          }
      }
      document.getElementById('star_table').addEventListener('mouseover', func, false);
  </script>

  <h2>Kohta E</h2>

  <form>
    <p>Puhelinumero:</p>
    <input type="text" id="phone">
   </form>

   <!-- Kirjoita JavaScript-ohjelma, joka lisää näppäimen painamiselle tekstikentässä "phone" tapahtumankäsittelijän: Jos käyttäjä kirjoittaa muuta kuin numeroita (ohjelma tarkistaa tapahtuman merkkikoodin ASCII-arvon) ja peruu tapahtuman kutsumalla preventDefault. -->

   <script>
       var func = function (e) {
           if(e.charCode < 48 || e.charCode > 57) {
               e.preventDefault();
           }
       }
       document.getElementById('phone').addEventListener('keypress', func, false);
   </script>