Escape JavaScript in Expression Language
Asked Answered
H

2

5

Sometimes, I need to render a JavaScript variable using EL in a JSF page.

E.g.

<script>var foo = '#{bean.foo}';</script>

or

<h:xxx ... onclick="foo('#{bean.foo}')" />

This fails with a JS syntax error when the EL expression evaluates to a string containing JS special characters such as apostrophe and newline. How do I escape it?

Hypotension answered 7/7, 2011 at 21:3 Comment(2)
The answer below put me on the correct track.Hypotension
added: xmlns:fn="java.sun.com/jsp/jstl/functions" and in the code '#{fn:replace(_selectedItem.item.webName,"'","")}',Hypotension
M
14

You can use Apache Commons Lang 3.x StringEscapeUtils#escapeEcmaScript() method for this in EL.

First create a /WEB-INF/functions.taglib.xml which look like this:

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib 
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
    version="2.0">
    <namespace>http://example.com/functions</namespace>

    <function>
        <name>escapeJS</name>
        <function-class>org.apache.commons.lang3.StringEscapeUtils</function-class>
        <function-signature>java.lang.String escapeEcmaScript(java.lang.String)</function-signature>
    </function>
</taglib>

Then register it in /WEB-INF/web.xml as follows:

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/functions.taglib.xml</param-value>
</context-param>

Then you can use it as follows:

<html ... xmlns:func="http://example.com/functions">
...
<script>var foo = '#{func:escapeJS(bean.foo)}';</script>
...
<h:xxx ... onclick="foo('#{func:escapeJS(bean.foo)}')" />

Alternatively, if you happen to already use the JSF utility library OmniFaces, then you can also just use its builtin of:escapeJS() function:

<html ... xmlns:of="http://omnifaces.org/functions">
...
<script>var foo = '#{of:escapeJS(bean.foo)}';</script>
...
<h:xxx ... onclick="foo('#{of:escapeJS(bean.foo)}')" />
Margay answered 7/7, 2011 at 21:12 Comment(4)
I've followed the above, but I'm getting the following exception : javax.servlet.ServletException: com.sun.faces.el.impl.ElException: No function is mapped to the name "util:escapeJS" I'm on JSF 1.1, JSP 2.1... any idea what I should look at?Conciseness
@bendicott: Above answer uses a Facelet taglib. You're using JSP, not Facelets. You need to create a JSP taglib instead.Margay
Had to correct the taglib-definition but your solution is great... simple and effective!Morale
We're using JSF 1 with Facelets (legacy), so we needed to use the version 1 taglib DTD rather than the version 2 schema, and the web.xml property is facelets.LIBRARIES rather than javax.faces.FACELETS_LIBRARIES, but the basic idea of this answer was applicable.Obsequies
U
-1

Have you tried \'#{_selectedItem.item.webName}\',?

Unarmed answered 7/7, 2011 at 21:9 Comment(1)
Read the question once again. It's webName which returns an apostrophed string value.Margay

© 2022 - 2024 — McMap. All rights reserved.