Martin Cohen Intype, dizajn, vývoj a somári Odoberať RSS

Inakšie Formuláre v Nette

Nájsť recept na správnu, rozširovateľnú a relatívne pohodlnú implementáciu formulárového modulu dá fakt zabrať. Pre Nette ujo Grudl síce vykročil, ale ja som to skúsil inak. Z fleku exámpl:

$document = new Container;
$document['title'] = new String;
$document['body'] = new Text;

Formulár z tohto pohľadu je definícia hodnôt a ich validácii. Ako si pozorní určite všimli, formulár nedefinuje názvy políčok, ani atribúty ako class, id, rows či cols. To všetko nechávam na šablonku. Čo nás zaujíma sú typy hodnôt ktoré očakávame: polia, reťazce, dátumy, súbory, atp. Nad týmito primitívnymi typmi následne fungujú validácie a filtre.

Hodnoty

Hodnoty sa čítajú z poľa hodnôt a je im jedno či je to POST, databáza, súbor alebo obyčajné pole. Na každom políčku je k dispozícii dvojička metód getValue a setValue, ktoré pracujú s obyčajnými poľami.

Integrácia s Nette

Klasickú formulárovú funkčnosť a integráciu do Nette zabezpečuje doplnková trieda Form. Form rieši komunikáciu s prezentérom, získavanie a distribúciu HTTP dát do políčok, nastavovanie action, či method atribútov. Form v sebe zapúzdruje inštanciu triedy Container, čiže zvonku sa javí prirodzene:

$form = new Form;
$form['document'] = new Container;
$form['document']['title'] = new String;
$form['document']['body'] = new Text;

if( $form->isSubmitted() )
{
        if( !$form->hasErrors() )
        {
                // Save data
        }
}
else
{
        $form['document']->setValue( array
        (
                'title' => 'Default title',
                'body' => 'Default body'
        ));
}

Šablony

Na zjednodušenie práce mám FormHelper, ktorý drobnosti so šablonou rieši za mňa. V žiadnom prípade sa však nesnaží definovať niečo navyše, výstupom sú holé políčka s nastavenými tými najnutnejšími atribútmi:

{widget:label $form['document']['title']}Titulok{/widget:label}
{widget:message:error $form['document']['title']}
{widget:text $form['document']['title'], 'width' => '100%'}

{widget:label $form['document']['body']}Body{/widget:label}
{widget:message:error $form['document']['body']}
{widget:text:area $form['document']['body'], 'rows' => 5, 'cols' => 40}

Až v šablone sa priraďuje políčku jeho vzhľad, spôsob rozloženia prvkov. Je to síce pracnejšie ako s ConventionalRenderer z Nette Forms, ale zato máte plnú voľnosť. FormHelper tiež zverejňuje funkcie na generovanie `name, id, style, ktoré sa dajú ľahko využiť pre písanie vlastných widgetov.

Políčka

Okrem obligátnych skalárnych, modul má aj komplikovanejšie políčka. Jedným z nich je ElasticContainer a pomôže ak UI vyžaduje pridávať vopred neurčený počet príloh, e-mailov, alebo tagov (každý v samostatnom políčku).

$form['emails'] = new ElasticContainer( function() {
        $prototype = new String;
        $prototype->validates( 'email' );
        return $prototype;
});

Základná sada políčok by mala stačiť na všetko, ak však chcete, nič vám nebráni si nadefinovať vlastnú triedu ktorá dedí od Field.

Validácie

Validácie to vie samozrejme tiež:

$form->validates( 'children', array
(
        'document/title' => array
        (
                'presence' => true,
                'length' => array( 'minimum' => 3 )
        ),

        'document/body' => array
        (
                'presence' => true
        )
));

Validácie je možné viazať na rodičovské, ale aj na detské políčka. Horný príklad je možné zapísať hneď niekoľkými spôsobmi:

// Naviazanim na 'document'; rodica 'title' a 'body' policok

$form['document']->validates( 'children', array
(
        'title' => array
        (
                'presence' => true,
                'length' => array( 'minimum' => 3 )
        ),

        'body' => array
        (
                'presence' => true
        )
));

// --- alebo naviazanim na samotne policko s pouzitim pola

$form['document']['title']->validates( array
(
        'presence' => true,
        'length' => array( 'minimum' => 3 )
));

$form['document']['body']->validates( array
(
        'presence' => true
));

// --- alebo postupnym volanim metody validates

$form['document']['title']
        ->validates( 'presence' )
        ->validates( 'length', array( 'minimum' => 3 ) );

$form['document']['body']
        ->validates( 'presence' );

Modul so sebou nesie niekoľko základných validátorov (presence, length, format, email, url, custom, children,…), a je samozrejme možné si dodefinovať vlastné. Mapa string → validátor je definovaná v triede Validator\Registry. Ak si chcete pridať vlastný, stačí vytvoriť funkciu a zaregistrovať ju:

$form['password'] = new Container;
$form['password']['first'] = new String;
$form['password']['second'] = new String;

function validatesPasswordConfirmation( $field, $options )
{
        if( $field['first']->getValue() != $field['second']->getValue() )
        {
                $field->addError( 'Passwords do not match.' );
                return false;
        }
        return true;
}

Validator\Registry::register( 'password_confirmation', 'validatesPasswordConfirmation' );

$form['password']->validates( 'password_confirmation' );

Registrovať sa dá aj lambda funkcia:

Validator\Registry::register( 'password_confirmation', function( $field, $options )
{
        if( $field['first']->getValue() != $field['second']->getValue() )
        {
                $field->addError( 'Passwords do not match.' );
                return false;
        }
        return true;
});

Ak potrebujete špeciálnu validáciu, možete použiť lambda funkciu priamo:

$form['password'] = new Container;
$form['password']['first'] = new String;
$form['password']['second'] = new String;

$form['password']->validates( function( $field )
{
        if( $field['first']->getValue() != $field['second']->getValue() )
        {
                $field->addError( 'Passwords do not match.' );
                return false;
        }
        return true;
});

Celý vtip je v tom, že si validačné pravidlá naviažete tam kde potrebujete. V tomto prípade zapúzdrujem obe heslá do jedného kontajneru a tým pádom si môžem zjednodušiť validáciu. Nerobí mi ale problém to urobiť aj bez kontajnéru.

Čo s tým?

Modul nie je zatiaľ verejný, keďže ho nemám plne nasadený a ustálený. Rád by som zistil, či sa aspoň niekomu zdá byť úžitočný. Mne to už teraz ušetrilo kopu nervov.

Ako som konečne urobil “Don’t Panic” text

A dám si to vytesať do Kindle, aby ste vedeli!

Ešte bude treba poštelovať apostrof a samozrejme kerning, ale to už sú detaily (porovnajte). Font WhoopAss je výborný základ.

Ako som si nenainštaloval Digsby

I chcel som skúsiť nový Digsby, na ktorý som kedysi zanevrel bo sa dal na temnú stránku a zavrel dvere inak podľa mňa celkom zaujímavému modelu „financovania“ cez distribuované počítanie.

Chlapci dostali dobrý nápad o tom neinformovať používateľov a tak sa z toho stal problém.

Spustil som inštaláciu a klikol Next. Kým sa však to prvé okieko prekreslilo, stihol som si prečítať čo je pod checkboxom dolu (defaultne zaškrtnutým):

Bla free browser plugin bla bla shop bla bla bla 1.800 bla bla bla,…

Inštinktívne som klikol na Cancel.

A to som chcel zrušiť kategóriu Somári, ach odpusťte.

Urobil som si wallpaper, aha

To, že to nie je vôbec žiadny originálny nápad, snáď nemusím zdôrazňovať. Ak sa vám to zdá kriklavé, smola, moje monitory to zobrazujú dobre (to neznamená, že sú lepšie ako tie vaše, alebo že sú lepšie nastavené). Poznámka pre budúceho Martinka: Ešte by to chcelo zmenšiť veľkosť štetca na steblách, aby to pôsobilo väčšie.

DIY: PHPDoc podpora pre Intype

Som lenivý, preto som si pre PHPDoc vytvoril jednoduchú bundle. S novým bundle editorom je to strašne pohodlné. Viem, že Ivo robil niečo podobné pre JavaScript. Nasledujúce sa dá samozrejme použiť kdekoľvek, aj v Intype 0.3.1 (za predpokladu, že budete upravovať súbory na disku), ale v novom 0.3.5 to bude podstatne jednoduchšie ako pre gramatiky:

Tak pre snippety:

Existujúca gramatika pre PHP nerobí rozdiel medzi obyčajným komentárom a komentárom s dokumentáciou. To sa dá jednoducho zmeniť. Potrebujeme pridať pravidlo ktoré v komentároch začínajúcich na /** nastaví scope na comment.block.doc.php.

/**
 * Nech Ctrl+P zobrazí comment.block.doc.php! Trištýýýýýýý-ri!
 */

Otvoríme PHP gramatiku a nájdeme v nej pravidlo pre comment.block. Blok vyzerá takto:

{
        begin: /\/\*/
        end: /\*\//
        name: 'comment.block.php'
        patterns: [ {
                match: /\@(a(ccess|uthor)|c(ategory|opyright)|global|l(ink|icense)|pa(ckage|ram)|return|s(ee|ince|tatic|ubpackage)|t(hrows|odo)|v(ar|ersion))\b/
                name: 'keyword.other.phpdoc.php'
        } ]
}

Urobíme kópiu pravidla nad ním. Potrebujeme upraviť begin, name a ešte z pôvodného pravidla pre komentár odmažeme patterns:

// Kópia s našimi úpravami pre PHPDoc
{
        begin: /\/\*\*/
        end: /\*\//
        name: 'comment.block.doc.php'
        patterns: [ {
                match: /\@(a(ccess|uthor)|c(ategory|opyright)|global|l(ink|icense)|pa(ckage|ram)|return|s(ee|ince|tatic|ubpackage)|t(hrows|odo)|v(ar|ersion))\b/
                name: 'keyword.other.phpdoc.php'
        } ]
}
// Pôvodný blok bez "patterns"
{
        begin: /\/\*/
        end: /\*\//
        name: 'comment.block.php'
}

Ok, čil, načo to bolo? No bolo to na to, aby sme mohli preťažiť klávesu Enter v komentári tak aby nevkladala iba nový riadok, ale aby k nemu prihodila i hviezdičku na začiatku. Čiže:

/**
 * <- keď tam tunák Enter, tak mi to vloží další riadok s hviezdičkou
 */

Predtým ako to urobíme by to chcelo novú bundle, aby sme v tom nemali bordel. Nazvime ju „PHPDoc“. Terazky vytvoríme nový snippet v tejto bundle s menom „New line in PHPDoc comment“. Do nej nastavíme obsah snippetu ako:

* $0

Čiže: nový riadok, medzera, hviezdička, medzera. Scope nastavíme na comment.block.doc.php a klávesovú skratku na Enter. Ctrl+S a môžeme to vyskúšať.

/**
 *
 *
 *
 *
 *
 * Jaké dobré, héééj.
 */

Teraz nám už len stačí vytvoriť sadu snippetov pre jednotlivé PHPDoc tagy. Ten najpeknejší je @param, inštrukcie hír:

  1. Vytvorte nový snippet v „PHPDoc“ s menom „@param“
  2. Snippet: @param ${1:type} \$${2:name} $0
  3. Scope: comment.block.doc.php
  4. Tab trigger: @param
  5. Ctrl+S

CEO Google, Eric Schmidt v interview CNBC povedal o súkromí užívateľov že: If you have something that you don't want anyone to know, maybe you shouldn't be doing it in the first place. Sebastian Anthony z DownloadSqu­ad.com to okomentoval aj za mňa.

Môj Amazon Kindle práve dostal update verzie 2.3. Optimalizovaná spotreba energie zvýši výdrž pri zapnutom pripojení k internetu skoro na dvojnásobok. Pribudla natívna podpora pre PDF. No a obraz si môžem otočiť na šírku. No že mňam.

Vedci našli ultraefektívnu metódu na detekciu pohybu tým, že previedli aktivitu buniek v mozgu muchy na matematické rovnice. – Neni možné.

Dnes som objavil Go – programovací jazyk od Google. Pôsobí zaujímavo, zase bude s čím sa hrať. Go sľubuje pohodlnosť interpretovaných jazykov a rýchlosť tých statických. Už sa teším na prvé pokusy…

Fekálvér v netbookoch

Nasrať, práve som kúpil pre mamu Lenovo Ideapad S10e s Windows XP. Tí kokoti tam dali 60 dňovú skúšobnú verziu Office, do toho zasraný Microsoft SQL Server 2005 a to všetko s debilným pridruženým fekálware, ktorý nikto nikdy nepoužije ako Windows Live, Windows Messenger a obdobný hnus.

Ani Symantec sa nezabudol na ten disk vysrať so svojím supernariť Norton Internet Security. K tomu nechýbajú ani hromádky od Lenova. Napríklad taký 250 MB Lenovo Quick Start v angličtine mame určite príde zaujímavý. Ani sa nečudujem, že sa bežní ľudia sťažujú na to, že majú pomalé počítače.

A vysvetlí mi prosím niekto načo (do riti) je dobrý odkaz na Adobe Reader na ploche?

Som zvedavý ako to ne/zvládne Google Chrome OS.

© Martin Cohen. Hnané WordPress–om. Formátované Texy–nou.