0

I'm am looking for a JavaScript equivalent for this (Java) code: org.apache.commons.lang.StringEscapeUtils.escapeJavaScript(String)

So I can use it in JavaScript like:

loop ... foo = something;
  elem.setAttribute("onclick", "bar(event, 'this:" + used_here(foo) + "');");
  foo = something else;
repeat loop

So what is missing here is the function used_here(), which would properly escape its parameter according to JavaScript string rules.

Is there such a function that is standard (supported by major browsers) ?

--

Explanation for false duplicate: This is not about HTML escaping.

So NOT THIS: " -> "
But this:    " -> \"
5
  • I found github.com/joliss/js-string-escape which suggests there is no standard function. Commented Oct 15, 2018 at 10:59
  • Possible duplicate of Can I escape html special chars in javascript? Commented Oct 15, 2018 at 11:00
  • 6
    Is there a reason why you can't simply use listeners? elem.addListener('click', () => ... Commented Oct 15, 2018 at 11:00
  • @DarrenSweeney escapeJavaScript escapes stuff for strings, namely quotes and such. Commented Oct 15, 2018 at 11:07
  • @vlaz My apologies, I understood your comment as a suggestion to use that Java method. I will remove the comments as unnecessary. Commented Oct 15, 2018 at 11:19

2 Answers 2

2

Begging your pardon for any offense, but this is like asking how to implement an address book app for a rotary phone, or an anti-arrow armour for homing pigeons. :) In this day and age, you should almost never have the reason to have JavaScript as string in a HTML attribute.

elem.setAttribute("onclick", "alert('this:" + used_here(foo) + "');");

is these days very cleanly written as

let foo = `Chief O'Brien & Dwayne "The Rock" Johnson can now have any special chars they want!`;
let elem = document.querySelector('button');

elem.addEventListener('click', evt => {
  alert(foo);
});
<button>Click me!</button>

EDIT: the loop.

let elems = document.querySelectorAll('button');

elems.forEach((elem, i) => {
  let foo = `Button ${i + 1}`; // foo is different, but it is local
  elem.addEventListener('click', evt => {
    alert(foo);
  });
});
<button>Click me!</button>
<button>No, click me!</button>
<button>No, me!</button>

Or, to support IE8, with jQuery, intentionally not using .each, because I want to demonstrate old-school for loop where closure over foo has to be prevented:

var elems = $('button');

var i, elem, foo;
for (i = 0; i < elems.length; i++) {
  elem = elems[i];
  foo = "Button " + (i + 1);
  (function(foo) {
    $(elem).on('click', function(evt) {
      alert(foo);
    });
  })(foo);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button>Click me!</button>
<button>No, click me!</button>
<button>No, me!</button>

Sign up to request clarification or add additional context in comments.

7 Comments

Have to give you an upvote for the analogies alone. While my answer does clear cut answer the question: I have to go along with Amadan's answer here. You should rarely have a need to escape javascript like I did in my answer. This appears to be an X/Y Problem. What are you trying to achieve @DavidBalažic? What do you need this for?
I am fixing XSS and similar holes in a legacy application. It might need to run on IE 8 or so.
Amadan, when/how is the reference to foo in the function evaluated?
Indeed you are right, in my code it would be evaluated at click time. It is very easy to change it to pre-evaluated though - just evaluate it and let it sit in a variable. As for IE8 or so, you might have to juggle .addEventListener with .attachEvent, or rely on a library (such as jQuery) to do it for you - still nicer and safer than JS-in-attribute. However, I understand that legacy projects sometimes don't give you freedom to not be waist-deep in muck (COBOL is still a thing), so yeah, that wouldn't really fall under my "this day and age" :(
@Amadan I did some updates to the question to make it a bit more clear, regarding these issues...
|
0

I converted over the escapeJavaStyleString from org.apache.commons.lang.StringEscapeUtils.escapeJavaScript into javascript:

function escapeJavaStyleString(str, escapeSingleQuote, escapeForwardSlash) {
    if (str == null) {
        return '';
    }
    const sz = str.length;
    let out = '';
    for (let i = 0; i < sz; i++) {
        const ch = str.charAt(i);
        // handle unicode
        if (ch > 0xfff) {
            out += "\\u" + ch.toString(16);
        } else if (ch > 0xff) {
            out += "\\u0" + ch.toString(16);
        } else if (ch > 0x7f) {
            out += "\\u00" + ch.toString(16);
        } else if (ch < 32) {
            switch (ch) {
                case '\b':
                    out += '\\';
                    out += 'b';
                    break;
                case '\n' :
                    out += '\\';
                    out += 'n';
                    break;
                case '\t' :
                    out += '\\';
                    out += 't';
                    break;
                case '\f' :
                    out += '\\';
                    out += 'f';
                    break;
                case '\r' :
                    out += '\\';
                    out += 'r';
                    break;
                default :
                    if (ch > 0xf) {
                        out += "\\u00" + ch.toString(16);
                    } else {
                        out += "\\u000" + ch.toString(16);
                    }
                    break;
            }
        } else {
            switch (ch) {
                case '\'' :
                    if (escapeSingleQuote) {
                        out += '\\';
                    }
                    out += '\'';
                    break;
                case '"' :
                    out += '\\';
                    out += '"';
                    break;
                case '\\' :
                    out += '\\';
                    out += '\\';
                    break;
                case '/' :
                    if (escapeForwardSlash) {
                        out += '\\';
                    }
                    out += '/';
                    break;
                default :
                    out += ch;
                    break;
            }
        }
    }
    
    return out;
}

console.log(escapeJavaStyleString('testing("bleh")'));

2 Comments

As mentioned in the question, I already found an implementation. Here: github.com/joliss/js-string-escape/blob/master/index.js
@DavidBalažic So use that, or see the other posted answers about listeners. You're asking for a non-archaic way to solve an archaic issue. Callbacks aren't done like this anymore: Period. It's bad coding, which is why your app is probably open up for XSS attacks. Rewrite the code for listeners, or use the solution you've already found.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.