开发者

How to hook jQuery own functions, to check if a string can be eval'ed to a function?

I want to be able to do this

$('.class').bind({'click':'function(){ ... }'}); // note that the value is a string

and somehow, checking inside a hooked "bind", that it's indeed a function, and eval() or new Function the string, so it will be correctly assigned as an event.

The reason I want to do this is because JSON doesn't allow functions to be defined as values, only strings/ints. I would want to find a way to apply this for all jquery functions (like animate(), click(), live(), etc) that take a handler/function as parameter. it would be a huge hassle and I think, and would become impractical after each new version of jQuery released

Or is there any better way to accomplish t开发者_JAVA技巧his? checking for the first 8 characters if they are === 'function' and then eval it is not a good idea, since it can be a "legitimate" text string. I tried passing a function as a result from a ajax JSON response, but $.parseJSON failed silently.


Is this what you are looking for, http://jsbin.com/adewe4/3

function definition https://gist.github.com/862112

You can use the parseJSONwithFunctions method to parse the JSON data that you receive as the AJAX response using $.getJSON.

parseJSONwithFunctions converts the function body as strings in the JSON into actual function objects; so rather than trying to make jQuery eval strings, you can just pass the function reference to it.

If you use the method as,

var my_json_data = {};

$.getJSON('URL_TO_GET_JSON', function (data) {
  my_json_data = parseJSONwithFunctions(data);
});

and the you can define handlers as,

$('.class').bind('click', my_json_data.clickHandler);


Just found my own answer, WOW, javascript can be quite powerful, check this out

var call_cache = [];

str_is_function = function(str){
  if (jQuery.type(str) !== 'string' || ! /^\s*?function/i.test(str) || ! /\}$/m.test(str)) return false;
  return true;
}

String.prototype.apply = function(obj){
  if ( ! str_is_function(this) ) return false;

  var str = this.toString(), cache_len = call_cache.length;
  fn = null;

  for(i = 0; i < cache_len; i++){
    if (call_cache[i].str === str) {
      fn = call_cache[i].fn;
      break;
    }
  }

  if (typeof fn != 'function'){
     $.globalEval('var fn = ' + str);
     call_cache.push({'str': str, 'fn': fn});
     cache_len = call_cache.length;
  }

  args = Array.prototype.slice.call(arguments, 1);

  if (typeof args[0] != 'undefined' && args[0].constructor === Array){
    args = args[0];
  }

  return fn.apply(obj, args);
}

String.prototype.call = function(obj){
  this.apply(obj, Array.prototype.slice.call(arguments, 1));
}

$('.gap').bind({'mouseover':'function(){ alert("gi");}'});

"function(name){ alert(name); }".call(null, "hi");
"function(name){ alert(name); }".apply(null, ["hello"]);
"function(){ alert('teehee'); }".call(null);
"alert".call(null, "hi"); // wont work

No need to hook any jQuery specific function. When it tries to call() or apply() on a string, it will eval to code/function. the problem is that this is a global modification, and could lead to some client-side havoc if someones find out about it hehe.

what are the caveats in this solution?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜