ugrás a tartalomhoz

Diszkrét Javascript

Bártházi András · 2005. Már. 19. (Szo), 23.30
Diszkrét Javascript
A Javascript ma minden bizonnyal reneszánszát éli, kezd felnőni a feladataihoz. Köszönhető ez a hozzáférhetőségre egyre nagyobb figyelmet helyező fejlesztőknek, talán a CSS-nek, s minden bizonnyal annak, hogy az elterjedtebb böngészőkben már jól használható a DOM szabvány. A cikkben, mely a PHP Konferencia előadásomra épül, a diszkrét Javascript témakörét fogjuk körüljárni, azaz megnézzük: hogyan használhatjuk úgy ezt a technológiát, hogy senkinek se okozzunk hátrányt vele.

Talán senkinek sem kell bemutatni: a Javascript egy programozási nyelv, melyet eredetileg LiveScript néven fejlesztettek ki a Netscape mérnökei, de azóta EcmaScript (a címen további részei is vannak) néven szabványos nyelv lett belőle, s az elterjedt grafikus böngészőkben megtalálható. Létezik szerver oldali és önálló, "asztali" megvalósítása is, PDF dokumentumokat is programozhatunk vele vagy akár Firefox kiterjesztések is létrehozhatóak segítségével, de ezekre nem fogunk kitérni, csakis a böngészőkben levő használatára fogunk szorítkozni. Illetve arra, hogy ezt hogyan tegyük úgy, hogy az mindenkinek jó legyen.

A Javascript egy objektum-orientált nyelv, számos előre definiált objektum áll rendelkezésünkre a böngészőkben, így egy weboldal egészéhez hozzáférhetünk, így kiegészíthetünk és megváltoztathatunk benne, illetve eltávolíthatunk belőle részeket. A weblapon belül szabadon garázdálkodhatunk, ennek minden előnyével, s hátrányával együtt.

Beszéljünk egy kicsit a hátrányokról! Ha a Javascriptet rosszul használjuk egy oldalon, s azt feltételezzük hogy a böngésző ismeri: hibát követünk el, hacsak nem vagyunk 100% biztosak benne, hogy igazunk van, például egy ismert böngészőket használó intranet hálózati megoldás esetén. Ha az internetre fejlesztünk, nem feledhetjük el annak változatosságát: van, aki nem grafikus böngészőket használ, van, aki biztonsági okokból letiltja a Javascriptet, s van, aki valamely testi fogyatékosságának okán nem is tud olyan böngészőt használni, mely támogatja azt. Ha a navigációt, az oldal valamely fontos szolgáltatását kizárólag Javascriptre építjük, hibát követünk el. A Javascript ezen használati módját hívhatjuk "tolakodó" Javascriptnek. Olyan megoldásnak, amivel látogatóink egy részét kizárjuk oldalunk használatából.

Itt kell megemlítenem a webalkalmazásokat (böngészőben használható, az asztali alkalmazásokhoz hasonlító webes programok), melyeket ha közelebbről megnézünk, bizony ilyen megoldások: csak bizonyos böngészőkkel működnek, nagy részben támaszkodnak a Javascript adta lehetőségekre, stb. A webalkalmazások célközönsége azonban általában nem mindenki, hanem egy meghatározott célcsoport, akik rendelkeznek ezekkel a kívánalmakkal felszerelt böngészővel (például egy oldal adminisztrátorairól van szó). Ha ez mégsincs így, s egy olyan alkalmazást készítünk, melynek célcsoportja a lehető legtöbb internetező, akkor két választásunk van: vagy megbarátkozunk a gondolattal, hogy mégsem tud a célcsoportunk a teljes internet lenni, vagy pedig valamilyen alternatív megoldást kínálunk, mely nem bír az összes szolgáltatással, amit a Javascriptre épülő társa tud, de a kínált funkcionalitás elérhető. Ezt a megoldást választotta a Google is a GMail esetén: kínálnak egy hagyományos felületű alkalmazást is, mely akár Javascript nélkül is használható. Ha ezt választjuk, próbáljuk meg ezt úgy tenni, hogy ne kelljen dupla munkát végeznünk. Erről is szó lesz a következőkben.

Felugró ablakok

Nézzünk meg egy egyszerű példát, egy popup ablak megnyitását. Az itt bemutatott megvalósítás több szempont miatt is rossz, ne használjuk!

<a href="/javascript:window.open('popup.html','popup');">popup nyitás</a>
Miért rossz? Mert a megvalósításhoz egy olyan megoldást használ, amely csak akkor működőképes, ha a kliensnek van Javascript támogatása. Mert egy kereső robot nem fogja tudni felismerni a linket, a popup ablakunkat nem fogja tudni leindexelni. Ez miért probléma? Előfordulhat, hogy valaki egy karakteres böngészővel, például Lynxet vagy Links-et használva próbálja meg megtekinteni az oldalt. Nos, ekkor csak bűvészkedve, az oldal forrását megtekintve fog tudni hozzáférni a popup ablak tartalmához. A tapasztalatok szerint a weblapok látogatóinak körülbelül 1%-a ebbe a kategóriába tartozik. Erre lehet mondani, hogy ez egy olyan kis szám, mellyel felesleges foglalkozni. Egészen addig, amíg elő nem fordul, hogy az egyik potenciális nagy megrendelő pont emiatt át nem megy a konkurenciához. Hogy ennek kicsi az esélye? Ki tudja. Mindenesetre én nem emiatt dobnám el a későbbiekben bemutatandó kifejezetten egyszerűen használható megoldást. És akkor nem beszéltem a keresőrobotokról sem, melyeket ha kizárunk így a tartalom eléréséből, akkor szintén csökkenni fog látogatottságunk. Egy weblap több százaléknyi látogatóját (akár több tíz százaléknyit) is hozhatnak keresők, ez sem egy lebecsülendő érv tehát.

De térjünk vissza arra, hogy hogyan lehetne a fenti kódon javítani? Sok helyen a következő, szintén hibás megoldást szokták javasolni:

<a href="#" onclick="window.open('popup.html','popup');return(false);">popup nyitás</a>
Itt a link nem mutat sehova (pontosabban az aktuális dokumentum elejére mutat). Javascriptet támogató böngésző esetében az ablak megnyílik, majd a return(false); visszatérésnek köszönhetően az eredeti esemény nem fut le, azaz nem ugrik a dokumentum elejére a böngészőnk. Az előbb felvázolt két problémát viszont nem oldottuk meg: Javascript nélkül továbbra is működésképtelen a megoldás.

Egy teljes, jól használható megoldás a következőképpen nézhet ki:

<a href="/popup.html" onclick="window.open('popup.html','popup');return(false);">popup nyitás</a>
Bekapcsolt Javascript esetén az előző megoldással teljesen megegyező eredményt kapunk, míg ha a Javascript nem támogatott, vagy ki van kapcsolva, a link akkor is működni fog. Mind a felhasználó, mind a kereső robot el tud jutni a popup ablakhoz, s meg tudja tekinteni a tartalmát. Ez jó. Ennyi volt? Nem: a probléma diszkrét Javascript megoldása esetén ez még csak a feladat egy része volt.

Diszkrét Javascript

A diszkrét Javascript azt mondja, hogy a HTML kódunkban ne használjunk Javascriptet, válasszuk le, s tegyük külön fájlba teljesen scriptjeinket, s építsük fel úgy az oldalt, hogy azok nélkül is teljes funkcionalitással bírjon - maximum nem olyan kényelmesen. Ismerősnek tűnhet az ötlet: a mai modern CSS technikák pontosan ezt mondják a stíluslapok esetén is: válasszuk szét a megjelenést és a tartalmat. A Javascript esetén a tartalom, s a használhatósági javítások szétválasztásáról van szó. A HTML azt mondja meg, mi ez a szöveg, a CSS azt, hogy hogyan nézzen ki, a Javascript pedig azt, hogy hogyan viselkedjen (az oldal). A Javascript egy nagyon jó eszköz a weblapok használhatóságának növelésére.

A diszkrét Javascript bár első ránézésre nem biztos, hogy így tűnik, a fejlesztő dolgát nem nehezebbé teszi, hanem megkönnyíti. Térjünk vissza a példánkhoz, s nézzük meg, hogyan alakul a popup ablakok sorsa.

A HTML kódunk nagyot fog egyszerűsödni:

<a href="/popup.html" class="popup">popup nyitás</a>

Diszkrét felugró ablakok

A titok nyitja a class megadása. Ahova ilyet teszünk a HTML forrásunkba, popupként fog megnyílni. Ugye milyen egyszerű? Nem kell extra Javascriptet írnunk sehova, csak egy egyszerű jelzés, s máris működik minden, ahogy szerettük volna. S CSS-ből akár még más stílust is adhatunk az ilyen linkeknek (például egy kis felugró ablakot stilizáló ikonkát kitéve ezen linkek mellé). Természetesen ehhez egy kicsit fejlesztenünk kell. De csak egyszer.

A háttérben futó Javascript nem fog mást tenni, mint az oldal betöltődése után végigmegy az összes popup osztályba (class-ba) sorolt elemen, s azoknál melyek href tulajdonsággal is rendelkeznek (biztos, ami biztos), beállítja hogy a kattintást (onclick) kapják el, s nyissanak meg egy ablakot. Ez nem olyan nehéz mint amilyennek tűnhet. A DOM függvényeket fogjuk használni a feladathoz, konkrétan a getElementsByTagName függvényt, s egy kis ciklust. Hogy egy kicsit általánosabb legyen a megoldásunk, bevezetünk egy getElementsByClass függvényt a getElementById DOM függvény mintájára. Egy tömböt fog visszaadni az összes olyan elemmel, mely egy adott osztályba lett sorolva (a class) tulajdonsággal. Íme a függvény:

function getElementsByClass(name) {
  var found = 0;
  var elems = new Array();
  var alltags = document.getElementsByTagName("*");
  if (alltags) {
    for (i=0; i < alltags.length; i++) {
        if (alltags[i].className==name) {
          elems[found++]=alltags[i];
        }
    }
  }
  return(elems);
}
A függvényünk régebbi böngészőkben nem működik - ez ellen lehet tenni kisebb kiegészítésekkel -, de ezt az olvasóra bízzuk, itt és most az érthetőségre törekszünk (és az egésznek ugye pont az a lényege, hogy nincs semmi baj, ha valaki olyan böngészőt használ, mely nem támogat valamilyen lehetőséget: a legrosszabb, ami megtörténhet, hogy nem felugró ablakban nyílik meg a link...). A függvény létrehoz egy tömböt, lekéri az oldalon levő összes elemet (ezt esetünkben, ahol csak linkeket kerestünk, szűkíthettük volna csak a elemekre), majd végigmegy rajtuk, s azokat, melyek a paraméteréül kapott osztályúak, beleteszi a tömbbe. Ezzel a tömbbel visszatér.

A fenti függvényen kívül egy másikat is használni fogunk, melynek az addEvent nevet fogjuk adni:

function addEvent(obj, evType, fn) {
  if (obj.addEventListener) {
    obj.addEventListener(evType, fn, true);
    return true;
  } else if (obj.attachEvent) {
    var r = obj.attachEvent("on"+evType, fn);
    return r;
  } else {
    return false;
  }
}
Ez a függvény egy adott böngésző objektum egy adott eseményéhez csatol hozzá egy adott függvényt, melyeket paraméteréül kap. Mint látható a kódból, sajnos a böngészők kapcsán nincs egység a megvalósítás terén, de nem árt, ha tudjuk, hogy a szabványos megoldás a W3C DOM szabványa szerint az addEventListener. Objektum alatt általában egy HTML elem böngészőbeli leképezését szoktuk érteni, így egy linkről, vagy az oldal window eleméről is szó lehet (ez utóbbi a <body> elemmel ekvivalens, amennyiben a load eseményét szeretnénk kihasználni). Második paraméternek az esemény nevét kell megadni, mely szintén sokminden lehet, így egy click, azaz kattintás esemény. A konkrét alkalmazást mindjárt látni fogjuk, de a függvényről még tudni kell, hogy nagy előnye: egy bizonyos elem egy bizonyos eseményéhez akár több függvényt is hozzárendelhetünk, szemben azzal a Javascript megoldással, ahol egy objektum onclick tulajdonságának állíthatunk be egy darab függvényt (objektum.onclick=fuggveny).

Ezután nincsen más dolgunk, mint végigmenni az első függvényünk által kapott elemeken, megnézni, van-e href tulajdonságuk, melyek nem üresek (nehogy egy popup osztályú div elemre állítsuk be a felugró ablakként működést), s ha igen, akkor beállítani a kívánt viselkedést. Íme:

function classPopupHandler() {
  var elems=getElementsByClass('popup');
  for(i=0;i<elems.length;i++) {
    if (elems[i].href && elems[i].href!='') {
      addEvent(elems[i],'click',doPopup);
    }
  }
}
A kívánt viselkedés itt a doPopup függvény meghívása lesz. Ez a függvény a következőképpen néz ki:

function doPopup(ev) {

  // vagy megkapjuk az esemény objektumot, vagy meg kell szereznünk
  ev || (ev = window.event);

  // mely objektum váltotta ki az eseményt?
  var source;
  if (typeof ev.target != 'undefined') {
    source = ev.target;
  } else if (typeof ev.srcElement != 'undefined') {
    source = ev.srcElement;
  } else { return(true); }

  window.open(source.href,'popup');
  
  // eseménnyel mi foglalkoztunk, nem kell továbbvinni
  if (ev.preventDefault) {
    ev.preventDefault(); ev.stopPropagation();
   } else {
    ev.cancelBubble = true; ev.returnValue = false;
  }
  return false;
}
Ha a doPopup függvényt közelebbről megnézzük, a lényegét tekintve nagyon hasonlít ahhoz a Javascript kódhoz, melyet az onclick tulajdonságba írtunk be nem is olyan rég: nem tesz mást, mint megnyit egy ablakot. Négy különválasztható részből áll, melyek egy részét ha jobban beleássuk magunkat a témába, célszerű külön függvényként megvalósítani. Az első részben az ev objektumot keressük meg. Elvileg a függvény paramétereként érkezik, de Internet Explorer alatt egy "globális" változót kiolvasva juthatunk hozzá. Ezután meghatározzuk, mely objektum váltotta ki az eseményt - ez is böngészőfüggő módon történik (ha ez sikertelen, akkor be is fejezzük a futást). A window.open megnyitja az ablakot, végül pedig arról gondoskodunk, hogy a bekövetkezett eseményt más már ne kezelje le, konkrétan ne nyíljon meg az eredeti ablakban a linkelt oldal.

Nos, ezután egy dolgunk maradt, valahogy elérni, hogy az oldal betöltődése után elinduljon a classPopupHandler függvényünk. Ehhez a következő sort kell hozzáadnunk Javascriptünkhöz:

addEvent(window, 'load', classPopupHandler);
És ezzel be is fejeztük a fejlesztést, ha betöltjük az oldalunkhoz ezt a külső Javascript fájlt, teljesen automatikusan elvégzi a dolgát.

Továbbfejlesztési lehetőségek

Ha egy kicsit gondolkodunk a működésen, több dolog is felmerülhet bennünk. Hogyan mondhatjuk meg, hogy mekkora legyen a felnyíló ablak? Szabályozhatjuk-e, hogy megjelenjenek a görgetősávok az ablakban, vagy ne? Ha nem popup ablakot szeretnénk megnyitni, más jellegű paraméterezési lehetőség is előjöhet, hogyan oldhatjuk ezt meg? Nos, több válasz is van a kérdésre.

A beállításokkal törődjön a felugró ablak maga

A felugró ablak döntse el saját maga, hogy mekkora szeretne lenni, szeretne egy görgetősávokat, stb. Ezt Javascripttel, illetve CSS segítségével meg lehet oldani. Előnye, hogy bármennyi méretünk lehet, van azonban hátránya is. Az ember nem szereti a felugró ablakokat (ez más téma, most nem térnék ki rá), de ha még át is méreteződik egy ilyen ablak, főként, ha például a böngészőben azt állította be az ember, hogy ez egy új fül legyen, nos, az még zavaróbb lehet. Még ha ez nem is lenne baj, akkor sem néz ki szépen az a folyamat, amikor megnyílik egy nagy ablak, s egy kisebbé ugrik össze. De van más lehetőség is.

Nem kell paraméterátadás

Ha a diszkrét Javascriptet szeretnénk megérteni, forduljunk bátran a modern CSS nézőponthoz! Hogyan jön ide a CSS? A következőképpen: egy általános szabály ott, hogy ne a megjelenéshez, hanem a funkcióhoz definiáljunk CSS stílusokat. Ne legyen pirosbekezdes, kekbekezdes osztályunk, hanem legyen figyelmeztetes és informacio nevű. Ha közelebbről megnézzük, a piros és kek része az előbbi osztályneveknek paraméterként értelmezhető. Ez azonban a későbbiek folyamán megváltozhat, s lehet, hogy nem is piros színű lesz az a bekezdés, vagy a piros színen kívül mást is be kell állítanunk. Nos, a helyzet ugyanez a Javascript esetén is. Ha különböző viselkedést szeretnénk, definiáljunk különböző osztályt hozzá. Ha ezután megváltozik a feladat, s egy kicsit nagyobb ablakot kell megynyitni, akkor nem a HTML forráshoz, hanem a Javascripthez kell hozzányúlnunk. És ez a lényeg: egy olyan réteg bevezetése, mely egy központi helyen teszi menedzselhetővé a feladatokat.

Ha mégis kell

Ha ennek ellenére mégis szükség lesz paraméterátadásra, többféleképpen járhatunk el (de tényleg gondolkodjunk el, szükség van-e erre!). Íme a lehetőségek:
  • az osztályba vegyük bele a paramétereket (href="/popup.html" class="popup 320 200")
  • definiáljunk saját tulajdonságokat (href="/popup.html" class="popup" width="320" height="200")
  • adjuk meg a link paramétereiként a tulajdonságokat (href="popup.html?width=320&height=200" class="popup")
Lássuk, melyik miért jó, miért nem jó!

Az osztályba történő paraméter bevétel látványos, de a HTML szabvány szellemiségéhez nem kifejezetten passzol. Az osztály tulajdonság akármennyire is szép megoldásnak tűnik a fenti, de nem arra van, hogy paramétereket adjuk át általa. Ez bármely más tulajdonság esetében is hasonlóképpen lesz, a HTML-ben nincs erre alkalmas tulajdonság. Egy további probléma, hogy opcionális paraméterek átadása ebben az esetben csak megkötésekkel, körülményesen lehetséges (kötött a paraméter sorrenddel).

A saját tulajdonságok használata szintén egy tetszetős megoldás, a szabvány szellemiségével sincsen baj, "csak" a szabvánnyal magával ütközik, ugyanis ilyen paraméterek nincsenek benne. Egy megoldás lehet az, hogy saját DTD-t definiálunk, s ebben az esetben a kódunk is helyes lesz, a paramétereket is át tudjuk adni. Ez egy megoldás lehet, bár elég körülményes.

A harmadik lehetőség, ahol a linkhez valódi paramétereket rendelünk, egy ötletes és szép megoldás a problémára. A felugró ablakot nyitó kód kiolvashatja ezeket a paramétereket, akár le is szedheti a linkről, tehát megoldhatja, hogy a megnyitott ablaknak (Javascript támogatás esetén) már át se adódjanak. Ezzel a technikával akkor lehet gond, amikor a diszkrét Javascript technikát nem egy link esetében szeretnénk alkalmazni, ekkor ugyanis nem áll rendelkezésünkre href tulajdonság, aminél beállíthatjuk ezeket.

Hogyan legyünk diszkrétek?

A diszkrét Javascript ismérvei a korábbiakban már elhangzottak. A példa kapcsán megismerhettük, hogy hogyan kell ennek jegyében megnyitni egy felugró ablakot, de természetesen ennél jóval többet nyújt ez a filozófia, technika. Erről még írok. De nézzük át, hogy miket kell elsajátítanunk, illetve hogyan kell gondolkodnunk ahhoz, hogy ennek ezen technológia jegyében készítsük el oldalunkat!

Javascript nélkül, vele, s az átmenet a kettő között

Gondoljuk végig, hogy milyen funkciót szeretnénk megvalósítani, s ez ha van Javascript hogyan nézne ki. Ha ez megvan, akkor pedig azon gondolkodjunk el, hogy lehet egy ehhez legjobban közelítő funkciót megvalósítani, de immár Javascript nélkül. Mindezt úgy, hogy az oldal manipulációjával a Javascript nélküli esetet át tudjuk alakítani (Javascript segítségével) az eredetileg elképzelt megoldásra. Ha ez megvan, talán ez a legnehezebb akkor a legfontosabbal meg is vagyunk.

Vegyünk egy példát: a feladat az, hogy ha egy beviteli mező fölé megyünk, jelenítsünk meg egy rövid súgószöveget hozzá egy div elem segítségével. A Javascript feladata itt a mező fókuszba kerülésekor és annak elvesztésekor ennek a div elemnek a megjelenítése, illetve eltüntetése lesz. A funkciót tehát elképzeltük. Hogyan jelenítenénk meg egy súgót akkor, ha nem Javascripttel szeretnénk megoldani a feladatot? Például úgy, hogy a beviteli mező alatt minden különösebb bonyolítás nélkül kiírjuk a szöveget.

Hogyan közelíthető egymáshoz a két megoldás? A Javascript kód megkeresi az oldal összes beviteli mezőjét, s megnézi, van-e hozzá súgószöveg. Például a súgószöveget tehetjük egy div elembe, aminek az azonosítójának az eleje megegyezik a beviteli mező azonosítójával, a vége pedig _help, vagyis ha a beviteli mező azonosítója name, akkor a hozzá tartozó súgóé name_help. A megtalált div elemeket elrejti a Javascript, majd a beviteli mező focus és blur eseményéhez egy megfelelő kódot rendel. Ezek fogják a súgó szöveget megjeleníteni, illetve elrejteni, amikor azt kell.

A feladat megoldva. Vegyük észre, hogy a felugró ablakos példával ellentétben itt nem használtunk osztályokat, itt másképp jelöltünk meg elemeket, hiszen azokat hozzá is kellett rendelni egy beviteli mezőhöz. A viselkedési réteget jelentő diszkrét Javascript megoldás nem konkrét problémákra kíván megoldást, hanem általános szemléletmódot kínál.

Használandó technológiák

A legfontosabb felhasznált technológia a W3C DOM. Ez egy hozzáférési módszert, eljárásokat, tulajdonságokat definiál. Az újabb böngészőkben használatos Javascript ezt a szabványt megvalósítja, s így a HTML (vagy éppen megtekintett más dokumentum, például XML) esetén ahhoz a DOM keretében hozzáférési, s manipulációs lehetőséget kínál. Magát a szabványt, s annak különböző verziót jó, ha megismerjük, de nem árt tudnunk, hogy az egyes böngészőknek (a legmodernebbeknek is) vannak elmaradásaik.

A diszkrét Javascripthez ezen kívül javasolt ismerni a CSS lehetőségeit (megjelenítés, elrejtés), s azt, hogy hogyan férhetünk az oldal s egyes elemeinek CSS-éhez hozzá Javascriptből.

Ha szép megoldásokat szeretnénk készíteni, jó ha ismerjük a Javascript lehetőségeit, s a HTML célját, lehetőségeit, s a szabványt és annak szellemiségét is.

A fenti technológiák egyáltalán nem bonyolultak, de ha nem is ismerjük mindet, akkor is van merre elindulnunk, ahogy a felugró ablakoknál láthattuk, kis lépésekből egy kényelmes és célszerű megoldást állíthatunk össze.

Mire jó még?

A diszkrét Javascript lehetőségeinek száma végtelen, legalábbis annyira, amennyire a CSS biztosít ezer és egy megjelenési lehetőséget egy oldalhoz. Nincs szó új technológiáról, nincs szó új célokról, a fentiekben "csak" egy viszonylag új szemléletmód bemutatására került sor.

További két lehetőséget felsoroltam előadásomban is, az egyik a textareaknak wyswiwyg osztály beállításával HTMLArea szerkesztővé történő átalakításáról szólt, a másik módszer pedig a Weblabor oldalain használt fülek kialakításának kapcsán mutatatta be a diszkrét Javascriptet.

Bármilyen meglepő, a Weblabor oldalain is mutattunk már be a diszkrét Javascript filozófiájára építő technikát, mely a Dinamikus betűméret választásba nyújtott betekintést. Ebben az esetben a "kezelőszerveket" akkor tettük csak ki, ha volt Javascript támogatás a böngészőben, vagyis csak akkor, amikor használni lehetett ezt a funkciót - egy extra viselkedést tettünk ezzel a módszerrel elérhetővé, ha pedig nem volt rá lehetőség, mint ha ott se lett volna, nem zavartak senkit a nem működő gombok.

Bízom benne, minden olvasó kedvet kap ehhez a szemlélethez, hiszen számos szempontból hasznos, s egy jobban működő webet is eredményez. Ha valakinek van ötlete, példája, hogy mire használta már ezt a megoldást, szívesen venném, ha megosztaná hozzászólás formájában, illetve ha tud róla egy hosszabb lélegzetvételű írást összeállítani, szívesen vennénk cikk keretében is.
 
Bártházi András arcképe
Bártházi András
Az Emarsys-nál dolgozik vezető fejlesztőként, és az API-ért, integrációkért felelős termékmenedzserként. Szeret profi csapatban profit alkotni.
1

pictureviewer

gellert · 2005. Már. 20. (V), 00.35
Hát ha már annyira kéred :-), éppen most raktam ki egy ilyen megoldást: egy kép nagy méretben való megtekintését pont az általad vázolt módon oldottam meg, pedig nem voltam ott a PHPConf-on :-)
http://arcok.ujevangelizacio.hu/bubu/hanna.html
Maga a modul vagy új ablakban vagy az oldalon is működő megoldással jeleníti meg a képet.
2

Konferencia

Bártházi András · 2005. Már. 20. (V), 09.59
Most már viszont tudom, hogy miért nem jöttél a konferenciára! Gratulálok a babához! :)

-boogie-

ui: a módszer sem rossz... ;)
3

Pár link

Bártházi András · 2005. Már. 20. (V), 10.10
Egy fontos mű:
Unobtrusive Javascript

Egy hasonló megoldás a cikkben bemutatotthoz:
Unobtrusive Popup Windows

Még egy hasonló megoldás:
Accessible Pop-up Links

Paraméterezés:
Onclick JavaScript parameters

-boogie-
4

javascript objektumok

prezi · 2005. Már. 20. (V), 11.41
Mivel nem osztály alapú a javascript objektum kezelése, ezért a programunkban nyugodtan hozzáadhatunk egyéb metódusokat, tulajdonságokat egy már létező objektumhoz.
pl:
objektumneve.sajatmetodus=sajatfuggveny;

Ez esetleg segíthet kiegészíteni a dom objektumokat egyéb funkcionalitással (databinding, adatlekérés a szerverről, stb.) kiegészíteni.

Az saját események létrehozása, és azok lekezelése még érdekes lehet, ezt sose próbáltam, de kíváncsi lennék rá :)
5

Példa script

Anonymous · 2005. Már. 20. (V), 13.11
Én gondoltam, hogy kipróbálom a példaprogramot, de nem jártam sikerrel. Az a hiba, ami a prezentációban volt ebben a
addEvent(document.body, 'load', classPopupHandler);
sorban, az itt már nincs, viszont sem IE-bem, sem FF-ban nem nyit uj ablakot, hanem a sima href alapjan tölti be az új oldalt.
Viszont a http://www.alistapart.com/d/popuplinks/examples.html cimen lévő példák működnek, bár ez egy kicsit másképp oldja meg a kérdést.

Gyulus
6

addEvent

Bártházi András · 2005. Már. 20. (V), 21.25
A végső addEvent-et elszúrtam, ugyanis nem a document.body, hanem a window objektum rendelkezik load eseménnyel. Javítottam, köszi a hibajelzést.

-boogie-
7

addEvent

Anonymous · 2005. Már. 20. (V), 22.08
Igen, a window tényleg javít rajta, így már felugrik az ablak, viszont az eredeti helyére is betöltődik a megnyitott oldal, hiába van ott a return(false).
Csak nálam van így?

Gyulus
8

:((

Bártházi András · 2005. Már. 20. (V), 22.53
Nem, nem csak nálad, hogy ez miért nem tűnt fel nekem korábban? További rossz hír, hogy az Internet Explorer másképp értelmezi a this-t, így nem az eseményt kiváltó objektumot adja vissza, ezért még egy további bűvészkedés kell. No, elkezdem átírni a cikk ezen részét. :)

-boogie-
9

:((

Anonymous · 2005. Már. 20. (V), 23.00
Látod, látod... :)
Javaslom, hogy ha elkészülsz, akkor az előadás prezentációjában is javítsd a javascripteket, ne legyen ott se lóvá téve a fél világ... :)

Gyulus
10

Javítva ez is

Bártházi András · 2005. Már. 20. (V), 23.06
A dolog működne különben, "csak" ott buktam be, hogy szerettem volna elegánsabbá tenni a kódot, s az egyszerű xyz.onclick= helyett a prezentáció és a cikk írása közben átírtam addEvent-re az esemény hozzárendelést (ami nem baj), s ezzel egy "kicsit" megváltozott a környezet.

-boogie-
11

Javítva ez is

Anonymous · 2005. Már. 21. (H), 12.00
Köszi, ez így már tényleg jó.
Operával azt is ki lehet próbálni, mi van, ha olyan böngészõvel nézik, ami nem ismeri az ilyesmi javascripteket. (Legalábbis a 8béta3-ban szépen belenyitja az elõzõ oldalba.)
Kiegészítettem magamnak a paraméterátadással, így lehet méretezni is a popup ablakot.

Gyulus
19

this

wiktor · 2005. Ápr. 3. (V), 14.43
Erről a this-es problémáról tudnál egy linket dobni, ahol leírják, hogy mi a gond vele? :)
20

this "probléma"

Bártházi András · 2005. Ápr. 3. (V), 19.36
Mindenekelőtt: a cikkben már javítva lett a problémás kód. A lényeg, hogy ha onclick értékébe írsz egy kódot, akkor ha this-t használsz, az az aktuális HTML elem, aktuális objektum, pl. maga a link lesz. Ha egy függvényt rendelsz az objektum click eseményéhez, akkor a függvényben használt this böngészőtől függően fog az aktuális függvényre, vagy az eseményt kiváltó, pl. link elemre, objektumra mutatni. A példában, ha le akarod kérdezni, hogy az eseményt kiváltó link hova mutat, akkor előbb ki kell deríteni, hogy melyik objektum volt az, ami ezt kiváltotta (source meghatározása), s csak utána tudod lekérdezni - erre a this itt már nem jó.

Linket, ahol ezt leírják, nem tudok, bár biztos van.

-boogie-
21

this megint

wiktor · 2005. Ápr. 5. (K), 14.59
Csak azért kérdeztem, mert én erről az oldalról http://www.quirksmode.org/js/this.html tanulgattam és itt nem írt ilyesmiről a kedvencem... :)
22

oda van írva

Bártházi András · 2005. Ápr. 5. (K), 16.20
Bár valóban nem hangsúlyozta ki, de bizony oda van írva. Egyrészt hogy mikor nem használható a this, pl. onclick="doSomething()" eseténe nem, másrészt hogy ha attachEvent-et használsz, akkor az olya, mint a onclick="doSomething()". A kettőből egy kis logikával kijön, hogy bizony, nem minden esetben használható a this.

-boogie-
23

megvagyok :)

wiktor · 2005. Ápr. 5. (K), 18.46
Jogos, teljesen jogos! :) Nem figyeltem oda elég rendesen... De most már értem... :) Boccs, hogy nem vágtam elsőre... :)
12

Üdv

Anonymous · 2005. Már. 23. (Sze), 12.16
Üdv Mindenkinek,

kérdésem, hogy az 'function addEvent(obj, evType, fn) ' sorban szereplő 'fn' függvénynévnek át lehet e adni, hogy melyik 'obj' objektumtól kapta az eseményt? Ha jól tudom az 'fn'-nek nem lehet paramétere a hozzárendeléskor?

Üdv
Sanyi
13

doPopup

Bártházi András · 2005. Már. 23. (Sze), 18.05
Lásd a doPopup függvényben levő source meghatározását végző részt.

-boogie-
14

Köszi,

Anonymous · 2005. Már. 23. (Sze), 19.43
Köszi,

közben magam is rájöttem ugyanerre a megoldásra
azért tutijó a dolog, egyre jobban kezd tetszeni :)

Üdv
Sanyi
15

Még...

thamas · 2005. Már. 28. (H), 09.39
Boogie!

Nem lenne kedved (időd, energiád) ;o) egy JS sorozatot írni az alapoktól, kezdőknek?

Üdvözlettel:
Hajas Tamás
16

Javascript

Bártházi András · 2005. Már. 28. (H), 10.16
Biztos vagyok benne, hogy lesz még szó a Javascriptről a Weblabor hasábjain. Addig is, ezt tudom ajánlani: http://wish.hu/oktatas/javascript.html ;)

-boogie-
17

Sajnos

thamas · 2005. Már. 30. (Sze), 12.11
A webes dolgok nálam hobbiként működnek csak, sajnos. Így se időm, se pénzem nincs, sajna, a linkelt tanfolyamra (amit már korábban felfedeztem...).
Nincs esetleg a tanfolyamnak vmilyen megvásárolható segédlete?
(Bocs, ha ez itt már off!)

Üdvözlettel:
Hajas Tamás
18

itt off

Hojtsy Gábor · 2005. Már. 30. (Sze), 20.05
De ott nem: http://weblabor.hu/forumok/temak/6354
24

a tag-be ágyazott img ...

Anonymous · 2005. Ápr. 8. (P), 13.58
A doPopup()-ban
source = getParent(source, 'a'); sort beszúrva az alábbi elé:
window.open(source.href,'popup');
A rekurzív getParent() metódus 'visszakeresi' a szülő 'a' tag-et.
Így már a beágyazott img-en is működik a dolog.
(Enélkül a source.href értéke undefined, lévén a source-ban img található)

function getParent(el, pTagName)
{
if (el == null) return null;
else if(el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) return el;
else return getParent(el.parentNode, pTagName);
}

forrás: http://isaacschlueter.com
26

Isaac Z. Schlueter

Anonymous · 2005. Május. 3. (K), 01.59
Thank you for the link. I don't speak hungarian, but it's always nice to see my stuff on other sites.

I didn't create the getParent function, however. It's all over the internet. I'm not sure who created it first.
25

nem működik

Anonymous · 2005. Ápr. 17. (V), 13.11
Nekem sajnos nem működik ez az egész...
Hiába rakom oda a return false-t, attól még átírányítja...
Üdv:
ChaTeve
27

Nekem így ment! (Tobiaspm)

Anonymous (nem ellenőrzött) · 2005. Május. 24. (K), 11.41

<html>

<head>
<meta http-equiv="Content-Language" content="hu">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250">
<title>alma</title>
<script language="javascript">
	function belepes( obj )
	{
		window.open( obj.href, '', '' );
	}
</script>
</head>

<body>
<p><a href="/index.htm" onclick="belepes( this ); return false">alma</a></p>
</body>

</html>
28

Szerintem! (Tobiaspm)

Anonymous · 2005. Május. 24. (K), 11.51
Szerintem ebben az esetben tök fölösleges osztályokkal bajlódni, mert sokkal többet dolgozik a gép és hosszabb a kód is és bonyolultabb.
29

Lásd cikk

Bártházi András · 2005. Május. 24. (K), 13.31
A lényege az egész bajlódásnak, hogy ha egyszer megcsináltad (vagy innen kimásoltad), sokkal egyszerűbben kezelhető, karbantartható lesz, egy központi helyen megváltoztatható, skinezhető, stb.
A diszkrét Javascript bár első ránézésre nem biztos, hogy így tűnik, a fejlesztő dolgát nem nehezebbé teszi, hanem megkönnyíti.

-boogie-
30

Opera - onload

Balogh Tibor · 2005. Jún. 13. (H), 10.49
Kipróbáltam az itt leírtak egy részét. Egy oldalon a window.onload eseményhez rendelt függvény rak ki egy ikont. Miért van az, hogy az Opera - 8.01 verzió - úgy gondolja, hogy a window.onload eseményét többször is végre kell hajtania?
Miatta kellett készíteni az addEvent függvényen kívül egy removeEvent függvényt is. Ti ezt hogy oldottátok meg?
31

Az Operáról...

kgyt · 2005. Jún. 13. (H), 23.19
Az Opera alapbeállításban újrarajzolja az oldalt betöltődés után egy másodperccel. Ez a megjelenítést teszi jobbá, de akit zavar, az kikapcsolhatja a beállításoknál.

--
Szeretettel: Károly György Tamás
kgyt&kgyt.hu - http://kgyt.hu
32

Opera újrarajzolja betöltéskor az oldalt

Balogh Tibor · 2005. Jún. 16. (Cs), 10.25
És ez miért vonná magával azt, hogy a load eseménynek többször is végre kell hajtódnia? Oldal újrarajzolása =/= oldal újratöltése. Mellesleg azon a weboldalon amin kipróbáltam, a következő eljárás nem csak kétszer kakukkolt, hanem megállás nélkül, a nyomtatás ikon nem is volt hajlandó működni.

addEvent(window, 'load', putOutPrintIcon);
function putOutPrintIcon(){
 if (document.getElementById && window.print){
  var printSpan = document.getElementById('printIt');
  if (printSpan){
   printSpan.innerHTML = '<img src="/printer.gif" alt="nyomtatás" />';
   addEvent(printSpan, 'click', printDocument);
  }
 }
 alert('kakukk');
 //removeEvent(window, 'load', putOutPrintIcon);
}
(Megj: A Firefoxban is be lehet állítani, hogy hány másodpercenként rajzolja ki az oldalt.)
33

cikk

inf · 2005. Okt. 11. (K), 16.44
Jó a cikk, a popupos dolog mondott 1-2 új dolgot, de egyénként szerintem nem valami nagy újdonság az egész, sokan már évek óta használják.. pl:
http://www.ozones.com
(az oldalnak azért nincs javascript nélküli része, mivel a témája, hogy hogyan lehet alkalmazni a javascriptet :>)
34

igen

Bártházi András · 2005. Okt. 11. (K), 18.29
Köszönöm a dícséretet.

A cikk nem feltétlenül vérprofikhoz, hanem kezdőkhöz szól, s ha találtál benne érdekességet, akkor már elérte a célját esetedben is: újdonságot nyújtott. Az lehet, hogy sokan évek óta használják a dolgot, viszont sokan pedig nem.

Az általad írt oldalon semmi olyat nem találtam, ami diszkrét JavaScriptre utalt volna, ami a cikkem témája. A diszkrét JavaScript lényege, hogy az oldal működik JavaScript nélkül is, ha nincs JavaScript nélküli rész, akkor rossz példa diszkrét JavaScriptre (persze attól még lehet jó az oldal). De lehet, hogy félreértettelek, mire gondoltál?

-boogie-
35

<Nincs cím>

inf · 2005. Okt. 23. (V), 03.56
Pont fordítva, én értettelek félre, mert csak felületesen olvastam a cikket, és azt hiszem nem voltam tisztában a diszkrét javascript fogalmával. :) Én inkább úgy értelmeztem, hogy az a fontos benne, hogy a program minden böngészőn működjön, és az csak egy adalék, hogy ha éppen nem támogatja a böngésző a javascriptet, akkor is elérhető legyen az információ. Szóval azt hiszem kissé elhamarkodott volt a hozzászólásom, bocs érte. (Egyébként így tényleg újat mutattál nekem, mert nálam kb az lenne javascript nélküli böngészőknél, hogy behoz egy másik oldalt a php, amiben abszolut nincs javascript..)
36

Egy kis gyorsítás....

sly · 2006. Ápr. 15. (Szo), 02.59
Ha tudjuk hogy milyen tag-hez kell, akkor csak azt választjuk ki. Nagyob oldal esetén akár még hasznos is lehet. 2000 elem helyet csak 100-at kell átbogarászni. :-)
function getElementsByClass(name,tag) {
  var found = 0;
  var elems = new Array();
  if (tag) var alltags = document.getElementsByTagName(tag);
  else var alltags = document.getElementsByTagName("*");
  if (alltags) {
    for (i=0; i < alltags.length; i++) {
        if (alltags[i].className==name) {
          elems[found++]=alltags[i];
        }
    }
  }
  return(elems);
}
37

az addEvent függvény pontosítása

wodka · 2006. Aug. 31. (Cs), 16.40

function addEvent(obj, evType, fn) {
  if (obj.addEventListener) {
    obj.addEventListener(evType, fn, TRUE); //false kell legyen!!!
    return true;
  } else if (obj.attachEvent) {
    var r = obj.attachEvent("on"+evType, fn);
    return r;
  } else {
    return false;
  }
}
Az addEventListener utolsó paramétere false kell legyen, az ezen az oldalon található instrukciók szerint. http://onlinetools.org/articles/unobtrusivejavascript/chapter4.html

Alapból az itteni megoldást használtam, de Operában nem működött, ezért kezdtem keresgélni. A 'false'-ra változtatás megoldotta a problémámat.

Az eredeti szöveg, amit emberünknek az Opera fejlesztői küldtek:
The addEvent function is not entirely standards-compliant. It will work for now in FireFox but once they fix this bug it will not work reliably in FireFox anymore. It probably does not do what you want in Opera, it supports the standards correctly. The issue is that you set up a "capturing" event handler by using "true" as the third argument to the addEventListener function:
if (obj.addEventListener){ 
   obj.addEventListener(evType, fn, true);
That true should be false. If it is true, the event listener should not fire for any element the event listener is registered on. For instance, if you use this with a LI element it will not do anything unless the LI has child elements. Test in Opera :)
38

Azért ez elég nagy égés

ashtor · 2009. Ápr. 16. (Cs), 09.17
Ha már előadásokat tartasz...
...meg cikkeket írsz...

...légyszíves előtte teszteld már le amit írsz.

Ez önmagáért beszél, de azért még egy építő jellegű kritikával megtoldanám:

Jó a cikkk. Csak sajnos a cikkben használt kódok "használhatatlanok". Ahány hozzászólás, annyiszor kellett javítani a kódot. Most akkor a cikk elején mit látok? A régi, rossz kódot, vagy már a hozzászólások alapján javított kódot?

Ha legközelebb ilyen van, legalább az oldal elején tüntest fel a következőt:

A) Kedves júzer, hagy a francba ezeket a kódokat mert jelezték, hogy nem megy. Olvasd végig a hozzászólásokat, majd aztán a 3-4 variációból csak találsz magadnak egy működőt

b) Kedves júzer, az elöször közölt kód hibás volt, de itt most a hozzászólások alapján javított, letesztelt, működő kódot látod.

Üdv:
Ashtor
39

És hol a hiba?

Török Gábor · 2009. Ápr. 16. (Cs), 10.25
Kérdés, hogy jobb-e egy adott helyeken pontatlan cikk mint egy semmilyen cikk? Bártházi András írásaiban tudása javát nyújtja, ahogy a Weblaboron mindannyiunknak ez a célja: egymással megosztani, hogy a közösnek több legyen. András írt egy hasznos és gondolatébresztő cikket, amelyben voltak elírások, apróbb hibák. Nem szakmai tévedések, valótlan állítások, hanem apróbb hibák. Ezeket a közösség javította. Most van egy klassz, hibátlan cikk. Nem látom, hol a hiba.
40

Ott, hogy a cikk vegen azert

hron84 · 2009. Nov. 29. (V), 00.42
Ott, hogy a cikk vegen azert illene megjelolni, hogy a cikk a hozzaszolasok alapjan javitasra kerult.

Egyebkent a pontatlansag josaga attol fugg. Egy typo nyilvanvaloan konnyen javithato hiba, am ha a cikk targyi pontatlansagokkal kuszkodik, akkor inkabb a semmilyen cikk a jo. Adott esetben a nem mukodo kodok lekozlese helyett jobb lenne, ha a cikk inkabb egy kodot sem tartalmazna. Ezt a portalt elsodlegesen kezdok olvassak vagy olyanok, akik segitsegre vagynak, nem pedig plusz munkara.
41

Gondolom tudsz olvasni

Joó Ádám · 2009. Nov. 29. (V), 02.28
Olvasol egy cikket.
Elolvasod a hozzászólásokat.
A hozzászólásokban jelzik, hogy ez és ez a hiba van a cikkben.

Ha ennyire megterhelő összevetni a jelzett hibát és a cikk szövegét, megállapítandó, hogy a hiba javításra került-e, akkor lehetséges, hogy a webfejlesztés, lévén nagyságrendekkel komplexebb problémákkal szembesít, nem neked való terület.

Ezt felismervén a problémád már meg is oldódott, hisz így értelmét veszti a cikk olvasása.

Minden jót.
42

Érdekes hangnem.

inf · 2009. Dec. 6. (V), 18.02
Érdekes hangnem.

Szerintem, ha veszi a fáradságot arra, hogy cikket írjon, akkor legalább egy minimális tiszteletet tanúsíthatnál felé.