diff options
Diffstat (limited to 'src/client/util/TooltipTextMenu.tsx')
-rw-r--r-- | src/client/util/TooltipTextMenu.tsx | 173 |
1 files changed, 124 insertions, 49 deletions
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 82e9d1bac..777abe030 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -1,12 +1,12 @@ import { action, IReactionDisposer, reaction } from "mobx"; -import { Dropdown, DropdownSubmenu, MenuItem } from "prosemirror-menu"; +import { Dropdown, DropdownSubmenu, MenuItem, MenuItemSpec, renderGrouped, icons, } from "prosemirror-menu"; //no import css import { baseKeymap, lift } from "prosemirror-commands"; import { history, redo, undo } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; -import { EditorState, Transaction, NodeSelection } from "prosemirror-state"; +import { EditorState, Transaction, NodeSelection, TextSelection } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { schema } from "./RichTextSchema"; -import { Schema, NodeType } from "prosemirror-model"; +import { Schema, NodeType, MarkType } from "prosemirror-model"; import React = require("react"); import "./TooltipTextMenu.scss"; const { toggleMark, setBlockType, wrapIn } = require("prosemirror-commands"); @@ -24,8 +24,12 @@ export class TooltipTextMenu { private tooltip: HTMLElement; private num_icons = 0; + private view: EditorView; + private fontStyles: MarkType[]; + private fontSizes: MarkType[]; constructor(view: EditorView) { + this.view = view; this.tooltip = document.createElement("div"); this.tooltip.className = "tooltipMenu"; @@ -34,7 +38,6 @@ export class TooltipTextMenu { //add additional icons library.add(faListUl); - //add the buttons to the tooltip let items = [ { command: toggleMark(schema.marks.strong), dom: this.icon("B", "strong") }, @@ -44,44 +47,142 @@ export class TooltipTextMenu { { command: toggleMark(schema.marks.superscript), dom: this.icon("s", "superscript") }, { command: toggleMark(schema.marks.subscript), dom: this.icon("s", "subscript") }, { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") }, - { command: toggleMark(schema.marks.timesNewRoman), dom: this.icon("x", "TNR") }, { command: lift, dom: this.icon("<", "lift") }, ] //add menu items items.forEach(({ dom, command }) => { this.tooltip.appendChild(dom); - }); - //add dropdowns - - //pointer down handler to activate button effects - this.tooltip.addEventListener("pointerdown", e => { - e.preventDefault(); - view.focus(); - //update view of icons - this.num_icons = 0; - items.forEach(({ command, dom }) => { - if (e.srcElement && dom.contains(e.srcElement as Node)) { - //let active = command(view.state, view.dispatch, view); - let active = command(view.state, view.dispatch, view); - //uncomment this if we want the bullet button to disappear if current selection is bulleted - //dom.style.display = active ? "" : "none"; - } + //pointer down handler to activate button effects + dom.addEventListener("pointerdown", e => { + e.preventDefault(); + view.focus(); + command(view.state, view.dispatch, view); }) - }) + + }); + + //dropdowns + //list of font btns to add + this.fontStyles = [ + schema.marks.timesNewRoman, + schema.marks.arial, + schema.marks.georgia, + schema.marks.comicSans, + schema.marks.tahoma, + schema.marks.impact, + ] + this.fontSizes = [ + schema.marks.p10, + schema.marks.p12, + schema.marks.p16, + schema.marks.p24, + schema.marks.p32, + schema.marks.p48, + schema.marks.p72, + ] + this.addFontDropdowns(); this.update(view, undefined); } + //adds font size and font style dropdowns + addFontDropdowns() { + //filtering function - might be unecessary + let cut = (arr: MenuItem[]) => arr.filter(x => x); + let fontBtns = [ + this.dropdownBtn("Times New Roman", "font-family: Times New Roman, Times, serif; width: 120px;", schema.marks.timesNewRoman, this.view, this.changeToMarkInGroup, this.fontStyles), + this.dropdownBtn("Arial", "font-family: Arial, Helvetica, sans-serif; width: 120px;", schema.marks.arial, this.view, this.changeToMarkInGroup, this.fontStyles), + this.dropdownBtn("Georgia", "font-family: Georgia, serif; width: 120px; width: 120px;", schema.marks.georgia, this.view, this.changeToMarkInGroup, this.fontStyles), + this.dropdownBtn("ComicSans", "font-family: Comic Sans MS, cursive, sans-serif; width: 120px;", schema.marks.comicSans, this.view, this.changeToMarkInGroup, this.fontStyles), + this.dropdownBtn("Tahoma", "font-family: Tahoma, Geneva, sans-serif; width: 120px;", schema.marks.tahoma, this.view, this.changeToMarkInGroup, this.fontStyles), + this.dropdownBtn("Impact", "font-family: Impact, Charcoal, sans-serif; width: 120px;", schema.marks.impact, this.view, this.changeToMarkInGroup, this.fontStyles), + ] + + let fontSizeBtns = [ + this.dropdownBtn("10", "width: 50px;", schema.marks.p10, this.view, this.changeToMarkInGroup, this.fontSizes), + this.dropdownBtn("12", "width: 50px;", schema.marks.p12, this.view, this.changeToMarkInGroup, this.fontSizes), + this.dropdownBtn("16", "width: 50px;", schema.marks.p16, this.view, this.changeToMarkInGroup, this.fontSizes), + this.dropdownBtn("24", "width: 50px;", schema.marks.p24, this.view, this.changeToMarkInGroup, this.fontSizes), + this.dropdownBtn("32", "width: 50px;", schema.marks.p32, this.view, this.changeToMarkInGroup, this.fontSizes), + this.dropdownBtn("48", "width: 50px;", schema.marks.p48, this.view, this.changeToMarkInGroup, this.fontSizes), + this.dropdownBtn("72", "width: 50px;", schema.marks.p72, this.view, this.changeToMarkInGroup, this.fontSizes), + ] + + //dropdown to hold font btns + let dd_fontStyle = new Dropdown(cut(fontBtns), { label: "Font Style", css: "color:white;" }) as MenuItem; + let dd_fontSize = new Dropdown(cut(fontSizeBtns), { label: "Font Size", css: "color:white;" }) as MenuItem; + this.tooltip.appendChild(dd_fontStyle.render(this.view).dom); + this.tooltip.appendChild(dd_fontSize.render(this.view).dom); + } + + //for a specific grouping of marks (passed in), remove all and apply the passed-in one to the selected text + changeToMarkInGroup(markType: MarkType, view: EditorView, fontMarks: MarkType[]) { + let { empty, $cursor, ranges } = view.state.selection as TextSelection; + let state = view.state; + let dispatch = view.dispatch; + + //remove all other active font marks + fontMarks.forEach((type) => { + if (dispatch) { + if ($cursor) { + if (type.isInSet(state.storedMarks || $cursor.marks())) { + dispatch(state.tr.removeStoredMark(type)); + } + } else { + let has = false, tr = state.tr + for (let i = 0; !has && i < ranges.length; i++) { + let { $from, $to } = ranges[i] + has = state.doc.rangeHasMark($from.pos, $to.pos, type) + } + for (let i = 0; i < ranges.length; i++) { + let { $from, $to } = ranges[i] + if (has) { + toggleMark(type)(view.state, view.dispatch, view); + } + } + } + } + }); //actually apply font + return toggleMark(markType)(view.state, view.dispatch, view); + } + + //makes a button for the drop down + //css is the style you want applied to the button + dropdownBtn(label: string, css: string, markType: MarkType, view: EditorView, changeToMarkInGroup: (markType: MarkType<any>, view: EditorView, groupMarks: MarkType[]) => any, groupMarks: MarkType[]) { + return new MenuItem({ + title: "", + label: label, + execEvent: "", + class: "menuicon", + css: css, + enable(state) { return true; }, + run() { + changeToMarkInGroup(markType, view, groupMarks); + } + }); + } // Helper function to create menu icons icon(text: string, name: string) { let span = document.createElement("span"); span.className = "menuicon " + name; span.title = name; span.textContent = text; + span.style.color = "white"; return span; } + //method for checking whether node can be inserted + canInsert(state: EditorState, nodeType: NodeType<Schema<string, string>>) { + let $from = state.selection.$from + for (let d = $from.depth; d >= 0; d--) { + let index = $from.index(d) + if ($from.node(d).canReplaceWith(index, index, nodeType)) return true + } + return false + } + + //adapted this method - use it to check if block has a tag (ie bulleting) blockActive(type: NodeType<Schema<string, string>>, state: EditorState) { let attrs = {}; @@ -100,30 +201,6 @@ export class TooltipTextMenu { } } - //this doesn't currently work but could be used to use icons for buttons - unorderedListIcon(): HTMLSpanElement { - let span = document.createElement("span"); - //let icon = document.createElement("FontAwesomeIcon"); - //icon.className = "menuicon"; - //icon.style.color = "white"; - //span.appendChild(<i style={{ color: "white" }} icon="list-ul" size="lg" />); - let i = document.createElement("i"); - i.className = "fa falist-ul"; - span.appendChild(i); - //span.appendChild(icon); - //return liftItem.spec.icon.sty - - //let sym = document.createElementNS(SVG, "symbol") - // sym.id = name - //sym.style.color = "white"; - //width then height - //sym.setAttribute("viewBox", "0 0 " + 1024 + " " + 1024); - //let path = sym.appendChild(document.createElementNS(SVG, "path")); - //path.setAttribute("d", "M219 310v329q0 7-5 12t-12 5q-8 0-13-5l-164-164q-5-5-5-13t5-13l164-164q5-5 13-5 7 0 12 5t5 12zM1024 749v109q0 7-5 12t-12 5h-987q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h987q7 0 12 5t5 12zM1024 530v109q0 7-5 12t-12 5h-621q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h621q7 0 12 5t5 12zM1024 310v109q0 7-5 12t-12 5h-621q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h621q7 0 12 5t5 12zM1024 91v109q0 7-5 12t-12 5h-987q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h987q7 0 12 5t5 12z"); - //span.appendChild(sym); - return span; - } - // Create an icon for a heading at the given level heading(level: number) { return { @@ -156,10 +233,8 @@ export class TooltipTextMenu { let left = Math.max((start.left + end.left) / 2, start.left + 3) this.tooltip.style.left = (left - box.left) + "px" //let width = Math.abs(start.left - end.left) / 2; - let width = 8 * 16 + 15; + let width = 220; let mid = Math.min(start.left, end.left) + width; - - //THIS WIDTH IS 15 * NUMBER OF ICONS + 15 this.tooltip.style.width = width + "px"; this.tooltip.style.bottom = (box.bottom - start.top) + "px"; } |