/** * NewBaseEditor is equivalent to BaseEditor for outside code, but is in typescript, and * so is friendlier and clearer to derive TypeScript classes from. */ import {GristDoc} from 'app/client/components/GristDoc'; import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec'; import {CellValue} from "app/common/DocActions"; import {Disposable, IDisposableOwner, Observable} from 'grainjs'; export interface IEditorCommandGroup { fieldEditCancel: () => void; fieldEditSaveHere: () => void; [cmd: string]: () => void; } export interface Options { gristDoc: GristDoc; cellValue: CellValue; rowId: number; formulaError: Observable; editValue?: string; cursorPos: number; commands: IEditorCommandGroup; state?: any; readonly: boolean; } export interface FieldOptions extends Options { field: ViewFieldRec; } /** * Required parameters: * @param {RowModel} options.field: ViewSectionField (i.e. column) being edited. * @param {String} options.cellValue: The value in the underlying cell being edited. * @param {String} options.editValue: String to be edited, or undefined to use cellValue. * @param {Number} options.cursorPos: The initial position where to place the cursor. * @param {Object} options.commands: Object mapping command names to functions, to enable as part * of the command group that should be activated while the editor exists. */ export abstract class NewBaseEditor extends Disposable { /** * Override the create() method to allow the parameters of create() expected by old-style * Editors and provided by FieldBuilder. TODO: remove this method once all editors have been * updated to new-style Disposables. */ public static create(owner: IDisposableOwner|null, options: Opt): NewBaseEditor; public static create(options: Opt): NewBaseEditor; public static create(ownerOrOptions: any, options?: any): NewBaseEditor { return options ? Disposable.create.call(this as any, ownerOrOptions, options) : Disposable.create.call(this as any, null, ownerOrOptions); } /** * Check if the typed-in value should change the cell without opening the editor, and if so, * returns the value to save. E.g. on typing , CheckBoxEditor toggles value without opening. */ public static skipEditor( typedVal: string|undefined, origVal: CellValue, options?: {event?: KeyboardEvent|MouseEvent} ): CellValue|undefined { return undefined; } /** * Check if editor supports readonly mode (default: true) */ public static supportsReadonly(): boolean { return true; } /** * Current state of the editor. Optional, not all editors will report theirs current state. */ public editorState?: Observable; constructor(protected options: Options) { super(); } /** * Called after the editor is instantiated to attach its DOM to the page. * - cellElem: The element representing the cell that this editor should match * in size and position. Used by derived classes, e.g. to construct an EditorPlacement object. */ public abstract attach(cellElem: Element): void; /** * Called to detach the editor and show it in the floating popup. */ public detach(): HTMLElement|null { return null; } /** * Returns DOM container with the editor, typically present and attached after attach() has been * called. */ public getDom(): HTMLElement|null { return null; } /** * Called to get the value to save back to the cell. */ public abstract getCellValue(): CellValue; /** * Used if an editor needs perform any actions before a save */ public prepForSave(): void | Promise { // No-op by default. } /** * Called to get the text in the editor, used when switching between editing data and formula. */ public abstract getTextValue(): string; /** * Called to get the position of the cursor in the editor. Used when switching between editing * data and formula. */ public abstract getCursorPos(): number; }