Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: JavaScript: JS: Monta käsittelijää tapahtumalle

Metabolix [26.11.2008 19:43:39]

#

Jos tekee monikäyttöisiä JavaScript-järjestelmiä, jotka vaativat alustustoimenpiteitä sivun latauduttua, täytyy tietenkin kirjoittaa käsittelijä window.onload-tapahtumalle. Joskus kuitenkin sattuu niin, että näitä järjestelmiä osuu samalle sivulle useampi, ja jokainen niistä tarvitsisi oman onload-koodinsa. Yksi vaihtoehto on tietenkin kirjoittaa aina uusi funktio, joka kutsuu erikseen jokaisen luokan onload-käsittelijää. On kuitenkin ikävä kirjoitella sellaisia joka sivulle, ja silloin voikin käyttää tässä koodivinkissä esitettävää jippoa.

Jos jotakin muuttujaa ei määritellä funktion sisällä mutta se on kuitenkin määritelty funktion ulkopuolella, viittaus tähän nimenomaiseen muuttujaan jää elämään funktiossa. Voidaan siis määritellä ensin listaobjekti ja sitten funktio, joka sitä käyttää, ja vasta lopuksi lisäillä tähän listaan sisältöä — joka siis päätyy funktion käyttöön.

Tässä koodivinkissä tehdään selkeyden (?) vuoksi ensin tavallinen olio, joka sisältää taulukon oikeasti kutsuttavista funktioista ja funktiot näiden lisäämiseen ja kutsumiseen. Sitten tehdään funktio, joka sisältää viittauksen tähän olioon ja kutsuu tästä funktiota, joka kutsuu edelleen näitä taulukon funktioita. JavaScriptissa funktiokin on sattumalta olio, joten lopuksi vielä lisätään sille oma jäsenfunktio, joka kutsuu edelleen sisäisen, "tavallisen" olion vastaavaa jäsenfunktiota. Näin saadaan aikaan funktio, jonka jäsenfunktiolla voidaan lisätä taulukkoon funktioita ja jota kutsumalla kutsutaankin kerralla kaikkia näitä lisättyjä funktioita.

Ensimmäinen listaus sisältää itse koodin, toisessa on esimerkki sen käytöstä.

// tapahtuma.js

// Luokan "tapahtuma" muodostin
function tapahtuma() {
  // Jäsenenä on lista funktioista
  this.lista = [];
  // Funktiota varten tarvitaan viittaus tähän olioon
  var _this = this;
  // Funktio kutsuu tämän olion funktiota "kutsu"
  this.funktio = function (parametri) {
    _this.kutsu(this, parametri);
  }
  // Lisätään vielä funktiolle jäsen, jolla kutsuttavia voi lisätä
  this.funktio.lisaa = function (f) {
    _this.lisaa(f);
  }
}
// Tässä on itse luokan funktio "lisaa"
tapahtuma.prototype.lisaa = function (f) {
  this.lista.push(f);
}
// Lopuksi tarvitaan luokan funktio "kutsu", joka kutsuu listan funktioita
tapahtuma.prototype.kutsu = function (_this, parametri) {
  for (var i in this.lista) {
    this.lista[i].call(_this, parametri);
  }
}
// Lisätään luokan muodostinfunktiolle vielä jäsenfunktio "uusi",
// jolla saadaan näppärästi olion sijaan suoraan funktio
tapahtuma.uusi = function() {
  var t = new tapahtuma();
  return t.funktio;
}

// Lisätään valmiiksi window.onload-tapahtumalle tällainen
window.onload = tapahtuma.uusi();
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="fi" lang="fi" xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Monta onload-tapahtumaa?</title>
  <script type="text/javascript" src="tapahtuma.js"></script>
  <script type="text/javascript">
    /* <![CDATA[ */
    // Lisätään nimetön funktio:
    window.onload.lisaa(function() {
      alert("Ensimmäinen onload-funktio!");
    });
    // Lisätään nimellinen funktio:
    function window_onload_2() {
      alert("Toinen onload-funktio!");
    }
    window.onload.lisaa(window_onload_2);
    // Molempia lisättyjä kutsutaan sitten, kun sivu on ladattu.
    /* ]]> */
  </script>
</head>
<body>
</body>
</html>

Pekka Karjalainen [08.12.2008 10:32:16]

#

Toinen tapa:

// tapahtuma.js
window.onload = function () {
  var lista = [];
  function kutsu() { for (var i in lista) lista[i](); }
  kutsu.lisaa = function (f) { lista.push(f); }
  return kutsu;
}();

Suositeltavaa lukemista: http://en.wikipedia.org/wiki/Closure_(computer_science)

jo123 [01.02.2009 20:58:06]

#

Kopeekka kirjoitti:

Suositeltavaa lukemista: http://en.wikipedia.org/wiki/Closure_(computer_science)

Taisi jäädä viimmeinen sulje ulos linkistä. ;)

esajeejee [13.03.2011 22:16:16]

#

Pekka Karjalainen kirjoitti:

Toinen tapa:

// tapahtuma.js
window.onload = function () {
  var lista = [];
  function kutsu() { for (var i in lista) lista[i](); }
  kutsu.lisaa = function (f) { lista.push(f); }
  return kutsu;
}();

Tämä käy läpi myös arrayn prototyypin ja kutsuu kaikkia siellä olevia propertyjä/metodeja funktiona...

Array.prototype.$ = function(){
this[0] = 3;
};
var a = [ function(){alert("moi"); } ];

alert(a[0]) // function(){ alert("moi"); }

for (var i in a ) {
a[i]();
}

alert(a[0]) // 3 (prototyyppimetodia kutsuttiin loopissa joka muutti funktiomuuttujan numeromuuttujaks)

Eli järjestykestä riippuen saatetana kutsua numeroa 3 funktiona. Eli for looppi pitäs olla, ei for in.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta