I have a complex code that travels inside windows and iframes (yes, windows cause I open some windows with window.open sometimes and also travel inside iframes) and when some condition apply I get an element from inside of those iframes (they usually are DIVs and SPANs).
So, I have the element that I want in the object "$(this)" so from the parent window how can I know the "document" element that has this element? I need to get the "document" element that has "$(this)" and set some attributes to it.
I tried $(this).parents(document) but it does not work.
If this refers to an element (such that $(this) would give you a jQuery wrapper around it) or indeed any Node, then this.ownerDocument is a reference to the document the element is in (null if it's not in a document). Details in ownerDocument in the specification.
Related
I want to replace a HTML document in the browser with another HTML document or another DOM without changing the document.location.
Possible with JavaScript?
No you can't change a Window's document property by any other means than navigation (in case of an opened Window or an <iframe>'s one from about:blank).
https://html.spec.whatwg.org/multipage/window-object.html#concept-document-window
For the page chrome://history, in Developer Tools, the DOM Elements tree shows nodes of type DocumentFragment like the following #shadow-root (open) which you can see selected in the screenshot below:
My question is how to use querySelector or another Javascript method to select such nodes ?
Unlike what another answer in this site suggested, DocumentFragment.querySelector doesn't exist.
As explained on developer.mozilla.org,
The ShadowRoot interface of the Shadow DOM API is the root node of a DOM subtree that is rendered separately from a document's main DOM tree.
You can retrieve a reference to an element's shadow root using its Element.shadowRoot property, provided it was created using Element.attachShadow() with the mode option set to open.
In your case, it looks like you need to do
var shroot = document.getElementById('history-app').shadowRoot
.getElementById('history').shadowRoot;
As you can see, we (apparently) have to browse down the DOM step-by-step. I.e. trying for example to access the 'history' element directly won't work since it is itself inside a shadowRoot.
I embedded console.log(document.body) at my local page for learning purpose and when I hit refresh it displayed properties of body element like baseURL, innerHTML, etc... rather than its
content. Why is this happening? (I am using Chrome43)
In JavaScript and the DOM, document.body is an object, and when you log it with console, Chrome is displaying displaying the object, which includes all of its properties. The content of document.body can be found in the innerHTML property and accessible via other properties as well.
Chrome may be displaying the object properties instead of the DOM tree if there's a race condition and console.log(document.body) is fired prior to the completion of the DOM tree.
If you need the DOM tree, then try logging document.body after the body loads.
document is the root of the DOM, not the same as window, the global browser scope. console.log(document.body); logs the DOM element, not the JavaScript object.
In this article a detached Div node is created:
http://www.bennadel.com/blog/1008-jQuery-empty-Kills-Event-Binding-On-Persistent-Nodes.htm
I don't understand : I thought that DOM owns every nodes. How would you attach to DOM then ?
Last but not least what would be the purpose of having detached node ?
I'm not sure which answer you expect, so here are some thoughts:
I thought that DOM owns every nodes.
The document owns every node. Each node has an ownerDocument [MDN] property.
From the specification:
The Document interface represents the entire HTML or XML document. Conceptually, it is the root of the document tree, and provides the primary access to the document's data.
Since elements, text nodes, comments, processing instructions, etc. cannot exist outside the context of a Document, the Document interface also contains the factory methods needed to create these objects. The Node objects created have a ownerDocument attribute which associates them with the Document within whose context they were created.
How would you attach to DOM then?
There are various ways to insert a new node, such as appendChild [docs] or insertBefore [docs].
Last but not least what would be the purpose of having detached node ?
One advantage is that you can build complex subtrees offline so that the browser does not have to recalculate the layout every time you insert a node.
Sometimes it is also useful for parsing an HTML string. By creating an empty, detached div and assign the HTML string to innerHTML, you can parse and process the HTML string easily.
The only caveat is that document.getElementById cannot find nodes which are not part of the tree.
Also interesting in this regard might be the explanation for the Node.parentNode property. After all, a Node which does not have parent is not part of the tree:
The parent of this node. All nodes, except Attr, Document, DocumentFragment, Entity, and Notation may have a parent. However, if a node has just been created and not yet added to the tree, or if it has been removed from the tree, this is null.
with document.createElement(), you can create an element node
var p = document.createElement("p");
At this point though, it will exist in memory but will not have been attached to the DOM.
There are numerous ways in which a node can be attached to the DOM, but probably the easiest would be using element.appendChild(node)
var p = document.createElement("p");
// attach the newly created node to the document body
document.body.appendChild(p);
You may want to create the element first, manipulate it and then attach to the DOM so that your manipulations do not cause browser reflow e.g. if you're setting the background colour, border, appending child elements, etc. you want to do this in memory without each change having to be reflected as a visual change in the browser.
Modifying the DOM is expensive. You can create a detached object, set it up the way you need to (adding its attributes, binding event handlers, etc). After its setup the way you want, then append it to the DOM.
You can definitely create elements that are not part of the DOM.
var someElement = document.createElement("div");
var someOtherElement = $("<div>");
Performing operations on detached elements are far more efficient than performing operations on attached elements because detached elements do not have to be rendered.
The page you linked to uses .empty() which detaches elements from the DOM and removes all event handlers from those elements.
There is also .detach(), which may be what you mean. .detach() basically just, well, detaches the node from the DOM. It's not part of the DOM anymore; it's just hanging around in memory (as long as you keep it in a variable). This means that if you discard the variable, you've lost the detached node forever (it's not in the DOM nor in a variable).
A use case is e.g. temporarily "removing" an element from the DOM without actually dismissing it, so that you can attach it later (using .append/.after/etc).
var detached = $("...").detach();
// later:
$("body").append(detached);
I am getting a reference to a DOM element from a WYSIWYG Editor.
I don't understand JS nor the WYSIWYG Editor (CKEditor) that deeply yet, but it somehow seems to be a pointer or other direct reference to the actual element that resides in an IFRAME within the WYSIWYG editor. At least, when I console.log the element, I get a link that, when clicked, opens the actual element in Firebug.
Is there a way to get a reference to this element's document object within the IFRAME?
If you have the DOM element reference, you can use the ownerDocument property:
var ownerDoc = someElement.ownerDocument;
I don't know that specific editor, but if it has a reasonably normal implementation of the DOM, each node (including the DOM element to which you get a reference) has a parentNode read-only property that references its parent node. By following the chain of parentNode references, you're moving upwards in the DOM tree and should eventually reach the document you want.
(The ownerDocument property offers a more immediate solution, but it was not supported in some old browsers such as IE 5.5 -- if you don't have to worry about such "archaeology" issues, it's fine, but parentNode works even more broadly).