DOM WidgetML™ - Kutatás-fejlesztési project 2019-2020
XML alapú szerver-oldali template-ező keretrendszer PHP alatt
A kutatási project célja - motiváció
A meglévő fejlesztői környezetek és a kódletisztulásra egyre kevésbbé alkalmas CMS rendszerek kiváltása korszerű eszközökkel, amelyek alkalmasak a szabványos irányelveknek és előírásoknak megfelelő weboldalak tervezésére, készítésére a 2020-as években. Ezt a project-et elsősorban Magyarországról tervezem elindítani, hátha találok elegendő számú ambiciózus önkéntest, aki fantáziát lát ebben a koncepcióban, és szeretne részt venni egy nyílt forráskódú, és majdan ingyenesen letölthető alkalmazás kitalálásában és megvalósításában.
A DOM WidgetML™ elnevezés eredete
Elsősorban akadálymentességi szempontból kerültek besorolásra az adott weboldalon található objektumok, ezeknek az alaptipusa a widget. Már az UI Designer is a moduláris tervezési elvet követve widgetekben gondolkodik. Ennek megvalósítása a front-end és a back-end feladata az implementáció során. A feladat, hogy a widget szemtikailag is egyértelmű legyen, jók körülhatárolható, és definiálható. Például a weboldalon található menük, fejlécek, láblécek, bannerek, satöbbi mind-mind önálló szemantikai tartalommal rendelkeznek, meghatározott funkciójuk van az adott weboldalon, és önálló logikai egységet alkotnak.
A DOM WidgetML™ és az akadálymentességi direktívák
Mint azt az előbbi bekezdésben kifejtettem, egy widget egy önálló szemantikai egység. Tehát egyszerűen akadálymentesíthető, csak annyit kell megadni, egy értelmes rövid tagmondat keretén belül, hogy mi a widget rendeltetése az adott weboldalon (például ez egy háromlépéses progress tracker, ami a megrendelési folyamat éppen aktuális lépését mutatja). Természetesen mindezt a wai-aria szabványban rögzített attribútumokkal, amit a felolvasóprogram egyszerűen felolvas. Néha még ez sem kell, ha szemantikai HTML jelölőelemeket használunk a szabványban előírt módon.
Weboldal-projectek költségvetésének tervezhetőségi szempontjai a DOM WidgetML™ rendszerben
Mivel, gyakorlatilag már a tervezés is és a kivitelezés is minden lépésében a widgeteken alapul, a képlet leegyszerűsödik, mivel egy-egy adott project tényleges költségét - össz-munkaóra-igényét a widgetek száma határozza meg. Gyakorlatilag már néhány project megvalósítása után egy webfejlesztő cég már tud mondani egy becslést, hogy átlagban egy widgetnek mi a bekerülési költsége. És ezt, mint szorzót tudja használni az árajánlat-készítés során. A rendszer lényege az egységbe-zártság, újrafelhasználhatóság, ami mobilissá teszi a kivitelezés folyamatát. A gyakorlatban természetesen egy project kivitelezése során történhetnek módosítások, például a megbízó kezdeményezésére, azonban az egységbe zártságnak köszönhetően, ezek olcsón vagy akár költségmentesen elvégezhetőek. Természetesen vannak kivételek is. Például egy reklámbanner desktop-on a main-ban Wide tipusú, viszont az oldalsávabn már SkyScraper. Tehát ennek a konkrét példának az esetében nem oldható meg az áthelyezés, mindenképp szükséges a widget teljes újratervezése, már a grafikai megjelenése kapcsán is. Amúgy nem valószínű, hogy a kivitelezés során olyan módosítások kerüljenek be, amik, mondjuk a widgetek számának megduplázódásához vezetnek, mert az már akkor egy alapvetően másik project volna.
A template-ezésről általában
A template-ezés nem újkeletű dolog, már vagy 20 éves, és egyidős az XML megjelenésével. A szabványos XML template-ezőt XSLT-nek hívják, és mostmár vagy 17éve minden böngésző natívan támogatja. Ennek ellenére nem terjedt el, mivel a különféle kereső-szolgáltatók semmilyen csatolmányt nem töltenek le ami az XML file-okhoz vannak kapcsolva, tehát az XML dumpok nem igazán tudtak megfelelő pozíciókat elérni a különféle keresőkben. Viszont például, ennek kompenzálására, ugyancsak 17 éve, rendelkezésre áll például a php XSLT modulja, aminek a segitségével eleve XHTML kimenetet generál ki a kimenetre. Csak nemigazán használják. Viszont az XSLT jelenleg kiválóan alkalmas például RSS feedek kliens oldali felcsinosítására.
Az XML-XSLT kombó esetében maximálisan érvényesült a tartalom és az arculat szigorú elválasztásának elve. A Google valójában bemappolta az XML nyitólapot, és mivel csak hasznos, statikus adatot tartalmazott, egész jó pozíciót is adott neki, főleg, hogy gyorsan, és minimális hálózati erőforrás-igénnyel dolgozott, de mivel az XML specifikáció alapjáraton nem ismeri a link, hivatkozás fogalmát, és mivel ezek az XSLT-ben voltak definiálva, így a weboldal mélységi bejárását sem hajtotta végre, és még webtérkép mellékelése esetében sem végezte el az aloldalak rankolását. Nyilván ezért nem terjedt el. A működési elve szerint a weboldal felkeresésekor letöltötte a template-t, majd pedig a weboldal böngészése során a továbbiakban már csak az XML állományok letöltése volt szükséges, ami minimálisra redukálta a hálózati adatforgalmat, tehát előnyös volt a dial-up korlátozott hálózatok idején.
Az utóbbi években azonban új template-ezési koncepciók születtek, amelyek javascript alapúak, kliens oldalon futnak és a nem-statikus tartalmak dinamikus megjelenését szolgálják. Továbbra is jelentős hátránya, hogy a keresők nem dolgozzák fel, így használata statikus tartalmak megjelenítése esetében nem javasolt, nem elfogadható. Erre nyújthat megoldást a template-ezés szerver-oldalra történő átcsoportosítása.
A Linux libXML könyvtára és a szerver oldali XML feldolgozás
Minden Linux disztribúció tartalmazza a libXML könyvtárat, továbbá a php is támogatja, olyannyira, hogy az utóbbi években, már nemcsak mint lib érhető el, hanem be van fordítva a magba. Így tehát a php-vel DOM dokumentumokat tudunk feldolgozni a szabványos DOM-függvények segítségével, új dokumentumokat tudunk létrehozni, módositani, meglévőket betölteni, átalakítani. Tulajdonképpen már csak ki kell használni az adottságait a korszellemnek megfelelően.
A jelenleg érvényre jutó és a HTML adatszerkezetekre vonatkozó szabványos előírások
A HTML szabvány a 2020-as évekre az úgynevezett „flat” adatszerkezeteket preferálja. A fejlesztések a CSS vonalon mind-mind ezt az irányelvet követik. Így első lépésben bevezetésre került a „flexbox” az egydimenziós struktúrákra, majd ezt követte a „grid” bevezetése a kétdimenziós struktúrákra. És jelenleg kutatás-fejlesztési stádiumban van a „regions” display tulajdonság, aminek a segítségével egy - például a képernyő közepére helyezett - objektumot körbe tudunk folyatni például szöveggel, úgy, ahogy azt egy nyomtatott újság esetén láthatjuk, illetve tudunk majd full-reszponzív horizontális menüket csinálni, ami mindaddig egymás mellett helyezi el a menüelemeket, amíg azok kiférnek a képernyőre, majd a maradékot lecsorgatja egy oszlopban a képernyő jobb szélén. És ez csak ízelítő. A flat adatszerkezet lehetővé teszi az egyciklusos adatfeldolgozást, aminek kulcsszerepe van a kód-hatékony template-ezés szempontjából. Tulajdonképpen csak adat-formázatlan dumpokat generálunk ki. A feladat a DOM-fák mélységének csökkentése, és nem mellékesen a DOM-csomópontok számának drasztikus csökkentése. Ezeknek az irányelveknek a be-nem-tartása már most is szankcionálásra kerülnek, például a Google találati listáiban való jelentős hátrébbsorolás formájában.
A HTML és a CSS kapcsolata és az optimális CSS kódolás
Továbbra is érvényben van a tartalom és az arculat elválasztásának szigorú irányelve. Ezért törekedni kell arra, hogy a HTML kód semminemű - megjelenésre vonatkozó - kódelemet ne tartalmazzon. További változás, hogy a szabvány jelenleg folyamatban lévő módosítása eredményeképpen, megszűntetésre kerül a szóköz, mint teljes mélységi illesztésű operátor, így a jövőben - tervezetten - a >> jelölés lesz használatos, mégpedig azért, hogy a delikvens kétszer is átgondolja, hogy valójában teljes mélységi illesztésű szabályt akar-e definiálni, mivel az algoritmus a közvetlen leszámazottakra vonatkozó illeszkedést tudja, és akarja hatékonyan alkalmazni > jelöléssel. Az algoritmus továbbra is a tagName alapján tud a leghatékonyabban illeszteni, felgyűjteni, tehát törekedjünk a tagName használatára. A HTML5 szabvány számos új szemantikus jelölőelemet vezetett be, így ezek használata egyszerűbbé teszi a CSS kódolást is. Egy jól struktúrált widget esetében ezeknek a szematikus jelölőelemeknek a száma erősen korlátozott, azaz nincs a kódban 120 DIV, ami nehezíti az egyértelmű beazonosítást. Tehát például egy SECTION pontosan egy headinget tartalmaz. Az algoritmus a tagName után az attributútumokra tud második leghatékonyabban felgyüjteni. Így tehát használható az attribútum. A class-ok felgyűjtése továbbra is költséges. Tehát az sem véletlen, hogy például 15 évet kellett várni a document.getElementsByClassName DOM-függvény leimplementálására, mivel ez továbbra is lassú. Konklúzió: spóroljunk a class-okkal. Amúgy lehet használni, de ésszel. Továbbá használjuk ki a kontextuálisok nyujtotta lehetőséget az egyértelmű illesztési szabályok definiálása érdekében, például section > h3
megoldás a javasolt.
A DOM WidgetML™ alapvető jelölőelemei és attribútumai
Tekintettel arra, hogy a template XML alapon működik, így nagyon komolyan kell venni az XML dokumentumok szintaktikájára vonatkozó előírásokat. Vegyük például a következő összehasonlítóműveletekkel és logikai operátorokkal tarkított kifejezést: value>5 && value<10
Ez teljesen logikus, értelmezhető, azonban szinte minden - az XML dokumentum szintaktikájára vonatkozó - előírást megsért. Gondoljuk át, hogy miért. Így ez - ebben a formában - nem használható.
if="expr"
attribútum- Az adott elemet feltételesen jeleníti meg a DOM-fában a kifejezés logikai kiértékelésének függvényében. Amennyiben hamis, akkor a DOM-csomópont nem kerül bele a DOM-fába.
loop="elem in array"
attribútum- A véges ismétlődések kezelésére való. A bemeneti tömb elemszámának függvényében nulla vagy több példányban kerül bele a DOM-csomópont a DOM-fába. Az éppen aktuális tömbelemet mindig az elem nevű változóban találhatjuk. Ezt használhatjuk fel hivatkozásként a template-en belül.
- A
bind:
attribútumprefix - Alkalmazása:
bind:attr="expr"
. A segítségével egy konkrét attribútumnak tudunk értéket adni. Az expr kifejezés kiértékelt eredményét generálja be az adott atrribútumba. - A
param:
attribútumprefix - Alkalmazása:
param:variablename="variable"
. Csak widget tipusú elem esetében használható. Mivel a widget esetében maximálisan érvényesülnie kell az egységbe-zárás elvének, azaz csak és kizárólag a lokális névterén definiált változókat láthatja és módosíthatja, így szükségessé válik, hogy paraméterváltozókat tudjunk átadni a widget objektumnak. Ezekre a változókra a variablename névvel tudunk hivatkozni a widgeten belül. - A
<widget>
elem - A template maga. A weboldalt widgetekből építjük fel, ezek egymásba ágyazásával. A widgetnek vannak kötelező és opcionális attribútumai. Lássuk ezeket:
- A
type
widget-attribútum - A widget egyedi bezonosítására való. csak az angol abc kisbetűit tartalmazhatja, tehát nem tartalmazhat írásjeleket, ékezetes betűket, szóközt, satöbbi, viszont tartalmazhat kötőjelet. A későbbiekben ezzel az azonosítóval hivatkozunk a widgetre, továbbá a szigorú megkötés azért szükséges, mivel ezt az elvevezést a későbbiekben, php, css, javascript, sql szintaxisban, változónevekben használjuk fel. Alapértelmezésben az elnevezésre az alábbi ökölszabályt szeretném érvényesíteni: pagename-widgetname, ahol a pagename az adott weboldal, aloldal azonosító neve, majd kötőjel, majd a widget rövid neve. Például:
index-main
. Erre a fejlesztés egy későbbi részében tervezett származtatás és kódújrahasznosíthatóság miatt látom értelmét. Vegyünk egy példát:page-base
nevű widgetből származtatjuk apage-base-extended
nevű widgetet. Ekkor máris használhatóvá válik rá a CSS egyik attribútum-szűrője. Tehát vegyük a következő CSS szabályt:[data-widget|='page-base'] { ... }
, majd vegyük a következőt:[data-widget|='page-base-extended'] { ... }
. Ekkor az első CSS szabály az illeszkedik mind a base, mind pedig az extended objektumra (kódújrahasznosíthatóság, redundancia csökkentése), viszont a második CSS szabály már csak az extended objektumra vonatkozik. Ebben kigészítő CSS tulajdonságokat definiálhatunk, vagy meglévőket definiálhatunk felül az eredetiből. - A
nodeName
widget-attribútum - A widget minden esetben átkonvertálásra kerül, mégpedig a HTML szabvány szerinti Node-ra, ezt kell itt megadni. Ha nem adjuk meg, akkor void tipusu, ami azt jelenti, hogy csak a tartalmát fűzi be a DOM-fába, mégpedig azon a szinten, ahol a widgetet hivatkoztuk. Amennyiben megadjuk, akkor a továbbiakban a DOM-fában ezen a nodeName-en érhetjük el. Például <section>.
- A
hidden
widget-attribútum - Használata
hidden="true"
. Rejtőzködő widget. Nem generálja be adata-widget
attribútumot. Bizonyos elemeknél fölösleges is, például vagy nem is definiálunk rá CSS szabályt, vagy eleve a nodeName alapján hivatkozunk rá a CSS-ben. Továbbá vannak olyan esetek, amikor a widgetet kifejezetten csupán az egységbe-zárás miatt definiáljuk le, vagy csak template-ként hozzuk létre, például egy cikluson belül. - A
once
widget-attribútum - Használata
once="true"
. Csak egy példányban kerülhet a widget a dokumentumba. Kódoptimalizálás szempontjából hasznos, mivel ekkor a DOMfa építésekor csak simán befűzi a DOMelemet, anékül, hogy leklónozná azt. Tipikusan minden elem ilyen, amireid
attribútumot definiálunk. - A
<void>
elem - Nem létező elem, ami azt jelenti, hogy csak a tartalmát fűzi be a DOMfába, magát az elemet nem. Kifejezetten egy template-ező elem. Viszont definiálhatunk rá
if
-et, vagyloop
-ot. - A
<text>
elem - Használata
<text>variable</text>
. A változó kiértékelt értékét textNode-ként illeszti be a DOMfába. Csak a változó kerül be a DOMfába, a hordozó elem nem. - A
<raw>
elem - Használata
<raw>variable</raw>
. A változó kiértékelt értékét CData-ként illeszti be a DOMfába. Csak a változó kerül be a DOMfába, a hordozó elem nem. Fontos, hogy olyan kódokat, amelyek inkompatibilisek az XML szabvánnyal, csak ilyen módon lehet beilleszteni a dokumentumba. Például javascriptkódok vagy HTML kódok.
A DOM WidgetML™ motorja, a rekurzív veremalgoritmus
A forráskód a következő linken tekinthető meg: widgetml.engine.v0.4.
Mint az látható, egy vegytiszta, klasszikus rekurzív veremalgoritmusról van szó. Induláskor a <html> elemre hívjuk meg a widget-apply metódust. A rekurzió eredményeképpen egy teljes mélységi fabejárást valósít meg, miközben a template-elemek cseréjével folyamatosan építi fel a DOMfát.
A DOM WidgetML™ és a Back-end (PHP, MYSQL) kapcsolata
A widgetekhez back-end oldalon 0, 1 vagy több SQL lekérdezést lehet hozzárendelni. Az SQL select-ek lefutása után közvetlenül kerül meghívásra a widgethez hozzárendelt PHP kód. Ez a PHP kód elsődlegesen az SQL selectek kimenetének utólagos manipulálására való. Amennyiben az SQL select jól van összerakva, akkor a hozzárendelt PHP kód minimális, vagy egyáltalán nincs is. A gyakorlatban tehát a PHPkódolás kissé háttérbe szorul, viszont szépen kidomborodik az SQLtudás, tehát a back-end-es továbbra sem marad munka nélkül. Ésszerűen összerakott lekérdezésekkel így tehát rendkívül hatékony kódot lehet írni.
Az SQL selectekhez van lehetőség PHPváltozók értékének az átadására. Fontos szabály, aminek folyamatosan érvényesülnie kell, az a teljes egységbe zárás elve, így tehát a widget csak és kizárólag a saját lokális névterén definált változókat látja-láthatja. A változó hozzárendelése template szabállyal történik, két egymásba ágyazott kapcsoszárójel között, {{$variable}}
, amit a select stringjében adunk meg, itt mintaillesztéses cserével történik a változó értékének a beillesztése.
Az SQL selectek esetében követendő irányelv az 1 select - 1 tábla - 1 ciklus elve. Logikusan következik, hogy például a wordpress tipusú kicsavart, vertikális, kulcs-érték párokra redukált táblák használata elfogadhatatlan, mivel mind a felgyűjtésük, mind pedig a feldolgozásuk rendkívűl költséges, lassú. Továbbá az 1 ciklus elvéből kifolyólag, nem támogatjuk az elemek például hármasával történő wrapper-be csomagolását sem, ide vonatkozóan lásd fentebb a flat adatszerkezetre vonatkozó követelményt. ??mde, ha mégis felmerül ilyen igény, úgy megoldható a hozzárendelt PHP script segítségével, hármasával altömbökbe kell rendezni az SQL kimenetét és azt feldolgozni a widget-en belül a cikluson belül további widget definiálása segítségével, ahol a belső widget, mint template funkcionál.
Fontos tudni, hogy az SQL tábla teljes felgyűjtése megtörténik egy kétdimenziós tömbbe, ami egy teljes ciklus, továbbá ha és amennyiben PHP utófeldolgozás is történik, az is egy teljes ciklus. Jelen esetben az SQL kimenetének optimalizált (invertált) „on-the-fly” soronkénti feldolgozására nincs lehetőség, nem megoldott. Ezt mindenképp figyelembe kell venni a memóriaköltség tervezésekor.
A DOM WidgetML™ és a Front-end (CSS, JavaScript) kapcsolata
A widgethez hozzárendelhetünk CSS és Javascript kódot is. Ennél követelmény, hogy továbbra is érvényesüljön az egységbezárás elve, tehát a CSS szabályokat úgy kell ledefiniálnunk, hogy azok ne legyenek kihatással bármely más widgetre. Ezt a leghatékonyabban a CSS attribútumszűrőjével tudjuk megoldani. Amennyiben a widget nem „rejtőzködő” tipusú, akkor automatikusan begenerálásra kerül a data-widget
attribútum. Erre való illeszkedéssel és kontextuálisok segítéségével tudjuk biztosítani az egységbezárást.