sma
sma

Reputation: 9597

Dojo Query by ID defaulting to getElementById

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

Answers (4)

Ruan Mendes
Ruan Mendes

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

tik27
tik27

Reputation: 2698

 var hellopuppy = dojo.query("[id='myId']",node);

Upvotes: 3

ankyskywalker
ankyskywalker

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

Bucket
Bucket

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

Related Questions