From a10eae9cd6d3bbbb75045ba7a27336ee2301c5fb Mon Sep 17 00:00:00 2001 From: jojohoch <joachim.hoch@iqb.hu-berlin.de> Date: Thu, 27 Oct 2022 10:39:52 +0200 Subject: [PATCH] Implement dynamic rows for textarea based on expected number of chars --- docs/release-notes-editor.txt | 3 +++ docs/unit_definition_changelog.txt | 2 ++ .../input-elements/text-area.component.ts | 6 +++++- .../elements/input-elements/text-area.ts | 4 ++++ .../pipes/update-textarea-rows.pipe.spec.ts | 8 ++++++++ .../common/pipes/update-textarea-rows.pipe.ts | 19 +++++++++++++++++++ projects/common/shared.module.ts | 4 +++- .../element-model-properties.component.html | 15 ++++++++++++++- projects/editor/src/assets/i18n/de.json | 4 +++- 9 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 projects/common/pipes/update-textarea-rows.pipe.spec.ts create mode 100644 projects/common/pipes/update-textarea-rows.pipe.ts diff --git a/docs/release-notes-editor.txt b/docs/release-notes-editor.txt index e3c859fb3..afb2f7936 100644 --- a/docs/release-notes-editor.txt +++ b/docs/release-notes-editor.txt @@ -7,6 +7,9 @@ Editor Die Bereiche können als Ellipsen, Rechtecke und Dreiecke angelegt werden. Ihre Position, Größe, Drehung, Farbe und Rahmenbreite kann eingestellt werden. Das Element kann als Pflichtfeld ausgezeichnet werden. +- Ermöglicht für Eingabebereichen die dynamische Anpassung der Anzahl von Zeilen + Auf Grundlage der Angabe der erwarteten Zeichen für die Antwort des Users wird + für das gegebene Seitenformat die Anzahl der Zeilen berechnet. 1.34.0 - Implement GeoGebra applet element diff --git a/docs/unit_definition_changelog.txt b/docs/unit_definition_changelog.txt index e1191b805..0cd16e574 100644 --- a/docs/unit_definition_changelog.txt +++ b/docs/unit_definition_changelog.txt @@ -41,3 +41,5 @@ iqb-aspect-definition@1.0.0 3.8.0 - +HotspotImageElement +- Textarea: +hasDynamicRowCount: boolean; + +expectedCharactersCount: number; diff --git a/projects/common/components/input-elements/text-area.component.ts b/projects/common/components/input-elements/text-area.component.ts index 05670801d..f50ec9c48 100644 --- a/projects/common/components/input-elements/text-area.component.ts +++ b/projects/common/components/input-elements/text-area.component.ts @@ -26,8 +26,12 @@ import { FormElementComponent } from '../../directives/form-element-component.di autocapitalize="none" autocorrect="off" spellcheck="false" - rows="{{elementModel.rowCount}}" value="{{elementModel.value}}" + [rows]="elementModel.rowCount | updateTextareaRows : + elementModel.expectedCharactersCount : + elementModel.hasDynamicRowCount : + input.offsetWidth : + elementModel.styling.fontSize" [attr.inputmode]="elementModel.showSoftwareKeyboard ? 'none' : 'text'" [formControl]="elementFormControl" [readonly]="elementModel.readOnly" diff --git a/projects/common/models/elements/input-elements/text-area.ts b/projects/common/models/elements/input-elements/text-area.ts index 2c4505c84..aa7166cd4 100644 --- a/projects/common/models/elements/input-elements/text-area.ts +++ b/projects/common/models/elements/input-elements/text-area.ts @@ -12,7 +12,9 @@ import { TextAreaComponent } from 'common/components/input-elements/text-area.co export class TextAreaElement extends InputElement implements PositionedUIElement { appearance: 'fill' | 'outline' = 'outline'; resizeEnabled: boolean = false; + hasDynamicRowCount: boolean = false; rowCount: number = 3; + expectedCharactersCount: number = 300; inputAssistancePreset: InputAssistancePreset = null; inputAssistancePosition: 'floating' | 'right' = 'floating'; hasArrowKeys: boolean = false; @@ -30,6 +32,8 @@ export class TextAreaElement extends InputElement implements PositionedUIElement if (element.appearance) this.appearance = element.appearance; if (element.resizeEnabled) this.resizeEnabled = element.resizeEnabled; if (element.rowCount) this.rowCount = element.rowCount; + if (element.hasDynamicRowCount) this.hasDynamicRowCount = element.hasDynamicRowCount; + if (element.expectedCharactersCount) this.expectedCharactersCount = element.expectedCharactersCount; if (element.inputAssistancePreset) this.inputAssistancePreset = element.inputAssistancePreset; if (element.inputAssistancePosition) this.inputAssistancePosition = element.inputAssistancePosition; if (element.restrictedToInputAssistanceChars !== undefined) { diff --git a/projects/common/pipes/update-textarea-rows.pipe.spec.ts b/projects/common/pipes/update-textarea-rows.pipe.spec.ts new file mode 100644 index 000000000..0c99a0bbe --- /dev/null +++ b/projects/common/pipes/update-textarea-rows.pipe.spec.ts @@ -0,0 +1,8 @@ +import { UpdateTextareaRowsPipe } from './update-textarea-rows.pipe'; + +describe('UpdateRowsPipe', () => { + it('create an instance', () => { + const pipe = new UpdateTextareaRowsPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/projects/common/pipes/update-textarea-rows.pipe.ts b/projects/common/pipes/update-textarea-rows.pipe.ts new file mode 100644 index 000000000..24f6119a0 --- /dev/null +++ b/projects/common/pipes/update-textarea-rows.pipe.ts @@ -0,0 +1,19 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'updateTextareaRows' +}) +export class UpdateTextareaRowsPipe implements PipeTransform { + transform(staticRowCount: number, + expectedCharactersCount: number, + hasDynamicRowCount: boolean, + inputWidth: number, + fontSize: number + ): number { + if (hasDynamicRowCount && expectedCharactersCount && inputWidth) { + const averageCharWidth = fontSize / 2; // s. AverageCharWidth of dotNet + return (Math.ceil((expectedCharactersCount * averageCharWidth) / inputWidth)); + } + return staticRowCount; + } +} diff --git a/projects/common/shared.module.ts b/projects/common/shared.module.ts index 36c93011c..d17113c90 100644 --- a/projects/common/shared.module.ts +++ b/projects/common/shared.module.ts @@ -71,6 +71,7 @@ import { GeometryComponent } from './components/geometry/geometry.component'; import { MathAtanPipe } from './pipes/math-atan.pipe'; import { MathDegreesPipe } from './pipes/math-degrees.pipe'; import { ArrayIncludesPipe } from './pipes/array-includes.pipe'; +import { UpdateTextareaRowsPipe } from './pipes/update-textarea-rows.pipe'; @NgModule({ imports: [ @@ -132,7 +133,8 @@ import { ArrayIncludesPipe } from './pipes/array-includes.pipe'; GeometryComponent, MathAtanPipe, MathDegreesPipe, - ArrayIncludesPipe + ArrayIncludesPipe, + UpdateTextareaRowsPipe ], exports: [ CommonModule, diff --git a/projects/editor/src/app/components/properties-panel/model-properties-tab/element-model-properties.component.html b/projects/editor/src/app/components/properties-panel/model-properties-tab/element-model-properties.component.html index 1c3ca293c..8a1c6eff5 100644 --- a/projects/editor/src/app/components/properties-panel/model-properties-tab/element-model-properties.component.html +++ b/projects/editor/src/app/components/properties-panel/model-properties-tab/element-model-properties.component.html @@ -82,13 +82,26 @@ {{'propertiesPanel.resizeEnabled' | translate }} </mat-checkbox> - <mat-form-field *ngIf="combinedProperties.rowCount != null" + <mat-checkbox *ngIf="combinedProperties.hasDynamicRowCount !== undefined" + [checked]="$any(combinedProperties.hasDynamicRowCount)" + (change)="updateModel.emit({ property: 'hasDynamicRowCount', value: $event.checked })"> + {{'propertiesPanel.hasDynamicRowCount' | translate }} + </mat-checkbox> + + <mat-form-field *ngIf="combinedProperties.rowCount != null && combinedProperties.hasDynamicRowCount === false" appearance="fill" class="mdInput textsingleline"> <mat-label>{{'rows' | translate }}</mat-label> <input matInput type="number" [value]="$any(combinedProperties.rowCount)" (input)="updateModel.emit({ property: 'rowCount', value: $any($event.target).value })"> </mat-form-field> + <mat-form-field *ngIf="combinedProperties.expectedCharactersCount != null && combinedProperties.hasDynamicRowCount" + appearance="fill" class="mdInput textsingleline"> + <mat-label>{{'propertiesPanel.expectedCharactersCount' | translate }}</mat-label> + <input matInput type="number" [value]="$any(combinedProperties.expectedCharactersCount)" + (input)="updateModel.emit({ property: 'expectedCharactersCount', value: $any($event.target).value })"> + </mat-form-field> + <aspect-button-properties [combinedProperties]="combinedProperties" (updateModel)="updateModel.emit($event)"> </aspect-button-properties> diff --git a/projects/editor/src/assets/i18n/de.json b/projects/editor/src/assets/i18n/de.json index d68588678..43bc4abb1 100644 --- a/projects/editor/src/assets/i18n/de.json +++ b/projects/editor/src/assets/i18n/de.json @@ -179,7 +179,9 @@ "customToolBar": "Anpassung Werkzeugleiste", "customToolbarHelp": "Hier kann definiert werden, welche Elemente auf der Werkzeigleiste angezeigt werden sollen. Für Details bitte die Dokumentation konsultieren.", "hotspots": "Aktive Bereiche", - "newHotspot": "Neuer Bereich" + "newHotspot": "Neuer Bereich", + "hasDynamicRowCount": "Dynamische Zeilen", + "expectedCharactersCount": "Erwartete Zeichenanzahl" }, "hotspot": { "top": "Abstand von oben", -- GitLab