-
Notifications
You must be signed in to change notification settings - Fork 35
Getter and setter
Unlike many others in better-dom there is no concepts like element attributes and element properties. Just to remind why vanilla DOM is total mess assuming we have element like below on the page:
<a href="/chemerisuk/better-dom" id="foo" data-attr="test">better-dom</a>
Now let's check what every entity returns:
var vanillaFoo = document.getElementById("foo");
vanillaFoo.href; // => "https://github.com/chemerisuk/better-dom"
vanillaFoo.getAttribute("href"); // => "/chemerisuk/better-dom"
vanillaFoo["data-attr"]; // => undefined
vanillaFoo.getAttribute("data-attr"); // => "test"
As we see from the example:
- method
getAttribute
always returns exact string that an element has in markup - property with the same name on the other hand can exist or not
- if a property exist, it may have a special behavior, therefore result value can be different from what you have in markup
Similar logic applies to setAttribute
. A bit complicated, isn't it?
In better-dom, things are clearer. Every element has only two methods: $Element#get
and $Element#set
.
var foo = DOM.find("#foo");
foo.get("href"); // => "https://github.com/chemerisuk/better-dom"
foo.get("data-attr"); // => "test"
Algorithm is simple: if an element has a property with an appropriate name, it's returned as a result. Otherwise an attribute value is returned.
Native DOM doesn't have a concept private data storage associated with a particular element. Well, it has dataset
in HTML5, but that property touches the DOM and introduces unnecessary side effects, therefore it's slow.
In JavaScript we usually use _
(underscore) symbol to mark private data. Why can't we use the same syntax for $Element
too:
foo.set("_bar", "hello");
foo.get("_bar"); // => "hello"
foo.get("_unknown"); // => undefined
If there is no such private property the library tries to parse appropriate data-*
attribute. Parsing of JSON attributes supported as well. For instance, if we have attributes like below:
data-simple="value"
data-obj-attr=`{"a": "b"}`
Those value can be read using calls like below:
foo.get("_simple"); // => "value"
foo.get("_objAttr"); // => {a: "b"}
Note: for private properties you have to use camel cased syntax which will be used to find the appropriate dash-separated attribute name.
Vanilla DOM has a concept of empty elements. Those elements have an important difference from regular: they can't have child nodes. Check an example below:
var vanillaDiv = document.createElement("div");
vanillaDiv.innerHTML = "<b>hello</b>";
vanillaDiv.innerHTML; // => "<b>hello</b>"
vanillaDiv.value = "<b>hello</b>";
vanillaDiv.value; // => undefined
Now try the same with <input>
:
var vanillaInput = document.createElement("input");
vanillaInput.innerHTML = "<b>hello</b>";
vanillaInput.innerHTML; // => ""
vanillaInput.value = "<b>hello</b>";
vanillaInput.value; // => "<b>hello</b>"
In better-dom this problem is solved using a 'value' shortcuts, e.g. when $Element#get
or $Element#set
method is called without passing the first argument:
var div = DOM.create("div");
var input = DOM.create("input");
div.set("<b>hello</b>");
div.get(); // => "<b>hello</b>"
input.set("<b>hello</b>");
input.get(); // => "<b>hello</b>"
Much simpler, isn't it? If you need to specify which property you want to access, you can always pass the name:
div.get("innerHTML"); // => "<b>hello</b>"
div.get("value"); // => undefined
input.get("value"); // => "<b>hello</b>"
input.get("innerHTML"); // => ""
In other words you can use $Element#get()
and $Element.set(String)
to make accessing to inner content to be consistent.