diff --git a/src/app/components/field-set/field-set.component.html b/src/app/components/field-set/field-set.component.html index b87bbe724705e0503c85490c8e4cbdabb19188d8..0dea7034b85852407812e4aea01b96e592239fc6 100644 --- a/src/app/components/field-set/field-set.component.html +++ b/src/app/components/field-set/field-set.component.html @@ -20,7 +20,8 @@ <mat-card-content> <ng-template ngFor let-p [ngForOf]="fields"> - <param-field-line *ngIf="isInputField(p)" [param]=p (radio)=onRadioClick($event) (valid)=onParamLineValid() (inputChange)=onInputChange()> + <param-field-line *ngIf="isInputField(p)" [param]=p (radio)=onRadioClick($event) (valid)=onParamLineValid() + (inputChange)=onInputChange() (tabPressed)="onTabPressed($event)"> </param-field-line> <select-field-line *ngIf="isSelectField(p)" [_select]=p> diff --git a/src/app/components/field-set/field-set.component.ts b/src/app/components/field-set/field-set.component.ts index 1541cba64a890778294eeaa5309ece21a2204796..bb3c51de86b46f5a931fee54cf659e553c1b8fa4 100644 --- a/src/app/components/field-set/field-set.component.ts +++ b/src/app/components/field-set/field-set.component.ts @@ -117,6 +117,10 @@ export class FieldSetComponent implements DoCheck { @Output() private radio = new EventEmitter<any>(); + /** événement signalant un appui sur TAB ou SHIFT+TAB */ + @Output() + protected tabPressed = new EventEmitter<any>(); + private hasRadioFix(): boolean { if (this._fieldSet.hasInputs) { switch (this._fieldSet.getInput(0).radioConfig) { @@ -209,6 +213,13 @@ export class FieldSetComponent implements DoCheck { this.validChange.emit(); } + /** + * Renvoie l'événement au composant du dessus + */ + public onTabPressed(event) { + this.tabPressed.emit(event); + } + public ngDoCheck() { this.updateValidity(); } diff --git a/src/app/components/fieldset-container/fieldset-container.component.html b/src/app/components/fieldset-container/fieldset-container.component.html index 3bb2f5d4c370f52dd13b9ceabe74bea170bf0fe8..c2f75e4f19ef29b671ec12f24afabd08b67f648b 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.html +++ b/src/app/components/fieldset-container/fieldset-container.component.html @@ -8,6 +8,7 @@ <field-set *ngFor="let fs of fieldsets" class="fieldset-inner" [fieldSet]=fs (radio)=onRadioClick($event) (validChange)=onFieldsetValid() (inputChange)=onInputChange() (addFieldset)=onAddFieldset($event) (removeFieldset)=onRemoveFieldset($event) - (moveFieldsetDown)=onMoveFieldsetDown($event) (moveFieldsetUp)=onMoveFieldsetUp($event)> + (moveFieldsetDown)=onMoveFieldsetDown($event) (moveFieldsetUp)=onMoveFieldsetUp($event) + (tabPressed)="onTabPressed($event)"> </field-set> </mat-card-content> diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts index 15ca4d3e33a0c30d819d8b731ed32d8d20ffec51..b5e7be12e51d7e97caa1ee80e71024378c4e9522 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.ts +++ b/src/app/components/fieldset-container/fieldset-container.component.ts @@ -60,6 +60,10 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { @Output() private inputChange = new EventEmitter(); + /** événement signalant un appui sur TAB ou SHIFT+TAB */ + @Output() + protected tabPressed = new EventEmitter<any>(); + private addStructure(after?: FieldSet) { if (after) { this._container.addFromTemplate(0, after.indexAsKid()); @@ -204,4 +208,11 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { const form = this._container.parent as FormulaireDefinition; form.moveFieldsetDown(fs); } + + /** + * Renvoie l'événement au composant du dessus + */ + public onTabPressed(event) { + this.tabPressed.emit(event); + } } diff --git a/src/app/components/generic-calculator/calculator.component.html b/src/app/components/generic-calculator/calculator.component.html index a714e0be4ec9b5bac39a194d92fbecfded9932f2..27eb0116b79bdf0a9ae47fa11d3623aa758914f1 100644 --- a/src/app/components/generic-calculator/calculator.component.html +++ b/src/app/components/generic-calculator/calculator.component.html @@ -32,10 +32,14 @@ <!-- chapitres --> <mat-card id="calc-card-field-sets" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px"> <ng-template ngFor let-fe [ngForOf]="formElements"> - <field-set *ngIf="isFieldset(fe)" [style.display]="getFieldsetStyleDisplay(fe.id)" [fieldSet]=fe (radio)=onRadioClick($event) - (validChange)=OnFieldsetValid() (inputChange)=onInputChange()></field-set> + <field-set *ngIf="isFieldset(fe)" [style.display]="getFieldsetStyleDisplay(fe.id)" [fieldSet]=fe + (radio)=onRadioClick($event) (validChange)=OnFieldsetValid() (inputChange)=onInputChange() + (tabPressed)="onTabPressed($event)"> + </field-set> - <fieldset-container *ngIf="isFieldsetContainer(fe)" [_container]=fe (radio)=onRadioClick($event) (validChange)=onFieldsetContainerValid()></fieldset-container> + <fieldset-container *ngIf="isFieldsetContainer(fe)" [_container]=fe (radio)=onRadioClick($event) + (validChange)=onFieldsetContainerValid() (tabPressed)="onTabPressed($event)"> + </fieldset-container> </ng-template> <mat-card-actions> diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 31842b9690c9e477dfd037eebcbe24686421144d..d7a267bb7d34f8fc668b9263a7cfd371eccb717a 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked } from "@angular/core"; +import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked, ElementRef, Renderer2 } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { Observer, Session, ParamValueMode } from "jalhyd"; @@ -98,7 +98,9 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, constructor( private route: ActivatedRoute, private router: Router, - private confirmCloseCalcDialog: MatDialog + private confirmCloseCalcDialog: MatDialog, + private _elementRef: ElementRef, + private renderer: Renderer2 ) { super(); this.intlService = ServiceFactory.instance.i18nService; @@ -308,7 +310,11 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, // accumulator (valeur précédente du résultat) acc, // currentValue (élément courant dans le tableau) - fieldset + fieldset, + // currentIndex (indice courant dans le tableau) + currIndex, + // array (tableau parcouru) + array ) => { return acc && fieldset.isValid; } @@ -322,7 +328,11 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, // accumulator (valeur précédente du résultat) acc, // currentValue (élément courant dans le tableau) - fieldsetContainer + fieldsetContainer, + // currentIndex (indice courant dans le tableau) + currIndex, + // array (tableau parcouru) + array ) => { return acc && fieldsetContainer.isValid; } @@ -357,6 +367,43 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, this._formulaire.resetResults([]); } + /** + * Passe d'un champ de saisie à l'autre lors de l'appui sur + * TAB, sans passer par les autres éléments d'interface + */ + public onTabPressed(event: any) { + // event source input id + const srcId = event.originalEvent.target.id; + + // find all available inputs + const qs = "ngparam-input input.form-control"; + let inputs: Node[] = Array.from(this._elementRef.nativeElement.querySelectorAll(qs)); + + // find calculated symbol if any, to exclude it from inputs list + let calcSymbol = ""; + if (this._formulaire.currentNub.calculatedParam) { + calcSymbol = this._formulaire.currentNub.calculatedParam.symbol; + } + inputs = inputs.filter((i: any) => { + return i.id !== calcSymbol; + }); + + // find position among inputs list + const currentIndex = inputs.findIndex((i: any) => { + return i.id === srcId; + }); + + // focus previous / next input + let newIndex = currentIndex; + if (event.shift) { + newIndex = (newIndex === 0) ? (inputs.length - 1) : (newIndex - 1); + } else { + newIndex = (newIndex + 1) % inputs.length; + } + const elt = (inputs[newIndex] as HTMLElement); + elt.focus(); + } + public openHelp() { window.open("assets/docs-fr/calculators/" + this._formulaire.helpLink + "/", "_blank"); } diff --git a/src/app/components/generic-input/generic-input.component.html b/src/app/components/generic-input/generic-input.component.html index f6ca6506f4d99ffcef937546366fca94cbcf63eb..c60194a79e28b460780eace9cbca97dc9caf8311 100644 --- a/src/app/components/generic-input/generic-input.component.html +++ b/src/app/components/generic-input/generic-input.component.html @@ -1,6 +1,7 @@ <mat-form-field> <input matInput #inputControl="ngModel" class="form-control" type="text" inputmode="numeric" [id]="inputId" [name]="inputId" [disabled]="isDisabled" [(ngModel)]="uiValue" [placeholder]="title" + (keydown.Tab)="onTabPressed($event, false)" (keydown.shift.Tab)="onTabPressed($event, true)" pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$" required> <mat-error>{{ errorMessage }}</mat-error> diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts index 1bac270188ab49a87be7951a421abad277d45947..0b8b3f09bcd90f653c1cfb983d1146c6f728e019 100644 --- a/src/app/components/generic-input/generic-input.component.ts +++ b/src/app/components/generic-input/generic-input.component.ts @@ -59,6 +59,12 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC @Output() protected change = new EventEmitter<any>(); + /** + * événement signalant un appui sur TAB ou SHIFT+TAB + */ + @Output() + protected tabPressed = new EventEmitter<any>(); + /** * valeur saisie. * Cette variable n'est modifiée que lorsqu'on affecte le modèle ou que l'utilisateur fait une saisie @@ -231,6 +237,14 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC } } + /** + * Renvoie l'événement au composant du dessus + */ + public onTabPressed(event, shift: boolean) { + this.tabPressed.emit({ originalEvent: event, shift: shift }); + return false; // stops event propagation + } + private updateAll() { this.updateAndValidateUI(); this.validateModel(); diff --git a/src/app/components/param-field-line/param-field-line.component.html b/src/app/components/param-field-line/param-field-line.component.html index acea333d21ba24a32813148e8aa38eb7147670f6..1c71eb5b957985b949b08b7862ed29578c6bb4e1 100644 --- a/src/app/components/param-field-line/param-field-line.component.html +++ b/src/app/components/param-field-line/param-field-line.component.html @@ -4,7 +4,8 @@ <!-- input de saisie de la valeur --> <div fxFlex="1 0 120px"> <!-- composant pour gérer le cas général (valeur numérique à saisir) --> - <ngparam-input [title]="param.title" [hidden]="! isRadioFixChecked" (change)="onInputChange($event)"></ngparam-input> + <ngparam-input [title]="param.title" [hidden]="! isRadioFixChecked" + (change)="onInputChange($event)" (tabPressed)="onTabPressed($event)"></ngparam-input> <!-- composant pour gérer le cas "paramètre calculé" --> <param-computed *ngIf="isRadioCalChecked" [title]="title" [param]="param"></param-computed> diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts index 06a78419f964544919d962f0dbe3c70903509b9d..59b38594abab5f9dd8da14bad4eef6d6afb0689e 100644 --- a/src/app/components/param-field-line/param-field-line.component.ts +++ b/src/app/components/param-field-line/param-field-line.component.ts @@ -127,6 +127,10 @@ export class ParamFieldLineComponent implements OnChanges { @Output() private inputChange: EventEmitter<void>; + /** événement signalant un appui sur TAB ou SHIFT+TAB */ + @Output() + protected tabPressed = new EventEmitter<any>(); + /** true si la valeur saisie est valide */ private _isInputValid = false; @@ -266,6 +270,13 @@ export class ParamFieldLineComponent implements OnChanges { this.emitValidity(); } + /** + * Renvoie l'événement au composant du dessus + */ + public onTabPressed(event) { + this.tabPressed.emit(event); + } + /** * émission d'un événement de validité */