diff options
author | Bob Zeleznik <zzzman@gmail.com> | 2019-11-11 18:39:23 -0500 |
---|---|---|
committer | Bob Zeleznik <zzzman@gmail.com> | 2019-11-11 18:39:23 -0500 |
commit | d220b23867050fb6565fe639c3be28080f589aa2 (patch) | |
tree | fdf66cdf026b902a5e5a4d35f92e9b313c562fb5 /src/client/util/TooltipTextMenu.tsx | |
parent | f4ca517725714d770096d683478a6f5cc995c0c3 (diff) |
made font size and font style text marks be parametrized to simplify api.
Diffstat (limited to 'src/client/util/TooltipTextMenu.tsx')
-rw-r--r-- | src/client/util/TooltipTextMenu.tsx | 277 |
1 files changed, 165 insertions, 112 deletions
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 5cbf8b761..9ce7acec8 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -29,11 +29,9 @@ export class TooltipTextMenu { public tooltip: HTMLElement; private view: EditorView; private editorProps: FieldViewProps & FormattedTextBoxProps | undefined; - private fontStyles: MarkType[]; - private fontSizes: MarkType[]; private listTypes: (NodeType | any)[]; - private fontSizeToNum: Map<MarkType, number>; - private fontStylesToName: Map<MarkType, string>; + private fontSizes: Mark[] = []; + private fontStyles: Mark[] = []; private listTypeToIcon: Map<NodeType | any, string>; //private link: HTMLAnchorElement; private wrapper: HTMLDivElement; @@ -135,46 +133,32 @@ export class TooltipTextMenu { //list of font styles - this.fontStylesToName = new Map(); - this.fontStylesToName.set(schema.marks.timesNewRoman, "Times New Roman"); - this.fontStylesToName.set(schema.marks.arial, "Arial"); - this.fontStylesToName.set(schema.marks.georgia, "Georgia"); - this.fontStylesToName.set(schema.marks.comicSans, "Comic Sans MS"); - this.fontStylesToName.set(schema.marks.tahoma, "Tahoma"); - this.fontStylesToName.set(schema.marks.impact, "Impact"); - this.fontStylesToName.set(schema.marks.crimson, "Crimson Text"); - this.fontStyles = Array.from(this.fontStylesToName.keys()); + this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Times New Roman" })); + this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Arial" })); + this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Georgia" })); + this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Comic Sans MS" })); + this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Tahoma" })); + this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Impact" })); + this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Crimson Text" })); //font sizes - this.fontSizeToNum = new Map(); - this.fontSizeToNum.set(schema.marks.p10, 10); - this.fontSizeToNum.set(schema.marks.p12, 12); - this.fontSizeToNum.set(schema.marks.p14, 14); - this.fontSizeToNum.set(schema.marks.p16, 16); - this.fontSizeToNum.set(schema.marks.p18, 18); - this.fontSizeToNum.set(schema.marks.p20, 20); - this.fontSizeToNum.set(schema.marks.p24, 24); - this.fontSizeToNum.set(schema.marks.p32, 32); - this.fontSizeToNum.set(schema.marks.p48, 48); - this.fontSizeToNum.set(schema.marks.p72, 72); - this.fontSizeToNum.set(schema.marks.pFontSize, 10); - // this.fontSizeToNum.set(schema.marks.pFontSize, 12); - // this.fontSizeToNum.set(schema.marks.pFontSize, 14); - // this.fontSizeToNum.set(schema.marks.pFontSize, 16); - // this.fontSizeToNum.set(schema.marks.pFontSize, 18); - // this.fontSizeToNum.set(schema.marks.pFontSize, 20); - // this.fontSizeToNum.set(schema.marks.pFontSize, 24); - // this.fontSizeToNum.set(schema.marks.pFontSize, 32); - // this.fontSizeToNum.set(schema.marks.pFontSize, 48); - // this.fontSizeToNum.set(schema.marks.pFontSize, 72); - this.fontSizes = Array.from(this.fontSizeToNum.keys()); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 10 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 12 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 14 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 16 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 18 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 20 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 24 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 32 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 48 })); + this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 72 })); //list types this.listTypeToIcon = new Map(); //this.listTypeToIcon.set(schema.nodes.bullet_list, ":"); this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "bullet" }), ":"); - this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "decimal" }), "1.1"); - this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "multi" }), "1.A"); + this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "decimal" }), "1.1)"); + this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "multi" }), "1.A)"); // this.listTypeToIcon.set(schema.nodes.bullet_list, "⬜"); this.listTypes = Array.from(this.listTypeToIcon.keys()); @@ -195,16 +179,13 @@ export class TooltipTextMenu { //label of dropdown will change to given label updateFontSizeDropdown(label: string) { - //filtering function - might be unecessary - let cut = (arr: MenuItem[]) => arr.filter(x => x); - //font SIZES let fontSizeBtns: MenuItem[] = []; - this.fontSizeToNum.forEach((number, mark) => { - fontSizeBtns.push(this.dropdownMarkBtn(String(number), "color: black; width: 50px;", mark, this.view, this.changeToMarkInGroup, this.fontSizes)); + this.fontSizes.forEach(mark => { + fontSizeBtns.push(this.dropdownFontSizeBtn(String(mark.attrs.fontSize), "color: black; width: 50px;", mark, this.view, this.changeToFontSize)); }); - let newfontSizeDom = (new Dropdown(cut(fontSizeBtns), { + let newfontSizeDom = (new Dropdown(fontSizeBtns, { label: label, css: "color:black; min-width: 60px; padding-left: 5px; margin-right: 0;" }) as MenuItem).render(this.view).dom; @@ -215,20 +196,15 @@ export class TooltipTextMenu { this.fontSizeDom = newfontSizeDom; } - // Make the DIV element draggable - //label of dropdown will change to given label updateFontStyleDropdown(label: string) { - //filtering function - might be unecessary - let cut = (arr: MenuItem[]) => arr.filter(x => x); - //font STYLES let fontBtns: MenuItem[] = []; - this.fontStylesToName.forEach((name, mark) => { - fontBtns.push(this.dropdownMarkBtn(name, "color: black; font-family: " + name + ", sans-serif; width: 125px;", mark, this.view, this.changeToMarkInGroup, this.fontStyles)); + this.fontStyles.forEach((mark) => { + fontBtns.push(this.dropdownFontFamilyBtn(mark.attrs.family, "color: black; font-family: " + mark.attrs.family + ", sans-serif; width: 125px;", mark, this.view, this.changeToFontFamily)); }); - let newfontStyleDom = (new Dropdown(cut(fontBtns), { + let newfontStyleDom = (new Dropdown(fontBtns, { label: label, css: "color:black; width: 125px; margin-left: -3px; padding-left: 2px;" }) as MenuItem).render(this.view).dom; @@ -468,8 +444,7 @@ export class TooltipTextMenu { this.tooltip.appendChild(listTypeBtn); return listTypeBtn; } - - //for a specific grouping of marks (passed in), remove all and apply the passed-in one to the selected text + //for a specific grouping of marks (passed in), remove all and apply the passed-in one to the selected textchangeToMarkInGroup = (markType: MarkType | undefined, view: EditorView, fontMarks: MarkType[]) => { changeToMarkInGroup = (markType: MarkType | undefined, view: EditorView, fontMarks: MarkType[]) => { let { $cursor, ranges } = view.state.selection as TextSelection; let state = view.state; @@ -498,29 +473,6 @@ export class TooltipTextMenu { }); if (markType) { - // fontsize - if (markType.name[0] === 'p') { - let size = this.fontSizeToNum.get(markType); - if (size) { this.updateFontSizeDropdown(String(size) + " pt"); } - if (this.editorProps) { - let ruleProvider = this.editorProps.ruleProvider; - let heading = NumCast(this.editorProps.Document.heading); - if (ruleProvider && heading) { - ruleProvider["ruleSize_" + heading] = size; - } - } - } - else { - let fontName = this.fontStylesToName.get(markType); - if (fontName) { this.updateFontStyleDropdown(fontName); } - if (this.editorProps) { - let ruleProvider = this.editorProps.ruleProvider; - let heading = NumCast(this.editorProps.Document.heading); - if (ruleProvider && heading) { - ruleProvider["ruleFont_" + heading] = fontName; - } - } - } //actually apply font if ((view.state.selection as any).node && (view.state.selection as any).node.type === view.state.schema.nodes.ordered_list) { let status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, @@ -531,6 +483,90 @@ export class TooltipTextMenu { } } + changeToFontFamily = (mark: Mark, view: EditorView) => { + let { $cursor, ranges } = view.state.selection as TextSelection; + let state = view.state; + let dispatch = view.dispatch; + + //remove all other active font marks + if ($cursor) { + if (view.state.schema.marks.pFontFamily.isInSet(state.storedMarks || $cursor.marks())) { + dispatch(state.tr.removeStoredMark(view.state.schema.marks.pFontFamily)); + } + } else { + let has = false; + for (let i = 0; !has && i < ranges.length; i++) { + let { $from, $to } = ranges[i]; + has = state.doc.rangeHasMark($from.pos, $to.pos, view.state.schema.marks.pFontFamily); + } + for (let i of ranges) { + if (has) { + toggleMark(view.state.schema.marks.pFontFamily)(view.state, view.dispatch, view); + } + } + } + + let fontName = mark.attrs.family; + if (fontName) { this.updateFontStyleDropdown(fontName); } + if (this.editorProps) { + let ruleProvider = this.editorProps.ruleProvider; + let heading = NumCast(this.editorProps.Document.heading); + if (ruleProvider && heading) { + ruleProvider["ruleFont_" + heading] = fontName; + } + } + //actually apply font + if ((view.state.selection as any).node && (view.state.selection as any).node.type === view.state.schema.nodes.ordered_list) { + let status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, + { ...(view.state.selection as NodeSelection).node.attrs, setFontFamily: fontName }), view.state.schema); + view.dispatch(status.setSelection(new NodeSelection(status.doc.resolve(view.state.selection.from)))); + } + else view.dispatch(view.state.tr.addMark(view.state.selection.from, view.state.selection.to, view.state.schema.marks.pFontFamily.create({ family: fontName }))); + view.state.storedMarks = [...(view.state.storedMarks || []), view.state.schema.marks.pFontFamily.create({ family: fontName })]; + } + + changeToFontSize = (mark: Mark, view: EditorView) => { + let { $cursor, ranges } = view.state.selection as TextSelection; + let state = view.state; + let dispatch = view.dispatch; + + //remove all other active font marks + if ($cursor) { + if (view.state.schema.marks.pFontSize.isInSet(state.storedMarks || $cursor.marks())) { + dispatch(state.tr.removeStoredMark(view.state.schema.marks.pFontSize)); + } + } else { + let has = false; + for (let i = 0; !has && i < ranges.length; i++) { + let { $from, $to } = ranges[i]; + has = state.doc.rangeHasMark($from.pos, $to.pos, view.state.schema.marks.pFontSize); + } + for (let i of ranges) { + if (has) { + toggleMark(view.state.schema.marks.pFontSize)(view.state, view.dispatch, view); + } + } + } + + let size = mark.attrs.fontSize; + if (size) { this.updateFontSizeDropdown(String(size) + " pt"); } + if (this.editorProps) { + let ruleProvider = this.editorProps.ruleProvider; + let heading = NumCast(this.editorProps.Document.heading); + if (ruleProvider && heading) { + ruleProvider["ruleSize_" + heading] = size; + } + } + //actually apply font + if ((view.state.selection as any).node && (view.state.selection as any).node.type === view.state.schema.nodes.ordered_list) { + let status = updateBullets(view.state.tr.setNodeMarkup(view.state.selection.from, (view.state.selection as any).node.type, + { ...(view.state.selection as NodeSelection).node.attrs, setFontSize: size }), view.state.schema); + view.dispatch(status.setSelection(new NodeSelection(status.doc.resolve(view.state.selection.from)))); + } + else view.dispatch(view.state.tr.addMark(view.state.selection.from, view.state.selection.to, view.state.schema.marks.pFontSize.create({ fontSize: size }))); + view.state.storedMarks = [...(view.state.storedMarks || []), view.state.schema.marks.pFontSize.create({ fontSize: size })]; + } + //remove all node typeand apply the passed-in one to the selected text changeToNodeType = (nodeType: NodeType | undefined) => { //remove oldif (nodeType) { //add new @@ -558,7 +594,7 @@ export class TooltipTextMenu { //makes a button for the drop down FOR MARKS //css is the style you want applied to the button - dropdownMarkBtn(label: string, css: string, markType: MarkType, view: EditorView, changeToMarkInGroup: (markType: MarkType<any>, view: EditorView, groupMarks: MarkType[]) => any, groupMarks: MarkType[]) { + dropdownFontFamilyBtn(label: string, css: string, mark: Mark, view: EditorView, changeFontFamily: (mark: Mark<any>, view: EditorView) => any) { return new MenuItem({ title: "", label: label, @@ -567,7 +603,22 @@ export class TooltipTextMenu { css: css, enable() { return true; }, run() { - changeToMarkInGroup(markType, view, groupMarks); + changeFontFamily(mark, view); + } + }); + } + //makes a button for the drop down FOR MARKS + //css is the style you want applied to the button + dropdownFontSizeBtn(label: string, css: string, mark: Mark, view: EditorView, changeFontSize: (markType: Mark<any>, view: EditorView) => any) { + return new MenuItem({ + title: "", + label: label, + execEvent: "", + class: "menuicon", + css: css, + enable() { return true; }, + run() { + changeFontSize(mark, view); } }); } @@ -649,7 +700,9 @@ export class TooltipTextMenu { this.view.dispatch(this.view.state.tr.removeMark(from, to)); Array.from(this._brushMarks).filter(m => m.type !== schema.marks.user_mark).forEach((mark: Mark) => { const markType = mark.type; - this.changeToMarkInGroup(markType, this.view, []); + if (mark.type === schema.marks.pFontFamily) this.changeToFontFamily(mark, this.view); + else if (mark.type === schema.marks.pFontSize) this.changeToFontSize(mark, this.view); + else this.changeToMarkInGroup(markType, this.view, []); }); } } @@ -868,50 +921,23 @@ export class TooltipTextMenu { //UPDATE LIST ITEM DROPDOWN //UPDATE FONT STYLE DROPDOWN - let activeStyles = this.activeMarksOnSelection(this.fontStyles); + let activeStyles = this.activeFontFamilyOnSelection(); if (activeStyles !== undefined) { - // activeStyles.forEach((markType) => { - // this._activeMarks.push(this.view.state.schema.mark(markType)); - // }); if (activeStyles.length === 1) { - // if we want to update something somewhere with active font name - let fontName = this.fontStylesToName.get(activeStyles[0]); - if (fontName) { this.updateFontStyleDropdown(fontName); } - } else if (activeStyles.length === 0) { - //crimson on default - this.updateFontStyleDropdown("Crimson Text"); - } else { - this.updateFontStyleDropdown("Various"); - } + activeStyles[0] && this.updateFontStyleDropdown(activeStyles[0]); + } else this.updateFontStyleDropdown(activeStyles.length ? "various" : "default"); } //UPDATE FONT SIZE DROPDOWN - let activeSizes = this.activeMarksOnSelection(this.fontSizes); + let activeSizes = this.activeFontSizeOnSelection(); if (activeSizes !== undefined) { if (activeSizes.length === 1) { //if there's only one active font size - // activeSizes.forEach((markType) => { - // this._activeMarks.push(this.view.state.schema.mark(markType)); - // }); - let size = this.fontSizeToNum.get(activeSizes[0]); - if (size) { this.updateFontSizeDropdown(String(size) + " pt"); } - } else if (activeSizes.length === 0) { - //should be 14 on default - this.updateFontSizeDropdown("14 pt"); - } else { //multiple font sizes selected - this.updateFontSizeDropdown("Various"); - } + activeSizes[0] && this.updateFontSizeDropdown(String(activeSizes[0]) + " pt"); + } else this.updateFontSizeDropdown(activeSizes.length ? "various" : "default"); } this.update_mark_doms(); } - - public mark_key_pressed(marks: Mark<any>[]) { - if (this.view.state.selection.empty) { - if (marks) this._activeMarks = marks; - this.update_mark_doms(); - } - } - update_mark_doms() { this.reset_mark_doms(); let foundlink = false; @@ -946,6 +972,30 @@ export class TooltipTextMenu { } + //finds fontSize at start of selection + activeFontSizeOnSelection() { + //current selection + let state = this.view.state; + let activeSizes: number[] = []; + const pos = this.view.state.selection.$from; + const ref_node: ProsNode = this.reference_node(pos); + if (ref_node && ref_node !== this.view.state.doc && ref_node.isText) { + ref_node.marks.forEach(m => m.type === state.schema.marks.pFontSize && activeSizes.push(m.attrs.fontSize)); + } + return activeSizes; + } + //finds fontSize at start of selection + activeFontFamilyOnSelection() { + //current selection + let state = this.view.state; + let activeFamilies: string[] = []; + const pos = this.view.state.selection.$from; + const ref_node: ProsNode = this.reference_node(pos); + if (ref_node && ref_node !== this.view.state.doc && ref_node.isText) { + ref_node.marks.forEach(m => m.type === state.schema.marks.pFontFamily && activeFamilies.push(m.attrs.family)); + } + return activeFamilies; + } //finds all active marks on selection in given group activeMarksOnSelection(markGroup: MarkType[]) { //current selection @@ -980,6 +1030,9 @@ export class TooltipTextMenu { this._activeMarks = ref_node.marks; activeMarks = markGroup.filter(mark_type => { if (dispatch) { + if (mark_type === state.schema.marks.pFontSize) { + return ref_node.marks.some(m => m.type.name === state.schema.marks.pFontSize.name); + } let mark = state.schema.mark(mark_type); return ref_node.marks.includes(mark); } |