From ba78c8948258de775c97e767e652a2e5348913fa Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 20 Nov 2019 11:37:30 -0500 Subject: [PATCH] LPXXX initial keyboard handling Signed-off-by: Bill Erickson --- .../marc-edit/editable-content.component.html | 2 + .../share/marc-edit/editable-content.component.ts | 74 +++++++++++++--- .../app/staff/share/marc-edit/editor-context.ts | 9 ++ .../src/app/staff/share/marc-edit/marcrecord.ts | 30 ++++++- .../share/marc-edit/rich-editor.component.html | 98 +++++++++++++++++----- .../staff/share/marc-edit/rich-editor.component.ts | 1 - 6 files changed, 176 insertions(+), 38 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.html b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.html index b667c7ac69..c6fdf6348e 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.html @@ -4,6 +4,7 @@ id='{{randId}}' class="d-inline-block p-1 text-break {{moreClasses}}" [attr.tabindex]="readOnly ? -1 : ''" + (keydown)="inputKeyDown($event)" (focus)="focusDiv($event)" (blur)="propagateTouch(); valueChange()"> @@ -17,6 +18,7 @@ [maxlength]="maxLength || ''" [disabled]="readOnly" [attr.tabindex]="readOnly ? -1 : ''" + (keydown)="inputKeyDown($event)" (focus)="$event.target.select()" (blur)="propagateTouch()" [(ngModel)]="content" diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts index 465832cb3d..4372a6f9ee 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts @@ -19,13 +19,15 @@ import {MarcEditContext} from './editor-context'; }] }) -export class EditableContentComponent implements OnInit, AfterViewInit, ControlValueAccessor { +export class EditableContentComponent + implements OnInit, AfterViewInit, ControlValueAccessor { @Input() context: MarcEditContext; @Input() readOnly: boolean; @Input() content: string; - @Input() maxLength: number; - @Input() bigText: boolean; + @Input() fieldId: number; + + @Input() dataType: 'tag' | 'indicator' | 'subfield' | 'text'; // space-separated list of additional CSS classes to append @Input() moreClasses: string; @@ -33,7 +35,9 @@ export class EditableContentComponent implements OnInit, AfterViewInit, ControlV get record(): MarcRecord { return this.context.record; } randId: number; - editDiv: any; // used for bigText + editInput: any; // used for bigText + maxLength: number; + bigText: boolean; // Stub functions required by ControlValueAccessor propagateChange = (_: any) => {}; @@ -43,15 +47,42 @@ export class EditableContentComponent implements OnInit, AfterViewInit, ControlV this.randId = Math.floor(Math.random() * 100000); } - ngOnInit() {} + ngOnInit() { + this.inspectDataType(); + } - ngAfterViewInit() { - if (this.bigText) { - this.editDiv = // numeric id requires [id=...] query selector - this.renderer.selectRootElement(`[id='${this.randId}']`); + inspectDataType() { + switch (this.dataType) { + + case 'tag': + this.maxLength = 3; + + // Arrow navigation focuses tags + this.context.fieldFocusRequest.subscribe(fieldId => { + if (fieldId === this.fieldId && this.editInput) { + this.editInput.focus(); + } + }); + break; + + case 'indicator': + case 'subfield': + this.maxLength = 1; + break; + + // use sfv, etc. + case 'text': + this.maxLength = null; + this.bigText = true; + break; } } + ngAfterViewInit() { + this.editInput = // numeric id requires [id=...] query selector + this.renderer.selectRootElement(`[id='${this.randId}']`); + } + inputSize(): number { // give at least 2 chars space and grow with the content return Math.max(2, (this.content || '').length) * 1.1; @@ -70,8 +101,8 @@ export class EditableContentComponent implements OnInit, AfterViewInit, ControlV } valueChange() { - if (this.editDiv) { - this.content = this.editDiv.innerText; + if (this.bigText && this.editInput) { + this.content = this.editInput.innerText; } this.propagateChange(this.content); } @@ -81,8 +112,8 @@ export class EditableContentComponent implements OnInit, AfterViewInit, ControlV content = ''; } this.content = content; - if (this.editDiv) { - this.editDiv.innerText = content; + if (this.bigText && this.editInput) { + this.editInput.innerText = content; } } @@ -93,5 +124,22 @@ export class EditableContentComponent implements OnInit, AfterViewInit, ControlV registerOnTouched(fn) { this.propagateTouch = fn; } + + inputKeyDown(evt: KeyboardEvent) { + console.log(evt.key); + + switch (evt.key) { + case 'ArrowDown': + if (evt.ctrlKey) { + // Copy the field down + } else { + // Navigate down one field + const field = this.record.getNextField(this.fieldId); + if (field) { + this.context.requestFieldFocus(field.fieldId); + } + } + } + } } diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor-context.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor-context.ts index 4c30256980..31705a9b32 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor-context.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor-context.ts @@ -2,9 +2,12 @@ import {EventEmitter} from '@angular/core'; import {MarcRecord} from './marcrecord'; import {NgbPopover} from '@ng-bootstrap/ng-bootstrap'; +/* Per-instance MARC editor context. */ + export class MarcEditContext { recordChange: EventEmitter; + fieldFocusRequest: EventEmitter; popOvers: NgbPopover[] = []; @@ -12,6 +15,7 @@ export class MarcEditContext { set record(r: MarcRecord) { if (r !== this._record) { this._record = r; + this._record.stampFieldIds(); this.recordChange.emit(r); } } @@ -22,6 +26,7 @@ export class MarcEditContext { constructor() { this.recordChange = new EventEmitter(); + this.fieldFocusRequest = new EventEmitter(); } // NgbPopovers don't always close when we want them to, @@ -29,5 +34,9 @@ export class MarcEditContext { closePopovers() { this.popOvers.forEach(p => p.close()); } + + requestFieldFocus(id: number) { + this.fieldFocusRequest.emit(id); + } } diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts index 58179b39e3..58ec9f1cde 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts @@ -19,7 +19,7 @@ export class MarcRecord { fixedFieldChange: EventEmitter; get leader(): string { - return this.record.leader; + return this.record.leader; } set leader(l: string) { @@ -27,7 +27,7 @@ export class MarcRecord { } get fields(): any[] { - return this.record.fields; + return this.record.fields; } set fields(f: any[]) { @@ -66,5 +66,31 @@ export class MarcRecord { this.fixedFieldChange.emit(fieldCode); return response; } + + // Give each field an identifier so it may be referenced later. + stampFieldIds() { + this.fields.forEach(f => + f.fieldId = Math.floor(Math.random() * 100000)); + } + + getField(id: number) { + return this.fields.filter(f => f.fieldId === id)[0]; + } + + getPreviousField(id: number) { + for (let idx = 0; idx < this.fields.length; idx++) { + if (this.fields[idx].fieldId === id) { + return this.fields[idx - 1]; + } + } + } + + getNextField(id: number) { + for (let idx = 0; idx < this.fields.length; idx++) { + if (this.fields[idx].fieldId === id) { + return this.fields[idx + 1]; + } + } + } } diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html index 6be1151503..c44630e9c3 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html @@ -11,43 +11,97 @@ + +
- - + + + + +
+ +
- - + + + +
+ +
- - - + + + + + + + + + + + + + - - + + [readOnly]="true" + i18n-ngModel [ngModel]="'‡'"> + - - + + [(ngModel)]="subfield[0]" + [context]="context" + [fieldId]="field.fieldId" + [maxLength]="1"> + - - + +
diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.ts index 4d4f07991d..7532e6fb54 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.ts @@ -53,7 +53,6 @@ export class MarcRichEditorComponent implements OnInit { dataFields(): any[] { return this.record.fields.filter(f => !f.isControlfield()); } - } -- 2.11.0