Egy hét Drupal 7: JavaScript library

Most, hogy gőzerővel készülök az Integral Vision Workshop rendezvénysorozatunkra, úgy gondoltam megosztok egy pár érdekességet, gondolatot a Drupal 7 verziójáról.

Ma a library fogalmáról és pár JavaScript újdonságról lesz szó.

Számos esetben előfordul, hogy kisebb látványelemekkel, felhasználói élményjavítókkal szeretnénk feltuningolni weboldalunkat. Ilyenkor általában a netről összevadászott JavaScript csodákat kell az oldalunkba illeszteni.

Gyakran ezek a csodák nem csak egy JavaScript fájlból álltak, hanem tartalmaztak css fájlokat is. Számos esetben különböző függőségeik voltak. Volt, hogy nem jQuery függvénykönyvtárat, hanem valami mást használtak, ami miatt nehezen tudtuk az oldalainkba illeszteni azokat. Azokról a widgetekről már ne is beszéljünk, amiknél a javascript fájlokat az adott projekt oldaláról kellet beszúrnunk. A Drupal 7 megoldást kínál ezekre a problémákra, egy kis próba modul segítségével nézzük meg hogyan.

A csatolt modul négy fájlt tartalmaz: egy .info és .modul fájlt, valamint egy .js és .css fájlt. E két utóbbi lesz a JavaScript könyvtár, amit az oldalunkba fogunk illeszteni. Ez a kis megoldás semmi mást nem csinál, mint azt a táblázat sort, ami az egér mutatója alatt van, kiemeli.

Vizsgáljuk meg első körben a JavaScript fájlt:

  1. (function($){
  2. Drupal.behaviors.js_proba = {
  3. attach : function (context){
  4. $('table.row-hover tr', context).once('row-hover').hover(
  5. function (e) {
  6. $(this).addClass('row-hovered');
  7. },
  8. function (e) {
  9. $(this).removeClass('row-hovered');
  10. }
  11. );
  12. }
  13. }
  14. })(jQuery)

A kód áttekintésénél mi most elsősorban a Drupal hatoshoz képesti különbözőségekre fogunk koncentrálni. Nézzük mindjárt az elején azt a furcsa kódot, amibe az egész JavaScript fájlunkat burkoltuk:

  1. (function($){
  2. })(jQuery)

Amennyiben azt mondom, hogy ez biztosítja azt, hogy más egyéb JavaScriptes keretrendszerekkel is együtt tudjon működni a mi rendszerünk, akkor nyílván elhisszük, de azért talán örülünk egy két magyarázó szónak a miért tekintetében.

Nézzük a következő kódot:

  1. function fuggveny(szoveg) {
  2. alert(szoveg);
  3. }
  4. valtozo = fuggveny;
  5. valtozo('írd ki');

Ami itt az érdekes, hogy a valtozo nevű változóba belerakjuk a fuggveny nevű függvényt és ezáltal a változó tud úgy viselkedni mint egy függvény. Ez nem gondolom, hogy túlzott újdonságot jelentene. Az már talán érdekesebb, hogy a függvény nevét megspórolhatjuk, hisz a JavaScriptben lehet névtelen függvényeket használni.

  1. valtozo = function (szoveg) {
  2. alert(szoveg);
  3. }
  4. valtozo('írd ki');

Most már csak egy lépést kell tennünk a megértés felé:

  1. szoveg = 'egészen más';
  2. (function (szoveg) {
  3. alert(szoveg);
  4. })('írd ki')

Ebből a kódból látható, hogy már a változót is kidobtam, a névtelen függvény pusztán önmagában áll, ráadásul egyből meg is hívjuk az 'írd ki' paraméterrel. Ennek látszólag semmi értelme nincsen, ezért is tettem bele a függvényen kívülre a szoveg változót. Ugyanis, ez az egész kódhalom semmi más célt nem szolgál mint, hogy a függvényen belüli névtér segítségével pontosan meg tudjuk mondani, hogy az adott kódrészletben a szoveg nevű változó mit is jelentsen.

A fenti példában a $ nevű változónak az értékét állítjuk be úgy, hogy az mindig a jQuery objektumra mutasson. Ez azért lesz számunkra életmentő, mivel például a prototype függvénykönyvtár is a $ nevű változót használja és így könnyedén meg tudjuk majd mondani, hogy az adott kód a $ nevű változó esetén pontosan melyik könyvtárat szeretné használni.

A másik újdonság amit megfigyelhetünk, hogy a Drupal.behaviors objektumhoz már nem csak egy függvényt kell hozzáadnunk, hanem kettőt. Az egyik akkor fog meghívódni amikor elemekre eseménykezelőket akarnak akasztani (attach), a másik akkor, amikor ezeket az eseménykezelőket el akarják távolítani (detach).

Mint látható a fenti JavaScript egy row-hovered osztályt ad ahhoz a sorhoz, amelyiken éppen az egérkurzor áll, magát a formázást a CSS fájlban találhatjuk:

  1. tr.row-hovered td {
  2. background-color: #fcc;
  3. color: black;
  4. }

No, akkor nézzük a modult.

Az első részben megoldjuk, hogy valahol látható legyen a próba oldal. Ebben semmi ördöngösség nincsen, egy sima hook_menu() implementáció:

  1. function js_proba_menu() {
  2. $items = array();
  3. $items['js_proba'] = array(
  4. 'title' => 'JS Próba',
  5. 'page callback' => 'js_proba_page',
  6. 'access arguments' => array('access content'),
  7. );
  8. return $items;
  9. }

Az oldalt előállító függvény kódjának a végén viszont már látjuk az újdonságot:

  1. function js_proba_page() {
  2. // adatfeltöltés most csak próba adatokkal
  3. $oszlop = 10;
  4. $sor = 10;
  5. $data = array();
  6. $data['header'] = array();
  7. $data['rows'] = array();
  8. for ($i = 0; $i < $oszlop; $i++) {
  9. $data['header'][] = 'Oszlop_'. $i;
  10. }
  11. for ($j = 0; $j < $sor; $j++) {
  12. $row = array();
  13. for ($i = 0; $i < $oszlop; $i++) {
  14. $row[] = 'Elem_'. $j .'_'. $i;
  15. }
  16. $data['rows'][] = $row;
  17. }
  18. //adatfeltöltés vége, most jön a lényeges rész
  19. drupal_add_library('js_proba', 'row_hover');
  20. $data['attributes']['class'] = array('row-hover');
  21. return theme('table', $data);
  22. }

Túl sok szót erre az újdonságra sem érdemes pazarolni, annyit azonban mindenképpen meg kell említeni, hogy a betöltendő könyvtáron kívül az őt megvalósító modult is meg kell adni.
No, és akkor nézzük a tényleges újdonságot, a hook_library kampófüggvényt:

  1. function js_proba_library() {
  2. $libraries['row_hover'] = array(
  3. 'title' => 'JS Próba',
  4. 'website' => 'http://palocz.hu/taxonomy/term/107',
  5. 'version' => '1.0',
  6. 'js' => array(
  7. drupal_get_path('module', 'js_proba') . '/js_proba.js' => array(),
  8. ),
  9. 'css' => array(
  10. drupal_get_path('module', 'js_proba') . '/js_proba.css' => array(
  11. 'type' => 'file',
  12. 'media' => 'all',
  13. ),
  14. ),
  15. );
  16. return $libraries;
  17. }

Egy modul több könyvtárat is megvalósíthat, ezért egy tömböt kell visszaadnunk. Ebben a tömbben a kulcs a könyvtár gépi neve, az érték pedig a könyvtárat leíró adathalmaz lesz. Mi most csak egy könyvtárat valósítunk meg a row_hover-t. A könyvtárat leíró adathalmaznak meg lehet adni egy, az emberek számára is olvasható nevet (title), a projekt weboldalát (website), a verzióját, valamint a js és css fájlokat.

A js és css fájlok szintén tömbök lesznek, ahol a kulcs az adott drupal_add_js vagy drupal_add_css függvény $data eleme, míg az értéke az előbbi függvényeknek átadott $options paraméter. Mivel a js fájlt csak egyszerűen beszúrjuk, tehát semmilyen paraméter nem adunk át neki, ezért van ott az üres tömb. A css fájlhoz már adunk át némi beállítást, de talán ez is érthető.

Holnap ezt a kódot fogjuk tovább bővíteni, hogy bemutathassak pár sminkeléssel kapcsolatos újdonságot.

CsatolmányMéret
Package icon js_proba.zip1.38 KB

Hozzászólások

  1. (function($){
  2. })(jQuery)

A (jQuery) után nincs pontosvessző?

A hook_library nagyon jó, mindjárt el is kezdem használni. :) Köszi.

Igazából nem kell semelyik sor végére se rakni pontosvesszőt, mert a js-ben a sörtörés jelöli a sor végét. Próbáld ki: Kitörölgeted a pontosvesszőket, minden ugyan úgy fog működni. Megpróbálsz több soros szöveget létrehozni, és nem fog sikerülni.

Szóval a válaszom: Nincs, és nem is kell.

Igen, így igaz, mert a JS "motor" automatikusan beilleszti, ahol nincs és ő úgy gondolja, hogy kell (Javascript semicolon insertion).

Viszont a Drupal JavaScript coding standards szerint ez problémákat okozhat, ha be van kapcsolva a JS aggregálás: http://drupal.org/node/172169

"All statements should be followed by ; except for the following:
for, function, if, switch, try, while"

Nem ismerem a drupal-t, csak most szemezgetek vele, de sztem igenis kell a pontosvessző a sor végére. Próbáljatok ki egy pontosvessző mentes scriptet egy régebbi firefox-ban. Garantáltan nem fog működni. És nem hiszem hogy ezen a drupal tudna változtatni :D

Csatlakozom, tömörítés és összefűzés esetén nyelvtanilag hibás kimenetet eredményezhet a pontosvessző hiánya.

Ezenfelül saját magad, a kóder társad és az IDE-d vagy editorod munkáját könnyíted meg, ha nem szopatod azzal, hogy restségből nem teszed ki a pontosvesszőt, mert úgy sem kell.

Egy korábbi budapest.js találkozón Farkas Máté előadásának a témája pont a pontosvessző kezelése volt. Érdemes átfutni az előadásfóliákat, elég meggyőzőnek gondolom arra nézve, hogy miért ne spróroljunk azon az egy karakteren.
Fóliák: http://files.meetup.com/1603209/FARKAS%20M%E1t%E9%20%96%20Pontosvessz%26...
Videó: http://vimeo.com/15392265

Nem kötelező, de érdemes.
Én személy szerint nagyon rossznak tartom, hogy nem kötelező. Sajnos sokszor csúnya, nehezebben követhető kódot eredményez, és amúgy is problémás.
Nálam jóval okosabb emberek (pl. többek közt Douglas Crockford) mindezt jól megfogalmazták:

http://www.jslint.com/lint.html

"Semicolon

JavaScript uses a C-like syntax which requires the use of semicolons to delimit certain statements. JavaScript attempts to make those semicolons optional with a semicolon insertion mechanism. This is dangerous because it can mask errors.
Like C, JavaScript has ++ and -- and ( operators which can be prefixes or suffixes. The disambiguation is done by the semicolon.
In JavaScript, a linefeed can be whitespace or it can act as a semicolon. This replaces one ambiguity with another.
JSLint expects that every statement be followed by ; except for for, function, if, switch, try, and while. JSLint does not expect to see unnecessary semicolons or the empty statement."

(+ http://javascript.crockford.com/code.html)

Még itt van egy jó gyűjtemény:
http://blog.stannard.net.au/2011/02/10/should-you-use-semicolons-in-java...
http://lucumr.pocoo.org/2011/2/6/automatic-semicolon-insertion/

"Are Semicolons Necessary in Javascript? Despite popular belief the answer is “sometimes” and not “no”. But to save yourself time and troubles, just place them all the time. Not only will it save yourself some headaches, your code will also look more consistent. Because there will be situations where a semicolon becomes necessary to resolve ambiguities."

akkor ideírom: Meggyőztetek, igazatok van. :)

Új hozzászólás