A következő címkéjű bejegyzések mutatása: web. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: web. Összes bejegyzés megjelenítése

2009. szeptember 17., csütörtök

Statikus file-ok organizációja

Előszó

Egyszer már neki fogtam ennek a cikk megírásának, ellenben az idő ahogy múlt, maga az írás is idejét múlt lett, újabb ötletek és próbálkozások történtek a módszerrel, finomodtak a műveletek.

Most újra nekifogok, ezúttal gyorsan és hatékonyan, hogy ne járjon el felette az idő vasfoga.

Bevezetés

Sokan írtak mostnában arról, hogy ők hogyan is rendezik a CSS-en belül a tulajdonságokat, hogyan generálják saját CSS Framework-jükkel a file-okat. Gondoltam itt az idő, hogy én is megosszam a saját módszeremet.

Mikor kialakítottam ezt a rendszert, mindvégig az volt a szemem előtt, hogy a látogatóknak a lehető leggyorsabban jelenjen meg minden, illetőleg a lehető leggazdaságosabban tudjuk őket kiszolgálni – kapcsolatok és kérések minimalizálása, file méretek csökkentése –, ugyanakkor fejleszteni se legyen egy rémálom, hogy minden egy 100K-s CSS file-ban van. De ne ugorjunk ennyire előre, kezdjük a legelején.

Tehát az egész megoldást a következő szemszögekből kell megvizsgálni:

  • a látogató;
  • és a fejlesztő.

A látogató

A látogatónak csak egy fontos: amit meg akar nézni, azt gyorsan megkapja. Hogy az oldal betöltésénél ne kelljen várnia több másodpercet és a betöltődött oldal ne egye meg a gépét.

Először Stoyan Stefanov említette meg a "High Performance Web pages" prezentációjában, amit azóta a legtöbb Yahoo! YSlow-val, illetve front-end optimalizációval kapcsolatos blogban és prezentációban hangoztatnak, miszerint:

  • We won't tolerate slow pages
  • 500 ms slower = 20% drop in traffic (Google)
  • 100 ms slower = 1% drop in sales (Amazon)

Ebből is látszik, hogy mennyire nagy "teher" van a front-end web fejlesztőkön, Rajtunk!

A fejlesztő

Most nézzük meg, hogy számunkra mi az, ami fontos. A CSS, JavaScript és egyéb állományokat jól struktúráltan kell tárolni. Ennek két megközelítése lehet:

  • oldalanként szeparált könyvtárba;
  • típusonként (modulonként) könyvtárba.

Eleinte az első megközelítést alkalmaztam, ellenben túl sok refaktorálással járt, mikor egy-egy állomány az oldal fejlődésével "közös" kódra épült. Ilyenkor mindig ki kellett emelni a saját könyvtrából, elhelyezni a közös kódoknak fenntartott konyvtárban, minden hivatkozást átírni, stb. Egy szóval jellemezve: macerás volt.

A második esetben már alapból egységnyi modulokra szétbontva tároljuk a CSS file-okat, így jóval ritkább esetben fordul elő, hogy egy új oldal/funkció létrehozásakor refaktorálnunk kelljen az állományainkat.

A struktúra

A struktúra, amit jelenleg használunk a következő (az itt látható könyvtárak a statikus állományokat kiszolgáló domain gyökerétől értendők):

[css] [common] browser_hacks.css footer.css header.css layout.css [component] captcha.css … [css_module] date.css nick.css … [loader] commonLoader1.css … cssModuleLoader1.css … componentsLoader1.css … pagesLoader1.css … [page] [shared] comments.css index_index.css style.css [img] [js] [swf] [build] (style-pack.php)

Amint látható, a CSS, JavaScript és kép illetve flash file-ok teljesen elkülönítve vannak tárolva a fejlesztés alatt. Azért írtam, hogy a fejlesztés alatt, mert a publikálás során az összes állomány átkerül a [build] könyvtárba ömlesztve, ezzel is csökkentve a kiszolgáláskor szükséges útvonal és a hozzá tartozó feloldáshoz szükséges idő hosszát.

A [css] könyvtár

A [common] tartalmazza a teljesen általános, minden oldalon használt – vagy használható – stílusokat, mint pl. az oldal struktúra, fejléc, lábléc vagy az általános, minden böngészőben használandó "hack"-ek.

A nálunk használt keretrendszerben lehetőség van a programból előállított, több helyen használt egységek – úgynevezett blokkok és komponensek – használatára. Ezek elkülönített stíluslapjai találhatóak a [component] könyvtárban. Ilyen például a captcha megjelenítő, vagy egy értékelő form megjelenítő.

A [css_module] könyvtárban található egységek hasonlítanak a [component]-ben található stíluslapokhoz, ellenben az itt elhelyezett különálló modulok nem programból generált tartalmak. Ilyenek a beviteli mezők, a felhasználói nick-ek, gombok, linkek, dátumok, címkék, stb. megjelenítése.

Az összes oldalhoz tartozik egy külön CSS file, még akkor is, ha az adott oldal megjelenése ezt nem követeli meg, tehát kvázi egy üres CSS file-ról van szó. Ezeket a file-okat a [page] könyvtárban helyezzük el. Amennyiben két vag több oldal megjelenése struktúrálisan megegyezne, ellenben azok nem modul szinten azonosak – tehát nem lehet sem a [component], sem a [css_module] könyvtárakban logikusan elhelyezni –, a [page]-en belül található [shared] könyvtárba rakjuk. Ezeket a file-okat az összes őt használó page szintű CSS file-nak a legelején importáljuk, így könnyen nyomon lehet követni, hogy mely oldalak használják azt.

Utoljára hagytam a fejlesztés és publikálás szempontjából legfontosabb könyvtárat, a [loader]-t. Ebben a könyvtárban találhatóak azok a loader típusú CSS file-ok, melyek az összes korábbi elsődleges könyvtárban (common, component, css_module és page) található file-okat importálják magukba. Erre azért van szükség, mert sajnálatos módon az Internet Explorer 6-os nem képes, csak maximum 31 @import szabályt feldolgozni egy CSS file-ból, és mindezt maximum 4 szint mélységig. A fentebb részletezett struktúrával elértük azt, hogyaz ilyen import mélység maximum 3 mélységű legyen.

Speciális CSS file-ok

style.css 

A style.css gyakorlatilag nem tartalmaz mást, mint a [loader] könyvtárban található loader típusú CSS file-okat importálja be. Így a három mélységünk a style.css-től számolva a következő:

  1. loader file-ok;
  2. common, component, css_module és page file-ok;
  3. a page file-okban található esetleges shared file-ok.

browser_hacks.css 

Jelenleg nálam a következőket tartalmaza:

  • Safari 3 és 4 szöveg anti-alias megjelenítési bug;
  • Mozilla Firefox alatt button és gomb típusú input-okon :hover esetén nem jelenik meg a text-decoration formázás;
  • Általánosan a képeket inline-block-ra állítani;
  • Internet Explorer 6-nál korábbi böngészők alatt a linkek-re a kurzor beállítása;
  • Internet Explorer 7 és újabbak, illetve a modern böngészők alatt a hidden input-ok elrejtése;
  • Internet Explorer alatt az input-ok dupla padding hack-je.

Mintakód

html, body, input, select, textarea, button { text-shadow: rgba(0, 0, 0, 0.01) 0 0 0; } input[type=hidden] { display: none !important; } @-moz-document url-prefix() { button, input[type=button], input[type=submit] { display: inline-block; } } a { cursor: pointer; cursor: hand; } img { display: inline-block; } input { _overflow: visible; }

Oldal stíluslapok

Ezek a stíluslapok találhatóak a [page] könyvtárban. A HTML-ben minden oldal kap egy, az oldal tartalmát tökéletesen beazonosító azonosítót. Ezt általában a body elemre rakott id attribútum használatával érhetjük el. Ennek segítségével oldható meg, hogy – bár az összes oldal stíluslapja be van mindig töltve, – csak a megfelelő oldal stílusai legyenek a tartalmunkra érvényesítve. Ez az azonosító megegyezik a CSS file nevével. Amennyiben egy máshol definiált komponensnek kicsit másképp kell kinéznie az adott oldalon, úgy az ilyen kivételek is ebbe a file-ba kerülnek.

Hogy jobban szemléletessem, íme egy mintakód, melyben a belépő oldalon a beviteli mezőkben nagyobb a szövegméret, mint az általános:

#user_login span.textInput { height: 26px; } #user_login span.textInput input { font-size: 18px; height: 22px; }

Kódolási konvenciók

Akár egyedül, akár többen dolgoznak is egy projekten, fontos, hogy minden típusú állománynak meglegyen a saját (lefektetett) írásmódja (kódolási konvenció). Nálunk jelenleg a következő minta alapján történik mindez:

h1, #myDiv .className { display: inline-block; color: #000; /* Azert kell, mert IE-ben kulonben nem jelenik meg a tartalom. */ _overlay: inline; }

Kiválasztó(k)

  • Minden kiválasztó szabályt külön sorba kell írni, azokat a specifikációban meghatározott módon vesszővel elválasztva. A vesszőt a szabály végén, közvetlenül – szóköz nélkül – kell írni.
  • A HTML elemeket kisbetűvel írjuk, követve az XHTML szabványt.
  • A class elnevezéseknek és azonosítóknak beszédesnek, de nem hosszúnak (maximum 15-20 karakteresnek) kell lenniük, és követniük kell a camelCase írásmódot.

A camelCase írásmód alól kivételt képeznek nálunk a rendszer jellegéből adódólag az oldalakat beazonosító id-k.

Személy szerint a következő ponttal ellent megyek a Google Page Speed elveinek, miszerint minél kevesebb kiválasztót használjunk, helyette minden elemnek adjunk saját class elnevezést vagy id-t. Ennek az ajánlásnak az az oka, mivel a böngészők a CSS selectorokat nem elölről, hanem hátulról kezdik el feldolgozni, emiatt a #myDiv div.container div ul li a span kiválasztónál először az összes span-t keresi meg a DOM fában, majd vissza felé lépkedve ebből az elem csoportból szűri ki a mintára nem illeszkedő elemeket. Ebből következik, hogy ha a cél span-ra rakunk egy containerLinkSpan class-t, jóval gyorsabban meg fogja találni az illeszkedő elemeket a DOM-ban a böngésző.

A kérdés persze az, hogy vajon miért is teszik ezt a böngészők? Illetve akkor mi értelme van egyáltalán a selector-oknak a CSS-ben és miért kellett újabbakat létrehozni a CSS3-ban? Illetve, hogy a HTML méret növekedése és a DOM-beli attribútumok számának növelése lassítja jobban a betöltést, vagy a "felesleges" CSS selector-ok?

  • A HTML kódban a lehető legkevesebb class elnevezést és id-t kell használni, helyettük használjuk a kiválasztókat.

Nyitó kapcsoszárójel

  • A nyitó kapcsoszárójelet minden esetben az utolsó kiválasztó után, szóközzel elválasztva kell írni, majd utána sortörést rakni.

Szabályok

  • Minden szabály külön sorba irandó, a szabály végén a pontosvessző kirakása kötelező;
  • A sorokat indenteljük egy tabulátor karakterrel;
  • A tulajdonságot és az értékét – betűcsalád és file útvonal kivételével – csupa kisbetűvel írjuk;
  • A HEXA színkódokat szintén kisbetűvel írjuk, és ahol #RRGGBB formátumú színt írunk, ott írjunk #RGB-t;
  • Amennyiben hack-et írunk, úgy azt plusz egy tabulátorral beljebb indentáljuk és felette megjegyzésben odaírjuk, hogy miért kell az adott hack-et használni.

Publikáló script-ek

Ezeknek a script-eknek nem más a feladata, mint az általunk gondosan szétválogatott és az előre megbeszélt kódolási konvenciók által megírt, kommentekkel ellátott CSS és JavaScript file-jainkból a lehető legkisebb, minden felesleges karaktertől megtisztított – a CSS file-ok esetében a kérések minimalizálása érdekében az importálandó file-okkal összevont (merge) – végleges file-okat hozzák létre.

Verziózás

Fontos továbbá az is, hogy amennyiben a Yahoo! YSlow és Google Page Speed ajánlásokat követve statikus állományainkat kellően hosszú lejárati idővel szolgáljuk ki, a megfelelő állományokra hivatkozásokat – például a CSS file-okban a képek – ellássa egy megfelelő verziószámmal, melynek hatására a böngészők új file-ként értelmezik őket, így nem a böngésző cache-ből, hanem a szerverről kérik le azt.

A verziószámmal való ellátásra kétféle megoldásunk lehet:

  • a file után irandó query string-ben helyezzük el (my_image.png?1234);
  • a file nevét egészítjük ki (my_image_1234.png).

CSS file-ok publikálása

A publikáláskor a script-ünk a style.css file-t dolgozza fel. A lépések, melyeket végrehajt:

File merge-elések

Az @import-ok helyére magának a file-nak a tartalmát "másolja" be rekurívan.

preg_replace('/\s*@import\s+(url\()?"(?P<file>.*?)"(?(1)\));/xe', '…', $cssLine)

Útvonalak normalizálása

Az így keletkezett tartalomban a képekre hivatkozások útvonalát normalizálja.

preg_replace('/(?<!@import )\s*url\(([^\'"].+?)\)/e', '\' url(\'.….'\'', $cssFileContent);

Ezekután a script megkeresi az összes képre való hivatkozást…

/url\((.+?\.(?:gif|jpg|png))\)/

…majd az általunk kiválasztott módszerrel ellátja a verziószámmal, amely jöhet SVN, CVS vagy Git revízió számból, vagy a file utolsó módosításának timestamp-jéből is.

Tartalom minimalitzálása

  • Felesleges sor eleji és végi whitespace-ek és kommentek törlése;
  • Felesleges egynél hosszabb whitespace-ek cseréje egy space-re;
  • A szabalyokban lévő felesleges whitespace-ek törlése;
  • "a b a b" értékek átalakítása "a b"-re;
  • "a b c b" értékek átalakítása "a b c"-re;
  • Mértékegységgel rendelkező 0 értékek cseréje mértékegység nélkülire;
  • Felesleges whitespace-ek eltávolítása a kapcsoszárójelek és vesszők körül;
  • #rrggbb színkódokból #rgb-t csinálunk;
  • !important előtt felesleges a whitespace;
  • Szabályokban az utolsó pontosvessző felesleges, ezeket töröljük.

Mintakód

preg_replace( array( '/(^\s+|\s+$|\/\*.*?\*\/)/s', '/\s+/', '/(\w)\s*:\s*(.+?)\s*(?:;|(\}))\s*/', '/(\d+(?:[a-z]{2}|%)?)\s+(\d+(?:[a-z]{2}|%)?)\s+\\1\s+\\2/', '/(\d+(?:[a-z]{2}|%)?)\s+(\d+(?:[a-z]{2}|%)?)\s+(\d+(?:[a-z]{2}|%)?)\s+\\2/', '/(?<=\D)0(?:[a-z]{2}|%)?/', '/\s*([{},])\s*/', '/#([a-f0-9])\\1([a-f0-9])\\2([a-f0-9])\\3/i', '/\s+!important/', '/;\}/' ), array( '', ' ', '$1:$2;$3', '$1 $2', '$1 $2 $3', '0', '$1', '#$1$2$3', '!important', '}' ), $content);

Böngésző specifikus hack-ek alkalmazása

A feladata az általánosan ismert böngésző hiányosságok pótlása a tartalomból. Ennek a megoldásnak köszönhetően a fejlesztés során nem kell törődni a böngészők ilyen irányú hiányosságaival, a script a szabványosan megírt CSS tartalomból állítja elő számunkra a böngésző-független forrást.

Ezek a hack-ek jelenleg a következők:

  • A inline-block tulajdonságot Firefox 2.0 nem ismeri, helyette display: -moz-inline-box; értéket kell alkalmazni;
  • A min-height és min-width tulajdonságot az Internet Explorer 7 és korábbi böngészők nem ismerik;
  • A :hover-t nem támogatják az Internet Explorer 8-nál korábbi verziók, csak a elemeken, így ezekre JavaScript-es megoldáshoz létrehozunk egy .originalClassName.hover nevű selector-t is;
  • Az opacity tulajdonságot nem kezelik a Firefox 2.0 és korábbi és az Internet Explorer 8-nál korábbi böngészők.

Mintakód

preg_replace( array( '/\bdisplay\s*:\s*inline-block\b/is', '/\bmin-height\s*:\s(\d+[a-z]{2}|%)/is', '/\bmin-width\s*:\s(\d+[a-z]{2}|%)/is', '/([^},\n]*?(?:\s|>|\+|:[a-z-]+\()(?:[^a]|[a-z]{2,}|\*)(?:\.\w+)*):hover(\s+[^{,\n]+?)?(?=\s*[{,\n])/isx', '/\bopacity\s*:\s*(\d*\.\d+|\d+)/ise', ), array( 'display: -moz-inline-box; display: inline-block', 'min-height: $1; _height: $1', 'min-width: $1; _width: $1', '$1:hover$2, $1.hover$2', 'opacity($1)' ), $content);

opacity() metódus

function opacity($value) { $value = (string)max(min((float)$value, 1), 0); return '-moz-opacity: '.$value.';'. 'opacity: '.$value.';'. 'filter: alpha(opacity='.(int)($value * 100).')'; }

JavaScript file-ok publikálása

A cél az, hogy vonjuk össze a lehető legtöbb JavaScript file-t, azokat minimalizáljuk (pack) a lehető legjobban, majd helyezzük el az így kapott file-t a [build] könyvtárban. Természetesen a file-jainkat szeparáltan tároljuk a fejlesztés során, a kérdés mindig a kiszolgálás mikéntjében rejlik.

Itt két megközelítés lehetséges. Az egyiknél a fejlesztés során van könnyebb dolgunk, a másiknál pedig a látogatónak kedvezünk. Amint azt korábban is már írtam, nem szabad csak a látogatót figyelembe venni a döntések során, a fejlesztő is ugyanolyan fontos!

Ha eldöntöttük, hogy melyik módszert alkalmazzuk, már csak a pack-elés módját kell kiválasztani. Számos mások által megírt megoldás közül is választhatunk. A megoldások után írt érték egy 120KB-s jQuery file-on végrehajtott méretcsökkenést jelent.

  • A Mozilla Rhino például a változóneveket lerövidíti a lehető legkisebbre, ügyelve azok láthatóságára. (43%)
  • Használhatjuk Dean Edwards által írt JavaScript Packer-t. Ez egy JavaScript-ben írt tömörítő. A hátránya, hogy némely kódok – például régebbi jQuery plugin-ek, stb. – nem működnek vele, illetve mivel maga a kicsomagoló JavaScript-ben íródott, ezért mire a becsomagolt script-ünk a letöltés után mire elérhetővé – értelmezetté – válik, eléggé sokáig tart. (66%)
  • Yahoo! YUI Compressor: sajnos ez idáig nem volt még vele tapasztalatom, mivel korábban a fenti két megoldást ötvözve használtam, az átállás egy hosszabb folyamat lenne, mert a YUI Compressor-ral is le kellene tesztelni minden eddig megírt – több, mint 1MB – JavaScript file működését az összes általunk támogatott böngészőn. Ez nagyon nagy munka, de idővel meg kell majd lépnünk, mert a JavaScript Packer a legkülönfélébb helyenek tud hibákat produkálni, melyek felderítése időigényes. (53%)

Minden JavaScript file-t külön pack-elünk

Nem szükséges minden módosítás után build-elni, mivel minden file-t be tudunk húzni a HTML-ben, amire szükségünk van.

Példával illusztrálva, ha nekünk van egy jQuery-nk (jquery.js), hozzá plugin-ek (jquery.scrollto.js és jquery.autocomplete.js) és a saját függvényeinket tartalmazó file (base.js), akkor ezeket egyenként fogjuk betölteni a HTML-ünkben mind a fejlesztés, mint éles környezetben. Ennek előnye, hogy a módosításokat azonnal tesztelhetjük, hátránya, hogy megnöveljük a betöltődés idejét, mivel megnöveltük a lekérések számát (minimum 4 JavaScript file betöltése mindig).

JavaScript file-ok összevonása egy file-ba

Ekkor a HTML-ben csak egy file-ra hivatkozunk, emiatt minden módosítás után szükséges az összevont file újboli létrehozása. Ez megnehezíti a kód tesztelését, bár szerintem idővel hozzászokik az ember, illetve a programozáshoz és teszteléshez való hozzáállást is javítja. Megfigyeltem, hogy mikor ezt a módszert alkalmaztam, egy idő után kevesebb hibát vétettem a programokban.

Persze lehet a build-elést automatizálni, akár lekéréskor a fejlesztői környezetben generálni a pack-elt JavaScrip file-t, de ez a betöltési időt növeli meg még akkor is, ha éppen nem a JavaScript-jeinkkel dolgozunk.

Képek

Ha már a publikáló script-jeink elvégeznek helyettünk mindent, miért is ne foglalkozzanak az oldalon használt képek optimalizálásával is. Ezzel mind mi spórolhatunk sávszélességet, mind a látogatónak gyorsabban töltődnek azok be.

Mi a fejlesztés során akár használhatunk minden esetben 24 bit-es PNG-ket – Internet Explorer 6 miatt átlátszóság nélkül –, azokból a programunk generálhat majd GIF vagy PNG8 képeket, annak megfelelően, hogy melyik eredményezi a kisebb file méretet.

Fotók esetén természetesen a JPEG formátumot használjuk, ellenben ezeken a file-okon is lehet optimalizációt végezni. Akár megcsinálhatjuk azt is, hogy a JPEG-jeinket mindig 100%-os minőségben mentjük ki. A publikáló script fog azokból egy általánosan elfogadott minőséget generálni – mondjuk egy konfigurációs file-ban előre, képenként külön is meghatározható beállítások szerint.

Ami viszont lényeges file méret csökkenést okoz, ha a JPEG és PNG file-jaink header-jeit csonkítjuk meg a lehető legjobban. Erre léteznek külön programok is, mint pl. a jpegtran vagy az OptiPNG. Ezen programok haszbálatával akár 40-50%-kal is csökkenthetjük a képi állományaink összméretét.

2009. június 14., vasárnap

Anchor, Button és Input…

…avagy hogyan legyen minden böngészőben ugyanolyan a gombunk. Hát ezt is sikerült – valamilyen szinten – megalkotni. Íme a kód minden körítés nélkül:

.button {
    border: 1px solid red;
    background: yellow;
    font-size: 12px;
    color: #000;
    display: inline-block;
    font-family: Arial;
    text-decoration: none;
    text-align: center;
    padding: 1px 1px 2px!important;
    margin: 0;
    cursor: pointer;
    vertical-align: bottom;

    /* Internet Explorer 7 button padding hack */
        overflow: visible;
        !width:auto!important;
    /* Internet Explorer 6 button padding hack */
        _width: 0;
        _padding: 0;
}

a.button {
    _padding: 1px 1px 2px;
}

/* Firefox button padding hack */
input.button::-moz-focus-inner,
button.button::-moz-focus-inner {
    border: 0;
    padding: 0;
}

Egyelőre csak IE6 és 8, valamint Firefox 3 és Safari alatt néztem meg, de remélhetőleg IE7 alatt is működik a dolog, holnap kitesztelem!

És kezd már elegem lenni az IE6 és 7 töketlenkedésekből!

2009. április 23., csütörtök

step-by-step

Avagy, ha arra vetemedünk, hogyan is fogjunk hozzá a tanulásnak.

Webszerkesztő / sitebuilder:

  1. Legyünk képesek a Photoshop használatára, legalább alapszinten.
  2. Tanuljunk meg angolul, ugyanis minden(!), amire szükségünk lesz, angolul írják — maximum lefordították már magyarra / németre, de az soha sem pontos;
  3. A web elengedhetetlen nyelve a HTML, ezért olvassuk át tüzetesen a w3c HTML referenciáját;
  4. Mivel szemantikus és táblázatmentes oldalt akarsz csinálni, nem törődve az elavult technológiákkal, ezért szükséged van a Cascading Style Sheets alapos megismerésére;
  5. Ezután, elképzelhető, hogy ki kell egészítened a készítendő oldaladat diszkrét JavaScript-tel (más néven ECMAScript), így annak sem árt, ha tudod, hol van a referenciája. Illetve, hogy hol vannak az MSIE specifikus dolgok leírva;
  6. Fontos továbbá a DOM és az AJAX ismerete is, a jelenlegi tendenciát figyelembe véve, így ezek ismerése is hasznos lehet a további munkáid során.

Webfejlesztő:

  1. Tanuljunk meg angolul, ugyanis minden(!), amire szükségünk lesz, angolul írják — maximum lefordították már magyarra / németre, de az soha sem pontos;
  2. A web elengedhetetlen nyelve a HTML, ezért olvassuk át tüzetesen a w3c HTML referenciáját;
  3. Nem árt, ha tudod, hol van a referenciája a JavaScript-nek (más néven ECMAScript). Illetve, hogy hol vannak az MSIE specifikus dolgok leírva;
  4. Fontos továbbá a DOM és az AJAX ismerete is, a jelenlegi tendenciát figyelembe véve, így ezek ismerése is hasznos lehet a további munkáid során;
  5. Ezekután jöhet az, amit tulajdonképpen tanulni is akartál, magának a programozási nyelvnek a megtanulása. Az mindegy, hogy Perl, PHP, Python, Ruby vagy ASP.
  6. Kifelejtettem egy fontos dolgot, most pótlom. Tehát a komplexebb rendszerek kialakításához, ami kicsivel több már, mint egy “Hello World!” progi, általában szükséged van valami adatbázis használatára is. Ez többféle lehet, sokan használják a MySQL. Kisebb feladatokra ott van az SQLite, de ha jót, gyorsat, okosat akar az ember, akkor érdemes komolyabb adatbáziskezelőt használni, mint például postgreSQL.

Továbbá fontos lehet még pl. XML, XSL és XSLT vagy SOAP ismerete is és még sorolhatnánk, de azok már mind-mind feladatfüggő tudások, melyeket — persze feladattól függetlenül is, csupán kedvtelésből –, akkor kell csak megtanulnunk, ha szükségünk lesz rájuk.
És egy fontos dolgot ne feledj, mielőtt bármilyen kérdést is felteszel levelezőlistán, fórumon, chaten, bárhol, a manuálokban mindig minden benne van, csak a megfelelő helyen kell keresned. Gondold végig mit akarsz csinálni. Például mivel dolgozol — string, array, stb. –, és akkor a manuálnak egyből a megfelelő részén tudod keresni a megoldást. Ha netán nem lenne meg, vagy valami hibaüzenetet kapsz, hibajelenséget tapasztalsz, keress rá google.com-on, biztos, hogy az első pár találatban, de az első két oldalon ott lesz a megoldás a találatok között. Nem te vagy az első, aki belefutott ezekbe a problémákba, hiszen most kezdted az egészet. Nem fogod feltalálni a spanyolviaszt, még ha úgy gondolod is.

A listákról, fórumokról, csatornákról

Igen, akik segítenek, le fognak szólni, mert olyat kérdezel, amit te magad is megtalálhattál volna. Akik ott vannak, nem az a dolguk, hogy válaszoljanak. Ők egy közösség része, akik segítenek, ha úgy ítélik meg, érdemes az illetőn segíteni és látszik rajta a tanulásvágy!

Remélem tanulsz ebből is!

2009. február 23., hétfő

A pixelben méretezett szövegeket az IE8 még mindig nem méretezi át

A 456Bereastreet.com legújabb cikkében arról ír, hogy az új IE sem fogja a szövegeket átméretezni, melyeket pixelben határoztunk meg.

Nem tudom, hogy mekkora haszna van ennek, főként, hogy hanyan használhatják. Én – nem hinném, hogy lustaságból –, pixelben adom meg a szövegek méretét. Mivel egy biztos, hogy az minden böngészőben és platformon ugyanúgy fognak megjelenni, nem függve attól, hogy a felhasználó pl. Windows alatt milyen dpi-t állít be a monitorára.

Ugyebár vannak módszerek:

body {
font-size: 62.5%;
}

És 1em az 10px lesz, viszont amikor eddig használtam, csak a baj volt belőle. Biztos bennem van a hiba…

2009. február 12., csütörtök

URL-ek linkesítése szövegben

Bent merült fel ismét a probléma, hogy hogyan lehet a legegyszerűbben lecserélni egy szövegben a benne található webcímeket (URL) kattintható HTML linkekre. A megtalálásuk igazából annyira nem volt bonyolult, aki írt már pár reguláris kifejezést (regular expression), annak szerintem egy 10-15 perces ujjgyakorlat:

/(?:[a-z]+:\/\/)?(?:\S+?(?::\S+?)?@)?(?:[a-z0-9][a-z0-9-]*[a-z0-9]\.)+[a-z]{2,6}(?:(?:\/|\?).*?(?=\s|<|$))?/imx

Viszont mi van azokkal az URL-ekkel, amik elé nem lett kitéve a protokoll azonosító (pl. http://)? Erre találtam ki azt, hogy – úgysem tudjuk elkerülni azt, hogy ne csak egy preg_replace() legyen – akkor minden href-be rakjuk bele egyből a "http://"-t az elejére és majd utána cseréljük le a "http://protokoll://"-t a "protokoll://"-re.

A kész és működő kód itt látható:

preg_replace( array( '/ (?<=\s|[^@a-z0-9]|>|^) # protocol (optional) (?:[a-z]+:\/\/)? # username:password@ (optional) (?:\S+?:\S+?@)? # ip address or domain name (?: # ip address (?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?) | # domain name (?: # domain name without tld (?:[a-z0-9][a-z0-9-]*[a-z0-9]\.)+ # tld (?: ac|ad|ae|aero|af|ag|ai|al|am|an|ao|aq|ar|arpa|as|asia|at|au|aw|ax|az| ba|bb|bd|be|bf|bg|bh|bi|biz|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz| ca|cat|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|com|coop|cr|cu|cv|cx|cy|cz| de|dj|dk|dm|do|dz| ec|edu|ee|eg|er|es|et|eu| fi|fj|fk|fm|fo|fr| ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy| hk|hm|hn|hr|ht|hu| id|ie|il|im|in|info|int|io|iq|ir|is|it| je|jm|jo|jobs|jp| ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz| la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly| ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mo|mobi|mp|mq|mr|ms|mt|mu|museum|mv|mw|mx|my|mz| na|name|nc|ne|net|nf|ng|ni|nl|no|np|nr|nu|nz| om|org| pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pro|ps|pt|pw|py| qa| re|ro|rs|ru|rw| sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz| tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|travel|tt|tv|tw|tz| ua|ug|uk|us|uy|uz| va|vc|ve|vg|vi|vn|vu| wf|ws| ye|yt|yu| za|zm|zw ) ) ) # port: 1-65535 (optional) (?::(?:[1-9]|[1-5]?\d{2,4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-5]\d|6556[0-5]))? # path, query string, fragment (optional) (?: # path separator (slash) or query string separator (?) (?:\/|\?) # anything until a whitespace, tag opening character (<) or EOL or EOF .*? )? (?=\s|<|$) /imx', '/http:\/\/([a-z]+:\/\/)/' ), array( '<a href="http://$0">$0</a>', '$1' ), $text );

Amennyiben találnál olyan URL-t, amire a fenti kód nem működik, kérlek tudasd velem és tovább finomítom. URL-ek, amiket próbáltam már (HTML tag-ek között is):

  • username:password@example.com/path/file.html?queryString
  • http://example.com
  • https://username@example.com/path?foo=bar+baz#fragment
  • sub.example.com?foo=bar

2009. január 21., szerda

Újabb Flash bug(?) fragment-hez ugráskor

Történt is mostanában, hogy szükség lett volna arra, hogy a Flash egy bizonyos anchor-hoz ugorjon – megszokott <a href="#header" /> megoldás HTML-ben –, szóval gondoltuk tök egyszerű lesz, hogy navigateToUrl('#header'); és boldogság!

Minden szépen és jól működött, amíg meg nem próbáltuk Safari alatt – OS X és Windows egyaránt –, és tapasztaltuk, hogy bizony az a fránya Flash valamiért az egész oldalt újratölti.

Megnéztem, ha HTML-ből egy link segítségével ugrok a #header-hez, akkor nem tölti újra, csak Flash Player-ből hívva, ebből is a következtetés, hogy Flash Player bug.

Ideiglenesen a navigateToUrl()-nek JavaScript hívást adunk át, így áthidalva a problémát, de szeretünk gondolni a JavaScript-et nem engedélyező látogatókra is!

Valaki valami megoldást?

2008. november 2., vasárnap

Saját JavaScript event dispatch-elése Flash-ből

Igen, ez a nagy kérdésem, hogy hogyan is lehetne ezt? Flash-ben bekövetkezett eseménykor szeretném, ha értesülne róla a JavaScript, tehát, hogy a beágyazott Flash Applet egy JavaScript event-et dispatch-eljen.

Valaki tud rá megoldást?

Nem, a fix metódusnév meghatározása nem jó, az nem Event driven megoldás lenne, és nekem nem is jó most!

Update: Kicsit kifejteném, mert kaptam visszajelzést, hogy nem eléggé érthető.

Amikor rákattintunk egy gombra, akkor az egy "click" típusú Event-et dispatch-el. Ugyanakkor lehetőségünk van arra is, hogy saját típusú Event-eket dispatch-eljünk, amikor csak akarunk. Ugyanilyen "tudással" bír az általunk beszúrt <object /> elem is, ami a fentebb említett Flash Applet-ünket tartalmazza. Na, én ebből a Flash Applet-ből szeretnék valahogyan az őt tartalmazó <object />-ünkön egy saját típusú Event-et dispatch-elni.

Ha valaki még mindig nem értené, szívesen elmagyarázom bővebben!

2008. október 30., csütörtök

IPC2008 — Architectures for scaling AJAX applications

Igazából nem volt szó másról, minthogy egy oldal lekérésekor a teljes megjelenítési időnek:

  • a 10%-a szerver-oldalon történik;
  • a maradék 90% viszont a kliensnél, így ezen lehet a legtöbbet gyorsítani
    • a kliensnél 10% a HTML letöltése és feldolgozása
    • a maradék 90%-on osztozkodnak a JavaScript, CSS és egyéb média file-ok.

Az oldal felépítési optimalizációról később szeretnék majd írni, mivel úgyis kell belőle egy előadást tartanom a cégnél.

Ezen kívül sokszor elhangzott a widget kifejezés, mely most számomra új értelmet nyert. Itt most nem arról volt szó, hogy egy 3rd party widget-et szúrsz be az oldaladba, és ez tök jó lesz, hanem, hogy az oldalad felépítéséből adódóan — a HTML oldalak dobozokból épülnek fel — ezekre a dobozokra külön entitásként, widget-ként kell tekinteni, és egyesével érdemes őket lefejleszteni, kezelni. A közöttük fellépő interkaciót pedig ún. publish/subscribe módszerrel megvalósítani, ami a gyakorlatban event-ekre propagálást jelent JavaScript-ben.

Szó volt még a Client-side template-ekről, amiknek én nem nagyon látom értelmét, pláne, hogy azokat a szervertől kérnénk le minden esetben. Persze ha igény van rá, akkor kifejthetem!

2008. október 29., szerda

IPC2008 — WebSocket az Internet új úttörője

Bevezetés

Ma egy teljesen jó Keynote-on sikerült részt vennem.

A Kaazing.org egyik alapítója, Jonas Jacobi beszélt a jelenlegi HTTP hátrányairól. Legfőképp a Half-Duplex problémát és a ma egyre terjedő RI alkalmazások — számára a RIA "Richer, and Interactive Applications"-t jelenti — miatt felvetődött igényeket taglalta.

Előkerült, hogy a w3c és a HTML5-öt fejlesztő egyéb csoportok 2022-re tervezik kiadni a végleges specifikációt, ugyanakkor elmondta, hogy nem kell aggódnunk, azért is ilyen távlati időpontokat adnak meg egy-egy specifikáció véglegesítésére, mivel ha azt mondanák, hogy a specifikációt mondjuk 2010-re véglegesítenék, akkor azt megvárnák a böngésző-fejlesztők és ezzel önmagunkat hátráltatnánk. Emiatt viszont, hogy 2022-re tették a véglegesítés időpontját, a böngésző-fejlesztők apránként — ahogy az a <canvas> elemmel is megtörtént —, a véglegesítése előtt már implementálni kezdték.

Megoldás (?)

Hogy mi az, amivel Jacobi a megváltás reméli számunkra, RIA fejlesztőkre? A neve WebSocket. Igazából nem másról van szó, mintsem, hogy engedjék a böngészők, hogy hozzáférjünk a TCP réteghez, ami ugyebár a HTTP alapja, és így kétirányú, Full-Duplex kapcsolatot építhessünk ki.
var myWebSocket = new WebSocket('ws://my.example.com/application');

Ennyi a kód, amivel létrehozhatunk majd JavaScript-ben egy ilyen WebSocket-et. Ennek az objektumnak három Event Handler-t állíthatunk be:

  • Open
  • Message
  • Close

Open

Amikor a kapcsolatunk létrejött hívódik meg.

Message

Minden, a szerver által push-olt üzenetkor hívódik meg. A kapott üzenetet az Event Handler-nek átadott event objektumon keresztül érhetjük el.

Close

A kapcsolat lezárásakor hívódik meg. Ezt a lezárást mind a kliens, mind a szerver kezdeményezheti.

A lényege

A WebSocket Server bármikor küldhet üzenetet a kliens számára, így nem kell a kliensnek a mai megoldásokkal időközönként ping-elni a szervert. Ezzel a megoldással időt, pénzt spórolhatunk meg:

  • Időt és pénzt, mert az ilyen alkalmazások (IM, mail, tőzsdei figyelő, játékok, stb.) fejlesztési ideje töredékére csökken.
  • Időt, mert az eseménykor azonnal megjelenik a kliensnél az eredmény, nem csak X idő múlva.
  • Pénzt, mert felesleges sávszélességtől kíméljük meg a szerverünket.

Nagy jövőt látok a WebSocket-ben, szerintem hatalmas fejlődés lesz az internet történetében ez, az 1992-es HTTP modellt megújító megoldás! Mostmár csak a böngészőknek kell implementálniuk a WebSocket-et, amint lesz belőle draft specifikáció.

2008. október 28., kedd

IPC2008 — PHP Konferencia 2008, Mainz, Németország

Kint vagyok, majd később írok is az itt látottakról, hallottakról. Két előadásonvagyoktúl, remélem a többi is ilyen jó lesz!

2008. október 22., szerda

Adobe Flash Player és Internet Explorer FlashVars bug

Amint azt ígértem korábban, egy újabb felfedezett bug-ot írok le. Úgy egy héttel ezelőtt ráment egy egész délutánunk, hogy rájöjjünk a megoldásra.

Kitérő

Egy eléggé nagy oldalnak a sitebuildere vagyok, így eléggé érdekes dolgokba tudok belefutni. Egy más oldalakba beágyazható videólejátszót készültünk a publikum számára elérhetővé tenni, viszont a tesztek során — ami persze a fejlesztés során minden más böngészőben (fejlesztés alatt Mozilla Firefox és Safari böngészőket használok) jól működött — előjött, hogy Internet Explorer-ben természetesen nem működik tökéletesen.

Alap elgondolásban úgy működött volna az egész, hogy a felhasználó egy állandó kódot ágyaz be az oldalába, mert ezt természetesen később nem tudjuk megváltoztatni, ahogy a youtube.com sem tudja. Így a beszúrt lejátszó útvonala tartalmazta volna a videó azonosítóját és query string-ben egy szín hexa kódját, ami a videó háttérszínét határozhatja meg.

Ezután a megadott URL mögötti kis okosság tovább dobja a lejátszó aktuális címére, query string-ben a videó azonosítójával, a megadott színnel és egyéb paraméterekkel felvértezve.

Példában: <object/> forrásának ez van megadva: http://example.com/videoid?color=eeeeee, ami átirányit így: http://example.com/player.swf?id=videoid&color=eeeeee&foo=...

Szóval ez volt az alap elképzelés, de valamiért csak a color változót látta a lejátszó, és nem értettük! Végül rájöttünk!

Megoldás

Az ActiveX-es Adobe Flash Player valamilyen okból kifolyólag a beszúráskor, tehát a HTML-ben megadott query string-et veszi alapul flashvars-nak. Az átirányítást figyelembe veszi, tehát a végleges cél flash file-t fogja betölteni, de az ott megadott query string-et már nem fogja flashvars-nak beadni. Ez csak akkor történik így, ha a HTML-ben van query string. Ha nincs, akkor az átirányításkor megadott query string-et teljes mértékben felveszi a flash applet. Megoldásként tehát azt alkalmaztuk, hogy nem color=eeeeee, hanem a videó azonosítójához hasonlóan, az URL részeként kell átadni.

Példában: http://example.com/videoid/eeeeee és ezt már átirányíthatjuk az előbb megadott címre, és az applet is jól fogja lekezelni.

Szóval újfent azt mondom, hogy utálom az Adobe Flash-t!

2008. október 20., hétfő

Flash beágyazása jQuery-vel

Minden simán ment, amíg a flash applet nem akarta használni az ExternalInterface-t, ugyanis bár meghívta a JavaScript metódust, de annak visszatérési értékét már nem kapta meg. Internet Explorer alatt. Csini mi?

Három napi bugkeresés után rájöttem, hogy ha a jQuery append(), prepend() vagy html() metódusok egyikével szúrom be a generált HTML-t, akkor bizony nem működik, ha pedig innerHTML-lel, akkor igen. Az már külön hab volt korábban a tortán, hogy ha nem generálok Internet Explorer alatt az applet-nek ID-t, akkor ugyan nem kapja meg az applet ígyse-úgyse a visszatérési értéket, de legalább JScript hibát is dob.

Adobe Flash Player 10

Mostanában jelent meg az Adobe által megvásárolt Flash Player új, 10-es verziója. Szükség is volt az új verzió kiadására, mivel nemrég jelent meg a CS4, amit telepakoltak ugye új "jóságokkal", aminek sokan örültek, mert most majd húdejó csillivilli effektekkel tudják ellátni, az amúgy is lassan erőművet igénylő oldalaikat.

Értem én, hogy fejlődik a technika, újabb és újabb ötleteket gyártanak Adobe-nál is, amit szeretnének millió oldalon használva látni, és milliárd gépen futni látni. Viszont mi lesz majd azokkal a hibákkal, amiket — ugye egyrészt az új funkciókkal beletettek, és amiket — korábban benne hagytak?

Későbbiekben — eddig kettőt biztosan — fogok írni ezekről az idegesítő hibákról, amiket munkám során megtapasztaltam vele kapcsolatban. Ezek nem csak a Flash használatával, belső működésével kapcsolatos hibák lesznek majd, hanem a már elkészült applet-ek beszúrása kapcsán előtárulkozó idiótaságok is.

Szóval köszöntsük az új verziót, várjuk a hibajavításokat (9-es playerből 124 release készült, szóval lesznek)!