Reputation: 9597
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
Upvotes: 4
Views: 4789
Reputation: 92274
Yes, it seems like if you specify a context for query('#myid', nodeInMemory)
, it should not use document.etElementById()
The workaround is to use
dojo.query("[id='myid']", nodeInMemory);
Upvotes: 0
Reputation: 1462
This may be a hack, but maybe it can help you,
function foo(){
this.bar = bar();
bar.[access the properties of the div here]
}
function bar(){
this.somenode = document.createElement("div");
return this.somenode;
}
you can access the properties of the div, in this case bar, without adding it to the page, 'somenode' in bar() can be anything that is a valid html element.
Upvotes: 0
Reputation: 7521
If the node is not yet in the DOM, it cannot be accessed with Dojo's query
selector. However, if the node is in the dijit registry, you can access it with dijit.registry.byId(<id>)
.
Upvotes: 0