views:

36

answers:

2

Greetings, I'm trying to override or extend the Element.show() and .hide() methods in mootools in order to add some WAI-Aria toggling. I was trying to use the Class.Refactor() method like this:

 Element = Class.refactor(Element, {

 show: function(displayString) {
   result = this.previous(displayString);
   // Do my thing
   return result;
 },

 hide: function() {
   result = this.previous();
   // Do my thing
   return result;
 }

});

however, this is not working, previous is null and I think the reason is that Mootools injects those methods through Element.implement. So the methods are not native?

I have figured out how to completely replace .show and .hide but I would like to retain all of their existing functionality and just add to it. Any ideas?

+1  A: 

not a refactor guy myself, but you can always do it 'old school' and save the previous function in a variable (_prev_show and _prev_hide for example), then do your override and call those functions from your new methods.

second option would be to try extending Element into itself and call this.parent(), this is the 'unsafe' version of Class.Refactor. [reference]

gonchuki
also posted a full example from a coworker which does exactly as you proposed.
ryber
+1  A: 

I got the answer from a coworker. He's not on SO so I'm posting on his behalf and will buy him a beer the next time we are in the same city:

Class.refactor doesn't work on Natives (Element, Array, String, etc.) because they aren't Classes nor can they be overrided to be; MooTools just adds some cool prototypes to make them more Class-like and fun and easy to work with.

The way to extend natives is to use the implement() method; The only problem is that this.parent() and this.previous() don't exist, so you have to get a bit trickier to extend existing methods without rewriting them:


(function(){ // Keeps the window namespace clean

   var old_hide = Element.prototype.hide;
   var old_show = Element.prototype.show;

   Element.implement({
       hide: function() {
           result = old_hide.run(arguments, this); // Calls old method
           alert("Hiding " + this.get('tag') );
           return result;
       },
       show: function(display) {
           result = old_show.run(arguments, this); // Calls old method
           alert("Showing " + this.get('tag') );
           return result;
       }
   });

})(); // Closes the private function and executes it immediately

The key concepts here are:

1 - Encapsulate the whole shebang in a private, self-executing function so the global namespace isn't polluted by our variable assignments for the original methods (e.g. old_hide and old_show);

2 - Use the Native object's implement() method to override each function, much like you had done as the second argument to Class.refactor;

3 - Instead of calling this.parent() or this.previous() in each method, you call the old prototypes using MooTools' run() method, which passes the arguments with a binding to the function and executes it.

As before, make sure to gather the result of the function.run() call and return it to maintain API consistency.

ryber