diff --git a/src/model.js b/src/model.js
index 7df18923..2f222c3f 100644
--- a/src/model.js
+++ b/src/model.js
@@ -106,7 +106,25 @@ my.Dataset = Backbone.Model.extend({
//
// A single entry or row in the dataset
my.Document = Backbone.Model.extend({
- __type__: 'Document'
+ __type__: 'Document',
+ initialize: function() {
+ _.bindAll(this, 'getFieldValue');
+ },
+
+ // ### getFieldValue
+ //
+ // For the provided Field get the corresponding rendered computed data value
+ // for this document.
+ getFieldValue: function(field) {
+ var val = this.get(field.id);
+ if (field.deriver) {
+ val = field.deriver(val, field, this);
+ }
+ if (field.renderer) {
+ val = field.renderer(val, field, this);
+ }
+ return val;
+ }
});
// ## A Backbone collection of Documents
@@ -117,18 +135,46 @@ my.DocumentList = Backbone.Collection.extend({
// ## A Field (aka Column) on a Dataset
//
-// Following attributes as standard:
+// Following (Backbone) attributes as standard:
//
-// * id: a unique identifer for this field- usually this should match the key in the documents hash
-// * label: the visible label used for this field
-// * type: the type of the data
+// * id: a unique identifer for this field- usually this should match the key in the documents hash
+// * label: (optional: defaults to id) the visible label used for this field
+// * type: (optional: defaults to string) the type of the data in this field. Should be a string as per type names defined by ElasticSearch - see Types list on
+// * format: (optional) used to indicate how the data should be formatted. For example:
+// * type=date, format=yyyy-mm-dd
+// * type=float, format=percentage
+// * type=float, format='###,###.##'
+// * is_derived: (default: false) attribute indicating this field has no backend data but is just derived from other fields (see below).
+//
+// Following additional instance properties:
+//
+// @property {Function} renderer: a function to render the data for this field.
+// Signature: function(value, field, doc) where value is the value of this
+// cell, field is corresponding field object and document is the document
+// object. Note that implementing functions can ignore arguments (e.g.
+// function(value) would be a valid formatter function).
+//
+// @property {Function} deriver: a function to derive/compute the value of data
+// in this field as a function of this field's value (if any) and the current
+// document, its signature and behaviour is the same as for renderer. Use of
+// this function allows you to define an entirely new value for data in this
+// field. This provides support for a) 'derived/computed' fields: i.e. fields
+// whose data are functions of the data in other fields b) transforming the
+// value of this field prior to rendering.
my.Field = Backbone.Model.extend({
+ // ### defaults - define default values
defaults: {
- id: null,
label: null,
- type: 'String'
+ type: 'string',
+ format: null,
+ is_derived: false
},
- initialize: function(data) {
+ // ### initialize
+ //
+ // @param {Object} data: standard Backbone model attributes
+ //
+ // @param {Object} options: renderer and/or deriver functions.
+ initialize: function(data, options) {
// if a hash not passed in the first argument throw error
if ('0' in data) {
throw new Error('Looks like you did not pass a proper hash with id to Field constructor');
@@ -136,6 +182,10 @@ my.Field = Backbone.Model.extend({
if (this.attributes.label == null) {
this.set({label: this.id});
}
+ if (options) {
+ this.renderer = options.renderer;
+ this.deriver = options.deriver;
+ }
}
});
diff --git a/test/model.test.js b/test/model.test.js
index 1bdff485..406692bc 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -38,6 +38,37 @@ test('Field: basics', function () {
equal('XX', out[0].label);
});
+test('Field: deriver and renderer', function () {
+ var doc = new recline.Model.Document({x: 123});
+ var cellRenderer = function(value, field) {
+ return '' + value + '';
+ }
+ var deriver = function(val, field, doc) {
+ return doc.get('x') * 2
+ }
+
+ var field = new recline.Model.Field({id: 'computed', is_derived: true}, {
+ deriver: deriver
+ });
+ var out = doc.getFieldValue(field);
+ var exp = 246;
+ equal(out, exp);
+
+ var field = new recline.Model.Field({id: 'x'}, {
+ renderer: cellRenderer
+ });
+ var out = doc.getFieldValue(field);
+ var exp = '123'
+ equal(out, exp);
+
+ var field = new recline.Model.Field({id: 'computed'}, {
+ renderer: cellRenderer,
+ deriver: deriver
+ });
+ var out = doc.getFieldValue(field);
+ var exp = '246'
+ equal(out, exp);
+});
// =================================
// Dataset