Display an entire html documention into a frame - javascript

I have an entire html document contained in a javascript string variable and I need to render it into a portion of my page. Have I to use frames?
How to do that?

With an iframe:
<iframe id="myiframe"></iframe>
var frame= document.getElementById('myiframe');
var doc= frame.contentDocument? frame.contentDocument : frame.contentWindow.document; // IE compatibility
doc.open('text/html');
doc.write(documenthtml);
doc.close();
Or, if you can cut off the bits you don't want (like any DOCTYPE and <head> element), you can just write innerHTML to any element. Normally handling [X][HT]ML with regexp or string processing is a really bad idea, but if you know that the body will always be contained within the exact strings ‘<body>...</body>’ and there will never be eg. any ‘<body>’ sequence hidden in a comment or script section, you might be able to get away with it.
To be honest, browsers at the moment are so forgiving they will typically even let you write a whole HTML document to a div's innerHTML, complete with doctype and ‘<head>’ in there! But that would be a bit naughty:
<div id="mycontent"></div>
document.getElementById('mycontent').innerHTML= htmldocument;
Here's a nasty hack combining both methods, to extract the body content without the use of regex:
<div id="mycontent"></div>
var frame= document.createElement('iframe');
frame.style.display= 'none';
document.body.appendChild(frame);
var doc= frame.contentDocument? frame.contentDocument : frame.contentWindow.document;
doc.open('text/html');
doc.write(documenthtml);
doc.close();
document.getElementById('mycontent').innerHTML= doc.body.innerHTML;
document.body.removeChild(frame);

document.getElementById('container').innerHTML = string;
This will load the contents of the string inside of an element (probably a div) with the id of "container".

myHtmlString = 'some stuff'; // whatever your big html string is
el = document.getElementById("myTarget"); // where you'd like the html to end up
el.innerHTML = myHtmlString; // set the HTML of el to be your big string.

Related

How to work around setting innerHTML causing escape sequences to expand?

I am trying to avoid a cross-site scripting vulnerability on my server. Before any user-inputted string is embedded within HTML or sent to client-side javascript code it is escaped ('<' replaced with '<', '&' replaced with '&', etc.) When embedding into HTML this works mostly fine; the HTML code produced does not contain any HTML elements inside the user-provided string. However, when the client-side javascript inserts HTML into the document, the escape sequences get expanded back into their special characters, which can result in user-inputted tags appearing in the document HTML. Here's approximately what I'm doing, javascript client-side:
// response_data received from XMLHttpRequest and parsed as JSON
var s = "";
for (var i = 0; i < response_data.length; ++i) {
s += "<p>";
s += response_data[i];
s += "</p>";
}
console.log(s);
elem.innerHTML = s;
Suppose the user inputted the string "abcde <script>alert("Hello!");</script>" earlier. Then response_data could be ["abcde <script>alert("Hello!");</script>"]. The print to console shows s to be "<p>abcde <script>alert("Hello!");</script></p>". However, when I assign elem.innerHTML, I can see in Inspect Element that the inner HTML of the element is actually <p>abcde <script>alert("Hello!");</script></p>! I don't think it executed, probably because of some browser security features regarding script tags within p tags, but it's obviously not very good. How do I work around this?
Code snippet (run and inspect element over the text created, it shows a script tag within the p tag):
var div_elem = document.querySelector("div");
div_elem.innerHTML = "<p><script>alert("Hello!");</script></p>";
<html>
<head></head>
<body>
<div></div>
</body>
</html>
Use innerText, it's like innerHTML but it's treated as pure text and won't decode the HTML entities.
Edit:
Set innerHTML to the p tags, then set the actual text using innerText on the tag
elem.innerHTML = "<p></p>";
elem.childNodes[0].innerText = s;

String Filtering.Need to remove the <style> tag and its contents and keep only the contents in <body>

In our project, we are getting a response from the DB. We are using the same string in two ways.
We have to display the text part alone in one line
We are putting the entire content as an HTML.
We are getting a response similar to this.
"<html><head><title>SomeTitle</title></head><style>a.hover{color:green}cc.a{color:red},pq.a{text-decoration:underline}</style> <body> Some content </body></html>"
I need to get the content only from the body using string manipulation.I need to filter out all the contents of the other tags as well.
For example
Final result should be
Some content
I used text() in some case but at times the content inside is also getting displayed. That is not allowed for me.
Note: There are times where I don't get so there should be a check for that as well.
any solution on this?
At times we are getting inside body as well. So is there any way to remove that part off?
for example
var str = "<html><head><title>SomeTitle</title></head><style>a.hover{color:green}cc.a{color:red},pq.a{text-decoration:underline}</style> <body> <style>.hello12{color:green}</style>Some content </body></html>";
and i should get just "some content"
Use DOMParser and get text content from body tag. Where querySelector can be used to get body element and get text content from textContent property.
var str = "<html><head><title>SomeTitle</title></head><style>a.hover{color:green}cc.a{color:red},pq.a{text-decoration:underline}</style> <body> Some content </body></html>";
var parser = new DOMParser();
var doc = parser.parseFromString(str, "text/html");
console.log(
doc.querySelector('body').textContent
)
FYI : To avoid script and style tag content use innerText property instead of textContent property.

Displaying uninterpreted HTML code into a html iframe

I want to display a text with CR and tabs (let's say the code is into a var shtml) into a iframe without losing the ASCII characters.
<!--var shtml-->
<HEAD>
</HEAD>
<BODY style="FONT-SIZE: 12.5pt">
mmm
</BODY>
My iframe
<iframe rows="5" cols="60" id="tahtml">
</iframe >
My JS
document.getElementById('tahtml').textContent = shtml; //innerText = shtml;
If I use .innerText then the code(shtml) is interpreted in Firefox. If I use .textContent the code(shtml) is displayed wihtout the ASCII characters. the jQuery .text() dose the same as .textContent.
Just like an <input>, a <textarea>'s DOM interface (HTMLTextAreaElement) has a value property, it looks like you want to set this property to shtml.
document.getElementById('tahtml').value = shtml;
Demo
For an <iframe> make the MIME for the page loaded inside it text/plain. This can be done by, for example, fetching an empty .txt or setting the src to data:text/pain,. Then you can do the following
// don't collapse whitespace, only needed to be done once
ifrmDoc.documentElement.style.whiteSpace = 'pre';
// set text
ifrmDoc.documentElement.innerHTML = shtml;
Where
var ifrm = document.getElementById('tahtml'),
ifrmDoc = ifrm.contentDocument || ifrm.contentWindow.document;
Of course, you could also do it by
writing the whole thing as a dataURI and pass it as the src
ifrm.src = 'data:text/pain,' + window.encodeURIComponent(shtml);
appending your text using by using DOM methods and text nodes
ifrmDoc.body.appendChild(ifrmDoc.createTextNode(shtml))
(this would still require whiteSpace: pre;)
making a <textarea> or <pre> in your <iframe>, into which you put shtml as value or a text node, respectively.

Converting html page represented as text to dom object

I have a text that represents some page. I need to convert this text to dom object, extract body element and append it to my dom.
I have used following code to convert text and extract body element:
$('body', $(text)).length
and:
$(text).filter('body').length
In both cases it returns 0...
To test: http://jsfiddle.net/wEyvr/1/
jQuery is parsing whole HTML in a non-standard way, so $(html) doesn't work as expected.
You can extract the content of the body tag using regexp and work from there:
// get the content of the body tags
var body = $(text.match(/<body[\s\S]*?>([\s\S]*?)<\/body>/i)[1]);
// append the content to our DOM
body.appendTo('body');
// bonus - to be able to fully use find -> we need to add single parent
var findBody = $("<body />").html(body.clone());
// now we are able to use selectors and have fun
findBody.find("div.cls").appendTo('body');
HERE is the working code.
EDIT: Changed the code to show both direct append and also using selectors.
Something like this:
var ifr = $("<iframe>"),
doc = ifr.appendTo("body")[0].contentWindow.document,
bodyLength;
doc.open();
doc.write(text);
doc.close();
bodyLength = ifr.contents().find("body").length;
ifr.remove();
alert(bodyLength);
http://jsfiddle.net/wEyvr/2/

document.write() and Ajax - Doesn't work, looking for an alternative

I recently asked a question here, and received a great response (which I will shortly be accepting the most active answer of, barring better alternatives arise) but unfortunately it seems the of the two options suggested, neither will be compatible with Ajax (or any dynamically added content that includes such "inline-relative jQuery")
Anyways, my question pertains to good ole' document.write().
While a page is still rendering, it works great; not so much when an appended snippet contains it. Are there any alternatives that won't destroy the existing page content, yet still append a string inline, as in where the call is occurring?
In other words, is there a way/alternative to document.write() that when called post-render, doesn't destroy existing page content? An Ajax friendly version so to speak?
This is where I'm going:
var _inline_relative_index = 0;
function $_inlineRelative(){
// i hate non-dedicated string concatenation operators
var inline_relative_id = ('_inline_relative_{index}').replace('{index}', (++_inline_relative_index).toString());
document.write(('<br id="{id}" />').replace('{id}', inline_relative_id));
return $(document.getElementById(inline_relative_id)).remove().prev('script');
}
And then:
<div>
<script type="text/javascript">
(function($script){
// the container <div> background is now red.
$script.parent().css({ 'background-color': '#f00' });
})($_inlineRelative());
</script>
</div>
you have access to the innerHTML property of each DOM node. If you set it straight out you might destroy elements, but if you append more HTML to it, it'll preserve the existing HTML.
document.body.innerHTML += '<div id="foo">bar baz</div>';
There are all sorts of nuances to the sledgehammer that is innerHTML, so I highly recommend using a library such as jQuery to normalize everything for you.
You can assign id to the script tag and replace it with the new node.
<p>Foo</p>
<script type="text/javascript" id="placeholder">
var newElement = document.createElement('div');
newElement.id='bar';
var oldElement = document.getElementById('placeholder');
oldElement.parentNode.replaceChild(newElement, oldElement);
</script>
<p>Baz</p>
And if you need to insert html from string, than you can do it like so:
var div = document.createElement('div');
div.innerHTML = '<div id="bar"></div>';
var placeholder = document.getElementById('placeholder'),
container = placeholder.parentNode,
elems = div.childNodes,
el;
while (el = elems[0]) {
div.removeChild(el);
container.insertBefore(el, placeholder);
}
container.removeChild(placeholder);

Categories