how to escape JavaScript code in HTML - javascript

I have some addHtml JavaScript function in my JS code. I wonder how to escape HTML/JS code properly. Basically, what I am trying right now is:
addHtml("<a onclick=\"alert(\\\"Hello from JS\\\")\">click me</a>")
However, that doesn't work. It adds the a element but it doesn't do anything when I click it.
I don't want to replace all " by ' as a workaround. (If I do, it works.)

I wonder how to escape HTML/JS code properly.
To insert string content into an HTML event handler attribute:
(1) Encode it as a JavaScript string literal:
alert("Hello \"world\"");
(2) Encode the complete JavaScript statement as HTML:
<a onclick="alert("Hello \"world\""">foo</a>
And since you seem to be including that HTML inside a JavaScript string literal again, you have to JS-encode it again:
html= "<a onclick=\"alert("Hello \\"world\\""\">foo<\/a>";
Notice the double-backslashes and also the <\/, which is necessary to avoid a </ sequence in a <script> block, which would otherwise be invalid and might break.
You can make this less bad for yourself by mixing single and double quotes to cut down on the amount of double-escaping going on, but you can't solve it for the general case; there are many other characters that will cause problems.
All this escaping horror is another good reason to avoid inline event handler attributes. Slinging strings full of HTML around sucks. Use DOM-style methods, assigning event handlers directly from JavaScript instead:
var a= document.createElement('a');
a.onclick= function() {
alert('Hello from normal JS with no extra escaping!');
};

My solution would be
addHtml('<a onclick="alert(\'Hello from JS\')">click me</a>')
I typically use single quotes in Javascript strings, and double quotes in HTML attributes. I think it's a good rule to follow.

How about this?
addHtml("<a onclick=\"alert("Hello from JS")\">click me</a>");
It worked when I tested in Firefox, at any rate.

addHtml("<a onclick='alert(\"Hello from JS\")'>click me</a>")

The problem is probably this...
As your code is now, it will add this to the HTML
<a onclick="alert("Hello from Javascript")"></a>
This is assuming the escape slashes will all be removed properly.
The problem is that the alert can't handle the " inside it... you'll have to change those quotes to single quotes.
addHtml("<a onclick=\"alert(\\\'Hello from JS\\\')\">click me</a>")
That should work for you.

What does the final HTML rendered in the browser look like ? I think the three slashes might be causing an issue .

Related

AngularJS escaping quotes

I am having a hard time escaping quotes in from the following statement
on-mouseover="mouseover('{{landmark.name}}')"
where landmark.name="Duke's Car"
I tried various solutions like:
$scope.escapeQuotes= function(str) {
return str
.replace(/('|\")/g, "\\$1")
.replace(/("|\")/g, "\\$1")
}
But it does not seem to work. Looks like a simple problem but I am having a hard time finding a solution. Any pointers are welcome.
I'd say use ng-mouseover instead, you don't need to worry about that escaping things
ng-mouseover="mouseover(landmark.name)"
Code
$scope.mouseover = function(name){
console.log("Value output:", name)
}
Pankaj's answer is better but if you absolutely need to use on-mousever, you can replace single and double quotation marks with their HTML entities which will prevent them from breaking the outer quotes of the mousever function call:
on-mouseover="mouseover(\"{{ landmark.name.replace(/'/g, "&apos;").replace(/"/g, """) }}\")"
Then landmark.name can safely contain single or quotes and it won't cause any problems.
So if landmark.name equals `Duke's Car", your HTML would renderlike this (after Angular compiles it):
on-mousever="mouseover(\"Duke&apos;s Car\")"
Whenever this is rendered by the browser, the &apos; HTML entity will become a single quotation mark: '

How do I store a block of HTML in string variable?

I am trying to assign a HTML block to a string variable in JavaScript. However enclosing quotation/speech marks aren't doing the trick. Is there another way to do this.
This is what I have tried:
var huge = '<div class="row"><div class.../div>'
I've realised I could put / before the quotation marks. However given the size of the block that doesn't seem like a great solution.
EDIT: Sorry, wasn't very clear. I meant that within the block of html code there are multiple sets of double quotes/single quotes which clash with the enclosing single quotes.
If your problem is you have a huge block of code consisting of both single quotes and double quotes, your options are to either escape it server-side first, or you'll have to manually format it.
var huge = "<div class=\"foo\">bar</div>";
Try putting the code in your HTML, rather than in your javascript, but hiding it with CSS. You can then either access it as a DOM element or use .html() to get it as a string.

Escaping JSON in JSPX

I want to initialize a Javascript variable from some JSON (generated via Jackson) in my JSPX, something like this:
<script>
var x = <c:out value="${myJson}" />;
</script>
But the output I get looks like:
<script>
var x = {"foo":&#034bar&#034};
</script>
I see what you did there, HTML-escaping the string. Obviously, I can't leave it completely unescaped because angle brackets in the data could break the page. But I don't really need all the quotes to be escaped, since I'm not putting the JSON within an attribute value, do I?
Now, this looks like it would be a perfectly valid way to write a script in HTML, just needlessly complicated (like, say, replacing spaces with ). As it turns out, it works just fine in XHTML, but with an HTML content type, I get an error, both in Firefox and IE. I'm not sure of the rationale, but that's how it is.
So, what's the best approach here? Do I really want to simply escape angle brackets but not escape double quotes, or are there any other gotchas? Is there a tag out there that would replace c:out (I know there are Spring tags for escaping Javascript, but that's still not the right kind of escaping)? How do people get this to work?
BTW, yes, I could make a separate AJAX call, but an extra round trip just to work around this problem seems silly.
UPDATE
I had a lot to learn about CDATA vs. PCDATA and how HTML is different from XHTML. Here I thought JSPX would make polyglot markup easy, but it turns out to be, as someone put it, a big ball of nasty.
For HTML, the <script> element has a CDATA content model (not to be confused with CDATA sections), which means nothing can be escaped, but </ must be absolutely avoided.
In the special case of JSON, where end tags can only occur within a quoted string, this therefore means the safe way to escape is to use Javascript (rather than HTML) escaping and replace </ with <\/.
For XHTML (if you care about such things) on the other hand, you just XML-escape everything as usual (& becomes &, etc.) and it all works beautifully. A compatible solution would have to use CDATA with guarding comments (<!--/*--><![CDATA[/*><!--*/ etc.) around the entire <script> body and then escape any occurrences of ]]> within the JSON; furthermore, I'd still escape </ too just to be safe. Big ball of nasty, indeed, but at least it can be automated.
set escapeXml=false
<c:out value="${myJson}" escapeXml="false"/>
OK, answering my own question here, after much research and no real help.
Based my "update" above, the most straightforward way targeting HTML is just:
<script>
var x = ${fn:replace(myJson, "\</", "\<\\/")};
</script>
Ugly but simple.
This will not yield valid XML or XHTML, unfortunately. If you really need that, the original c:out will work fine, though it will not yield valid HTML. And if you really need a single solution to work on both, you probably need a custom taglib (or TAGX) that will either switch from the content type or do all of the following:
wrap the script body in a comment-guarded CDATA section
replace each </ with <\/
replace each ]]> with ]]\>

Too many quotes within quotes -- what to do?

Here is a section of code used by CKEditor on my website:
CKEDITOR.config.IPS_BBCODE = {"acronym":{"id":"8","title":"Acronym","desc":"Allows you to make an acronym that will display a description when moused over","tag":"acronym","useoption":"1","example":"[acronym='Laugh Out Loud']lol[/acronym]", ...
If you scroll to the right just a little, you will see this:
"[acronym='Laugh Out Loud']lol[/acronym]"
I need to store all of the CKEditor code inside a javascript string, but I can't figure out how to do it because the string has both " and ' in it. See the problem? Furthermore, I don't think I can just escape the quotes because I tried doing that and the editor didn't work.
Any idea what I can do?
You might try taking the string and injecting JavaScript escape codes into it. JavaScript can essentially use any unicode value when using the format: \u#### - so, for a ' character, the code is \u0039, and for the " character, the code is \u0034.
So - you could encode your example portion of the string as:
\u0034[acronym=\u0039Laugh Out Loud\u0039]lol[/acronym]\u0034
Alternatively, you could attempt to simply escape the quotes as in:
\"[acronym=\'Laugh Out Loud\']lol[/acronym]\"
The problem here occurs when you wind up with this kind of situation:
"data:{'prop1':'back\\slash'}"
Which, when escaped in this manner, becomes:
"data:{\'prop\':\'back\\\\slash\'}\"
While this is somewhat more readable than the first version - de-serializing it can be a little tricky when going across object-spaces, such as a javascript object being passed to a C# parser which needs to deserialize into objects, then re-serialize and come back down. Both languages use \ as their escape character, and it is possible to get funky scenarios which are brain-teasers to solve.
The advantage of the \u#### method is that only JavaScript generally uses it in a typical stack - so it is pretty easy to understand what part should be unescaped by what application piece.
hmm.. you said you already tried to escape the quotes and it gave problems.
This shouldn't give problems at all, so try this:
$newstring = addslashes($oldstring);
There's no need to use Unicode escape sequences. Just surround your string with double quotes, and put a backslash before any double quotes within the string.
var x = "\"[acronym='Laugh Out Loud']lol[/acronym]\"";

How can I pass a tag`s value to a javascript function after an event?

How can I pass a tag`s value to a javascript function?
this works:
onclick="submit(this.value)"
but this dosnt work:
onclick="submit(document.getElementById("ShortcutID").value)"
If you want to include quote characters in an attribute value delimited with the same kind of quote characters, you have to represent them with character references.
onclick="submit(document.getElementById("ShortcutID").value)"
Alternatively, use a different kind of quote character.
onclick="submit(document.getElementById('ShortcutID').value)"
… but try to avoid using intrinsic event attributes and bind your JavaScript event handlers with JavaScript instead. See Unobtrusive JavaScript
there is syntax error.
ShortcutID should be enclosed in this 'ShortcutID'
Change this
onclick="submit(document.getElementById("ShortcutID").value)"
to this
onclick="submit(document.getElementById('ShortcutID').value)"
but this dosnt work: onclick="submit(document.getElementById("ShortcutID").value)"
Because you're using double quotes both to delimit the onclick attribute and also inside to delimit the JavaScript string. Try:
onclick="submit(document.getElementById('ShortcutID').value)"
This is why JavaScript allows both single and double quotes for quoting strings.
You can also do it with entities, because remember that the content of an attribute is HTML text just like anything else in the HTML, so:
onclick="submit(document.getElementById("ShortcutID").value)"
The fact that the content is HTML text tends to be problematic when you're doing something non-trivial, which is one reason not to use onclick="code" style event handling but rather hooking up the event in code instead.
The problem you have in your code is you are using two sets of double quotes. To fix this, try this: onclick="submit(document.getElementById('ShortcutID').value)"

Categories