From 5063e8c88a4ea43701b0cef39b554abc4f9275a5 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 20 Nov 2019 13:28:00 -0500 Subject: [PATCH] LPXXX initial keyboard handling Signed-off-by: Bill Erickson --- .../marc-edit/editable-content.component.html | 14 +- .../share/marc-edit/editable-content.component.ts | 154 ++++++++++++--------- .../share/marc-edit/rich-editor.component.html | 69 +++------ 3 files changed, 114 insertions(+), 123 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 c6fdf6348e..bba29d2c68 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 @@ -3,10 +3,10 @@
+ (focus)="focusBigText($event)" + (input)="bigTextValueChange()">
@@ -16,12 +16,12 @@ class="p-0 pl-1 text-break rounded-0 form-control {{moreClasses}}" [size]="inputSize()" [maxlength]="maxLength || ''" - [disabled]="readOnly" - [attr.tabindex]="readOnly ? -1 : ''" + [disabled]="fieldText" + [attr.tabindex]="fieldText ? -1 : ''" (keydown)="inputKeyDown($event)" (focus)="$event.target.select()" - (blur)="propagateTouch()" - [(ngModel)]="content" + [ngModel]="getContent()" + (ngModelChange)="setContent($event)" /> 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 4372a6f9ee..af537d109e 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 @@ -1,5 +1,5 @@ import {ElementRef, Component, Input, Output, OnInit, EventEmitter, - AfterViewInit, Renderer2, forwardRef} from '@angular/core'; + AfterViewInit, Renderer2} from '@angular/core'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; import {MarcRecord} from './marcrecord'; import {MarcEditContext} from './editor-context'; @@ -11,84 +11,120 @@ import {MarcEditContext} from './editor-context'; @Component({ selector: 'eg-marc-editable-content', templateUrl: './editable-content.component.html', - styleUrls: ['./editable-content.component.css'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EditableContentComponent), - multi: true - }] + styleUrls: ['./editable-content.component.css'] }) -export class EditableContentComponent - implements OnInit, AfterViewInit, ControlValueAccessor { +export class EditableContentComponent implements OnInit, AfterViewInit { @Input() context: MarcEditContext; - @Input() readOnly: boolean; - @Input() content: string; - @Input() fieldId: number; + @Input() field: any; // MARC.Field + @Input() fieldType: 'ldr' | 'tag' | 'cfld' | 'ind' | 'sfc' | 'sfv' = null; - @Input() dataType: 'tag' | 'indicator' | 'subfield' | 'text'; + // used when the fieldType is ambiguous. E.g. 'ind1' + @Input() fieldName: string = null; + + // read-only field text. E.g. 'LDR' + @Input() fieldText: string = null; + + // array of subfield code and subfield value + @Input() subfield: any; // MARC.Subfield // space-separated list of additional CSS classes to append @Input() moreClasses: string; get record(): MarcRecord { return this.context.record; } - randId: number; - editInput: any; // used for bigText - maxLength: number; - bigText: boolean; - - // Stub functions required by ControlValueAccessor - propagateChange = (_: any) => {}; - propagateTouch = () => {}; + bigText = false; + randId = Math.floor(Math.random() * 100000); + editInput: any; // or
+ maxLength: number = null; constructor(private renderer: Renderer2) { this.randId = Math.floor(Math.random() * 100000); } ngOnInit() { - this.inspectDataType(); + this.setupDataType(); } - inspectDataType() { - switch (this.dataType) { + setupDataType() { + const content = this.getContent(); + + switch (this.fieldType) { + case 'ldr': + if (content) { this.maxLength = content.length; } + break; case 'tag': this.maxLength = 3; // Arrow navigation focuses tags - this.context.fieldFocusRequest.subscribe(fieldId => { - if (fieldId === this.fieldId && this.editInput) { - this.editInput.focus(); - } - }); + if (this.field) { // LDR tag does not have a field + this.context.fieldFocusRequest.subscribe(fieldId => { + if (fieldId === this.field.fieldId && this.editInput) { + this.editInput.select(); + } + }); + } break; - case 'indicator': - case 'subfield': + case 'ind': + case 'sfc': this.maxLength = 1; break; - // use sfv, etc. - case 'text': - this.maxLength = null; + case 'sfv': this.bigText = true; break; } } + getContent(): string { + if (this.fieldText) { return this.fieldText; } // read-only + + switch (this.fieldType) { + case 'ldr': return this.record.leader; + case 'cfld': return this.field.data; + case 'tag': return this.field.tag; + case 'ind': return this.field[this.fieldName]; + case 'sfc': return this.subfield[0]; + case 'sfv': return this.subfield[1]; + } + } + + setContent(value: string) { + + if (this.fieldText) { return; } // read-only text + + switch (this.fieldType) { + case 'ldr': this.record.leader = value; break; + case 'cfld': this.field.data = value; break; + case 'tag': this.field.tag = value; break; + case 'ind': this.field[this.fieldName] = value; break; + case 'sfc': this.subfield[0] = value; break; + case 'sfv': this.subfield[1] = value; break; + } + } + + // Propagate editable div content into our record + bigTextValueChange() { + this.setContent(this.editInput.innerText); + } + ngAfterViewInit() { this.editInput = // numeric id requires [id=...] query selector this.renderer.selectRootElement(`[id='${this.randId}']`); + + // Initialize the editable div + this.editInput.innerText = this.getContent(); } inputSize(): number { // give at least 2 chars space and grow with the content - return Math.max(2, (this.content || '').length) * 1.1; + return Math.max(2, (this.getContent() || '').length) * 1.1; } - focusDiv($event) { + focusBigText($event) { const targetNode = $event.srcElement.firstChild; const range = document.createRange(); @@ -100,45 +136,35 @@ export class EditableContentComponent selection.addRange(range); } - valueChange() { - if (this.bigText && this.editInput) { - this.content = this.editInput.innerText; - } - this.propagateChange(this.content); - } - - writeValue(content: string) { - if (content === null || content === undefined) { - content = ''; - } - this.content = content; - if (this.bigText && this.editInput) { - this.editInput.innerText = content; - } - } - - registerOnChange(fn) { - this.propagateChange = fn; - } - - 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); + const field = this.record.getNextField(this.field.fieldId); if (field) { this.context.requestFieldFocus(field.fieldId); } } + evt.preventDefault(); + break; + + case 'ArrowUp': + if (evt.ctrlKey) { + // Copy the field up + } else { + // Navigate upone field + const field = this.record.getPreviousField(this.field.fieldId); + if (field) { + this.context.requestFieldFocus(field.fieldId); + } + } + evt.preventDefault(); + break; + } } } 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 c44630e9c3..df70af04f5 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 @@ -14,37 +14,21 @@
- + - +
- + - +
@@ -53,55 +37,36 @@ *ngFor="let field of dataFields()"> - + - + - + - + - + - +
-- 2.11.0