Html ids are kind of the antithesis of good web application development. When you use reusable components, having IDs anywhere immediately either makes your component non-reusable, or forces you to manage a unique set of ids, which is bad for code maintenance and can easily introduce errors.
Aria-owns seems to require the use of ids. I would have assumed there would be a way to specify an a11y relationship in javascript with bare dom node references, but I can't seem to find anything like that.
Is there any way of avoiding ids if you want to use accessibility features like aria-owns?
Shadow DOM is a good way to include web components while avoiding id attributes overlapping.
The DOM shadow boundary would prevent any problem while still enabling screenreaders to parse the accessibility tree
No. HTML attributes can't use JS references.
IDs are the standard means to identify an element.
Generate a unique ID for the elements you need to reference: You already have a DOM reference in your JS to set it on.
Related
JavaScript lets you add arbitrary properties and methods to any object, including DOM nodes. Assuming the property was well namespaced (something like _myLib_propertyName) so that it would be unlikely to create a conflict, are there any good reasons not to stash data in DOM nodes?
Are there any good use cases for doing so?
I imagine doing this frequently could contribute to a sloppy coding style or code that is confusing or counter-intuitive, but it seems like there would also be times when tucking "custom" properties into DOM nodes would be an effective and expedient technique.
No, it is usually a bad idea to store your own properties on DOM nodes.
DOM nodes are host objects and host objects can do what they like. Specifically, there is no requirement in the ECMAScript spec for host objects to allow this kind of extension, so browsers are not obliged to allow it. In particular, new browsers may choose not to, and existing code relying on it will break.
Not all host objects in existing browsers allow it. For example, text nodes and all ActiveX objects (such as XMLHttpRequest and XMLDOM objects, used for parsing XML) in IE do not, and failure behaviour varies from throwing errors to silent failure.
In IE, the ability to add properties can be switched off for a whole document, including all nodes within the document, with the line document.expando = false;. Thus if any of the code in your page includes this line, all code relying on adding properties to DOM nodes will fail.
I think more than anything, the best reason not to store data in the DOM is because the DOM is meant to represent content structure and styling for an HTML page. While you could surely add data to the nodes in a well-namespaced manner as to avoid conflicts, you're introducing data state into the visual representation.
I'm trying to find an example for or against storing data in the DOM, and scratching my head to find a convincing case. In the past, I've found that the separation of the data state from the visual state has saved headache during re-designs of sites I've worked on.
If you look at HTML 5 there is the data attribute for fields that will allow you to store information for the field.
Don't be surprised to run into trouble with IE 6 & 7. They are very inconsistent with setAttribute vs set as a property.
And if you're not careful you could set circular references and give yourself a memory leak.
http://www.ibm.com/developerworks/web/library/wa-memleak/
I always set node properties as a last resort, and when I do I'm extra careful with my code and test more heavily than usual.
For what it's worth, the D3.js library makes extensive use of custom properties on DOM nodes. In particular for the following packages that introduce interaction behaviors:
https://github.com/d3/d3-zoom - the __zoom property
https://github.com/d3/d3-brush - the __brush property
D3 also provides a mechanism for putting your own custom properties on DOM elements called d3.local. The point of that utility is to generate property names that are guaranteed not to conflict with the DOM API.
The primary risk I can see associated with custom properties on DOM nodes is accidentally picking a name that already has some meaning in the DOM API. If you use d3.local or maybe prefix everything with __, that should avoid conflicts.
We use dojo/parser on our application to parse html produced by our server side templating language using the dojo-data-type attribute.
One common thing we need to do is access a node that's part of the modules' domNode to do something with. We've come up with a unique id method for id'ing the nodes we want, but that leaves me uneasy for various reasons.
the _templated mixin allows you to define 'attach-points' in templates that get attached to the object instance. Does something like this exist for for the parser, so a node can be easily identified by the module code?
If not, what's the best way to parse the module's domNode to find these important child nodes, especially avoiding child nodes that belong to another (child) module's domNode?
No, attach-point is not supported in the parser. That is a Dijit template thing.
Using an ID will work, but that runs the risk of duplicate IDs and things will break. I'd suggest using classNames and finding your nodes with dojo.query.
If the attachable items are other Dijits, you can access them with widget.getChildren();
If you are not using all the features of dojo.parser (there a lot that I don't use) you could build your own. I built one, and it's shocking how tiny it is compared to Dojo's. Note that mine has just been created and has had very little testing, so this is just for reference. https://github.com/clubajax/dx-ui/blob/master/util/parser.js
I need to keep the state of my Html control (I've a multi select list and I need to keep the info about selected items), for which I'm using a custom attribute like:
// put
$("#element").attr("selectionState", "value");
// get
alert($("#element").attr("selectionState"));
While it works, I wonder if it's a safe approach and if not, how would you solve the problem?
The only risk I can see is - another script creating custom attributes with the same names, which is something I can manage.
I suggest using .data() instead.
$('#element').data('selectionState', 'value');
It's definitely safer, as it keeps the data completely in JavaScript instead of the "attributes" maps in the DOM elements. Sins ".data()" is all JavaScript, you can store anything there, including functions and closures. (I guess you could do that with ".attr()" too but it's pretty risky in IE, which, in old versions at least, had quite different storage management internally for DOM and for JScript.)
The namespace problem you allude to is of course the same, as would be the possible ways of managing it.
Is it considered good practice to use DOM Element's getAttribute/setAttribute calls to associate additional information about contents of the element ?
For example I want to call setAttribute("MY_ATTRIBUTE_VALUE", "..."), where MY_ATTRIBUTE_VALUE isn't anything applicable to <div>.
Thanks !
You should definitely go with data attributes. Here's an article on them. HTML5 Custom Data Attributes.
It is very good practise as long as you're setting custom data attributes, whose purpose is holding meta data about those elements. Data attributes take the form data-name where name can be any valid descriptor.
Traditionally people would add classes, and in some cases this is still appropriate (e.g. when a class describes the state of an attribute and also denotes a style class, for which class is primarily used).
If you believe that markup is about presentation, then associating data with HTML elements is inconsistent with that philosophy. If you think that it doesn't matter, then use data- attributes introduced in HTML5. Note however that HTML5 is not a standard and is not yet that widely supported (if the term "supported" has any meaning in the context of a "living specification" that is constantly changing). However data- attributes likely won't upset most browsers but you must use get/setAttribute to access them reliably in a browser independant way.
It is considered good practice to keep data separate from presentation so that you can change the presentation to provide multiple views of the same data. If you bind data to the presentation, you reduce your ability to do that. It also means that changing the data model may well affect presentation unnecessarily.
Storing data in an object and relating it to the element (say by the element's id) will likely provie much faster access to the data (direct property access is much faster than function calls passing strings) and allow for a more flexible UI and data model.
Well, I admit: I've extensively used jQuery.attr to store custom data in DOM elements in many, many scripts. I'm wondering if convert all my script to use jQuery.data instead of jQuery.attr. As far as I understand, the advantages of jQuery.data are:
produce neat and valid HTML code
can store any type of data (objects, array,...) on elements
The main advantage of custom attributes are:
If WEB pages are not strict HTML, I can produce HTML code with custom attributes on the server
In firebug it's easy to inspect my HTML code in search of my custom attributes
Can someone tell me if I miss something or if exists issues that makes use of jQuery.data highly preferable?
You pretty much got it. But do you know every HTML attribute? There are a lot of attributes that are used by screen-readers and other usability tools that are not standard (yet). What happens when you accidentally use the role attribute and a screen-reader picks that up? Using $.data isn't only neater, it's safer for you and makes more sense.
EDIT: I learned something last night that is pertinent to this question. In HTML5, you ca specify custom attributes for storing data. These custom attributes must be specified using the prefix "data-". See the spec for more detailed information.
What this means, is that you do not have to go back and change all of your old code, because you will never have to worry about overlapping with other attributes if you prefix with "data-". However, if you need to store more complicated data types than strings, use $.data.
I think that you don't miss anything but storing data on dom elements attributes is always a bad practice so i think you should use the $.data function.