RekrowYnapmoc
RekrowYnapmoc

Reputation: 2166

Escaping dilemma in Javascript

I have the following

var id='123';

newDiv.innerHTML = "<a href=\"#\" onclick=\" TestFunction('"+id+"', false);\"></a>";

Which renders <a href="#" onclick="return Testfunction('123',false);"></a> in my HTML.

The problem I have is that I wish to take the call to the method TestFunction, and use as a string parameter in my function StepTwo(string, boolean), which would ideally end up in live HTML as shown...

<a href="#" onclick="StepTwo("TestFunction('123',false)",true)"></a>

notice how the TestFunction is a string here (it is executed within StepTwo using eval).

I have tried to format my JS as by :

newDiv.innerHTML = "<a href=\"#\" onclick=\"StepTwo(\"TestFunction('"+id+"', false);\",true)\"></a>";

but while this appears to me correct in my IDE, in the rendered HTML, it as garbelled beyond belief.

Would appreciate if anyone could point me in the right direction. Thanks!

Upvotes: 1

Views: 2170

Answers (11)

Hedzer
Hedzer

Reputation: 119

I know this is hella' old now, but if anyone has issues with escaped strings when using eval (and you absolutely have to use eval), I've got a way to avoid problems.

var html = '<a href="#\" onclick=" TestFunction(\''+id+'\', false);"></a>';
eval('(function(div, html){div.innerHTML = html;})')(newDiv, html);

So, what's going on here?

  1. eval creates a function that contains two parameters, div and html and returns it.
  2. The function is immediately run with the parameters to the right of the eval function. This is basically like an IIFE.

In this case

var myNewMethod = eval('(function(div, html){div.innerHTML = html;})');

is basically the same as:

var myNewMethod = function(div, html){div.innerHTML = html;}

and then we're just doing this:

myNewMethod(newDiv, html); //where html had the string containing markup

I would suggest not using eval. If it can't be avoided, or if you control all the inputs and there's no risk of injection then this will help in cases where string escapes are an issue.

I also tend to use Function, but it isn't any more secure. Here's the snippet I use:

    var feval = function(code) {
    return (new Function(code))();
}

Upvotes: 0

ngn
ngn

Reputation: 7902

<a href="#" onclick="StepTwo('TestFunction(\'123\', false)', true)">...</a>

Upvotes: 0

Gene
Gene

Reputation: 1527

You claim that eval is the right thing to do here. I'm not so sure.

Have you considered this approach:

<a href="#" onclick="StepTwo(TestFunction,['123',false],true)"></a>

and in your StepTwo function

function StepTwo(func,args,flag){
    //do what ever you do with the flag
    //instead of eval use the function.apply to call the function.
    func.apply(args);
}

Upvotes: 1

Kent Fredric
Kent Fredric

Reputation: 57384

One of the biggest capital failures on the internet is creating html in javascript by gluing strings together.

var mya = document.createElement("a");
mya.href="#"; 
mya.onclick = function(){ 
    StepTwo(function(){ 
        TestFunction('123', false ); 
    }, true );   
};
newDiv.innerHTML = ""; 
newDiv.appendChild(mya);

This Eliminates the need for any fancy escaping stuff.

( I probably should do 'onclick' differently, but this should work, I'm trying hard not to just use jQuery code to do everything )

Heres how I would do it in jQuery:

jQuery(function($){ 

  var container = $("#container"); 
  var link = document.createElement("a"); /* faster than  $("<a></a>"); */
  $(link).attr("href", "Something ( or # )" ); 
  $(link).click( function(){ 
       var doStepTwo = function()
       { 
            TestFunction('123', true ); 
       };
       StepTwo( doStepTwo, false );  /* StepTwo -> doStepTwo -> TestFunction() */
  });
  container.append(link); 
}); 

There is no good excuse for gluing strings together in Javascript

All it does is ADD overhead of html parsing back into dom structures, and ADD potential for XSS based broken HTML. Even beloved google get this wrong in some of their advertising scripts and have caused epic failures in many cases I have seen ( and they don't want to know about it )

I don't understand Javascript is the only excuse, and it's NOT a good one.

Upvotes: 5

Mauricio
Mauricio

Reputation: 387

The best way is to create the element with document.createElement, but if you're not willing to, I guess you could do <a href="#" onclick="StepTwo('TestFunction(\'123\',false)',true)"></a> or use &quot;.

In your code:

newDiv.innerHTML = "<a href=\"#\" onclick=\"StepTwo('TestFunction(\'"+id+"\', false);\',true)\"></a>";

If it doesn't work, try changing "\'" to "\\'".

Remember that the " character is used to open and close the attribute on HTML tags. If you use it in the attribute's value, the browser will understand it as the close char.

Example: <input type="text" value="foo"bar"> will end up being <input type="text" value="foo">.

Upvotes: 0

RekrowYnapmoc
RekrowYnapmoc

Reputation: 2166

Hey guys, thanks for all the answers. I find that the quot; seems to work best.

I'll give you guys some votes up once I get more reputation!

In regards to eval(), what you see in the question is a very small snapshot of the application being developed. I understand the woes of eval, however, this is one of those one in a million situations where it's the correct choice for the situation at hand.

It would be understood better if you could see what these functions do (have given them very generic names for stackoverflow).

Thanks again!

Upvotes: 0

Corey Trager
Corey Trager

Reputation: 23141

  1. You need to alternate your " and '.

  2. Maybe you don't need quotes around the 123, because of Javascripts flexible typing. Pass it without quotes but treat it as a string within TestFunction.

Upvotes: 0

Gareth
Gareth

Reputation: 138200

Your biggest problem is using eval, it leads to so many potential problems that it's nearly always better to find an alternative solution.

Your immediate problem is that what you really have is

<a href="#" onclick="StepTwo("></a>

as the next " after the start of the onclick attribute, closes it. Use &quot; as others have suggested. And don't use eval.

Upvotes: 0

kͩeͣmͮpͥ ͩ
kͩeͣmͮpͥ ͩ

Reputation: 7856

You could create the a element and attach to the click event using DOM Methods.

A Javascript Framework (like the ubiquitous jQuery) would make this a lot easier.

Upvotes: 0

knabar
knabar

Reputation: 1156

Try using &quot; instead of \"

newDiv.innerHTML = "<a href=&quot;#&quot;...

Upvotes: 2

Greg
Greg

Reputation: 321806

You should be using &quot; not " or \" inside an HTML string quoted with double-quotes.

NewDiv.innerHTML = "<a href=\"#\" onclick=\"StepTwo(&quot;TestFunction('"+id+"', false);&quot;,true)\"></a>";

There's probably a better way to do this - any time you find yourself using eval() you should stand back and look for a different solution.

Upvotes: 2

Related Questions