Vypnutí escapování u maker link, plink

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

Jde nějak vypnout escapování u těchto maker? (v mém případě mi konkrétně vadí html escapování, kdy se mi v šabloně oscapuje & a při natažení šablony do callbacku javascriptu se mi neprovede signál, protože to nezvládne tu entitu v url)

Filip Procházka
Moderator | 4668
+
0
-

Kde je problém? Ukaž kód.

<div data-url="{plink Homepage:}"></div>

nebo třeba

<script>
var url = {plink Homepage:};
</script>

funguje naprosto validně.

ViPEr*CZ*
Člen | 817
+
0
-

Dost často používám jQuery UI dialogy. Tak jsem si zkusil udělat komponentu co mi vytvoří dialog (vygeneruje kód) přes PHP Nette komponentu. To je v pohodě, mám komponentu, tady nějakou šablonu a ta přidá komponentu. Ku příkladu:

/** Odeslání k archivaci */
$("#button").on("click", function(event){
	{control archiveConfirmDialog}
});

Komponenta má vlastní šablonu, kterou mi sem vykreslí. Část šablony, která se v mém živém příkladu použije vypadá:

$("#{!$id}").createConfirmDialog({
	'title': '{$title}',
	'width': '{$width}',
	'height': '{$height}',
	'message': '{$message}',
	'callbackConfirm': {if $callbackConfirm}{$callbackConfirm}{else}undefined{/if}
});

No a teď si potřebuji nastavit vlastní html (spíše js kód) pro callback, když kliknu na ano a potvrdím dialog. Do proměnný $callbackConfirm si vklidu můžu poslat Nette\Template\FileTemplate jenže ta mi právě do toho javascriptu zmrví URL. Problém je, že ten kód toho callbacku je javascript, ale není v té šabloně uzavřen do <script></script>, proto se tam volí html escapování místo js escapování a to mrví tu URL. Když to ale uzavřu do těch tagů, tak to zase nebude z hlediska html fungovat (nelze otevřít tag script již v otevřeným scriptu). Nějaká rada?

Filip Procházka
Moderator | 4668
+
0
-

Vždyť to děláš úplně špatně!

<script>
$("#" + {$id}).createConfirmDialog({
    'title': {$title},
    'width': {$width},
    'height': {$height},
    'message': {$message},
    'callbackConfirm': {if $callbackConfirm}{$callbackConfirm}{else}undefined{/if}
});

A co je za odpornost ten první kód?


Kód na dialogy… Generuj do HTML, skryj ho pomocí CSS a pak ho unobtrusive zobraz kde potřebuješ.

Generovat HTML do Javascriptu nebo Javascript do HTML je odporné™, špatně™, zlo™ a už to tak neděláme!

ViPEr*CZ*
Člen | 817
+
0
-

Mně přijde hrozný zlo si do html vkládat

<div id="dialog" title="Basic dialog">
  <p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
</div>

a to pak pomocí css skrýt jak píšeš. To je opruz děsnej. Takhle mám jQuery plugin co mi tenhle html kód vytvoří přes javascript. Děsná úleva, když můžu jen nastavit parametry dialogu v javascriptovým bloku a nemusím ještě pamatovat na to, že si musím do stránky vložit html tělo samotného dialogu.
Ten první kód vkládá javascript do javascriptu… což je podle mě teda správně. Jen přes možnosti PHP a settery při vytváření té komponenty nastavuji jak má výsledný jsko vypadat.
Nevýhoda právě je, že ta šablona té komponenty pro generování jska nemůže být obalena do tagu script, protože jí pak potřebuji vložit do již otevřeného tagu skript a druhá věc je, že ta komponenta by se měla vždy vkládat do otevřeného tagu script.

Filip Procházka
Moderator | 4668
+
0
-

Při čtení tohohle odstavce mi po těle řádila husí kůže.

Nevýhoda právě je, že ta šablona té komponenty pro generování jska nemůže být obalena do tagu script, protože jí pak potřebuji vložit do již otevřeného tagu skript a druhá věc je, že ta komponenta by se měla vždy vkládat do otevřeného tagu script.

Ty to necítíš, jak strašně děsivě to zní?


Pokud je HTML jednoduché, tak určitě nevadí ho sestavovat pomocí jQuery. A pokud máš jenom jednoduchou zprávu – why not.

Co se týče složitějších řešení, koukni třeba sem. Vždyť to je krása, jenom napíšeš HTML kód a Javascript máš pro všechna okna stejný. Parametry okna nastavíš pomocí data attributů a funguje to pěkně v celém projektu.

A vždycky si na to můžeš vyrobit makro, tohle je zrovna příklad složitějšího okna, ale pointa je jasná.

<!-- Button to trigger modal -->
<a n:modal="foo">Launch demo modal</a>

<!-- Modal -->
{modal foo}
	<header><h3 id="myModalLabel">Modal header</h3></header>
	<content>
		<p>One fine body…</p>
	</content>
	<footer>
		<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
		<button class="btn btn-primary">Save changes</button>
	</footer>
{/modal}
ViPEr*CZ*
Člen | 817
+
0
-

Je mi to jasný. Mně z toho právě taky lítá husí kůže, proto jsem se šel někam poradit. Hacknout se to dá vždy, že jo, ale tfuj. Mně se to samotnému nelíbí, proto přemýšlím jak to udělat líp.

V podstatě vytvoření dialogu mám přes jsko, ale to vem čert. Dá se říci, že jsi mi v podstatě řekl, že to mám nechat v té podobě co to mám (což je hodně podobné tomu bootstrapu) :-( Což je stále spousty neintuitivního psaní :-(
Jen pro korektnost, já volám třeba pro jednoduchý info dialog (alias alertu v jQuery UI) toto:

$("#moje").createInfoDialog({
	'title': 'Info Box',
	'message': 'Toto je informační zpráva!'
});

Definice pak doplní jeden button OK a akci click na tento button, která zavře dialog. Samozřejmě toto je default a těch parametrů je více. Jenže kdo si je má pamatovat? PHP komponenta mi je mohla našeptávat. Netbeans mi z jska parametry nenašeptá. Proto tato akce to předělat, aby to bylo intuitivnější.

Btw. by mě zajímalo co vygeneruje to tvoje makro modal?

Editoval ViPEr*CZ* (27. 2. 2013 15:55)

Filip Procházka
Moderator | 4668
+
0
-

To makro byl jenom příklad :)


Ohledně napovídání…

class ModalControl extends Nette\Application\UI\Control
{
	public $allowResize = FALSE;
	// ...

	public function render()
	{
		$this->template->attrs = Html::el()->addAttributes(array(
			'id' => $this->htmlId,
			'class' => 'modal hide',
			'data-allow-resize' => (bool) $this->allowResize,
			// ...
		));
		// ...
	}
}
<a href="#{$control->htmlId}" class="modal" data-...>
<div {!$attrs->attributes()}>
	{$content}
</div>

I data attributy můžeš mít generované ;)

ViPEr*CZ*
Člen | 817
+
0
-

Tělo dialogu s attributama tedy je toto:

<div {!$attrs->attributes()}>
    {$content}
</div>

A toto se někde přes nějakej plugin přestaví na jQuery dialog. A jak tam třeba nastavíš javascript callback pro kliknutí na tlačítko dialogu (mějme dialog s tlačítky Ano a Ne), samozřejmě tak, abych si ho lehce mohl nastavit pro každý dialog vlastní?

Filip Procházka
Moderator | 4668
+
0
-

A toto se někde přes nějakej plugin přestaví na jQuery dialog.

Například takto

$('.modal').each(function () {
	var modal = $(this);
	modal.modal({
		'allow-resize': modal.data('allow-resize')
		// ...
	});
});

A jak tam třeba nastavíš javascript callback pro kliknutí na tlačítko dialogu (mějme dialog s tlačítky Ano a Ne), samozřejmě tak, abych si ho lehce mohl nastavit pro každý dialog vlastní?

Pokud máš jenom confirm dialog, tak předpokládám, že po potvrzení chceš nejspíš zavolat nějaký signál? Já bych to alespoň tak udělal.

<a href="#confirmFoo" data-confirm-yes="{plink fooConfirmed!}">...</a>

nebo

$modal->confirmYes = $this->link('fooConfirmed!');

Snadno pak navážeš událost na tlačítka, že když klikne na Ano a máš data attribut confirm-yes, tak zavolá Ajax. Z ajaxu můžeš vrátit snippety, nebo klidně vyvolat přesměrování.

To samé můžeš udělat data-confirm-no="", budťto zavoláš signál, nebo neprovedeš operaci, pokud attribut neexistuje.


Nebo to můžeš ještě vylepšit a udělat nějakou třídu ConfirmModal, která bude mít vlastní signály a po kliknutí na tlačítko se budou volat ajaxem vždy. Vytvoříš na ní události

class ConfirmModal extends Modal
{
	public $onConfirm = array();
	public $onAbort = array();

A v signálu je budeš volat.

// ...
	public function handleConfirm()
	{
		$this->onConfirm($this);
	}

	public function handleAbort()
	{
		$this->onAbort($this);
	}

Vytvoříš tím Nette-way rozhranní, na jaké jsme všichni zvyklí z formulářů :)

ViPEr*CZ*
Člen | 817
+
0
-

Ten první způsob dá se říct používám a to mi právě přišlo už děsně složitý, proto jsem to chtěl převést na myšlenku nastavitelné komponenty a selsky řečeno kód co vytvoří dialog nechat generovat PHP kód. Mám sice kód v pluginu pro jQuery, ale i tak je tam tolik parametrů, které si prostě z hlavy nepamatuji a musím pak koukat do kódu toho pluginu, protože Netbeans mi to nikterak nenapoví.
A narazil jsem právě jak namapovat callbacky do toho dialogu, když se bude jeho kód generovat v komponentě. Udělal jsem to teď tak, že definuju callback v šabloně, kde chci pak vykreslit komponentu generující dialog a té komponentě při vytváření předám jen jméno callbacku, který se pak zavolá na správném místě.
To tvoje řešení číslo 2 vypadá hezky… chápu ho a taktéž bych ho věděl před tím udělat. Bohužel callback není vždy jen signál. Například se mi provede vlastní js validace na straně klienta + ajaxSubmit + pokud je submit success dojde k zavření dialogu + refresh nějakého bloku html kódu nebo pokud není submit success dojde k vyvolání dalšího dialogu nad otevřeným dialogem (tzv. Info Dialog) s textem a tlačítkem OK. Což do data attributu jen stěží tento balast narvu a s handle signálama si jen nevystačím.