www.webdeveloper.com
Results 1 to 6 of 6

Thread: How to override a method from a third party source

Hybrid View

  1. #1
    Join Date
    Apr 2013
    Posts
    3

    How to override a method from a third party source

    Hello,

    I'm working with some widgets from dhtmlx.com, and have a need to be notified after the completion of a function call that is internal to the widget. Normally this isn't a problem, but I don't understand how to get my hook into it.

    The function is defined like this:

    Code:
    dhtmlXGridObject.prototype.toPDF=function(url,mode,header,footer,rows,target){
    
       // some object declarations as such:
       var save_sel = {
          row: this.getSelectedRowId(),
          col: this.getSelectedCellIndex()
       };
    
       // then ...
       function targetFunction() {
       }
    }
    So now I want to override dhtmlXGridObject.prototype.toPDF, but only the targetFunction portion of it. I know how to override the whole thing, but how can I get just the targetFunction object? dhtmlXGridObject.prototype.toPDF.targetFunction?

  2. #2
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    once a function is parsed, it cannot be changed, but you can appropriate it rather easily:
    Code:
    var oldOne=dhtmlXGridObject.prototype.toPDF;
    dhtmlXGridObject.prototype.toPDF=function(a,b,c){
       oldOne(a,b,c);
       alert("inside toPDF()");
       function targetFunction(){ /*...*/ }
    };

  3. #3
    Join Date
    Apr 2013
    Posts
    3
    I'm not sure what you mean by appropriate. With the technique you are describing, will my targetFunction be called instead of the widget's when I invoke oldOne(a,b,c)? I'll give this a try.

    Thanks.

  4. #4
    Join Date
    Apr 2013
    Location
    Bournemouth, UK
    Posts
    15
    I don't think there is a legitimate way to edit the private method, that is why it's private. However there is a way Some optimisations and stuff needed though, but it works
    Code:
    function replacePrivateMethod(func_body, func_name, func_rep) {
    	func_body = func_body.toString();
    	func_rep = func_rep.toString();
    	var index = func_body.search(new RegExp('(var|function)\\s+' + func_name));
    	index = func_body.indexOf('{', index) + 1;
    	var brack = 1, last = index;
    	while(brack !== 0 && func_body[last] !== '}') {
    		if(func_body[last] === '{') brack++;
    		else if(func_body[last] === '}') brack--;
    		last++;
    	}
    	func_rep = func_rep.substring(func_rep.indexOf("{") + 1, func_rep.lastIndexOf("}"));
    	func_body = func_body.substr(0, index) + func_rep + func_body.substr(last);
    	return (new Function("return " + func_body + ';'))();
    }
    
    // assume a,b are numbers
    var x = function(a, b) {
    	function some_func(c) {
    		console.log(a, b, c);
    	}
    	var other_func = function(c) {
    		console.log(c, b, a);
    	}
    	some_func(a+b);
    	other_func(a-b);
    }
    
    function new_func1(c) {
    	console.log(c, b, a);
    }
    
    function new_func2(c) {
    	console.log(a, b, c);
    }
    
    var y = replacePrivateMethod(x, 'some_func', new_func1);
    var z = replacePrivateMethod(y, 'other_func', new_func2);
    
    console.log('x()');
    x(1, 2);
    console.log('y()');
    y(1, 2);
    console.log('z()');
    z(1, 2);

  5. #5
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    since you brought it up, i wrote a tool for that a week ago:

    Code:
    //regular off-the shelf ajax routine:
    function aGet(turl,callback){
      var XHRt=new XMLHttpRequest;
      XHRt.onreadystatechange=function(){
    	if(XHRt.readyState==4&&XHRt.status==200){
    		callback(XHRt.responseText,XHRt);
    	}
      };
      XHRt.open("GET",turl,true);
      XHRt.send();
      return XHRt;
    }
    
    
    //the magic patch function:
    Function.prototype.patch=function(sig, code){
      var s=String(this).split("\n");
      var splicePoint=0;
      s.map(function(a,b){if(a.indexOf(sig)!==-1)splicePoint=b;  });
      s.splice(splicePoint, 0, code);
      return eval("0||"+s.join("\n"));
    };
    
    //demo: add a request header to the existing ajax routine:
    var jsGet=aGet.patch(
        ".send(",  
        "XHRt.setRequestHeader('content-type', 'application/json');"  
    ) ;
    
    jsGet("/url/etc/", myCallBack);

    usage:

    function.patch(strBeforeWhichToPatch, strToInsertBeforePatchPoint) returns Function

  6. #6
    Join Date
    Apr 2013
    Posts
    3
    Thanks for both replies--I have to try all this out. I'm usually an advocate for leaving private functions alone, but the alternative I'm facing right now is that third-party source code has been altered by developers at my company, which is the greater of the two evils I think. I recently upgraded to the latest version of the widget library, and you can probably guess that there were problems. I'll still have problems if private code has changed, but at least I'll see the problem when stepping through my own code.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles