Remove body element - javascript

How to remove HTML <body> element with all of its content?
var e = document.getElementsByTag('html');
e.removeChild('body');
Does not work.

The simple solution would be
document.body.innerHTML = "";
But why on earth would you want to do this?
By the way:
var e = document.getElementsByTag('html');
should be
var e = document.getElementsByTagName('html')[0];
and
e.removeChild('body');
should be
e.removeChild(document.body);

getElementsByTagName returns a collection of nodes, not a single node
removeChild takes a node, not a string containing a tag name
var e = document.body;
e.parentNode.removeChild(e);
… however HTML documents require a body element, so this may have unexpected behavior.

...
document.body.parentNode.removeChild(document.body);

I think this will remove it
var html = document.getElementsByTagName('html')[0];
var body = document.getElementsByTagName('body')[0];
html.removeChild(body);

The body itself has a method which does just that:
document.body.remove();

document.body.parentNode.removeChild(document.body)
or
document.body = document.createElement("body")
or
while(document.body.childNodes.length != 0) {
document.body.removeChild(document.body.childNodes[0])
}

Try this code it will remove all the content of body tag on click on the button
And if you want to remove content onload then use this onload="document.body.innerHTML = '';"
<html>
<body>
This is example Text<br>
<button onclick="document.body.innerHTML = '';">Click me to remove body contents</button>
</body>
</html>

Several people on this page have asked why one might even wish to remove a <body> element from an HTML Document.
Admittedly, it's a seldom-seen approach, but it's almost always because one wishes to remove the current <body> from a document (while keeping the <head>) and then create a new <body> element (to follow the same <head> as before).
So why not, simply empty the existing <body> element via:
document.body.innerHTML = '';
or
while (HTMLSourceTab.document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
The answer might be:
If the HTML Document in question is being opened in a new browser tab, these processes (above) can only execute after the DOMContentLoaded event fires.
And they may not execute quickly enough to prevent a brief Flash Of Legacy Body.
Whereas:
document.body.remove();
will normally execute quickly enough after DOMContentLoaded to prevent that flash.
Once the legacy <body> has been removed, a new <body> can be created and added via:
let newBody = document.createElement('body');
document.documentElement.appendChild(newBody);
or (if adding an empty <body>) simply:
document.body = document.createElement('body');
Full code for opening an existing document in a new tab, removing the existing <body> and adding a new <body>:
myNewTab = window.open(myNewTabURL, '_blank');
myNewTab.addEventListener('DOMContentLoaded', () => {
myNewTab.document.body.remove();
setTimeout(() => myNewTab.document.body = myNewTab.document.createElement('body'), 800);
});
myNewTab.focus();

Related

How to remove specific <script> and <style> tag from DOM

I've got a third party API response that sends me JS and CSS and I inject it into the document head.
Model.retrieve().then(res => {
// inject to the DOM
if(res) {
$("head").prepend( res.css ); //res.css would be a <style>
$("head").append( res.js ); // Would be a <script> ... </script>
let div = document.getElementById( 'banner-outerwrap' );
div.insertAdjacentHTML( 'beforeend', res.html );
} else {
// No response, do the cleanup.
}
})
Issue:
I want to clean up / Remove (CSS and JS) if the response is empty. (I.e for use cases that's not applicable) but I'm not sure how to do it with jQuery without refreshing DOM. (I run this code in a directive.js and I can't refresh the DOM hence, I would need to clean up)
Any insights would be appreciated.
Requirements
What I understood so far you are injecting some script wrapped in a <script> tag inside a document based on the text response you receive from the API and want to cleanup/remove afterward.
Problem
The problem is that there could be multiple scripts inside the <head> tag and you are not keeping the track of the injected script which would be more flexible and easier for you to manipulate your document.
Solution
For doing that I would prefer that you use the DocumentFragment function createDocumentFragment.
The trick is that before you inject the script you need to provide the <script> tag with some id or class so that you can select that tag later when the new response received rather than removing all tags.
I will continue from receiving the response, let say we have the following response
var response='<script>alert("hello all")<\/script>';
Now we have the above script tag as a text to assign it a class we need to transform it into a node and then append it to the documentFragment and assign it a new attribute class and then append it to the document
//create a document fragment
let htmlFragment = document.createDocumentFragment();
//create a div element to hold the response
let tempNode = document.createElement('div');
//add response to the div
tempNode.innerHTML = response;
//append the <script> tag from the div to the fragment
htmlFragment.appendChild(tempNode.firstChild);
//select script tag from the fragment now
let scriptTag = htmlFragment.querySelector('script');
//add class to the <script> tag
scriptTag.setAttribute('class', 'removeables');
//append the tag to the document body
$(document.body).append(fragment);
once done you can now easily select and remove the script tag by
$('.removeables').remove();
A working example for the above is given below it injects the script tag on page load and then on the click of the button delete it removes the script tag you can open HTML inspector and view.
I have created a function updateTags(response) to which you can pass your <script> response and it returns you a documentfragment which you can append using jquery or javascript.
//method to add script
function updateTags(response) {
let htmlFragment = document.createDocumentFragment();
let tempNode = document.createElement('div');
tempNode.innerHTML = response;
htmlFragment.appendChild(tempNode.firstChild);
let scriptTag = htmlFragment.querySelector('script');
scriptTag.setAttribute('class', 'removeables');
return htmlFragment;
}
$(document).ready(function() {
var response = '<script>alert("hello")<\/script>';
var fragment = updateTags(response);
$(document.body).append(fragment);
$("#delete").on('click', function() {
$('.removeables').remove();
});
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div id="content">
</div>
<button id="delete">remove</button>
</body>
</html>

Does anyone know a way to print the loaded page HTML after DOM is completed?

I'm looking for a way to read the source code of a page after it finished loading and inspect the code to see if it contains a specific text.
I found this reference but this only returns the text visible in the page and not the whole HTML code.
For instance, if the html source code is:
<html>
<header>
<header>
<body>
<p> This is a paragraph</a>
<body>
</html>
I want the script to print exactly the same thing.
Your help is appreciated.
I think you are over-complicating this problem. You don't need to "print" the page's HTML or "inspect the code".
In a comment, you said:
Check if page contains an iframe [and] Display a message if the iframe is found
You can just use DOM traversal functions to examine the DOM.
Try something like this:
window.addEventListener('load', function() {
if(document.getElementsByTagName('iframe').length){
console.log('Found an iframe');
}
});
Or with jQuery:
$(function() {
if($('iframe').length){
console.log('Found an iframe');
}
});
That's so simple, you can use this method to run a script after a page is fully loaded window.onload
function load(){
console.log(document.getElementsByTagName('html')[0].innerHTML);
}
window.onload = load;
For further explanations, check this post
Do like this, call this function on load
Fiddle Demo
function printBody() {
// store oiginal content
var originalContents = document.body.innerHTML;
// get the outer html of the document element
document.body.innerText = document.documentElement.outerHTML;
// call window.print if you want it on paper
window.print();
// or put it into an iframe
// var ifr = document.createElement('iframe');
// ifr.src = 'data:text/plain;charset=utf-8,' + encodeURI(document.documentElement.outerHTML);
// document.body.appendChild(iframe);
// a small delay is needed so window.print does not get the original
setTimeout(function(){
document.body.innerHTML = originalContents;
}, 2000);
}
Src: Print <div id=printarea></div> only?
Assuming that by 'print' you don't actually mean to transfer it to a paper copy, you can add some script like:
window.addEventListener('load', function() {
var content = document.documentElement.innerHTML,
pre = document.createElement('pre'),
body = document.body;
pre.innerText = content;
body.insertBefore(pre, body.firstChild);
});
What this does, step by step is:
window.addEventListener('load', function() > Wait for the page to be fully loaded and then execute the function
content = document.documentElement.innerHTML > store the actual page source in the content variable (document.documentElement refers to the 'root'-node, usually <html> in html documents
pre = document.createElement('pre') > create a new <pre>-element
body = document.body > create a reference to the <body> element
pre.innerText = content > assign the HTML-structure we've stored earlier as text to the <pre>-element
body.insertBefore(pre, body.firstChild) > put the <pre>-element (now with contents) before any other element in the body (usually on top of the page).
This leaves you with the entire source (as it was before creating the <pre>-element containing the source) on top of you page.
Edit: Added <iframe> workflow
It was not clear to me you actually wanted to target an <iframe>, so here's how to do that (using a naive approach, more on that further on):
window.addEventListener('load', function() {
var iframeList = document.getElementsByTagName('iframe'),
body = document.body,
content, pre, i;
for (i = 0; i < iframeList.length; ++i) {
content = iframeList[i].documentElement.innerHTML;
pre = document.createElement('pre');
pre.innerText = content;
body.insertBefore(pre, body.firstChild);
}
});
why is this approach naive?
There is a thing called Same-Origin-Policy in javascript, which prevents you from accessing <iframe>-content which if the contents do not originate from the same domain as the page containing the <iframe>.
There are several ways to take this into consideration, you could wrap the inside of the for-loop in try/catch-blocks, though I prefer to use a more subtle approach by not even considering <iframes> which do not match the Same-Origin-Policy.
In order to do this, you can swap the getElementsByTagName method with the querySelectorAll method (please note the compatibility table at the bottom of that page, see if it matches your requirements).
The querySelectorAll accepts a valid CSS selector and will return a NodeList containing all matching elements.
A simple selector to use would be
'iframe[src]:not([src^="//"]):not(src^="http")' which selects all iframe with a src attribute which does not start with either // or http
Disclaimer: I never use a <base>-tag (which changes all relative paths within the HTML) or refer to the current website using a path containing the domain, so the example CSS-selector does not consider these aberrations.
Can you use :not()
IE9 or better
Can you use document.querySelector(All)
IE8 or better (in order to use with :not(), IE9 or better)
hover/click the boxes above to show the spoiler

`ImportNode` in Firefox and extracting an element from an `iframe`

I am trying to understand importNode in html using the following example.
Suppose we have a content.html:
<html>
<body>
<nav id="sidebar1" class="sidebar">
Hi there!
</nav>
</body>
</html>
and a main.html:
<html>
<body>
<iframe src='content.html' hidden='true'></iframe>
<script>
var idframe = document.getElementsByTagName("iframe")[0];
var oldNode = idframe.contentWindow.document.getElementsByTagName("nav")[0];
var newNode = document.importNode(oldNode, true);
document.getElementsByTagName("body")[0].appendChild(newNode);
alert("HI!!!");
</script>
</body>
</html>
I am getting the error:
TypeError: Argument 1 of Document.importNode is not an object.
var newNode = document.importNode(oldNode, true);
What is the proper way to get an element form an iframe and insert it into my html?
You can only access content of the iframe document after the iframe document has been loaded. This can be accomplished different ways:
either by putting your accessing code into load handler of the main (that contains iframe element) document window,
or inside a DOMContentLoaded event listener of the document loaded in iframe.
Below is example of using load event of window of the main document:
window.addEventListener('load', function() {
var iframe = document.getElementsByTagName("iframe")[0];
var oldNode = iframe.contentWindow.document.getElementById("myNode");
var newNode = document.importNode(oldNode, true);
document.body.insertBefore(newNode, document.body.firstChild);
}, false);
Otherwise, iframe content is not yet loaded when you try to access it.
See the live example at JSFiddle (iframe content is placed encoded in the srcdoc attribute of the iframe just because I'm not aware of ability to create subdocuments at JSFiddle without creating a separate fiddle).

Can Zombie.js/Phantom.js be used to get HTML of newly open window by window.open?

I am trying to get html of newly open window after activating a link that uses javascript by zombie.js.
Here is the html code
<html>
<head>
<script type="text/javascript">
function newin(id)
{
var url="page.php?id="+id;
window.open(url,id,"toolbar=no,location=top,directories=no,status=no,scrollbars=yes,hscroll=no,resizable=yes,copyhistory=no,width=1025,height=1250");
}
</script>
</head>
<body>
<div>
123<br/>
234<br/>
345<br/>
</div>
</body>
The Script I am using is:
var Browser = require("zombie");
var browser = new Browser();
browser.visit("http://localhost:8000/testpage.html", function () {
browser.wait(function(){
var selector = "a[href*='newin']";
var elements = browser.queryAll(selector);
for (var e=0;e<elements.length;e++){
browser.clickLink(elements[e],function(){
browser.wait(function(){
console.log(browser.html());
});
});
}
});
});
I am not able to get HTML of any window.Any ideas what is wrong in this code ? Or is this possible with phantomjs??
Finally I come to know that if a link contains JavaScript directly in the href or action, Zombie seems to understand that as opening a new page like a normal hyperlink would. While the JavaScript is still executed correctly, the DOM is lost as a result of Zombie trying to load the invalid target as a new page.
A problematic link would be e.g.
test
There’s no support for javascript:links, it is still an open issue:
https://github.com/assaf/zombie/issues/700

Need javascript to auto-scroll to the target html element after page loads

I'm backend developer, new to javascript. Can anyone provide a few lines of script that will allow the page to auto-scroll to the "target" element after the page loads
<html>
<bod>
<p id="target">...</p> // auto-scroll here
</bod>
</html>
Thanks
You can use scrollIntoView on the element in window.onload event..
In your case you would be doing:
window.onload = function() {
var el = document.getElementById('target');
el.scrollIntoView(true);
}
Good docs can be found here:
MDN scrollIntoView
Also change your body tag to something like
<body onload="ScrollToTarget">
Then your function can be defined in the header as
function ScrollToTarget()
{
document.getElementById("target").scrollIntoView(true);
}

Categories

Resources