1 /*jshint indent:2, curly:true, eqeqeq:true, immed:true, latedef:true,
2 newcap:true, noarg:true, regexp:true, undef:true, trailing:true,
4 /*global enyo:true, XT:true, XM:true, XV:true, _:true */
13 @name XV.CharacteristicPicker
14 @class For the {@link XV.CharacteristicsWidget} displays the list of characteristics
15 that the user can select from to classify a {@link XV.CharacteristicItem}.
16 @extends XV.PickerWidget
19 /** @lends XV.CharacteristicPicker# */{
20 name: "XV.CharacteristicPicker",
21 kind: "XV.PickerWidget",
22 classes: "xv-characteristic-picker",
23 collection: "XM.characteristics",
24 noneText: "_delete".loc(),
25 noneClasses: "xv-negative",
33 @name XV.OptionsPicker
34 @class Displays a list of items that can be selected.
36 enyo.kind(/** @lends XV.OptionsPicker# */{
37 name: "XV.OptionsPicker",
48 onSelect: "itemSelected"
51 {kind: "onyx.InputDecorator", classes: "xv-input-decorator",
53 {kind: "onyx.PickerDecorator",
55 {classes: "xv-picker"},
56 {name: "picker", kind: "onyx.Picker"}
60 disabledChanged: function () {
61 // XXX Implementation appears slightly crazy because I can't find a disable
62 // setter for onyx.InputDecorator:
63 // http://enyojs.com/api/#onyx.InputDecorator::disabledChange
65 this.$.inputDecorator.disabled = this.disabled;
66 this.$.inputDecorator.bubble("onDisabledChange");
69 @todo Document the itemSelected method.
71 itemSelected: function (inSender, inEvent) {
72 var value = this.$.picker.getSelected().content;
77 @todo Document the setCollection method.
79 setCollection: function (collection) {
84 this.collection = collection;
85 collection.comparator = this.sort;
87 this.$.picker.destroyClientControls();
88 for (i = 0; i < collection.length; i++) {
89 model = collection.at(i);
90 value = model.get('value');
91 c = this.$.picker.createComponent({ content: value });
92 // Autormatically select first
93 if (i === 0) { this.$.picker.setSelected(c); }
98 @todo Document the setValue method.
100 setValue: function (value, options) {
101 options = options || {};
102 var oldValue = this.getValue(),
104 components = this.$.picker.getComponents(),
105 component = _.find(components, function (c) {
106 if (c.kind === "onyx.MenuItem") {
107 return c.content === value;
110 if (!component) { value = null; }
111 this.$.picker.setSelected(component);
113 if (value !== oldValue) {
115 if (!options.silent) {
116 inEvent = { originator: this, value: value };
117 this.doValueChange(inEvent);
123 @todo Document the sort method.
125 sort: function (a, b) {
126 var aord = a.get('order'),
127 bord = b.get('order'),
131 aname = a.get('value');
132 bname = b.get('value');
133 return aname < bname ? -1 : 1;
135 return aord < bord ? -1 : 1;
140 @name XV.CharacteristicItem
141 @class Contains a set of fittable columns which make up a single row in a list of characteristics
142 for the {@link XV.CharacteristicsWidget}.<br />
143 Components: {@link XV.CharacteristicPicker}, {@link XV.InputWidget},
144 {@link XV.DateWidget}, {@link XV.OptionsPicker}.<br />
145 Derived from <a href="http://enyojs.com/api/#enyo.FittableColumns">enyo.FittableColumns</a>.
146 @extends enyo.FittableColumns
148 enyo.kind(/** @lends XV.CharacteristicItem# */{
149 name: "XV.CharacteristicItem",
150 kind: "FittableColumns",
151 classes: "xv-characteristic-item",
157 onValueChange: "controlValueChanged"
160 {kind: "XV.CharacteristicPicker", attr: "characteristic",
162 {kind: "XV.InputWidget", attr: "value", showLabel: false},
163 {kind: "XV.DateWidget", attr: "value", showLabel: false,
165 {kind: "XV.OptionsPicker", attr: "value", showLabel: false,
168 disabledChanged: function (oldValue) {
169 this.$.characteristicPicker.setDisabled(this.disabled);
170 this.$.inputWidget.setDisabled(this.disabled);
171 this.$.dateWidget.setDisabled(this.disabled);
172 this.$.optionsPicker.setDisabled(this.disabled);
175 @todo Document the controlValueChanged method.
177 controlValueChanged: function (inSender, inEvent) {
178 var attr = inSender.getAttr(),
179 value = inSender.getValue(),
181 model = this.getValue(),
184 attributes[attr] = _.isDate(value) ? value.toJSON() : value;
185 model.set(attributes);
186 if (attr === 'characteristic') {
188 characteristic = model.get('characteristic');
189 switch (characteristic.get('characteristicType'))
198 defaultVal = characteristic.get('options').models[0].get('value');
200 model.set('value', defaultVal);
209 @todo Document the getCharacteristicPicker method.
211 getCharacteristicPicker: function () {
212 return this.$.characteristicPicker;
215 @todo Document the valueChanged method.
217 valueChanged: function () {
218 var model = this.getValue(),
219 characteristic = model.get('characteristic'),
220 type = characteristic ?
221 characteristic.get('characteristicType') : TEXT,
222 value = model.get('value'),
228 this.$.dateWidget.hide();
229 this.$.optionsPicker.hide();
230 this.$.inputWidget.show();
231 valueWidget = this.$.inputWidget;
234 this.$.optionsPicker.hide();
235 this.$.inputWidget.hide();
236 this.$.dateWidget.show();
237 valueWidget = this.$.dateWidget;
240 this.$.dateWidget.hide();
241 this.$.inputWidget.hide();
242 this.$.optionsPicker.show();
243 valueWidget = this.$.optionsPicker;
244 options = characteristic.get('options');
245 this.$.optionsPicker.setCollection(options);
247 this.$.characteristicPicker.setValue(characteristic, {silent: true});
248 valueWidget.setValue(value, {silent: true});
253 @name XV.CharacteristicsWidget
254 @class Use to implement a box for entering and viewing characteristics.
255 Made up of a header, a repeater (the control for making the list of characteristic items),
256 and fittable columns for the navigation buttons.<br />
257 Components: {@link XV.CharacteristicItem}.
259 enyo.kind(/** @lends XV.CharacteristicsWidget# */{
260 name: "XV.CharacteristicsWidget",
261 classes: "xv-characteristics-widget xv-input",
266 // note: which is now being kept track of in the model, and maybe should
267 // only be kept track of in the model.
272 {kind: "onyx.GroupboxHeader", content: "_characteristics".loc()},
273 {kind: "Repeater", count: 0, onSetupItem: "setupItem", components: [
274 {kind: "XV.CharacteristicItem"}
276 {kind: "FittableColumns", classes: "xv-characteristic-buttons",
278 {kind: "onyx.Button", name: "newButton",
279 classes: "icon-plus xv-characteristic-button",
283 disabledChanged: function () {
284 this.$.newButton.setDisabled(this.disabled);
289 destroy: function () {
291 this.value.off('add', this.lengthChanged, this);
292 this.value.off('statusChange', this.lengthChanged, this);
294 this.inherited(arguments);
297 Kick off the repeater.
299 lengthChanged: function () {
300 this.$.repeater.setCount(this.readyModels().length);
303 Add a new model to the collection.
305 newItem: function () {
306 var Klass = XT.getObjectByName(this.getModel()),
307 model = new Klass(null, { isNew: true });
308 this.value.add(model);
311 Returns an array of models in the collection whose status is ready.
313 @return {Array} models
315 readyModels: function () {
316 return _.filter(this.value.models, function (model) {
317 var status = model.getStatus(),
319 // Avoiding bitwise because performance matters here
320 return (status === K.READY_CLEAN ||
321 status === K.READY_DIRTY ||
322 status === K.READY_NEW);
326 Render the repeaterlist.
328 setupItem: function (inSender, inEvent) {
329 var item = inEvent.item.$.characteristicItem,
330 model = this.readyModels()[inEvent.index],
331 which = this.getWhich(),
332 picker = item.getCharacteristicPicker(),
333 filter = function (models) {
334 return _.filter(models, function (m) {
338 item.setValue(model);
339 item.setDisabled(this.disabled);
341 // quote characteristics, notably, have no picker
342 picker.filter = filter;
344 if (!model.get('characteristic')) {
351 Sort by status, then order, then name
353 sort: function (a, b) {
354 var astatus = a.isNew(),
356 achar = a.get('characteristic'),
357 bchar = b.get('characteristic'),
358 aord = achar ? achar.get('order') : null,
359 bord = bchar ? bchar.get('order') : null,
362 if (astatus === bstatus) {
364 aname = achar ? achar.get('name') : null;
365 bname = bchar ? bchar.get('name') : null;
366 return aname < bname ? -1 : 1;
368 return aord < bord ? -1 : 1;
370 return astatus < bstatus ? -1 : 1;
373 @param {XM.Collection} value
375 setValue: function (value) {
377 this.value.off('add', this.lengthChanged, this);
378 this.value.off('statusChange', this.lengthChanged, this);
381 this.value.on('add', this.lengthChanged, this);
382 this.value.on('statusChange', this.lengthChanged, this);
383 this.value.comparator = this.sort;
385 this.lengthChanged();