Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function (..) throws 'eval is evil' message

I'm not using eval, and I'm not sure what the problem is that Crockford has with the following. Is there a better approach to solve the following problem or is this just something I need to ignore (I prefer to perfect/improve my solutions if there is areas for improvement).

I'm using some pixel tracking stuff and in this case a client has bound a JS function to the onclick property of an HTML image tag which redirects off the site. I need to track the clicks reliably without running into race conditions with multiples of event listeners on the image. The strategy is to override the event at run time, copying and running it in my own function. Note this is being applied to a site I do not control and cannot change. So the solution looks something like:

...
func = Function(img.attr('onclick'));
...
img.attr('onclick', '');
... //some custom tracking code
func.call(this);

and the JSLint checker throws the eval is evil error.

Is there a better way to avoid race conditions for multiple events around href actions?

like image 522
patrickgamer Avatar asked Jan 17 '23 20:01

patrickgamer


2 Answers

You're implicitly using eval because you're asking for the callback function as it was specified as an attribute in the HTML as a string and then constructing a Function with it.

Just use the img.onclick property instead, and you will directly obtain the function that the browser built from the attribute that you can then .call:

var func = img.onclick; // access already compiled function
img.onclick = null;     // property change updates the attribute too

... // some custom tracking code

func.call(img, ev);     // call the original function

or better yet:

(function(el) {
    var old = el.onclick;
    el.onclick = function() {
        // do my stuff
        ..
        // invoke the old handler with the same parameters
        old.apply(this, arguments);
    }
})(img);

The advantage of this latter method are two fold:

  1. it creates no new global variables - everything is hidden inside the anonymous closure
  2. It ensures that the original handler is called with the exact same parameters as are supplied to your replacement function
like image 118
Alnitak Avatar answered Jan 24 '23 17:01

Alnitak


var oldClick = myImg.onclick;
myImg.onclick = function(evt){ 
  // Put you own code here
  return oldClick.call( this, evt );
};
like image 28
Phrogz Avatar answered Jan 24 '23 19:01

Phrogz