dynamicke pridavani stylu / scriptu do layoutu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
vlna
Člen | 34
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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}
arron
Člen | 464
+
0
-

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).

Patrik Votoček
Člen | 2221
+
0
-

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>

???

arron
Člen | 464
+
0
-

vrtak-cz napsal(a):

Myslíš jako něco takového?

Presne:-) Pak uz se s tim da delat snad cokoliv:-)

jasir
Člen | 746
+
0
-

Jo, tak nějak. Jenom dodám, že použití v šablonách pak vypadá nějak takhle:

{extends $layout}
{block #cssStyles}
	{include #parent}
	...můj přidaný obsah
{/block}
{block #jsScripts}
	{include #parent}
	... můj přidaný obsah javascriptů
{/block}
Patrik Votoček
Člen | 2221
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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)