HTML elemek

Nette\Utils\Html osztály egy segédprogram a HTML kód generálásához, amely megakadályozza a Cross Site Scripting (XSS) sebezhetőséget.

Úgy működik, hogy az objektumai HTML elemeket reprezentálnak, paramétereiket beállítjuk, és hagyjuk őket renderelni:

$el = Html::el('img'); // <img> elemet hoz létre
$el->src = 'image.jpg'; // beállítja az src attribútumot
echo $el; // kiírja '<img src="image.jpg">'

Telepítés:

composer require nette/utils

Minden példa feltételezi, hogy a következő osztály alias van definiálva:

use Nette\Utils\Html;

HTML-elem létrehozása

Az elem létrehozása a Html::el() módszerrel történik:

$el = Html::el('img'); // <img> elemet hoz létre

A HTML-szintaxisban a név mellett más attribútumokat is megadhat:

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

Vagy asszociatív tömbként adja át őket a második paraméterhez:

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

Egy elem nevének megváltoztatása és visszaadása:

$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, mivel <img> üres elem

HTML-attribútumok

Az egyes HTML-attribútumokat háromféleképpen állíthatod be és kaphatod meg, rajtad áll, hogy melyik tetszik jobban. Az első a tulajdonságokon keresztül:

$el->src = 'image.jpg'; // beállítja az src attribútumot

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

unset($el->src); // az attribútum eltávolítása
// vagy $el->src = null;

A második mód a metódusok hívása, amelyeket a tulajdonságok beállításával ellentétben láncszerűen egymáshoz kapcsolhatunk:

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

$el->alt(null); // eltávolítja az attribútumot.

A harmadik mód pedig a legbeszédesebb:

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

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

$el->removeAttribute('alt');

Tömegesen, az attribútumokat a addAttributes(array $attrs) segítségével lehet beállítani, és a removeAttributes(array $attrNames) segítségével törölni.

Egy attribútum értékének nem kell csak egy karakterláncnak lennie, logikai attribútumokhoz logikai értékek is használhatók:

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

Egy attribútum lehet szóközökkel elválasztva felsorolt tokenek tömbje is, ami például CSS-osztályok esetében megfelelő:

$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // a null értéket figyelmen kívül hagyjuk.
$el->class[] = 'top';
echo $el; // '<input class="active top">'

Alternatív megoldás az asszociatív tömb, ahol az értékek megmondják, hogy a kulcsot fel kell-e sorolni:

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

A CSS-stílusok asszociatív tömbök formájában írhatók:

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

Most a tulajdonságokat használtuk, de ugyanezt megtehetjük a metódusok használatával is:

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

Vagy akár a legbeszédesebb módon:

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

Még egy utolsó dolog: a href() módszer megkönnyítheti a lekérdezési paraméterek összeállítását egy URL-ben:

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

Adatattribútumok

Az adatattribútumok speciális támogatással rendelkeznek. Mivel a nevük kötőjeleket tartalmaz, a tulajdonságokon és metódusokon keresztüli hozzáférés nem olyan elegáns, ezért van egy módszer: data():

$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // nem olyan elegáns
$el->data('max-size', '500x300'); // nagyon elegáns
echo $el; // '<input data-max-size="500x300">'

Ha az adatattribútum értéke egy tömb, akkor az automatikusan JSON-ba szerializálódik:

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

Elem tartalma

Az elem belső tartalmát a setHtml() vagy a setText() metódusok határozzák meg. Az elsőt csak akkor használja, ha tudja, hogy megbízhatóan biztonságos HTML karakterláncot ad át a paraméterben.

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

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

Ezzel szemben a belső tartalmat a getHtml() vagy a getText() metódusokkal kapjuk meg. A második eltávolítja a címkéket a HTML-kimenetből, és a HTML-elemeket karakterekké alakítja.

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

Gyermek csomópontok

Egy elem belső tartalma lehet a gyermekelemek tömbje is. Ezek mindegyike lehet egy-egy karakterlánc vagy egy másik Html elem. Ezek beillesztése a addHtml() vagy a addText() segítségével történik:

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

Egy másik módja egy új Html csomópont létrehozásának és beszúrásának:

$el = Html::el('ul')
	->create('li', ['class' => 'first'])
		->setText('hello');
// <ul><li class="first">hello</li></ul>

A csomópontokkal úgy dolgozhat, mintha tömbelemek lennének. Tehát az egyeseket szögletes zárójelek segítségével érhetjük el, a count() segítségével megszámolhatjuk őket, és iterálhatunk rajtuk:

$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

Egy új csomópontot a insert(?int $index, $child, bool $replace = false) segítségével lehet egy adott pozícióba beilleszteni. Ha $replace = false, akkor a $index pozícióba illeszti be az elemet, a többit pedig áthelyezi. Ha $index = null, akkor egy elemet illeszt a végére.

// beilleszti az elemet az első pozícióba és előrébb lépteti a többit.
$el->insert(0, Html::el('span'));

Az összes csomópontot a getChildren() metódus adja vissza, és a removeChildren() metódus távolítja el.

Dokumentumtöredék létrehozása

Ha csomópontok tömbjével akarsz dolgozni, és nem érdekel a csomagoló elem, létrehozhatsz egy úgynevezett dokumentumtöredéket, ha az elem neve helyett a null címet adod meg:

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

A fromHtml() és a fromText() metódusok gyorsabb módját kínálják a töredék létrehozásának:

$el = Html::fromHtml('hello<br>');
echo $el; // 'hello<br>'

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

HTML kimenet generálása

A HTML-elemek generálásának legegyszerűbb módja a echo használata, vagy egy objektumnak a (string) címre történő átvitele. A nyitó vagy záró címkéket és attribútumokat külön is ki lehet nyomtatni:

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

echo $el;               // '<div class="header"></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"'

Fontos funkció a Cross Site Scripting (XSS) elleni automatikus védelem. Minden attribútumérték vagy a setText() vagy a addText() használatával beillesztett tartalom megbízhatóan elkerüli az escapet:

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

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

Átalakítás HTML ↔ Szöveg

A htmlToText() statikus módszerrel a HTML-t szöveggé alakíthatja:

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

HtmlStringable

A Nette\Utils\Html objektum megvalósítja a Nette\HtmlStringable interfészt, amelyet például a Latte vagy az űrlapok használnak azon objektumok megkülönböztetésére, amelyek rendelkeznek egy olyan __toString() metódussal, amely HTML-kódot ad vissza. Így nem történik kettős eszkábálás, ha például a sablonban az objektumot a {$el} segítségével nyomtatjuk ki.

verzió: 4.0