diff options
Diffstat (limited to 'src/client/views/nodes/FormattedTextBox.tsx')
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 97 |
1 files changed, 91 insertions, 6 deletions
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index fc0cc98aa..87b1d43c1 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -1,10 +1,11 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faEdit, faSmile, faTextHeight } from '@fortawesome/free-solid-svg-icons'; -import { action, IReactionDisposer, observable, reaction, runInAction, computed, trace } from "mobx"; +import { action, IReactionDisposer, observable, reaction, runInAction, computed, Lambda, trace } from "mobx"; import { observer } from "mobx-react"; import { baseKeymap } from "prosemirror-commands"; import { history } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; +import { Node as ProsNode } from "prosemirror-model"; import { EditorState, Plugin, Transaction, Selection } from "prosemirror-state"; import { NodeType, Slice, Node, Fragment } from 'prosemirror-model'; import { EditorView } from "prosemirror-view"; @@ -33,6 +34,7 @@ import { Templates } from '../Templates'; import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); +import { For } from 'babel-types'; import { DateField } from '../../../new_fields/DateField'; import { Utils } from '../../../Utils'; import { MainOverlayTextBox } from '../MainOverlayTextBox'; @@ -49,6 +51,7 @@ export interface FormattedTextBoxProps { height?: string; color?: string; outer_div?: (domminus: HTMLElement) => void; + firstinstance?: boolean; } const richTextSchema = createSchema({ @@ -63,14 +66,16 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(FormattedTextBox, fieldStr); } + public static Instance: FormattedTextBox; private _ref: React.RefObject<HTMLDivElement>; private _outerdiv?: (dominus: HTMLElement) => void; private _proseRef?: HTMLDivElement; private _editorView: Opt<EditorView>; - private _toolTipTextMenu: TooltipTextMenu | undefined = undefined; + private static _toolTipTextMenu: TooltipTextMenu | undefined = undefined; private _applyingChange: boolean = false; private _linkClicked = ""; private _reactionDisposer: Opt<IReactionDisposer>; + private _searchReactionDisposer?: Lambda; private _textReactionDisposer: Opt<IReactionDisposer>; private _proxyReactionDisposer: Opt<IReactionDisposer>; private dropDisposer?: DragManager.DragDropDisposer; @@ -100,6 +105,10 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe return ""; } + public static getToolTip() { + return this._toolTipTextMenu; + } + @undoBatch public setFontColor(color: string) { let self = this; @@ -115,6 +124,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe constructor(props: FieldViewProps) { super(props); + //if (this.props.firstinstance) { + FormattedTextBox.Instance = this; + //} if (this.props.outer_div) { this._outerdiv = this.props.outer_div; } @@ -145,7 +157,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe // tx.setSelection(new Selection(tx.)) const state = this._editorView!.state; this._editorView!.dispatch(tx); - if (this._toolTipTextMenu) { + if (FormattedTextBox._toolTipTextMenu) { // this._toolTipTextMenu.makeLinkWithState(state) } e.stopPropagation(); @@ -161,7 +173,20 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (this._editorView) { const state = this._editorView.state.apply(tx); this._editorView.updateState(state); + if (state.selection.empty && FormattedTextBox._toolTipTextMenu) { + const marks = tx.storedMarks; + if (marks) { FormattedTextBox._toolTipTextMenu.mark_key_pressed(marks); } + } this._applyingChange = true; + const fieldkey = "preview"; + if (Object.keys(this.dataDoc).indexOf(fieldkey) !== -1) { + this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON())); + this.dataDoc[this.props.fieldKey + "_text"] = state.doc.textBetween(0, state.doc.content.size, "\n\n"); + } + else { + Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON())); + Doc.GetProto(this.dataDoc)[this.props.fieldKey + "_text"] = state.doc.textBetween(0, state.doc.content.size, "\n\n"); + } if (this.extensionDoc) this.extensionDoc.text = state.doc.textBetween(0, state.doc.content.size, "\n\n"); if (this.extensionDoc) this.extensionDoc.lastModified = new DateField(new Date(Date.now())); this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON())); @@ -175,6 +200,50 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } + public highlightSearchTerms = (terms: String[]) => { + if (this._editorView && (this._editorView as any).docView) { + const fieldkey = "preview"; + const doc = this._editorView.state.doc; + const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight); + doc.nodesBetween(0, doc.content.size, (node: ProsNode, pos: number, parent: ProsNode, index: number) => { + if (node.isLeaf && node.isText && node.text) { + let nodeText: String = node.text; + let tokens = nodeText.split(" "); + let start = pos; + tokens.forEach((word) => { + if (terms.includes(word) && this._editorView) { + this._editorView.dispatch(this._editorView.state.tr.addMark(start, start + word.length, mark).removeStoredMark(mark)); + // else { + // this._editorView.state.tr.addMark(start, start + word.length, mark).removeStoredMark(mark); + // } + } + start += word.length + 1; + }); + } + }); + } + } + + public unhighlightSearchTerms = () => { + if (this._editorView && (this._editorView as any).docView) { + const doc = this._editorView.state.doc; + const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight); + doc.nodesBetween(0, doc.content.size, (node: ProsNode, pos: number, parent: ProsNode, index: number) => { + if (node.isLeaf && node.isText && node.text) { + if (node.marks.includes(mark) && this._editorView) { + this._editorView.dispatch(this._editorView.state.tr.removeMark(pos, pos + node.nodeSize, mark)); + } + } + }); + // const fieldkey = 'search_string'; + // if (Object.keys(this.props.Document).indexOf(fieldkey) !== -1) { + // this.props.Document[fieldkey] = undefined; + // } + // else this.props.Document.proto![fieldkey] = undefined; + // } + } + } + protected createDropTarget = (ele: HTMLDivElement) => { this._proseRef = ele; if (this.dropDisposer) { @@ -277,6 +346,22 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } }, { fireImmediately: true }); this.setupEditor(config, this.dataDoc, this.props.fieldKey); + + this._searchReactionDisposer = reaction(() => { + return StrCast(this.props.Document.search_string); + }, searchString => { + const fieldkey = 'preview'; + let preview = false; + // if (!this._editorView && Object.keys(this.props.Document).indexOf(fieldkey) !== -1) { + // preview = true; + // } + if (searchString) { + this.highlightSearchTerms([searchString]); + } + else { + this.unhighlightSearchTerms(); + } + }, { fireImmediately: true }); } clipboardTextSerializer = (slice: Slice): string => { @@ -411,7 +496,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe onPointerDown = (e: React.PointerEvent): void => { if (e.button === 0 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) { e.stopPropagation(); - if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) { + if (FormattedTextBox._toolTipTextMenu && FormattedTextBox._toolTipTextMenu.tooltip) { //this._toolTipTextMenu.tooltip.style.opacity = "0"; } } @@ -467,7 +552,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } onPointerUp = (e: React.PointerEvent): void => { - if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) { + if (FormattedTextBox._toolTipTextMenu && FormattedTextBox._toolTipTextMenu.tooltip) { //this._toolTipTextMenu.tooltip.style.opacity = "1"; } if (e.buttons === 1 && this.props.isSelected() && !e.altKey) { @@ -508,7 +593,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe tooltipTextMenuPlugin() { let myprops = this.props; - let self = this; + let self = FormattedTextBox; return new Plugin({ view(_editorView) { return self._toolTipTextMenu = new TooltipTextMenu(_editorView, myprops); |