diff options
-rw-r--r-- | package.json | 4 | ||||
-rw-r--r-- | src/client/util/RichTextSchema.tsx | 32 | ||||
-rw-r--r-- | src/client/util/TooltipTextMenu.scss | 2 | ||||
-rw-r--r-- | src/client/util/TooltipTextMenu.tsx | 83 | ||||
-rw-r--r-- | src/debug/Viewer.tsx | 3 | ||||
-rw-r--r-- | src/new_fields/RichTextField.ts | 2 |
6 files changed, 115 insertions, 11 deletions
diff --git a/package.json b/package.json index 59a9cc906..b1f44c37a 100644 --- a/package.json +++ b/package.json @@ -154,8 +154,10 @@ "passport-local": "^1.0.0", "pdfjs-dist": "^2.0.943", "probe-image-size": "^4.0.0", + "prosemirror": "^0.11.1", "prosemirror-commands": "^1.0.7", "prosemirror-example-setup": "^1.0.1", + "prosemirror-find-replace": "^0.9.0", "prosemirror-history": "^1.0.4", "prosemirror-keymap": "^1.0.1", "prosemirror-model": "^1.7.0", @@ -198,4 +200,4 @@ "uuid": "^3.3.2", "xoauth2": "^1.2.0" } -}
\ No newline at end of file +} diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 63c879d67..9197a3b6f 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -282,7 +282,7 @@ export const marks: { [index: string]: MarkSpec } = { }, highlight: { - parseDOM: [{ style: 'background: #d9dbdd' }], + parseDOM: [{ style: 'color: blue' }], toDOM() { return ['span', { style: 'color: blue' @@ -290,6 +290,15 @@ export const marks: { [index: string]: MarkSpec } = { } }, + search_highlight: { + parseDOM: [{ style: 'background: yellow' }], + toDOM() { + return ['span', { + style: 'background: yellow' + }]; + } + }, + // :: MarkSpec Code font mark. Represented as a `<code>` element. code: { @@ -493,28 +502,39 @@ export class SummarizedView { _view: any; constructor(node: any, view: any, getPos: any) { this._collapsed = document.createElement("span"); - this._collapsed.textContent = "㊉"; + this._collapsed.textContent = node.attrs.visibility ? "㊀" : "㊉"; this._collapsed.style.opacity = "0.5"; this._collapsed.style.position = "relative"; this._collapsed.style.width = "40px"; this._collapsed.style.height = "20px"; let self = this; this._view = view; + const js = node.toJSON; + node.toJSON = function () { + + return js.apply(this, arguments); + }; this._collapsed.onpointerdown = function (e: any) { if (node.attrs.visibility) { - node.attrs.visibility = !node.attrs.visibility; + // node.attrs.visibility = !node.attrs.visibility; let y = getPos(); + const attrs = { ...node.attrs }; + attrs.visibility = !attrs.visibility; let { from, to } = self.updateSummarizedText(y + 1, view.state.schema.marks.highlight); let length = to - from; let newSelection = TextSelection.create(view.state.doc, y + 1, y + 1 + length); // update attrs of node - node.attrs.text = newSelection.content(); - node.attrs.textslice = newSelection.content().toJSON(); + attrs.text = newSelection.content(); + attrs.textslice = newSelection.content().toJSON(); + view.dispatch(view.state.tr.setNodeMarkup(y, undefined, attrs)); view.dispatch(view.state.tr.setSelection(newSelection).deleteSelection(view.state, () => { })); self._collapsed.textContent = "㊉"; } else { - node.attrs.visibility = !node.attrs.visibility; + // node.attrs.visibility = !node.attrs.visibility; let y = getPos(); + const attrs = { ...node.attrs }; + attrs.visibility = !attrs.visibility; + view.dispatch(view.state.tr.setNodeMarkup(y, undefined, attrs)); let mark = view.state.schema.mark(view.state.schema.marks.highlight); view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.doc, y + 1, y + 1))); const from = view.state.selection.from; diff --git a/src/client/util/TooltipTextMenu.scss b/src/client/util/TooltipTextMenu.scss index b10573b3e..6e6818636 100644 --- a/src/client/util/TooltipTextMenu.scss +++ b/src/client/util/TooltipTextMenu.scss @@ -235,7 +235,7 @@ } .tooltipMenu { - position: relative; + position: absolute; z-index: 2000; background: #121721; border: 1px solid silver; diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 9f8d0b2f6..e72e3cf5e 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -33,6 +33,7 @@ export class TooltipTextMenu { private fontStylesToName: Map<MarkType, string>; private listTypeToIcon: Map<NodeType, string>; private link: HTMLAnchorElement; + //private wrapper: HTMLDivElement; private linkEditor?: HTMLDivElement; private linkText?: HTMLDivElement; @@ -49,8 +50,10 @@ export class TooltipTextMenu { constructor(view: EditorView, editorProps: FieldViewProps & FormattedTextBoxProps) { this.view = view; this.editorProps = editorProps; + //this.wrapper = document.createElement("div"); this.tooltip = document.createElement("div"); this.tooltip.className = "tooltipMenu"; + this.dragElement(this.tooltip); // this.createCollapse(); // if (this._collapseBtn) { @@ -129,8 +132,6 @@ export class TooltipTextMenu { this.tooltip.appendChild(this.createStar().render(this.view).dom); - - this.updateListItemDropdown(":", this.listTypeBtnDom); this.update(view, undefined); @@ -164,6 +165,50 @@ export class TooltipTextMenu { this.fontSizeDom = newfontSizeDom; } + // Make the DIV element draggable: + + dragElement(elmnt: HTMLElement) { + var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; + if (elmnt) { + // if present, the header is where you move the DIV from: + elmnt.onmousedown = dragMouseDown; + } + const self = this; + + function dragMouseDown(e: any) { + e = e || window.event; + e.preventDefault(); + // get the mouse cursor position at startup: + pos3 = e.clientX; + pos4 = e.clientY; + document.onmouseup = closeDragElement; + // call a function whenever the cursor moves: + document.onmousemove = elementDrag; + } + + function elementDrag(e: any) { + e = e || window.event; + e.preventDefault(); + // calculate the new cursor position: + pos1 = pos3 - e.clientX; + pos2 = pos4 - e.clientY; + pos3 = e.clientX; + pos4 = e.clientY; + // set the element's new position: + elmnt.style.top = (elmnt.offsetTop - pos2) + "px"; + elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; + self.highlightSearchTerms(["hello", "there"]); + } + + function closeDragElement() { + // stop moving when mouse button is released: + document.onmouseup = null; + document.onmousemove = null; + //self.highlightSearchTerms(self.state, ["hello"]); + self.unhighlightSearchTerms(); + } + } + //label of dropdown will change to given label updateFontStyleDropdown(label: string) { //filtering function - might be unecessary @@ -551,6 +596,38 @@ export class TooltipTextMenu { return found; } + highlightSearchTerms = (terms: String[]) => { + const doc = this.view.state.doc; + const mark = this.view.state.schema.mark(this.view.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.view.dispatch(this.view.state.tr.addMark(start, start + word.length, mark).removeStoredMark(mark)); + } + else { + start += word.length + 1; + } + }); + } + }); + } + + unhighlightSearchTerms = () => { + const doc = this.view.state.doc; + const mark = this.view.state.schema.mark(this.view.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.view.dispatch(this.view.state.tr.removeMark(pos, pos + node.nodeSize, mark)); + } + } + }); + } + //updates the tooltip menu when the selection changes update(view: EditorView, lastState: EditorState | undefined) { let state = view.state; @@ -603,6 +680,8 @@ export class TooltipTextMenu { } this.view.dispatch(this.view.state.tr.setStoredMarks(this._activeMarks)); this.updateLinkMenu(); + //this.highlightSearchTerms(["hello", "there"]); + //this.unhighlightSearchTerms(); } //finds all active marks on selection in given group diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx index b22300d0b..d880f1a28 100644 --- a/src/debug/Viewer.tsx +++ b/src/debug/Viewer.tsx @@ -10,6 +10,7 @@ import { List } from '../new_fields/List'; import { URLField } from '../new_fields/URLField'; import { EditableView } from '../client/views/EditableView'; import { CompileScript } from '../client/util/Scripting'; +import { RichTextField } from '../new_fields/RichTextField'; function applyToDoc(doc: { [index: string]: FieldResult }, key: string, scriptString: string): boolean; function applyToDoc(doc: { [index: number]: FieldResult }, key: number, scriptString: string): boolean; @@ -117,6 +118,8 @@ class DebugViewer extends React.Component<{ field: FieldResult, setValue(value: content = <p>"{field}"</p>; } else if (typeof field === "number" || typeof field === "boolean") { content = <p>{field}</p>; + } else if (field instanceof RichTextField) { + content = <p>RTF: {field.Data}</p>; } else if (field instanceof URLField) { content = <p>{field.url.href}</p>; } else if (field instanceof Promise) { diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index 89d077a47..527c7b313 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -18,6 +18,6 @@ export class RichTextField extends ObjectField { } [ToScriptString]() { - return "invalid"; + return `new RichTextField("${this.Data}")`; } }
\ No newline at end of file |