I've done this kind of thing too. In general, I try to avoid it only because it tends to muddy up the API. In this case, the methods you are altering don't have any arguments, but this pattern tends to break down when you have a method you want to do this to that takes numerous arguments.
It's not a bad solution though. On Thu, Jan 7, 2010 at 2:07 PM, Perrin Perrin <[email protected]>wrote: > Hey Rolf, I modified your example to work without having to do any > renaming, and still keep all of the logic in the > See the 'hide' method. > > http://mootools.net/shell/JfhBn/1/ > > --Perrin > > > On Thu, Jan 7, 2010 at 3:16 PM, Rolf -nl <[email protected]> wrote: > >> In-depth answer! >> You lost me at first with the explanation how the classes work etc, >> but after reading it two times and the combination with my "problem" I >> think it's clear :) >> I understand anyway why this.parent doesn't exists anymore. >> >> The renaming of the parent method in the Init method of a class is a >> quick way to get around it, indeed it feels hacky.. I will not use it >> (also, because you say it's hacky, if I came up with the idea I might >> have thought it was a smart hack, hehehe). >> >> I will probably just copy the parent's method, leave 80% of it like it >> is and add what I need. Done. >> >> Thanks! >> >> >> On Jan 5, 10:37 pm, Aaron Newton <[email protected]> wrote: >> > You are delving into the depths of how Class works, so this is going to >> get >> > a little complicated. >> > >> > All methods of classes are wrapped in a function that then calls the >> > function in question. So if you pass an object to Class that has a >> > *foo* method, >> > Class returns a constructor that when invoked returns an object that has >> a * >> > foo* method that calls the original one. >> > >> > var fooBase = { >> > foo: function(){ alert('foo'); }}; >> > >> > var Foo = new Class(fooBase); >> > var myFoo = new Foo(); >> > myFoo.foo(); //alerts "foo" >> > >> > When we call the *foo* method on our instance, we're really calling the >> > wrapper that the Class constructor put around the *foo* method on our >> > fooBase object. This wrapper therefore knows when *foo* is being called, >> and >> > before it calls the original *foo* it defines *this.parent*. It doesn't >> look >> > like this, but here's a very simple illustration: >> > >> > instanceOfFoo.foo = function(){ >> > this.someVar = 'blah'; >> > this.originalFooMethod(); >> > delete this.someVar; >> > >> > }; >> > >> > So only while our original method is being run is *this.parent* defined >> (and >> > only if there is a parent method on the prototype). >> > >> > If you think about it, that's the only way this could work, because * >> > this.parent *has to point at different things depending on which method >> is >> > calling it. *this* is our instance, and the *parent* property of our >> > instance changes depending on the method. Removing it after a method is >> > called is the only way to allow the next method to call it. >> > >> > So, let's look at your code: >> > >> > showMask: function() { >> > var fn = function() { >> > this.parent(); >> > }.bind(this); >> > this.element.tween('opacity', >> this.options.opacity).get('tween').chain( >> > fn); >> > }, >> > >> > Your method calls *element.tween*, which starts an effect. After the >> effect >> > it calls your function, which references *this.parent*. But this >> > asynchronous method call is going to occur *after* the *showMask* method >> > exits, which means that *this.parent *has been deleted, right? >> > >> > So, how do you extend a class and add this kind of effect? The only >> > mechanism to do this is to rename the original methods: >> > >> > var Foo.Extended = new Class({ >> > Extends: Foo, >> > initialize: function(){ >> > this._foo = this.foo; >> > this.foo = this._newFoo; >> > }, >> > _newFoo: function(){ >> > (function(){ >> > this.parent(); >> > }).delay(1000, this); >> > }}); >> > >> > var myFoo = new Foo.Extended(); >> > myFoo.foo(); //waits 1 second, alert's "foo" >> > >> > This is hacky and in general a bad practice. >> > >> > If you look at the showMask method in Spinner, which completely >> overwrites >> > the method from Mask (it does not call this.parent), you can see how it >> does >> > this fading in. Note that I *could* have done this method renaming from >> the >> > example above, but that method renaming is more brittle than I prefer. >> I've >> > only used the technique on a very few occasions. >> > >> > >> > >> > On Tue, Jan 5, 2010 at 11:55 AM, Rolf -nl <[email protected]> >> wrote: >> > > I've extended more's Mask so I can apply an opacity tween effect to >> > > the mask... (and still have all the benefits of Mask, else I could use >> > > DWalsh's Overlay...) >> > >> > > Earlier I tried a simple way to extend Mask, just changing the >> > > showMask and hideMask methods: >> > >http://mootools.net/shell/A65x7/ >> > >> > > But then I get the error: The method "parent" cannot be called. >> > > Q1. Why can't I call the this.parent() methods showMask and hideMask? >> > >> > > Then I extended it in another way (needed to use it, so, went for the >> > > easy way out): >> > >http://mootools.net/shell/PMpZM/ >> > >> > > In the original Mask show (and hide) methods it says: >> > > this.showMask.apply(this, arguments); >> > >> > > Q2: When are these methods (show/hide) getting any arguments? >> > >
