getElementById() on Elements not yet part of the current document always returns null

288 views
Skip to first unread message

Chris L

unread,
Mar 21, 2013, 6:36:26 AM3/21/13
to mootool...@googlegroups.com
As part of what I'm doing to add a slightly dynamic veneer to an otherwise static site I want to pluck fragments from one or more pages and add them to the current page. I'm doing essentially the following, but getElementById() on a detached Element always returns null.

// Give us somewhere to put an HTML string
var temp = new Element('div');

// htmlOfSomeOtherPage retrieved via an XHR
temp.set('html', htmlOfSomeOtherPage);

// Without this, getElementById on 'temp' returns null
// $('somewhere_else').adopt(temp);

// Find the interesting bit
var newContent = temp.getElementById('content');

// Add that to the current page
$('container').adopt(newContent);


Is there a way to make this work without resorting to temporarily adding 'temp' to the main DOM?

Chris

Haakon

unread,
Mar 21, 2013, 8:34:11 AM3/21/13
to mootool...@googlegroups.com
getElementById is probably simply restricted to the DOM. You might
have better luck with Slick.find(temp, '#content'), but I haven`t
tested it.
http://mootools.net/docs/core/Slick/Slick
https://github.com/mootools/slick

Håkon
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "MooTools Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to mootools-user...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Aaron Newton

unread,
Mar 21, 2013, 10:46:54 AM3/21/13
to mootool...@googlegroups.com
temp.getElement('#foo')

Sanford Whiteman

unread,
Mar 21, 2013, 2:19:19 PM3/21/13
to Haakon
> getElementById is probably simply restricted to the DOM.

Not really, it is restricted to _documents that have a known attribute
of type ID_. Simply having an attribute called `id` doesn't make it an
ID: that's the root cause.

If you wrap your returned (X)HTML with proper NS and DTD (and you are
returning valid XHTML, right?) you can use getElementById on it, even
without injecting it into the DOM.

And, unsurprisingly, it is orders of magnitude faster than Slick,
which is emulating an ID-indexed search the best it can but can't
possibly keep up.

http://jsfiddle.broadleafsystems.com/FrTQc/2/

Even with a tiny tree the native getElById is that much faster.

This demo works in Gecko and Webkit. I'm quite sure that (years ago
now) I had it working it IE as well, although I had to wrap the XHTML
differently from the server end. I could look that up if you're
interested, or you could do try { getElementByID } and then catch {
Slick }.

-- S.

Chris L

unread,
Mar 21, 2013, 5:30:27 PM3/21/13
to mootool...@googlegroups.com
On Thursday, 21 March 2013 18:19:19 UTC, Sanford Whiteman wrote:
> getElementById is probably simply restricted to the DOM.

Not really, it is restricted to _documents that have a known attribute
of type ID_. Simply having an attribute called `id` doesn't make it an
ID: that's the root cause.

If you wrap your returned (X)HTML with proper NS and DTD (and you are
returning valid XHTML, right?) you can use getElementById on it, even
without injecting it into the DOM.

My experiment hadn't got as far as fetching actual pages - I was just using an embedded string literal, admittedly originally without a DOCTYPE. It validates fine as HTML5. No XHTML, NS or DTD though. (NS seems to be the only one that's vital)
Most of the time, these pages will be rendered un-molested as standalone pages. Less frequently, they will be cherry-picked client-side to build a composite page. I don't have sufficient appreciation of the subtleties to know whether it's valid to have '<html xmlns="http://www.w3.org/1999/xhtml">' as the root of an html5 document. I need to make my experiment more closely match the intended final application. If all else fails, I can make it work by appending the incoming page to a DOM element with "display: none;".

Thanks for putting so much effort into your reply.

Chris

Sanford Whiteman

unread,
Mar 21, 2013, 5:49:47 PM3/21/13
to mootool...@googlegroups.com
If the browser recognizes real, NSed XML in the Ajax response and the linked DTD has `id` as an ID... you will be able to use getElementById on it. This is old-school Ajax, when the "x" had one meaning.

Getting there is the fun part.

As you're building the server from scratch, you should be in OK shape (as opposed to when you are only getting X/HTML fragments from someone else's web service, where they aren't intended to be heavily queried outside the DOM but rather injected, then styled).

-- S.

Sanford Whiteman

unread,
Mar 21, 2013, 10:53:35 PM3/21/13
to Sanford Whiteman
OK, found my old work on IE & XML for your continued reference.

http://jsfiddle.broadleafsystems.com/FrTQc/21/

Uses getElementById when available, falls back to selectSingleNode
otherwise. Then also runs w/Slick if possible.

I also do a getElementById on similarly structured HTML markup (not
the XML response) for a performance reference.

On my machine:

· selectSingleNode-against-XML is 2x slower than
getElementById-against-HTML within IE 8

· getElementById-against-XML is only slightly slower than
getElementById-against-HTML in Firefox 15, and they're both
rocket-fast compared to IE

· even so, selectSingleNode/IE is still 25% faster than Slick/Firefox
15; Slick is still the slowest dog in the bunch

That last tidbit is a bit apples-and-oranges, but regardless I would
not use Slick against XML if you don't have to (i.e. if you can craft
your XML to fit the task and you don't need Slick's fancy selectors).

-- S.

Haakon

unread,
Mar 22, 2013, 7:04:40 AM3/22/13
to mootool...@googlegroups.com
Hi, thanks for the insight there.

While playing around with your example though, I found that in a more
'practical' loop, like 1-4, Slick is actually much faster (running
Chrome).
I can`t see why you would do an optimization here though, if we are
speaking single digit milliseconds.

Håkon

Sanford Whiteman

unread,
Mar 22, 2013, 3:46:31 PM3/22/13
to Haakon
> While playing around with your example though, I found that in a more
> 'practical' loop, like 1-4, Slick is actually much faster (running
> Chrome).

If you're still using the tiny test XML, that's still not "practical."
The high number of iterations was one way to amplify the performance
differences. The other way is to use a real XML file of some depth and
breadth and run with far fewer iterations.

Here we only run 100 times over a 256K XML file.

http://jsfiddle.broadleafsystems.com/FrTQc/41/show/light/

The differences are very dramatic, it's not wasting single-digit
milliseconds in this scenario but rather almost 1 to 5 full _seconds_.
In my FF, I get 0-1ms times for native getElementById yet ~1 second
times for Slick. In IE, it's 500ms times for native selectSingleNode
and ~6 seconds for Slick!

So I don't consider it premature nand/nor micro-optimization.
Especially when you take JS' single-threading model into account. It's
unlike other deployments where slow-running code can be left to crawl
along, or even lock up one CPU leaving other CPUs free. An
optimization that would be crazy-talk in a traditional desktop
environment can be quite reasonable in the browser.

And consider web apps that use XML as a "data island" to frequently
run complex lookups against the same doc, say online spreadsheets and
suchlike (after all, if we have a need for getElementById outside of
the DOM at all, the implication is that XML is not being used simply
as an opaque transport mechanism for HTML tags). I wouldn't want to
know I'm spending 70ms per lookup if I can get it down to 5ms pretty
easily.

True, you could make the point that optimization is unnecessary you're
just running getElementById a couple of times over the page's
lifetime. But even in a one-page site I just built, I pull in like 200
records over XML and query across them before insertion (because I
have to massage certain stuff as I don't own the back end). I wish I
could be assured of the best performance possible.

-- S.


pixel67

unread,
Mar 23, 2013, 10:27:02 AM3/23/13
to mootool...@googlegroups.com
Thanks for this Sanford, I will learn something here :)

Haakon

unread,
Mar 23, 2013, 1:32:50 PM3/23/13
to mootool...@googlegroups.com
Ok, I think you`ve made good arguments for doing the optimization if
you`re using JS to lookup nodes in a data structure and not the DOM.
Chris L wasn`t doing that in this case, but it`s good to know!

Thanks,
Håkon

Sanford Whiteman

unread,
Mar 23, 2013, 1:48:48 PM3/23/13
to Haakon
Heh, thanks for seeing it my way.

-- S.

Rolf Langenhuijzen

unread,
Mar 29, 2013, 9:19:04 AM3/29/13
to mootool...@googlegroups.com
Hey Håkon,

You have witnessed Sandy's power. He's from another planet.. when it comes to stuff like this us normal (earth) people can only say "ay master!"

No joke!

Rolf

Tony Brown

unread,
Mar 29, 2013, 11:55:16 AM3/29/13
to mootool...@googlegroups.com
True that!


--
 
---
You received this message because you are subscribed to a topic in the Google Groups "MooTools Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mootools-users/Qjwu0viFJiw/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to mootools-user...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Sincerely, 

Tony Brown

Sanford Whiteman

unread,
Mar 29, 2013, 5:19:15 PM3/29/13
to Tony Brown
Geez guys, I thought I was just "that guy who loves the IE8 Dev
Tools." :)

Have a great weekend!

-- S.

Reply all
Reply to author
Forward
0 new messages