reede, 30. aprill 2010

JS: "this" ja sulundid 2 (HTML inline sündmused)

JavaScript võimaldab kasutada mitmesuguseid sündmuseid - näiteks on võimalik käivitada programmi funktsioon kui kasutaja klikib lehel mingil kindlal elemendil või kui hiir liigub üle selle elemendi. Kuigi kõige lihtsam on seda teha otse HTML koodi sees, nn. inline (<div onclick="alert('klikk!')">kliki mind</div>), siis soovitatav kasutusjuht oleks siiski defineerida sündmus HTML koodist eraldi, eristada programmiline osa dokumendist (element.addEventListener("click", callback, false);). Mida aga teha siis, kui meil on tarvis siiski kasutada inline sündmust, kuid tegu pole mitte "päris" sündmusega, vaid hoopis kohandatud, ise defineeritud ja väljakutsutava sündmusega?

Ütleme et meil on olukord, kus tahame HTML elementidele lisada inline kohandatud sündmuseid, näiteks pookida elemendile külge väljamõeldud sündmust nimega kell12, mis rakendub juhul kui kell saab 24:00 (eeldusel et sama lehekülg on brauseris sel ajal lahti)

<span onkell12="alert(this.innerHTML)" style="display:none">Käes on südaöö!</span>

Sündmuse parameetri prefiksiks on seatud sarnaselt teistele inline sündmustele (onclick, onmouseover jne) "on", kuid see ei ole tehniline vaid põhimõtteline seadistus, sama hästi võiks see olla lihtsalt "kell12" või "kellasyndmus". Näite järgi peaks kell 24:00 tulema kasutajale teade, mille sisuks on konkreetse SPAN elemendi sisu (innerHTML, "Käes on kesköö!").

Kuidas siis sellist sündmust tööle panna?

Esiteks tuleb elemendist sündmuse  sisu kuidagi kätte saada. Seda saab teha getAttribute meetodiga.

var syndmus = span_element.getAttribute("onkell12","");

Kui sündmuse sisu on käes, tuleks see käivitada. Aga kuna tegu pole mitte funktsiooni-, vaid tekstilise väärtusega, tuleb saadud tekst implementaatoris programmiks muuta. Selle jaoks kasutatakse reeglina käsklust eval. Antud käsklus võtab parameetrina saadud teksti ning muudab selle JavaScripti koodiks. Näiteks nii - eval("alert(1)");

Siinjuhul eval siiski ei kõlba, kuna kuidagi on vaja siduda this väärtus käivitatavas tekstis õige SPAN elemendiga, eval puhul oleks this väärtuseks aga window. Eelmisest postitusest tutvustatud bind meetodit vms. ei saa siin otse kasutada, kuna eval käivitab, mitte ei tagasta funktsiooni. Siin tuleb appi konstruktor Function - nimelt Function konstruktor käitub eval käsule sarnaselt, teisendades teksti programmiks, kuid käivitamise asemel tagastab funktsiooniobjekti ning sellele saab juba rakendada this väärtuse sidumiseks meetodit call.

Function(syndmus).call(span_element);

Antud konstruktsioon kõigepealt loob tekstilisest lähtekoodist (muutuja syndmus sisu) funktsiooniobjekti; ning seejrel funktsiooni meetod call seob funktsioonis this väärtuseks HTML elemendi span_element ning käivitab niiviisi saadud funktsiooni.

Kokkuvõttes oleks skript siis järgmine. Seadistatakse timeout käsklus, mis käivitatakse täpselt kell 24:00. Lehelt otsitakse käivituse käigus üles kõik SPAN elemendid ning üritatakse kasutada nende elementide onkell12 atribuute.

window.setTimeout(function(){
    var spans = document.body.getElementsByTagName("span");
    for(var i=0, len = spans.length; i<len; i++){
         Function(
           spans[i].getAttribute("onkell12","")
         ).call(spans[i]);
    }
},new Date(+new Date()+86400000).setHours(0,0,0,0)-new Date());
Järgmises postituses üritan millalgi kirjutada XHMTL elementide laiendamisest oma nimeruumi elementidega (näiteks nagu FaceBook'i XFBML elemendid ) - seal muutub oluliseks ka siin postituses kirjeldatud inline sündmuste süsteem, kuna nii on mugav võõraid elemente enda lehele külge pookida.

Kommentaare ei ole: