Getting Notified When jQuery Methods Are Called - J Query

Problem
You want to perform a certain action when a DOM element gets modified using jQuery. This could involve changing an attribute such as a CSS property, removing it from the document, etc.Some browsers already support mutation events,# which would serve this need, but they’re not something you can use in a cross-browser fashion yet, and they are n’t integrated with jQuery.
Another thing you might ever need is to modify the arguments passed to jQuery methods before they’re executed. On the same principle, you could need to alter the data returned by a method after the executing of the function itself.

Solution

This is somehow related to aspect-oriented programming,* but here we won’t be nesting functions; instead, we’ll overload the desired method once and trigger events every time the method is called.
We’ll need one event to be triggered before the function is run to allow the arguments to be changed. We’ll also need an event after the function is run so we can retrieve the returned data and even change it if necessary.
Let’s see how to code this as a plugin. I’ll show you each step separately.

Discussion

Overloading the desired method

First, let’s create a function that replaces jQuery methods with our own function. I’ll name it jQuery.broadcast(); you can change its name if you prefer something else:

name needs to be the method name we want to override, for example:

Triggering an event prior to the execution

Now that we have put our own function as the jQuery method, let’s see how to trigger an event that will allow us to change the incoming arguments:

Assuming you’re broadcasting addClass(), we can now do this:

Executing the original method

An event is now triggered, but we still have to call the old addClass(). We’ll save there turned data into the event object as well so we can expose it later when we trigger the other event.

As you can see, we don’t pass the original arguments array; instead, we use the one we exposed in case it was modified in some way.

Triggering an event after the execution

We now have the returned data saved in our event object. We can now trigger the final event, allowing external modification of the returned data.
We’ll reuse the same event object, but we’ll change the event’s name.

Returning the result

All what’s left now is to return the resulting data and continue with the normal execution.We’ll give out what we saved on e.ret that could have been modified by an event handler:

Putting it all together

This is the completed code we’ve developed:

Where to go from here?

I tried to keep the example short to illustrate the point. There are a couple of things you can do to improve it; here are a few ideas:

  • Use triggerHandler() instead of trigger(): if you don’t need the events to bubble,you could simply use triggerHandler(). This will make the whole process faster; note that triggerHandler() only triggers the event on the first element of the collection.

  • Run the process on each element separately: in the previous example, trigger() is called on the whole collection at once. That will be OK for most cases but can yield unexpected results when used on collections with multiple elements.
    You could wrap what we put inside the function with a call to map(). That should make the code work once per element.
    The downside is that it will be slightly slower and will also generate an (unexpected) stack entry (pushStack()) due to the call to map().

  • Allow external code to prevent normal execution: if you’re using jQuery 1.3 or higher, you could take advantage of the methods for jQuery.Event.
    You can “ask” the event object whether someone called its preventDefault() methodusing e.is DefaultPrevented().
    If this returns true, then you don’t call the original function.

  • Avoid multiple overloads of the same jQuery method: this one is pretty simple; just create an internal object literal where you keep track of which methods were overloaded. Then you just ignore repeated calls.

  • Integrate this with jQuery.event.special: this one will save you from calling jQuery.broadcast() for each method you want to overload.
    Instead, you add an entry to jQuery.event.special for each method, and you internally call jQuery.broadcast() when someone binds an event. This should be combined with the check for duplicated calls.

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

J Query Topics