KlÃÄem k vytváÅenà âživýchâ stránek je modifikace DOMu.
Zde uvidÃme, jak vytváÅet nové elementy âza bÄhuâ a jak modifikovat obsah existujÃcà stránky.
PÅÃklad: zobrazenà zprávy
PÅedveÄme si to na pÅÃkladu. PÅidáme na stránku zprávu, která bude vypadat lépe než alert.
Bude to vypadat následovnÄ:
<style>
.upozornÄnà {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<div class="upozornÄnÃ">
<strong>Nazdar!</strong> PrávÄ ÄteÅ¡ důležitou zprávu.
</div>
To byl pÅÃklad v HTML. Nynà vytvoÅme stejný div v JavaScriptu (pÅedpokládáme, že styly jsou již definovány v HTML/CSS).
VytvoÅenà elementu
K vytvoÅenà DOM uzlu sloužà dvÄ metody:
document.createElement(znaÄka)-
VytvoÅà nový elementový uzel se zadanou znaÄkou:
let div = document.createElement('div'); document.createTextNode(text)-
VytvoÅà nový textový uzel se zadaným textem:
let textovýUzel = document.createTextNode('Tady jsem');
VÄtÅ¡inou potÅebujeme vytváÅet elementové uzly, napÅÃklad div pro naÅ¡i zprávu.
VytvoÅenà zprávy
VytvoÅenà znaÄky div pro zprávu se skládá ze tÅà kroků:
// 1. VytvoÅÃme element <div>
let div = document.createElement('div');
// 2. NastavÃme jeho tÅÃdu na "upozornÄnÃ"
div.className = "upozornÄnÃ";
// 3. VložÃme do nÄj obsah
div.innerHTML = "<strong>Nazdar!</strong> PrávÄ ÄteÅ¡ důležitou zprávu.";
VytvoÅili jsme element. ProzatÃm se vÅ¡ak nacházà jen v promÄnné jménem div a ne na stránce, takže ho nemůžeme vidÄt.
Metody pro vkládánÃ
Aby se nám div ukázal, musÃme ho vložit nÄkam do document, napÅÃklad do elementu <body>, na který se odkazuje document.body.
K tomu sloužà speciálnà metoda append: document.body.append(div).
Zde je celý kód:
<style>
.upozornÄnà {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<script>
let div = document.createElement('div');
div.className = "upozornÄnÃ";
div.innerHTML = "<strong>Nazdar!</strong> PrávÄ ÄteÅ¡ důležitou zprávu.";
document.body.append(div);
</script>
Tady jsme volali append na document.body, ale metodu append můžeme volat i na kterémkoli jiném elementu, abychom do nÄj vložili dalšà element. Můžeme napÅÃklad nÄco pÅipojit k <div> volánÃm div.append(dalÅ¡ÃElement).
Existujà i dalšà vkládacà metody, které specifikujà jiná mÃsta, kam se má vkládat:
uzel.append(...uzly nebo ÅetÄzce)â pÅipojà uzly nebo ÅetÄzce na konec uzluuzel,uzel.prepend(...uzly nebo ÅetÄzce)â vložà uzly nebo ÅetÄzce na zaÄátek uzluuzel,uzel.before(...uzly nebo ÅetÄzce)â- vložà uzly nebo ÅetÄzce pÅeduzel,uzel.after(...uzly nebo ÅetÄzce)â- vložà uzly nebo ÅetÄzce zauzel,uzel.replaceWith(...uzly nebo ÅetÄzce)â- nahradÃuzelzadanými uzly nebo ÅetÄzci.
Argumenty tÄchto metod je jakýkoli seznam DOM uzlů, které se majà vložit, nebo textových ÅetÄzců (z nich se automaticky vytvoÅà textové uzly).
PodÃvejme se na nÄ v akci.
Následuje pÅÃklad, jak pomocà tÄchto metod pÅidat prvky do seznamu a text pÅed a za nÄj:
<ol id="ol">
<li>0</li>
<li>1</li>
<li>2</li>
</ol>
<script>
ol.before('pÅed'); // vložà ÅetÄzec "pÅed" pÅed <ol>
ol.after('za'); // vložà ÅetÄzec "za" za <ol>
let liPrvnà = document.createElement('li');
liPrvnÃ.innerHTML = 'zaÄátek';
ol.prepend(liPrvnÃ); // vložà liPrvnà na zaÄátek <ol>
let liPoslednà = document.createElement('li');
liPoslednÃ.innerHTML = 'konec';
ol.append(liPoslednÃ); // vložà liPoslednà na konec <ol>
</script>
Na obrázku je zobrazeno, co tyto metody dÄlajÃ:
Výsledný seznam tedy bude:
pÅed
<ol id="ol">
<li>zaÄátek</li>
<li>0</li>
<li>1</li>
<li>2</li>
<li>konec</li>
</ol>
za
Jak bylo uvedeno, tyto metody dokážà vložit vÃce uzlů a Äástà textu pÅi jednom volánÃ.
NapÅÃklad zde se vložà ÅetÄzec a element:
<div id="div"></div>
<script>
div.before('<p>Ahoj</p>', document.createElement('hr'));
</script>
ProsÃme vÅ¡imnÄte si, že text se vložà âjako textâ, ne âjako HTMLâ, takže znaky jako < a > budou pÅÃsluÅ¡ným způsobem upraveny.
Výsledný HTML kód tedy je:
<p>Ahoj</p>
<hr>
<div id="div"></div>
Jinými slovy, ÅetÄzce se vložà bezpeÄným způsobem stejnÄ, jak to dÄlá elem.textContent.
Tyto metody tedy můžeme použÃt jedinÄ ke vkládánà DOM uzlů a Äástà textu.
Ale co když chceme vložit HTML ÅetÄzec âjako htmlâ, aby v nÄm fungovaly vÅ¡echny znaÄky a vÅ¡echno ostatnÃ, stejnÄ, jak to provádà elem.innerHTML?
insertAdjacentHTML/Text/Element
K tomu můžeme použÃt jinou, vÃceúÄelovou metodu: elem.insertAdjacentHTML(kam, html).
PrvnÃm parametrem je kódové slovo, které specifikuje, kam se má vkládat, relativnÄ vůÄi elem. Musà to být jedno z následujÃcÃch:
"beforebegin"â vložÃhtmlbezprostÅednÄ pÅedelem,"afterbegin"â vložÃhtmldoelemna zaÄátek,"beforeend"â vložÃhtmldoelemna konec,"afterend"â vložÃhtmlbezprostÅednÄ zaelem.
Druhým parametrem je HTML ÅetÄzec, který bude vložen âjako HTMLâ.
PÅÃklad:
<div id="div"></div>
<script>
div.insertAdjacentHTML('beforebegin', '<p>Ahoj</p>');
div.insertAdjacentHTML('afterend', '<p>Sbohem</p>');
</script>
â¦VytvoÅÃ:
<p>Ahoj</p>
<div id="div"></div>
<p>Sbohem</p>
TÃmto způsobem můžeme ke stránce pÅipojit libovolný HTML kód.
Varianty vkládánà jsou znázornÄny na obrázku:
Snadno si vÅ¡imneme podobnostà mezi tÃmto a pÅedchozÃm obrázkem. MÃsta pro vkládánà jsou ve skuteÄnosti stejná, ale tato metoda vkládá HTML kód.
Tato metoda má dvÄ sesterské metody:
elem.insertAdjacentText(kam, text)â stejná syntaxe, ale ÅetÄzectextse mÃsto HTML vložà âjako textâ,elem.insertAdjacentElement(kam, elem)â stejná syntaxe, ale vložà element.
Tyto metody existujà hlavnÄ proto, aby syntaxe byla âjednotnáâ. V praxi se vÄtÅ¡inou použÃvá jen insertAdjacentHTML, protože pro elementy a text máme metody append/prepend/before/after â jsou kratšà na napsánà a umÄjà vkládat uzly nebo Äásti textu.
Zde je tedy alternativnà varianta zobrazenà zprávy:
<style>
.upozornÄnà {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<script>
document.body.insertAdjacentHTML("afterbegin", `<div class="upozornÄnÃ">
<strong>Nazdar!</strong> PrávÄ ÄteÅ¡ důležitou zprávu.
</div>`);
</script>
OdstranÄnà uzlu
K odstranÄnà uzlu sloužà metoda uzel.remove().
Nechme naši zprávu za jednu sekundu zmizet:
<style>
.upozornÄnà {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<script>
let div = document.createElement('div');
div.className = "upozornÄnÃ";
div.innerHTML = "<strong>Nazdar!</strong> PrávÄ ÄteÅ¡ důležitou zprávu.";
document.body.append(div);
setTimeout(() => div.remove(), 1000);
</script>
ProsÃme vÅ¡imnÄte si, že jestliže chceme pÅemÃstit element na jiné mÃsto, nemusÃme jej z původnÃho mÃsta odstraÅovat.
VÅ¡echny vkládacà metody automaticky odstranà uzel z mÃsta, kde se nacházel pÅedtÃm.
NapÅÃklad prohoÄme elementy navzájem:
<div id="prvnÃ">PrvnÃ</div>
<div id="druhý">Druhý</div>
<script>
// nenà tÅeba volat remove
druhý.after(prvnÃ); // vezme #druhý a za nÄj vložà #prvnÃ
</script>
Klonovánà uzlů: cloneNode
Jak vložit dalšà podobnou zprávu?
Mohli bychom vytvoÅit funkci a vložit kód do nÃ. AlternativnÃm způsobem vÅ¡ak je klonovat existujÃcà div a zmÄnit text uvnitÅ nÄj (pokud to potÅebujeme).
NÄkdy, když máme velký element, to může být rychlejšà a jednoduššÃ.
- VolánÃ
elem.cloneNode(true)vytvoÅà âhlubokýâ klon elementu â se vÅ¡emi atributy a podelementy. Jestliže zavolámeelem.cloneNode(false), bude klon vytvoÅen bez dÄtských elementů.
PÅÃklad kopÃrovánà zprávy:
<style>
.upozornÄnà {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<div class="upozornÄnÃ" id="div">
<strong>Nazdar!</strong> PrávÄ ÄteÅ¡ důležitou zprávu.
</div>
<script>
let div2 = div.cloneNode(true); // naklonujeme zprávu
div2.querySelector('strong').innerHTML = 'Sbohem!'; // zmÄnÃme klon
div.after(div2); // zobrazÃme klon za existujÃcÃm <div>
</script>
DocumentFragment
DocumentFragment je speciálnà DOM uzel, který sloužà jako obal pro pÅedávánà seznamů uzlů.
Můžeme k nÄmu pÅidávat dalšà uzly, ale když jej nÄkam vložÃme, mÃsto nÄj se vložà jeho obsah.
NapÅÃklad následujÃcà funkce vraÅ¥ObsahSeznamu vygeneruje fragment s prvky <li>, které jsou následnÄ vloženy do <ul>:
<ul id="ul"></ul>
<script>
function vraťObsahSeznamu() {
let fragment = new DocumentFragment();
for(let i=1; i<=3; i++) {
let li = document.createElement('li');
li.append(i);
fragment.append(li);
}
return fragment;
}
ul.append(vraťObsahSeznamu()); // (*)
</script>
ProsÃme vÅ¡imnÄte si, že na poslednÃm Åádku (*) jsme pÅipojili DocumentFragment, ale ten âvymizÃâ a výsledná struktura bude následujÃcÃ:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
DocumentFragment se explicitnÄ použÃvá jen zÅÃdka. ProÄ bychom mÄli nÄco pÅipojovat ke speciálnÃmu druhu uzlu, když mÃsto nÄj můžeme vrátit pole uzlů? PÅepsaný pÅÃklad:
<ul id="ul"></ul>
<script>
function vraťObsahSeznamu() {
let výsledek = [];
for(let i=1; i<=3; i++) {
let li = document.createElement('li');
li.append(i);
výsledek.push(li);
}
return výsledek;
}
ul.append(...vraÅ¥ObsahSeznamu()); // append + operátor "..." = pÅátelé!
</script>
ZmÃnili jsme DocumentFragment hlavnÄ proto, že na nÄm jsou postaveny urÄité koncepty, napÅÃklad element Å¡ablony, který probereme mnohem pozdÄji.
Vkládacà a odebÃracà metody ze staré Å¡koly
Existujà i metody pro manipulaci s DOMem âze staré Å¡kolyâ, které jsou zachovány z historických důvodů.
Tyto metody pocházejà z mnohem dÅÃvÄjšà doby. V souÄasnosti nenà důvod je použÃvat, jelikož modernà metody, napÅ. append, prepend, before, after, remove, replaceWith, jsou flexibilnÄjÅ¡Ã.
Jediným důvodem, proÄ zde tyto metody uvádÃme, je, že je můžete najÃt v mnoha starých skriptech:
rodiÄovskýElement.appendChild(uzel)-
PÅipojÃ
uzeljako poslednà dÃtÄ elementurodiÄovskýElement.NásledujÃcà pÅÃklad pÅidá nový
<li>na konec<ol>:<ol id="seznam"> <li>0</li> <li>1</li> <li>2</li> </ol> <script> let novýLi = document.createElement('li'); novýLi.innerHTML = 'Ahoj, svÄte!'; seznam.appendChild(novýLi); </script> rodiÄovskýElement.insertBefore(uzel, dalÅ¡ÃSourozenec)-
VložÃ
uzelpÅed uzeldalÅ¡ÃSourozenecdo elementurodiÄovskýElement.NásledujÃcà kód vložà nový prvek seznamu pÅed druhý
<li>:<ol id="seznam"> <li>0</li> <li>1</li> <li>2</li> </ol> <script> let novýLi = document.createElement('li'); novýLi.innerHTML = 'Ahoj, svÄte!'; seznam.insertBefore(novýLi, seznam.children[1]); </script>Chceme-li vložit
novýLijako prvnà element, můžeme to udÄlat následovnÄ:seznam.insertBefore(novýLi, seznam.firstChild); rodiÄovskýElement.replaceChild(uzel, původnÃDÃtÄ)-
NahradÃ
původnÃDÃtÄmezi dÄtmi elementurodiÄovskýElementuzlemuzel. rodiÄovskýElement.removeChild(uzel)-
OdstranÃ
uzelz elementurodiÄovskýElement(za pÅedpokladu, žeuzelje jeho dÃtÄtem).NásledujÃcà pÅÃklad odstranà prvnÃ
<li>z<ol>:<ol id="seznam"> <li>0</li> <li>1</li> <li>2</li> </ol> <script> let li = seznam.firstElementChild; seznam.removeChild(li); </script>
VÅ¡echny tyto metody vracejà vložený nebo odstranÄný uzel. Jinými slovy, rodiÄovskýElement.appendChild(uzel) vrátà uzel. Návratová hodnota se vÅ¡ak obvykle nepoužÃvá, prostÄ jen zavoláme metodu.
Pár slov o âdocument.writeâ
Existuje jeÅ¡tÄ jedna, velice stará metoda pro pÅidávánà na webovou stránku: document.write.
Syntaxe:
<p>NÄkde na stránce...</p>
<script>
document.write('<b>Pozdrav od JS</b>');
</script>
<p>Konec</p>
Volánà document.write(html) zapÃÅ¡e html na stránku âprávÄ tady a teÄâ. ÅetÄzec html může být dynamicky generován, takže metoda je do urÄité mÃry flexibilnÃ. Můžeme v JavaScriptu vytvoÅit webovou stránku obsahujÃcà vÅ¡e potÅebné a zapsat ji.
Tato metoda pocházà jeÅ¡tÄ z doby, kdy neexistoval žádný DOM, žádné standardy⦠Z opravdu dávné doby. Stále vÅ¡ak existuje, protože jsou skripty, které ji využÃvajÃ.
V modernÃch skriptech ji vidÃme jen zÅÃdka, a to kvůli následujÃcÃmu důležitému omezenÃ:
Volánà document.write funguje jen tehdy, dokud se stránka naÄÃtá.
Pokud ji zavoláme pozdÄji, stávajÃcà obsah dokumentu bude smazán.
PÅÃklad:
<p>Po jedné sekundÄ bude obsah této stránky nahrazen...</p>
<script>
// document.write po 1 sekundÄ
// tedy po naÄtenà této stránky, takže existujÃcà obsah se smaže
setTimeout(() => document.write('<b>...TÃmto.</b>'), 1000);
</script>
Ve stavu âpo naÄtenÃâ je tedy vÃceménÄ nepoužitelná, na rozdÃl od ostatnÃch DOM metod, které jsme tady probrali.
To je jejà nevýhoda.
Má vÅ¡ak i výhodu. Technicky, když je document.write zavolána a nÄco zapÃÅ¡e, zatÃmco prohlÞeÄ naÄÃtá (âparsujeâ) pÅicházejÃcà HTML kód, prohlÞeÄ to zpracuje tak, jako by to bylo v původnÃm HTML kódu.
Funguje tedy bleskovÄ rychle, protože se nekoná žádná modifikace DOMu. Zapisuje rovnou do textu stránky, dokud jeÅ¡tÄ DOM nenà vytvoÅen.
Pokud tedy potÅebujeme dynamicky pÅidat do HTML velké množstvà textu, nacházÃme se ve fázi naÄÃtánà stránky a záležà nám na rychlosti, tato metoda nám může pomoci. V praxi vÅ¡ak tyto požadavky málokdy pÅicházejà souÄasnÄ. A ve skriptech tuto metodu vidÃme pÅevážnÄ proto, že jsou prostÄ staré.
ShrnutÃ
-
Metody pro vytváÅenà nových uzlů:
document.createElement(znaÄka)â vytvoÅà element se zadanou znaÄkou,document.createTextNode(hodnota)â vytvoÅà textový uzel (použÃvá se málokdy),elem.cloneNode(hluboce)â naklonuje element, pokudhluboce==true, pak se vÅ¡emi potomky.
-
Vkládánà a odstraÅovánÃ:
uzel.append(...uzly nebo ÅetÄzce)â vložà douzelna jeho konec,uzel.prepend(...uzly nebo ÅetÄzce)â vložà douzelna jeho zaÄátek,uzel.before(...uzly nebo ÅetÄzce)â vložà bezprostÅednÄ pÅeduzel,uzel.after(...uzly nebo ÅetÄzce)â vložà bezprostÅednÄ zauzel,uzel.replaceWith(...uzly nebo ÅetÄzce)â nahradÃuzel,uzel.remove()â odstranÃuzel.
Textové ÅetÄzce se vkládajà âjako textâ.
-
Existujà i metody âze staré Å¡kolyâ:
rodiÄ.appendChild(uzel)rodiÄ.insertBefore(uzel, dalÅ¡ÃSourozenec)rodiÄ.removeChild(uzel)rodiÄ.replaceChild(novýElement, uzel)
VÅ¡echny tyto metody vracejÃ
uzel. -
Máme-li nÄjaký HTML kód v promÄnné
html, pak jejelem.insertAdjacentHTML(kam, html)vložà na mÃsto, které závisà na hodnotÄkam:"beforebegin"â vložÃhtmlbezprostÅednÄ pÅedelem,"afterbegin"â vložÃhtmldoelemna jeho zaÄátek,"beforeend"â vložÃhtmldoelemna jeho konec,"afterend"â vložÃhtmlbezprostÅednÄ zaelem.
Existujà i podobné metody
elem.insertAdjacentTextaelem.insertAdjacentElement, které vkládajà textové ÅetÄzce a elementy, ale použÃvajà se jen zÅÃdka. -
Pro pÅipojenà HTML kódu ke stránce, jeÅ¡tÄ než skonÄilo jejà naÄÃtánÃ:
document.write(html)
Po dokonÄenà naÄÃtánà stránky toto volánà smaže dokument. K vidÄnà pÅevážnÄ ve starých skriptech.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)