How do I clear off all that was written in a document? Is there a DOM JavaScript API that will erase all that's in the document object's buffer; an equivalent of the server-side Response.Clear()?
I am just practicing JavaScript.
You can remove the root (html) element using:
document.querySelector('html').remove();
or the jQuery equivalent if you have a very old browser:
$('html').remove();
here's an alternative that doesn't require querying:
document.documentElement.remove();
What do you mean by “document object's buffer”? The actual visible content is usually contained in the body, so you can empty it:
document.body.innerHTML = null;
There is no buffer like in server-side preprocessor languages, because the DOM document is entirely client-side rendered.
You can even wipe all the document's descendants, clearing the <html> element:
document.getElementsByTagName('html').item(0).innerHTML = null;
Also, if you don't like innerHTML, you can also use textContent:
document.head.textContent = null;
This is because, quoting MDN:
Setting this property on a node removes all of its children and replaces them with a single text node with the given value.
Related
I can get nodeType from nodes like <a> or <div> in Chrome devtools, but I can't get the nodeType of an attribute. I've tried like this:
document.getElementByTagName('a')[0].href.nodeType
The DOM Standard says attributes are also a type of node. Why can't get its nodeType?
Links : https://dom.spec.whatwg.org/#attr
...but I can't get the nodeType of an attribute. I've tried like this:
document.getElementByTagName('a')[0].href.nodeType
When you access .href on an Element, you're not using the attribute node (not directly), you're using the reflected property for the attribute (which accesses the attribute node under the covers). That property is an accessor property that returns a string. Strings don't have a nodeType property. (You can find this in the HTML spec, starting at the a element which tells you it's an HTMLAnchorElement, which includes HTMLHyperlinkElementUtils, which has href which defines the behavior of the href accessor property.)
To access the attribute node directly, you'd use the attributes collection or getAttributeNode:
const example = document.getElementsByTagName("a")[0];
const node = example.attributes[0];
console.log(`node.nodeType = ${node.nodeType}`);
console.log(`node.nodeName = ${node.nodeName}`);
console.log(`node.nodeValue = ${node.nodeValue}`);
example
In a comment you've asked:
But how do you know that?Does the Dom standard says that in any line?
Truthfully I've learned this stuff over a period of ~24 years and don't remember when I first learned that while attributes are part of the DOM, they aren't part of the node tree, they're held separately as the attributes NamedNodeMap. That information is in the DOM spec where it defines the node tree (note that it doesn't mention attribute nodes), but...you'd have to be looking for it to catch that I think. :-) If you kick around the DOM and HTML specs long enough, though, you'll pick these things up.
Is there a way to create a new element in a Document object from the tag source? Essentially what I'd like to do is something to effect of:
myDocument.createElement('<sometag attr="lol">');
No, native DOM API for .createElement doesn't support that syntax. You need to create the plain Element and set any property either directly on the object
newElem.attr = "lol";
or (better), use .setAttribute()
newElem.setAttribute( 'attr', 'lol' );
What you "could" do is do create a documentFragment, then use .innerHTML to write that string into that fragment and finally .append its contents to its target destination.
well, use innerHTML instead of trying to hack dom manipulation for this kind of thing.
To do so, create a valid node with dom if you want (or get it via getElementById), then set innerHTML of this node with your code
The innerHTML property works here - but it's a tad bit difficult to place the thing where you want it sometimes. For example:
var div = document.createElement('div');
div.innerHTML = "<img src='http://www.google.com/logos/classicplus.png'/>";
In my humble opinion, it's a heck of a lot easier to use jQuery to handle it for you, as it comes with all of the jQuery methods already attached.
var div = $("<div class='blah'><img src='http://www.google.com/logos/classicplus.png'/></div>");
div.find('img').hide();
div.appendTo('body');
div.find('img').fadeIn();
This might be crazy but it intriguing me for quite some time :)
I would like to know how a javascript variable can bind itself do the DOM after it is appended to the body, for example?
var p = document.createElement('p');
p.innerHTML = 'Hello World';
document.body.appendChild(p);
So now I have this p variable which contains an exact reference of that specific paragraph no matter where it is located inside the body.
p.innerHTML = 'new content';
will easily find the paragraph and change its value
So my question is...how this binding is made?
what If I want to re-create that after the variable is gone?
is there any way to attach that again without having to run through the DOM and find it?
I was thinking if somehow each node inside the DOM have its specific identifier that is not the id attribute but some kind of UUID that can be referred later on?
like:
console.log(p.localName); //aoi12e2kj2322444r4t
p = null;
so I can still recover that paragraph node thought this uuid?
In this environment I wouldn't have access to any external node attribute, such name, id, data, etc..
So I am quite curious to know how this binding is created between variable and DOM node?
I believe that it changes depending on the browser your using. There's no standard way to do so. Currently you either use the id or iterate over the dom until you reach the element you want.
The binding is created on the first line, where you assign the result of document.createElement to p. This is no different from any other time you assign something to a variable, which always binds the variable name to the value. As far as the script is concerned, there is no other binding occurring. The p is an HTMLElement, and that's all of the element that's exposed.
Note that for p.innerHTML = 'new content';, the element doesn't have to be found because p already refers to the element. That's what the DOM does: it exposes documents and document elements.
If you later want another reference to the same element, you'll have to use DOM methods (such as getElementById) to find it. That's what they're there for.
As for how the DOM exposes elements, that's implemented internally and varies from browser to browser or library to library (since the DOM isn't used just in browsers).
I'm looking for a way to find if element referenced in javascript has been inserted in the document.
Lets illustrate a case with following code:
var elem = document.createElement('div');
// Element has not been inserted in the document, i.e. not present
document.getElementByTagName('body')[0].appendChild(elem);
// Element can now be found in the DOM tree
Jquery has :visible selector, but it won't give accurate result when I need to find that invisible element has been placed somewhere in the document.
Here's an easier method that uses the standard Node.contains DOM API to check in an element is currently in the DOM:
document.body.contains(MY_ElEMENT);
CROSS-BROWSER NOTE: the document object in IE does not have a contains() method - to ensure cross-browser compatibility, use document.body.contains() instead. (or document.head.contains if you're checking for elements like link, script, etc)
Notes on using a specific document reference vs Node-level ownerDocument:
Someone raised the idea of using MY_ELEMENT.ownerDocument.contains(MY_ELEMENT) to check for a node's presence in the document. While this can produce the intended result (albeit, with more verbosity than necessary in 99% of cases), it can also lead to unexpected results, depending on use-case. Let's talk about why:
If you are dealing with a node that currently resides in an separate document, like one generated with document.implementation.createHTMLDocument(), an <iframe> document, or an HTML Import document, and use the node's ownerDocument property to check for presence in what you think will be your main, visually rendered document, you will be in a world of hurt.
The node property ownerDocument is simply a pointer to whatever current document the node resides in. Almost every use-case of contains involves checking a specific document for a node's presence. You have 0 guarantee that ownerDocument is the same document you want to check - only you know that. The danger of ownerDocument is that someone may introduce any number of ways to reference, import, or generate nodes that reside in other documents. If they do so, and you have written your code to rely on ownerDocument's relative inference, your code may break. To ensure your code always produces expected results, you should only compare against the specifically referenced document you intend to check, not trust relative inferences like ownerDocument.
Do this:
var elem = document.createElement('div');
elem.setAttribute('id', 'my_new_div');
if (document.getElementById('my_new_div')) { } //element exists in the document.
The safest way is to test directly whether the element is contained in the document:
function isInDocument(el) {
var html = document.body.parentNode;
while (el) {
if (el === html) {
return true;
}
el = el.parentNode;
}
return false;
}
var elem = document.createElement('div');
alert(isInDocument(elem));
document.body.appendChild(elem);
alert(isInDocument(elem));
You can also use jQuery.contains:
jQuery.contains( document, YOUR_ELEMENT)
Use compareDocumentPosition to see if the element is contained inside document. PPK has browser compatibility details and John Resig has a version for IE.
function isInDocument(query){
return document.querySelectorAll(query).length != 0;
}
// isInDocument("#elemid")
I'm trying to reduce DOM manipulation during my javascript execution, and I thought about lazy-writing DOM elements, versus writing a large section of the DOM hidden and unhiding the needed parts later.
To do this, I've separated out all my DOM content into a JSP which I load into a variable via ajax and manipulate with jQuery. However, if jQuery is doing this manipulation in a hidden div on the DOM, I've achieved no performance gain. Help?
New Answer
I just checked a couple of your recent questions and I think I see what you're asking here.
When you call jQuery like $('selector string', context) it gets routed to this:
jQuery(context).find('selector string')
do you see that? The context argument becomes the first argument to a [sub] call to jQuery. That in turn gets routed to this batch of shortcut code:
// Handle $(DOMElement)
if ( selector.nodeType ) {
this[0] = selector;
this.length = 1;
this.context = selector;
return this;
}
so the context argument gets stored on the returned jQuery object in the .context property.
Now judging from your comment to this question, you are aware that you should have your server side code respond with a "Content-Type: text/xml" header. Doing so will instruct the browser to automatically create a DOMDocument tree from your xml response body (FYI it's accessible in the responseXML property on the XMLHttpRequest object itself - jQuery simply passes it on to your success handler).
To answer your question: if you pass this DOMDocument object on to jQuery as the context parameter and proceed to modify attributes on this object, there is no manipulation in any hidden/temporary div that you have to worry about. The DOMDocument is simply mutated in-place.
Hope that answers your question.
Original Answer:
If you have html in a string and you need it to be nodes in a DOM structure, you've got to convert it somehow. Putting it inside a throwaway element is the only way I know to do this while leveraging the built-in browser parser:
// HTML string
var s = '<span>text</span>';
var div = document.createElement('div');
div.innerHTML = s;
var elements = div.childNodes;
Many of the libraries do this more or less, including jQuery. If it makes you feel any better, the throwaway div above is not inserted into the DOM, thereby avoiding DOM reflow (a very expensive operation), saving some cycles.
You might want to look at document fragments as a container to hold the generated DOM nodes.
var fragment = document.createDocumentFragment();
for ( var e = 0; e < elems.length; e++ ) {
// append elements to fragment
fragment.appendChild( elems[e] );
}