Vložení JS/CSS z komponenty do šablony

- Šaman
 - Člen | 2668
 
Ahoj, název vlákna není přesný, ale chtěl jsem, aby byl co nejvýstižnější. Jak řešíte komponenty, nebo továrny na formuláře, které mají vlastní JS/CSS?
Všechny diskuze, co jsem našel, jsou 5 let staré, tak předpokládám, že frontenďáci už mají nějaký osvědčený způsob, který nepotřebuje diskutovat :)
P.S. Teď mi nejde o to, aby se scripty načítaly odněkud z vendoru, nebo
/app. Samotné scripty budou ve /www na přesně
definované adrese pomocí boweru. Jde mi jen o to, že třeba JS který je
potřeba pro konkrétní formulář se závislými selectboxy, nechci načítat
ani v @layoutu (kanón na vrabce), ani ručně v šabloně, která ten
formulář používá (tam na to mohu zapomenout).

- Pavel Kravčík
 - Člen | 1206
 
Nedávno jsem to řešil s pomocí webloaderu, že jsem si udělal „balíčky“.
js:
  base:
    files:
      - bootstrap-3.3.1.min.js
      - netteForms.js
      - spinner.ajax.js
  default:
    files:
	  - jquery.confirm.js
      - bootstrap-filestyle.js
      - jquery.autocomplete.min.js
      - jquery.elevate-zoom-3.0.8.min.js
  dochazka:
    files:
      - dochazka/dochazka.js
V základní šabloně je něco jako {component cssBase}
{component cssExtend} a v presenteru kde potřebuji jiné styly si
přetížím metody createComponentCssExtend a ta pak vypadá takhle:
protected function createComponentExtendJs()
{
  return $this->webLoader->createJavaScriptLoader('dochazka');
}
Tj. pro každý presenter si jednoduše připravíš správný guláš js.

- Šaman
 - Člen | 2668
 
No, to si mohu udělat i ručně. (Načíst správné JS v šabloně
presenteru.)
Já bych docela rád docílil toho, že příslušný JS zapíšu jen do
šablony (nebo php kódu) komponenty a pak mi bude jedno, kam tuto komponentu
umístím. Protože když je větší množství komponent různě po celém
projektu, tak už nevím, která potřebuje dolinkovat nějaký JS/CSS a
která ne.

- Šaman
 - Člen | 2668
 
Díky za odpovědi, ale nakonec se jako nejjednodušší ukázalo staré řešení
od Tharose.
Trochu jsem si to upravil, rozšířil o možnost načítat i CSS (ačkoliv to
nedoporučuji) a výsledek je tento:
$(function () {
	// basePath nastavíme buď pomocí data-atributu při načtení scriptu
	// <script src="{$basePath}/js/easyLoader.js" id="easyLoader" data-basepath="{$basePath}"></script>
	var basepath = $('#easyLoader').data('basepath');
	// nebo se použije adresa serveru
	if (basepath === undefined) {
		basepath = window.location.protocol + "//" + window.location.host + "/";
	}
	// načtení CSS (na CSS se tento loader nedoporučuje používat, protože je závislý na JS a načtení stylů je zpožděné)
	$('[data-css]').each(function (index, element) {
		var style = $(element).data('css');
		if (style instanceof Array) {
			$.each(style, function (index, style) {
				head.load(basepath + style);
			})
		} else {
			head.load(basepath + style);
		}
	});
	// načtení JS
	$('[data-js]').each(function (index, element) {
		var script = $(element).data('js');
		if (script instanceof Array) {
			$.each(script, function (index, script) {
				head.js(basepath + script);
			})
		} else {
			head.js(basepath + script);
		}
	});
});
<!-- @layout.latte -->
<script src="{$basePath}/bower/jquery/dist/jquery.min.js"></script>
<script src="{$basePath}/bower/headjs/dist/1.0.0/head.load.min.js"></script>
<script src="{$basePath}/js/easyLoader.js" id="easyLoader" data-basepath="{$basePath}"></script>
<!-- template.latte -->
<h1 data-css="/css/pokus.css">Pokusy</h1>
<div data-js="/js/bootstrap.tab.history.js">…</div>
- Je to vyzkoušené na aktuálních verzích FF, Chrome, Exploreru a Opery. Mělo by to být kompatibilní i se staršími (nikoliv archaickými) prohlížeči.
 - Pokud máte nastavený server tak, že v adrese není /www (nebo jiný kus adresářové stuktury), tak není potřeba přenášet tu basepath v data atributu.
 - Pokud máte zkušenosti s JS, napadá vás nějaký zásadní problém, proč tohle řešení nepoužívat? A co na to @Tharos, který s tím má osobní zkušenosti? Koukal jsem, že na svém GitHubu už to smazal.
 - Repozitář a možná bower balíček tomu vytvořím, až to otestuji v praxi. Zatím mi na tom běží jen pokusná miniaplikace.
 
Pozn. Celá část s basepath je možná úplně zbytečná,
čitelnější mi připadá předávat rovnou celou cestu už z šablony.
<!-- @layout.latte -->
<script src="{$basePath}/bower/jquery/dist/jquery.min.js"></script>
<script src="{$basePath}/bower/headjs/dist/1.0.0/head.load.min.js"></script>
<script src="{$basePath}/js/easyLoader.js"></script>
<!-- template.latte -->
<h1 data-css="{$basePath}/css/pokus.css">Pokusy</h1>
<div data-js="{$basePath}/js/bootstrap.tab.history.js">…</div>
					Editoval Šaman (26. 11. 2015 4:15)

- Jan Mikeš
 - Člen | 771
 
Ahoj, ja toto resim tak, ze mam v hlavnim @layout.latte tesne pred </body> nasledujici blok:
 {control js}
 {block js}{/block}
{control js} je webloader
V pripade, ze potrebuji nejaky dalsi js je to jednoduche, v sablone, kde jej potrebuji rozsiruji
{block js}
	{include #parent}
	<script ...>
{/block}
Pokud se jedna o sablonu komponenty, ve ktere chci js/css mit, pak pridavam komponente view js/css a tento view pak prislusnym renderem renderuji v presenteru takze v konecnem vysledku vypada nejak takhle
// MyPresenter.default.latte
{block js}
	{include #parent}
	<script ...>
	<script ...>
	{control myComponent:js}
	{control myComponentXy:js}
{/block}
	// MyComponent\js.latte
	<script ...>
					Editoval Lexi (26. 11. 2015 7:42)

- Šaman
 - Člen | 2668
 
Jenže právě toho se chci vyvarovat. Presenter přece neví, že nějaká
komponenta má i JS. Když k nějaké komponentě připíšu script, tak
nechci prohledávat celý projekt a u každého výskytu přidat do šablony
presenteru i {control myComponent:js}.
Ten webloader je jedno řešení, dynamické donačítání scriptů je druhé
řešení. A na občasné donačtení malých JS (typicky oživení
konkrétního formuláře) mi zatím to druhé řešení vyhovuje víc.

- CZechBoY
 - Člen | 3608
 
A když si uděláš svojí komponentu, která bude spravovat js + css
komponent?
Ke každý komponentě si tu službu přidáš a budeš po ní požadovat, ať
tyhle js a css knihovny přidá.
Ta služba potom bude spravovat pořadí, ve kterým se mají js a css načíst,
aby se to nějak nepo**lo … :)

- Demo
 - Člen | 1
 
Ahoj,
v nette jsem začátečník, ale narazil jsem na stejný problém. Nepokročilo
se od posledního příspěvku k nějakému elegantnějšímu vestavěnému
řešení? Přišlo by mi smysluplné mít v @layout třeba block {block
dalsiScripty} a z šablony komponenty pak jen do tohoto bloku přidat další
položku/obsah. Změna v šabloně komponenty by se tak automaticky projevila
všude, kde je jí třeba. Protože komponent může být v presenteru mnoho,
tak by se obsahy skládaly…
Díky,
Demo

- AntiCZ
 - Člen | 13
 
Ja jsem to vyresil pres tovarnu komponenty, ktera v konstruktoru setuje do servisy svoje jmeno. A potom si v BasePresenteru v beforeRenderu projdu seznam vyzadanych komponent.
- Nevyhody
 - To ze probehl inject v Presenteru, jeste neznamena, ze bude kompopenta vyrendrovana, treba s tim v JS pocitat.
 - U vnorenych komponent je potreba predavat tovarnu na komponentu jako zavislost rodici.
 
Editoval AntiCZ (2. 6. 2018 8:55)