Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design reason behind the relationship between element's property and its corresponding attribute

I'm puzzled by the reason behind how the relationship between some DOM element's property and its corresponding attributes works.

Below is a graph from the book jquery in action 2015 Bear Bibeault, showing the relationship between property and attribute of DOM element.

enter image description here

To further explain the concept, the author had the following code and explanation for the code.

enter image description here

enter image description here

My question is, why some property and attribute are synced, why some are not synced, and why some attributes does not have corresponding property?

I have found a great post explaining the relationship between property and attribute, but it didn't touch on why it was designed this way. I hope to understand the reasons behind the design.

A related question, if I want to get or set a value on a DOM element, should I get/set the property or the attribute?

And how do we find the relationship between a particular property and its corresponding attribute when we need to? Is there a documentation specifically detailing the relationship?

like image 641
Thor Avatar asked Mar 13 '18 02:03

Thor


People also ask

What is the difference between attributes and property?

An attribute is a quality or character ascribed to or considered to belong to, or be inherent in, a person or thing. A property is a quality or characteristic belonging to a person or thing, with its original use implying ownership, and also either being essential or special.

What is the difference between property and attribute in CSS?

The attributes have a data type of string. So no matter the value of the attribute, it will always return a string. Property: In contrast to the attributes, which are defined in HTML, properties belong to the DOM. Since DOM is an object in JavaScript, we can get and set properties.

What are the properties of a HTML element attribute?

Once the browser parses this code, a HTMLInputElement object will be created, and this object will contain dozens of properties like: accept, accessKey, align, alt, attributes, autofocus, baseURI, checked, childElementCount, childNodes, children, classList, className, clientHeight, etc.


2 Answers

DOM is something that has grown "naturally" to a large degree. You have to consider, HTML (meaning: attributes) came first and originally there was no scripting whatsoever. Eventually, Netscape introduced JavaScript with what you would consider an extremely limited API today. This API was geared towards manipulating forms, not really arbitrary HTML elements. And then Netscape and Internet Explorer came out with different variants of what they called DHTML back then (Dynamic HTML). Netscape's variant relied on a special <layer> tag and nobody remembers it today. The Internet Explorer variant allowed more generic access to HTML elements and in particular had a 1:1 mapping of attributes to properties.

While Internet Explorer won this war, its DHTML variant was designed when people were thinking of HTML attribute names as a fixed collection. With arbitrary attributes, it had too many issues. For example:

  • The class attribute could not be mapped to JavaScript originally because class is a reserved keyword. While subsequent changes to the JavaScript standard allowed using reserved keywords as property names, Internet Explorer has to map class attribute to the className property. Setting className attribute on an element or el["class"] property on a JavaScript object resulted in hilarious inconsistencies.
  • HTML attributes are case-insensitive whereas JavaScript properties are case-sensitive. So Internet Explorer had all kinds of hacks to recognize intent. What happened when the element was <FOO SOMEATTIRIBUTE> and you tried to access el.someAttribute or el.SOMEATTRIBUTE from JavaScript? I no longer remember, but it wasn't pretty.
  • JavaScript objects always have methods as well. An attribute toString for example cannot possibly be mapped to a property because it would mask the toString() method.

No browser other than Internet Explorer ever implemented this 1:1 mapping of attributes to properties, and even Internet Explorer gave up on it as soon as it was feasible in terms of backwards compatibility (this took a very long time). Instead, attributes and properties are treated as separate namespaces now. Browsers will provide you with some properties as shortcuts for attribute access and manipulation, but they are really only there for your convenience. And there are some backwards compatibility cases muddying the waters: the value property and value attribute are not actually mapped to each other, the former reflecting the current state of the element whereas the latter reflects its initial state.

Edit: Just for reference, you are quoting the following statement:

If attribute exists as a built-in property but it's a Boolean, the value isn't synchronized.

This is wrong, the behavior has nothing to do with booleans vs. strings. As mentioned above, the value property is similarly missing synchronization as the checked property. On the other hand, the boolean hidden property will be synced with the corresponding attribute properly. From what I can tell, you will find missing sync between property and attribute around the original form manipulation APIs that have been introduced by Netscape - this is simply backwards compatibility.

So maybe you shouldn't trust people who write books on jQuery with DOM questions. After all, these explicitly chose to quit touching the DOM directly and opted for an entirely different representation with its very own set of quirks.

like image 174
Wladimir Palant Avatar answered Sep 30 '22 15:09

Wladimir Palant


You will find the answers buried inside HTML specs. I first want you to have a look at the attributes and properties of the input element (heading "Content attributes" and "DOM interface") and the section about attribute reflection (first paragraph).

You will notice that all attributes have corresponding properties and manipulating a property will change the attribute it reflects. It is worth noting that:

(1) An attribute could be reflected by a property with a slightly different name. The classical example is the class attribute which is reflected by className property and for attribute which is reflected by htmlFor property.

(2) Likewise the checked attribute is reflected by defaultChecked property whereas the checked property represents the internal state of the checkbox irrespective of the checked attribute. This has always caused confusion among programmers (and book authors). The difference is explained at the end of this answer.

(3) Made-up attributes (such as the "book" attribute in your example) will not generate corresponding property and vice-versa. For this purpose the HTML specs describe a mechanism called data attributes and dataset property.

A related question, if I want to get or set a value on a DOM element, should I get/set the property or the attribute?

Depends. For example both of the following produce identical result and HTML:

document.getElementById("div-1").title = "Hello";
document.getElementById("div-1").setAttribute("title") = "Hello";

However, for form elements you should manipulate the state instead of attribute. Suppose you have this HTML markup:

<input type="checkbox" id="checkbox-1">

And you execute either of the following:

document.getElementById("checkbox-1").defaultChecked = true;
document.getElementById("checkbox-1").setAttribute("checked", "checked");

And here is the result:

<input type="checkbox" id="checkbox-1" checked="checked">

But whether the checkbox actually get checked depends on the dirtiness of the control (i.e. if its state was changed at some point). For form elements you would normally manipulate the properties that correspond to the internal state:

document.getElementById("checkbox-1").checked = true;
like image 43
Salman A Avatar answered Sep 30 '22 15:09

Salman A