[FIX] completely broken float formatting when leading 0
[odoo/odoo.git] / addons / web / static / src / js / formats.js
1
2 openerp.web.formats = function(openerp) {
3
4 /**
5  * Formats a single atomic value based on a field descriptor
6  *
7  * @param {Object} value read from OpenERP
8  * @param {Object} descriptor union of orm field and view field
9  * @param {Object} [descriptor.widget] widget to use to display the value
10  * @param {Object} descriptor.type fallback if no widget is provided, or if the provided widget is unknown
11  * @param {Object} [descriptor.digits] used for the formatting of floats
12  * @param {String} [value_if_empty=''] returned if the ``value`` argument is considered empty
13  */
14 openerp.web.format_value = function (value, descriptor, value_if_empty) {
15     // If NaN value, display as with a `false` (empty cell)
16     if (typeof value === 'number' && isNaN(value)) {
17         value = false;
18     }
19     switch (value) {
20         case false:
21         case Infinity:
22         case -Infinity:
23             return value_if_empty === undefined ?  '' : value_if_empty;
24     }
25     switch (descriptor.widget || descriptor.type) {
26         case 'integer':
27             return _.sprintf('%d', value);
28         case 'float':
29             var precision = descriptor.digits ? descriptor.digits[1] : 2;
30             var int_part = Math.floor(value);
31             var dec_part = _.sprintf(
32                     '%.' + precision + 'f',
33                     Math.abs(value) % 1).substring(2);
34             return _.sprintf('%d%s%s',
35                     int_part,
36                     openerp.web._t.database.parameters.decimal_point,
37                     dec_part);
38         case 'float_time':
39             return _.sprintf("%02d:%02d",
40                     Math.floor(value),
41                     Math.round((value % 1) * 60));
42         case 'progressbar':
43             return _.sprintf(
44                 '<progress value="%.2f" max="100.0">%.2f%%</progress>',
45                     value, value);
46         case 'many2one':
47             // name_get value format
48             return value[1];
49         case 'datetime':
50             if (typeof(value) == "string")
51                 value = openerp.web.auto_str_to_date(value);
52             try {
53                 return value.toString(_.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate,
54                     Date.CultureInfo.formatPatterns.longTime));
55             } catch (e) {
56                 return value.format("%m/%d/%Y %H:%M:%S");
57             }
58             return value;
59         case 'date':
60             if (typeof(value) == "string")
61                 value = openerp.web.auto_str_to_date(value);
62             try {
63                 return value.toString(Date.CultureInfo.formatPatterns.shortDate);
64             } catch (e) {
65                 return value.format("%m/%d/%Y");
66             }
67         case 'time':
68             if (typeof(value) == "string")
69                 value = openerp.web.auto_str_to_date(value);
70             try {
71                 return value.toString(Date.CultureInfo.formatPatterns.longTime);
72             } catch (e) {
73                 return value.format("%H:%M:%S");
74             }
75         case 'selection':
76             // Each choice is [value, label]
77             var result = _(descriptor.selection).detect(function (choice) {
78                 return choice[0] === value;
79             });
80             if (result) { return result[1]; }
81             return;
82         default:
83             return value;
84     }
85 };
86
87 openerp.web.parse_value = function (value, descriptor, value_if_empty) {
88     switch (value) {
89         case false:
90         case "":
91             return value_if_empty === undefined ?  false : value_if_empty;
92     }
93     switch (descriptor.widget || descriptor.type) {
94         case 'integer':
95             var tmp;
96             do {
97                 tmp = value;
98                 value = value.replace(openerp.web._t.database.parameters.thousands_sep, "");
99             } while(tmp !== value);
100             tmp = Number(value);
101             if (isNaN(tmp))
102                 throw value + " is not a correct integer";
103             return tmp;
104         case 'float':
105             var tmp = Number(value);
106             if (!isNaN(tmp))
107                 return tmp;
108             tmp = value.replace(openerp.web._t.database.parameters.decimal_point, ".");
109             var tmp2 = tmp;
110             do {
111                 tmp = tmp2;
112                 tmp2 = tmp.replace(openerp.web._t.database.parameters.thousands_sep, "");
113             } while(tmp !== tmp2);
114             tmp = Number(tmp);
115             if (isNaN(tmp))
116                 throw value + " is not a correct float";
117             return tmp;
118         case 'float_time':
119             var tmp = value.split(":");
120             if (tmp.length != 2)
121                 throw value + " is not a correct float_time";
122             var tmp1 = openerp.web.parse_value(tmp[0], {type: "integer"});
123             var tmp2 = openerp.web.parse_value(tmp[1], {type: "integer"});
124             return tmp1 + (tmp2 / 60);
125         case 'progressbar':
126             return openerp.web.parse_value(value, {type: "float"});
127         case 'datetime':
128             var tmp = Date.parseExact(value, _.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate,
129                     Date.CultureInfo.formatPatterns.longTime));
130             if (tmp !== null)
131                 return openerp.web.datetime_to_str(tmp);
132             tmp = Date.parse(value);
133             if (tmp !== null)
134                 return openerp.web.datetime_to_str(tmp);
135             throw value + " is not a valid datetime";
136         case 'date':
137             var tmp = Date.parseExact(value, Date.CultureInfo.formatPatterns.shortDate);
138             if (tmp !== null)
139                 return openerp.web.date_to_str(tmp);
140             tmp = Date.parse(value);
141             if (tmp !== null)
142                 return openerp.web.date_to_str(tmp);
143             throw value + " is not a valid date";
144         case 'time':
145             var tmp = Date.parseExact(value, Date.CultureInfo.formatPatterns.longTime);
146             if (tmp !== null)
147                 return openerp.web.time_to_str(tmp);
148             tmp = Date.parse(value);
149             if (tmp !== null)
150                 return openerp.web.time_to_str(tmp);
151             throw value + " is not a valid time";
152     }
153     return value;
154 };
155
156 openerp.web.auto_str_to_date = function(value, type) {
157     try {
158         return openerp.web.str_to_datetime(value);
159     } catch(e) {}
160     try {
161         return openerp.web.str_to_date(value);
162     } catch(e) {}
163     try {
164         return openerp.web.str_to_time(value);
165     } catch(e) {}
166     throw "'" + value + "' is not a valid date, datetime nor time"
167 };
168
169 openerp.web.auto_date_to_str = function(value, type) {
170     switch(type) {
171         case 'datetime':
172             return openerp.web.datetime_to_str(value);
173         case 'date':
174             return openerp.web.date_to_str(value);
175         case 'time':
176             return openerp.web.time_to_str(value);
177         default:
178             throw type + " is not convertible to date, datetime nor time"
179     }
180 };
181
182 /**
183  * Formats a provided cell based on its field type
184  *
185  * @param {Object} row_data record whose values should be displayed in the cell
186  * @param {Object} column column descriptor
187  * @param {"button"|"field"} column.tag base control type
188  * @param {String} column.type widget type for a field control
189  * @param {String} [column.string] button label
190  * @param {String} [column.icon] button icon
191  * @param {String} [value_if_empty=''] what to display if the field's value is ``false``
192  * @param {Boolean} [process_modifiers=true] should the modifiers be computed ?
193  */
194 openerp.web.format_cell = function (row_data, column, value_if_empty, process_modifiers) {
195     var attrs = {};
196     if (process_modifiers !== false) {
197         attrs = column.modifiers_for(row_data);
198     }
199     if (attrs.invisible) { return ''; }
200     if (column.tag === 'button') {
201         return [
202             '<button type="button" title="', column.string || '', '">',
203                 '<img src="/web/static/src/img/icons/', column.icon, '.png"',
204                     ' alt="', column.string || '', '"/>',
205             '</button>'
206         ].join('')
207     }
208
209     if (!row_data[column.id]) {
210         return value_if_empty === undefined ? '' : value_if_empty;
211     }
212     return openerp.web.format_value(
213             row_data[column.id].value, column, value_if_empty);
214 }
215     
216 };