Questo how-to spiega come inserire riferimenti a file CSS e Javascript in un layout CakePHP.
CakePOWER estende le funzionalità di link di script esterni utilizzando l'helper di sistema PowHelper. Lo scopo è fornire allo sviluppatore un sistema coerente di organizzazione delle librerie e fornire un sistema di compressione dell'output completamente integrato e trasparente allo sviluppo.
Inclusione CSS di base: il seguente screencast illustra le basilari operazioni necessarie ad inserire uno (o più) files CSS in un layout CakePHP:
HtmlHelper è l'helper più comune di CakePHP ed il suo metodo css() è comunemente utilizzato per l'inclusione di file CSS nel template. PowHelper utilizza questo metodo per garantire massima compatibilità verso gli aggiornamenti di CakePHP nella generazione del codice xHTML di inclusione CSS.
JavascriptHelper è l'helper CakePHP atto alla gestione delle funzioni Javascript (e all'utilizzo della libreria prototype purtroppo…). PowHelper utilizza il metodo link() per garantire massima compatibilità verso gli aggiornamenti di CakePHP nella generazione del codice xHTML di inclusione script.
AssetHelper è un helper di terze parti 1) ed eroga funzionalità di accorpamento e compressione dei file CSS e script Javascript. Il sorgente originale è stato in parte modificato per correggere alcuni bug e garantire la compatibilità con CakePOWER. Sono richieste le librerie JsMin e TidyCSS 2).
PowHelper è l'helper core di CakePOWER e contiene i metodi utilizzati in questo articolo.
Di seguito illustro una ipotetica struttura di directory per la nostra applicazione. Lo scopo è caricare nel nostro layout tutti i files di seguito elencati.
# Layout /app/views/layout/howto.ctp # File generici di applicazione /app/webroot/css/main.css /app/webroo/js/main.js # Librerie erogate da un plugin /app/plugins/foo/vendors/css/stile_plugin.css /app/plugins/foo/vendors/js/script_plugin.js
Di seguito il sorgente del layout “howo.ctp”:
<html>
<head>
<title>PowHelper :: Caricamento librerie esterne</title>
<?php
// Carico i CSS
$pow->css('main');
$pow->css('foo::stile_plugin');
// Carico gli script
$pow->js('main');
$pow->js('foo::script_plugin');
echo $pow->css_for_layout();
?>
</head>
<body>
<h1>HowTo</h1>
<?php echo $content_for_layout; ?>
<?php echo $pow->js_for_layout(); ?>
</body>
</html>
Come si può vedere è possibile utilizzare la sintassi “plugin_name::script_name” per caricare una libreria di plugin (di un qualunque plugin!).
Gli script non vegono visualizzati nel momento in cui vengono richiesti bensì mediante un'apposita chiamata. Questo serve per ottimizzare il caricamento delle librerie.
Esiste la funzione $pow→script_for_layout() che produce il codice necessario all'inclusione di tutti gli script tuttavia una delle regole di ottimizzazione di Yahoo prevede che il codice Js sia erogato a piè di pagina e l'esempio proposto rispetta questa linea guida.
Durante lo sviluppo di un'applicazione è possibile cadere così in basso da inserire nel codice xHTML di layout e viste dei blocchi Javascript o dei blocchi di stile… CakePOWER fornisce un sistema abbastanza semplice per “raccogliere” questi blocchi e visualizzarli solamente dopo l'inclusione delle librerie javascript.
... <script type="text/javascript"> alert("Hello world!"); </script> ...
diventa:
... <?php $pow->codeBlock(); ?> <script type="text/javascript"> alert("Hello world!"); </script> <?php $pow->codeBlock(); ?> ...
Il risultato è che il blocco di codice viene letto ed inserito in una memoria temporanea che verrà utilizzata nel momento in cui si lancia il metodo $pow→scripts_for_layout() o $pow→js_for_layout().
Lo scopo è permettere allo sviluppatore di “sporcare” il codice xHTML a piacere e mantenere comunque un elevato livello di prestazioni della pagina.
NOTA: $pow→codeBlock() non fa distinzione tra Javascript e CSS.
E' possibile specificare il media di destinazione del CSS che si sta caricando utilizzando il parametro apposito:
$pow->css('css_di_stampa','print');
Il valore di default è “screen”.
Una delle più grandi maledizioni del nostro tempo è Internet Explorer. Lento, brutto, pieno di bachi di sicurezza e completamente irrispettoso degli standard CSS.
Pur apprezzando gli sforzi di chi spende molte ore nella ricerca di hack all'interno dei CSS (me compreso) mi rendo conto che la soluzione più semplice sono i commenti condizionali e così CakePOWER mette a disposizione un sistema semplicissimo per realizzarli:
// ccss : conditional css $pow->ccss( $file_path, $version = 'ie', $media = 'screen');
Questa istruzione produce un blocco di codice condizionale contenente l'istruzione di link del relativo css. La path del file rispecchia le stesse regole del metodo base e consente di includere facilmente i css di plugin CakePHP.
Il parametro version esprime il tipo di commento condizionale che si intende ottenere:
| Tabella delle opzioni $pow→ccss() | ||
|---|---|---|
| $version | Commento condizionale | Descrizione |
| ie | <!–[if IE]> | Condizionale generico Internet Explorer |
| ie5 | <!–[if IE 5]> | Intenet Explorer 5.x |
| ie50 | <!–[if IE 5.0]> | Intenet Explorer 5.0 |
| ie55 | <!–[if IE 5.5]> | Intenet Explorer 5.5 |
| ie6 | <!–[if IE 6]> | Intenet Explorer 6.x |
| ie7 | <!–[if IE 7]> | Intenet Explorer 7.x |
| up5 | <!–[if gte IE 5]> | Intenet Explorer 5.x e superiori |
| lo6 | <!–[if lt IE 6]> | Intenet Explorer inferiori al 6.x |
| lo55 | <!–[if lte IE 5.5]> | Intenet Explorer 5.5 e inferiori |
| up6 | <!–[if lt IE 6]> | Intenet Explorer 6.x e superiori |
E' possibile utilizzare un'unica chiamata a “css” e “js” per includere più files:
$pow->css('script1,script2,plugin::foo','screen'); $pow->css('print1,plugin::print','print'); $pow->js('script1,script2,plugin::script');
L'utilizzo di questa sintassi è equivalente all'utilizzo di più istruzioni di inclusione. Le due tipologie di inclusione vanno utilizzate in base alle proprie preferenze personali.
La vista viene interpretata prima del layout per cui, utilizzando i comandi precedentemente illustrati, si possono includere risorse preponendole a quelle richieste nel layout.
Esiste un metodo concepito appositamente per permettere alle viste di richiedere risorse ed accodarle alle risorse richieste nel layout estendendo in questo modo le funzionalità client dell'applicazione:
// Inclusione di css (e css condizionali con "ccss") $pow->queque('css','file_name'); $pow->queque('css','file_name', array('media'=>'screen') ); // Inclusione di script Javascript di sistema e di plugin $pow->queque('js', 'file_name,file1,plugin_name::script'); // Richiesta di plugin jQuery $pow->queque( 'jqp', 'plugin,plugin1' );
Esiste la possibilità di richiedere particolari risorse anche dai metodi di controller utilizzando, attraverso PowComponent, gli stessi metodi analizzati per l'helper:
// Inclusione di css (e css condizionali con "ccss") $this->Pow->css('file_css'); $this->Pow->css('plugin::file','print'); // Inclusione di script Javascript di sistema e di plugin $this->Pow->js('script1,plugin::script2'); // Richiesta di plugin jQuery $this->Pow->jqp('plugin_name');
E' possibile personalizzare la richiesta di risorse esterne anche dalla configurazione DAC utilizzando il sistema di configurazione discendente per applicazione, controller, azione.
// CSS JC::write('app.client.css',array( 'name' => 'css_name', 'media' => 'screen' )); // CSS in commenti condizionali JC::write('app.client.ccss',array( 'name' => 'css_name', 'version' => 'ie6', 'media' => 'screen' )); // Javascript JC::write('app.client.js',array( 'name' => 'script_name' )); // jQuery plugins JC::write('app.client.jqp',array( 'name' => 'plugin1,plugi2' ));
E' possibile utilizzare le chiavi di dettaglio per controller e azione per sovrascrivere la definizione più generale entrando nel dettaglio fino ad ogni singola azione:
JC::write('controller.users.view.client.js',array('name'=>'foo'));
Come accennato all'inizio dell'articolo CakePOWER è in grado di comprimere le librerie Javascript e CSS creando un'unica istruzione di inclusione per i CSS e un'unica istruzione di inclusione per i Javascript.
NOTA: Se vengono richiesti CSS per media diversi verrà generato un file compresso per ogni media richiesto.
NOTA: Le inclusioni condizionali ed i blocchi di codice in linea non sono soggetti a tale ottimizzazione.
Affinchè la compressione funzioni è necessario che la cartella ”/app/webroot/packed/” esista e sia scrivibile. In caso contrario la compressione può causare errori e può non funzionare.
CakePOWER è in grado di mantenere i riferimenti alle immagini utilizzate nei CSS se si presta attenzione ai seguenti accorgimenti:
/* Questa istruzione causa errori con la compressione attiva: Non possono essere utilizzati spazi bianchi tra "url(" e la path dell'immagine. */ body { background: url( immagine.png ); } /* Istruzione corretta: */ body { background: url(immagine.png); }
Quando si scrivono CSS di plugin le immagini non possono risiedere nella medesima cartella dei CSS (CakePHP non è in grado di usarle!) ma devono essere posizionate nella cartella “img” del plugin stesso. Diventa così un po' più artificioso utilizzare tali immagini:
body { background: url(../img/immagine.png); }
E' comunque valida la regola di evitare gli spazi tra “url(” e la path dell'immagine.