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 collection: "XM.characteristics",
23 noneText: "_delete".loc(),
24 noneClasses: "xv-negative",
32 @name XV.OptionsPicker
33 @class Displays a list of items that can be selected.
35 enyo.kind(/** @lends XV.OptionsPicker# */{
36 name: "XV.OptionsPicker",
47 onSelect: "itemSelected"
50 {kind: "onyx.InputDecorator", classes: "xv-input-decorator",
52 {kind: "onyx.PickerDecorator",
54 {classes: "xv-picker"},
55 {name: "picker", kind: "onyx.Picker"}
59 disabledChanged: function () {
60 // XXX Implementation appears slightly crazy because I can't find a disable
61 // setter for onyx.InputDecorator:
62 // http://enyojs.com/api/#onyx.InputDecorator::disabledChange
64 this.$.inputDecorator.disabled = this.disabled;
65 this.$.inputDecorator.bubble("onDisabledChange");
68 @todo Document the itemSelected method.
70 itemSelected: function (inSender, inEvent) {
71 var value = this.$.picker.getSelected().content;
76 @todo Document the setCollection method.
78 setCollection: function (collection) {
83 this.collection = collection;
84 collection.comparator = this.sort;
86 this.$.picker.destroyClientControls();
87 for (i = 0; i < collection.length; i++) {
88 model = collection.at(i);
89 value = model.get('value');
90 c = this.$.picker.createComponent({ content: value });
91 // Autormatically select first
92 if (i === 0) { this.$.picker.setSelected(c); }
97 @todo Document the setValue method.
99 setValue: function (value, options) {
100 options = options || {};
101 var oldValue = this.getValue(),
103 components = this.$.picker.getComponents(),
104 component = _.find(components, function (c) {
105 if (c.kind === "onyx.MenuItem") {
106 return c.content === value;
109 if (!component) { value = null; }
110 this.$.picker.setSelected(component);
112 if (value !== oldValue) {
114 if (!options.silent) {
115 inEvent = { originator: this, value: value };
116 this.doValueChange(inEvent);
122 @todo Document the sort method.
124 sort: function (a, b) {
125 var aord = a.get('order'),
126 bord = b.get('order'),
130 aname = a.get('value');
131 bname = b.get('value');
132 return aname < bname ? -1 : 1;
134 return aord < bord ? -1 : 1;
139 @name XV.CharacteristicItem
140 @class Contains a set of fittable columns which make up a single row in a list of characteristics
141 for the {@link XV.CharacteristicsWidget}.<br />
142 Components: {@link XV.CharacteristicPicker}, {@link XV.InputWidget},
143 {@link XV.DateWidget}, {@link XV.OptionsPicker}.<br />
144 Derived from <a href="http://enyojs.com/api/#enyo.FittableColumns">enyo.FittableColumns</a>.
145 @extends enyo.FittableColumns
147 enyo.kind(/** @lends XV.CharacteristicItem# */{
148 name: "XV.CharacteristicItem",
149 kind: "enyo.Control",
150 classes: "xv-characteristic-item",
156 onValueChange: "controlValueChanged"
159 {controlClasses: 'enyo-inline', components: [
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,
169 disabledChanged: function (oldValue) {
170 this.$.characteristicPicker.setDisabled(this.disabled);
171 this.$.inputWidget.setDisabled(this.disabled);
172 this.$.dateWidget.setDisabled(this.disabled);
173 this.$.optionsPicker.setDisabled(this.disabled);
176 @todo Document the controlValueChanged method.
178 controlValueChanged: function (inSender, inEvent) {
179 var attr = inSender.getAttr(),
180 value = inSender.getValue(),
182 model = this.getValue(),
185 attributes[attr] = _.isDate(value) ? value.toJSON() : value;
186 model.set(attributes);
187 if (attr === 'characteristic') {
189 characteristic = model.get('characteristic');
190 switch (characteristic.get('characteristicType'))
199 defaultVal = characteristic.get('options').models[0].get('value');
201 model.set('value', defaultVal);
210 @todo Document the getCharacteristicPicker method.
212 getCharacteristicPicker: function () {
213 return this.$.characteristicPicker;
216 @todo Document the valueChanged method.
218 valueChanged: function () {
219 var model = this.getValue(),
220 characteristic = model.get('characteristic'),
221 type = characteristic ?
222 characteristic.get('characteristicType') : TEXT,
223 value = model.get('value'),
229 this.$.dateWidget.hide();
230 this.$.optionsPicker.hide();
231 this.$.inputWidget.show();
232 valueWidget = this.$.inputWidget;
235 this.$.optionsPicker.hide();
236 this.$.inputWidget.hide();
237 this.$.dateWidget.show();
238 valueWidget = this.$.dateWidget;
241 this.$.dateWidget.hide();
242 this.$.inputWidget.hide();
243 this.$.optionsPicker.show();
244 valueWidget = this.$.optionsPicker;
245 options = characteristic.get('options');
246 this.$.optionsPicker.setCollection(options);
248 this.$.characteristicPicker.setValue(characteristic, {silent: true});
249 valueWidget.setValue(value, {silent: true});
254 @name XV.CharacteristicsWidget
255 @class Use to implement a box for entering and viewing characteristics.
256 Made up of a header, a repeater (the control for making the list of characteristic items),
257 and fittable columns for the navigation buttons.<br />
258 Components: {@link XV.CharacteristicItem}.
260 enyo.kind(/** @lends XV.CharacteristicsWidget# */{
261 name: "XV.CharacteristicsWidget",
262 classes: "xv-characteristics-widget xv-input",
267 // note: which is now being kept track of in the model, and maybe should
268 // only be kept track of in the model.
274 {kind: "onyx.GroupboxHeader", content: "_characteristics".loc()},
275 {kind: "Repeater", count: 0, onSetupItem: "setupItem", components: [
276 {kind: "XV.CharacteristicItem"}
278 {controlClasses: 'enyo-inline', classes: "xv-buttons", components: [
279 {name: "label", classes: "xv-label"},
280 {kind: "onyx.Button", name: "newButton",
281 classes: "icon-plus xv-characteristic-button", onclick: "newItem"}
284 create: function () {
285 this.inherited(arguments);
286 this.showLabelChanged();
288 disabledChanged: function () {
289 this.$.newButton.setDisabled(this.disabled);
294 destroy: function () {
296 this.value.off('add', this.lengthChanged, this);
297 this.value.off('statusChange', this.lengthChanged, this);
299 this.inherited(arguments);
302 Kick off the repeater.
304 lengthChanged: function () {
305 this.$.repeater.setCount(this.readyModels().length);
308 Add a new model to the collection.
310 newItem: function () {
311 var Klass = XT.getObjectByName(this.getModel()),
312 model = new Klass(null, { isNew: true });
313 this.value.add(model);
316 Returns an array of models in the collection whose status is ready.
318 @return {Array} models
320 readyModels: function () {
321 return _.filter(this.value.models, function (model) {
322 var status = model.getStatus(),
324 // Avoiding bitwise because performance matters here
325 return (status === K.READY_CLEAN ||
326 status === K.READY_DIRTY ||
327 status === K.READY_NEW);
331 Render the repeaterlist.
333 setupItem: function (inSender, inEvent) {
334 var item = inEvent.item.$.characteristicItem,
335 model = this.readyModels()[inEvent.index],
336 which = this.getWhich(),
337 picker = item.getCharacteristicPicker(),
338 filter = function (models) {
339 return _.filter(models, function (m) {
343 item.setValue(model);
344 item.setDisabled(this.disabled);
346 // quote characteristics, notably, have no picker
347 picker.filter = filter;
349 if (!model.get('characteristic')) {
356 Sort by status, then order, then name
358 sort: function (a, b) {
359 var astatus = a.isNew(),
361 achar = a.get('characteristic'),
362 bchar = b.get('characteristic'),
363 aord = achar ? achar.get('order') : null,
364 bord = bchar ? bchar.get('order') : null,
367 if (astatus === bstatus) {
369 aname = achar ? achar.get('name') : null;
370 bname = bchar ? bchar.get('name') : null;
371 return aname < bname ? -1 : 1;
373 return aord < bord ? -1 : 1;
375 return astatus < bstatus ? -1 : 1;
378 @param {XM.Collection} value
380 setValue: function (value) {
382 this.value.off('add', this.lengthChanged, this);
383 this.value.off('statusChange', this.lengthChanged, this);
386 this.value.on('add', this.lengthChanged, this);
387 this.value.on('statusChange', this.lengthChanged, this);
388 this.value.comparator = this.sort;
390 this.lengthChanged();
394 Sets visibility of the widget label.
396 showLabelChanged: function () {
397 this.$.label.setShowing(this.getShowLabel());