"javascript"
Wednesday, October 6, 2010

Mime-stream

Sain lõpuks ometi tööle enam-vähem töötava mime formaadis striimi parseri. See tähendab, et ühest otsast visatakse mime-formaadis kirja sisu parserile jaokaupa ette ja teisest otsast tuleb struktureeritud objekt välja. Kui keegi viitsib jälge ajada, siis detaile saab näha siin.

Momendil on kõige suuremaks teoreetiliseks probleemiks, kui mime boundary satub kogemata poolikuna edastatavate andmete hulka. See tähendab, et andmed tulevad umbes 10kB juppidena ning on vähemalt teoreetiline võimalus, et see vajalik serva tähis tuleb pooleldi ühe ja pooleldi teise andmehulgaga. Niikaua aga kui seda ei juhtu, tundub kõik toimivat.

Kirja manustes olevate binaarsete andmetega ei tehta tegelikult hetkel veel midagi, loetakse ainult baitide arv kokku, kuid edaspidi hakkab minema binary stream otse faili (GridFS) ning e-kirja andmete objektis asendatakse manuse sisu võtmega manuse juurde GridFS andmebaasis. Nii ei ole vaja tervet manusefaili korraga mällu lugeda (see aga tähendab, et manuste suurus ei ole põhimõtteliselt oluline - katsetasin näiteks 16 MB manuse vastuvõtmist ja erilist koormust ei paistnud see tekitavat).

Avastasin ka, et juhul kui kiri sisaldab manuseid, kipuvad mitmedki e-posti kliendid panema kogu kirja sisu nested multipart bloki sisse. Välise kirja sees on veel üks väiksem kiri, mis siis sisaldab tegelikku kirja sisu. Sellisel juhul välises kirjas on a) vaid text/plain sisublokk või b) ei ole üldse midagi ja kogu kirja sisu tuleb multipart blokist otsida.

Igatahes, tundub, et kõik suuremad probleemid on praeguseks suunal saatja -> vastuvõttev server -> kliendile edastamine lahendatud. Lõpliku lahenduseni on veel palju maad, kuid see on rohkem juba tegemise vaev.

Friday, September 3, 2010

node-markdown

Vormistasin väga hea Showdown skripti Node.JS mooduliks nimega node-markdown. Tegu on siis Markdown süntaksi konverteerijaga, mis teeb Markdown tekstist HTML koodi. Installida saab mooduli npm kaudu käsuga npm install node-markdown.

Kasutamine on lihtne - tuleb laadida konverteerimisfunktsioon ja seda saabki seejärel otse kasutada.

var md = require("node-markdown").Markdown,
    html = md(markdown_text);


Täpsemalt võib lugeda mooduli lehelt.

Miks üldse Markdowni kasutada?

Tegu on “naturaalse” süntaksiga, mis on eeskuju võtnud tekstilise e-posti vormistamisest. Idee seisneb selles, et ka töötlemata tekst peaks olema silmale arusaadav ning ei paistaks otseselt kodeeringuna välja.

Näiteks

See on pealkiri
-------------------

Siin tuleb mummudega nimekiri:

  * Nimekirja element nr 1
  * Nimekirja element nr 2
  * Nimekirja element nr 3


Näeb ju arusaadav välja. Kodeerijast läbi lastes muutuks “See on pealkiri”
<H2> elemendiks, “Siia tuleb mummudega nimekiri” <P> paragrafiks ja tärnidega read <UL> nimekirjaks.

Monday, August 30, 2010

Kuidas töötab AJAX?

Ma olen sellest kunagi aastaid tagasi juba juttu teinud, aga nüüd otsustasin põhjalikumalt asjad kirja panna ning tulemuseks on seletus, kuidas teha AJAX päringuid ILMA väliste teekideta (jQuery, Prototype vms.).

Muudest juttudest on veel pooleli sündmuste haldus (hetkel on kaetud ainult DOM level 0). Üritan selle teema millalgi uuesti käsile võtta.

Friday, August 20, 2010

Node.JS v.0.2

Täna uuenes lisaks muudele asjadele ka Node.JS ja seda versioonile v.0.2. Tegu ei ole millegi põhimõttelise uuendusega vaid API fikseerimisega - kogu 0.2 perekonna juures ei tohiks API väga muutuda. Seega midagi sellist nagu promise objektide kaotamisega, kus suur hulk programme lakkasid töötamast, lähiajal enam juhtuda ei tohiks.

Saturday, August 7, 2010

Konkurss JS1K

Kes veel ei tea, siis parasjagu on käsil konkurss JS1K mis võtab vastu kuni 1 KB (1024 B) JavaScripti programme. Programmid ei tohi sõltuda ühestki välisest failist, ainsaks boonuseks on võistluslehel juba asetsev CANVAS element, mida saab mugavalt ära kasutada. Konkurss kestab kuni 10. septembrini.


Minu osalemistöö leiab siit.
Sunday, August 1, 2010

node.ee

Paar päeva tagasi sain tööle tõenäoliselt esimese avaliku node.JS serveri Eestis - node.ee. Tegu pole ses suhtes küll 100% node.JS serveriga, kuna antud platvorm ei paista maailmale kätte otse, vaid läbi nginx proksi. See tähendab, et hetkel kõik aadressid kujul node.ee/node/* teenindatakse just node.JS poolt, muude eest aga hoolitseb juba nginx.

Sellega seoses olen juba paari asja katsetanud ja ühe huvitava projektina proovisin teha kliendipoolset andmebaasi liidest. See tähendab, et server näitab välja otsad andmebaasiga majandamiseks, kuid konkreetseid tegevusi teeb selle liidese abil juba kliendi pool ehk brauseris jooksev JavaScript. Tulemust saab näha siit. Kõik päringuandmed teisendatakse vahepeal lihtsalt objektidest JSON’i kujule ja vastupidi kuid edasi antakse kliendile/andmebaasile need juba originaalkujul.

See tähendab, et kui klient koostab mingisuguse päringu (objekti kujul, näiteks {eesnimi:”Peeter”, perenimi:”Meeter”}), teisendatakse see JSON’iks, saadetakse serverile, server taastab JSON’ist uuesti objekti ja annab selle andmebaasile töötlemiseks. Täpselt sama, ainult et vastupidises järjekorras, toimub ka andmete saatmisega andmebaasist tagasi kliendile. Server otsib näitena toodud päringu alusel üles kõik kirjed, kus eesnimi on Peeter ja perekonnanimi Meeter ja tagastab need massiivina kliendile.

Juhul kui selline baas on kasutajapõhine ning erinevate kasutajate baasid on üksteisest eraldatud (näiteks serveri poolt lisatud prefiksid tabeli nimedes), peaks tulemus olema piisavalt stabiilne, et a) kliendil on väga suur vabadus käia andmetega ringi nagu soov on ning b) üks klient ei saa ligi teise kliendi andmetele. Suurepärane näiteks veebilehel olevatele widgetitele enda seadete salvestamiseks jms.

Huvitav teema indeed!

Saturday, July 31, 2010

Statistika: JavaScripti kasutamine Eesti veebilehtedes

Eelmistes postitustes tundsin huvi milliseid JavaScripti teeke Eesti veebilehed kõige parema meelega kasutavad. Esialgu uurisin käsitsi lappasin läbi 30 enam külastatavat veebilehte, kuid kuigi tulemused olid muidugi huvitavad, ei andnud see suuremat pilti Eesti veebilehtede kohta üldisemalt. Seega kirjutasin lihtsa roboti, mis võttis ette kõigi Eesti veebilehtede esilehed ja kontrollis nendes kasutatud teeke.

Tulemused pole 100% usaldusväärsed kuid piisavalt ülevaatlikud. Probleemid tekkisid peamiselt kahest asjast - kas ebaõnnestus serveriga ühendus (läks kirja, et sait ei kasuta JavaScripti) või oli lehel näiteks osa skripte pandud tegelikult HTML kommentaaride sisse. Robot otsis aga skripte regulaaravaldistega, ning kommentaare ei jälginud. Nii jäid esimesel juhul osad asjad märkimata, aga teisel juhul märgiti üle asju, mida tegelikult ei kasutatud. Samuti jäi teegi kasutamine märkimata, kui see laeti lehele dünaamiliselt (näiteks Google Ajax API goole.load abil). Kokkuvõttes aga ei tohiks need probleemid lõpptulemust väga mõjutada, kuna valim oli suhteliselt suur (~50 000 veebilehte).

NB! Kõik numbrid on graafikutel protsentides.

1. JavaScripti kasutamine üldisemalt

Selles testis vaatasin, kas sait a) ei kasutanaud üldse JavaScripti, b) kasutas mõnda tuntud teeki või c) ei kasutanud ühtegi teeki, vaid midagi muud (siia alla lähevad ka Google Analytics jms loendurprogrammid).



2. Teekide omavaheline osakaal

Järgmisena vaatasin, milline on teekide kasutamise omavaheline osakaal - milliseid teeke kasutatakse rohkem, milliseid vähem. Teeke kasutavaid saite oli üldse kokku 19%.



3. Teekide versioonid

Viimasena uurisin täpsemalt teegi siseselt, millised konkreetsed versioonid kindlast teegist kasutusel on ja millised on nende omavahelised suhted.

3.1 jQuery

jQuery on enimkasutatud teek ja seega on ka erinevaid versioone kasutusel seinast seina.



3.2 MooTools



3.3 Prototype



3.4 YAHOO



3.5 Ext-JS



3.6 DOJO



Nagu näha on olukord üsna kirju. Teekide hulgas troonib suurelt jQuery, mida kasutab sama palju veebilehti, kui kõiki teisi kokku. Samas aga on veel väga palju veebilehti, mis teeke ei kasuta. Siinkohal tundub olevat mõistlik kasutada Google AJAX API majutust teekide serveerimiseks - juhul kui kasvõi väike osa veebisaitidest seda kasutavad, muutub üsna tõenäoliseks et kui kasutaja esimest korda sinu saidile satub, on tal saidil kasutatav teek juba brauseri poolt puhverdatud ja seega on säästetud ekstra 100kB lehe laadimisaega ja mis veel tähtsam - 100kB võrguliiklust. Üks klient ei tähenda suurt midagi, aga kümne tuhande kliendi puhul on see juba terve gigabait.
Thursday, July 29, 2010

JavaScripti teekide kasutamine Eesti lehtedel vol 2

Panin eile käima roboti, mis kammib läbi Eesti veebilehtede esikülgi (kasutan NETI serverite nimekirja) ja lootsin, et täna õhtuks on tulemused käes. Paraku on robot väga aeglane ja praeguseks on läbi käidud vaid pool 50 000 aadressist, seega mingeid lõplikke järeldusi veel teha ei saa. Kui robot on oma töö ükskord lõpetanud, siis panen tulemused kindlasti üles.

Küll aga võib niipalju öelda, et praeguseks kogutud andmete põhjal on juba selgunud paar huvitavat asja. Esiteks fakt mida võis juba varem eeldada - suurem osa veebilehtedest ei kasutagi (vähemalt populaarsemaid) teeke. Teiseks veidi üllatuslikuks momendiks on enamkasutatavate teekide järjekord. Esimene on oodatult suure ülekaaluga jQuery, kuid järgmised kohad läksid minu ennustustest veidi lahku. Aga sellest kõigest siis, kui lõplikud tulemused käes.

Seega kuigi uuringutulemusi veel päris kätte täna ei saanud, õnnestus mul lõpuks ometi saada üles Node.JS server aadressile node.ee. Siiani olen katsetanud localhostis ning veidi ka Amazon EC2 virtuaalmasinas, kuid Amazon on lihtsalt katsetamiseks kallis (ligi 1000 krooni kuus kui server töötab 24/7), localhosti aga väljastpoolt keegi ligi ei pääse. Täna siis lõpuks tellisin Zone virtuaalse privaatserveri ja seadistasin selle jooksutama Nginx + Node.JS + mongoDB.

Nginx’i installisin Node.JS ette puhtpraktilistel kaalutlustel - et saaks kasutada serverit ka tavalise failiserverina (näiteks kasvõi HTML ja pildifailide serveerimiseks), Node.JS puhul on see veidi ebamugavam. Pealegi saan nii Node.JS’i taustal restartida, ilma et server sel ajal eetrist ära kaoks. Failid jõuavad ikka kohale, lihtsalt Node.JS skriptide poole pöördudes tuleb sel ajal Error 503 Bad Gateway.

MongoDB valisin andmebaasiks seetõttu, et mul õnnestus see ära installida. Tahtsin tegelikult kasutada CouchDB‘d, kuid miskipärast kukkus paketihaldur selle installi peale nii pröökama, et kogu paketimajandus läks veidi nihu (ei saanud enam midagi peale ega maha installida) ja pidin Google abil veidi nikerdama enne kui kõik korda sain. CouchDB aga ei hakanudki tööle ja võtsin selle asemel siis eelpoolmainitud MongoDB.

Tuesday, July 13, 2010

HTML Notifications API

HTML5 Notifications API võimaldab veebilehtedel brauseriaknast “välja murda” ja kuvada erinevaid teavitusi veebilehe asukohast sõltumatult töölaual sarnasena näiteks MSN Messengeri sisselogimisteavitustega. Pikemalt kirjutasin sellest siin.

Thursday, July 8, 2010

JavaScripti moodulite vaheline suhtlus JavaScriptis

Tänapäevased keerulisemad veebilehed koosnevad tõenäoliselt mitmetest eri komponentidest, mida suuremal või vähemal määral manatakse lehele JavaScripti abil. Nendeks komponentideks võivad muu hulgas olla näiteks järgmised elemendid - sisselogimise vorm mis avaneb hiirekliki peale (algselt on näha ainult tekst “Logi sisse”); bännerite kuvamine lehel; pisike interaktiivne kast ilmateateinfoga (saab valida piirkonda, aega jne); lightbox efekt piltide kuvamiseks; valuuta konverteerimise vidin jms.

Kuigi eemalt vaadates pole neil komponentidel palju ühist, võib siiski juhtuda olukordi kus eri komponendid vajavad võimalust üksteisega suhtlemiseks, et selle abil enese tööd parendada. Näiteks kui kasutaja valib ilmateate kastis mõne muu asukoha, kui algselt määratud, tahaks bännerite kuvaja võibolla näidata kasutajale ainult neid bännereid, mis on valitud piirkonnaga seotud. Või kui kasutaja passiivsuse tõttu keskkonnast automaatselt välja logitakse, ilma uut lehenäitamist tegemata, tahaksid tõenäoliselt kõik komponendid sellest teada saada, nii et suudaksid endid sobivalt ümber häälestada. Rääkimata siis veel sellistest juhtudest, kus seosed on palju otsesemad - kui kasutaja end välja logib/välja logitakse tuleks taastada vahepeal eemaldatud sisselogimise link.

Tõenäoliselt tegelevad kõikide nende operatsioonidega erinevad moodulid. Sisselogimisega üks, bännerite kuvamisega teine ja ilmateatega hoopis kolmas. Seega tuleb välja mõelda mingi mõistlik viis, kuidas need eraldiseisvad moodulid üksteisega suheldud saaks.

Naabrite eiramine

Kõige triviaalsem on lihtsalt teist moodulit eirata ja selle tegevused ise läbi viia. Näiteks kui ilmateate kastis on element <a id=”tervitus_tekst”> mis sisseloginud kasutajale teatab “Tere [nimi]!” ning väljaloginud kasutajale “Tere kasutaja!”, siis kutsudes esile väljalogimisprotsessi klikkides lehel lingil “Logi välja”, ei anna kasutaja haldamise moodul sellest väljalogimisest ilmateate moodulile teada, vaid lihtsalt kirjutab selles oleva kasutajainfoga seotud elemendi üle.

Kasutaja logib välja ->
kasutajate moodul:
$(“tervitus_tekst”).innerHTML=”Tere kasutaja!”

Antud lähenemine on võibolla lihtsustamise mõttes mõistlik väga väiksemahuliste, kuid kindlasti mitte keerulisemate elementide korral. Esiteks võib selline käitumine teise mooduli katki teha - too eeldab, et lehel on üks asi, tegelikult on aga hoopis midagi muud. Samuti võib kõik katki minna, kui lehel polegi ilmateate moodulit. Pealegi lõhutakse nii päris korralikult modulaarsust, kus iga komponent peaks olema eraldiseisev tervik ning pärsitakse ka skaleeruvust programmikoodi mõistes - taoline tegevus on alati erand ning kui erandid kipuvad kuhjuma, on oodata suuri probleeme.

Tagasikutse funktsioonide kasutamine

Keerulisem viis oleks seada üles tagasikutsefunktsioonide registreerimise süsteem. Sellisel juhul ilmateate moodul ütleks lehe laadimisel, et erinevate sisselogimisega seotud sündmuste korral tuleks käivitada parameetrina antud tagasikutsefunktsioon. Juhul kui nüüd kasutaja välja logib, võtab kasutajate haldamise moodul ette kõik sedasi registreeritud tagasikutsefunktsioonid ja paneb need ükshaaval käima. Nii saab ilmateate moodul teada, et kasutaja on välja loginud ja asendab ise tervituse teksti vastavaga.

Tagasikutse funktsiooni registreerimine ->
ilmateate moodul:
kasutajate_moodul.notify_logout_callback = function(){
    ilmateate_moodul.kasutaja_logis_välja();
};

Kasutaja logis välja ->
kasutajate moodul:
kasutajate_moodul.notify_logout_callback();

Antud lähenemine on juba tunduvalt parem kui eelmisena näidatud variant - seekord on moodulid üksteisest juba üsna eraldatud, kumbki teise tööpõllule ei roni. Samuti ei teki ka probleeme, kui ilmateate moodul lehelt üldse puudu on. Küll aga tekivad probleemid siis, kui lehel puudub sisselogimise moodul. Moodulid on endiselt üksteisest kaudselt sõltuvad, kuna vähemalt üks eeldab teise olemasolu (ilmateate moodul eeldab kasutajate mooduli olemasolu).

Kohandatud sündmuste kasutamine

Nõrgalt seotud elementide korral tasuks kõige rohke kaaluda just kohandatud sündmuste kasutusele võttu. Süsteem oleks sarnane nagu tavaliste tagasikutse funktsioonide kasutamise korralgi - ilmateate moodul registreerib tagasikutse funktsiooni, mis käivitatakse juhul kui kasutaja haldamise moodul on kasutaja välja loginud, kuid seekord ei registreeritaks seda sündmust mitte otse kasutajate haldaja pihta, vaid hoopis kohandatud sündmusena mõne suvalise DOM elemendi, näiteks document pihta.

Kui nüüd kasutaja välja logib, annab kasutajate haldamise moodul sellest teada, aga mitte otse ilmateate moodulile, vaid hoopis sellele sõnumikandjana kasutatavale elemendile. Too võtab ükshaaval ette kõik huvitatud ja käivitab nende tagasikutse funktsioonid.

Kohandatud sündmuse registreerimine ->
ilmateate moodul:
document.observe(“kasutaja:logis-välja”, function(event){
    ilmateate_moodul.kasutaja_logis_välja();
});

Kasutaja logis välja ->
kasutajate moodul:
document.fire(“kasutaja:logis-välja”);

Viimane lähenemine on käsitletutest kõige turvalisem - kõik moodulid on üksteisest täielikult eraldatud. Kuna üksteisega suhtlemiseks kasutatakse vahendajat, ei puutu ükski moodul otseselt teisega kunagi kokku. Nii võib suvaline moodul heita üles teate, et nüüd midagi juhtus ja juhul kui mõnda teist moodulit see huvitama peaks, saab ta selle teate kätte. Kui aga selliseid huvitatuid pole, ei lähe ka midagi katki. Samuti kui mõni moodul määrab ära teda huvitava sündmuse, siis ei juhtu ka midagi sellest, kui ühtegi taolist sündmust esilekutsuvat moodulit lehel polegi.

Täiendavaks plussiks kohandatud sündmuste kasutamise korral oleks veel “tasuta kaasa tulevad” sündmuste haldamise võimalused - iga käivitatud tagasikutse funktsioon saab standardsel viisil edasist sündmuse täitmist peatada (event.stopPropagation), saab tegevust ka maha registreerida, nii et seda järgmiste sündmuste juures ei kasutata (document.stopObserving) jne.

Vaata ka seda: Ajaxian, How Custom Events Will Save Us All

NB! Näidetes on kasutatud Prototype käsklusi, sama on võimalik saavutada ka kõigi teiste sarnaste teekide abil.

My Tumblr Likes ♥