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', [	'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 

A třetí způsob je nejvíce upovídaný:

$el = Html::el('img')	->setAttribute('src', 'image.jpg')	->setAttribute('alt', 'photo'); echo $el->getAttribute('src'); // 'image.jpg' $el->removeAttribute('alt'); 

Hromadně lze atributy nastavit pomocí addAttributes(array $attrs) a odstranit pomocí removeAttributes(array $attrNames).

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">' 

Nebo i tím nejvíce upovídaným způsobem:

$el = Html::el('input'); $el->appendAttribute('style', 'color', 'green'); $el->appendAttribute('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', [	'id' => 10,	'lang' => 'en', ]); // '<a href="index.php?id=10&amp;lang=en"></a>' 

Data attributy

Speciální podporu mají datové atributy. Protože jejich názvy obsahují pomlčky, není přístup přes property a metody tak elegantní, proto existuje metoda data():

$el = Html::el('input'); $el->{'data-max-size'} = '500x300'; // není tolik elegantní $el->data('max-size', '500x300'); // je elegatní echo $el; // '<input data-max-size="500x300">' 

Pokud je hodnotou datového attributu pole, automaticky se serializuje do JSONu:

$el = Html::el('input'); $el->data('items', [1,2,3]); echo $el; // '<input data-items="[1,2,3]">' 

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í addHtml() či addText():

$el = Html::el('span')	->addHtml('hello<br>')	->addText('10 < 20')	->addHtml( Html::el('br') ); // <span>hello<br>10 &lt; 20<br></span> 

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

$ul = Html::el('ul'); $ul->create('li', ['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)	->addHtml('hello<br>')	->addText('10 < 20')	->addHtml( Html::el('br') ); // hello<br>10 &lt; 20<br> 

Rychlejší způsob vytvoření fragmentu nabízí metody fromHtml() a fromText():

$el = Html::fromHtml('hello<br>'); echo $el; // 'hello<br>' $el = Html::fromText('10 < 20'); echo $el; // '10 &lt; 20' 

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>' $s = $el->toHtml(); // '<div class="header">hello</div>' $s = $el->toText(); // 'hello' echo $el->startTag(); // '<div class="header">' echo $el->endTag(); // '</div>' echo $el->attributes(); // 'class="header"' 

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> 

Konverze HTML ↔ text

Pro převod HTML do textu můžete využít statickou metodu htmlToText():

echo Html::htmlToText('<span>One &amp; Two</span>'); // 'One & Two' 

HtmlStringable

Objekt Nette\Utils\Html implementuje rozhraní Nette\HtmlStringable, 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}.

verze: 4.0 3.x 2.x