esmaspäev, 2. november 2009

onhashchange event

Üheks HTML5 standardi järgi lisanduvaks window objekti sündmuseks on onhashchange ehk siis sündmus, mis annab JavaScriptile teada, kui URL-is on muutunud URL'i lõpus asuv #hash.

Milleks see kasulik on?

Sisuliselt saab antud sündmusega lahendada Ajax põhisel navigeerimisel (lehte ennast navigeerimisel ei laeta, muudetakse vaid osa lehe sisust serverist laetud andmetega) edasi-tagasi liikumise ning ka järjehoidjate probleemi.

Probleem

Nimelt kui kasutaja enda teada liigub lehel ringi ja ühel hetkel tahab tagasi liikuda lehe eelmise oleku juurde ning vajutab selle saavutamiseks brauseri back nuppu, siis selle asemel et saavutada lehe eelmine olek, navigeeritakse lehelt üldse minema. Kuna tegelikkuses vahepeal ühtegi lehe laadimist ei ole toimunud, siis brauseri jaoks tähendab tagasiminek tagasiminekut eelmise veebilehe juurde.

#hash lingid aga on mõeldud just lehesiseseks navigeerimiseks (lehe laadimist ei toimu) ning brauser salvestab need muutused ka kenasti brauseri ajaloos, kust võetakse info edasi-tagasi liikumise kohta. Siiani aga on probleemiks olnud, et skript ei saa mitte kuidagi teada, kui kasutaja mingil viisil #hash linki muudab.

Loomulikult saab erinevatel kaudsetel viisidel seda asja lahendada. Näiteks kui kasutaja klikib lingil #teemidagi, siis on lingile lisatud ka vastav onclick sündmus, mis selle "teemidagi" operatsiooni ära teeks. URL muutub ja operatsioon tehakse ära.

Probleem aga tekib ikkagi, kui kasutaja nüüd back nuppu vajutab. Seekord ju onclick sündmus ei rakendu ja skript ei tea rakenduda. Sama lugu on järjehoidjatega. Kui kasutaja lisab #teemidagi URL enda järjehoidjatesse ja avab selle sealt, ei tea skript samuti rakendumisest midagi.

Lahendus

Lahendus peitubki onhashchange sündmuses. Sellisel viisil ei pea lingile defineerima täiendavat onclick sündmust, mis muudab ära nii hash'i kui teeb ka nõutud operatsiooni, vaid ühe universaalse onhashchange sündmuse.

Kui kasutaja klikib lingile #teemidagi, siis brauser muudab URL-i ära ning seejärel annab onhashchange sündmuse kuulajale teada, et hash on muutunud. Kuulaja kontrollib, et mis on hetkel hashi väärtus (location.hash) ja teeb sellele vastava tegevuse.

Kui kasutaja klikib edasi-tagasi nuppe või avab lingi järjehoidja kaudu, siis rakendub täpselt sama skeem. Brauser annab kogu aeg vastavale kuulajale teada hashi muutumisest ning skript teab alati käituda vastavalt vajadusele.

Kus töötab?

onhashchange sündmuse tugi on olemas brauserites Firefox 3.6 beta, Internet Explorer 8, Chrome 4, Webkit nightly. Eeldades, et brauserid uuenevad praeguses tempos peaks umbes poole aasta pärast antud sündmuse haldust toetama enamus brauseritest.

pühapäev, 25. oktoober 2009

Open source CMS Google App Engine platvormile

Olen praktiliselt kogu oma hostingu kolinud Google App Engine peale, kuid sinna saab saata ainult aplikatsioone - vahel aga on vajadus lihtsalt kodulehe järele. Ükski olemasolev CMS sinna peale aga ei sobi (kasutusel on Python+BigTable vs. standardne PHP+MySQL). Seega otsustasin luua ise lihtsa CMS-i ja olen nüüd paar päeva sellega vaeva näinud. Tulemuseks on TurbineCMS.

Hetkel ei tasu koledat disaini väga tähele panna - ma pole ise eriline disainimees, aga Heimar lubas mind selle koha pealt veidi aidata. Pealegi igaüks saab ise oma disaini luua (ja seda saab muuseas teha ka CMS-i adminni liidese kaudu).

Tegu on MIT litsentsiga välja antud avatud lähtekoodiga rakendusega, kasutan küll ka LGPL komponente (TinyMCE), kuid loodan et need litsentsid ei lähe omavahel konflikti. Samuti kasutan hetkel ühte vabavaralist ikooni failide näitamiseks, kuid kuna ma ei leidnud mis litsentsi alt see välja antud on, siis ma ei osanud sellega arvestada. Kui tuleb välja, et ei sobi, siis otsin uue ikooni.

Platvorm:
  • Hostinguna on kasutusel Google App Engine konto (id: turbinecms), millele viitab domeen turbinecms.com
  • Serveripoolne kood on kirjutatud Pythonis (1 fail)
  • Andmebaasiks on GAE poolt pakutav BigTable
  • Üleslaetud failid (sh. ka kasutaja loodud kujundusfail) hoitakse andmebaasis
  • Kõik andmebaasist tulevad andmed on puhverdatud memcache puhvrisse
  • Templiidimootoriks on Django 0.96 (GAE default)
  • JavaScripti teekidena on kasutusel Prototype + Scriptaculous
Võimalused:
  • CMS võimaldab luua WYSIWYG tekstitoimetiga (TinyMCE) uusi lehti
  • Samuti saab luua alamlehti, mida näidatakse põhilehe järel. Näiteks Uudiste põhilehele saab lisada alamlehtedena üksikuid uudiseid.
  • Lehed võivad olla mustandid või avaldatud. Juhul kui on mustandid, siis neid avalikult vaadata ei saa.
  • Saab laadida üles pilte ja faile, et neid lehe sees kasutada. Kahjuks on faili suuruse piirang hetkel 1 MB, seega tuleks pildid eelnevalt arvutis väiksemaks teha, kui need juhtuvad liiga suured olema.
  • Lehe kujundust saad muuta on-line administreerimise lehelt. Kujundus moodustub ühest HTML failist (Django 0.96 templiidiformaat)
Probleemid:
  • Hetkel on peamiseks probleemiks kujundus, mis on suhteliselt lihtsakoeline
  • Internet Exploreri kasutajatel ei toimi failide upload, failinimede asemel saab skript failinimed koos kataloogiteega - C:/Documents and settings/.../pilt.jpg" ja seega genereeritud lingid ei tööta, kuna sisaldavad endas ka failinime. Avasin ka vastava issue endale meeldetuletuseks.
Tõmmata saab (ja lähtekoodi sirvida) Google Code lehel - http://code.google.com/p/turbinecms/

Kasutamiseks peab olema Google App Engine konto, kuid testida saab ka GAE SDK-ga kaasa tuleva localhost serveri peal.

Kui keegi tunneb projekti vastu huvi ja tahab mingil viisil kaasa aidata (kas siis koodi või disaini arenduses), siis kõik on oodatud (Y)


PS. Selles blogis oli probleem kommenteerimisega - määrasin adminniliidesest, et kommenteerimine käib otse blogi lehelt, aga hetkel kasutuses olev templiit ei oska seda teha (katsetasin vana templiidiga), seega kommenteerida ei saanudki. Nüüd saab kommenteerimiseks kasutada Bloggeri vaikimisi kommentaarivormi eraldi lehel.

esmaspäev, 19. oktoober 2009

iPhone veebirakendused vol. 3

Eelmistest iPhone veebirakenduste postitusest kirjutasin, kuidas kasutada ära erinevaid iPhone brauseri poolt pakutud võimalusi, loomaks rakendustelaadseid veebilehti. Kuid siiani on nendelt rakendustel olnud üks häda - need töötavad ainult võrgus olles, offline annab rakendus veateate.

Õnneks on ka siin lahendus olemas, tuleb kasutada offline application caching API't, mille toetus on olemas nii uuemates Firefoxides kui ka Safarites ning seega ka iPhone brauseris.

Lehe puhverdamiseks on esiteks tarvis luua puhvri manifest fail - selles kirjeldame ära, millised ressursid peaks brauser ära tõmbama. Kuna demorakenduses on kõik vajalik ainult HTML failis endas, siis midagi muud puhverdada polegi vaja.

myapp.manifest faili sisu:
CACHE MANIFEST
app.php

Selle jaoks, et manifesti fail oleks brauserile üheselt arusaadav, tuleks paika seada ka vastav mime-tüüp. Kui serveris on võimalik kasutada .htaccess faile, saab seda teha lisades manifesti faili kataloogis asuvasse .htaccess faili rea

AddType text/cache-manifest manifest

Ja viimasena oleks tarvis veebilehe koodis ära märkida, et puhverdamine on kasutusel. Kuna tegu on HTML5 featuuriga, peaks ka doctype olema vastav.

<!DOCTYPE HTML>
<html manifest="myapp.manifest">

Kui nüüd avada selline rakendus iPhone brauseriga ning lisada see telefoni töölauale, siis võib rakendust avada ka täiesti offline olekus, mis teeb rakendusest praktiliselt samaväärse kui AppStore'i kaudu hangitud rakendused on. Ainsa vahega, et installida on suhteliselt mugav - seda saab teha otse veebilehelt ning ilma igasuguse itunes kontota.

Selle jaoks, et kontrollida, kas veebileht on avatud otse brauserist või töölaualt (et vahet teha, kas näidata installimise juhendit või mitte), saab kasutada window.navigator omadust standalone.

if (window.navigator.standalone){
    // tee vajalikke asju
}else{
    // näita installimise juhendit
}

Näites kasutatud puhverdamine on suhteliselt primitiivne - võibolla tuleks vahepeal mingeid asju uuesti laadida või tuleks andmete sünkroniseerimiseks kontrollida, kas parasjagu ollakse online või offline jms.  Kõik see on võimalik, tasub lugeda täpsemat spetsifikatsiooni, mille leiad siit.

laupäev, 17. oktoober 2009

Cross domain JavaScript

Ülidselt on cross-domain JavaScript brauserites rangelt keelatud. See tähendab, et ei ole võimalik teha AJAX päringuid võõrasse domeeni (st. domeeni, mis on erinev lehe domeenist, kust päring esitati, näiteks www.neti.ee ei saa teha AJAX päringut aadressile www.delfi.ee) ning samuti ei ole võimalik JavaScriptil ligi pääseda võõrast domeenist tulevale teise freimi või akna sisule.

Juhul kui domeenid on samad, pole freimide (sh. ka iframe ning brauseri teised aknad) puhul mingit probleemi - teise freimi sisu on kättesaadav sama lihtsalt nagu window.document DOM puu. window.document asemel tuleb kasutada lihtsalt vastavale freimile viitavale objektile. Iframe saab põhifreimi kätte objektist parent ning aken, mis on avatud teise akna poolt, saab avaja kätte objektist window.opener.

Juhul kui põhidomeen on sama, aga alamdomeen on erinev, näiteks ühes freimis on avatud leht aadressilt www1.neti.ee ja teises freimis on avatud www2.neti.ee, saavad freimid omavahel suhelda, kui mõlemad muudavad ära document.domain väärtuse põhidomeeni vastu.

Põhifreim (www1.neti.ee):
document.domain = 'neti.ee';
abc = 123;

Iframe (www2.neti.ee):
document.domain = 'neti.ee';
alert(parent.abc); //123

Keerulisem aga on lugu juhul, kui erinevad freimid asuvad täiesti eri domeenidel, näiteks aadressidel teenus1.com ning teenus2.com. Siiani praktiline lahendus puudus, kuid uutes HTML5 toega brauserites (näiteks alates Firefox 3.0 ning Internet Explorer 8) on probleemi lahendamiseks võimalik kasutada messaging API't.

Töötab asi järgmiselt - freim, kes tahab saata teisele freimile mingit infot, käivitab selle jaoks vastava freimi objektis postMessage meetodi, mis edastab info adressaadini. Adressaat ise aga peab sõnumite kättesaamiseks seadma üles vastava sündmusehalduri (window.onmessage).

Juhul kui sündmuse haldajale laekub teisest freimist sõnum peaks see kontrollima, kas info tuleb usaldusväärsest allikast ning seejärel saab teha saadud infoga, mida vaja.

Sisuliselt võib öelda, et turvakontroll on lükatud brauserist skripti poolele. Skript ise vastutab, et see info (mis tuleb sisse alati stringi kujul) kõlbab töötlemiseks või mitte.

Sõnumi saatmiseks tuleb kasutada postMessage meetodit:

parent.postMessage(message, targetOrigin);

message on saadetav sõnum stringi kujul.
targetOrigin - string, mis määrab ära lubatud vastuvõtja. Lubatud kuju on protokoll://domeen[:port]. Port on vaja määrata vaid juhul, kui see ei ole sama mis protokolli vaikimis port (http:80, https:443). Võimalik on kasutada ka kuju "*",  sellisel juhul saavad sõnumi kõik aknad.

Sõnumi kättesaamiseks adressaadi poolt tuleb seada üles vastav sündmus - onmessage.

window.onmessage = function(e){
    e.source; // objekt, mis viitab sõnumit saatvale freimile
    e.origin; // string, mis sisaldab endas saatja domeeni kujul protokoll://domeen[:port]
    e.data; // vastuvõetud sõnum stringi kujul
}

Kuigi sõnumi saatja kontroll pole kohustuslik, samuti võib sõnumit saata "broadcast'ina", kasutades vastuvõtjana stringi "*", on soovitatav kontrollida nii sõnumi saajat, kui saatjat. Ja seda seetõttu, et kolmandad osapooled ei saaks midagi kurja korda saata.

Näiteks eeldame, et stringi kujul transporditakse JSON koodi, mis käivitatakse vastuvõtja poolt eval käsuga.

window.onmessage = function(e){
    data = eval(e.data);
}

Juhul kui saatjaks on pahalane, võib e.data sisaldada endas näiteks mõnda funktsiooni, mis tõstab kõrvale kasutaja hetke sessiooni või veebipõhise e-posti kliendi puhul näiteks suunab kasutaja e-posti aadressi pahalase aadressile. Sellest, aga mida kõike paha sarnasel viisil teha annab (meenutagem näiteks Orkuti viiruseid), kirjutan juba mõni teine kord.

Lingid:
window.postMessage Mozilla Developers saidil
window.postMessage dokumentatsioon MSDN saidil

kolmapäev, 30. september 2009

DOMCached jQuery plugin

Tegin DOMCached teegist ka jQuery versiooni, mida saab siis kasutada jQuery pluginana. Plugina leht jQuery lehel on http://plugins.jquery.com/project/DOMCached ning testida saab seda DOMCached veebilehel samamoodi kui Prototype versiooni.

Tekkis ka väike süntaksi erinevus - kui Prototype versioonis käib näiteks andmete lugemine kujul DOMCached.get("key"), sis jQuery versioonis teeb sama $.DOMCached.get("key") ehk et lisandus jQuery kuulus dollar.



Veebirakendus iPhone jaoks, vol 2 - andmebaas

Eelmises iPhone veebirakenduse teemalises postituses oli juttu rakenduse olemuslikust küljest - kuidas teha veebilehte, mis telefonis käituks kui rakendus. Edasi aga räägiks, et mida selle rakendusega üldse teha saaks.

Üheks olulisemaks asjaks oleks ilmselt kasutaja andmete salvestamine, mingisugune profiili loomine - kui rakendus näeks täpselt samasugune välja kõikide kasutajate korral ja selles puuduks igasugune dünaamilisus, siis poleks rakendust üldse mõtet rakendusena vormistada, vaid piisaks tühipaljast veebilehest.

Andmeid (selle all pean silmas dünaamilisi andmeid, mitte veebilehte ennast) aga ei pea vastupidiselt üldlevinud arvamusele sugugi hoidma ainult serveri poole peal, kus rakenduse avades tõmmatakse serverist andmed telefoni brauserisse. Andmeid saab ka kohe brauseri poolel hoida.

Võimalik on näiteks kasutada eelmises postituses kirjeldatud DOM storage meetodeid (sessionStorage, localStorage), kuid iPhone brauser pakub sellest palju enamat. Nimelt Safari sisaldab endas ootamatult täisfunktsionaalset SQLite andmebaasi, mida saabki ülihästi andmete salvestamiseks kasutada.

Andmebaasiühenduse saab avada järgmiselt
db = openDatabase(db_name:String, db_version:String, db_description:String, 10000);

Päringud käivitatakse transaktsioonidena, kus algselt avatakse andmebaasi suhtes transaktsiooni objekt ning sellega viiakse läbi vajalikud päringud
db.transaction(function(tx) {
  tx.executeSql(sql:String, params:Array, result_callback:Function(tx, results), error_callback:Function(tx, error))
});

Näiteks uue tabeli loomine andmebaasi käiks nii
//CREATE TABLE my_table
tx.executeSql("CREATE TABLE my_table (id REAL UNIQUE, name TEXT)", 
  [], // No params to provide
  function(tx,result) { // results callback function
    alert('Success!');
  },
  function(tx,error) { // error callback function
    alert('Error creating table - ' + error.message);
  }
});

Andmete sisestamine käiks tavalise INSERT lausega
//INSERT ROWS TO my_table
tx.executeSql("INSERT INTO my_table (id, name) VALUES(?,?)", 
  [1,"minunimi"], // first param stands for "id" and the second for "name"
  function(tx,result) { // results callback function
    alert("Success!")
  },
  function(tx,error) { // error callback function
    alert('Error - ' + error.message);
  }
});

Ja andmete lugemine vastavalt SELECT lausega
//READ VALUES FROM my_table
tx.executeSql("SELECT * FROM my_table WHERE id=? AND name=?", 
  [1,"minunimi"], // first param stands for "id" and the second for "name"
  function(tx,result) { // results callback function
    if(result && result.rows){
      for (var i = 0; i < result.rows.length; ++i) {
        var row = result.rows.item(i);
        alert(row['name']);
      }
    }
  },
  function(tx,error) { // error callback function
    alert('Error - ' + error.message);
  }
});

Tähele tasub panna kuidas käib muutujate sisestamine SQL lausesse - selle jaoks tuleb vajalikku kohta sisestada küsimärk (?), ning selle järjekorrale vastavalt tuleb lisada SQL päringu järgmisse parameetrisse massiivi elemendiks tegelik väärtus. Nii ei pea muretsema andmete puhastamise pärast, seda teeb andmebaasi API ise.

Seda, et kui palju aplikatsiooni andmebaas mahtu kulutab ja kui palju mahtu veel alles on, saab telefonis kontrollida seadete menüüst. Settings->Safari->Databases->andmebaasi_nimi

Reeglina peaks andmebaasi suuruseks olema 5 MB. Puhtalt andmete mõttes on seda üsna palju - selle ruumi sisse saaks näiteks vabalt mahutada plain text formaadis kõik Sõrmuste isanda raamatud.

Nii, et kui siduda omavahel iPhone veebirakenduse, andmebaasi ja ühes varasemas postituses kirjeldatud graafikateegi (see töötab ka iPhone brauseris), on juba täiesti võimalik ehitada iPhone platvormile täisfunktsionaalseid aplikatsioone. Näiteks graafilisi mänge vms.

---
Täiendus: Algselt jäi mainimata kes seda brauseri andmebaasi juba kasutavad. Seda teeb näiteks Gmail, kes salvestab kasutaja viimased kirjad brauseri andmebaasi. Seega kui avada telefonis Gmail, on koheselt kirjad ees. Alles peale baasis olevate kirjade kuvamist hakkab brauser serverist kontrollima, kas vahepeal on midagi juurde tulnud.

------
Veel üks täiendus: Versioon andmebaasiühenduse loomisel peaks hetkel olema "1.0"

teisipäev, 29. september 2009

DOMCached teek andmete puhverdamiseks browser-side

Eelmises postituses sai lühidalt mainitud DOM Storage võimalusi, mis lubab brauseri poolel talletada suhteliselt mahukas koguses andmeid, nii et JavaScript neid kasutada saaks.

Kuna mainitud funktsionaalsus on erinevatel brauseritel erinev - üks brauser lubab üht, teine teist ja kolmas annab üldse veateate, siis olen teinud lihtsa wrapper teegi, mis kontrollib brauseri võimalusi ja teisendab sisendandmed brauserile mõistetavale kujule.

Teegi nimi on DOMCached ning katsetada/tõmmata saab seda aadressilt www.domcached.com

Nimi tuleneb populaarsest puhverdussüsteemist nimega memcached, kuna implementeerisin DOMCached objekti sarnase meetoditega nagu on Google App Engine memcache teek.


Miks selline asi üldse kasulik peaks olema?

DOMCached sarnane puhverdusteek võimaldab kokku hoida näiteks Ajax päringute pealt - kui kasutaja on vastavaid andmeid serverilt juba küsinud, siis skript ei pea seda uuesti tegema.

Või kui kasutaja täidab mingit vormi ja liigub selles edasi-tagasi, siis ei pea vormi eeltäitmisega (juba varem sisestatud andmetega) tegelema server, vaid selle saab teha JavaScript puhverdatud andmetega. Eriti mugavaks võib see muidugi osutuda, kui vormi täitmise ajal peaks browser kokku jooksma või vool ära minema või midagi muud sarnast juhtuma, mis täidetud sisu muidu hävitaks.

Igatahes, teek on litsenseeritud MIT stiilis litsentsiga, mis lubab seda vabalt oma rakendustes kasutada ja seda nii tasuta kui tasulistes.

esmaspäev, 28. september 2009

HTML5

HTML viiendast versioonist on juba mõndagi juttu olnud. Mida see aga veebitegijale reaalselt tähendab, mida see järjekorranumbri muutus üldse annab?

Muutunud DOCTYPE

Esiteks muidugi kõige lihtsam muutus - mugavam DOCTYPE deklaratsiooni kirjeldus. Kui varasemalt tähendas DOCTYPE midagi krüptilist, mida keegi ise üles kirjutada ei osanud ning seega tuli korrektse koodi nimel see kuskilt mujalt kopeerida, siis nüüd on asi palju kergem.

Kui varem võis DOCTYPE deklaratsioon välja näha selline

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

Siis HTML 5 korral saab kasutada vormi

<!DOCTYPE html>

Küsimuseks jääb muidugi, et kui kunagi tuleb HTML versioon 6, kas siis tuleb jälle hakata pikemaid DOCTYPE deklaratsioone kirjutama - hetke variandis ju versiooninumbrile kohta ei leidu. Arvestades aga, et kui kaua HTML4 ringi liikunud on ja HTML viiendale versioonile vähemalt sama pikka eluiga ennustades (HTML 5 aeg pole ju tegelikult veel käeski, kuna Internet Explorer ei tea sellest midagi), võib väga pikkadeks aastateks antud mure unustada.

Audio tag

Edaspidi (st. kohe peale seda kui Internet Explorer peaks HTML 5 tuge omama hakkama) võib Flash mp3 pleieri ära unustada. HTML 5 sisaldab endas <audio> silti ning see element on täielikult skriptitav. See tähendab, et saab puhtalt JavaScript vahenditega valmistada täiesti korraliku muusikapleieri, mida kasutaja kasutajaliidese abil juhtida saab (edasi-tagasi kerimine, lugude vahetus jne)

Video tag

HTML 5 sisaldab ka video tuge sarnaselt audio sildile, selle jaoks on kasutusel <video> silt. Ja nagu audiogi, on ka see täielikult skriptitav.

Mõningaseks puuduseks võib ehk lugeda hetkel vaid nii video kui audio juures vabavaraliste koodekite (ogg) tuge. Päris mp3 pleierit nii veel teha ei saa, kuna mp3 koodekit vähemalt Firefoxis pole.

DOM storage

See ei ole küll otseselt HTML 5 osa, kuid on üks lahedamaid uuendusi, mis viimasel ajal koos HTML 5 tulekuga saabunud on (või noh, tegelikult juba Firefox 2 ajast saadik, aga mujale on nüüd jõudnud). Ja mis peamine - seda toetab ka Internet Explorer 8. Nimelt lokaalne sessiooni andmete hoidmine.

Kui varem sai brauseris sessiooni andmete püsivaks hoidmiseks (kui mitte arvestada Google Gears võimalusi) kasutada vaid küpsiseid, siis nüüd on olemas veidi parem alternatiiv, nimelt DOM storage. Teen sellest tulevikus kindlasti juttu, kuid lühidalt on tegu key-value tüüpi anmebaasiga, kuhu saab salvestada tekstilist infot (sealhulgas ka siis JSON stringe). Firefox lubab kasutada kuni 5 MB ning IE kuni 10 MB, nii et võrreldes küpsiste poolt pakutavate mõnede kilobaitidega, on tegu ikka päris suure edasminekuga.

reede, 25. september 2009

Web Workers API

Firefox 3.5, Safari 4 ja Chrome 2 toetavad uut JavaScript API't nimega Web Workers. Põhimõtteliselt peaks Internet Exploreris ning eelpoolmainitud brauserite vanemates versioonides saavutama sama tulemuse Google Gears WorkerPool API, kuid ebamugavaks teeb asja, et sellisel juhul tuleks kasutaja arvutisse paigaldada Google Gears.

Iphones kahjuks momendil Web Workers toetatud pole (kuigi arvata on, et see sinna kunagi jõuab, kuna Safari 4's on toetus juba olemas), seega Web Worker API't eelmises postituses mainitud veebiaplikatsioonides lisavahendina kasutada ei saa.

Web Workers on rakendusliides, mis võimaldab lükata suuremad arvutuskäigud jms. JavaScript programmi põhivoost eraldi protsessi, nii et see ei segaks programmi põhivoo kulgu (erinevad pikemad tsüklid ja arvutused võivad muidu panna brauseri "hanguma").

Kasutamine on lihtne - worker asub eraldi .js failis, see laetakse läbi Worker konstruktori käima ning suhtlus põhiprogrammi ja workeri vahel käib üksteisele teateid postitades.

Näiteks võib põhiprogramm välja näha nii:

var worker = new Worker("worker.js");
worker.onmessage = function(e){
  document.getElementByid('result').innerHTML = e.data;
};
worker.postMessage("start");

Kõigepealt defineeritakse uus worker, mis asub failis worker.js. Seejärel defineeritakse sõnumi vastuvõtmise sündmus, mis ei kirjutab sõnumi sisu lehele kindla elemendi sisutekstiks. Ja viimasena saadetakse välja sõnum, mille alusel worker teab tööd alustada.

Worker.js fail võiks sellisel juhul välja näha järgmine:

onmessage = function(e){
  if ( e.data === "start" ) {
    var tulemus = 0;
    /
     * tee siin midagi
     */
    postMessage(tulemus);
  }
};

Esiteks defineerime sõnumi vastuvõtmise sündmuse (nb, tasub tähele panna, et erinevalt põhiprogrammist, asub onmessage globaalses, st. window skoobis, samuti ka postMessage).

Kontrollime, kas on õige sisuga sõnum, arvutame midagi ning tagastame tulemuse põhiprogrammile, kutsudes välja postMessage funktsiooni. Saadetud sõnum käivitabki põhiprogrammis sündmuse worker.onmessage.

Piirangud

Web Workers API seab kahjuks ka mõned piirangud. Näiteks ei ole võimalik workeril pääseda ligi DOM objektile. Küll aga on saab teha serverile Ajax päringuid, kasutada taimereid jms.

Saadetavad sõnumid peaksid olema string väärtustena, näiteks JSON või XML tekstina või mõne muu primitiivse väärtusena (number, boolean). Objekte kahjuks saata ei saa, kuna tulemus pole ette teada (erinevad brauserid võivad käituda erinevalt).

Demo

Töötava demorakendusena saab uurida aadressi http://jscode.org/worker/- selles olev programm arvutab taustal välja algarvud kuni numbrini 10 000 ning kuvab tulemused lehel.

kolmapäev, 23. september 2009

Kuidas luua iPhone veebiaplikatsioone

Kuigi iPhone puhul on rohkem tuntud App Store kaudu laetavad aplikatsioonid (Eestis toodab selliseid näiteks Indilo), siis tegelikult võimaldab ka telefoni brauser aplikatsioonilaadseid asju jooksutada.

Nimelt on võimalik veebilehe HTML koodis telefonile teada anda, et seda lehte tuleks kasutada kui aplikatsiooni. See tähendab, et lehte vaadates eemaldatakse brauseri kasutajaliides (aadressiriba ja olekuriba) ning kogu ekraanipind eraldatakse veebilehele.

Kuna brauser võimaldab salvestada veebilinkide otseteid (koos sobiva ikooniga, mille saab samuti veebilehe poolt ette anda) telefoni töölauale, saavutamegi väga lihtsate vahenditega efekti, nagu oleks tegu tavalise aplikatsiooniga.

Taoline veebiaplikatsioon saab ka määrata "startup" pildi, mida näidatakse kasutajale lehe laadimisel peale telefoni töölaual oleva aplikatsiooni otsetee avamist.

Aga nüüd kõigest lähemalt.

Esiteks oleks vaja veebilehes anda brauserile märku, et tegu on aplikatsiooniga, selle jaoks saab HTML lehe päisesse seada mõned meta-sildid.

<meta content="yes" name="apple-mobile-web-app-capable"></meta>
<meta content="black-translucent" name="apple-mobile-web-app-status-bar-style"></meta>
<meta content="telephone=no" name="format-detection"></meta>
<link href="startup.png" rel="apple-touch-startup-image"></link>
<link href="icon.png" rel="apple-touch-icon"></link>
<meta name = "viewport" content = "width = device-width,maximum-scale=1.0,minimum-scale=1.0, initial-scale = 1.0, user-scalable = no"></meta> 

Esimene rida - apple-mobile-web-app-capable annab teada, et veebilehte tuleks käsitleda aplikatsioonina ning brauser peaks oma kasutajaliidese elemendid ära peitma. Aplikatsiooni staatust arvestatakse ainult siis, kui leht avatakse telefoni töölaual oleva otsetee kaudu, mitte brauseriga otse aplikatsiooni aadressile minnes.

Teine rida - apple-mobile-web-app-status-bar-style seab ainsa säilinud kasutajaliidese elemendi stiili - telefoni ülemine kitsas riba, mis näitab levi tugevust, kellaaega ja aku täituvust.

Kolmas rida format-detection keelab telefonil konverteerida lehel asuvaid numbreid klikitavateks telefoninumbriteks.

Neljas rida - apple-touch-startup-image määrab ära pildi (320x480 px, portrait), mida näidatakse lehe laadimisel.

Viies rida - apple-touch-icon määrab ära otsetee ikooni (57x57 px). Ikoon peaks olema tavaline png fail - telefon ise muudab selle nurgad ümaraks ja lisab kerge peegelduse.

Kuues rida - viewport määrab ära mitmed vajalikud seaded (need töötavad ka otse veebi kaudu lehe avades, mitte ainult otseteed kasutades), näiteks selle et kasutaja ei saa lehte ise suurendada ega vähendada.

CSS

Peamised kaks CSS definitsiooni mida kasutada, oleks body[orient="landscape"] {} ja body[orient="portrait"]{}, need nimelt võimaldavad määrata lehele eri stiile vastavalt telefoni orientatsioonile. Lisaks antud definitsioonidele on võimalik veel kasutada mitmeid -webkit algusega eristiile, mis töötavad ka tavalises Safari brauseris.

JavaScript

Lisaks tuttavale käsustikule lisab iPhone JavaScripti window objektile paar uut meetodit ja omadust, mis on siis seotud ekraani orientatsiooniga.

1. window.orientation - omadus, mis sisaldab endas hetke ekraani orientatsiooni. Väärtuseks on üks järgmisest massiivist [0, 90, -90]. Kui omaduse väärtus on 90, siis "Home" nupp jääb ekraanist paremale.

2. window.onorientationchange - sündmus, mis rakendub kui kasutaja keerab telefoni, nii et ekraani orientatsioon muutub.

Näitena, et kuidas kõike seda kokku panna valmistasin lihtsa veebilehe, mis käitub täpselt vastavalt kirjeldatule. Täiendavalt saab aplikatsioon aru, et kas seda vaadatakse veebivaades või aplikatsioonivaates ning käitub vastavalt (veebivaates näitab juhendit, kuidas aplikatsiooni "installida").

Näite leiab siit (ava iPhone või iPod touch brauseris, lähtekoodi võid vaadata suvalise brauseriga).




teisipäev, 22. september 2009

Raphaël teek JavaScript graafika loomiseks

Viimasel ajal olen suhteliselt palju mänginud JavaScripti teegiga nimega Raphaël. Kui siiani on olnud JavaScriptiga probleeme dünaamilise graafika loomiseks - dünaamilist graafikat ei saa teha üht ega teistpidi, kuna iga brauser (st. IE vs. kõik teised) toetab erinevaid meetodeid. Põhiprobleemiks on IE, mis pole suurt midagi kuulnud SVG graafikast, küll aga tunneb VML põhist graafikat.

Siinkohas tulebki appi Raphaël, mis kujutab endast abstraktsioonikihti brauseri graafikavõimelisuse peal. Vahet pole, missugust meetodit brauser parasjagu oskab - Raphaël tõlgib selle ilusti ära. Ja seda praktiliselt kõigi levinud brauserite jaoks, sh. ka IE 6.0.

Miks sellist asja üldse vaja on? Kõik vajaliku saab ju teha kas serveri pool dünaamiliselt pildifaile genereerides või siis brauseris Flash objektidega.

JavaScript põhisel dünaamilisel graafikal on muude tehnikate ees mitmeid eeliseid.

Esiteks hoiab kokku võrguliikluse pealt, kuna liiguvad ainult (vabatekstilised) andmed ja JavaScripti kood. Kusjuures seda liiklust saab muu hulgas ka päris korralikult serveri poolt kokku pakkida, saades sellega täiendava mahuvõidu.

Teiseks saab sellisel viisil lükata serveri poolt koormust ära kliendi poolele - suhteliselt kalli dünaamilise graafika genereerimisega ei pea serveri CPU end enam vaevama. Lükkab andmed andmebaasist kliendile ja see teeb neist ise endale sobiva pildi.

Kolmandaks - iga graafikaelement ehk iga kasutatud vektor on omakorda DOM element. See aga tähendab, et näiteks igale joonele saab omistada erinevaid sündmuseid (click, mouseover, mouseout jne), saab kontrollida ja muuta elemendi asukohta, peita/näidata ja teha muid manipulatsioone JavaScripti abil otse kliendi vaates brauseri aknas.

Flash põhine graafika on sellele küll üsna lähedane võimaldades teoreetiliselt sama, kuid arvestada tuleb, et Flash on igal juhul väga piiratud. Kui .swf faili pole mingi funktsionaalsus sisse kirjutatud, siis hiljem seda väga lihtne muuta ei ole. Samuti ei ulata Flash reeglina üle tervet lehekülje, vaid on ainult oma väikeses piiratud kastis.

Kui nüüd jõuaks ära oodata kuni saaks valmis WebGL ja see ka IE's tööle hakkaks, siis võiks näha JavaScripti põhises graafikas väga huvitavaid arenguid :)

Igatahes lõpetuseks väike näide - allolev ring on joonistatudki Raphaël teeki kasutades. Hiirega peale minnes vahetab ring värvi.
HTML:
<div id="holder"></div>
JavaScript:
var paper = Raphael("holder", 180, 180);
var circle = paper.circle(90, 90, 85);
circle.attr("fill", "#f00");
circle.attr("stroke", "#0f0");

circle.node.onmouseover = function(){
    circle.attr("fill", "#00f");
}

circle.node.onmouseout = function(){
    circle.attr("fill", "#f00");
}

pühapäev, 20. september 2009

SMS-Publisher

Sama jutt oli tegelikult ka teises blogis üleval, kuid lisan ka siia kirjelduse, kuidas on teostatud SMS-Publisher ja mida see ednast täpselt kujutab. Kes on varem juba maksnud, see rohkem seda tegema ei pea - vanad koodid kehtivad edasi.

Tahad teenida oma blogi või veebilehe sisu pealt raha? Nüüdsest on kõigil huvilistel võimalik kasutada selleks uut Fortumo teenust nimega SMS-Publisher. Kuid erinevalt teistest teenustest ei ole see Fortumo enda välja töötatud. Nimelt on tegu esimese vastava API põhjal loodud kolmanda pakkuja teenusega. Kuidas teenus täpselt üles ehitatud on ja mida see platvormina kasutab jms., saab lugeda juba väikese tasu eest (seda SMS-Publisheri teenus võimaldabki)


Tagasi Blogspotis

Otsustasin kolida enda WordPress põhise blogi pealt tagasi kunagi kasutuses olnud Blogspot blogi peale. Ma ainult ei mäleta enam, mis mul tollal blogi aadress oli, kustutasin selle juba ammu ära. Hetkel aga kasutan oma domeeni.

Kui oleks taibanud juba varem FeedBurneri kasutusele võtta, siis ei oleks lugejate (keda on päris vähe alles jäänud, aga pole kedagi müüd süüdistada kui iseennast - sest ma ei viitsi enam ammu suurt midagi kirjutada) jaoks midagi muutunud peale blogi kujunduse. 

Aga miks Blogspot, WordPress on ju ääretult parem?

Aga kas on ikka parem? Enda hostitud WordPressi puhul peab hoolega jälgima, et oleks kasutusel uusim tarkvara versioon, vastasel juhul riskid võimalusega, et sinu blogi muutub mingiks drooniks ja viiruste levitajaks (ebatõenäoline, aga täiesti võimalik). Fakt, kas ma blogi hooldada suudan või mitte, on täiesti erinev sellest, kas ma seda ka tegelikult teha tahan - ja ausalt öeldes, väga ei viitsi. Googlet kipun ma siiski sama tegevuse juures suhteliselt kõrgelt hindama ja ei eeldan muretult, et edaspidi hoiabki juba Google kõik probleemid blogist eemal.

WordPress on teinud keeruliseks (oma hostitud serveris) või lausa võimatuks (wordpress.com poolt hostitud blogis) kolmanda osapoolte pakutud "vidinate" kasutamise postitustes. Wordpress.net serveris hostitud blogis ei ole võimalik taolisi vidinaid üldse kasutada. Oma hostitud blogis saab vähemalt teema kujunduse HTML koodi muuta (kuigi, oleme ausad, algajal on päris keeruline kõikide nende eri failide vahel orienteeruda + risk kujundusfailides kasutatud php kood ära rikkuda).

Mis on muutunud?
  • FTP asemel on vaja muuta nimeserveri kirjeid. A kirjed (4 tk) lähevad mingitele Google IP'de peale ja CNAME www läheb ghs.google.com peale.
  • Enam ei saa ära võtta seda ülemist Bloggeri sinist riba, mida varem FTP hostingu puhul teha sai.
  • Postituse lisamise WYSIWYG kast on saanud väikese värskenduse. Saab näiteks postitust poolitada.
  • Templiidifailid on XML formaadis struktuursed failid, erinevalt varasemast full page HTML tekstist, kus asendati lihtsalt märgendeid.
Need mõned momendid, mil uut süsteemi kasutanud olen, on igatahes igati meeldiva mulje Blogspotist jätnud.