import {ElementRef, Component, Input, Output, OnInit, EventEmitter,
AfterViewInit, Renderer2} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
-import {MarcRecord} from './marcrecord';
+import {MarcRecord, MarcField} from './marcrecord';
import {MarcEditContext} from './editor-context';
/**
export class EditableContentComponent implements OnInit, AfterViewInit {
@Input() context: MarcEditContext;
- @Input() field: any; // MARC.Field
+ @Input() field: MarcField;
@Input() fieldType: 'ldr' | 'tag' | 'cfld' | 'ind' | 'sfc' | 'sfv' = null;
// used when the fieldType is ambiguous. E.g. 'ind1'
@Input() fieldText: string = null;
// array of subfield code and subfield value
- @Input() subfield: any; // MARC.Subfield
+ @Input() subfield: string[]; // [code, value]
// space-separated list of additional CSS classes to append
@Input() moreClasses: string;
switch (evt.key) {
case 'ArrowDown':
- if (evt.ctrlKey) {
- // Copy the field down
- } else {
- // Navigate down one field
+
+ if (evt.ctrlKey) { // Copy field down
+
+ this.context.record.insertFieldsAfter(
+ this.field,
+ this.context.record.cloneField(this.field)
+ );
+
+ } else { // Jump to next tag
+
const field = this.record.getNextField(this.field.fieldId);
if (field) {
this.context.requestFieldFocus(field.fieldId);
break;
case 'ArrowUp':
- if (evt.ctrlKey) {
- // Copy the field up
- } else {
- // Navigate upone field
+
+ if (evt.ctrlKey) { // Copy field up
+
+ this.context.record.insertFieldsBefore(
+ this.field,
+ this.context.record.cloneField(this.field)
+ );
+
+ } else { // Jump to previous tag
+
const field = this.record.getPreviousField(this.field.fieldId);
if (field) {
this.context.requestFieldFocus(field.fieldId);
import {EventEmitter} from '@angular/core';
-import {MarcRecord} from './marcrecord';
+import {MarcRecord, MarcField} from './marcrecord';
import {NgbPopover} from '@ng-bootstrap/ng-bootstrap';
/* Per-instance MARC editor context. */
// MARC breaker delimiter
const DELIMITER = '$';
+// This acts as a veneer over a Marc.Field object.
+export interface MarcField {
+ fieldId?: number;
+ data?: string;
+ tag?: string;
+ ind1?: string;
+ ind2?: string;
+
+ // [[sfCode, sfValue], [sfCode, sfValue], ...]
+ subfields?: string[][];
+
+ isControlfield(): boolean;
+}
+
export class MarcRecord {
id: number; // Database ID when known.
this.record.leader = l;
}
- get fields(): any[] {
+ get fields(): MarcField[] {
return this.record.fields;
}
- set fields(f: any[]) {
+ set fields(f: MarcField[]) {
this.record.fields = f;
}
// Give each field an identifier so it may be referenced later.
stampFieldIds() {
- this.fields.forEach(f =>
- f.fieldId = Math.floor(Math.random() * 100000));
+ this.fields.forEach(f => {
+ if (!f.fieldId) {
+ f.fieldId = Math.floor(Math.random() * 100000)
+ }
+ });
+ }
+
+ insertFieldsBefore(field: MarcField, ...newFields: MarcField[]) {
+ this.record.insertFieldsBefore.apply(
+ this.record, [field].concat(newFields));
+ this.stampFieldIds();
+ }
+
+ insertFieldsAfter(field: MarcField, ...newFields: MarcField[]) {
+ this.record.insertFieldsAfter.apply(
+ this.record, [field].concat(newFields));
+ this.stampFieldIds();
}
- getField(id: number) {
+ getField(id: number): MarcField {
return this.fields.filter(f => f.fieldId === id)[0];
}
- getPreviousField(id: number) {
+ getPreviousField(id: number): MarcField {
for (let idx = 0; idx < this.fields.length; idx++) {
if (this.fields[idx].fieldId === id) {
return this.fields[idx - 1];
}
}
- getNextField(id: number) {
+ getNextField(id: number): MarcField {
for (let idx = 0; idx < this.fields.length; idx++) {
if (this.fields[idx].fieldId === id) {
return this.fields[idx + 1];
}
}
}
+
+ cloneField(field: MarcField): MarcField {
+ const newField: any = {tag: field.tag};
+
+ if (field.isControlfield()) {
+ newField.data = field.data;
+ return new MARC21.Field(newField);
+ }
+
+ newField.ind1 = field.ind1;
+ newField.ind2 = field.ind2;
+ newField.subfields = this.cloneSubfields(field.subfields);
+
+ return new MARC21.Field(newField);
+ }
+
+ cloneSubfields(subfields: string[][]): string[][] {
+ const root = [];
+ subfields.forEach(sf => root.push([].concat(sf)));
+ return root;
+ }
}
import {IdlService} from '@eg/core/idl.service';
import {OrgService} from '@eg/core/org.service';
import {TagTableService} from './tagtable.service';
-import {MarcRecord} from './marcrecord';
+import {MarcRecord, MarcField} from './marcrecord';
import {MarcEditContext} from './editor-context';
]).then(_ => this.dataLoaded = true);
}
- controlFields(): any[] {
+ controlFields(): MarcField[] {
return this.record.fields.filter(f => f.isControlfield());
}
- dataFields(): any[] {
+ dataFields(): MarcField[] {
return this.record.fields.filter(f => !f.isControlfield());
}
}