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

Šaman
Člen | 2659
+
0
-

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

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

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.

CZechBoY
Člen | 3608
+
0
-

Do komponenty si pridej JsCssManager a pres tenhle singleton pridavej js, css soubory.
V šabloně klasicky vypiš jako komponentu {control jsCssManager:js}, {control jsCssManager:css}

Šaman
Člen | 2659
+
+1
-

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

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 | 2659
+
+1
-

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

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 … :)

Eagle
Člen | 5
+
0
-

Ahoj Honzo,
mě se toto Tvé řešení líbí. Zrovna jsem to potřeboval nějak slušně vyřešit a funguje mi to, takže díky za to! :-)

Demo
Člen | 1
+
0
-

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

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)