can
Version:
MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
170 lines (137 loc) • 5.24 kB
Markdown
Object<String,can.Map.prototype.define.attrDefinition>} can.Map.prototype.define define
can.Map.plugins
Defines the
type, initial value, get, set, remove, and serialize behavior for attributes
of a [can.Map].
{Object<String,can.Map.prototype.define.attrDefinition>} A map of
attribute names to [can.Map::define.attrDefinition attribute definition]
objects.
## Use
The [can.Map::define can.Map.define] plugin allows you to completely control the behavior
of attributes on a [can.Map]. To use it, you specify
an define object that is a mapping of properties
to [can.Map::define.attrDefinition attribute definitions]. The following example
specifies a Paginate Map:
var Paginate = can.Map.extend({
define: {
count: {
type: "number",
value: Infinity,
// Keeps count above 0.
set: function(newCount){
return newCount < 0 ? 0 : newCount;
}
},
offset: {
type: "number",
value: 0,
// Keeps offset between 0 and count
set: function(newOffset){
var count = this.attr("count");
return newOffset < 0 ?
0 :
Math.min(newOffset, !isNaN( count - 1) ?
count - 1 :
Infinity);
}
},
limit: {
type: "number",
value: 5
},
page: {
// Setting page changes the offset
set: function(newVal){
this.attr('offset', (parseInt(newVal) - 1) *
this.attr('limit'));
},
// The page value is derived from offset and limit.
get: function (newVal) {
return Math.floor(this.attr('offset') /
this.attr('limit')) + 1;
}
}
}
});
## Default behaviors
The [can.Map::define can.Map.define] plugin not only allows you to define
individual attribute behaviors on a [can.Map], but you can also define default
behaviors that would apply to any unspecified attribute. This is particularly
helpful for when you need a particular behavior to apply to every attribute on
a [can.Map] but won't be certain of what every attribute will be.
The following example is a [can.Map] that is tied to [can.route] where only
specified attributes that are serialized will be updated in the location hash:
var State = can.Map.extend({
define: {
foo: {
serialize: true
},
'*': {
serialize: false
}
}
});
var state = new State();
// tie State map to the route
can.route.map(state);
can.route.ready();
state.attr('foo', 'bar');
state.attr('bar', 'baz');
window.location.hash; // -> #!foo=bar
## Overview
This plugin is a replacement for the now deprecated [can.Map.attributes attributes] and [can.Map.setter setter] plugins. It intends to provide a single place to define the behavior of all the properties of a can.Map.
Here is the cliffnotes version of this plugin. To define...
* The default value for a property - use [can.Map.prototype.define.value value]
* That default value as a constructor function - use [can.Map.prototype.define.ValueConstructor Value]
* What value is returned when a property is read - use [can.Map.prototype.define.get get]
* Behavior when a property is set - use [can.Map.prototype.define.set set]
* How a property is serialized when [can.Map::serialize serialize] is called on it - use [can.Map.prototype.define.serialize serialize]
* Behavior when a property is removed - use [can.Map.prototype.define.remove remove]
* A custom converter method or a pre-defined standard converter called whenever a property is set - use [can.Map.prototype.define.type type]
* That custom converter method as a constructor function - use [can.Map.prototype.define.TypeConstructor Type]
## Inheritance
[can.Map] constructors can inherit values from the [can.Map::define can.Map.define]
plugin. If a parent [can.Map] constructor has a `define` property and a child
constructor extends the parent and also has a `define` property, the two will
be merged together so `define` properties from the parent are also available
on instances of the child. For example:
var ParentMap = can.Map.extend({
define: {
inheritedProp: {
get: function() {
return 15;
},
set: function(newVal) {
return newVal;
}
},
parentProp: {
get: function() {
return 15;
}
}
}
});
var ChildMap = ParentMap.extend({
define: {
childProp: {
get: function() {
return 22;
}
},
inheritedProp: {
get: function() {
return 22;
}
}
}
});
var map = new ChildMap();
map.attr('childProp'); // -> 22
map.attr('inheritedProp'); // -> 22
map.attr('parentProp'); // -> 15
map.attr('inheritedProp', 13); // -> calls ParentMap’s setter for inheritedProp
## Demo
The following shows picking cars by make / model / year:
can/map/define/doc/examples/make-model-year.html
{