Closed chemerisuk closed 10 years ago
Hi, Maksim. Your suggestion seems right. But it is useful to have all private properties in a single object in case you are watching for changes in a whole $Element._data
Hey Roman. All data will be stored in the private _data
object as it was before. But I'm curious why do you need to monitor the whole object? Accessing private properties is unsafe and a bad practice in general. Can you use something like below (didn't look at the latest APIs for Object.observe
but you'll get the idea):
var changableObject = {};
el.data("changable", changableObject);
...
Object.observe(el.data("changable"), function(changes) {
// handle the object changes
});
The final syntax that I decided to use in better-dom 2 is like below.
Having
<a id="link" data-test-param="value"></a>
This is how it was in better-dom 1.7.3+:
DOM.find("#link").get("_test-param"); // => "value"
This is how it will be in better-dom 2+:
DOM.find("#link").get("_testParam"); // => "value"
Notice, that I use camel case for the argument key. There are several reasons to use came case:
Reason 1. We treat camel case variables as a JavaScript stuff This is a habit. There are lots of code style guides that encourage to use came case for naming variables. So any such name looks like a stuff related to JavaScript. And it is a good thing, because the main propose of private properties is to be used in code.
Reason 2. We usually use dash-separated names in HTML Variables in camel case is clearly different from dash-separated. It allows to have a better separation between:
DOM.find("#link").get("data-test-param"); // => "value"
that should be treated like a "reading an attribute value", and
DOM.find("#link").get("_testParam"); // => "value"
that actually "reads a private property".
Now despite on returning the same value they are more different from each other.
Writing a code for the DOM often requires to have an extra data associated with an element instance. Therefore better-dom has
$Node.prototype.data
method which provides access to a private key/value map to associate any kind of object with an$Element
.The problem
This method has a useful ability to grab and parse data from
data-*
attributes that have name equal to key in the private key-value map object. For example if we have an element like below:The private key-value map of the element will be automatically populated when you call the
data
method with appropriate keys at the first time:On the one hand this feature is very useful, because saves lines of code. On the other hand it introduces a naming collision with the
get
andset
methods:Having both
foo.data("bar")
andfoo.get("data-bar")
to do similar thing looks confusing.Conflict with the
HTMLElement.dataset
The
data
method behaviour looks similar to what the HTML5dataset
attribute does. But thedataset
attribute has several important differences:data-*
attribute value when appropriate property was changed (that makes it very slow comparing to regular JavaScript objects BTW).So
data
anddataset
have very different behaviour despite on similar names. This introduces a small logical conflict with existing standards.The sense and goals of the
$Node.prototype.data
method is very close to storing private data associated with an$Element
instance. Thats why I've made the phrase private key-value map to be bold several times.Solution
In JavaScript private properties are usually prefixed with the underscore symbol. Why not to use this syntax we are all familiar with that also explains the sense of the method clearer than the
data
word:It looks very clear for me and takes the same number of symbols and a line with
data
word. So in theory you should write programs with the same speed :)Another advantage of this change is that it allows to reduce amount of code, because the
data
method has similar code parts with getter and setter. Also, the newwatch
method can reuse some logic to listen to changes of the private key/value map as well.The change for getter and setter submitted for the 1.7.3, because it won't break anything.
$Node.prototype.data
will be removed in 1.8, the next minor release.