erp5_web_renderjs_ui: float field: handle all ERP5 input types
Showing
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*global window, rJS, Math */ | ||
/*global window, rJS, Math, parseFloat, isNaN */ | ||
/*jslint indent: 2, maxerr: 3 */ | ||
(function (window, rJS, Math) { | ||
(function (window, rJS, Math, parseFloat, isNaN) { | ||
"use strict"; | ||
var separator_re = /\d([\., \-_])?\d\d\d/, | ||
input_format_re = /(-?)(\d+)(\.\d+)?/; | ||
var HTML5_INPUT_STYLE = "-1234.5", | ||
SPACE_INPUT_STYLE = "-1 234.5", | ||
SPACE_COMMA_INPUT_STYLE = "-1 234,5", | ||
DOT_COMMA_INPUT_STYLE = "-1.234,5", | ||
COMMA_DOT_INPUT_STYLE = "-1,234.5", | ||
PERCENT_INPUT_STYLE = "-12.3%"; | ||
/** Slice any slice-able parameter into triplets **/ | ||
function toTriplets(sliceable) { | ||
var parts = [], | ||
i = sliceable.length; | ||
for (i = sliceable.length; i > 3; i -= 3) { | ||
parts.unshift(sliceable.slice(i - 3, i)); | ||
function setCharAt(str, index, chr) { | ||
return str.substring(0, index) + chr + str.substring(index + 1); | ||
} | ||
function getSeparatorDict(input_style) { | ||
if (input_style === SPACE_INPUT_STYLE) { | ||
return {thousand: ' ', decimal: '.'}; | ||
} | ||
if (input_style === SPACE_COMMA_INPUT_STYLE) { | ||
return {thousand: ' ', decimal: ','}; | ||
} | ||
if (input_style === DOT_COMMA_INPUT_STYLE) { | ||
return {thousand: '.', decimal: ','}; | ||
} | ||
if (input_style === COMMA_DOT_INPUT_STYLE) { | ||
return {thousand: ',', decimal: '.'}; | ||
} | ||
throw new Error('No supported input style: ' + input_style); | ||
} | ||
function convertFloatToHTML5Input(precision, input_style, float) { | ||
// ERP5 always devides the value by 100 if it is set to percentages | ||
// thus we have to mitigate that in javascript here | ||
if (input_style === PERCENT_INPUT_STYLE) { | ||
float *= 100.0; | ||
} | ||
if (!isNaN(precision)) { | ||
float = float.toFixed(precision); | ||
} | ||
return float.toString(); | ||
} | ||
function convertERP5InputToHTML5Input(input_style, text) { | ||
// Convert ERP5 input style to html5 float text | ||
if (input_style === HTML5_INPUT_STYLE) { | ||
return text; | ||
} | ||
if (input_style === PERCENT_INPUT_STYLE) { | ||
if (text[text.length - 1] !== '%') { | ||
|
||
throw new Error('Can not parse: ' + text); | ||
} | ||
return text.substring(0, text.length - 1); | ||
} | ||
var separator_dict = getSeparatorDict(input_style), | ||
decimal_index = text.indexOf(separator_dict.decimal), | ||
original_text = text, | ||
i; | ||
if (decimal_index !== -1) { | ||
text = setCharAt(text, decimal_index, '.'); | ||
i = decimal_index; | ||
} else { | ||
i = text.length; | ||
} | ||
i = i - 4; | ||
// Remove thousand separator | ||
while (i > 0) { | ||
if (text[i] !== separator_dict.thousand) { | ||
throw new Error('Can not parse: ' + original_text); | ||
} | ||
text = text.substring(0, i) + text.substring(i + 1); | ||
i -= 4; | ||
} | ||
return text; | ||
} | ||
function convertHTML5InputToERP5Input(input_style, text) { | ||
if (input_style === HTML5_INPUT_STYLE) { | ||
return text; | ||
} | ||
if (input_style === PERCENT_INPUT_STYLE) { | ||
return text + '%'; | ||
|
||
} | ||
var separator_dict = getSeparatorDict(input_style), | ||
decimal_index = text.indexOf('.'), | ||
i; | ||
if (decimal_index !== -1) { | ||
text = setCharAt(text, decimal_index, separator_dict.decimal); | ||
i = decimal_index; | ||
} else { | ||
i = text.length; | ||
} | ||
i = i - 3; | ||
// Add thousand separator | ||
while (i > 0) { | ||
text = text.substring(0, i) + separator_dict.thousand + text.substring(i); | ||
i -= 3; | ||
} | ||
parts.unshift(sliceable.slice(0, i)); | ||
return parts; | ||
return text; | ||
} | ||
rJS(window) | ||
... | ... | @@ -24,9 +114,10 @@ |
}) | ||
.declareMethod('render', function (options) { | ||
var field_json = options.field_json || {}, | ||
input_style = (field_json.input_style || ""), | ||
percentage = input_style.endsWith("%"), | ||
thousand_sep = separator_re.test(input_style) ? (separator_re.exec(input_style)[1] || "") : "", | ||
input_style = (field_json.input_style || HTML5_INPUT_STYLE), | ||
value = field_json.default, | ||
text_content, | ||
precision = parseFloat(field_json.precision), | ||
state_dict = { | ||
editable: field_json.editable, | ||
required: field_json.required, | ||
... | ... | @@ -34,11 +125,8 @@ |
id: field_json.key, | ||
name: field_json.key, | ||
title: field_json.description, | ||
precision: window.parseFloat(field_json.precision), | ||
// precision: window.parseFloat(field_json.precision), | ||
error_text: field_json.error_text, | ||
// erp5 always put value into "default" (never "value") | ||
value: window.parseFloat(field_json.default), | ||
text_content: '', | ||
// `step` is used for browser-level validation thus a mandatory value | ||
// if unspecified we can use "any" value | ||
step: "any", | ||
... | ... | @@ -47,31 +135,32 @@ |
// Force calling subfield render | ||
// as user may have modified the input value | ||
render_timestamp: new Date().getTime() | ||
}, | ||
tmp; | ||
if (percentage) { | ||
// ERP5 always devides the value by 100 if it is set to percentages | ||
// thus we have to mitigate that in javascript here | ||
// (field_json.default type is number, only when it is initially loaded) | ||
if (typeof(field_json.default) == 'number') { | ||
state_dict.value *= 100.0; | ||
} | ||
state_dict.append = "%"; | ||
}; | ||
if (typeof value === 'number') { | ||
value = convertFloatToHTML5Input(precision, input_style, value); | ||
text_content = convertHTML5InputToERP5Input(input_style, value); | ||
} else if (value === null) { | ||
text_content = ''; | ||
value = undefined; | ||
} else { | ||
text_content = value; | ||
value = convertERP5InputToHTML5Input(input_style, value); | ||
} | ||
if (!window.isNaN(state_dict.precision)) { | ||
state_dict.step = Math.pow(10, -state_dict.precision).toFixed(state_dict.precision); | ||
state_dict.value = state_dict.value.toFixed(state_dict.precision); | ||
state_dict.value = value; | ||
state_dict.text_content = text_content; | ||
state_dict.input_style = input_style; | ||
if ((input_style === PERCENT_INPUT_STYLE) && state_dict.editable) { | ||
// Display the % next to the input field | ||
state_dict.append = "%"; | ||
} | ||
if (!window.isNaN(state_dict.value)) { | ||
state_dict.text_content = state_dict.value.toString(); | ||
if (state_dict.text_content !== "" && thousand_sep !== "") { | ||
tmp = input_format_re.exec(state_dict.text_content); | ||
// tmp == [full-number, sign, integer-part, .decimal-part (can be undefined because of permissive regexp), ...] | ||
state_dict.text_content = tmp[1] + toTriplets(tmp[2]).join(thousand_sep) + (tmp[3] || ""); | ||
tmp = undefined; | ||
} | ||
if (!isNaN(precision)) { | ||
state_dict.step = Math.pow(10, -precision) | ||
.toFixed(precision); | ||
} | ||
return this.changeState(state_dict); | ||
}) | ||
... | ... | @@ -106,10 +195,19 @@ |
}) | ||
.declareMethod('getContent', function () { | ||
var gadget = this; | ||
if (this.state.editable) { | ||
return this.getDeclaredGadget('sub') | ||
.push(function (gadget) { | ||
return gadget.getContent(); | ||
.push(function (sub_gadget) { | ||
return sub_gadget.getContent(); | ||
}) | ||
.push(function (result) { | ||
result[gadget.state.name] = | ||
convertHTML5InputToERP5Input( | ||
gadget.state.input_style, | ||
result[gadget.state.name] | ||
); | ||
return result; | ||
}); | ||
} | ||
return {}; | ||
... | ... | @@ -125,4 +223,4 @@ |
return true; | ||
}, {mutex: 'changestate'}); | ||
}(window, rJS, Math)); | ||
\ No newline at end of file | ||
}(window, rJS, Math, parseFloat, isNaN)); | ||
\ No newline at end of file |