0

I believe this is close JavaScript: Overriding alert() Through all my googlefu this was the closest I could see that might relate. The problem is I don't know exactly what the issue is only the solution I desire.

So there's a website that I'd like to add more functionality (much needed functionality) on my client side only so I'm trying to use greasemonkey and am slowly cracking it open with Firebug. I'm not very good at javascript, but I have years in other languages C++,C#,and java so I'm not a complete noob.

There's a a DOM element button that is pressed and fires an event that fires another that fires another that finally fires an event that adds to a collection and most importantly the reason I think I can't get the above example to work is it takes two parameters.

foo.create(t,e);

I'm just trying to get in and see what's getting passed through I'd like to do more but started with just a simple alert to see what's going on.

oldfoocreate=foo.create;
foo.create(t,e){
    alert(JSON.stringify(t) + "  ?  " + JSON.stringify(e));
    oldfoocreate(t,e);
}

It works as expected on the alert I get to see the data and it is a data I expected to see however it is a very complicated web app and it fires other events ( I suppose or is expecting the event from another wrapper) because I get an error:

this._fooBar is not a function

I'll continue to google and try the proxy idea in different ways, but married, kids, school, and unfortunately I do manual labor for work invites me very little time for my passion. Thank you community for the help.

What I'm thinking is it's expecting a wrapper of some sort an outter object calling the function??? The main reason I'm stumped is cause I said change foo.create to foo.create ohh by the way I am going from window so window.foo.create so I'm as far back as I can get. I haven't read much on javascript this keyword so any information is also welcome!

Community
  • 1
  • 1
Roger
  • 87
  • 6

3 Answers3

1

You can bind your function to the context you want using ES5 bind.

var oldfoocreate = foo.create.bind(foo);
Yury Tarabanko
  • 39,619
  • 8
  • 73
  • 90
  • *bind* doesn't "bind a function to a context", functions have an execution context, not the other way around. ;-) *binds* assigns an object to a function's *this* so that no matter how you call the function, *this* references the object. – RobG Jan 07 '15 at 00:03
0

You will need to call oldfoobar with the correct context, or make it a property of foo.

oldfoocreate.call(foo, t, e);

or

foo.oldfoocreate=foo.create;
foo.create = function(t,e){
    alert(JSON.stringify(t) + "  ?  " + JSON.stringify(e));
    foo.oldfoocreate(t,e);
}

The problem happened originally because you called the function stored in the foo.create property without a context, so this became window. By using .call, or placing the function in another property on foo and executing it from there, this was again foo.

Kevin B
  • 92,700
  • 15
  • 158
  • 170
  • 2
    I'll try yours next don't know why it's downvoted :( – Roger Jan 06 '15 at 23:09
  • Both solutions should work, Yury's is likely a bit easier to implement, just keep in mind cross-browser support if you need to support older browsers. – Kevin B Jan 06 '15 at 23:10
  • I haven't downvoted, but perhaps it is because your solution is polluting the `foo`'s API while it shouldn't. Using `bind` is the proper way to go. – plalx Jan 06 '15 at 23:11
  • For the protocol. It was not me. :) – Yury Tarabanko Jan 06 '15 at 23:11
  • For the record, i prefer the call method, the other is just another option, good or bad. Hoped it would spark the reason why the problem happened to begin with. – Kevin B Jan 06 '15 at 23:12
  • This worked as well both worked splendidly thank you so much. – Roger Jan 06 '15 at 23:13
  • i fixed it in my answer – Kevin B Jan 06 '15 at 23:19
  • ahh yeah my answer didn't =function I had it right in original code was in a rush running out of time wife's headed home lol I'm not sure how to get .call to work I just do oldfoo.call(foo,t,e) and then my code as is? I can't chat and getting warning on comment max. I'll accept Yury's since its easiest to implement without further knowledge of javascript. Thank you for the help though – Roger Jan 06 '15 at 23:20
0

Using bind is the correct approach, but you should also make sure that you aren't polluting your current scope (especially if it's the global one) with an unecessary oldfoocreate variable.

Here's how you should probably do it:

foo.create = (function (oldfoocreate) {
    return function (t,e) {
        alert(JSON.stringify(t) + "  ?  " + JSON.stringify(e));
        oldfoocreate(t, e);
    };
})(foo.create.bind(foo));

Now oldfoocreate is only reachable where needed and no one could ever call the old one without going through the new one.

Note that you can also do it without bind:

foo.create = (function (oldfoocreate) {
    return function (t,e) {
        alert(JSON.stringify(t) + "  ?  " + JSON.stringify(e));
        oldfoocreate.call(this, t, e);
    };
})(foo.create);
plalx
  • 39,329
  • 5
  • 63
  • 83