Elementi HTML

Razred Nette\Utils\Html je pomočnik za generiranje kode HTML, ki preprečuje ranljivost XSS (Cross Site Scripting).

Deluje tako, da njegovi predmeti predstavljajo elemente HTML, nastavimo njihove parametre in jih pustimo, da se izrišejo:

$el = Html::el('img');  // ustvari element <img>
$el->src = 'image.jpg'; // nastavi atribut src
echo $el;               // izpiše '<img src="image.jpg">'

Namestitev:

composer require nette/utils

Vsi primeri predpostavljajo, da je definiran naslednji vzdevek razreda:

use Nette\Utils\Html;

Ustvarjanje elementa HTML

Element je ustvarjen z metodo Html::el():

$el = Html::el('img'); // ustvari element <img>

Poleg imena lahko v sintaksi HTML vpišete tudi druge atribute:

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

Lahko pa jih posredujete kot asociativno polje v drugem parametru:

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

Če želite spremeniti in vrniti ime elementa:

$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, ker je <img> prazen element

Atributi HTML

Posamezne atribute HTML lahko nastavite in pridobite na tri načine, od vas pa je odvisno, kateri vam je bolj všeč. Prvi je prek lastnosti:

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

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

unset($el->src);  // odstrani atribut
// ali $el->src = null;

Drugi način je klicanje metod, ki jih lahko v nasprotju z nastavljanjem lastnosti verižno povežemo:

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

$el->alt(null); // odstrani atribut

Tretji način je najbolj zgovoren:

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

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

$el->removeAttribute('alt');

Atribute je mogoče množično nastaviti s addAttributes(array $attrs) in izbrisati s removeAttributes(array $attrNames).

Vrednost atributa ni nujno samo niz, za logične atribute lahko uporabite tudi logične vrednosti:

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

Atribut je lahko tudi polje žetonov, ki so na seznamu ločeni s presledki, kar je primerno na primer za razrede CSS:

$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // ničla se ne upošteva
$el->class[] = 'top';
echo $el; // '<input class="active top">'

Druga možnost je asociativno polje, kjer vrednosti povedo, ali naj bo ključ naveden:

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

sloge CSS lahko zapišemo v obliki asociativnih polj:

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

Uporabili smo lastnosti, enako pa lahko storimo tudi z metodami:

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

Ali celo na najbolj pogovoren način:

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

Še nekaj: metoda href() lahko olajša sestavljanje parametrov poizvedbe v naslovu URL:

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

Podatkovni atributi

Podatkovni atributi imajo posebno podporo. Ker njihova imena vsebujejo pomišljaje, dostop prek lastnosti in metod ni tako eleganten, zato je na voljo metoda data():

$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // ne tako elegantno
$el->data('max-size', '500x300'); // je eleganten
echo $el; // '<input data-max-size="500x300">'

Če je vrednost podatkovnega atributa polje, se samodejno serializira v JSON:

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

Vsebina elementa

Notranja vsebina elementa se nastavi z metodama setHtml() ali setText(). Prvo metodo uporabite le, če veste, da v parametru zanesljivo posredujete varen niz HTML.

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

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

Nasprotno pa notranjo vsebino pridobimo z metodama getHtml() ali getText(). Druga odstrani oznake iz izpisa HTML in pretvori entitete HTML v znake.

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

Podrejena vozlišča

Notranja vsebina elementa je lahko tudi polje otrok. Vsak od njih je lahko niz ali drug element Html. Vstavljamo jih z uporabo addHtml() ali addText():

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

Drug način za ustvarjanje in vstavljanje novega vozlišča Html:

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

Z vozlišči lahko delate, kot da so elementi polja. Tako do posameznih dostopate z uporabo oglatih oklepajev, jih preštejete s count() in iterirate nad njimi:

$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

Novo vozlišče lahko vstavite na določeno mesto z uporabo insert(?int $index, $child, bool $replace = false). Če je $replace = false, vstavi element na mesto $index in premakne ostale. Če je $index = null, se element doda na konec.

// vstavi element v prvi položaj in premakne druge
$el->insert(0, Html::el('span'));

Vsa vozlišča se vrnejo z metodo getChildren() in odstranijo z metodo removeChildren().

Ustvarjanje fragmenta dokumenta

Če želite delati z nizom vozlišč in vas zavijalni element ne zanima, lahko ustvarite tako imenovani dokumentni fragment tako, da namesto imena elementa posredujete null:

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

Metodi fromHtml() in fromText() ponujata hitrejši način ustvarjanja fragmenta:

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

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

Ustvarjanje izpisa HTML

Element HTML najlažje generirate tako, da uporabite echo ali pa predmet oddate v (string). Ločeno lahko natisnete tudi odpiralne ali zapiralne oznake in atribute:

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

Pomembna lastnost je samodejna zaščita pred križanjem spletnih strani (XSS). Vse vrednosti atributov ali vsebine, vstavljene z uporabo setText() ali addText(), so zanesljivo izločene:

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

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

Pretvorba HTML ↔ Besedilo

Za pretvorbo HTML v besedilo lahko uporabite statično metodo htmlToText():

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

HtmlStringable

Predmet Nette\Utils\Html implementira vmesnik Nette\HtmlStringable, ki ga na primer Latte ali obrazci uporabljajo za razlikovanje predmetov, ki imajo metodo __toString(), ki vrača kodo HTML. Tako do dvojnega izrivanja ne pride, če na primer objekt v predlogi izpišemo z uporabo {$el}.

različica: 4.0