# Attributes and properties When the browser loads the page, it "reads" (another word: "parses") the HTML and generates DOM objects from it. For element nodes, most standard HTML attributes automatically become properties of DOM objects. For instance, if the tag is `
`, then the DOM object has `body.id="page"`. But the attribute-property mapping is not one-to-one! In this chapter we'll pay attention to separate these two notions, to see how to work with them, when they are the same, and when they are different. ## DOM properties We've already seen built-in DOM properties. There's a lot. But technically no one limits us, and if it's not enough -- we can add our own. DOM nodes are regular JavaScript objects. We can alter them. For instance, let's create a new property in `document.body`: ```js run document.body.myData = { name: 'Caesar', title: 'Imperator' }; alert(document.body.myData.title); // Imperator ``` We can add a method as well: ```js run document.body.sayTagName = function() { alert(this.tagName); }; document.body.sayTagName(); // BODY (the value of "this" in the method is document.body) ``` We can also modify built-in prototypes like `Element.prototype` and add new methods to all elements: ```js run Element.prototype.sayHi = function() { alert(`Hello, I'm ${this.tagName}`); }; document.documentElement.sayHi(); // Hello, I'm HTML document.body.sayHi(); // Hello, I'm BODY ``` So, DOM properties and methods behave just like those of regular JavaScript objects: - They can have any value. - They are case-sensitive (write `elem.nodeType`, not `elem.NoDeTyPe`). ## HTML attributes In HTML, tags may have attributes. When the browser parses the HTML to create DOM objects for tags, it recognizes *standard* attributes and creates DOM properties from them. So when an element has `id` or another *standard* attribute, the corresponding property gets created. But that doesn't happen if the attribute is non-standard. For instance: ```html run ``` Please note that a standard attribute for one element can be unknown for another one. For instance, `"type"` is standard for `` ([HTMLInputElement](https://html.spec.whatwg.org/#htmlinputelement)), but not for `` ([HTMLBodyElement](https://html.spec.whatwg.org/#htmlbodyelement)). Standard attributes are described in the specification for the corresponding element class. Here we can see it: ```html run ``` So, if an attribute is non-standard, there won't be a DOM-property for it. Is there a way to access such attributes? Sure. All attributes are accessible by using the following methods: - `elem.hasAttribute(name)` -- checks for existence. - `elem.getAttribute(name)` -- gets the value. - `elem.setAttribute(name, value)` -- sets the value. - `elem.removeAttribute(name)` -- removes the attribute. These methods operate exactly with what's written in HTML. Also one can read all attributes using `elem.attributes`: a collection of objects that belong to a built-in [Attr](https://dom.spec.whatwg.org/#attr) class, with `name` and `value` properties. Here's a demo of reading a non-standard property: ```html run ``` HTML attributes have the following features: - Their name is case-insensitive (`id` is same as `ID`). - Their values are always strings. Here's an extended demo of working with attributes: ```html run ``` Please note: 1. `getAttribute('About')` -- the first letter is uppercase here, and in HTML it's all lowercase. But that doesn't matter: attribute names are case-insensitive. 2. We can assign anything to an attribute, but it becomes a string. So here we have `"123"` as the value. 3. All attributes including ones that we set are visible in `outerHTML`. 4. The `attributes` collection is iterable and has all the attributes of the element (standard and non-standard) as objects with `name` and `value` properties. ## Property-attribute synchronization When a standard attribute changes, the corresponding property is auto-updated, and (with some exceptions) vice versa. In the example below `id` is modified as an attribute, and we can see the property changed too. And then the same backwards: ```html run ``` But there are exclusions, for instance `input.value` synchronizes only from attribute -> to property, but not back: ```html run ``` In the example above: - Changing the attribute `value` updates the property. - But the property change does not affect the attribute. That "feature" may actually come in handy, because the user actions may lead to `value` changes, and then after them, if we want to recover the "original" value from HTML, it's in the attribute. ## DOM properties are typed DOM properties are not always strings. For instance, the `input.checked` property (for checkboxes) is a boolean: ```html run checkbox ``` There are other examples. The `style` attribute is a string, but the `style` property is an object: ```html run