Řešení všech Javascriptů, CSSek, obrázků a dalších výmyslů
- Filip Procházka
- Moderator | 4668
Odkud co
Prvně si stáhneme a inicializujeme Kdyby sandbox ;)
$ git clone git://github.com/Kdyby/sandbox.git
$ ./prepare # nastaví app/log a app/temp zapisovatelné a spustí script vendor/vendors
Nyní by vám po přechodu do složky www/
měl naběhnout nový
sandbox. Pokud nenaběhl, můžete mi vynadat a nebo lépe reportovat
chybu ;)
Jak to teďka vypadá
V @layout.latte
se pár věcí změnilo, má novou hlavičku
<!DOCTYPE html>
<html>
{head title => "Nette Application Skeleton"}
<meta name="description" content="Nette Framework web application skeleton">
{stylesheet 'css/screen.css', media => "screen,projection,tv"}
{stylesheet 'css/print.css', media => "print"}
{javascript 'http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js',
'js/netteForms.js'}
<link rel="shortcut icon" href="{$basePath}/favicon.ico" type="image/x-icon">
{block head}{/block}
{/head}
Ničeho se nebojte, na začátek cest v makrech stylesheet a javascript
budou automaticky doplněny proměnné $basePath
, stačí
neuvádět lomítko na začátku.
Makro stylesheet
Je určené pouze na csska, když neuvedete absolutní cestu ke stylu, bude
se brát %wwwDir%
. Protože makro předává data dále do mnou
ohnutého Asseticu,
obsahuje i podporu balíčků, více zde.
Pokud ve vlastním balíčku budete mít nějaké statické soubory,
/MyPackage
/Resources
public/
css/
foo.css
js/
bar.js
je možné na ně odkazovat takto
{stylesheet '@MyPackage/public/css/foo.css'}
{javascript '@MyPackage/public/js/bar.js'}
Kouzlo je v tom, že makro se zkompiluje tak, aby se nezávisle na jakýchkoliv podmínkách přidaly soubory do manageru, který se jmenuje FormulaeManager. Tomuto manageru budou soubory předem připraveny a analyzovány, takže první vykreslení stránky může trvat krapet déle. Potom se vždy, když se začne vykreslovat šablona, soubory do něj připojí.
Má to jedno omezení, co nejméně v těchto makrech používejte proměnné. Proměnné se totiž zpracovávají runtime a já potřebuji už při compiletime vědět přesně, jaké soubory budou použity.
Makro podporuje i filtry (less, sass, …), ale ty jsem zatím nepotřeboval, takže ještě nejsou implementované, Assetic pro ně má ale podporu a bude možné psát vlastní filtry.
Makro javascript
Funguje úplně stejně, jenom má méně parametrů a je jenom pro javascripty
Makro head
Tady jsem se krapet nechal unést ;) Vytvořil jsem novou komponentu (promiň Honzo) HeaderControl
Komponenta se registruje do presenteru
protected function createComponentHead()
{
return new Kdyby\Components\Header\HeaderControl(
$this->context->application,
$this->context->assetic_formulaeManager,
$this->context->httpRequest
);
}
Její api je velice jednoduché. Určitě bude rozšiřováno, ale měnit už
snad nic nebudu. Je to jenom obálka na tagy a vytahuje z
FormulaeManager
u cesty k assetům.
Mezi makry {head}
a {/head}
je možné používat
normálně Latte, ale netestoval jsem úplně všechno, takže na něčem to
může padat. Prostě to nehackujte ;)
Komponenta si při vykreslení sáhne na FormulaeManager
, zeptá
se ho na cesty, které byly nasbírány z maker {stylesheet}
a
{javascript}
a ty pak vykreslí do hlavičky spolu
s vašimi tagy.
Jak je to s těmi komponentami?
Stačí kdekoliv v její šabloně napsat makro {stylesheet}
,
nebo {javascript}
a Kdyby se postará, aby se soubory objevily tam
kde mají, v hlavičce ;)
Má to jednu podmínku, musí se šabloně předat do proměnné
$_fm
instance FormulaeManager
z DI Containeru a taky
musí mít registrována moje makra. Ale to s Kdyby není vůbec žádný
problém, protože samo při kompilování Containeru najde komponenty a
připojí k nim TemplateConfigurator
Takže si ty komponenty shrneme
- Podědím
Kdyby\Application\UI\Control
, který kamarádí sTemplateConfigurator
em TemplateConfigurator
předám, nebo dám komponentě v DIC Containeru tag „component“ a Kdyby jí to nastaví samo. Zde bych poprosil zatahat za nitky, kdo můžete zde.
$container->addDefinition('cms_rbacForm')
->setClass('Kdyby\Components\AccessControl\RbacForm', array('@doctrine'))
->addTag('component');
TemplateConfigurator
mi nastaví makra a proměnnou_fm
Nevýhody
Není možné v rozumné době zjistit, jaké komponenty budou načteny do
stránky a jaké se vykreslí, prostě to nejde. Vykreslení šablony se tedy
funkcemi ob_start()
a ob_get_clean()
násilně
zdržuje, dokud nebude celá k dispozici do momentu, kdy už další komponenty
nepřibudou a pak teprve vykreslí hlavičku a za ní tělo šablony. Mírně se
tím oddálí první znak odeslaný uživateli a malinko to zvedne využití
paměti. Vím, že sám jsem to kritizoval (zdravím Venne :P), ale jinak to
asi nejde.
Pokud na #nettebc vymyslíme něco lepšího, určitě to vylepším ;)
PS: Psal jsem to tak trochu narychlo, kdyby něco nebylo jasné, rád doplním
Editoval HosipLan (10. 1. 2012 8:54)
- Felix
- Nette Core | 1245
Hezke reseni urcite vyzkousim. Jak si psal, hodnekrat jsem to resil. Tedka
naposled jsem to vyresil tak, ze mam komponentu HeadLoader
, ktera
ze seznamu komponent zkousi volat fci napriklad usedCss resp
usedJs, ktery vracej pole souboru :) neco jako
function usedCss() {
return array('%wwwDir%/css/theme.css', '%dataDir%/css/datepicker/example2.css');
}
PS: Slo by to teoreticky i pres anotace, ne?
/** @UsedCss */
public $usedCss = array('%wwwDir%/css/theme.css', '%dataDir%/css/datepicker/example2.css');
Jak je to s rychlosti? Kdyz uz to nette jednou nacte, tak by to melo bejt v pohode ne?
Editoval Felix (9. 1. 2012 18:23)
- Ani
- Člen | 226
Ahoj,
vypadá to pěkně. U sebe jsem si zavedl podobné makro javascript, je to obdoba capture, jen ho používám trochu jinak možná by se ti ta syntaxe líbila. Hlavní výhoda je v kombinaci s n variantou a tim pádem zvýrazňování syntaxe…
<script n:javascript>
alert('kokos');
</script>
případně i, ale to mám zatím rozdělané
přidá soubor
<script n:javascript="file" src="kokos.js"></script>
Editoval Ani (10. 1. 2012 15:48)
- Filip Procházka
- Moderator | 4668
To se mi líbí. N-makra jsem chtěl také přidávat, ale prioritou bylo, aby to fungovalo, hračičky se můžou dodělat kdykoliv :)
- Filip Procházka
- Moderator | 4668
Implementována podpora inline scriptů v e384d94e2ae, pro vyzkoušení nezapomenout aktualizovat sandbox
sandbox $ git pull origin
a vendory
sandbox $ vendor/vendors update
- Jan Jakeš
- Člen | 177
Vypadá to pěkně. Mám jeden dotaz – dá se nějak ovlivnit pořadí přidávání assets do hlavičky?
Sám jsem přemýšlel o nějakém komplexním řešení všech assets a zatím mám myšlenku, že by jakákoliv komponenta mohla mít assets a závislost na jiných komponentách. Jak assets tak závislosti bych asi rád nastavoval přes config, abych opravdu mohl přidat třeba pouze knihovnu JS tímto způsobem:
jquery:
assets: ['cesta-k-jquery']
myComponent:
assets: ['moje-assets'] # anebo jejich nastavení v šabloně komponenty
dependencies: [jquery]
A jQuery by se samo načetlo před assets myComponent
. Je to
jen nástin, podstata je, že bych se rád dostal k řešení, kdy kompletní
instalace komponenty (např. stažené z doplňků) bude vyžadovat jen
přidání adresáře s komponentou např. do libs
, její
přidání do config.neon
s nastavením, na kterých knihovnách
závisí.
Editoval Juan (12. 1. 2012 11:16)
- Filip Procházka
- Moderator | 4668
Určitě by to šlo, ale nevidím důvod, proč dělit cesty k js knihovnám, které prakticky patří k view, někam do configu.
- Jan Jakeš
- Člen | 177
Mně šlo hlavně o to, jak řešit závislosti komponent a tedy pořadí načítání jejich JS, případně CSS. O ten zápis v konfigu nejde, to byla vlastně jen „zkratka“ pro to, abych nemusel pro čistě JS framework hned vytvářet komponentu se šablonou a přesto na něj mohl nějak vyjádřit závislost.
- 22
- Člen | 1478
já bych se rád někdy dožil toho, aby stačilo komponentu vzít a akorát nahrát do libs.. nebo kam vidí robotLoader. Zásadní zádrhel je v tom, že v šabloně komponenty nemůžu definovat např. {block head}<script>..{/block}, i když je jasný, že komponenta bez Presenteru je k ničemu a Presenter bez @layout.latte, kde je ten block definovanej, jak by smet.
- Filip Procházka
- Moderator | 4668
Však to už funguje (tedy, až znovu opravím Kdyby na nejnovější Nette :)
Stačí šabloně komponenty přidat makra a FormulaeManager
,
o což se ti postará kdyby, když budeš dědit
Kdyby\Application\UI\Control
a dáš tovírničce na komponentu
v DIC tag component
.
<script n:javascript>
$(function () { });
</script>
A bude fungovat ;)
- Filip Procházka
- Moderator | 4668
Mám dilema, udělat aliasy {css}
a {js}
?
//edit: tak jsem to tam nakonec dal :)
Editoval HosipLan (13. 1. 2012 14:24)