puzzled about document.documentElement - javascript

I got puzzled about it .
1 Is document equal to document.documentElement? I think they are both root node.
2 Why I can use document.documentElement.getElementsByTagName() but I can not use
document.documentElement.getElementById()?

There is a difference between the document object and the document element.
When an HTML document is loaded into a web browser, it becomes a document object.
The document object is the root node of the HTML document and the common ancestor of all other nodes, such as element nodes (including the document element), text nodes and attribute nodes.
One of the differences is that an element has getElementsByTagName() but not getElementById(), which is part of the document itself.
To successfully use an element to get another one based on ID, you need to go through its document:
var elem2 = elem1.ownerDocument.getElementById(whatever)

Related

Document Object Model

Question is simple but confusing for me that when i console.log(document.body) or (document.head) both are working fine but when i do with document.script or document.html these two are not working why ? although all these things are in the document ?
Q2) i can write
document.getElementById('something')
but why i can't write
document.body.getElementById('something')
although body is in the document and element in the body tag as well, while sometime document.body works at different stages in script
getElementById is a method on document, which is an object that uses the Document interface from the DOM. It's not a method on elements (the Element interface from the DOM and its specialization the HTMLElement interface from HTML). document.body is an element (an HTMLBodyElement, which is an HTMLElement, which is an Element), not a document.
Some methods (like querySelector) are methods on both document and elements, because it makes sense for them to be (on an element, querySelector only looks within the element, not throughout the document). But getElementById isn't. (It could be, but it would be a bit odd to scope it to just an element when IDs are meant to be unique throughout the document.)

How to detect an jquery element is in DOM?

I have a jquery element. and I remove it from DOM by using remove(), but jQuery still keep a reference of it.
and later I still can use it and insert it into DOM.
How to detect that this "var p" is in DOM or off DOM ?
var p=$('p');
p.remove();
console.log(p);
p.insertAfter($('body'));
I think p.parent() is more easy way to go. if it in DOM it will get another DOM node
use javascript length to check if dom element exists or not
if($("p").length>0)
{
// p exists
}
var p=$('p');
p.remove();
So when you did p.remove(), it is removed from the dom but it still exists in memory as a stand alone dom node object with all its contents intact.
You can perform any operation as in normal dom element like append anywhere, change contents or change attributes.
The only difference is that it is not part of the document unless you append it in the html.
jQuery has contains method to check if the element is part of the document
jQuery.contains(document, $foo[0]));
p.parent() in case of removed p will return a 0 length jquery object because p is independent node and has no parent.

JQuery working wierdly for function 'find':

I have the following jQuery line:
$('<html>hi</html>').find('a')
I expect the result to be a wrapped set of one element. However the result is an empty array ([]). Why?
-- EDIT --
For some reason the code below works.
$('<html><div>hi</div></html>').find('a');
Why is this happening?
That's because the html element is stripped when the string is parsed:
> $('<html>hi</html>')
[​hi​​]
i.e. the current collection contains an element that you are trying to find(). As the top-level a element doesn't (and can't) have a descendants the find() call will return an empty collection.
From jQuery documentation:
When passing in complex HTML, some browsers may not generate a DOM that exactly replicates the HTML source provided. As mentioned, jQuery uses the browser's .innerHTML property to parse the passed HTML and insert it into the current document. During this process, some browsers filter out certain elements such as <html>, <title>, or <head> elements. As a result, the elements inserted may not be representative of the original string passed.
edit: The second snippet can find() a element as when the html element is stripped the top-level element of the collection is a div element that does have a descendant.
As in the Documentation of .find() descriped
Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
$('<html>hi</html>')
will just provide an Object of your a-tag.
Demo
If there are multiple anchor-tags inside your html-string you can filter them, e.g.:
var elem = $('<html>hihi</html>');
var filter = elem.filter(function(){
return $(this).attr('href') === "cnn.com";
});
Demo
Edit
When passing in complex HTML, some browsers may not generate a DOM
that exactly replicates the HTML source provided. As mentioned, jQuery
uses the browser's .innerHTML property to parse the passed HTML and
insert it into the current document. During this process, some
browsers filter out certain elements such as <html>, <title>, or
<head> elements. As a result, the elements inserted may not be
representative of the original string passed.
Source: http://api.jquery.com/jQuery/#jQuery2 down to the Paragraph Creating New Elements
So jQuery uses .innerHTML. According to the docs
Removes all of element's children, parses the content string and
assigns the resulting nodes as children of the element.
So the html-string <html>test</html> gets stripped to <a></a>.
When wrapping a div around the anchor, the anchor stays a descendat of an elemnt and therefore gets found by the .find()-function.
You should read the documentation at Jquery docs about find()
$('html').find('a');
Check this jsfiddle

Elements outside document

I was just reading this article by MDN and saw that, according to the specifications for "document.getElementById", elements not in the document are not searched.
I'm confused by why/how elements can be outside the document. How does this differ from the definition of an absolutely positioned element (namely, that absolutely positioned elements are removed from the document flow). I'm not entirely sure the absolutely positioned element case applies to this, but a clarification on what it means to be "outside the document" and why something like that would be used would be greatly appreciated.
A document is a tree, but you can have nodes (leaves/branches) that aren't on the tree (either because they never were, or because they've come off it).
Examples will probably make this clearer.
Example 1: Never in the tree:
Here's an element that's not in any document:
var elm = document.createElement('div');
elm.id = "foo";
That's an element, with an id, but it isn't part of any document.
Example 2: Removed from the tree:
HTML:
<body>
<div id="foo"></div>
</body>
JavaScript:
// The div is in the document, so this works:
var elm = document.getElementById("foo");
// Now we remove it:
elm.parentNode.removeChild(elm);
// 'elm' is no longer in any document
console.log(document.getElementById("foo")); // null
Example 2 Live | Source
"not in the document" means "not stored in the DOM tree of the current document", i.e. the nodes exist in memory, but they're not "attached" to any node on the page.
A corrollary of that is that the elements must therefore be invisible, but it's for an entirely different reason to that of absolute position. In the latter, the nodes do exist in the DOM, they just may not be position "on screen".

Can I keep a reference to a document fragment?

I'm playing around with a document fragment. I find it hard to understand how it behave when I append it to the DOM.
I create a doc fragment that I assign to a variable, when I insert some stuff into it, and append the doc fragment into a element. But if I clear the element my variable which should reference to the doc fragment contain an empty document fragment.
I trying to make a cache for a third party lib that creates document fragments. So I would like to get this working. Should I create a cloneNode before I append the fragment to the DOM, is that correct?
I have created a JS fiddle:
http://jsfiddle.net/4CTXG/1/
var test = document.createDocumentFragment();
//var test = document.createElement("div"); // This one work
$(test).append($("<div>").html('Hello world!'));
$("#result").append(test);
setTimeout(function(){
$("#result").children().remove();
$("#result").append(test);
console.log('Now test should have been appended');
$(result).css({"background": "#FF0000"});
},5000)
When you append an Element (e.g. the <div>) into the DOM, the Element gets added as a child of its new parent. The div's children are not changed. When you remove the element from its parent, the Element is just detached from the DOM. It you still have a reference to the Element it will still contain its children, available to reattach later.
When you append an DocumentFragment into the DOM, the children of the DocumentFragment are removed from the DocumentFragment and moved to be children of its DOM element parent. The DocumentFragment is now empty.
So instead of appending the DocumentFragment, you should append a deep clone of the fragment.
See http://dom.spec.whatwg.org/#concept-node-insert for the gory details.
Javascript objects are copied by reference rather than value. So when you assign the fragment to a variable and then insert the fragment into the DOM, both the variable and the DOM are referencing the same object. Any change you make to one will also occur in the other.
If you really want the variable to reference an object that is distinct from the DOM, then cloning is the right approach.

Categories