Merge pull request #9607 from tchak/fix-decimal-number-input
fix(dossier): remove extra input event on page load
This commit is contained in:
commit
c72c7bc957
4 changed files with 57 additions and 49 deletions
|
@ -1 +1 @@
|
|||
= @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, required: @champ.required?, pattern: "-?[0-9]+([\.,][0-9]{1,3})?", inputmode: :decimal, data: { controller: 'format decimal-number-input', format: :decimal }))
|
||||
= @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, required: @champ.required?, pattern: "-?[0-9]+([\.,][0-9]{1,3})?", inputmode: :decimal, data: { controller: 'format', format: :decimal }))
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
import { ApplicationController } from './application_controller';
|
||||
|
||||
export class DecimalNumberInputController extends ApplicationController {
|
||||
connect() {
|
||||
const value = this.inputElement.value;
|
||||
|
||||
if (value) {
|
||||
this.formatValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
formatValue(value: string) {
|
||||
const number = parseFloat(value);
|
||||
|
||||
if (isNaN(number)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.inputElement.value = number.toLocaleString();
|
||||
this.emitInputEvent(); // trigger format controller
|
||||
}
|
||||
|
||||
private get inputElement(): HTMLInputElement {
|
||||
return this.element as HTMLInputElement;
|
||||
}
|
||||
|
||||
private emitInputEvent() {
|
||||
const event = new InputEvent('input', {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
|
||||
this.inputElement.dispatchEvent(event);
|
||||
}
|
||||
}
|
|
@ -7,25 +7,29 @@ export class FormatController extends ApplicationController {
|
|||
case 'list':
|
||||
this.on('change', (event) => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
target.value = this.formatList(target.value);
|
||||
const value = this.formatList(target.value);
|
||||
replaceValue(target, value);
|
||||
});
|
||||
break;
|
||||
case 'iban':
|
||||
this.on('input', (event) => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
target.value = this.formatIBAN(target.value);
|
||||
const value = this.formatIBAN(target.value);
|
||||
replaceValue(target, value);
|
||||
});
|
||||
break;
|
||||
case 'integer':
|
||||
this.on('input', (event) => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
target.value = this.formatInteger(target.value);
|
||||
const value = this.formatInteger(target.value);
|
||||
replaceValue(target, value);
|
||||
});
|
||||
break;
|
||||
case 'decimal':
|
||||
this.on('input', (event) => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
target.value = this.formatDecimal(target.value);
|
||||
const value = this.formatDecimal(target.value);
|
||||
replaceValue(target, value);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -48,12 +52,34 @@ export class FormatController extends ApplicationController {
|
|||
}
|
||||
|
||||
private formatDecimal(value: string) {
|
||||
// Le séparateur de décimales est toujours après le séparateur de milliers (un point ou une virgule).
|
||||
// S'il n'y a qu'un seul séparateur, on considère que c'est celui des décimales.
|
||||
// S'il n'y en a pas, ça n'a pas d'effet.
|
||||
const decimalSeparator =
|
||||
value.lastIndexOf(',') > value.lastIndexOf('.') ? ',' : '.';
|
||||
|
||||
return value.replace(new RegExp(`[^-?\\d${decimalSeparator}]`, 'g'), '');
|
||||
const decimalSeparator = getDecimalSeparator(value);
|
||||
const number =
|
||||
decimalSeparator == ','
|
||||
? value.replace(/\./g, '').replace(/,/g, '.')
|
||||
: value.replace(/,/g, '');
|
||||
return number.replace(new RegExp(`[^-?\\d.]`, 'g'), '');
|
||||
}
|
||||
}
|
||||
|
||||
function replaceValue(target: HTMLInputElement, value: string) {
|
||||
const delta = target.value.length - value.length;
|
||||
const start = target.selectionStart;
|
||||
const end = target.selectionStart;
|
||||
const dir = target.selectionDirection;
|
||||
target.value = value;
|
||||
target.selectionStart = start ? start - delta : 0;
|
||||
target.selectionEnd = end ? end - delta : 0;
|
||||
target.selectionDirection = dir;
|
||||
}
|
||||
|
||||
function getDecimalSeparator(value: string) {
|
||||
if (value.indexOf('.') != -1 && value.indexOf(',') != -1) {
|
||||
if (value.lastIndexOf('.') < value.lastIndexOf(',')) {
|
||||
return ',';
|
||||
}
|
||||
return '.';
|
||||
} else if (value.indexOf(',') != -1) {
|
||||
return ',';
|
||||
}
|
||||
return (1.1).toLocaleString().indexOf('.') != -1 ? '.' : ',';
|
||||
}
|
||||
|
|
|
@ -195,15 +195,20 @@ describe 'The user' do
|
|||
champ_value_for('nombre décimal') == '123456.78'
|
||||
}
|
||||
|
||||
fill_in('nombre décimal', with: '1,234.56')
|
||||
champ_past_value_for('nombre décimal', '1,234.56')
|
||||
wait_until {
|
||||
champ_value_for('nombre décimal') == '1234.56'
|
||||
}
|
||||
|
||||
fill_in('nombre décimal', with: '-1,234.56')
|
||||
champ_past_value_for('nombre décimal', '-1,234.56')
|
||||
wait_until {
|
||||
champ_value_for('nombre décimal') == '-1234.56'
|
||||
}
|
||||
|
||||
champ_past_value_for('nombre décimal', '1.234,56')
|
||||
wait_until {
|
||||
champ_value_for('nombre décimal') == '1234.56'
|
||||
}
|
||||
end
|
||||
|
||||
scenario 'extends dossier experation date more than one time, ', js: true, retry: 3 do
|
||||
|
@ -584,6 +589,18 @@ describe 'The user' do
|
|||
champ_for(libelle).value
|
||||
end
|
||||
|
||||
def champ_id_for(libelle)
|
||||
champ_for(libelle).input_id
|
||||
end
|
||||
|
||||
def champ_past_value_for(libelle, value)
|
||||
execute_script("{
|
||||
let target = document.querySelector('##{champ_id_for(libelle)}');
|
||||
target.value = \"#{value}\";
|
||||
target.dispatchEvent(new CustomEvent('input', { bubbles: true }));
|
||||
}")
|
||||
end
|
||||
|
||||
def champ_for(libelle)
|
||||
champs = user_dossier.reload.champs_public
|
||||
champs.find { |c| c.libelle == libelle }
|
||||
|
|
Loading…
Reference in a new issue