Debug Element Modification in MooTools by Monkey Patching Prototypes

By  on  

Let's face it:  JavaScript development and CSS modification can be a frustrating process, especially when your web application has loads of JavaScript.  One practice that is very helpful in troubleshooting CSS/JS problems is monkey-patching JavaScript prototypes and adding console statements to figure out what styles are being set on what elements.  Let me show you how you can save valuable time in debugging Element issues.

A Basic Example:  Watching Element.setStyle Assignments

Style additions are a frequent spot for trouble and confusion with JavaScript development.  You can easily monkey-patch the Element.setStyle method to spy on what style is being modified to what value on a given element:

(function() {
	/*
		SetStyle
	*/
	// "Save" the old setStyle prototype
	var oldSetStyle = Element.prototype.setStyle;
	// Create a new prototype method for setStyle
	Element.prototype.setStyle = function(property,value) {
		console.log("setStyle: Setting element ",this,"'s '",property,"' style to '",value,"'");
		return oldSetStyle.apply(this,arguments);
	}
	
	/*
		Set
	*/
	// "Save" the old set prototype
	var oldSet = Element.prototype.set;
	// Create a new prototype method for set
	Element.prototype.set = function(property,value) {
		console.log("set: Setting element ",this,"'s '",property,"' attribute to '",value,"'");
		return oldSet.apply(this,arguments);
	}
	
})();

When a style is set on any DOM node, you will see:

MooTools Debug

Having a record of style modification can be extremely helpful in debugging CSS issues, but why stop there?  What about attribute setters and className modification?  Let's do it.

Advanced:  Watching CSS Classes, Element Styles, and Element Attributes

I've created an array of objects with method names and a string template to log to the console:

// Set up some templates and properties
[
	{ method: "setStyle", description: "Setting '{arg1}' style to '{arg2}'" },
	{ method: "set", description: "Setting '{arg1}' attribute to '{arg2}'" },
	{ method: "addClass", description: "Adding class '{arg1}'" },
	{ method: "removeClass", description: "Removing class '{arg1}'" }
]

With that object, we can recurse over it and spy on each method!

// Set up some templates and properties
[
	{ method: "setStyle", description: "Setting '{arg1}' style to '{arg2}'" },
	{ method: "set", description: "Setting '{arg1}' attribute to '{arg2}'" },
	{ method: "addClass", description: "Adding class '{arg1}'" },
	{ method: "removeClass", description: "Removing class '{arg1}'" }
].each(function(method) {
	// Save the old prototype fn
	var oldProto = Element.prototype[method.method];
	// Create a new prototype
	Element.prototype[method.method] = function(arg1,arg2) {
		// Console out the method for debugging
		console.log(method.method,": ",this,": ",method.description.substitute({ arg1:arg1, arg2:arg2, element:this }));
		// Return the value by calling the old prototype fn
		return oldProto.apply(this,arguments);
	};
});

Now you can spy on CSS styles, classes, and attributes!  Working with DOM elements should be easier and your debugging will be more efficient! Better yet, return values and functionality does not change; monkey-patching simply adds console statements!

Recent Features

  • By
    5 Ways that CSS and JavaScript Interact That You May Not Know About

    CSS and JavaScript:  the lines seemingly get blurred by each browser release.  They have always done a very different job but in the end they are both front-end technologies so they need do need to work closely.  We have our .js files and our .css, but...

  • By
    CSS vs. JS Animation: Which is Faster?

    How is it possible that JavaScript-based animation has secretly always been as fast — or faster — than CSS transitions? And, how is it possible that Adobe and Google consistently release media-rich mobile sites that rival the performance of native apps? This article serves as a point-by-point...

Incredible Demos

  • By
    GitHub-Style Sliding Links

    GitHub seems to change a lot but not really change at all, if that makes any sense; the updates come often but are always fairly small. I spotted one of the most recent updates on the pull request page. Links to long branch...

  • By
    Assign Anchor IDs Using MooTools 1.2

    One of my favorite uses of the MooTools JavaScript library is the SmoothScroll plugin. I use it on my website, my employer's website, and on many customer websites. The best part about the plugin is that it's so easy to implement. I recently ran...

Discussion

  1. Very cool. I was just using something similar to this in a custom Fx.CSS class I was writing for doing animation, this is much more efficient though. Thanks. :-)

  2. Thanks for the article! Been trying to find something this simple to refer to for a while!

  3. Why not use Class.Refactor?

    function refactored(arg1,arg2){
      console.log("Setting "+arg1+" style to "+arg2);
      this.previouse(arg1,arg2);
    }
    
    var methods = /* a list of methods names pointing to above function */;
    
    Class.Refactor.apply(Element,methods);
    

    IMO this is much easier to read and maintain (and uses Mootools awesomeness)

  4. misspelled ‘previous ‘ above’ – bad spellchecker… but you get the point

  5. And off course – no need for apply – this is the intended use (I wasn’t sure if it was using this or not).
    so – Class.refactor(Element,methods);

  6. Great point Arieh! I used the code above because I wanted to inspire developers of other frameworks to employ the same techniques — those frameworks wont provide Refractor. Excellent idea though — should have mentioned it!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!