Elemente HTML

Clasa Nette\Utils\Html este un ajutor pentru generarea codului HTML care previne vulnerabilitatea Cross Site Scripting (XSS).

Funcționează astfel: obiectele sale reprezintă elemente HTML cărora le setăm atributele și apoi le randăm:

$el = Html::el('img');  // creează elementul <img>
$el->src = 'image.jpg'; // setează atributul src
echo $el;               // afișează '<img src="image.jpg">'

Instalare:

composer require nette/utils

Toate exemplele presupun că a fost creat un alias:

use Nette\Utils\Html;

Crearea unui element HTML

Elementul se creează folosind metoda Html::el():

$el = Html::el('img'); // creează elementul <img>

Pe lângă nume, puteți specifica și alte atribute folosind sintaxa HTML:

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

Sau le puteți transmite ca array asociativ în al doilea parametru:

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

Modificarea și obținerea numelui elementului:

$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, deoarece <img> este un element gol

Atribute HTML

Atributele HTML individuale pot fi setate și citite în trei moduri; depinde de dvs. care preferați. Primul mod este prin proprietăți:

$el->src = 'image.jpg'; // setează atributul src

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

unset($el->src);  // elimină atributul
// sau $el->src = null;

Al doilea mod este prin apelarea metodelor, care, spre deosebire de setarea proprietăților, pot fi înlănțuite:

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

$el->alt(null); // eliminarea atributului

Și al treilea mod este cel mai verbos:

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

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

$el->removeAttribute('alt');

Atributele pot fi setate în bloc folosind addAttributes(array $attrs) și eliminate folosind removeAttributes(array $attrNames).

Valoarea atributului nu trebuie să fie doar un șir; se pot folosi și valori booleene pentru atributele booleene:

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

Atributul poate fi și un array de valori, care se afișează separate prin spații, util, de exemplu, pentru clasele CSS:

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

O alternativă este un array asociativ, unde valorile indică dacă cheia trebuie afișată:

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

Stilurile CSS pot fi scrise sub formă de array-uri asociative:

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

Am folosit proprietăți, dar același lucru se poate scrie folosind metode:

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

Sau chiar în modul cel mai verbos:

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

Un mic detaliu la final: metoda href() poate facilita compunerea parametrilor query în URL:

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

Atribute data-*

Atributele data-* (data attributes) au un suport special. Deoarece numele lor conțin cratime, accesul prin proprietăți și metode nu este la fel de elegant, de aceea există metoda data():

$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // nu este la fel de elegant
$el->data('max-size', '500x300'); // este elegant
echo $el; // '<input data-max-size="500x300">'

Dacă valoarea unui atribut data-* este un array, acesta se serializează automat în JSON:

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

Conținutul elementului

Conținutul intern al elementului se setează cu metodele setHtml() sau setText(). Folosiți setHtml() doar dacă sunteți sigur că parametrul conține un șir HTML sigur.

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

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

Invers, conținutul intern se obține cu metodele getHtml() sau getText(). getText() elimină tag-urile HTML din conținut și convertește entitățile HTML în caractere.

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

Noduri copil

Conținutul unui element poate fi, de asemenea, un array de noduri copil (children). Fiecare nod poate fi fie un șir, fie un alt element Html. Le adăugăm folosind addHtml() sau addText():

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

Altă modalitate de a crea și insera un nou nod Html:

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

Cu nodurile se poate lucra la fel ca și cu un array. Adică, accesarea individuală a acestora folosind paranteze drepte, numărarea lor folosind count() și iterarea peste ele:

$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

Un nod nou poate fi inserat într-o poziție specifică folosind insert(?int $index, $child, bool $replace = false). Dacă $replace este false, inserează elementul la poziția $index și le deplasează pe celelalte. Dacă $index este null, adaugă elementul la sfârșit.

// inserează elementul la prima poziție și le deplasează pe celelalte
$el->insert(0, Html::el('span'));

Toate nodurile copil se obțin cu metoda getChildren() și se elimină cu metoda removeChildren().

Crearea unui fragment de document

Dacă dorim să lucrăm cu un array de noduri fără un element înconjurător, putem crea un fragment de document transmițând null în loc de numele elementului:

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

Metodele fromHtml() și fromText() oferă o modalitate mai rapidă de a crea un fragment:

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

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

Generarea ieșirii HTML

Cel mai simplu mod de a afișa un element HTML este să folosiți echo sau să convertiți obiectul la (string). Se pot, de asemenea, afișa separat tag-urile de deschidere sau închidere și atributele:

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

O caracteristică importantă este protecția automată împotriva Cross Site Scripting (XSS). Toate valorile atributelor sau conținutul inserat prin setText() sau addText() sunt escapate în mod fiabil:

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

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

Conversie HTML ↔ text

Pentru a converti HTML în text, puteți utiliza metoda statică htmlToText():

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

HtmlStringable

Obiectul Nette\Utils\Html implementează interfața Nette\HtmlStringable. Latte și formularele folosesc această interfață pentru a distinge obiectele care au o metodă __toString() ce returnează cod HTML. Astfel, nu se produce dublă escapare dacă, de exemplu, afișăm obiectul într-un șablon folosind {$el}.

versiune: 4.0