Monkey Patching Dojo’s Menu Dijit
If you haven't already read Bryan Forbes' Monkey Patching tutorial, I want you to do so right now. Leave this blog and do it. Why? Because it's an invaluable tool in safely patching installs of your favorite JavaScript framework. In a nutshell, "Monkey Patching" is the process of "extending or modifying the runtime code of dynamic languages (e.g. Smalltalk, JavaScript, Objective-C, Ruby, Perl, Python, Groovy, etc.) without altering the original source code."
Why is that important? A number of reasons:
- You don't touch a JavaScript library's packaged code, making upgrading your library much more straight-forward.
- You don't need to remember where you patched that one thing that one time.
- Your patches are much more portable.
- You don't need to wait until your favorite library's team updates the functionality (...if they every do).
Where am I going with all of this? I recently needed to Monkey Patch a core Dojo/Dijit functionality. Between Dojo 1.3.2 and 1.4.3, the Menu class changed in that submenus needed to be clicked to pop out instead of the usual hover trigger. Here's how I MP'ed the Menu class to do what I wanted it to.
The Dojo JavaScript
/* Popup Menu Open on Hover */
(function() {
dijit.Menu.prototype.allowSubmenuHover = true;
dijit.Menu.prototype.popupDelay = 500;
dijit.Menu.prototype.onItemHover = function(item) {
if(this.isActive || this.allowSubmenuHover) {
this.focusChild(item);
if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){
this.hover_timer = setTimeout(dojo.hitch(this, '_openPopup'), this.popupDelay);
}
}
if(this.focusedChild){
this.focusChild(item);
}
this._hoveredChild = item;
};
})();
/* popup hover patch end */
I modified the dijit.Menu class' prototype, adding two options: allowSubmenuHover and popupDelay (the timer). I then modify the onItemHover method to account for the two new options. Now submenus will pop out when you hover over their label. FTW!
Like I said, even if you aren't a Dojo developer, you really should read Bryan's post. The method described in his post applies to *any* JavaScript code: jQuery, Dojo, MooTools, YourLib, whatever. His post even saves the original prototype and calls it once the custom work is done -- even better! I promise it will make you a better JavaScript developer!
Comments
Be Heard!
Share your thoughts without being a jerk! And wrap your code in <code> tags, f00!
Or you could just use MooTools and make a subclass. MooTools FTW!
@Daniel15: You can subclass these in Dojo as well, but this allows me to not need to go through the rest of the app and change code to the subclass’ name.