DOM4: Deprecated properties and methods, what does it mean? - javascript

"Warning: In DOM Core 1, 2 and 3, Attr inherited from Node. This is no longer the case in DOM4. In order to bring the implementation of Attr up to specification, work is underway to change it to no longer inherit from Node . You should not be using any Node properties or methods on Attr objects. Starting in Gecko 7.0 (Firefox 7.0 / Thunderbird 7.0 / SeaMonkey 2.4) , the ones that are going to be removed output warning messages to the console. You should revise your code accordingly. See Deprecated properties and methods for a complete list."
Scrolling down the page, we can see replacements for nodeName and NodeValue, using Attr.name and Attr.value.
https://developer.mozilla.org/en/DOM/Attr#Deprecated_properties_and_methods
What does it really mean for other methods like attributes or childNodes?
The reference says it is deprecated but they don't give any replacement!
It is deprecated for an Attribute but is it for a Node too?
Attr object: http://www.w3schools.com/jsref/dom_obj_attr.asp
Edit: nodeValue will ONLY be deprecated for Attributes (Attr) since Attr will not inherit from a Node anymore in DOM Level 4:
Here's a quick example that helped me to understand:
<div id="myAttribute">myTextNode</div>
var myDiv = document.getElementById("myAttribute");
// If you want to get "myAttribute" from div tag
alert(myDiv.attributes[0].value);
// Correct way to get value of an attribute (displays "myAttribute")
alert(myDiv.attributes[0].nodeValue);
// Working too but deprecated method for Attr since it doesn't inherit from Node in DOM4 (.nodeValue is specific to a Node, not an Attribute)
// If you want to get "myTextNode" from div tag
alert(myDiv.childNodes[0].value);
// Not working since .value is specific to an attribute, not a Node (displays "undefined")
alert(myDiv.childNodes[0].nodeValue);
// Working, .nodeValue is the correct way to get the value of a Node, it will not be deprecated for Nodes! (displays "myTextNode")
Maybe this will avoid confusion to others when accessing Attributes/Nodes :)

What they are saying is that objects that were Attr instances (e.g. such as those returned by Element.getAttributeNode()), used to have properties that it inherited from Node.
However, because this is not the case in DOM4, they are trying to remove this inheritance. Because of this, when you now get an instance of a Attr object, the properties listed in the deprecated list will behave as they're documented.
The big question: It is deprecated for an Attribute but is it for a Node too?: No, they are not deprecated. You can see the list of properties Node has from it's own documentation page.
Attr objects aren't used much (ever?) anyway; are you sure this concerns you?

Related

removeChild, textContent and appendChild are deprecated. Alternatives?

I ask this question based on the following link: https://developer.mozilla.org/en-US/docs/Web/API/Attr
I see so many developers use these methods and honestly I am not entirely sure if they are really deprecated as a whole or just in a certain context. Either way, it does list them as deprecated, which is why im asking: what valid and up-to-date alternatives are there? Specifically for:
removeChild, textContent, appendChild. Even insertBefore is deprecated.
My guess is that you are confusing node objects and attribute objects. The functions you named are commonly used with the former, but not the latter. The MDN article is only describing attribute objects.
For more information:
A <div> is a node, and it could have an attribute data-foo="bar" on it.
It is common to append children or modify text to a node. For example, given:
var node = document.createElement('div');
node.innerHTML = '<p>Hello</p><p> World</p>';
node.removeChild(node.firstChild);
would produce HTML of <div><p> World</p></div>
However, this doesn't really make sense for attributes. Attributes are essentially just strings attached to a node. The common actions that are used with attributes are name and value. For example:
var node = document.createElement('div');
node.setAttribute('data-foo', 'bar');
var attr = node.getAttributeNode('data-foo');
console.log(attr.name); // prints 'data-foo'
console.log(attr.value); // prints 'bar'
console.log(typeof attr); // prints 'object'
At least personally, I have rarely had use for the Attr object, instead node.getAttribute('data-foo') returns a string of bar, and that is sufficient for my needs.
As to why those methods exist in the first place on attr objects, I will simply copy/paste from the MDN article you linked:
Warning: In DOM Core 1, 2 and 3, Attr inherited from Node. This is no longer the case in DOM4. In order to bring the implementation of Attr up to specification, work is underway to change it to no longer inherit from Node. You should not be using any Node properties or methods on Attr objects.

Why are directly assigned attributes ignored by document.querySelector()?

I've recently discovered a very fundamental difference between the 2 methods of setting custom DOM attributes in Javascript. The difference is in how the HTML5 Selectors API interacts with those attributes (ie, in document.querySelector() and friends).
<button id="b3">View</button>
<script>
document.getElementById('b3').shape = 'square';
console.log( document.querySelector('*[shape]') ); // FAIL: returns null
document.getElementById('b3').setAttribute('shape','square');
console.log( document.querySelector('*[shape]') ); // WORKS: returns element
</script>
So basically if you apply attributes to an element without using .setAttribute() then you cannot later select the element by the attribute name.
BTW. This behaviour is consistent across browsers which makes me think it might be addressed by the standard, however I can't see it:
http://www.w3.org/TR/css3-selectors/#attribute-selectors
http://www.w3.org/TR/selectors-api/
The selectors API standard doesn't appear to care:
Selectors allow the representation of an element's attributes. When a
selector is used as an expression to match against an element,
attribute selectors must be considered to match an element if that
element has an attribute that matches the attribute represented by the
attribute selector.
The entire attribute matching rule seems to boil down to "if the element has an attribute" and you would think that someElement.someAttribute = something would meet the criteria of "having an attribute" but for whatever reason it doesn't.
My question is basically why the difference? Is it actually part of a standard or just an identical implementation quirk in all the major browsers (IE11, FF38 and Chrome 43)?
The reason is very simple - getElementById and all of those kind return an Element Object (see specs: http://www.w3schools.com/jsref/met_document_getelementbyid.asp)
Which means you set property shape on an object. Then you try to do a query selector, but you haven't modified the html that's queried. They are different things.

JavaScript document.getElementById(“id”) and element id attribute

I have:
<div id="myDiv1"></div>
<div id="myDiv2"></div>
In JavaScript, I can set div innerHTML by writing:
myDiv1.innerHTML = "myDiv1, Hi!"
or
document.getElementById("myDiv2").innerHTML = "myDiv2, Hi!"
Why should I use document.getElementById when I can simply use element Id ? Is this working every time or only in some special scenarios (like simple sample)?
thanks,
Mike
Why should I use document.getElementById when I can simply use element Id ?
To avoid conflicts. The global namespace on browsers is incredibly crowded, all sorts of things are dumped in there, including (as you've found) globals referring to any element with an id (so-called "automatic globals").
In contrast, getElementById only does what it says, finds an element by its id; it's more constrained. (Other than bugs in old versions of IE, which also looked at elements with name attributes.)
when you write
myDiv1.innerHTML = "myDiv1, Hi!"
you are calling window object, so actual call is like this
window.myDiv1.innerHTML = "myDiv1, Hi!"
This behavior is deprecated now and to be avoided. Instead we should use
document.getElementById`

Why does cloneNode exclude custom properties?

This is related to the question javascript cloneNode and properties.
I'm seeing the same behaviour. Node.cloneNode does not copy over any properties that I add myself (code from original post):
var theSource = document.getElementById("someDiv")
theSource.dictator = "stalin";
var theClone = theSource.cloneNode(true);
alert(theClone.dictator);
theClone does not contain any property "dictator".
I haven't been able to find any explanation for why this is the case. The documentation on MDN states that cloneNode "copies all of its attributes and their values", a line which is taken directly from the DOM specification itself.
This seems broken to me as it makes it next to impossible to do a deep copy of a DOM tree that contains custom properties.
Am I missing something here?
A property is not equal to an attribute.
Use setAttribute() and getAttribute() instead.
var theSource = document.getElementById("someDiv")
theSource.setAttribute('dictator','stalin');
var theClone = theSource.cloneNode(true);
alert(theClone.getAttribute('dictator'));
Not every property corresponds to an attribute. Adding a custom property to an element does not add an attribute, so what happens when you do that is not covered by the DOM spec.
In fact, what happens when you add a property to a host object (such as a DOM node) is completely unspecified and is by no means guaranteed to work, so I'd strongly recommend against doing it. Instead, I'd suggest using wrappers if you want to extend the functionality of host objects (as jQuery and many other libraries do).
Tested this. cloneNode does include the custom attribute in the clone, but that attribute can't be retrieved directly. Try:
var theSource = document.getElementById("someDiv")
theSource.dictator = "stalin";
//or better / more cross browser compatible
theSource.setAttribute('dictator','stalin');
var theClone = theSource.cloneNode(true);
alert(theClone.getAttribute('dictator')); //so, use getAttribute
It may be a browser problem with cloning expando properties. I ran a testcase (see later) from this rather old bugzilla report. It didn't work in Chrome and Firefox (both latest versions).
//code from testcase # bugzilla
var a = document.createElement("div");
a.order = 50;
alert(a.order);
b = a.cloneNode(true);
alert(b.order);

Sometimes object.setAttribute(attrib,value) isn't equivalent to object.attrib=value in javascript?

It appears that sometimes object.setAttribute(attrib,value) isn't equivalent to object.attrib=value in javascript?
I've got the following code, which works fine:
var lastMonthBn = document.createElement('input');
lastMonthBn.value='<'; // This works fine
lastMonthBn.type='button'; // This works fine
But the following code doesn't:
var div = document.createElement('div');
div.class = 'datepickerdropdown'; // No luck here!
So i need to use the following:
div.setAttribute('class','datepickerdropdown');
My question is, why? From reading this, I thought that object.setAttribute(blah,value) was the same as object.blah=value??
Properties and Attributes aren't really the same, however the DOM exposes standard attributes through properties.
The problem you're facing specifically with the class attribute is that class is a future reserved word.
In some implementations the use of a future reserved word can cause a SyntaxError exception.
For that reason, the HTMLElement DOM interface provides a way to access the class attribute, through the className property:
var div = document.createElement('div');
div.className = 'datepickerdropdown';
Remember, attributes aren't the same as properties, for example:
Immagine a DOM element that looks like this:
<div></div>
If you add a custom attribute to it, e.g.:
myDiv.setAttribute('attr', 'test');
An attribute will be added to the element:
<div attr="test"></div>
Accessing attr as a property on the div element, will simply give you undefined (since is not a property).
myDiv.foo; // undefined
If you bind a property to an element, e.g.:
myDiv.prop = "test";
The getAttribute method will not be able to find it, (since is not an attribute):
myDiv.getAttribute('test'); // null
Note: IE wrongly messes up attributes and properties. :(
As I've said before, the DOM exposes standard attributes as properties, but there are some exceptions that you'll have to know:
The class attribute, is accessible through the className property (the problem you have).
The for attribute of LABEL elements, is accessible through the htmlFor property (collides with the for statement).
Attributes are case-insensitive, but the language bindings for JavaScript properties are not, so the convention is to use the names is camelCase to access attributes through properties, for example the ones formed by two words, e.g. cellSpacing, colSpan, rowSpan, tabIndex, maxLength, readOnly frameBorder, useMap.
It should be noted that browsers like Safari will NOT run JavaScript if keywords like "class" or "int" are present.
So it's a cross-browser support sort of thing. "class" is present in JS2.0 [I believe a package system is available there too]
...
I should also note that in IE, setAttribute [for non-class things, since setAttribute should be use-able for other members such as "style"] can be glitchy.

Categories