NamedNodeMap#
NamedNodeMap.setNamedItem()#
Metoda setNamedItem()
dodaje lub zastępuje pasujący pod względem przestrzeni nazw i nazwy lokalnej istniejący atrybut przekazanym atrybutem w liście atrybutów skojarzonej z daną mapą nazwanych atrybutów i w zależności od sytuacji zwraca odpowiednie wartości.
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
var return_attr = namedNodeMap.setNamedItem(attr);
gdzie poszczególne człony oznaczają:
- return_attr - referencja do zastąpionego atrybutu w liście atrybutów lub wartość
null
. - namedNodeMap - mapa nazwanych atrybutów będąca obiektem kontekstu.
- attr - referencja do ustawianego atrybutu w liście atrybutów.
Algorytm wywołania metody setNamedItem(attr)
nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
- Zwróć wynik ustawiania atrybutu z przekazaniem attr oraz elementu skojarzonego z obiektem kontekstu. Zrzuć ponownie każdy wyjątek.
Analizując dokładnie wszystkie powiązane z metodą setNamedItem()
algorytmy można dojść do następujących wniosków:
- Ustawienie atrybutu, który jest skojarzony z innym elementem niż element skojarzony z mapą nazwanych atrybutów, zwraca błąd.
- Ustawienie atrybutu, który już istniał w liście atrybutów (ten sam obiekt) zwróci jedynie referencję do tego atrybut (bez usuwania i zaobserwowania zmian).
- Ustawienie atrybutu, który już istniał w liście atrybutów (różne obiekty), usuwa także poprzedni atrybut i zwraca referencje do usuniętego atrybutu. Zasady dopasowywania atrybutów dotyczą ich przestrzeni nazw oraz nazw lokalnych. Nowy atrybut zastępuje poprzedni atrybut w jego oryginalnym miejscu, co oznacza, że kolejność atrybutów w elemencie nie ulega zmianie.
- Ustawienie atrybutu, którego nie było w liście atrybutów, zwróci wartość
null
.
Alternatywnie można skorzystać z identycznie działających metod NamedNodeMap.setNamedItemNS()
, Element.setAttributeNode()
lub Element.setAttributeNodeNS()
. Taka szeroka wymienność jest ukłonem w stronę przeglądarek Chrome, Safari i Edge, które nigdy nie zaimplementowały wspomnianych metod zgodnie z wymogami poprzednich specyfikacji DOM, co w ostateczności doprowadziło do zmiany tych wymagań w obecnej specyfikacji DOM4 (DOM - Bug 117).
Prosty przykład:
<!DOCTYPE html>
<html>
<head>
<script>
window.onload = function(){
p = document.getElementsByTagName("p")[0]; // referencja do akapitu
p.setAttributeNS("www.test1.com", "ID", "Test1");
p.setAttributeNS("www.test2.com", "Class", "Test2");
p.setAttribute("id", "Identyfikator");
p.className = "Klasa1 Klasa2 Klasa3";
p.setAttributeNS("www.test3.com", "A:NEW", "Test3");
p.setAttributeNS("www.test4.com", "a:new", "Test4");
allAttr = p.attributes;
var info = document.getElementById("info");
}
function outputAttributes(){
var allAttrLen = allAttr.length;
var allAttrData = "";
for (var i = 0; i < allAttrLen; i++){
var thisAttr = allAttr[i];
allAttrData += "<br>" + thisAttr.namespaceURI + " " + thisAttr.prefix + " " + thisAttr.localName + " " + thisAttr.name;
}
return allAttrData;
}
function createAndSet(namespace, name, variant){
try{
var new_attr;
if (variant == 0){
new_attr = document.createAttributeNS(namespace, name);
}
else if (variant == 1){
new_attr = info.attributes[0];
}
else if (variant == 2){
new_attr = allAttr[0];
}
var beforeChange = outputAttributes();
var beforeChangeLen = allAttr.length;
var return_attr = allAttr.setNamedItem(new_attr);
info.innerHTML = "Interfejs mapy nazwanych atrybutów: " + allAttr // [object NamedNodeMap]
+ "<br>" + "Właściwość length (przed zmianą): " + beforeChangeLen
+ "<br>" + "Właściwość length (po zmianie): " + allAttr.length
+ "<br><br>" + "Interfejs nowego atrybutu: " + new_attr
+ "<br>" + "Właściwość namespaceURI: " + new_attr.namespaceURI
+ "<br>" + "Właściwość prefix: " + new_attr.prefix
+ "<br>" + "Właściwość localName: " + new_attr.localName
+ "<br>" + "Właściwość name: " + new_attr.name
+ "<br>" + "Właściwość value: " + new_attr.value;
if (return_attr){
info.innerHTML += "<br><br>" + "Interfejs zwróconego atrybutu: " + return_attr
+ "<br>" + "Właściwość namespaceURI: " + return_attr.namespaceURI
+ "<br>" + "Właściwość prefix: " + return_attr.prefix
+ "<br>" + "Właściwość localName: " + return_attr.localName
+ "<br>" + "Właściwość name: " + return_attr.name
+ "<br>" + "Właściwość value: " + return_attr.value
+ "<br><br>" + "Nowy atrybut == Zwrócony atrybut: " + (new_attr == return_attr);
}
else{
info.innerHTML += "<br><br>" + "Atrybutu nie było w liście atrybutów i metoda zwróciła: " + return_attr;
}
info.innerHTML += "<br><br>" + "Wykaz wszystkich atrybutów przed zmianą (przestrzeń nazw|prefiks|nazwa lokalna|nazwa kwalifikowana):";
info.innerHTML += beforeChange;
info.innerHTML += "<br><br>" + "Wykaz wszystkich atrybutów po zmianie (przestrzeń nazw|prefiks|nazwa lokalna|nazwa kwalifikowana):";
info.innerHTML += outputAttributes();
}
catch(e){
info.innerHTML = "Wyjątek: " + e;
}
}
</script>
</head>
<body>
<p>Akapit z atrybutami ustawianymi z poziomu skryptu:</p>
<ul>
<li>p.setAttributeNS("www.test1.com", "ID", "Test1");</li>
<li>p.setAttributeNS("www.test2.com", "Class", "Test2");</li>
<li>p.setAttribute("id", "Identyfikator");</li>
<li>p.className = "Klasa1 Klasa2 Klasa3";</li>
<li>p.setAttributeNS("www.test3.com", "A:NEW", "Test3");</li>
<li>p.setAttributeNS("www.test4.com", "a:new", "Test4");</li>
</ul>
<p>Kliknij przycisk by ustawić określony atrybut w liście atrybutów akapitu.</p>
<input type="button" value="setNamedItem(attr['','id'])" onclick="createAndSet('','id',0)">
<input type="button" value="setNamedItem(attr['ns1','id'])" onclick="createAndSet('ns1','id',0)">
<input type="button" value="setNamedItem(attr['ns2','ID'])" onclick="createAndSet('ns2','ID',0)">
<input type="button" value="setNamedItem(attr[null,'Class'])" onclick="createAndSet(null,'Class',0)">
<input type="button" value="setNamedItem(attr['www.test3.com','A:NEW'])" onclick="createAndSet('www.test3.com','A:NEW',0)">
<input type="button" value="setNamedItem(attr['ns3','A:NEW'])" onclick="createAndSet('ns3','A:NEW',0)">
<input type="button" value="setNamedItem(attr['www.test3.com','a:new'])" onclick="createAndSet('www.test3.com','a:new',0)">
<input type="button" value="setNamedItem(attr['ns4','Fresh'])" onclick="createAndSet('ns4','Fresh',0)">
<input type="button" value="setNamedItem(attr z p)" onclick="createAndSet('','',1)">
<input type="button" value="setNamedItem(attr z innego p)" onclick="createAndSet('','',2)">
<p style="color: blue;">Szczegółowe informacje dla ustawionych atrybutów:</p>
<p id="info"></p>
</body>
</html>
Na chwilę obecną jedynie przeglądarka Firefox obsługuje metodę setNamedItem()
zgodnie z najnowszymi wymaganiami specyfikacji DOM4. Pozostałe przeglądarki mają mniejsze lub większe problemy w tym obszarze.
Składnia Web IDL#
[LegacyUnenumerableNamedProperties] interface NamedNodeMap { Attr? setNamedItem(Attr attr); }