1 /*jshint node:true, indent:2, curly:true, eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
2 regexp:true, undef:true, trailing:true, white:true */
3 /*global XT:true, XV:true, XM:true, Globalize:true, enyo:true, _:true */
8 The widget is created with an attr value that is an object composed of two key-values pairs.
9 These pairs include the amount (localValue or baseValue) and the currency attribute strings from the model.
10 The workspace replaces the attribute name string value
11 The localValue key should be used if the model stores the local currency and the baseValue key should
12 be used if the models stores the base currency.
13 The effective attribute should contain the date by which calculations
16 name: "XV.MoneyWidget",
17 kind: "XV.NumberWidget",
18 classes: "xv-moneywidget",
20 scale: XT.MONEY_SCALE,
21 localValue: null, // {Number} the number in the user field
22 baseValue: null, // {Number} the amount in the base currency
25 currencyDisabled: false,
26 currencyShowing: true,
29 isEditableProperty: "localValue" // The property mapped to an attribute that checks whether editbale
32 onValueChange: "pickerChanged" // intercept picker events
36 {controlClasses: 'enyo-inline', components: [
37 {name: "label", content: "", classes: "xv-label"},
38 {kind: "onyx.InputDecorator", components: [
39 {name: "input", kind: "onyx.Input",
40 onchange: "inputChanged", onkeydown: "keyDown"}
42 {name: "picker", kind: "XV.CurrencyPicker", classes: "xv-currency-picker", showLabel: false}
44 {controlClasses: 'enyo-inline', name: "basePanel", showing: false, components: [
45 {classes: "xv-label"},
46 {kind: "onyx.InputDecorator", components: [
47 {name: "baseAmountLabel", classes: "xv-label"}
49 {classes: "xv-currency-picker", components: [
50 {kind: 'onyx.InputDecorator', components: [
51 {name: 'baseCurrencyLabel'}
57 Set the base price into the base amount label
59 baseValueChanged: function () {
60 var localMode = this.getLocalMode(),
65 baseValue = this.getBaseValue();
66 scale = this.getScale();
67 content = baseValue || baseValue === 0 ?
68 Globalize.format(baseValue, "n" + scale) : "";
69 this.$.baseAmountLabel.setContent(content);
76 If the effective date is provided, the fixedRate is set and the
80 this.inherited(arguments);
82 var baseCurrency = XT.baseCurrency();
84 this.bubble("onNotify", {message: "_baseCurrencyMustBeSet".loc()});
87 this.setEffective(new Date());
88 this.setCurrency(baseCurrency);
89 this.setLocalValue(0);
90 this.$.baseCurrencyLabel.setContent(baseCurrency.get('abbreviation'));
92 // the currency picker may be disabled or hidden on creation in certain situations
93 this.currencyDisabledChanged();
94 this.currencyShowingChanged();
96 // this is for styling of the picker since the PickerWidget has a built in
98 this.$.picker.$.inputWrapper.removeClass("onyx-input-decorator");
100 // set the "mode" of this widget, whether or not it directly saves the local
101 // value to the model, or if it converts it to and from the base value.
102 this.setLocalMode(_.has(this.getAttr(), "localValue"));
105 clear: function (options) {
106 this.setValue({localValue: null}, options);
109 currencyChanged: function () {
110 this.$.picker.setValue(this.getCurrency(), {silent: true});
114 currencyDisabledChanged: function () {
115 this.$.picker.setDisabled(this.getCurrencyDisabled());
118 currencyShowingChanged: function () {
119 this.$.picker.setShowing(this.getCurrencyShowing());
123 This setDisabled function is all or nothing for both widgets
126 disabledChanged: function () {
127 var disabled = this.getDisabled(),
128 currencyDisabled = this.getCurrencyDisabled();
129 this.$.input.setDisabled(disabled);
130 this.$.picker.setDisabled(disabled || currencyDisabled);
131 this.$.label.addRemoveClass("disabled", this.getDisabled());
135 @todo Document the labelChanged method.
137 labelChanged: function () {
138 var attr = this.getAttr(),
139 valueAttr = attr.localValue || attr.baseValue;
140 var label = (this.getLabel() || ("_" + valueAttr || "").loc());
141 this.$.label.setContent(label + ":");
144 effectiveChanged: function () {
148 localValueChanged: function () {
149 this.valueChanged(this.getLocalValue()); // forward to XV.Number default for formatting
153 recalculate: function () {
154 var localMode = this.getLocalMode(),
155 value = localMode ? this.getLocalValue() : this.getBaseValue(),
156 request = localMode ? "toBase" : "fromBase",
157 setter = localMode ? "setBaseValue" : "setLocalValue",
158 currency = this.getCurrency(),
159 effective = this.getEffective(),
160 showing = localMode && _.isDate(effective) && currency &&
161 !currency.get("isBase"),
166 if (!currency || !effective) { return; }
168 // Keep track of requests, we'll ignore stale ones
169 this._counter = _.isNumber(this._counter) ? this._counter + 1 : 0;
172 if (_.isNumber(value)) {
173 if (currency.get("isBase")) {
174 // we're at base, so just set the fields with the base value we have
177 options.success = function (calcValue) {
178 // I only smell freshness
179 if (i < that._counter) { return; }
180 that[setter](calcValue);
182 currency[request](value, effective, options);
184 } else { // amount is null
188 this.$.basePanel.setShowing(showing);
191 setDisabled: function (isDisabled) {
192 this.inherited(arguments);
193 this.$.picker.setDisabled(isDisabled || this.getCurrencyDisabled());
197 This setValue function handles a value which is an
198 object potentially consisting of multiple key/value pairs for the
199 amount and currency controls.
201 @param {Object} Value
202 @param {Object} [value.currency] Currency
203 @param {Date} [value.effective] Effective date
204 @param {Number} [value.localValue] Local value
205 @param {Number} [value.baseValue] Base value
207 setValue: function (value, options) {
208 options = options || {};
209 var attr = this.getAttr(),
211 keys = _.keys(value),
216 // Loop through the properties and update calling
217 // appropriate "set" functions and add to "changed"
218 // object if applicable
219 for (i = 0; i < keys.length; i++) {
221 set = 'set' + key.slice(0, 1).toUpperCase() + key.slice(1);
222 this[set](value[key]);
224 changed[attr[key]] = value[key];
228 // Bubble changes if applicable
229 if (!_.isEmpty(changed) && !options.silent) {
230 this.doValueChange({value: changed});
234 inputChanged: function (inSender, inEvent) {
235 var input = this.$.input.getValue(),
236 value = this.validate(input),
237 prop = this.getLocalMode() ? 'localValue' : 'baseValue',
239 if (value !== false) {
247 this.valueChanged("");
252 Intercept the valueChanged event from picker.
254 pickerChanged: function (inSender, inEvent) {
256 if (inEvent.originator.name === "picker") {
257 value = XM.currencies.get(inEvent.value);
258 this.setValue({currency: value});