Some people often wonder: “Hey, when a user calls $(‘body’).css(‘background’, ‘something-awesome’); is there a way I can run some code before that happens?”. The answer is yes and it’s not very hard to do. If there is a name for this technique, I’m not aware of it so I’m just going to call it “hijacking”.

UPDATE: I have an expanded version of this technique. It includes a destroy() method to restore the original function/method. Check out the gist on github.

The process would be to create a function that returns the method along with some custom arguments that have been tampered with (scary, I know). Here is something basic to achieve this effect:

jQuery.fn.css = (function(_jQueryCSS){
 
	return function(){
		// Run some custom code here and alter the arguments passed in
		return _jQueryCSS.call(this, arguments);
	}
 
})(jQuery.fn.css);

This technique has been done before by other developers. James Padolsey implements this technique in his cross-domain-ajax plugin and over-writes the jQuery.ajax method.

Normally I would stay clear of methods under another namespace (Don’t modify objects you don’t own -Nicholas Zakas) but sometimes it makes sense to over-write them to add your own custom bits like in James’ case (just be careful ;) , he’s not hurting the current functionality of jQuery.ajax, he’s simply augmenting it. I’ve created a simple function to handle this type of hijacking.

The hijack function

/**
* Allows you to alter with arguments before the method is actually called
* @param {Function} method A method/function to call after doing some tampering
* @param {Function} cb A callback that is passed the arguments for you to play with
*/
function hijack(method, cb){
 
	// A function needs to be passed or there will be hell to pay
	if(Object.prototype.toString.call(cb) !== "[object Function]"){
		throw new Error('An anonymous function must be passed as the second parameter!');
	}
 
	return function(){
 
		// Turn arguments into a true array
		var args = Array.prototype.slice.call(arguments);
 
		// Call the copied method and pass it some 'tampered' arguments from our callback
		return method.apply(this, cb.call(this, args) || args);
 
	};
 
}

Usage

Here is a simple use-case of how you would hijack the CSS method in jQuery.

// Hijack the CSS method in jQuery
jQuery.fn.css = hijack(jQuery.fn.css, function(user_args){
 
	// Now store the arguments passed in by the user
	var args = user_args;
 
	// Do some checking and alter the arguments
	if(args[0] == 'background' && args[1] == 'this-will-be-replaced-with-green'){
		args[1] = 'green';
	}
 
	return args;
 
});

So now when I call:

$('body').css('background', 'this-will-be-replaced-with-green');

It will run through my hijacked function and replace ‘this-will-be-replaced-with-green’ with ‘green’. And voila, your background is green.