How can I display the HTML content of a XHR responseText in a DIV and strip out its <script> tags and append them to the head tag? (using Google Closure)
Something like extractScripts in Prototype JS.
If the responseText is a whole web page with HTML and script tags, then maybe you should just attach it to an iFrame and the iFrame src and let the browser manage it all for you rather than put it in a DIV where you have to manage the different parts of the web page.
If you really want to get the responseText and put it directly into a div in your own document, then you have a couple options.
First, if the response is just an HTML fragment with embedded script tags (not a whole web page), then you can just read the whole response into a JS variable and then assign it to the .innerHTML attribute of your DIV. The browser will parse the HTML, including the embedded tags and evaluate it as if it was originally part of that div (except the script execution timing obviously isn't until right after you assign the .innerHTML.
As an example:
var myDiv = document.getElementById("myDiv");
myDiv.innerHTML = responseText;
Second, if there's some reason you want to pull out the tags separately (and I can't think of such a reason versus the first option), then you'll have to parse the start and end script tags out of the responseText yourself, put the JS code text in between them into a JS variable and use eval on that variable to execute it and make it part of your document. Then, assign the remaining HTML to the innerHTML attribute of your div as in the example above.
If that script has document.write in it, that won't work this second way because there's no location context for the document.write. If those script tags rely on any page loading methods like onload, then the scripts also won't see those events (except if it's the src of an iFrame.
Related
I'm playing with inject JavaScript code into an existing DOM.
I've seen that if I put the script by hand in the browser's DOM elements inspector
<script>alert("XSS test");</script>
the script node is added to the DOM, but it has no effect. I mean, no alert box is shown.
On the other hand, if I put the script as plain text through the JavaScript console using document.write(), in this case the code got parsed and executed immediately, and the alert box is shown as expected.
document.write('<script>alert("XSS test");</script>');
I'm used to see that hand made changes to the DOM elements in the inspector reflects immediately in the page, while it seems that JavaScript nodes are an exception.
Why web browsers do not execute JavaScript nodes put by hand in the inspector?
Is there another way to send the script node to the DOM and make it run immediately?
script tags added via innerHTML and related methods (insertAdjacentHTML, etc.) are not executed. (The exact rules are somewhere in the script portion of the HTML specification but it's heavy going.) This may be because early on it was identified that poorly-written pages might use innerHTML and such to append user content, and so not executing it was a quick and simple way to avoid very, very basic XSS attacks. But only very, very basic ones.
You can add a script tag to the DOM and have it executed by creating and appending a script tag:
const script = document.createElement("script");
script.textContent = `console.log("Hi there");`;
document.body.appendChild(script);
You can do that from the console tab in devtools, for instance, rather than the DOM inspector tab.
try going to the web page you want and then in the URL bar at the top add
javascript:[your script]
for example
javascript:alert("Hello World!");
This:
function myFunction()
{
document.write("sup");
}
called in html like:
<div id="myDiv">
<script>myFunction();</script>
</div>t
adds a string sup to the myDiv div element. Which is what I want, exactly. However, this:
function loadFile(uri)
{
var r = new XMLHttpRequest();
document.write("trying to open: " + uri);
r.open('GET', uri, true);
r.send(null);
r.onreadystatechange = function()
{
if (r.readyState == 4)
{
myFunction();
}
}
}
function myFunction()
{
document.write("sup");
}
called like this:
<div id="myDiv">
<script>loadFile("filename.txt");</script>
</div>
seems to be overwriting my whole html file. I.e. when I run it in Firefox it shows me only the string sup (that's the whole content of the page) but the page seems to be still loading (the loading icon of FF is still there animating, apparently infinitely).
First of all, this is going to be used only locally, offline, as a fast and handy way of presenting data (using html+js and web browser instead of plain text file). What I want is to load a local text file and then put some of its content as a part of the html page. The same as in my first example but with loading the text file first.
The issue is that when you run document.write after the document has loaded, it overwrites the entire document. If it is run before that, it does not overwrite it.
What you want to do is set the innerHtml of a specific element, something like:
document.getElementById("myDiv").innerHTML="Sup";
Lets go over what a browser does when it receives an html file.
The window document is opened for writing. Imagine opening a text file.
Browser writes the contents to the document. A lot of magic happens in this step - objects get created and html rendered as boxes.
The window document closes the document. Kind of like saving the text file.
Now, modern browsers also expose a document API that allow you to do exactly those tasks using javascript.
You can open a document for writing using document.open(). You can also start writing content to the document using document.write(). Finally, you can close the document for writing using document.close(). Since the document always needs to be opened for writing before you write, calling document.write() always results in an implicit document.open().
Interspersing document.write() calls throughout an html body is a commonly used technique used to insert string contents dynamically into an html page.
For example, if you execute document.write("<p>holla</p>") in the body of an html file, the browser will do the following upon receiving the html file.
Open the document for writing.
Start writing the html contents to the document.
JavaScript engine will execute document.write() when it encounters it and then write "<p>holla</p>" into that specific line in the document, just as if the string was already part of the html file! Since document.write() is called during the parsing of an html file, it just gets parsed as part of the page.
Close the document for writing. Parsing complete.
If that's how you use document.write(), there would have been no surprise. Instead, you call document.write() after the html is parsed.
So what do you think should happen?
As I mentioned before, a document needs to be opened for writing before it is written to. In theory, we could either append to the existing content or just overwrite it. Well, if we append to the content, we'll end up with an invalid html page because the new values will appear after the closing tags. So the more sensible behavior is to overwrite the content and that's exactly what happens.
This question already has answers here:
Why am I seeing 'function not defined' on my error console when I'm sure my function IS defined?
(3 answers)
Closed 4 months ago.
I'm using an html script tag with the src attribute as follows:
<script src="http://...">
</script>
I need to also put a bit more code to redirect the page after the script has run - is it valid/acceptable to add the script between the existing script tags or should I add another script on the end?
This:
<script src="http://...">
...do something else he
</script>
Or:
<script src="http://...">
</script>
<script>
...my other code here
</script>
No it can't.
Use the bottom one.
The long answer…
w3c states
“The SCRIPT element places a script within a document. This element may appear any number of times in the HEAD or BODY of an HTML document.
The script may be defined within the contents of the SCRIPT element or in an external file. If the src attribute is not set, user agents must interpret the contents of the element as the script. If the src has a URI value, user agents must ignore the element's contents and retrieve the script via the URI.”
Source: http://www.w3.org/TR/html401/interact/scripts.html
Oh, boy. you can't write code inside the script tag having src tag.
You have to use different script tags.
As js loads top to bottom. Your code will work fine.
If a script element has a src attribute, the content must be ignored, any other behaviour is non-conformant.
It has been suggested in blogs (as a hack) to put content in the element knowing that it won't be evaluated, then use DOM methods to get the content as a string and either eval it or insert it in a new script element. Neither of these are a good idea.
So better add another script tag after the initial script tag with the src in it.
I've just tried this and the code in between the script tags wont run,
I imagine this is because as soon as you add a 'src' attribute the code within the script tags is ignored.
However if you simply want to redirect the page after the script is run you just need
window.location = "../YourRedirectPage";
At the end of the code in the external file
I want to add a script that applies to a DOM object of a certain type right after it is loaded/rendered. This type of object always comes together with the javascript script, and I want to put them together within some tag. Is it right to do it as below? If so, I suspect span is not the best tag to be used here because it may interact with the way the element inside will be displayed. What tag should I use?
<span>
<div>the dom object to be modified by the script</div>
<script>theJavascriptFunctionThatModifiesTheDomObject()</script>
</span>
I doubt this is the best way to load your script just after a particular element has been loaded by DOM due to these reasons:-
It makes your page load slower.
User will see your complete page in a discrete way.
Instead you should do this:-
Specify a selector to your element.
Include your single javascript code at the end of body.
Update DOM elements using that script.
EDIT:
Solution1: Append your JS at the end of body so that it has access to all the DOM elements.
Since you are injecting the element in DOM using ajax, you can define a success handler for XHR object which will modify your element in DOM.
Solution2: You can define a separate method in your JS and bind this method on some event. In your HTML markup define a data-event attribute and in your success handler append the element to DOM, extract the data-event using jquery data method and trigger that event.
Atleast it will keep you markup far away from scripting logic.
Some useful Links:
Best practices for speeding up your website - yahoo
Why we should load scripts at end - SO Link
The problem here is the script tag does not know where it is located in the DOM. It would be better to do something like add a class to the element[s] you want to alter. On DOM ready, you look up the element[s] and do your magic.
I would avoid this approach; scripts block the page loading
– so if you did this after several dom elements the page would run slow (or not at all if errors were found)
Try using jquery onready - example here : http://api.jquery.com/ready/
And scripts [usually] need to go on the bottom of the page to allow the page to load first
…there are exceptions to this rule such as the well known modernizer script library that needs to go first so it can evaluate the dom as it loads
Is there a general rule, when one should use document.write to change the website content and when to use .innerHTML?
So far my rules were:
1) Use document.write when adding new content
2) Use .innerHTML when changing existing content
But I got confused, since someone told me that on the one hand .innerHTML is a strange Microsoft standard, but on the other hand I read that document.write is not allowed in XHTML.
Which structures should I use to manipulate my source code with JavaScript?
innerHTML can be used to change the contents of the DOM by string munging. So if you wanted to add a paragraph with some text at the end of a selected element you could so something like
document.getElementById( 'some-id' ).innerHTML += '<p>here is some text</p>'
Though I'd suggest using as much DOM manipulation specific API as possible (e.g. document.createElement, document.createDocumentFragment, <element>.appendChild, etc.). But that's just my preference.
The only time I've seen applicable use of document.write is in the HTML5 Boilerplate (look at how it checks if jQuery was loaded properly). Other than that, I would stay away from it.
innerHTML and document.write are not really comparable methods to dynamically change/insert content, since their usage is different and for different purposes.
document.write should be tied to specific use cases. When a page has been loaded and the DOM is ready you cannot use that method anymore. That's why is generally most used in conditional statements in which you can use it to syncronously load external javascript file (javascript libraries), including <script> blocks (e.g. when you load jQuery from the CDN in HTML5 Boilerplate).
What you read about this method and XHTML is true when the page is served along with the application/xhtml+xml mime type: From w3.org
document.write (like document.writeln) does not work in XHTML documents (you'll get a "Operation is not supported" (NS_ERROR_DOM_NOT_SUPPORTED_ERR) error on the error console). This is the case if opening a local file with a .xhtml file extension or for any document served with an application/xhtml+xml MIME type
Another difference between these approaches is related on insertion node: when you use .innerHTML method you can choose where to append the content, while using document.write the insertion node is always the part of document in which this method was used.
1) document.write() puts the contents directly to the browser where the user can see it.
this method writes HTML expressions or JavaScript code to a document.
The below example will just print ‘Hello World’ into the document
<html>
<body>
<script>
document.write("Hello World!");
</script>
</body>
</html>
2) document.innerHTML changes the inner content of an element
It changes the existing content of an element
The below code will change the content of p tag
<html>
<body>
<p id="test" onclick="myFun()">Click me to change my HTML content or my inner HTML</p>
<script>
function myFun() {
document.getElementById("test").innerHTML = "I'm replaced by exiesting element";
}
</script>
</body>
</html>
you could use document.write() without any connected HTML, but if you already have HTML that you want to change, then document.innerHTML would be the obvious choice.
I agree with the above comments. Basically:
document.write can be useful while the page is loading, to output new HTML tags or content while the browser is building the document object model. That content is output precisely where the JavaScript statement is embedded.
.innerHTML is useful at any time to insert new HTML tags/content as a string, and can be more easily directed to specific elements in the DOM regardless of when/where the JavaScript is run.
A couple of additional notes...
When document.write is called from a script outside of the body element, its output will be appended to the body element if called while the page is loading; but once the page is loaded, that same document.write will overwrite the entire document object model, effectively erasing your page. It all depends on the timing of document.write with the page load.
If you are using document.write to append new content to the end of the body element, you may be better off using this:
document.body.innerHTML += "A string of new content!";
It's a bit safer.