Archive for the ‘OOP’ Category

Ügyfelünk kérése alapján el kellett készítenünk egy DropDown menüt a nyitólapjára. Most is - mint általában - a jQuery JavaScript könyvtárban kerestem a megoldást. Rövid keresgélés után megtaláltam a Superfish jQuery plugin-t, mely tökletesen megfelelőnek tűnt a célra…legalábbis első ránézésre.

A probléma a tesztelés során jelentkezett, mégpedig a szokásos IE6/IE7/FF kompatibilitási ellentétek keretében.
Mondanom sem kell, hogy a plugin FF alatt teljesen jól teljesített (ugyanúgy mint Safari-n vagy Opera-n), a Microsoft két böngészőjénél az oldal gyakorlatilag összeomlott.

A menü FF-ban:

DropDown menü FF

Az internet Explorerben elég érdeksen mutatott:

DropDown menü IE
DropDown menü IE
DropDown menü IE

Először úgy gondoltam megkeresem a megoldást, mert biztosan lokális gond van, hiszen az oldalon található bemutatókon nincs gond Internet Explorer alatt sem, de akárhogy csürtem csavartam nem akart működni. Nem csak a kinézettel volt összeakadás, hanem a funkcionalitás sem működött. IE alatt egyszerüen eltünt a DropDown menü amikor elhagytam az egérrel a legfelső meüelemet.

Néhány órányi küszködés után úgy felidegesítettem magam, hogy eldöntöttem inkább írok egy sajátot, hiszen nem egy atomfizika a DropDown menü, főleg a jQuery-t használva.

Nézzük meg, először a HTML osztályokat, az elrendezési szabályokat!

Íme egy főmeü, és a hozzá tartozó DropDown menü:

  1. <div class="menu-sor">
  2.   <div class="ddown-menu">
  3.       <div class="fomenu-ikon">
  4.         <a href="/beteg-vagyok-gyogyulni-akarok"><img src="/themes/nyitolap/images/segiteni_img.jpg" alt="" /></a>
  5.       </div>
  6.       <ul class="submenu">
  7.         <li><?php print l("Pozitív hozzáállás", "pozitiv-hozzaallas"); ?></li>
  8.         <li><?php print l("Gyógyító nevetés", "gyogyito-nevetes"); ?></li>
  9.         <li><?php print l("Függőségek", "fuggosegek"); ?></li>
  10.         <li><?php print l("Mozgásszervi betegségek", "mozgasszervi-betegsegek"); ?></li>
  11.         <li><?php print l("Orvosok, akik agykontrollt végeztek", "orvosok-akik-agykontrollt-vegeztek"); ?></li>
  12.         <li><?php print l("Kiadványok gyógyulni vágyóknak", "kiadvanyok-gyogyulni-vagyoknak"); ?></li>
  13.       </ul>
  14.   </div>
  15.   <div class="fomenu">
  16.     <p><a href="/beteg-vagyok-gyogyulni-akarok">Beteg vagyok és gyógyulni akarok</a></p>
  17.   </div>
  18.   <div class="clear"></div>
  19. </div>

Az l() fgv. használata ne tévesszen meg senkit sem, ez egy beépített Drupal fgv., síma link generálódik belőle.
Tehát a

  1. <li><?php print l("Pozitív hozzáállás", "pozitiv-hozzaallas"); ?></li>

Sorok nyugodtan lecserélhetőek síma HTML elemekre:

  1. <li><a href="/valamilyen-tartalom">Tartalom címe</a></li>

Nézzük meg a css-t, hogy ki is nézzen valahogy, nameg azért vannak benne fontos részek:

  1. <style type="text/css">
  2. ul.submenu {
  3.   position: absolute;
  4.   display: inline;
  5.   z-index: 99;
  6.   border: 5px solid #962ab2;
  7.   display: none;
  8.   margin-left: 65px;
  9.   margin-top: 0;
  10.   width: 250px;
  11.   margin-bottom: 0;
  12. }
  13. ul.submenu li {
  14.   margin: 0;
  15.   padding: 0;
  16.   width: 250px;
  17. }
  18. ul.submenu li a {
  19.   font-size: 10pt;
  20.   display: block;
  21.   color: #409066;
  22.   background: #fdf3fd;
  23.   padding: 5px 20px;
  24.   border-bottom: 1px solid #962ab2;
  25.  
  26.   margin: 0;
  27.   width: 210px;
  28.   line-height: 14pt;
  29. }
  30. ul.submenu li a:hover {
  31.   background: white;
  32.   text-decoration: none;
  33. }
  34. div.ddown-menu {
  35.   width: 70px;
  36.   float: left;
  37. }
  38. div.ddown-menu div.fomenu-ikon {
  39.   width: 70px;
  40. }
  41. div.fomenu {
  42.   width: 250px;
  43.   float: left;
  44. }
  45. div.fomenu p {
  46.   padding-left: 10px;
  47.   padding-top: 5px;
  48. }
  49. div.menu-sor {
  50.   padding-top: 10px;
  51. }
  52. div.clear {
  53.   clear: both;
  54. }
  55. </style>

Itt volt egy-két érdekesség, amit mindenképpen szeretnék megmelíteni!

Az ul.submenu css definícióban fontos elemek:

  1.   position: absolute;
  2.   display: inline;
  3.   z-index: 99;
  4.   width: 250px;

Az első három nélkül az oldal IE-ben szétcsúszik, a szélesség megadása nélkül pedig IE6-ban csak 70px lesz a lehullómenü szélessége.

Az “ul.submenu” és az “ul.submenu li a” css definíciónál is nagyon fontos a szélesség megadása, mert különben IE6-ban eltűnik a DropDown menü ha az első elemet elhagyjuk (tehát nem tudjuk kivűlasztani mondjuk a második, vagy harmadik elemet a mnüből).
Az a (link) elemnél nyiván a paddingot kivonjuk a szélességből, ezért lesz 40px-el kevesebb.

A harmadik dolog amire figyelni kell az, hogy mindenhol megadtam a margin-bottom értékét, mégpedig 0-nak. Ez is fontos, különben IE6 alatt nagy alsó margót rak minden menüelem alá.

Végül, mint IE6 mint IE7 alatt nem volt megfelelő az “ul.submenu” bal oldali margó értéke (65px), ezért teljesen kiment a DropDown menü a jobb oldalra. Erre a Conditional comments megoldással probálkoztam, vagyis:

  1. <!–[if lte IE 7]>
  2.   margin-left: -5px;
  3. <![endif]–>

De sajnos ez nem reagált semmit, úgyhogy megoldottam ezt is JavaScript-el:

  1. <script type="text/javascript">
  2. $(function() {
  3.   if ($.browser.msie) {
  4.     $('ul.submenu').css("margin-left", "-5px");
  5.   }
  6. });
  7. </script>

Nézzük meg végül a lényeget, a HTML-hez tarotó jQuery kódot, amiben kivitelezzük a DropDown menüt:

  1. <script type="text/javascript">
  2. $(function() {
  3.   var submenu_active = false;
  4.   $(".ddown-menu").hover(
  5.   function() {
  6.     $("ul.submenu", $(this)).show();
  7.     $("ul.submenu", $(this)).hover(
  8.     function() {
  9.       submenu_active = true;
  10.     },
  11.     function() {
  12.       $(this).hide();
  13.       submenu_active = false;
  14.     });
  15.   },
  16.   function() {
  17.     if (!submenu_active) {
  18.       $("ul.submenu", $(this)).hide();
  19.     }
  20.   }
  21.   );
  22. });
  23. </script>

Mit is csinál?

Az oldal betöltődése után létrehoz egy bool tipusú változót, melyben a DropDown menü aktivitását figyeljük, majd végigmegy az összes ddown-menu osztályon, és figyeli a hover esemény.
Amikor bekövetkezik, a hozzá tartozó submenu osztályt előhozza (show), majd ennek a megjelenített menünek figyeli a hover eseményét.
Ha bekövetkezik, akkor a submenu_active változó értéke igaz lesz, hiszen éppen a menüben vagyunk, ha pedig elhagyjuk, akkor elrejtjük, és a submenu_active értékét hamisra állítjuk.
Végül megnézzük, hogy a ddown-menu osztályba tartozó elemek hover eseményének végén a submenu_active igaz-e, és ha nem akkor a DropDown listát eltávolítjuk. Erre azért van szükség, mert olyan szituáció is elképzelhető, hogy valaki nem lép be a submenu-be, csak előhozza. Ha ez a sor kimaradna, akkor ilyen esetekben a sumenu nem tunne el.

Régebben írtam egy cikket a dinamikus form ellenőrzésről, és arra gondoltam leírom az eljárás modernebb változatát, azaz a hibaüzenetek nem alert ablakban jelennek meg, hanem DHTML segítségével.

Természetesen olyan kódot kell készíteni amely akárhány form-ra dinamikusan működik, tehát nem függ az input mezők számától, és az oldalon elhelyezett form-ok mennyiségétől.

A megoldást itt is a jQuery JavaScript könyvtár adja.

De mindenek előtt érdemes átnézni hogyan is kell felépíteni egy profi form-ot. Khauth György kollegám írt már erről néhány nagyon hasznos cikket:

Miután az alapelvek tanulmányozásával végeztünk készítsük el a form-ot:

  1. <style type="text/css">
  2. .form-row {
  3.   padding-bottom: 10px;
  4.   width: 290px;
  5. }
  6.  
  7. .form-row label {
  8.   float: left;
  9.   width: 100px;
  10.   padding-right: 10px;
  11. }
  12.  
  13. .form-row input {
  14.   float: left;
  15.   padding: 3px;
  16.   width: 160px;
  17. }
  18.  
  19. .clear {
  20.   clear: both;
  21. }
  22.  
  23. .form-error {
  24.   text-align: center;
  25.   color: #C52020;
  26.   border: 1px solid #DD7777;
  27.   background: #FFCCCC;
  28.   margin: 10px 0;
  29.   display: none;
  30. }
  31. </style>
  32.  
  33. <div style="margin: 0 auto; width: 300px;">
  34.   <form action="#" method="post">
  35.     <div class="form-row">
  36.       <label for="keresztnev">Keresztnév:</label><input type="text" name="keresztnev" class="kotelezo" id="keresztnev" />
  37.       <div class="clear"></div>
  38.       <div class="form-error hianyos">A keresztnév megadása kötelező!</div>
  39.     </div>
  40.    
  41.     <div class="form-row">
  42.       <label for="vezeteknev">Vezetéknév:</label><input type="text" name="vezeteknev" class="kotelezo" id="vezeteknev" />
  43.       <div class="clear"></div>
  44.       <div class="form-error hianyos">A vezetéknév megadása kötelező!</div>
  45.     </div>
  46.    
  47.     <div class="form-row">
  48.       <label for="email">Email:</label><input type="text" name="email" class="kotelezo email" id="email" />
  49.       <div class="clear"></div>
  50.       <div class="form-error hianyos">Az email cím megadása kötelező!</div>
  51.       <div class="form-error hibas">Nem valós az email cím!</div>
  52.     </div>
  53.    
  54.     <div class="form-row" style="text-align: center;">
  55.       <input type="submit" name="submit" value="Mehet" style="float: none;" />
  56.     </div>
  57.   </form>
  58. </div>

Ha megnézzük a kód a css stílus felépítésével kezdődik, ez gyakorlatilag csak az átlátható kinézetet kezeli. A lényeg természetesen a form, és a form-on belüli osztályok elhelyezkedése!

A form-ot körülöleli egy div, a JavaScript kóddal ezen belül fogunk keresni. Ennek az a lényege, hogy akárhány form-on el tudjuk sütni az eljárást, ne kelljen minden form-nál újra és újra megírni, hozzáigazítani a form-hoz.
Három adatok kérünk be: keresztnév, vezetéknév, és email cím.
Ha megfigyeljük mindegyik alatt megtalálható a hozzá tartozó hibaüzenet is. A hibaüzenetek mindegyike a form-error osztályba van sorolva, így a kinézetük egységesen definiálható, és láthatóságuk egységesen kezelhető.
A hibaüzenetek nem csak a form-error osztályba tartoznak, hanem a hiba típusába is. Ezesetben mind a három input mezőhöz tartozik egy hianyos osztály, ami akkor jelenik meg ha üresen hagytuk, az email címhez pedig egy hibas osztály, ami akkor jelenik meg ha az email cím nem valós.

Nézzük meg a hozzá tartozó JavaScript kódot, melyben dinamikusan elleőrizzük az input mezők kitöltöttségét, és az email cím helyességét, valósságát is:

  1. <script type="text/javascript">
  2.  
  3. $(function() {
  4.   $('form').submit(function() {
  5.     var mehet       = true;
  6.     var first_error = true;
  7.     var error_obj   = null;
  8.     $('div.form-error', $(this).parent()).each(function() {
  9.       $(this).hide();
  10.     });
  11.     $('input.kotelezo', $(this).parent()).each(function() {
  12.       if ($(this).val() == '') {
  13.         mehet = false;
  14.         if (first_error) {
  15.           first_error = false;
  16.           error_obj   = $(this);
  17.         }
  18.         $('div.hianyos', $(this).parent()).show();
  19.       }
  20.     });
  21.  
  22.     var email   = $('input.email', $(this).parent()).val();
  23.     var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
  24.     if (!filter.test(email)) {
  25.       mehet = false;
  26.       if (first_error) {
  27.         first_error = false;
  28.         error_obj   = $(this);
  29.       }
  30.       $('div.hibas', $(this).parent()).show();
  31.     }
  32.  
  33.     if (mehet) {
  34.       return true;
  35.     } else {
  36.       location = '#' + error_obj.attr('id');
  37.       return false;
  38.     }
  39.   });
  40. });
  41.  
  42. </script>

A dinamikus form ellenőrzésről írt cikkemhez képes van néhány eltérés, most ezekre térnék ki elsősorban.
Az első, hogy nem csak a mehet változót deklaráljuk, hanem a first_error bool típusút, és az error_obj html objektum típusút is. Ezek azt a célt szolgálják, hogy hibás kitöltés esetén le tudjuk tárolni melyik hiba volt az első a sorban, és automtaikusan oda ugorjunk az oldalon.
Utána láthatjuk a

  1. $('div.form-error', $(this).parent()).each(function() {
  2.       $(this).hide();
  3.     });

részt, ami arra való, ha már egyszer hibásan töltöttük ki a form-ot, akkor eltűntetjük az összes hibaüzenetet, különben ottmaradhat második hibás kitöltés esetén olyan üzenet is, ami már nem aktuális.

Ezután ellenőrizzük a kitöltöttséget, tehát végigmegyünk a kötelező input mezőkön. Ha valameny nincs kitöltve akkor a szülö objektumának hianyos osztályát megjelenítjük. Végül ellenőrizzük az email cím helyességét, tehát hogy illeszkedik-e a szabványra, és ha nem a szülő html objektumának hibas osztályát megjelenítjük.

Végül ha nem találtunk hibát tobábbengedjük a submit eseményt, ha találtunk akkor az első hibás mezőhöz ugrunk.

A Drupal 5-ben van egy hiba amiről a programozók sokszor elfelejtkeznek.

A $node objektumnak van egy path attribútuma:

  1. <?php
  2. $node->path;
  3. ?>

Ez a node-hoz tartozó url alias, tehát a megadott elérési címet tartalmazza. Sokszor használjuk különböző tartalmak dinamikus gyűjtőoldalán, ezért fontos tisztában lennünk ezzel a hibával.

A probléma az, hogy amikor admin-ként vagyunk bejelentkezve a path érték megfelelő, ám ha nem akkor üres, így minden link a kezdőoldalra mutat. Ez annyit takar, hogy nem lehet elérni a kívánt bejegyzéseket, és ha nem elég körültekintő a tesztelés, akkor fel sem tűnik, mivel a session-be bentmaradunk mint bejelentkezett admin-ok, így nem is érzékeljük a hibát.

A megoldás egy egyszerű beépített Drupal fgv használata

  1. <?php
  2. $node->path = drupal_get_path_alias("node/$node->nid");
  3. ?>

Ez egy nagyon egyszerű megoldás, mégis ha nem vagyunk vele tisztába komoly gondot okozhat a weboldalon, de hangsúlyozom: megfelelő tesztelés esetén ki kell hogy derüljön még az élesítés előtt.

Olyan oldalaknál ahol egy bizonyos node tipushoz sok beviteli mező tartozik elvárás lehet, hogy ne kelljen minden módosításnál lemenni a lap aljára.

A logikus megoldás az, hogy az ENTER gomb lenyomásával jelzi a felhasználó, hogy végzett a tartalom módosításával, feltöltésével.

Az eseményt a jQuery JavaScript könyvtárral könnyen meg lehet oldalni, utána pedig már csak egy nagyon egyszerű Drupal modult kell hozzá írni, és minden olyan weblapon alkalmazni lehet ahol szükség van rá.

Íme a JavaScript fájl amint majd hozzárendelünk az oldalhoz:

  1. var writing   = false;
  2. var node_edit = false;
  3.  
  4. $(document).ready(function() {
  5.  
  6.   if ($('#node-form').length) {
  7.     node_edit = true;
  8.   }
  9.  
  10.   if (node_edit) {
  11.     $('.form-textarea', $('#node-form').parent()).focus(function() {
  12.       writing = true;
  13.     });
  14.     $('.form-textarea', $('#node-form').parent()).blur(function() {
  15.       writing = false;
  16.     });
  17.   }
  18. });
  19.  
  20. $(document).keypress(function(event) {
  21.   if (event.keyCode == 13 && !writing && node_edit) {
  22.  
  23.     if (confirm_submit()) {
  24.       $('#edit-submit', $('#node-form').parent()).click();
  25.     }
  26.   }
  27. });
  28.  
  29. function confirm_submit() {
  30.   var agree = confirm("Valóban menti a tartalom változásait?");
  31.   if (agree) {
  32.     return true ;
  33.   } else {
  34.     return false ;
  35.   }
  36. }

Menjünk végig a kódon, mi miért van!

Először is a writing változó, a node_edit változó és az oldal betöltésekor lefutó fgv-ek, vagyis a $(document).ready(function()).
A writing változó azért fontos, mert az ENTER lenyomása esetén nem feltétlenül a tartalom szerkesztésének befejeztét jelzi a felhasználó, hanem esetlegesen éppen egy olyan szöveget gépel be, amiben van sortörés. Az pedig elég nagy gond lenne, ha nem lehetne több sort bevinni egy node-ba :-)
Ezért aztán létrehozzuk a writing bool tipusú változót alapértelmezetten hamisra állítva, és figyelve az eseményeket változtatjuk, hogy éppen gépelés történik vagy sem.
Az odlal betöltődésekor a form-textarea osztályokhoz hozzárendeljük a focus() és blur() fgv-eket.
Amikor egy textarea-ba bekattint (focus) a felhasználó a writing változó értéke igazra változik, amikor elhagyja (blur) hamisat vesz fesz vel.
A node_edit bool tipusú változót azért hozzuk létre, mert a későbbiekben a hook_form_alter()-t fogjuk használni a js beépítésére, ez azonban nem csak a node-ok szerkesztésénél fut le, hanem például a felhasználók kezelési felületén is. Ezért megvizsgáljuk, hogy a node-form létezik-e, és csak akkor futtatjuk a kódót ha igen.

A billentyű lenyomása, a keypress(function).
Ezt magához az oldalhoz ($(document)) kell hozzárendelni, hiszen nem valamely beviteli mezőt figyeljük.
A fgv paramétere az event változó, ez tartalmazza a billentyűlenyomás tulajdonságait.
A keyCode a lenyomott billentyű ID-ját tartalmazza ami egy egész. Az ENTER gomb kulcsa a 13-as szám.
Emiatt a feltételben megvizsgáljuk, hogy a 13-as kódszámmal rendelkező billentyű lett-e lenyomva (ENTER), és hogy éppen folyik-e a gépelés (writing változó).
Ha a feltételnek megfelelőek az értékek és a felhasználó megerősítette (confirm_submit), hogy befelyezte a szerkesztést akkor végrehajtjuk a node mentését.

Lehetséges, hogy a

  1. $('#edit-submit', $('#node-form').parent()).click();

sor egy kis magyarázatra szorul.

Az node-form a form id attributuma.
Gondolhatnánk a legegyszerűbb meghívni a submit eseményt a submit() fgv-el. A probléma az, hogy a node szerkesztési felületén három submit gomb van: beküldés, előnézet, törlés. Emiatt a submit esemény nem egyértelmű, hiszen mind a három gomb, ugyanannak a form-nak a submit gombjai, és mindegyik mást csinál. Emiatt nem történik semmi.
A következő gondolat az, hogy oldajuk meg a problémát az edit-submit id-jú gomb click esemény meghívásával.
Ezzel a gond az, hogy a Drupal beépített form-jainak mind ez az azonosítója. Így pl ha engedélyezve van a search modul akkor annak a submit gombaja is ugyanezzel az id-val rendelkezik, tehát könnyen előfordulhat, hogy az enter lenyomása mondjuk keresést eredményez, nem pedig a tartalom elmentését.
Ezért magában a form-ban kell megkeresnünk a megfelelő gombot, viszont form-on belül nem lehet html objektumot keresni, ezért a form-ot körülölelő div-ben kell megtennünk.

Az utolső fgv. a megerősítés, vagyis rákérdez a felhasználótól, hogy valóban mentsük-e a tartalmat.

Ez a jQuery megvalósítás működik, mostmár csak be kell építeni a site-ba.

Mivel ennek a JavaScript-nek csak és kizárólag a node szerkeztési felületén kell megjelnnie, így a hook_form_alter()-t a legérdemesebb használni.

A modulunk, tehát az .info fájlon kívül ennyi:

  1. <?php
  2. /**
  3.  * hook_form_alter().
  4.  */
  5. function enter_node_submit_form_alter($form_id, &$form) {
  6.   drupal_add_js(drupal_get_path('module', 'enter_node_submit') .'/enter_node_submit.js');
  7. }
  8. ?>

A modul letölthető innen:
enter_node_submit.module

Egyik ügyfelünknél felmerült az igény, hogy egy form kitöltése után automatikusan küldjünk ki egy email-t csatolmánnyal együtt.

A probléma megoldására a régebbről ismert HtmlMimeMail PHP osztályt használtam.

Nagyon jól megszerkesztett osztály úgyhogy nagyon könnyű használni, ám Drupal alatt mégsem lehetett alkalmazni a leírásban olvastakat.

Az első problémát az jelentette, hogy nem lehetett az osztályt beilleszteni, illetve objektumot készíteni belőle. Egyszerűen kifagyott tőle a Drupal és fehér képernyő jelent meg. Szerencsére van olyan verziója is, amitől nem jelentkezik ez a probléma.

Innen telölthető zip-el tömörítve (20 KB): HtmlMimeMail Drupal.

Miután ez megoldódott nagyjából a HtmlMimeMail oldalán található leírásokat kellett alkalmazni néhány dolgot kivéve.

Először egy ellenőrzés arról, hogy nem-e létezik már az osztály:

  1.       if (!class_exists('htmlMimeMail') && !class_exists('Mail_mimePart')) {
  2.         require_once(dirname(__FILE__)."/htmlmimemail/htmlMimeMail.php");
  3.       }

Utána a szokásos eljárást követve létrehozzuk az objektumot, és beállítjuk a karakterkódolást is, hiszen a Drupal UTF-8 -at használ

  1.       $mail = new htmlMimeMail();
  2.       $mail->setTextCharset('UTF-8');
  3.       $mail->setHtmlCharset('UTF-8');
  4.       $mail->setHeadCharset('UTF-8');

A setFrom() setSubject() és a setText() vagy setHTML() beállítása ugynúgy történik mint általában:

  1.       $mail->setFrom($_POST["offer_name"] . " <" . $_POST["offer_email"] . ">");
  2.       $mail->setSubject('Ezt nézd meg');
  3.       $mail->setText($uzenet);   // Ha text levelt kuldunk
  4.       $mail->setHTML($uzenet); // Ha HTML levelet kuldunk

Na ezután jöhetett a csatolmány hozzárendelése! A HtmlMimeMail weboldalán a következőt olvashatjuk:

  1. $mail->addAttachment(new fileAttachment('example.zip', 'application/zip', new Base64Encoding()));

Ez sajnos hibát generál, mivel nem létezik a FileAttachement osztály, így nincs miből objektumot létrehozni.
A megoldást a következő eljárás jelentette:

  1.       $filename = $node->field_nyitolap_top10_latvany[0]['filepath'];
  2.       $attachment = '';
  3.  
  4.       if ($fp = fopen($filename, 'rb')) {
  5.         while (!feof($fp)) {
  6.           $attachment .= fread($fp, filesize($filename));
  7.         }
  8.       }
  9.       fclose($fp);

Így a csatolmány egyből bekerült a levélbe!

Végül be kell állítani a fejlécet és elküldeni:

  1.       $mail->setHeader('Date',date('D, d M y H:i:s 0'));
  2.       $mail->setHeader('X-Mailer','Drupal');
  3.       $mail->send(array('<' . $_POST["offered_email_$i"] . '>'),'mail');

És tökéletesen működik a csatolmány elküldése Drupal alatt.

Sokszor felmerül a kérdés, hogy lehet a form mezőinek kitöltöttségét egyszerűen és újrahasznosíthatóan megírni.

Erre egy nagyon jó megoldást ad a jQuery JavaScript könyvtár.
A lényeg az, hogy egy kód megírásával lehessen ellenőrizni az oldalon található összes form kötelező mezőinek kitöltöttségét, függetlenül attól, hogy mely formnak hány kötelező mezője van.

Ehez fontos, hogy a form-okat a megfelőle stratégia szerint építsük fel…a lényeg a helyes osztályok használata. Ha a megfelelő input mezőket a megfelelő osztályokba soroljuk, akkor a megoldás néhány sor JS-el megoldható, és el lehet sütni akármikor a jövőben is.

Néhány napja az egyik ügyfelünknek kellett elkészítenem egy site részletet, ahol az oldalak összességét tekintve, kb. 20 formot kellett elhelyezni, namost ez sok, és ha mindet a szabványos JS módszerekkel próbáltam volna ellenőrizni (a mezőket ID alapján lekérdezem és ellenőrzöm, hogy ki van-e töltve), akkor sok kódot kellett volna írni, valamint a hibalehetőség is nagy. Ahol nagy a hibalehetőség azt minimum tízszer annyi idő tesztelni, mint egy megfelően elkészített form ellenőrzést.

Vegyünk egy egyszerű példát egy négy mezőböl álló form-ra, melynek három kötelező mezője, amiből az egyik email, tehát az email cím valósságát is ellenőrizni kell.

A form a következő képp néz ki:

  1. <div class="form">
  2.  
  3. Ide jöhet a form bevezető szövege
  4. <form class="feliratkozo-form" action="#" method="post">
  5. <div style="display: block; width: 70%; margin: 0 auto;">
  6. <div class="form-row" style="clear: left;">
  7.         <label style="float: left; clear: left;" for="lastname">Vezetéknév</label>
  8. <input id="lastname" class="register-input-narrow kotelezo" name="mssys_lastname" type="text" /></div>
  9. <div class="form-row" style="clear: left;">
  10.         <label style="float: left; clear: left;" for="firstname">Keresztnév</label>
  11. <input id="firstname" class="register-input-narrow kotelezo" name="mssys_firstname" type="text" /></div>
  12. <div class="form-row" style="clear: left;">
  13.         <label style="float: left; clear: left;" for="email">Email cím</label>
  14. <input id="email" class="register-input-narrow kotelezo email" name="email" type="text" /></div>
  15. <div class="form-row" style="clear: left;">
  16.         <label style="float: left; clear: left;" for="honnan">Honnan hallottál rólunk?</label>
  17. <input id="honnan" class="register-input-narrow" name="honnan" type="text" /></div>
  18. </div>
  19. <input class="desc" type="submit" value="Kérem a tanulmányt!" />
  20.   </form>
  21.  
  22. Ide is jöhet valamilyen szöveg, mondjuk arról, hogy nem adjuk az email címed másnak
  23. </div>

Menjünk szépen végig a kódon mikre kell figyelni, mik a lényeges részletek!
Nyilván nem a CSS-en van a lényeg, az csak az elrendezés miatt van.
Ha megnézzük az egész form egy div-be helyezkedik el, és osztályba van sorolva. Ez nem véletlen. A későbbiekben ezen div adott osztályain fogunk végigmenni, és ellenőrizni a kitöltöttség helyességét. Azért nem a form-on, mert a mezők a div-hez tartoznak, nem pedig a form-hoz, tehát a formon belül nem tudunk osztályokat keresni.
A felépítést tekintve megfigyelhetjük, hogy a mezőknek van id paraméterük és egy label követi. Ez fontos és sokan elfelejtik. Egy modert formban a mező címére kattintva is a mező válik aktívvá, ez különösen pl. a checkbox-oknál igaz. Gondoljunk bele, milyen rosz megoldás ha van egy checkbox mellette egy sor szöveg, és csak akkor válik kiválaszottá a checkbox ha a kis négyzetébe kattintuk, ha a szövegre akkor nem történik semmi. Erre teljesen tökéletes a mező id és a label for párosítás.
A három kötelező mező a Vezetéknév, Keresztnév, és Email cím. Ezeket a kotelezo osztályba soroljuk. Megfigyelhetjük az Email cím mellett ott van az email oszály tag is. Itt megjegyezném, hogy ha egy HTML elemet szóközökkel elválasztva osztályokba sorolunk az azt jeleni, hogy az összes adott osztályba tartozik. Tehát például az Email cím az egyszerre tartozik a register-input-narrow, a kotelezo és az email osztályokba.

Nézzük meg a hozzá tartozó jQuery kódot:

  1. <script type="text/javascript">
  2. $(document).ready(function() {
  3.   $('.feliratkozo-form').submit(function() {
  4.     var mehet = true;
  5.     $('input.kotelezo', $(this).parent()).each(function() {
  6.       if ($(this).val() == '') {
  7.         mehet = false;
  8.       }
  9.     });
  10.    
  11.     if (mehet) {
  12.       var x = $('input.email', $(this).parent()).val();
  13.       var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
  14.       if (!filter.test(x)) {
  15.         alert('Nem valós az e-mail cím');
  16.         return false;
  17.       }
  18.       return true;
  19.     } else {
  20.       alert('Minden mező kitöltése kötelező!') ;
  21.       return false;
  22.     }
  23.   });
  24. });
  25. </script>

Láthatjuk, hogy az oldal betoltődésekor fut le a kód. Végigmegyünk az összes feliratkozo-form osztályon és lekezeljük a submit eseményét. Ebbe az osztályba soroltuk be az oldalon talalhátaó összes ellenőrizendő form-ot.
Eztán végigmegyünk az összes olyan input mezőn amit a kotelezo osztalyba soroltunk, és a form szülő objektumába tartozik. Ez az objektum az a div amibe elhelyzetük a form-ot.
Ha valami nincs kitöltve akkor a mehet változót hamis értékre állítjuk.

Ha a mehet változó értéke nem igaz, akkor alert ablakban informáljuk a felhasználót a hiba okáról és hamis értékkel térünk vissza a ciklusból, tehát nem fog lefutni a submit esemény. Ha igaz akkor folytatjuk a további szükséges ellenörzéseket. ez jelen esetben az email cím helyessége.

Miután minden szükséges ellenőrzést megtettünk az adatok függvényében fut le a submit esemény, az oldalon elhelyezett akárhány form esetén.

Előnye hogy pár sor, nem függ a form mezőinek számától és lényegesen lerövidül a tesztelés időtartalma. Az osztályokkal való mezőellenőrzés ha működik egy form-ra akkor működik a többire is, ha nem működik akkor semmelyiknél se fog.

Természetesen olyan ellenőrzésekre is szükség lehet mint például hogy egy legördülő select-ből mindenképpen válasszon az felhasználó egyet, de azt is hasonlóképpen bele lehet vinni a kódba.

Drupal 6 Internet Corporation theme: Letöltés / Download

Mivel még nem sok Drupal 6 smink készült el és nem akartam a Drupal 6 alapértelmezett sminkjét felrakni az oldalamra úgy döntöttem megpróbálok egy Drupal 5-öst átírni, hogy működjön.

Az Internet Corporation theme mellett döntöttem.

Szerencsére felkerült a Drupal oldalára egy dokumentáció a Drupal 6 sminkeléséről
Ez volt a kiinduló alapom, hogy mégis mért nem müködnek a Drupal 5-ös sminkek a 6-os verzió alatt.

Bevallom őszintén nagyobb problémára gondoltam mint amekkora ténylegesen volt. Az egész megvalósítás nem vett igénybe fél óránál többet, persze miután elolvastam a Drupal oldalán a dokumentációt.

Lényeges különbség, hogy kell egy info fájl, mint a moduloknál. Ebbe kell egy a sminkkel kapcsolatos dolgokat deffiniálni. Milyen css-ek tartoznak hozzá, milyen JavaScript-eket töltösön be automatikusan, milyen régiói vannak stb.

Az Internet_Corporation.info így néz ki, mivel nem igényel különösebb js fájlokat, és a template.php fájlba a régiók definiálva vannak, bár itt is megtehettem volna.

Internet_Corporation.info:

; $Id$
  1. name = Internet Corporation
  2. description = Implements of Internet_Corporation theme for Druapl 6
  3. version = 1.0
  4. core = 6.x
  5. engine = phptemplate
  6. stylesheets[all][] = style.css

Innenstől fogva már nagyjából működött is, persze a blokkok nem jelentek meg, mert megválzotak. Az eredeti Internet Corporation smink nem volt valid HTML úgyhogy eltávolítottam belőle a primary_links-re vontakozó hibát.
A gond az volt, hogy az eredeti Drupal 5-ös sminkbe ez szerepelt:

  1. <ul id="menu">
  2. <?php if (isset($primary_links)) { ?><?php print theme('links', $primary_links, array()) ?><?php } ?>
  3. </ul>

A links_theme ul - li elemeket generál, ezért nem lehet körülvenni egy ul elemmel. Így hát a Drupal 6-os sminkben kicseréltem div-re:

  1. <div id="menu">
  2. <?php if (isset($primary_links)) { ?><?php print theme('links', $primary_links, array()) ?><?php } ?>
  3. </div>

Egy lényeges különség az, hogy mostmár nem a $slidebar_left és $slidebar_right változókkal tudjuk elérni a bal- és jobboldali régiókat hanem a $left és $right változókkal. Így a Drupal 5-ös Internet Corporation theme-ben szereplő

  1. <?php if ($sidebar_left) { ?>
  2.   <div id="left">
  3.     <?php print $sidebar_left ?>      
  4.  </div>
  5. <?php } ?>

kódrészletet ki kellett cserélni Drupal 6 alatt a következőre:

  1. <?php if (!empty($left)) { ?>
  2.   <div id="left">
  3.     <?php print $left ?>      
  4.  </div>
  5. <?php } ?>

Ezután a Drupal 5-ös page.tpl.php-ban szereplö

  1. <?php if ($mission) { ?><div class="mission"><?php print $mission ?></div><?php } ?>

sort ki kellett cserelni a

  1. <?php if (!empty($mission)) { ?><div class="mission"><?php print $mission ?></div><?php } ?>

sorra. Így mér ez is működött Drupal 6 alatt.

Végül eltérés a $footer_message változó hiánya. Ez is megváltozott és a $footer vette át a helyet.

Így a Druapl 5-ös kódban szereplő

  1. <div id="col1"><?php print $footer_message ?></div>

sort egyszerűen kicsereltem a

  1. <div id="col1"><?php print $footer ?></div>

sorra, és innenstől kezdve az Internet Corporation theme, ugyanúgy működött Drupal 6 alatt, mintha Drupal 5-öt használnánk.