40. fejezet - Javascript készítése

Tartalom

Html_013_ScriptDemo projekt
BodyFelderites (DOM szerkezete) szkript gyakorlat
Nyomkövetés (DOM szerkezete) szkript gyakorlat
Dinamikus html-tartalom generálás szkript gyakorlat
Időzítés (timer) szkript gyakorlat
Analóg és Digitális óra szkript gyakorlat
Prompt (felhasználói input) szkript gyakorlat
Input (felhasználói input) szkript gyakorlat
Navigate szkript gyakorlat
Canvas „osztály” szkript gyakorlat
Window login szkript gyakorlat
LocalStorage szkript gyakorlat
GeoLokáció szkript gyakorlat

Html_013_ScriptDemo projekt

Úgy tűnik, hogy a webes programozás általános nyelve hosszú és kacskaringós út után a javascript lesz, tekintve, hogy ez ma az egyetlen implementáció, ami biztosítja, hogy platformoktól függetlenül egy kód ugyanúgy fusson le. És bár a programozási nyelvek fejlődése a natív kódolásoktól a menedzselt kódú, komponens orientált paradigmáig szintén igen hosszú volt, a java „túlélte” ezeket a „változás viharokat” és szilárdabb, mint valaha. A html5 webes környezetben a jövőt tervezők szerint kifejezetten az egyetlen programozási eszköz marad. Ennek megfelelően a html5 erősen támaszkodik a javascript nyelvi lehetőségeire, és ezért a nyelvnek széleskörű api támogatását tervezik.

Mi most ennek a lehetőség-halmaznak csak az alapjait tekintjük át, kihasználva a javascript nyelvi szabályainak egyszerűségét. Néhány bevezető fogalom tisztázásával kezdjük, és igyekszünk folyamatosan kódokkal szemléltetni gyarapodó tudásunkat.

Amikor javascript kódot írunk, mindig tartsuk szem előtt, hogy a kód egy böngésző által értelmezetten fog végrehajtódni. Vagyis nem esik át fordításon, mint natív elvű nyelveknél, és nem dolgozza fel egy virtuális gép, mint annak gépi kódú utasításait. Szóval ez egy interpretált nyelv, melynek utasításait sorról-sorra hajtja végre a böngésző. Ebből a tényből több jelentős következmény adódik. A végrehajtás lassúbb, mintha natív kódot hajtana végre a processzor, de cserébe nem kell egy fejlesztői rendszer fodítási és linkelési szolgáltatása, vagyis a program módosítását követően az „új” kód azonnal futásra kész.

Egy másik fontos adottsága, hogy a kód futásának eredménye általában a böngésző által megjelenített weblap tartalmának módosulásával jár, vagyis a „kimenet” maga a weblap. Dinamikus tulajdonsága teszi lehetővé, hogy szinte mindent megváltoztathassunk kódból, amit tervezési időben html nyelven írtunk. Az első kérdés, hogy hol lehet javascript kódot elhelyezni egy weblap hatókörében. Alapvetően két helyen, magában a html kódban, vagy egy külső fájlban. Ha a html kódban helyezzük el, akkor ez három helyen lehetséges.

  • A <head></head> tag-ek között, általános felhasználásra, metódusok formájában.

  • Egy egy html tulajdonság értékeként a html tag-en belül.

  • Html elemek eseménykezelésében a html tag-en belül.

A javascript kódok az adott weblap html elemeinek tulajdonságait programatikailag érik el, ez úgy lehetséges, hogy a weblap adott szerkezetének megfelelően a böngészőbe való betöltődéskor létrejön egy objektum modell is, melynek szerkezete (hierarchiája) követi a weblapét. Ezt az objektum modellt DOM-nak (document object model-nek) nevezzük. A DOM szerkezetének ismerete elengedhetetlen a javascript programozáshoz, ezért kezdjük ezzel az ismerkedést.

http://www.technologyuk.net/the_internet/web/document_object_model.shtml

7-1. ábra -

kepek4/18fejezet-7-1.jpg


A fenti szerkezet legfelső eleme a window objektum, melynek alapján „felderíthető” a DOM.

BodyFelderites (DOM szerkezete) szkript gyakorlat

Ugorjunk fejest a szkript programozásba, és tűzzük ki célul egy olyan kis szkript elkészítését, mely a korábban megtervezett html lapunk <body></body> tag-jébe a DOM-ban leképezett szerkezetéről ad egy listát. Mint a fenti ábrán látszik, a Window objektum alatt létezik egy document objektum, mely a html struktúra alapján épült fel.

Maga a html tartalom a weblap body tag-jai között szerepel az alábbiak szerint:

Mint látjuk, csak egy kiírást tartalmaz és egy nyomógombot, aminek az onclick eseményéhez egy BodyFelderites nevű eljárást kötöttünk. Ez még nincs megírva, tehát kezdjük ezzel a munkát.

Mivel már volt dolgunk programfejlesztéssel korábban assembly és c# környezetben is, ezért a <head></head> szekcióban elhelyezendő javascript kódot soronként értelmezni tudjuk.

A funkció neve tehát BodyFelderites(), és a var kulcsszóval egy-egy változót vezetünk be, melynek típusa az első értékadáskor dől el. A bodyString változónk például sztring típusú (karakterlánc) lesz, mert egy üres ’’ jellel inicializáltuk. A bodyObj változónk azonban már egy objektum lesz, mégpedig a DOM-ban a html forrásban htmlbody id-vel azonosított objektum, mely terveink szerint éppen maga a <body></body> tag. Vagyis ez az a pillanat, amikor a DOM-ból kinyerjük a html forrásban megtervezett tag objektum példányát. Mostantól kezdve bármit csinálunk ezzel az objektummal, az olyan, mintha magában a html forrásban végeznénk módosítást. Így valósul meg a dinamikus, kódból történő változtatás lehetősége. A gyerekObj nevű objektumba pedig a következő sorban kinyerjük a bodyObj gyerek objektumait, amin egy for ciklussal iterálva kiíratjuk a típust és az id-t. A teljes forrás tehát a következő:

A BodyFelderites funkció végén egy alert függvényt hívunk (ami a window objektum tagfüggvénye), amellyel egy modális ablakban kiírjuk az eddig összegyűjtött információt.

7-2. ábra -

kepek4/18fejezet-7-2.jpg


7-3. ábra -

kepek4/18fejezet-7-3.jpg


A fenti példában a szkriptet a <head></head> szekcióban helyeztük el, és ezzel nem is lenne semmi baj, ha csak ez az egy, vagy csak néhány eljárást szeretnénk használni. Mivel azonban ebben a projektben terveink szerint több javascript példát írunk, ezért célszerű a korábban említett külső fájlban tárolni eljárásunkat. Ehhez a szkript törzsét kimásoljuk egy külön fájlba, és a projekt jscript nevű alkönyvtárába másoljuk (mindig a fejezet alcím) BodyFelderités.js néven. A hivatkozást erre a külső fájlra pedig az „elárvult” <script></script> tag attributumaként adjuk meg.

Külön felhívjuk a figyelmet, hogy a <button></button> tag-ben elhelyezett onclick metódus valójában egy komplett javscript kód lehet, (idézőjelek között) mint azt a sorvégi „;” is szemlélteti. A továbbiakban tehát mindig egy egy külső fájlban helyezzük el a szkriptet, és ezt a head szekcióban beírt hivatkozással tesszük elérhetővé. Nagyjából ez a módszer akkor is, amikor nem saját, hanem valamilyen „idegen” rutingyűjteményt használunk.

Nyomkövetés (DOM szerkezete) szkript gyakorlat

Már az elején jó, ha gyakorlatot szerzünk a nyomkövetésben, mert ezzel sok kellemetlenségtől és felesleges időveszteségtől kímélhetjük meg magunkat. Vegyük fel az előző projekt kódját újra a weblapon, és készítsünk a külső fájlban tárolt javascript kódunkban egy hibát szándékosan.

Legyen ez a hiba az, hogy window.alert(bodyString); sorban „felejtsük le a záró zárójelet window.alert(bodyString;.

Ha futtatjuk, akkor az alábbi üzenetet kapjuk:

7-4. ábra -

kepek4/18fejezet-7-4.jpg


Ez egy olyan típusú hiba, ami a javascript kód értelmezhetetlensége miatt keletkezett. Javítsuk ki, és nézzünk egy lépésenkénti végrehajtást. Ha az IE9-et használjuk tesztelésre, akkor a forrásban elhelyezett töréspontra a futás megáll, és innen az ismert lépésenkénti üzemmódban haladhatunk tovább a VS-ben megszokott minden debug funkció segítségével.

7-5. ábra -

kepek4/18fejezet-7-5.jpg


Mint látható, használhatjuk a változók ellenőrzését, listázását, stb. a megszokott módon. További futásközbeni vizsgálatra van lehetőség az IE9 beépített (F12-vel előhívható) fejlesztői eszközeinek megnyitásával.

7-6. ábra -

kepek4/18fejezet-7-6.jpg


Dinamikus html-tartalom generálás szkript gyakorlat

Az egyik leggyakoribb felhasználási területe a javascript kódok írásának, hogy a böngészés „futásidejében” módosítjuk adott html elemek tartalmát. Az alábbi példában a h2_id azonosítójú <h2></h2> tag-ben foglalt tartalmat módosítjuk a html kódban az alábbi szkripttel.

Ebben a példában azt is megmutatjuk, hogy globális hatókörű változókat is deklarálhatunk úgy, hogy a függvények „testén” kívül helyezzük el őket. A példában elhelyezett globalint változót az összes egyéb javascript forrásban látjuk.

Természetesen a <head></head> szekcióban a különálló forrásra való hivatkozást el kell helyeznünk.

7-7. ábra -

kepek4/18fejezet-7-7.jpg


Időzítés (timer) szkript gyakorlat

A dinamikus weblaptartalom kezelésnek egyik speciális fajtája a ciklikus feladatokat megvalósító algoritmusok gyűjteménye, melynek alapja valamilyen időzítési esemény kezelése. Legyen a feladat az, hogy három progressbar „value” értékét frissítsük periodikusan 100 ms sűrűséggel, és közben jelezzük ki az időt is. Ehhez az alábbi statikus html kódot használjuk:

A feljécben pedig jelezzük, hogy a végrehajtáshoz szükséges javascript kódot egy ProgressTimer.js nevű külső állományban tesszük hozzáférhetővé:

Ezek után lássuk a javascript kódot:

Mint látszik, a két nyomógomb ugyanazt a funkciót hívja, és az elindítás, illetve a leállítás közötti esetszétválasztás a csatolt paraméter szerint történik. („Start” vagy „End”) Amikor elindítás van, akkor a „ráindítás gátló” flag állapotának engedélyezésére a timer objektum létrejön a setInterval függvénynek a timer eseménykezelője a milliszekundumban megadott ismétlési érték, mint paraméter megadásával. Ezt követően a vezérlés az adott ciklikussággal a TimerWork nevű eljárásra adódik át, amiben módosítjuk a progressbar-ok tartalmát, és hívunk egy TimeDisplay nevű rutint, ami kiírja az aktuális időt.

7-8. ábra -

kepek4/18fejezet-7-8.jpg


A leállítás eseménykezelőjében a clearIntervall eljárással állítjuk le a paraméterként átadott timer objektumot.

Analóg és Digitális óra szkript gyakorlat

A fenti példa kis átalakításával egy analóg óra html kódja:

A WatchTimer.js kódban megírt javascript kód pedig az alábbi:

Mint látszik, a két nyomógomb funkcionalitásait összevontuk, és a watchtimerobj logikai változó állapotától függően működtetjük, illetve feliratozzuk. Bár még nem mélyedtünk el a stílusok rejtelmeiben, azért néhány elemközi stílus felhasználásával már „pofás” analóg órát fabrikáltunk.

7-9. ábra -

kepek4/18fejezet-7-9.jpg


Itt mutatjuk be a firefox környezetben használható debug eszközöket, melyek használata előtt a firebug nevű beépülő modult telepíteni kell. Ezt követően az F12-es funkció-billentyűvel lehetőségünk van a forrásnyelvi nyomkövetésre.

https://addons.mozilla.org/hu/firefox/addon/firebug/

7-10. ábra -

kepek4/18fejezet-7-10.jpg


7-11. ábra -

kepek4/18fejezet-7-11.jpg


A firefox debug lehetőségei szinte minden fejlesztő igényt kielégítenek, és méltán népszerűek, hiszen alkalmazásukkal bármilyen weblap kezelhető a linkelt javascript kódokkal együtt.

Prompt (felhasználói input) szkript gyakorlat

A javascript programok másik gyakori felhasználási területe a felhasználói adatok lekérdezése és manipulálása. A felhasználó adatok külön ablakban való lekérdezésére alkalmas a prompt utasítás, melynek egyszerű használatáról az alábbi példa szól:

Az option group-ba szervezett radio button-ok szerint háromféle összeadás lehetséges „text” „int” és „float”. A bemenő paraméterek bekérését, és az eredmény kiírását az alábbi javascript kód végzi:

A felhasználótól kapott adatok a kiválasztott „mód” szerinti összeadása az futási képernyőn:

7-12. ábra -

kepek4/18fejezet-7-12.jpg


Input (felhasználói input) szkript gyakorlat

Amikor egy vagy több felhasználói inputot kérünk be a weblapon, gyakran előfordul, hogy szeretnénk a bevitt adatokat típus és mérték szerint is korlátozni, például egy algebrai függvény értékkészlete szerint. Ilyenkor nagyon hasznosak a korábban már ismertetett <input/> típusú vezérlések, melyekkel az adatbevitel szabályozható. Legyen a feladat egy olyan függvényekből álló rendszer megjelenítése, ahol, mint a html kódból látszik, egy canvas-t használunk a kirajzolásra, melynek stílusában ún. beágyazott módon határozzuk meg a háttérképet.

A háttérkép egy példányát a projekt Images alkönyvtárába másoltuk.

7-13. ábra -

kepek4/18fejezet-7-13.jpg


A rajzolás mindig a mellékelt Input_fg.js fájlban kódolt, Input_fg() nevű függvény hívására történik meg, mely az <input/> vezérlések állapotváltozásainak eseményéhez kötött.

Vagyis html5-ben a canvas biztosítja azt az objetumot, melyre rajzolhatunk. Ez szoftvertechnológiai szempontból kísértetiesen hasonlít a 80-as évek basic alapú programozási technikájához, ami azért lehangoló kissé, mert azóta a szoftveripar jelentős szakmai erőfeszítésekkel sikeresen szétválasztotta a vizualitást és a kódokat, és kifejezetten objektum alapon kezeli a grafikai megjelenítést.

Azonban, mint azt néhány kiváló demó-n láthattuk is, például a korábban olyan népszerű Atari alapú játékprogramokat átírták html5-re !/arcade/atari-promo, s ez igen látványosan sikerült. Mi most szemléltetésként a valamikor a C64-esek korában (1983) készült „Ági” grafikai c64–es program paraméterezhető függvény megjelenítési modulját „alkottuk” újra html5 környezetben javascript segítségével.

7-14. ábra -

kepek4/18fejezet-7-14.jpg


Navigate szkript gyakorlat

A javascript kódok másik leggyakoribb alkalmazása a programozott navigáció magvalósítása. Az alábbi html kódban elhelyezett két combóban a felsorolt url-ekre navigálhatunk. A két combóban található url felsorolásból a navigációt azonban eltérő technikával valósítjuk meg. Míg ez első esetben egy nyomógomb „onclick” eseményéhez kötjük (vagyis egy plusz felhasználói beavatkozáshoz), addig a másik esetben a combo „onchange” eseményéhez, melynek hatására a választást követően azonnal megtörténik a lapváltás. Készítettünk egy „Sajatlap.htm” nevő weboldalt is a saját magunk által fejlesztett lapok közötti navigáció szemléltetésére.

A saját lap pedig a lehető legegyszerűbb kialakítású, csak egy kiiratást és egy visszatérő linket tartalmaz.

A megvalósító javascript kódok valójában nagyon hasonlítanak egymásra (össze is lehetne vonni), és az alábbiak szerint néznek ki. (Navigate.js)

Először kinyerjük a combo objektumát és a selectedIndex tagváltozó segítségével elérjük az aktuális kiválasztott url stringet. Ezt követően a documentum.locate tulajdonságának beállításával navigálunk a kívánt oldalra.

Természetesen a <head></head> szekcióban a különálló javascript kódot tartalmazó fájl elérését lehetővé tesszük egy bejegyzéssel az alábbi módon.

7-15. ábra -

kepek4/18fejezet-7-15.jpg


7-16. ábra -

kepek4/18fejezet-7-16.jpg


Canvas „osztály” szkript gyakorlat

A javascript objektumorientált tulajdonságainak kihasználására készítsünk egy korábban már megoldott feladatot, de most „osztály” felhasználásával. Az osztályokat a javascriptben, mint funkciót hozzuk létre és a tagváltozók, valamint a tagfüggvények csatolását legegyszerűbben konstruktorban valósíthatjuk meg. Az alábbi html kóddal hozzuk létre a vizualitás statikus elemeit.

A javascript kódban először létrehozunk egy osztályt, mely tagváltozóit a létrehozáskor adjuk meg, majd illesztjük a külön megírt metódust is az osztályhoz.

7-17. ábra -

kepek4/18fejezet-7-17.jpg


Ugyanazt az algoritmust használjuk és az osztályban tárolt „egységbezárt” tulajdonságok és kirajzoló függvény miatt, akár több példány is készülhetne ugyanolyan módon akár különböző színekkel.

7-18. ábra -

kepek4/18fejezet-7-18.jpg


Vagy akár több eltérő állapotú objektum is osztozhat az azonos kirajzolási felületen.

7-19. ábra -

kepek4/18fejezet-7-19.jpg


A módosított html és javascript-kód az alábbi:

Itt ragadjuk meg az alkalmat, hogy bemutassuk a Chrome nyomkövetési rendszerét, mely a szokásos F12 billentyűvel aktivizálható:

7-20. ábra -

kepek4/18fejezet-7-20.jpg


A nyomkövetés a szkript kiválasztása után az elhelyezett törésponttól folytatható. A lokális és a globális változók, valamint a tesztelő által kijelölt változók tartalma külön ablakban követhető.

Window login szkript gyakorlat

A javascript kódokkal új ablakokat is létrehozhatunk, melyekben másodlagos, vagy különleges operációkat hajthatunk végre. Az egyik tipikusan ilyen feladat a beléptetés külön ablakban. A html vizualitásban csak egy egyszerű kiiratást és két nyomógombot hozunk létre és a nevet valamint a jelszót külön ablakban kérdezzük le. Ennek megvalósítását azonban csak javascript kód felhasználásával realizáljuk.

A nyomógomb eseményében létrehozunk egy üres abalakot és a html kódokat a szkript helyezi el az új ablakban. Bárki bármit mond, a dinamikus html oldalak kódból történő elkészítéséhez mindenki használ valamilyen segédeszközt. A legegyszerűbb, ha magát az oldal vizualitását egy „tervezői” alkönyvtárban létrehozzuk, és a html kódot később innen másoljuk a javascript kódba.

7-21. ábra -

kepek4/18fejezet-7-21.jpg


A futásidőben ablakot generáló javascript kód pedig a következő:

Ebben a kódban megtervezünk egy felhasználói osztályt (user néven), és ennek egy tömbben tárolt adatait használjuk az azonosításhoz. Megjegyezzük, hogy ez csak egy tanpélda és a regisztrált felhasználók adatait szigorúan tilos a kliens oldalra eljuttatni. Vagyis adott egy login ablak, amit „feldobunk” és a beírt adatok elemzése alapján folytatjuk a beléptetést.

7-22. ábra -

kepek4/18fejezet-7-22.jpg


LocalStorage szkript gyakorlat

Egy régen meglévő jogos igény a szerver és a kliens közötti felesleges utaztatást elkerülő státusz információk (lánykori nevén cookie stb.) tárolása és visszakeresése, melyet a localStorage osztály 5MB határig megvalósít.

Példánkban legyen egy játék „forráskód” állapotának mentése és a böngésző bármikori bezárása illteve újraindítás utáni visszaállítása a feladat, melyet a fenti html vizualitással támogatunk. Ha beírunk valamit a kis editorunkba, akkor a „Mentés” nyomógombra elmentjük, a „Visszaállítás”-ra pedig a legutolsó tartalmat visszaírjuk az editorba.

Ehhez az alábbi javascript logikára lesz szükség:

A fenti kódrészletben megalkottuk a játék osztályát is (bár nem használjuk még semmire, de ha valódi lenne a feladat, akkor célszerű lenne objektumorientáltan kezelni a játékot és a játékosokat is). A futási képen a visszatöltés előtti, a módosított, és a visszatöltés után állapot látható.

7-23. ábra -

kepek4/18fejezet-7-23.jpg


GeoLokáció szkript gyakorlat

A helymeghatározás lehetőségét is biztosítja a html5 új szabványa, melyet az alábbi html vizualitáson mutatunk be:

A „Helymeghatarozas()” javascript függvény a „GeoLocation.js” külső fájlban kapott helyet.

Valójában mindössze két függvényt használunk, az első futáskor a böngésző engedélyezteti a felhasználóval a helyi adatok publikálását az alábbi képernyő szerint:

7-24. ábra -

kepek4/18fejezet-7-24.jpg


Az engedély megadása után megjelennek a kért hosszúság és szélesség adatok.

7-25. ábra -

kepek4/18fejezet-7-25.jpg