1 | var _ = require("underscore");
|
2 | var Trackr = require("trackr");
|
3 | var utils = require("./utils");
|
4 | var Model = require("./model");
|
5 | var View = require("./view");
|
6 |
|
7 | var Section =
|
8 | module.exports = View.extend({
|
9 | constructor: function() {
|
10 | this.rows = {};
|
11 | this._row_deps = {};
|
12 | View.apply(this, arguments);
|
13 | },
|
14 |
|
15 | invert: function(val) {
|
16 | if (!_.isBoolean(val)) val = !this._inverted;
|
17 | this._inverted = val;
|
18 | return this;
|
19 | },
|
20 |
|
21 | isInverted: function() {
|
22 | return !!this._inverted;
|
23 | },
|
24 |
|
25 | setPath: function(path) {
|
26 | this._path = path;
|
27 | return this;
|
28 | },
|
29 |
|
30 | onRow: function(fn) {
|
31 | if (!_.isFunction(fn))
|
32 | throw new Error("Expecting function for row handler.");
|
33 |
|
34 | this._onRow = fn;
|
35 | return this;
|
36 | },
|
37 |
|
38 | addRow: function(key, data) {
|
39 |
|
40 | this.removeRow(key);
|
41 |
|
42 |
|
43 | if (!Model.isModel(data)) {
|
44 | data = new Model(data, this.model);
|
45 | }
|
46 |
|
47 |
|
48 | var row = new View(data);
|
49 |
|
50 |
|
51 | row.render = this._onRow;
|
52 | this.rows[key] = row;
|
53 | this.addMember(row);
|
54 | row.mount();
|
55 |
|
56 | return row;
|
57 | },
|
58 |
|
59 | hasRow: function(key) {
|
60 | return this.getRow(key) != null;
|
61 | },
|
62 |
|
63 | getRow: function(key) {
|
64 | return this.rows[key];
|
65 | },
|
66 |
|
67 | removeRow: function(key) {
|
68 | if (this.rows[key] == null) return this;
|
69 |
|
70 | var row = this.rows[key];
|
71 | this.removeMember(row);
|
72 | delete this.rows[key];
|
73 |
|
74 | return this;
|
75 | },
|
76 |
|
77 | removeAllRows: function() {
|
78 | Object.keys(this.rows).forEach(this.removeRow, this);
|
79 | return this;
|
80 | },
|
81 |
|
82 | render: function() {
|
83 | if (this._path == null) throw new Error("Missing path.");
|
84 |
|
85 | var self = this,
|
86 | val, isEmpty, inverted, isList,
|
87 | rowSort, model, proxy, keys;
|
88 |
|
89 | val = this.get(this._path);
|
90 | model = new Model(val, this.model);
|
91 | proxy = model.getProxyByValue(val);
|
92 | inverted = this.isInverted();
|
93 | isList = model.callProxyMethod(proxy, val, "isList");
|
94 |
|
95 | function getEmptiness() {
|
96 | return model.callProxyMethod(proxy, val, "isEmpty");
|
97 | }
|
98 |
|
99 | Trackr.nonreactive(function() {
|
100 | isEmpty = !val || (isList && !getEmptiness())
|
101 | });
|
102 |
|
103 | if (isEmpty && inverted) {
|
104 | if (isList) getEmptiness();
|
105 | this.addRow(0, model);
|
106 | } else if (!isEmpty && !inverted) {
|
107 | if (isList) {
|
108 | keys = [];
|
109 |
|
110 | this.autorun(function(comp) {
|
111 | var nkeys = model.callProxyMethod(proxy, val, "keys");
|
112 |
|
113 |
|
114 | Trackr.currentComputation = comp._parent;
|
115 |
|
116 |
|
117 | _.difference(keys, nkeys).forEach(function(key) {
|
118 | if (this._row_deps[key]) {
|
119 | this._row_deps[key].stop();
|
120 | delete this._row_deps[key];
|
121 | }
|
122 |
|
123 | this.removeRow(key);
|
124 | }, this);
|
125 |
|
126 |
|
127 | _.difference(nkeys, keys).forEach(function(key) {
|
128 | var row, rmodel;
|
129 |
|
130 | row = this.getRow(key);
|
131 | rmodel = row != null ? row.model :
|
132 | new Model(null, new Model({ $key: key }, this.model));
|
133 |
|
134 | this._row_deps[key] = this.autorun(function(c) {
|
135 | rmodel.set(model.callProxyMethod(proxy, val, "get", key));
|
136 |
|
137 | });
|
138 |
|
139 |
|
140 | if (row == null) this.addRow(key, rmodel);
|
141 | }, this);
|
142 |
|
143 |
|
144 | Trackr.currentComputation = comp;
|
145 |
|
146 |
|
147 | keys = nkeys;
|
148 | });
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 | } else {
|
163 | this.addRow(0, model);
|
164 | }
|
165 | } else if (isList) {
|
166 | getEmptiness();
|
167 | }
|
168 |
|
169 |
|
170 | this.once("invalidate", function() {
|
171 | this._row_deps = {};
|
172 | this.removeAllRows();
|
173 | });
|
174 | }
|
175 |
|
176 | }, {
|
177 |
|
178 | isEmpty: function(model, proxy) {
|
179 | if (!model.data) return true;
|
180 | if (proxy == null) proxy = model.getProxyByValue(model.data);
|
181 | return model.callProxyMethod(proxy, model.data, "isList") &&
|
182 | model.callProxyMethod(proxy, model.data, "isEmpty");
|
183 | }
|
184 |
|
185 | });
|