ares-ide
Version:
A browser-based code editor and UI designer for Enyo 2 projects
126 lines (125 loc) • 4.49 kB
JavaScript
//*@public
/**
The _enyo.ModelController_ kind is designed as a proxy for other objects
to bind to properties of a _model_ safely, even when the model is changing.
It also allows for extended logic capabilities beyond that of the _model_
alone without modifying the _model_ kind. Its primary purpose is to _proxy_
the underlying data from the _model_. Like _enyo.Model_, the use of the _get_
and _set_ methods are restricted to _attributes_ of the _model_ schema. There
are convenience methods _localGet_ and _localSet_ that will act like the _get_
and _set_ of _enyo.Object_ and subkinds. This _controller_ has the ability
to interact with the _enyo.Component_ event system but also proxies the _event_
API of _enyo.Model_ and _enyo.Controller_.
*/
enyo.kind({
name: "enyo.ModelController",
kind: enyo.Controller,
/**
This property must be set to an instance of _enyo.Model_ for it
to function as expected.
*/
model: null,
/**
Retrieve an _attribute_ from the _model_ (if it exists). The only exceptions
are the _model_ property itself may be returned from this method or _computed_
properties of the _controller_. This way, _bindings_ can correctly bind to
a _model controller's computed properties_ without modifying the _model_ definition.
There is a limitation here that a computed property with the same name as an _attribute_
or _computed property_ of the _model_ will not be accessible to _bindings_ on the
_model controller_.
*/
get: function (prop) {
if (prop == "model") {
return this.getLocal(prop);
} else if (this._isComputed(prop)) {
return this._getComputed(prop);
} else if (this.model) {
return this.model.get.apply(this.model, arguments);
} else {
// to ensure that bindings will clear according to their api
return null;
}
},
/**
Will allow the retrieval of local properties and computed properties
according to the _enyo.Object.get_ method.
*/
getLocal: function () {
return enyo.getPath.apply(this, arguments);
},
/**
Set an _attribute_ (or _attributes_ if an object) on the _model_
(if it exists). Returns the _model_ if it exists otherwise _undefined_.
The only exception is the _model_ properties itself may be set using
this method as well.
*/
set: function (prop, value) {
if (prop == "model") { return this.setLocal(prop, value); }
if (this.model) { return this.model.set.apply(this.model, arguments); }
},
/**
Will allow the setting of local properties according to the _enyo.Object.set_
method.
*/
setLocal: function () {
return enyo.setPath.apply(this, arguments);
},
/**
To arbitrarily update any bindings to known _attributes_ of the
_model_ (if it exists), call this method. Optionally provide
a hash of properties and values with which to notify observers noting
that the values will be used as the _previous_ values if there is
no `model` present on the _controller_.
*/
sync: function (props) {
var m = this.model,
aa = props || (this.model && this.model.attributes);
for (var k in aa) { this.notifyObservers(k, m? m.previous[k]: aa[k], m? this.model.get(k): null); }
},
/**
This method responds to the _model_ property being set on this _controller_.
Overload this method for additional behaviors.
*/
modelChanged: function (previous, model) {
var p = previous,
m = model;
// remove our listeners from the model that is no longer ours
if (p) {
p.removeListener("change", this._modelChanged);
p.removeListener("destroy", this._modelDestroyed);
// if we're removing the current record and there isn't a replacement
// we need to synchronize observers related to this record
if (!m) { this.sync(p.attributes); }
}
if (m) {
// assign listeners to respond to events from the model
m.addListener("change", this._modelChanged);
m.addListener("destroy", this._modelDestroyed);
this.sync();
}
},
//*@protected
create: enyo.inherit(function (sup) {
return function () {
sup.apply(this, arguments);
if (this.model) {
this.notifyObservers("model", null, this.model);
}
};
}),
constructor: enyo.inherit(function (sup) {
return function () {
sup.apply(this, arguments);
this._modelChanged = this.bindSafely("_modelChanged");
};
}),
_modelChanged: function (r) {
var ch = r.changed;
for (var k in ch) { this.notifyObservers(k, r.previous[k], ch[k]); }
},
_modelDestroyed: function (r) {
if (r === this.model) {
this.setLocal("model", null);
}
}
});