Elemente HTML

Clasa Nette\Utils\Html este un ajutor pentru generarea codului HTML care nu permite apariția vulnerabilității Cross Site Scripting (XSS).

Funcționează astfel încât obiectele sale reprezintă elemente HTML cărora le setăm parametrii și le lăsăm să se randeze:

$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 crearea unui alias:

use Nette\Utils\Html;

Crearea unui element HTML

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

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

Pe lângă nume, puteți specifica și alte atribute în 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 returnarea numelui elementului:

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

Atribute HTML

Atributele HTML individuale pot fi modificate și citite în trei moduri, depinde de dvs. care vă place mai mult. Primul este prin proprietăți:

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

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

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

A doua cale este apelarea metodelor, care, spre deosebire de setarea proprietăților, pot fi înșiruite:

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

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

Și a treia modalitate este cea mai verbioasă:

$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 masă folosind addAttributes(array $attrs) și eliminate folosind removeAttributes(array $attrNames).

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

$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, ceea ce este util, de exemplu, pentru clasele CSS:

$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // null se ignoră
$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">'

Acum 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 verbios:

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

Încă 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 de date

Atributele de date au un suport special. Deoarece numele lor conțin cratime, accesul prin proprietăți și metode nu este atât de elegant, de aceea există metoda data():

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

Dacă valoarea atributului de date 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(). Prima o folosiți doar dacă știți că în parametru transmiteți un șir HTML sigur în mod fiabil.

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

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

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

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

Noduri copil

Interiorul elementului poate fi, de asemenea, un array de noduri copil (children). Fiecare dintre acestea poate fi fie un șir, fie un alt element Html. Le inseră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 cum ar fi 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-un loc specific folosind insert(?int $index, $child, bool $replace = false). Dacă $replace = false, inserează elementul la poziția $index și le deplasează pe celelalte. Dacă $index = null, adaugă elementul la sfârșit.

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

Toate nodurile 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 și nu ne interesează elementul înconjurător, putem crea așa-numitul 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>

O modalitate mai rapidă de a crea un fragment este oferită de metodele fromHtml() și fromText():

$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, prin care, de exemplu, Latte sau formularele disting obiectele care au metoda __toString() returnând cod HTML. Astfel, nu se produce dublă escapare dacă, de exemplu, afișăm obiectul într-un șablon folosind {$el}.

versiune: 4.0