Looking through the code in Dojo's library for dojo/query, it looks like they default to use document.getElementById if the selector passed in is an ID selector.
For example, if I do:
query("#myId")
This will behind the scenes run:
document.getElementById("myId")
This is fine for querying nodes in the window document, but what if you are building nodes not yet put in the document? If I am constructing a node in memory to put in the DOM later and I need to query on that node by ID, I can't do it. Because this node isn't in the document yet.
I understand that this is how jQuery does it, too, but jQuery is different because the approach for querying by an ID or a different selector (class, attribute, etc.) is the same regardless. For example:
$("#myId")
$(".myClass")
$("div[align=center]")
The approach is the same. So, defaulting to document.getElementById in this instance is fine to me.
With Dojo, its pretty misleading in light of the fact that Dojo offers a separate function that serves as an alias to getElementById (dom.byId). If I wanted ID querying against the actual document, I'd use that. If I'm using dojo/query by a selector, then I want to be able to query the document or a contextual node.
Dojo uses the lite.js selector engine in situations where a viable native selector engine is available. The beginning of the file has a "fast path" block that actually does this default to dom.byId. If I comment out this block, the engine reverts to use a querySelectorAll, which in turn fixes this issue.
Can anyone explain the reasoning for Dojo doing this? Or if there is a viable workaround that doesn't require me to comment out Dojo's code? One approach I've seen that works is the use of data-attributes in place of IDs, which fake out the engine but that just seems lame.
EDIT:
Note: You can pass a contextual node to dojo/query when querying, but in Dojo even if you create a node outside the DOM using dom-construct, the ownerDocument of that node is still the window.document. In other words:
var node = domConstruct.toDom('<div><p><span id="myId">Content</span></p></div>');
var doc = node.ownerDocument;
will result in 'doc' being the window.document. So, doing something like:
doc.getElementById("myId") will fail. As will this:
var results = query("#myId", node);
Because Dojo's code looks for the ownerDocument of 'node', which again is the window.document
contextparameter is that it too must be a DOM element, so it can't be used if the node is only in memory. - Bucket