Programming JavaScript, I repeatedly faced the Problem of an existing function (i.e. exposed by a library) solving my issue very closely, but not entirely. Therefore I searched for a solution to execute some statements each time before or after the execution of the existing function. Scratching your head? Here’s an example:

In the JavaScript libraries of the Atlassian Confluence SDK, there’s a method AJS.Editor.previewFrameOnLoad which is called every time the preview frame of the internal TinyMCE wysiwyg editor fully loaded. Each time this happened, I wanted to change the DOM within the preview frame using JavaScript. Unfortunately, the library does not expose any events in parralel to that action.

After some embarrasing and nooby tries (we’re all humans right?) I found a solution. I’m going to show my steps (incl. the incredibly nooby ones) that eventually led to this solution.

Step #1

AJS.Editor.previewFrameOnload = function() {
  myCustomCodeBefore();
  AJS.Editor.previewFrameOnload(); // oh no!
  myCustomCodeAfter();
};

In this step, I tried to override the original function to append or and prepend my custom code. Yes: wrong! Doing this, I lost the reference to the original function and the exectution gets caught up in an endless loop, bam!

Step#2

var oldFunc = AJS.Editor.previewFrameOnload; // tmp the original
AJS.Editor.previewFrameOnload = function() {
  myCustomCodeBefore();
  oldFunc(); // my bad!
  myCustomCodeAfter();
}

Now, I’m saving the original function in a temporary and override the original function. Within the overriding function, I call the temporary saved function. OK? No. oldFunc references the original function, the original function is overriden, oldFunc is overriden too (call by reference). Endless loop again!

Step#3
I realized I needed a more professional approach to this issue and that it can’t be done with a simple override or tmp variable. Good that I learned a lot about JavaScript Closures in the last months! And thus I realized that the light at the end of the tunnel would be overriding the original function with a closure that maintains a reference to the original function:

AJS.Editor.previewFrameOnload = (function(oldFunc) {
  return function(body, iframe) {
    myCustomCodeBefore();
    oldFunc();
    myCustomCodeAfter();
  };
}(AJS.Editor.previewFrameOnload));

Within the closure that is assigned to the original function, oldFunc still references the original function that is given as parameter to the closure. The call sequence is now correct: (1) myCustomCodeBefore, (2) the original function AJS.Editor.previewFrameOnload, (3) myCustomCodeAfter. Note that the body and iframe are the same as the parameters of the original function.

However, this solution still suffers a significant problem: the original AJS.Editor.previewFrameOnload function is usually executed with the method invocation pattern which means that the this value within the function must reference AJS.Editor. But we’re calling the function with the function invocation pattern and this will reference the global object (window mostly). That’s bad!
Fortunately, JavaScript offers a mechanism to pass a value to functions that is to be used as this within the function body: every function has the methods apply and call (yes, since functions inherit from Object in JavaScript, they can have methods). These methods can be used almost exchangeably. In my example, I’m using apply.

Also, I’m not passing any arguments to the original function. Essentially, we must find a way that the original function is executed as though we never touched it.

Step#4 - Finally some code that works!

AJS.Editor.previewFrameOnload = (function(oldFunc) {
  return function(body, iframe) {
    myCustomCodeBefore();
    oldFunc.apply(AJS.Editor, arguments);
    myCustomCodeAfter();
};
}(AJS.Editor.previewFrameOnload));

As described earlier, the AJS.Editor object is passed as the this value to the original function which is then executed as never touched.

Alright! As soon as this closure is executed initially, my custom code is executed every time the original previewFrameOnload function is called, while this original function is promised to run as if it had never been touched. Categorically!

Step#5 - Some tuning

So, I found a good solution that works. But: if I want to do different things at different places when the original function is called? For example, imagine I you have different TinyMCEs on different pages and you want to run different code previewFrameLoad. It’s no good way to override the function with different closures in each context. Instead, we should do that on a global level and fire custom events each time the original function is called:

// I'm using jQuery in here to trigger custom events.
// This can be done with native JS very easily too.
AJS.Editor.previewFrameOnload = (function(oldFunc) {
  return function(body, iframe) {
    $(document).trigger('previewFrameLoadedBefore');
    oldFunc.apply(AJS.Editor, arguments);
    $(document).trigger('previewFrameLoadedAfter');
};
// Somewhere I want to listen for these events like this:
$(document).on('previewFrameLoadedBefore', function() {
  myCustomCodeBefore();
});
$(document).on('previewFrameLoadedAfter', function() {
  myCustomCodeAfter();
});

It’s a much better way to have a single point of access/override and delegate the calls of the original function with events. Now I can listen to these events and execute custom code as desired at any place I’m interested. Note that I’m firing events on the global document object. This could be improved by having a “dispatcher element” on the closure or local function scope level to avoid touching global properties.

Conclusion
In this article, I demonstrated how custom code can be hooked onto already existing functions. It was shown that this is not a very trivial issue, being dependent on advanced functional concepts like closures and JavaScript’s apply method. However, the solution is not difficult to implement and can help in different situations, for example when the contents of a library’s function are not sufficient.