What exactly do I have to escape inside a `script` element? - javascript

What parts of JavaScript code do I have to escape inside a script element in a HTML page? Is <>& enough or too much?
[EDIT] This is related to this bug: http://code.google.com/p/rendersnake/issues/detail?id=15#c6 comment #6

In HTML (and XHTML if you're an evil person that sends your XHTML pages as text/html), script tags are #CDATA, and therefore, the only thing that you shouldn't have in the content is </script>, as that is all that the parser looks for to signal the end of the tag. Don't escape anything; just make sure you don't have </script> in the tag content. For example, if you have a string with a closing script tag, split it up:
var a = '</scr' + 'ipt>';
In XHTML, sent as application/xhtml+xml, script tags are #PCDATA, and therefore, escaping < and & is necessary, unless you can use a <![CDATA[ ... ]]> block to change to #CDATA parsing mode, but in that case, remember that you can't have ]]> in your tag content.

Generally, the only thing I escape is the / in closing tags. Thus:
var msg = "<p>Do you <em>really<\/em> think so, Miss Worthington?<\/p>";
For the rest, I rely on commenting out the entire thing:
<script>
<!--
var msg = "<p>Do you <em>really<\/em> think so, Miss Worthington?<\/p>";
-->
</script>
The comment takes care of the HTML opening tags.

Escaped <, > and & does not work with many browsers. It is good an enough if you put everything inside a CDATA section. Please note that the CDATA section itself will have to be in a JavaScript comment, for this to work with all browsers.
<script>
// <![CDATA[
script here
// ]]>
</script>

Related

Javascript weird logical operator behavior using JSF : `&&`

I am trying to work on a keydown event in javascript and I am currently stuck on something that never happened to me before :
var maxL = $("#myField").attr("maxLength")
console.log("Maximum Length : " + maxL);
if (e.key.length === 1 && str.length >= parseInt(maxL)) {
console.log(">>>> in if");
console.log(">>>> e.char == \"" + e.key + "\"");
e.preventDefault();
}
When I load the page, it fails. On debug, my server console logs this error :
Error Parsing /folder/myPage.xhtml: Error Traced[line: 384] The entity name
must immediately follow the '&' in the entity reference.
where 384 is the line where the if is
I tried both conditions individually and they work just fine, which leads me to think there is something wrong with the "&&" operator.
If this is of any importance, I work on a WebSphere server in JSF with PrimeFaces and I try to run it in Chrome. The javascript is embedded inside a div in order to delete it after the page is loaded :
<div id="deleteScript">
<SCRIPT>
//my script code
$("#deleteScript").remove();
</SCRIPT>
</div>
I actually had to use the following syntax :
<div id="deleteScript">
<SCRIPT>
<!--//--><![CDATA[//><!--
//my script code
$("#deleteScript").remove();
//--><!]]>
</SCRIPT>
</div>
Which I could find on this other answer. BalusC seems to think that we should only use this solution if we work for older web browsers, but it appears that it becomes necessary when we work on older JSF servers as well.
Looks like the jsf is interpreting parts of your js as if it was xhtml.
Wrap your script (after the <script> tag) with <![CDATA[ and ]]> to make it interpret the content literally:
<script>
<![CDATA[
//your code
]]>
</script>
The <![CDATA[ ... ]]> tags are used in XML files to allow the use of characters that usually are reserved such as '&', '>' etc. You can read more on this answer and here.
This is not a problem with the browser; It looks like your server is attempting to operate on the "&&". Maybe you have to escape it in your code.
The problem comes from the fact that you have your JS written in the html script tag. What I would do if I were you is:
<div id="deleteScript">
<script src="path/to/script.js"></script>
</div>
Since the script tag is within the div with ID "deleteScript", the element will exist when the script loads and you can delete it.

Syntax error in JS intended for website "flashing" fix

1 if (document.getElementById) {
2 document.write(
3 '<style type="text/css" media="screen">
4 #element1, .element2 {display:none;}
5 </style>'
6 );
7 }
I get "Uncaught SyntaxError: Unexpected token ILLEGAL" on line 3. This is probably soo easy for you guys, but I just started with JS and like always - it's a whole new language.
I could use 2 kinds of advice if they are different..
How to use this code in file.php between < script > tags?
How to use this code from seperate file.js file?
I know how to link .js, don't worry about that.
For the record, this is intended to be in < head > and to hide some html elements before they are fully loaded if Im not mistaken. Experts, feel free to confirm this or give me a better solution if there is any, thank you!
In JavaScript, strings cannot be broken up into multiple lines. The new line character is not a valid string character. You will have to close the string on each line and add the string concatenation operator after each line that is continued on the next line (or before each line that is a continuation of the previous line, like so:
if (document.getElementById)
{
document.write(
'<style type="text/css" media="screen">' +
'#element1, .element2 {display:none;}'
+ '</style>');
}
This will get rid of the error, but it will not achieve the desired effect of hiding elements. document.write automatically calls document.open() if an HTML document has already been opened (which it has, if the script is executing.) document.open will wipe out the contents of the page, including the script that contains that code. You will be left with a blank page.
As #Chris says, you can include script tags in the output of a php script simply by writing the script outside of the php parsing context. i.e.
?>
<head>
<!-- other stuff -->
<script type="text/javascript">// type="text/javascript" is only needed for browser versions that do not support HTML5
// place code here
</script>
<!-- other stuff -->
</head>
<?php
On the other hand, if you wish to include a separate, external JavaScript file, replace that script tag in the code snippet above with
<script src="[absolute or relative path to script]" type="text/javascript">
</script>
Note that script tags are not self-closing, so even though this script tag has no contents, you cannot use the self closing tag syntax, as in <script ... />
As for the problem of how to handle the flickering problem, this Stack Overflow post may be helpful:
Page Transitioning - Ways to Avoid the "flicker"
I'm not an expert on php, but this site says this is your basic syntax for embedded php.
http://php.net/manual/en/language.basic-syntax.phpmode.php
<p>This is going to be ignored by PHP and displayed by the browser.</p>
<?php echo 'While this is going to be parsed.'; ?>
<p>This will also be ignored by PHP and displayed by the browser.</p>
Also, it looks like you probably need to escape a few things for that tag.
'<style type=\"text/css\" media=\"screen\">
#element1, .element2 {display:none;}
</style>'

document.write - replace "</script>" tags with "<\/script>"

I've already tested this code manually adding the backslash to all the </script> tags, and
if all the tags become <\/script> the code works.
var iframe = document.createElement('iframe');
var html = '<html><head><script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.js"><\/script><script type="text/javascript">$(window).load(function(){function popo1(){alert("ciaoooo!");}popo1();$(".eccolo").html("<br><br><br><br>xD sygsyusgsuygsus ysg usygsuys");});<\/script></head><body><div class="eccolo"></div></body></html>';
document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();
DEMO
But I need to dynamically auto-replace all the </script> tags with <\/script> using something like
XXX.replace(/<\/script>/ig, "<\\\/script>");
according to this post
but seems that this type of replace is actually not working...
var iframe = document.createElement('iframe');
var XXX = '<html><head><script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.js"><\/script><script type="text/javascript">$(window).load(function(){function popo1(){alert("ciaoooo!");}popo1();$(".eccolo").html("<br><br><br><br>xD sygsyusgsuygsus ysg usygsuys");});<\/script></head><body><div class="eccolo"></div></body></html>';
var YYY = XXX.replace(/<\/script>/ig, "<\\\/script>");
document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(YYY);
iframe.contentWindow.document.close();
DEMO
Unfortunately I can't use .js files, so I hope that there is a way to properly do the tags replace
But what if I want to dynamically replace all the </script> tags with <\/script>...
In a comment below, you've said:
I'm getting the var XXX from an input that always changes.. I just added a defined value (var XXX='<html><head>...) in my question just for example
That's a very different thing than what's in your question. If you're saying that you'll receive input in the XXX string whose content (in memory, not a string literal) looks like this:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.js"></script>
<script type="text/javascript">
$(window).load(function() {
function popo1() {
alert("ciaoooo!");
}
popo1();
$(".eccolo").html("<br><br><br><br>xD sygsyusgsuygsus ysg usygsuys");
});
</script>
</head>
<body>
<div class="eccolo"></div>
</body>
</html>
...then than input is perfectly fine and can be used as-is to set the content of the iframe. You don't have to do the replacement on it. The post you linked to doesn't relate to what you're doing.
But if you're saying you'll get input like this:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.js"></script>
<script type="text/javascript">
$(window).load(function() {
var str = "The problem is here: </script>"; // <======
});
</script>
</head>
<body>
<div class="eccolo"></div>
</body>
</html>
...then you're in the same unfortunate position as the HTML parser: You don't know when the substring </script> actually ends a script element, or is text within a JavaScript string literal (or a comment). If you had a web page with that content, the HTML parser would conclude the script element ended immediately after The problem is here:. And indeed, if you output that content to an iframe via document.write, the parser will choke on it. The line:
var str = "The problem is here: </script>";
needs to be
var str = "The problem is here: <\/script>";
// or
var str = "The problem is here: </sc" + "ript>";
// or similar
...in order to avoid tripping up the HTML parser. (It would be fine in a .js file, but that's not your use case.)
Fundamentally, if you're receiving input with something like that in it, the person giving it to you is giving you invalid input. The substring </script> cannot appear in JavaScript code within <script>/</script> tags — not in a string literal, not in a comment, nowhere.
The answer defined by the spec is: Don't try to figure it out, require that it be correct. But if you know the scripts are JavaScript, and you really really want to allow invalid input and correct it, you'll need a JavaScript parser. That sounds outrageous, but Esprima is exactly that, there's jsparser in the Meteor stuff, and there may be others. You'd scan the string you're given to find <script>, then let the JavaScript parser take over and parse the code (you'll probably need to modify it so it knows to stop in </script> outside of a string literal / comment). Then take the text consumed by the parser, use your replace to convert any </script> in the code's text to <\/script>, and continue on.
It's non-trivial, which is why the spec doesn't require HTML parsers to do it.
But again, if the input is like your example in your question (without the backslashes you used to avoid this problem with your string literal), you don't have to do a replace at all. Just output it to the iframe, and it will work fine.
You can create script tag programatically and append in the head tag after page is loaded.
Following is the code and DEMO
var iframe = document.createElement('iframe');
var html = '<html><head></head><body><div class="eccolo"></div></body></html>';
document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
var script1 = iframe.contentWindow.document.createElement('script');
var script2 = iframe.contentWindow.document.createElement('script');
script2.textContent = '$(window).load(function(){function popo1(){alert("ciaoooo!");}popo1();$(".eccolo").html("<br><br><br><br>xD sygsyusgsuygsus ysg usygsuys");});'
var head = iframe.contentWindow.document.querySelector('head');
head.appendChild(script1);
script1.onload = function() {
head.appendChild(script2);
}
script1.src = 'http://code.jquery.com/jquery-1.11.0.js';
iframe.contentWindow.document.close();
Hope it helps...

Syntax error while trying to add CDATA within script tags dynamically

So there is an ad code which I try to add to the DOM dynamically, something that looks like this:
<script type="text/javascript"><!--<![CDATA[
JAVASCRIPT CODE
//]]>--></script>
If I paste this code directly in the source code, it works, but if I try to insert it to the DOM with jQuery it throws some untraceable errors - at least I cant trace it. Actually this:
The interesting part is that Firebug connects this error to random scripts in the page which contain jQuery. The ad code is inserted into the DOM this way /element is a jQuery object/:
element.html(data.content);
What I have tried yet:
I have tried to remove the <!-- --> html comment tags.
I have tried to wrap the wole code to a script tag dynamically created by jQuery.
I even tried to remove the CDATA tags, but that broke everything, I think it is important for the main ad handler script provided by the ad manager company.
Any help would be appreciated, thanks in advance!
(Please dont care about the method, it must be done with ajax.)
EDIT: The problem still persists, but I think there must be a problem with the ad code, so I accepted the first useful answer for this topic.
Try like this:
<script type="text/javascript">
/* <![CDATA[ */
...
/* ]]> */
</script>
<script type="text/javascript">
//<![CDATA[
...
//]]>
</script>
<!-- (For styles, it is different) -->
<style type="text/css">
/*<![CDATA[*/
...
/*]]>*/
</style>
And if you really need compatibility with very old browsers that do not recognize the script or style tags resulting in their contents displayed on the page, you can use this:
<script type="text/javascript"><!--//--><![CDATA[//><!--
...
//--><!]]></script>
<!-- (For styles, it is different) -->
<style type="text/css"><!--/*--><![CDATA[/*><!--*/
...
/*]]>*/--></style>
With <![CDATA[ you can embed JS in XML (and XHTML) documents without the need to replace special XML characters like <, >, &, etc by XML entities <, >, & etc
Use this one
<script type="text/javascript">
//<![CDATA[
//YOUR CODE
//]]>
</script>
Let me know if problem still persist.

XSL parsing is shortening script tag causing issues in IE

I have a C# application that generates an html document from transforming an xml file with an xsl file. In my xsl template I reference an external javascript file like this:
<script language="javascript" type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js" ></script>
after the transformation the previous line is being translated to:
<script language="javascript" type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js" />
For Firefox and Chrome this is no problem however IE throws an 'object not found' error and does not work. Any suggestions for getting IE to like this syntax? Or is there something I need to do in my xsl (or the C# XslCompiledTransform class) to preserve the syntax?
Solution: By placing <![CDATA[ <!-- Some Comment --> ]]> between the script tags the parser doesn't attempt to shorten the ending tag.
Try putting an empty CDATA section inside. This should force the parser to not mess with your script tags.
<script language="javascript" type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js" ><![CDATA[ ]]></script>
Actually, bobince is right. If you use...
<xsl:output method="html"/>
... you can get the right output for XslCompiledTransform, but you have to use its OutputSettings with the XmlWriter you use as output object:
XslCompiledTransform xslt = new XslCompiledTransform(true);
xslt.Load("stylesheetFile.xsl");
XmlWriter outputWriter = XmlWriter.Create("outputfile.html", xslt.OutputSettings);
xslt.Transform(input, null, outputWriter);
This way, the method="html" works, so script, textarea et al keep their closing tags.
Generate an XML comment inside <script>:
<script type="text/javascript" src="..." ><xsl:comment/></script>
The output will be:
<script type="text/javascript" src="..."><!-- --></script>
which is semantically equivalent to an empty <script>.
Not preserve it, but if you're producing backwards-compatible HTML you need to tell the XSLT processor that HTML-compatible-XHTML is what you want and not generic self-closing-allowed XML:
<xsl:output method="xhtml"/>
Unfortunately, the ‘xhtml’ output method is an XSLT 2.0 extension that .NET's XslTransform doesn't support, so you have to use good old legacy HTML instead:
<xsl:output method="html"/>
(and appropriate HTML 4.01 DOCTYPE instead of XHTML.)
Putting some dummy content in <script> may solve your immediate problem, but there may be other places where the default ‘xml’ output method will produce inappropriate markup for legacy browsers like IE.
Re: comment. Hmm... you're right! The ‘html’ output method does not produce valid HTML; the ‘xhtml’ output method does not produce XHTML conformant to XHTML Appendix C. What's more, ‘html’ includes provisions such as not escaping ‘<’, and de-escaping the ancient and broken-even-for-its-time Netscape 4 construct ‘&{...}’, that will take your working markup and make it invalid.
So changing the output method is completely useless, and the only way to produce working HTML with XSLT is:
a. hack every occurrence of an inappropriate self-closing tag manually (there are likely to be many more than just this script), or
b. post-process with something like HTMLTidy.
How sad, and sloppy that this hasn't been addressed even in XSLT 2.0.
had the same prob. right now, this is my solution:
<xsl:text disable-output-escaping="yes">
<![CDATA[<script type="text/javascript" src="" ></script>]]>
</xsl:text>
Just Missing the closing </script>.
<xsl:output method="html" omit-xml-declaration="yes" doctype-system="about:legacy-compat" encoding="utf-8"/>
should solve your probleme

Categories

Resources