HTML elementi
Razred Nette\Utils\Html je pomočnik za generiranje HTML kode, ki preprečuje nastanek ranljivosti Cross Site Scripting (XSS).
Deluje tako, da njegovi objekti predstavljajo HTML elemente, katerim nastavimo parametre in jih pustimo izrisati:
$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 ustvarjen vzdevek:
use Nette\Utils\Html;
Ustvarjanje HTML elementa
Element ustvarimo z metodo Html::el()
:
$el = Html::el('img'); // ustvari element <img>
Poleg imena lahko navedete tudi druge atribute v HTML sintaksi:
$el = Html::el('input type=text class="red important"');
Ali pa jih posredujete kot asociativno polje kot drugi parameter:
$el = Html::el('input', [
'type' => 'text',
'class' => 'important',
]);
Sprememba in vrnitev imena elementa:
$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, ker je <img> prazen element
HTML atributi
Posamezne HTML atribute lahko spreminjamo in beremo na tri načine, odvisno od vas, kateri vam bo bolj všeč. Prvi je preko lastnosti (properties):
$el->src = 'image.jpg'; // nastavi atribut src
echo $el->src; // 'image.jpg'
unset($el->src); // prekliče atribut
// ali $el->src = null;
Drugi način je klicanje metod, ki jih za razliko od nastavljanja lastnosti lahko verižimo:
$el = Html::el('img')->src('image.jpg')->alt('photo');
// <img src="image.jpg" alt="photo">
$el->alt(null); // preklic atributa
In 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');
Množično lahko atribute nastavite z addAttributes(array $attrs)
in odstranite z
removeAttributes(array $attrNames)
.
Vrednost atributa ni nujno samo niz, lahko uporabljate tudi logične vrednosti za logične atribute:
$checkbox = Html::el('input')->type('checkbox');
$checkbox->checked = true; // <input type="checkbox" checked>
$checkbox->checked = false; // <input type="checkbox">
Atribut je lahko tudi polje vrednosti, ki se izpišejo ločene s presledki, kar je uporabno na primer za CSS razrede:
$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // null se ignorira
$el->class[] = 'top';
echo $el; // '<input class="active top">'
Alternativa je asociativno polje, kjer vrednosti povedo, ali naj se ključ izpiše:
$el = Html::el('input');
$el->class['active'] = true;
$el->class['top'] = false;
echo $el; // '<input class="active">'
CSS stile je mogoče zapisati v obliki asociativnih polj:
$el = Html::el('input');
$el->style['color'] = 'green';
$el->style['display'] = 'block';
echo $el; // '<input style="color: green; display: block">'
Zdaj smo uporabljali lastnosti, vendar se enako lahko zapiše 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 zgovoren 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 majhna podrobnost za konec: metoda href()
lahko olajša sestavljanje query parametrov v URL:
echo Html::el('a')->href('index.php', [
'id' => 10,
'lang' => 'en',
]);
// '<a href="index.php?id=10&lang=en"></a>'
Data atributi
Posebno podporo imajo podatkovni atributi (data attributes). Ker njihova imena vsebujejo vezaje, dostop preko lastnosti in
metod ni tako eleganten, zato obstaja metoda data()
:
$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // ni tako elegantno
$el->data('max-size', '500x300'); // je elegantno
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
Notranjo vsebino elementa nastavimo z metodama setHtml()
ali setText()
. Prvo uporabite samo
v primeru, da veste, da v parametru posredujete zanesljivo varen HTML niz.
echo Html::el('span')->setHtml('hello<br>');
// '<span>hello<br></span>'
echo Html::el('span')->setText('10 < 20');
// '<span>10 < 20</span>'
In obratno, notranjo vsebino dobimo z metodama getHtml()
ali getText()
. Druga odstrani iz izpisa
HTML oznake in HTML entitete pretvori v znake.
echo $el->getHtml(); // '10 < 20'
echo $el->getText(); // '10 < 20'
Podrejeni vozli
Notranjost elementa je lahko tudi polje podrejenih (children) vozlov. Vsak izmed njih je lahko bodisi niz ali drug
Html
element. Vstavljamo jih z addHtml()
ali addText()
:
$el = Html::el('span')
->addHtml('hello<br>')
->addText('10 < 20')
->addHtml( Html::el('br') );
// <span>hello<br>10 < 20<br></span>
Drug način za ustvarjanje in vstavljanje novega Html
vozla:
$ul = Html::el('ul');
$ul->create('li', ['class' => 'first'])
->setText('prvi');
// <ul><li class="first">prvi</li></ul>
Z vozli lahko delamo enako, kot da bi šlo za polje. Torej dostopati do posameznih z oglatimi oklepaji, jih prešteti z
count()
in iterirati 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
Nov vozel lahko vstavite na določeno mesto z insert(?int $index, $child, bool $replace = false)
. Če je
$replace = false
, vstavi element na pozicijo $index
in ostale premakne. Če je
$index = null
, doda element na konec.
// vstavi element na prvo pozicijo in ostale premakne
$el->insert(0, Html::el('span'));
Vse vozle dobimo z metodo getChildren()
in jih odstranimo z metodo removeChildren()
.
Ustvarjanje fragmenta dokumenta
Če želimo delati s poljem vozlov in nas ne zanima ovojni element, lahko ustvarimo t.i. document fragment
s posredovanjem null
namesto imena elementa:
$el = Html::el(null)
->addHtml('hello<br>')
->addText('10 < 20')
->addHtml( Html::el('br') );
// hello<br>10 < 20<br>
Hitrejši način ustvarjanja fragmenta ponujata metodi fromHtml()
in fromText()
:
$el = Html::fromHtml('hello<br>');
echo $el; // 'hello<br>'
$el = Html::fromText('10 < 20');
echo $el; // '10 < 20'
Generiranje HTML izpisa
Najenostavnejši način za izpis HTML elementa je uporaba echo
ali pretvorba objekta v (string)
.
Lahko tudi ločeno izpišete odpiralne ali zapiralne oznake in atribute:
$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"'
Pomembna značilnost je samodejna zaščita pred Cross
Site Scripting (XSS). Vse vrednosti atributov ali vsebina, vstavljena preko setText()
ali addText()
,
se zanesljivo ubežijo (escape):
echo Html::el('div')
->title('" onmouseover="bad()')
->setText('<script>bad()</script>');
// <div title='" onmouseover="bad()'><script>bad()</script></div>
Pretvorba HTML ↔ besedilo
Za pretvorbo HTML v besedilo lahko uporabite statično metodo htmlToText()
:
echo Html::htmlToText('<span>One & Two</span>'); // 'One & Two'
HtmlStringable
Objekt Nette\Utils\Html
implementira vmesnik Nette\HtmlStringable
, s katerim na primer Latte ali
obrazci razlikujejo objekte, ki imajo metodo __toString()
, ki vrača HTML kodo. Tako ne pride do dvojnega ubežanja
(escaping), če na primer objekt izpišemo v predlogi z {$el}
.