You are browsing the unmaintained documentation for old Nette 2.2. See documentation for current Nette.

HTML elementy

Třída Nette\Utils\Html je pomocník pro generování HTML kódu, který nedovolí vznik zranitelnosti Cross Site Scripting (XSS).

Funguje tak, že jeho objekty představují HTML elementy, kterým nastavíme parametry a necháme je vykreslit:

$el = Html::el('img');  // vytvoří element <img>
$el->src = 'image.jpg'; // nastaví atribut src
echo $el;               // vypíše '<img src="image.jpg">'

Instalace:

composer require nette/utils

Všechny příklady předpokládají vytvořený alias:

use Nette\Utils\Html;

Vyvoření HTML elementu

Element vytvoříme metodou Html::el():

$el = Html::el('img'); // vytvoří element <img>

Kromě názvu můžete zadat i další atributy v HTML syntaxi:

$el = Html::el('input type=text class="red important"');

Nebo je předat jako asociativní pole druhým parametrem:

$el = Html::el('input', array(
	'type' => 'text',
	'class' => 'important',
));

Změna a vrácení názvu elementu:

$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // TRUE, jelikož <img> je prázdný element

HTML atributy

Jednotlivé HTML atributy můžeme měnit a číst třemi způsoby, záleží na vás, který se vám bude líbit víc. První z nich je skrze property:

$el->src = 'image.jpg'; // nastaví atribut src

echo $el->src; // 'image.jpg'

unset($el->src);  // zruší atribut
// nebo $el->src = NULL;

Druhou cestou je volání metod, které oproti nastavování properties můžeme za sebe řetězit:

$el = Html::el('img')->src('image.jpg')->alt('photo');
// <img src="image.jpg" alt="photo">

$el->alt(NULL); // zrušení atributu

Hromadně lze atributy nastavit pomocí addAttributes(array $attrs).

Hodnotou atributu nemusí být jen řetězec, lze používat i logické hodnoty pro logické atributy:

$checkbox = Html::el('input')->type('checkbox');
$checkbox->checked = TRUE;  // <input type="checkbox" checked>
$checkbox->checked = FALSE; // <input type="checkbox">

Atributem může být i pole hodnot, které se vypíší oddělené mezerami, což se hodí například pro CSS třídy:

$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = NULL; // NULL se ignoruje
$el->class[] = 'top';
echo $el; // '<input class="active top">'

Alternativou je asociativní pole, kde hodnoty říkají, zda má být klíč vypsán:

$el = Html::el('input');
$el->class['active'] = TRUE;
$el->class['top'] = FALSE;
echo $el; // '<input class="active">'

CSS styly lze zapisovat ve formě asociativních polí:

$el = Html::el('input');
$el->style['color'] = 'green';
$el->style['display'] = 'block';
echo $el; // '<input style="color: green; display: block">'

Nyní jsme používali property, ale totéž se dá zapsat pomocí metod:

$el = Html::el('input');
$el->style('color', 'green');
$el->style('display', 'block');
echo $el; // '<input style="color: green; display: block">'

Ještě drobnost na závěr: metoda href() umí usnadnit skládání query parametrů v URL:

echo Html::el('a')->href('index.php', array(
	'id' => 10,
	'lang' => 'en',
));
// '<a href="index.php?id=10&amp;lang=en"></a>'

Obsah elementu

Vnitřní obsah elementu nastavíme metodami setHtml() či setText(). První z nich použijte jen v případě, že víte, že v parametru předáváte spolehlivě bezpečný HTML řetězec.

echo Html::el('span')->setHtml('hello<br>');
// '<span>hello<br></span>'

echo Html::el('span')->setText('10 < 20');
// '<span>10 &lt; 20</span>'

A obráceně vnitřní obsah získáme metodami getHtml() či getText(). Druhá z nich odstraní z výstupu HTML značky a HTML entity převede na znaky.

echo $el->getHtml(); // '10 &lt; 20'
echo $el->getText(); // '10 < 20'

Podřízené uzly

Vnitřek elementu může být také pole podřízených (children) uzlů. Každý z nich může být buď řetězec, nebo další Html element. Vkládáme je pomocí add():

$el = Html::el('span')
	->add('hello<br>')
	->add( Html::el('br') );
// <span>hello<br><br></span>

Další způsob pro vytvoření a vložení nového Html uzlu:

$el = Html::el('ul')
	->create('li', array('class' => 'first'))
		->setText('první');
// <ul><li class="first">první</li></ul>

S uzly lze pracovat stejně, jako by se jednalo o pole. Tedy přistupovat k jednotlivým z nich pomocí hranatých závorek, spočítat je pomocí count() a iterovat nad nimi:

$el = Html::el('div');
$el[] = '<b>hello</b>';
$el[] = Html::el('span');
echo $el[1]; // '<span></span>'

foreach ($el as $child) { ... }

echo count($el); // 2

Nový uzel lze na konkrétní místo vložit pomocí insert(?int $index, $child, bool $replace = FALSE). Pokud je $replace = FALSE, vloží prvek na pozici $index a ostatní posune. Pokud je $index = NULL, přidá prvek nakonec.

// vloží prvek na první pozici a ostatní posune
$el->insert(0, Html::el('span'));

Všechny uzly získáme metodou getChildren() a odstraníme je metodou removeChildren().

Vytvoření document fragment

Pokud chceme pracovat s polem uzlů a nezajímá nás obalovací element, můžeme vytvořit tzv. document fragment předáním NULL místo jména elementu:

$el = Html::el(NULL)
	->add('hello<br>')
	->add( Html::el('br') );
// hello<br><br>

Generování HTML výstupu

Nejjednodušším způsobem, jak vypsat HTML element, je použít echo nebo objekt přetypovat na (string). Lze také samostatně vypsat otevírací nebo uzavírací značky a atributy:

$el = Html::el('div class=header')->setText('hello');

echo $el;               // '<div class="header">hello</div>'
$s = (string) $el;      // '<div class="header">hello</div>'
echo $el->startTag();   // '<div class="header">'
echo $el->endTag();     // '</div>'

Důležitým rysem je automatická ochrana proti Cross Site Scriptingu (XSS). Všechny hodnoty atributů nebo obsah vložený přes setText() či addText() se spolehlivě escapuje:

echo Html::el('div')
	->title('" onmouseover="bad()')
	->setText('<script>bad()</script>');

// <div title='" onmouseover="bad()'>&lt;script&gt;bad()&lt;/script&gt;</div>

Výstup je možné přepnout do XHTML nastavením statické proměnné Html::$xhtml na TRUE:

$el = Html::el('input')->disabled(TRUE);
echo $el; // '<input disabled>'
Html::$xhtml = TRUE;
echo $el; // '<input disabled="disabled" />'

IHtmlString

Objekt Nette\Utils\Html implementuje rozhraní Nette\Utils\IHtmlString, kterým například Latte nebo formuláře rozlišují objekty, které mají metodu __toString() vracející HTML kód. Takže nedojde k dvojímu escapování, pokud třeba objekt vypíšeme v šabloně pomocí {$el}.