Když prohlížeč načte stránku, „přečte“ (jiné slovo:„analyzuje“) HTML a vygeneruje z něj objekty DOM. U uzlů prvků se většina standardních atributů HTML automaticky stává vlastnostmi objektů DOM.
Pokud je například značka <body id="page">
, pak má objekt DOM body.id="page"
.
Ale mapování atributů a vlastností není individuální! V této kapitole se budeme věnovat oddělení těchto dvou pojmů, abychom viděli, jak s nimi pracovat, kdy jsou stejné a kdy se liší.
Vlastnosti modelu DOM
Již jsme viděli vestavěné vlastnosti DOM. Je toho hodně. Technicky nás ale nikdo neomezuje, a pokud jich není dost, můžeme přidat vlastní.
Uzly DOM jsou běžné objekty JavaScriptu. Můžeme je změnit.
Vytvořme například novou vlastnost v document.body
:
document.body.myData = {
name: 'Caesar',
title: 'Imperator'
};
alert(document.body.myData.title); // Imperator
Můžeme přidat i metodu:
document.body.sayTagName = function() {
alert(this.tagName);
};
document.body.sayTagName(); // BODY (the value of "this" in the method is document.body)
Můžeme také upravit vestavěné prototypy jako Element.prototype
a přidejte nové metody ke všem prvkům:
Element.prototype.sayHi = function() {
alert(`Hello, I'm ${this.tagName}`);
};
document.documentElement.sayHi(); // Hello, I'm HTML
document.body.sayHi(); // Hello, I'm BODY
Vlastnosti a metody DOM se tedy chovají stejně jako u běžných objektů JavaScript:
- Mohou mít jakoukoli hodnotu.
- Rozlišují se malá a velká písmena (zapište
elem.nodeType
, nikolielem.NoDeTyPe
).
Atributy HTML
V HTML mohou mít značky atributy. Když prohlížeč analyzuje kód HTML, aby vytvořil objekty DOM pro značky, rozpozná standardní atributy a vytváří z nich vlastnosti DOM.
Takže když má prvek id
nebo jiný standard atribut, vytvoří se odpovídající vlastnost. To se ale nestane, pokud je atribut nestandardní.
Například:
<body id="test" something="non-standard">
<script>
alert(document.body.id); // test
// non-standard attribute does not yield a property
alert(document.body.something); // undefined
</script>
</body>
Upozorňujeme, že standardní atribut pro jeden prvek může být pro jiný neznámý. Například "type"
je standardní pro <input>
(HTMLInputElement), ale ne pro <body>
(HTMLBodyElement). Standardní atributy jsou popsány ve specifikaci pro odpovídající třídu prvků.
Tady to můžeme vidět:
<body id="body" type="...">
<input id="input" type="text">
<script>
alert(input.type); // text
alert(body.type); // undefined: DOM property not created, because it's non-standard
</script>
</body>
Pokud je tedy atribut nestandardní, nebude pro něj existovat vlastnost DOM. Existuje způsob, jak získat přístup k těmto atributům?
Tak určitě. Všechny atributy jsou přístupné pomocí následujících metod:
elem.hasAttribute(name)
– kontroluje existenci.elem.getAttribute(name)
– získá hodnotu.elem.setAttribute(name, value)
– nastaví hodnotu.elem.removeAttribute(name)
– odebere atribut.
Tyto metody fungují přesně s tím, co je napsáno v HTML.
Také je možné číst všechny atributy pomocí elem.attributes
:kolekce objektů, které patří do vestavěné třídy Attr s name
a value
vlastnosti.
Zde je ukázka čtení nestandardní vlastnosti:
<body something="non-standard">
<script>
alert(document.body.getAttribute('something')); // non-standard
</script>
</body>
Atributy HTML mají následující vlastnosti:
- V jejich názvu se nerozlišují velká a malá písmena (
id
je stejný jakoID
). - Jejich hodnoty jsou vždy řetězce.
Zde je rozšířená ukázka práce s atributy:
<body>
<div id="elem" about="Elephant"></div>
<script>
alert( elem.getAttribute('About') ); // (1) 'Elephant', reading
elem.setAttribute('Test', 123); // (2), writing
alert( elem.outerHTML ); // (3), see if the attribute is in HTML (yes)
for (let attr of elem.attributes) { // (4) list all
alert( `${attr.name} = ${attr.value}` );
}
</script>
</body>
Poznámka:
getAttribute('About')
– první písmeno je zde velké a v HTML je to celé malé. Ale na tom nezáleží:názvy atributů nerozlišují malá a velká písmena.- Atributu můžeme přiřadit cokoli, ale stane se z něj řetězec. Takže tady máme
"123"
jako hodnotu. - Všechny atributy včetně těch, které jsme nastavili, jsou viditelné v
outerHTML
. attributes
kolekce je iterovatelná a má všechny atributy prvku (standardní i nestandardní) jako objekty sname
avalue
vlastnosti.
Synchronizace atributů vlastností
Když se změní standardní atribut, odpovídající vlastnost se automaticky aktualizuje a (až na některé výjimky) naopak.
V níže uvedeném příkladu id
je upraven jako atribut a můžeme vidět změnu vlastnosti. A pak totéž zpětně:
<input>
<script>
let input = document.querySelector('input');
// attribute => property
input.setAttribute('id', 'id');
alert(input.id); // id (updated)
// property => attribute
input.id = 'newId';
alert(input.getAttribute('id')); // newId (updated)
</script>
Existují však výjimky, například input.value
synchronizuje pouze z atributu → do vlastnosti, ale ne zpět:
<input>
<script>
let input = document.querySelector('input');
// attribute => property
input.setAttribute('value', 'text');
alert(input.value); // text
// NOT property => attribute
input.value = 'newValue';
alert(input.getAttribute('value')); // text (not updated!)
</script>
Ve výše uvedeném příkladu:
- Změna atributu
value
aktualizuje vlastnost. - Změna vlastnosti však atribut neovlivní.
Tato „funkce“ se může ve skutečnosti hodit, protože akce uživatele mohou vést k value
změny a po nich, pokud chceme obnovit „původní“ hodnotu z HTML, je to v atributu.
Vlastnosti DOM jsou zadány
Vlastnosti DOM nejsou vždy řetězce. Například input.checked
vlastnost (pro zaškrtávací políčka) je booleovská:
<input id="input" type="checkbox" checked> checkbox
<script>
alert(input.getAttribute('checked')); // the attribute value is: empty string
alert(input.checked); // the property value is: true
</script>
Existují další příklady. style
atribut je řetězec, ale style
vlastnost je objekt:
<div id="div" style="color:red;font-size:120%">Hello</div>
<script>
// string
alert(div.getAttribute('style')); // color:red;font-size:120%
// object
alert(div.style); // [object CSSStyleDeclaration]
alert(div.style.color); // red
</script>
Většina vlastností jsou však řetězce.
Poměrně zřídka, i když je typem vlastnosti DOM řetězec, může se lišit od atributu. Například href
Vlastnost DOM je vždy úplná URL, i když atribut obsahuje relativní adresu URL nebo jen #hash
.
Zde je příklad:
<a id="a" href="#hello">link</a>
<script>
// attribute
alert(a.getAttribute('href')); // #hello
// property
alert(a.href ); // full URL in the form http://site.com/page#hello
</script>
Pokud potřebujeme hodnotu href
nebo jakýkoli jiný atribut přesně tak, jak je napsán v HTML, můžeme použít getAttribute
.
Nestandardní atributy, datová sada
Při psaní HTML používáme spoustu standardních atributů. Ale co nestandardní, zakázkové? Nejprve se podívejme, zda jsou užitečné nebo ne? K čemu?
Někdy se k předání vlastních dat z HTML do JavaScriptu nebo k „označení“ prvků HTML pro JavaScript používají nestandardní atributy.
Takhle:
<!-- mark the div to show "name" here -->
<div show-info="name"></div>
<!-- and age here -->
<div show-info="age"></div>
<script>
// the code finds an element with the mark and shows what's requested
let user = {
name: "Pete",
age: 25
};
for(let div of document.querySelectorAll('[show-info]')) {
// insert the corresponding info into the field
let field = div.getAttribute('show-info');
div.innerHTML = user[field]; // first Pete into "name", then 25 into "age"
}
</script>
Také je lze použít ke stylizaci prvku.
Například zde u objednávky uveďte atribut order-state
se používá:
<style>
/* styles rely on the custom attribute "order-state" */
.order[order-state="new"] {
color: green;
}
.order[order-state="pending"] {
color: blue;
}
.order[order-state="canceled"] {
color: red;
}
</style>
<div class="order" order-state="new">
A new order.
</div>
<div class="order" order-state="pending">
A pending order.
</div>
<div class="order" order-state="canceled">
A canceled order.
</div>
Proč by bylo použití atributu vhodnější než mít třídy jako .order-state-new
, .order-state-pending
, .order-state-canceled
?
Protože správa atributu je pohodlnější. Stav lze změnit stejně snadno jako:
// a bit simpler than removing old/adding a new class
div.setAttribute('order-state', 'canceled');
Může však nastat problém s vlastními atributy. Co když pro naše účely použijeme nestandardní atribut a později jej standard zavede a přiměje k něčemu? Jazyk HTML je živý, roste a zdá se, že více atributů vyhovuje potřebám vývojářů. V takovém případě může dojít k neočekávaným účinkům.
Aby se předešlo konfliktům, existují atributy data-*.
Všechny atributy začínající na „data-“ jsou vyhrazeny pro použití programátory. Jsou k dispozici v dataset
majetek.
Například, pokud elem
má atribut s názvem "data-about"
, je k dispozici jako elem.dataset.about
.
Takhle:
<body data-about="Elephants">
<script>
alert(document.body.dataset.about); // Elephants
</script>
Víceslovné atributy jako data-order-state
mít velbloudí pouzdro:dataset.orderState
.
Zde je přepsaný příklad „stavu objednávky“:
<style>
.order[data-order-state="new"] {
color: green;
}
.order[data-order-state="pending"] {
color: blue;
}
.order[data-order-state="canceled"] {
color: red;
}
</style>
<div id="order" class="order" data-order-state="new">
A new order.
</div>
<script>
// read
alert(order.dataset.orderState); // new
// modify
order.dataset.orderState = "pending"; // (*)
</script>
Pomocí data-*
atributy je platný a bezpečný způsob předávání vlastních dat.
Vezměte prosím na vědomí, že datové atributy můžeme nejen číst, ale také upravovat. Poté CSS odpovídajícím způsobem aktualizuje pohled:v příkladu nad posledním řádkem (*)
změní barvu na modrou.
Shrnutí
- Atributy – je to, co je napsáno v HTML.
- Vlastnosti – to je to, co je v objektech DOM.
Malé srovnání:
Vlastnosti | Atributy | |
---|---|---|
Typ | Jakákoli hodnota, standardní vlastnosti mají typy popsané ve specifikaci | Řetězec |
Jméno | V názvu se rozlišují velká a malá písmena | V názvu se nerozlišují velká a malá písmena |
Metody pro práci s atributy jsou:
elem.hasAttribute(name)
– zkontrolovat existenci.elem.getAttribute(name)
– získat hodnotu.elem.setAttribute(name, value)
– pro nastavení hodnoty.elem.removeAttribute(name)
– k odstranění atributu.elem.attributes
je sbírka všech atributů.
Pro většinu situací je vhodnější použít vlastnosti DOM. Na atributy bychom měli odkazovat pouze tehdy, když nám vlastnosti DOM nevyhovují, když potřebujeme přesně atributy, například:
- Potřebujeme nestandardní atribut. Ale pokud to začíná
data-
, pak bychom měli použítdataset
. - Chceme číst hodnotu „jak je napsáno“ v HTML. Hodnota vlastnosti DOM se může lišit, například
href
vlastnost je vždy úplná adresa URL a možná budeme chtít získat „původní“ hodnotu.