aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/TooltipTextMenu.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util/TooltipTextMenu.tsx')
-rw-r--r--src/client/util/TooltipTextMenu.tsx189
1 files changed, 135 insertions, 54 deletions
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 48f835a0f..3869db41a 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -1,19 +1,23 @@
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");
import { library } from '@fortawesome/fontawesome-svg-core';
import { wrapInList, bulletList, liftListItem, listItem } from 'prosemirror-schema-list';
-import { faListUl } from '@fortawesome/free-solid-svg-icons';
+import {
+ faListUl,
+} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { FieldViewProps } from "../views/nodes/FieldView";
+import { throwStatement } from "babel-types";
const SVG = "http://www.w3.org/2000/svg";
@@ -22,8 +26,14 @@ export class TooltipTextMenu {
private tooltip: HTMLElement;
private num_icons = 0;
-
- constructor(view: EditorView) {
+ private view: EditorView;
+ private fontStyles: MarkType[];
+ private fontSizes: MarkType[];
+ private editorProps: FieldViewProps;
+
+ constructor(view: EditorView, editorProps: FieldViewProps) {
+ this.view = view;
+ this.editorProps = editorProps;
this.tooltip = document.createElement("div");
this.tooltip.className = "tooltipMenu";
@@ -32,7 +42,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") },
@@ -42,44 +51,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 of ranges) {
+ let { $from, $to } = 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 = {};
@@ -98,30 +205,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 {
@@ -152,14 +235,12 @@ export class TooltipTextMenu {
// Find a center-ish x position from the selection endpoints (when
// crossing lines, end may be more to the left)
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;
+ this.tooltip.style.left = (left - box.left) * this.editorProps.ScreenToLocalTransform().Scale + "px";
+ let width = Math.abs(start.left - end.left) / 2 * this.editorProps.ScreenToLocalTransform().Scale;
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";
+ this.tooltip.style.width = 220 + "px";
+ this.tooltip.style.bottom = (box.bottom - start.top) * this.editorProps.ScreenToLocalTransform().Scale + "px";
}
destroy() { this.tooltip.remove(); }