Hi,

FWIW, I wouldn't use a Hash for `observableChanges` either, it's
overkill. Just use an object:

// Initializing it when creating the class:
this.observableChanges = {}; // {} is a more concise way to say new
Object()

// Checking for/getting the array of observer tuples:
var observationTuples = this.observableChanges[property];
if (!observationTuples) {
    observationTuples = this.observableChanges[property] = []; // [] =
new Array()
}

// Adding a new tuple using object literal notation
observationTuples.push({
    observer: observer,
    callback: callback
});

> I have several classes that I'd like to have this functionality. What
> approach would you recommend for doing that? Subclassing?

Probably a mix-in rather than a superclass.

HTH,
--
T.J. Crowder
Independent Software Consultant
tj / crowder software / com
www.crowdersoftware.com


On Dec 4, 9:10 pm, Wil <[email protected]> wrote:
> TJ and David,
>
> Thanks - that was all very useful information and I have things
> working now.
>
> The info.key.info.value business was, in retrospect, a fairly silly
> failure to think about the order of operations. I somehow expected it
> to have been (info.key).(info.value), rather than
> ((info.key).info).value...
>
> Good to know that Hash only works with string keys. Obvious, I guess,
> or at least well documented :)
>
> As a followup, given the working approach:
>
> MyClass1.prototype.observeValueChange = function(observer, property,
> callback) {
>     if (this.observableChanges == null) this.observableChanges = new
> Hash();
>     var observationTuples = this.observableChanges.get(property);
>     if (observationTuples == null) {
>         observationTuples = new Array();
>         this.observableChanges.set(property, observationTuples);
>     }
>     var tuple = new Object();
>     tuple['observer'] = observer;
>     tuple['callback'] = callback;
>     observationTuples.push(tuple);
>
> }
>
> MyClass1.prototype.fireValueChanged = function(property) {
>     if (this.observableChanges == null) return;
>     var observationTuples = this.observableChanges.get(property);
>     if (observationTuples == null) return;
>     var that = this;
>     observationTuples.each(function(tuple) {
>         var obj = tuple.observer;
>         var func = tuple.callback;
>         func.call(obj, that);
>     });
>
> }
>
> I have several classes that I'd like to have this functionality. What
> approach would you recommend for doing that? Subclassing?
>
> Thanks,
>
> Wil
>
> On Dec 4, 3:38 am, david <[email protected]> wrote:
>
>
>
> > Hi,
>
> > Thanks to TJ answer, I forgot THE each second argument to
> > automatically bind the called function to a context.
>
> > --
> > david.
>
> > On 4 déc, 12:22, "T.J. Crowder" <[email protected]> wrote:
>
> > > Hi,
>
> > > > Tracing through the code, everything appears fine up to the point
> > > > where I try to call the stored callback. This line:
>
> > > > info.key.info.value(this));
>
> > > > info.key and info.value are both valid objects, but nothing happens.
>
> > > Your 'info.key' property is your observer, which I tend to suspect
> > > doesn't then have a property called 'info' on it, but that's what
> > > "info.key.info" retrieves. Then you retrieve the 'value' property from
> > > that and try to call it ("info.key.info.value(this)"). You're also
> > > passing in a 'this' value which refers to the browser window, whereas
> > > I suspect you wanted to refer to the observable object.
>
> > > I think this is what you meant:
>
> > >     observerInfo.each(function(info) {
> > >         info.value.call(info.key, this);
> > >     }, this);
>
> > > ...which will call the callback setting the observer as the context
> > > (the 'this' value within the callback) and passing in the observed
> > > object -- note that to do that, I had to pass 'this' into #each as its
> > > second argument because otherwise context is lost when you call #each.
>
> > > But the above, by itself, won't solve the problems because I think you
> > > probably have an issue here:
>
> > > > this.observableChanges.get(property).set(observer, callback);
>
> > > Hash#set is documented as accepting a String for the key, but you're
> > > passing in other kinds of objects, not just strings. You can't rely on
> > > the key not getting converted to a string (a string that will probably
> > > be "[Object]" or similar).
>
> > > FWIW, I probably wouldn't use Hash for this at all, it's overkill for
> > > the 'observableChanges' property and mis-matched for the values within
> > > that. I'd probably just use a plain JavaScript object for
> > > 'observableChanges' using the property name as the key, with the value
> > > being an array of tuples for the callbacks to make.
>
> > > HTH,
> > > --
> > > T.J. Crowder
> > > Independent Software Consultant
> > > tj / crowder software / comwww.crowdersoftware.com
>
> > > On Dec 3, 9:00 pm, Wil <[email protected]> wrote:
>
> > > > Hi all,
>
> > > > I'm trying to implement a somewhat generic way for my controller
> > > > objects to listen for changes to various properties of my model
> > > > objects. I'm not a javascript expert, so there is quite possibly a
> > > > Better Way™ of solving the bigger problem - I'm open to pointers in
> > > > that direction, if my current approach is not a good idea.
>
> > > > Here's the machinery I currently have in place:
>
> > > > MyClass.prototype.observeValueChange = function(observer, property,
> > > > callback) {
> > > >     if (this.observableChanges == null) this.observableChanges = new
> > > > Hash();
> > > >     if (this.observableChanges.get(property) == null)
> > > > this.observableChanges.set(property, new Hash());
> > > >     this.observableChanges.get(property).set(observer, callback);
>
> > > > }
>
> > > > MyClass.prototype.fireValueChanged = function(property) {
> > > >     if (this.observableChanges == null) return;
> > > >     var observerInfo = this.observableChanges.get(property);
> > > >     if (observerInfo == null) return;
> > > >     observerInfo.each(function(info) {
> > > >         info.key.info.value(this));
> > > >     });
>
> > > > }
>
> > > > Here's an example of registering to listen:
>
> > > > objectOfMyObservableClass.observeValueChange(this, 'foo', function
> > > > (destination) {
> > > >     alert("observed change in foo");
>
> > > > });
>
> > > > objectOfMyObservableClass.fireValueChanged("foo");
>
> > > > Tracing through the code, everything appears fine up to the point
> > > > where I try to call the stored callback. This line:
>
> > > > info.key.info.value(this));
>
> > > > info.key and info.value are both valid objects, but nothing happens.
>
> > > > Thanks in advance!

--

You received this message because you are subscribed to the Google Groups 
"Prototype & script.aculo.us" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en.


Reply via email to