/src/js/cilantro/structs.js

https://github.com/cbmi/cilantro · JavaScript · 230 lines · 166 code · 57 blank · 7 comment · 12 complexity · d9c7d7fb2d1c3c97cafd44ca51060e90 MD5 · raw file

  1. /* global define */
  2. define([
  3. 'underscore',
  4. 'backbone',
  5. './models/base'
  6. ], function(_, Backbone, base) {
  7. var Index = Backbone.Model.extend({
  8. defaults: {
  9. visible: true
  10. },
  11. show: function() {
  12. this.set({
  13. visible: true
  14. });
  15. },
  16. hide: function() {
  17. this.set({
  18. visible: false
  19. });
  20. }
  21. });
  22. var Indexes = Backbone.Collection.extend({
  23. model: Index
  24. });
  25. var Datum = Backbone.Model.extend({
  26. constructor: function(attrs, index, options) {
  27. if (!(index instanceof Index)) {
  28. index = new Index(index);
  29. }
  30. this.index = index;
  31. Backbone.Model.prototype.constructor.call(this, attrs, options);
  32. },
  33. size: function() {
  34. return 1;
  35. },
  36. width: function() {
  37. return 1;
  38. }
  39. });
  40. // A collection of Datum objects which serves as an internal container for
  41. // the Series.
  42. var _DatumArray = Backbone.Collection.extend({
  43. constructor: function(attrs, indexes, options) {
  44. this.indexes = indexes;
  45. var _this = this;
  46. this.model = function(value, options) {
  47. // Collections length are not updated immediately so this uses the
  48. // internal hash to determine the next index.
  49. var index = _this.indexes.at(_.keys(_this._byId).length);
  50. Datum.prototype.constructor.call(this, {value: value}, index, options);
  51. };
  52. this.model.prototype = Datum.prototype;
  53. Backbone.Collection.prototype.constructor.call(this, attrs, options);
  54. }
  55. });
  56. var Series = Backbone.Model.extend({
  57. constructor: function(attrs, indexes, options) {
  58. var data;
  59. if (!options) options = {};
  60. if (!(indexes instanceof Indexes)) {
  61. indexes = new Indexes(indexes);
  62. }
  63. this.indexes = indexes;
  64. if (_.isArray(attrs)) {
  65. data = attrs;
  66. attrs = null;
  67. }
  68. else {
  69. options.parse = true;
  70. }
  71. this.data = new _DatumArray(data, indexes);
  72. Backbone.Model.prototype.constructor.call(this, attrs, options);
  73. },
  74. parse: function(resp, options) {
  75. this.data.reset(resp.values, options);
  76. delete resp.values;
  77. return resp;
  78. },
  79. isColumn: function() {
  80. return this.width() === 1;
  81. },
  82. isRow: function() {
  83. return !this.isColumn();
  84. },
  85. size: function() {
  86. if (this.isColumn()) {
  87. return this.data.length;
  88. }
  89. return 1;
  90. },
  91. width: function() {
  92. return this.indexes.length;
  93. }
  94. });
  95. // Collection of Series objects that serves as an internal container for
  96. // the Frame object.
  97. var _SeriesArray = Backbone.Collection.extend({
  98. constructor: function(attrs, indexes, options) {
  99. this.indexes = indexes;
  100. var _this = this;
  101. this.model = function(attrs, options) {
  102. Series.prototype.constructor.call(this, attrs, _this.indexes, options);
  103. };
  104. this.model.prototype = Series.prototype;
  105. Backbone.Collection.prototype.constructor.call(this, attrs, options);
  106. }
  107. });
  108. var Frame = base.Model.extend({
  109. constructor: function(attrs, indexes, options) {
  110. var data;
  111. if (!options) options = {};
  112. if (!(indexes instanceof Indexes)) {
  113. indexes = new Indexes(indexes);
  114. }
  115. this.indexes = indexes;
  116. if (_.isArray(attrs)) {
  117. data = attrs;
  118. attrs = null;
  119. }
  120. else {
  121. options.parse = true;
  122. }
  123. this.series = new _SeriesArray(data, indexes);
  124. base.Model.prototype.constructor.call(this, attrs, options);
  125. },
  126. parse: function(resp, options) {
  127. base.Model.prototype.parse.call(this, resp, options);
  128. this.indexes.reset(resp.keys, options);
  129. this.series.reset(resp.items, options);
  130. delete resp.keys;
  131. delete resp.items;
  132. return resp;
  133. },
  134. size: function() {
  135. return this.series.length;
  136. },
  137. width: function() {
  138. return this.indexes.length;
  139. },
  140. column: function(index) {
  141. var data = this.series.map(function(series) {
  142. return series.data.at(index);
  143. });
  144. return new Series(data, this.indexes.at(index));
  145. }
  146. });
  147. var FrameArray = base.Collection.extend({
  148. model: Frame,
  149. constructor: function(attrs, options) {
  150. this.indexes = new Indexes();
  151. this.on('reset', function(collection) {
  152. var model = collection.models[0];
  153. if (model) {
  154. return this.indexes.reset(model.indexes.models);
  155. }
  156. });
  157. this.on('add', function(model, collection) {
  158. if (collection.length === 1) {
  159. return this.indexes.reset(model.indexes.models);
  160. }
  161. });
  162. base.Collection.prototype.constructor.call(this, attrs, options);
  163. }
  164. });
  165. return {
  166. Datum: Datum,
  167. Frame: Frame,
  168. FrameArray: FrameArray,
  169. Index: Index,
  170. Indexes: Indexes,
  171. Series: Series
  172. };
  173. });