dynamicke pridavani stylu / scriptu do layoutu
- vlna
- Člen | 34
Ahoj, napada me potreba mit moznost v nejake komponente pridat (az
v pripade potreby) do layoutu napr. vygenerovany javascript nebo javascript,
ktery je potreba jen za urcitych podminek.
V predchozim frameworku jsme pouzivali neco jako
$oLayout = Layout::getLayout(); //singleton
$oLayout->title = '...';
$oLayout->addScript('js/datagrid.js');
$oLayout->addStyle('css/datagrid.css');
$oLayout->addScriptStart('FOOT');
document.getElementById("dataGrid1").onclick = function ...;
$oLayout->addScriptEnd();
...
v template potom:
$oLayout->generateCss($vypsatMistoJenOdkazat=false);
Jak docilit neceho podobneho v Nette ? Tusim, ze tomu jde mozna naproti
moznost „noveho“ zpusobu parsovani sablon dedenim ?
diky
Editoval vlna (22. 5. 2009 2:40)
- Patrik Votoček
- Člen | 2221
Požívám něco takového:
BasePresenter:
<?php
class BasePresenter extends /*Nette\Application\*/Presenter
{
protected function addJsScript($data, $isFile = TRUE)
{
if (empty($this->template->jsScripts))
$this->template->jsScripts = array();
//Tohle je zjednoduseni mam na to vlastni classu
$this->template->jsScripts[] = (object) array('isFile' => $isFile, 'data' => $data);
}
protected function addCssStyle($data, $isFile = TRUE, $type = "all")
{
if (empty($this->template->cssStyles))
$this->template->cssStyles = array();
//Tohle je zjednoduseni mam na to vlastni classu
$this->cssStyles[] = (object) array('isFile' => $isFile, 'data' => $data, 'type' => $type);
}
}
?>
Layout template:
<html>
<head>
...
{* Load CSS Styles *}
{foreach $cssStyles as $cssStyle}
{if $cssStyle->isFile}
<link rel="stylesheet" media="{$cssStyle->type}" type="text/css" href="{$baseUri}{$cssStyle->data}">
{else}
<style type="text/css" media="{$cssStyle->type}">
{$cssStyle->data}
</style>
{/if}
{/foreach}
{* Load JS Scripts *}
{foreach $jsScripts as $jsScript}
{if $jsScript->isFile}
<script type="text/javascript" src="{$baseUri}{$jsScript->data}"></script>
{else}
<script type="text/javascript">
{$jsScript->data}
</script>
{/if}
{/foreach}
...
</head>
<body>
...
<body>
</html>
Edit:
Pak jenom v presenteru resp. action (dříve: view):
<?php
class MyPresenter extends BasePresenter
{
public function actionDefault()
{
$this->addCssStyle("css/mystyle.css");
$this->addJsScript("js/myscript.js");
//Nebo
$this->addCssStyle("css/mystyle.css", TRUE, "screen");
//Resp
$data = '#page { color: #f00; }';
$this->addCssStyle($data, FALSE);
$data = 'document.getElementById("dataGrid1").onclick = function ...;';
$this->addJsScript($data, FALSE);
//Nebo
$data = '#page { color: #f00; }';
$this->addCssStyle($data, FALSE, "screen");
}
}
?>
Chystám se že to předělám do vykreslitelných komponent.
Edit 2: byl tam blbě $baseUri
Editoval vrtak-cz (22. 5. 2009 10:34)
- redhead
- Člen | 1313
Neco takoveho je resene ve frameworku Stripes primo v templatě:
<stripes:layout-component name="html-head-javascript">
<script language="javascript" src="./js/projectx-form-controller.js"></script>
</stripes:layout-component>
Prijde mi to dosti logicke to mit v template, bo to muze ovlivnovat napr. koder bez toho aby musel do php kodu.
Nejak me nenapada jak to v Nette resit.
Stale v Nette narazim na to, ze je delany spise pro jednoho cloveka, a ne pro mozny tym lidi (programatori, koder)
- jasir
- Člen | 746
redhead napsal(a):
Neco takoveho je resene ve frameworku Stripes primo v templatě:
<stripes:layout-component name="html-head-javascript"> <script language="javascript" src="./js/projectx-form-controller.js"></script> </stripes:layout-component>
Prijde mi to dosti logicke to mit v template, bo to muze ovlivnovat napr. koder bez toho aby musel do php kodu.
Nejak me nenapada jak to v Nette resit.
Stale v Nette narazim na to, ze je delany spise pro jednoho cloveka, a ne pro mozny tym lidi (programatori, koder)
Můžeš to řešit v šabloně buď pomocí bloků, nebo si na to vytvořit nějaký helper.
- Patrik Votoček
- Člen | 2221
Něco takového by šlo udělat taky (při použití renderování v opačném pořadí):
Layout:
<html>
<head>
...
{* Load CSS Styles *}
{block #cssStyles}{/block}
{* Load JS Scripts *}
{block #jsScripts}{/if}
...
</head>
<body>
...
<body>
</html>
Šablona:
{extends '@layout.phtml'}
{block #cssStyles}
<link rel="stylesheet" media="all" type="text/css" href="{$baseUri}css/mystyle.css">
{/block}
{block #jsScripts}
<script type="text/javascript" src="{$baseUri}js/myscript.js"></script>
{/block}
- Patrik Votoček
- Člen | 2221
arron napsal(a):
Idealne zkombinovat obe metody dohromady:-) Bylo by to Nette-clean a zaroven by se daly scripty a styly prirazovat dynamicky (treba podle nastaveni konkretniho uzivatele).
Myslíš jako něco takového?
Layout template:
<html>
<head>
...
{* Load CSS Styles *}
{foreach $cssStyles as $cssStyle}
{if $cssStyle->isFile}
<link rel="stylesheet" media="{$cssStyle->type}" type="text/css" href="{$baseUri}{$cssStyle->data}">
{else}
<style type="text/css" media="{$cssStyle->type}">
{$cssStyle->data}
</style>
{/if}
{/foreach}
{block #cssStyles}{/block}
{* Load JS Scripts *}
{foreach $jsScripts as $jsScript}
{if $jsScript->isFile}
<script type="text/javascript" src="{$baseUri}{$jsScript->data}"></script>
{else}
<script type="text/javascript">
{$jsScript->data}
</script>
{/if}
{/foreach}
{block #jsScripts}{/block}
...
</head>
<body>
...
<body>
</html>
???
- Patrik Votoček
- Člen | 2221
já zase doplním že část {include #parent} je nutná pouze pokud chceme zachovat co jsme nastavili v rodičovské žabloně pokud dědíme pouze od Layoutu který je popsán výše tak není třeba.
- jasir
- Člen | 746
Jo, ale když už jsme u toho, jak tohle řešíte u komponent? Tam to
přes bloky IMHO nejde.
Čili by asi nějaký „centrální systém“ správy assetů (img, css, js)
nebyl od věci.
Mám teď na mysli, kdy mám komponentu a chci jí mít sakumprdum v jednom
adresáři i s css, img atd.
Možná by stálo za to vymyslet, jak tyto soubory mít u komponenty a nějak
automaticky je kopírovat
do document_root…
- Patrik Votoček
- Člen | 2221
jasir napsal(a):
Možná by stálo za to vymyslet, jak tyto soubory mít u komponenty a nějak automaticky je kopírovat
do document_root…
Rewrite pravidlo do .htaccess
?
- jasir
- Člen | 746
vrtak-cz napsal(a):
jasir napsal(a):
Možná by stálo za to vymyslet, jak tyto soubory mít u komponenty a nějak automaticky je kopírovat
do document_root…Rewrite pravidlo do
.htaccess
?
Takže pro každou komponentu rewrite do htacces? Já ti nevím… Radši bych viděl všechny věci pod document_rootem… Nebo by šlo udělat nějaké jednotné pravidlo? Jak by pak mělo vypadat?
- vlna
- Člen | 34
Parada, spousta pouzitelnych napadu, diky.
Ja bych se mozna nebal dopsat si na to nejaky filtr, protoze pujde vzdy
o stejny kod, ktery nema smysl v sablonach kopirovat. Nevadilo by mi ani
pouzit primo nejakou metodu $presenter->printCss(…) v sablone (az budu
potrebovat jiny format nez HTML, budu resit), ale filtr bude asi cistsi.
K tomuhle jsem si uz parkrat posteskl, ze CurlyBracketFilter (AFAIK)
nepodporuje neco jako template-run-time-callbacky.
$macros = array(
'/block' => '<?php %:macroBlock% ?>',
'stylesImport' => 'BasePresenter::printStyles',
...
aby proste template engine v dobe kompilace zavolal
BasePresenter::printStyles( udaje_o_tagu, objektSablony ); Callback by vratil
to, co je ted staticky v $macros.
Nebo to nejak jde ?
- jasir
- Člen | 746
aby proste template engine v dobe kompilace zavolal BasePresenter::printStyles( udaje_o_tagu, objektSablony ); Callback by vratil to, co je ted staticky v $macros.
Nebo to nejak jde ?
Jde to, tak jak to píšeš, teď jsem to zkoušel:
<?php
class Testik {
static function macroMujTest($var, $modif=NULL)
{
return 'rendering in compile time.';
}
}
$t = new Template();
$t->registerFilter('CurlyBracketsFilter::invoke');
CurlyBracketsFilter::$macros['mujtest'] = '<h2>%Testik::macroMujTest%<h2>';
$t->setFile('testBrackets.phtml');
$t->render();
?>
v šabloně:
{mujtest ble fuje hnida |modif}
Do funkce pak v dostaneš v prvnim parametru „ble fuje hnida“, v druhym „|modif“.
- vlna
- Člen | 34
jasir napsal(a):
Jde to, tak jak to píšeš, teď jsem to zkoušel:
CurlyBracketsFilter::$macros[‚mujtest‘] = ‚<h2>%Testik::macroMujTest%<h2>‘;
v šabloně:
{mujtest ble fuje hnida |modif}
Do funkce pak v dostaneš v prvnim parametru „ble fuje hnida“, v druhym „|modif“.
Perfektni! Diky, zkousel jsem predtim zadat callback ruzne, ale nejspis jsem nekde udelal chybu.
Podle reseni, ktera tu padla bych teda udelal:
(1) na BasePresenteru teda vytvorim pristup k pomocnemu objektu, ktery se bude starat o css / js importy. (chci to aspon jasneji oddelit od metod presenteru). Pristup potom bude napr.:
$presenter->htmlResources->addStyle($sLink, $bInclude=false, $aHtmlAttributes);
$presenter->htmlResources->addScript($sLink, $bInclude=false, $aHtmlAttributes=null, $sSection=false|HEAD|FOOT);
$presenter->htmlResources->scriptStart($sSection, $aHtmlAttributes);
$presenter->htmlResources->scriptEnd();
$presenter->htmlResources->cssStart($sSection, $aHtmlAttributes);
$presenter->htmlResources->cssEnd();
# + tohle aby se napr. jednoduse dalo rict pri renderovani sablony pro
mail,
# aby forcovala vkladani celych stylu / js, misto externich odkazu
$presenter->htmlResources->setRenderingMode(NORMAL|FORCE_EXPAND|FORCE_hups_opak_expand);
(2) k CurlyBracketFilter pridam makro treba {cssDump} {jsDump section=Head mode=internal|external} ktery to bude
vypisovat … resp. generovat php kod s iterovanim pres
$presenter->htmlResources->data .
Nebude se teda vkladat pouze vygenerovane html, pro pripad, ze by se chtelo
prave „podminkovat“ vygenerovani stylu/scriptu v ruznych rezimech, za
ruznych okolnosti.
Prijde vam to takle ok? Asi by to melo byt spis primo na sablone, ale to ohybani by se myslim nevyplatilo.
Editoval vlna (24. 5. 2009 13:50)