From 4e45ad641bd34c4703188e69a93a23243f3659a4 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 10 Apr 2019 21:35:12 -0400
Subject: fixed text menu and text dragging.

---
 src/client/util/TooltipTextMenu.tsx | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index bd5753093..7951e5686 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -12,19 +12,23 @@ const { toggleMark, setBlockType, wrapIn } = require("prosemirror-commands");
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { wrapInList, bulletList } from 'prosemirror-schema-list';
 import { faListUl } from '@fortawesome/free-solid-svg-icons';
+import { FieldViewProps } from "../views/nodes/FieldView";
+import { throwStatement } from "babel-types";
 
 
 //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
 export class TooltipTextMenu {
 
     private tooltip: HTMLElement;
+    private editorProps: FieldViewProps;
 
-    constructor(view: EditorView) {
+    constructor(view: EditorView, editorProps: FieldViewProps) {
+        this.editorProps = editorProps;
         this.tooltip = document.createElement("div");
         this.tooltip.className = "tooltipMenu";
 
         //add the div which is the tooltip
-        view.dom.parentNode!.appendChild(this.tooltip);
+        view.dom.parentNode!.parentNode!.appendChild(this.tooltip);
 
         //add additional icons
         library.add(faListUl);
@@ -124,13 +128,13 @@ 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;
+        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 = 122 + "px";
-        this.tooltip.style.bottom = (box.bottom - start.top) + "px";
+        this.tooltip.style.bottom = (box.bottom - start.top) * this.editorProps.ScreenToLocalTransform().Scale + "px";
     }
 
     destroy() { this.tooltip.remove(); }
-- 
cgit v1.2.3-70-g09d2


From 15514b0f3d685764d1bd7ebeac9cdee1f778e184 Mon Sep 17 00:00:00 2001
From: laurawilsonri <laura_wilson@brown.edu>
Date: Thu, 11 Apr 2019 12:06:46 -0400
Subject: font style and size dropdowns work

---
 package.json                                | 332 +++++++++---------
 src/client/util/RichTextSchema.tsx          | 507 ++++++++++++++++------------
 src/client/util/TooltipTextMenu.scss        | 238 ++++++++++++-
 src/client/util/TooltipTextMenu.tsx         | 173 +++++++---
 src/client/views/nodes/FormattedTextBox.tsx |   7 +-
 5 files changed, 830 insertions(+), 427 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/package.json b/package.json
index 135bd4a91..11eb6f0f5 100644
--- a/package.json
+++ b/package.json
@@ -1,168 +1,168 @@
 {
-  "name": "dash",
-  "version": "1.0.0",
-  "description": "",
-  "main": "index.js",
-  "scripts": {
-    "start": "nodemon --watch src/server/**/*.ts --exec ts-node src/server/index.ts",
-    "build": "webpack --env production",
-    "test": "mocha -r ts-node/register test/**/*.ts",
-    "tsc": "tsc"
-  },
-  "devDependencies": {
-    "@types/chai": "^4.1.7",
-    "@types/mocha": "^5.2.6",
-    "@types/react-dom": "^16.8.2",
-    "@types/webpack-dev-middleware": "^2.0.2",
-    "@types/webpack-hot-middleware": "^2.16.4",
-    "awesome-typescript-loader": "^5.2.1",
-    "chai": "^4.2.0",
-    "copy-webpack-plugin": "^4.6.0",
-    "css-loader": "^2.1.1",
-    "file-loader": "^3.0.1",
-    "mocha": "^5.2.0",
-    "sass-loader": "^7.1.0",
-    "scss-loader": "0.0.1",
-    "style-loader": "^0.23.1",
-    "ts-node": "^7.0.1",
-    "typescript": "^3.4.1",
-    "webpack": "^4.29.6",
-    "webpack-cli": "^3.2.3",
-    "webpack-dev-middleware": "^3.6.1",
-    "webpack-dev-server": "^3.2.1",
-    "webpack-hot-middleware": "^2.24.3"
-  },
-  "dependencies": {
-    "@fortawesome/fontawesome-free-solid": "^5.0.13",
-    "@fortawesome/fontawesome-svg-core": "^1.2.15",
-    "@fortawesome/free-solid-svg-icons": "^5.7.2",
-    "@fortawesome/react-fontawesome": "^0.1.4",
-    "@hig/flyout": "^1.0.3",
-    "@hig/theme-context": "^2.1.3",
-    "@hig/theme-data": "^2.3.3",
-    "@trendmicro/react-dropdown": "^1.3.0",
-    "@types/async": "^2.4.1",
-    "@types/bcrypt-nodejs": "0.0.30",
-    "@types/bluebird": "^3.5.25",
-    "@types/body-parser": "^1.17.0",
-    "@types/connect-flash": "0.0.34",
-    "@types/cookie-parser": "^1.4.1",
-    "@types/cookie-session": "^2.0.36",
-    "@types/d3-format": "^1.3.1",
-    "@types/express": "^4.16.1",
-    "@types/express-flash": "0.0.0",
-    "@types/express-session": "^1.15.12",
-    "@types/express-validator": "^3.0.0",
-    "@types/formidable": "^1.0.31",
-    "@types/jquery": "^3.3.29",
-    "@types/jsonwebtoken": "^8.3.2",
-    "@types/lodash": "^4.14.121",
-    "@types/mobile-detect": "^1.3.4",
-    "@types/mongodb": "^3.1.22",
-    "@types/mongoose": "^5.3.21",
-    "@types/node": "^10.12.30",
-    "@types/nodemailer": "^4.6.6",
-    "@types/passport": "^1.0.0",
-    "@types/passport-local": "^1.0.33",
-    "@types/prosemirror-commands": "^1.0.1",
-    "@types/prosemirror-history": "^1.0.1",
-    "@types/prosemirror-inputrules": "^1.0.2",
-    "@types/prosemirror-keymap": "^1.0.1",
-    "@types/prosemirror-menu": "^1.0.1",
-    "@types/prosemirror-model": "^1.7.0",
-    "@types/prosemirror-schema-basic": "^1.0.1",
-    "@types/prosemirror-schema-list": "^1.0.1",
-    "@types/prosemirror-state": "^1.2.3",
-    "@types/prosemirror-transform": "^1.1.0",
-    "@types/prosemirror-view": "^1.3.1",
-    "@types/pug": "^2.0.4",
-    "@types/react": "^16.8.7",
-    "@types/react-color": "^2.14.1",
-    "@types/react-measure": "^2.0.4",
-    "@types/react-table": "^6.7.22",
-    "@types/request": "^2.48.1",
-    "@types/request-promise": "^4.1.42",
-    "@types/socket.io": "^2.1.2",
-    "@types/socket.io-client": "^1.4.32",
-    "@types/typescript": "^2.0.0",
-    "@types/uuid": "^3.4.4",
-    "@types/webpack": "^4.4.25",
-    "async": "^2.6.2",
-    "babel-runtime": "^6.26.0",
-    "bcrypt-nodejs": "0.0.3",
-    "bluebird": "^3.5.3",
-    "body-parser": "^1.18.3",
-    "bootstrap": "^4.3.1",
-    "class-transformer": "^0.2.0",
-    "connect-flash": "^0.1.1",
-    "connect-mongo": "^2.0.3",
-    "cookie-parser": "^1.4.4",
-    "cookie-session": "^2.0.0-beta.3",
-    "crypto-browserify": "^3.11.0",
-    "d3-format": "^1.3.2",
-    "express": "^4.16.4",
-    "express-flash": "0.0.2",
-    "express-session": "^1.15.6",
-    "express-validator": "^5.3.1",
-    "expressjs": "^1.0.1",
-    "flexlayout-react": "^0.3.3",
-    "font-awesome": "^4.7.0",
-    "formidable": "^1.2.1",
-    "golden-layout": "^1.5.9",
-    "html-to-image": "^0.1.0",
-    "i": "^0.3.6",
-    "jsonwebtoken": "^8.5.0",
-    "jsx-to-string": "^1.4.0",
-    "lodash": "^4.17.11",
-    "mobile-detect": "^1.4.3",
-    "mobx": "^5.9.0",
-    "mobx-react": "^5.3.5",
-    "mobx-react-devtools": "^6.1.1",
-    "mongodb": "^3.1.13",
-    "mongoose": "^5.4.18",
-    "node-sass": "^4.11.0",
-    "nodemailer": "^5.1.1",
-    "nodemon": "^1.18.10",
-    "normalize.css": "^8.0.1",
-    "npm": "^6.9.0",
-    "passport": "^0.4.0",
-    "passport-local": "^1.0.0",
-    "prosemirror-commands": "^1.0.7",
-    "prosemirror-example-setup": "^1.0.1",
-    "prosemirror-history": "^1.0.4",
-    "prosemirror-keymap": "^1.0.1",
-    "prosemirror-model": "^1.7.0",
-    "prosemirror-schema-basic": "^1.0.0",
-    "prosemirror-schema-list": "^1.0.2",
-    "prosemirror-state": "^1.2.2",
-    "prosemirror-transform": "^1.1.3",
-    "prosemirror-view": "^1.8.3",
-    "pug": "^2.0.3",
-    "raw-loader": "^1.0.0",
-    "react": "^16.8.4",
-    "react-bootstrap": "^1.0.0-beta.5",
-    "react-bootstrap-dropdown-menu": "^1.1.15",
-    "react-color": "^2.17.0",
-    "react-dimensions": "^1.3.1",
-    "react-dom": "^16.8.4",
-    "react-golden-layout": "^1.0.6",
-    "react-image-lightbox": "^5.1.0",
-    "react-jsx-parser": "^1.15.0",
-    "react-measure": "^2.2.4",
-    "react-mosaic": "0.0.20",
-    "react-pdf": "^4.0.2",
-    "react-pdf-highlighter": "^2.1.2",
-    "react-pdf-js": "^4.0.2",
-    "react-simple-dropdown": "^3.2.3",
-    "react-split-pane": "^0.1.85",
-    "react-table": "^6.9.2",
-    "request": "^2.88.0",
-    "request-promise": "^4.2.4",
-    "socket.io": "^2.2.0",
-    "socket.io-client": "^2.2.0",
-    "typescript-collections": "^1.3.2",
-    "url-loader": "^1.1.2",
-    "uuid": "^3.3.2",
-    "xoauth2": "^1.2.0"
-  }
+    "name": "dash",
+    "version": "1.0.0",
+    "description": "",
+    "main": "index.js",
+    "scripts": {
+        "start": "nodemon --watch src/server/**/*.ts --exec ts-node src/server/index.ts",
+        "build": "webpack --env production",
+        "test": "mocha -r ts-node/register test/**/*.ts",
+        "tsc": "tsc"
+    },
+    "devDependencies": {
+        "@types/chai": "^4.1.7",
+        "@types/mocha": "^5.2.6",
+        "@types/react-dom": "^16.8.2",
+        "@types/webpack-dev-middleware": "^2.0.2",
+        "@types/webpack-hot-middleware": "^2.16.4",
+        "awesome-typescript-loader": "^5.2.1",
+        "chai": "^4.2.0",
+        "copy-webpack-plugin": "^4.6.0",
+        "css-loader": "^2.1.1",
+        "file-loader": "^3.0.1",
+        "mocha": "^5.2.0",
+        "sass-loader": "^7.1.0",
+        "scss-loader": "0.0.1",
+        "style-loader": "^0.23.1",
+        "ts-node": "^7.0.1",
+        "typescript": "^3.4.1",
+        "webpack": "^4.29.6",
+        "webpack-cli": "^3.2.3",
+        "webpack-dev-middleware": "^3.6.1",
+        "webpack-dev-server": "^3.2.1",
+        "webpack-hot-middleware": "^2.24.3"
+    },
+    "dependencies": {
+        "@fortawesome/fontawesome-free-solid": "^5.0.13",
+        "@fortawesome/fontawesome-svg-core": "^1.2.15",
+        "@fortawesome/free-solid-svg-icons": "^5.7.2",
+        "@fortawesome/react-fontawesome": "^0.1.4",
+        "@hig/flyout": "^1.0.3",
+        "@hig/theme-context": "^2.1.3",
+        "@hig/theme-data": "^2.3.3",
+        "@trendmicro/react-dropdown": "^1.3.0",
+        "@types/async": "^2.4.1",
+        "@types/bcrypt-nodejs": "0.0.30",
+        "@types/bluebird": "^3.5.25",
+        "@types/body-parser": "^1.17.0",
+        "@types/connect-flash": "0.0.34",
+        "@types/cookie-parser": "^1.4.1",
+        "@types/cookie-session": "^2.0.36",
+        "@types/d3-format": "^1.3.1",
+        "@types/express": "^4.16.1",
+        "@types/express-flash": "0.0.0",
+        "@types/express-session": "^1.15.12",
+        "@types/express-validator": "^3.0.0",
+        "@types/formidable": "^1.0.31",
+        "@types/jquery": "^3.3.29",
+        "@types/jsonwebtoken": "^8.3.2",
+        "@types/lodash": "^4.14.121",
+        "@types/mobile-detect": "^1.3.4",
+        "@types/mongodb": "^3.1.22",
+        "@types/mongoose": "^5.3.21",
+        "@types/node": "^10.12.30",
+        "@types/nodemailer": "^4.6.6",
+        "@types/passport": "^1.0.0",
+        "@types/passport-local": "^1.0.33",
+        "@types/prosemirror-commands": "^1.0.1",
+        "@types/prosemirror-history": "^1.0.1",
+        "@types/prosemirror-inputrules": "^1.0.2",
+        "@types/prosemirror-keymap": "^1.0.1",
+        "@types/prosemirror-menu": "^1.0.1",
+        "@types/prosemirror-model": "^1.7.0",
+        "@types/prosemirror-schema-basic": "^1.0.1",
+        "@types/prosemirror-schema-list": "^1.0.1",
+        "@types/prosemirror-state": "^1.2.3",
+        "@types/prosemirror-transform": "^1.1.0",
+        "@types/prosemirror-view": "^1.3.1",
+        "@types/pug": "^2.0.4",
+        "@types/react": "^16.8.7",
+        "@types/react-color": "^2.14.1",
+        "@types/react-measure": "^2.0.4",
+        "@types/react-table": "^6.7.22",
+        "@types/request": "^2.48.1",
+        "@types/request-promise": "^4.1.42",
+        "@types/socket.io": "^2.1.2",
+        "@types/socket.io-client": "^1.4.32",
+        "@types/typescript": "^2.0.0",
+        "@types/uuid": "^3.4.4",
+        "@types/webpack": "^4.4.25",
+        "async": "^2.6.2",
+        "babel-runtime": "^6.26.0",
+        "bcrypt-nodejs": "0.0.3",
+        "bluebird": "^3.5.3",
+        "body-parser": "^1.18.3",
+        "bootstrap": "^4.3.1",
+        "class-transformer": "^0.2.0",
+        "connect-flash": "^0.1.1",
+        "connect-mongo": "^2.0.3",
+        "cookie-parser": "^1.4.4",
+        "cookie-session": "^2.0.0-beta.3",
+        "crypto-browserify": "^3.11.0",
+        "d3-format": "^1.3.2",
+        "express": "^4.16.4",
+        "express-flash": "0.0.2",
+        "express-session": "^1.15.6",
+        "express-validator": "^5.3.1",
+        "expressjs": "^1.0.1",
+        "flexlayout-react": "^0.3.3",
+        "font-awesome": "^4.7.0",
+        "formidable": "^1.2.1",
+        "golden-layout": "^1.5.9",
+        "html-to-image": "^0.1.0",
+        "i": "^0.3.6",
+        "jsonwebtoken": "^8.5.0",
+        "jsx-to-string": "^1.4.0",
+        "lodash": "^4.17.11",
+        "mobile-detect": "^1.4.3",
+        "mobx": "^5.9.0",
+        "mobx-react": "^5.3.5",
+        "mobx-react-devtools": "^6.1.1",
+        "mongodb": "^3.1.13",
+        "mongoose": "^5.4.18",
+        "node-sass": "^4.11.0",
+        "nodemailer": "^5.1.1",
+        "nodemon": "^1.18.10",
+        "normalize.css": "^8.0.1",
+        "npm": "^6.9.0",
+        "passport": "^0.4.0",
+        "passport-local": "^1.0.0",
+        "prosemirror-commands": "^1.0.7",
+        "prosemirror-example-setup": "^1.0.1",
+        "prosemirror-history": "^1.0.4",
+        "prosemirror-keymap": "^1.0.1",
+        "prosemirror-model": "^1.7.0",
+        "prosemirror-schema-basic": "^1.0.0",
+        "prosemirror-schema-list": "^1.0.2",
+        "prosemirror-state": "^1.2.2",
+        "prosemirror-transform": "^1.1.3",
+        "prosemirror-view": "^1.8.3",
+        "pug": "^2.0.3",
+        "raw-loader": "^1.0.0",
+        "react": "^16.8.4",
+        "react-bootstrap": "^1.0.0-beta.5",
+        "react-bootstrap-dropdown-menu": "^1.1.15",
+        "react-color": "^2.17.0",
+        "react-dimensions": "^1.3.1",
+        "react-dom": "^16.8.4",
+        "react-golden-layout": "^1.0.6",
+        "react-image-lightbox": "^5.1.0",
+        "react-jsx-parser": "^1.15.0",
+        "react-measure": "^2.2.4",
+        "react-mosaic": "0.0.20",
+        "react-pdf": "^4.0.2",
+        "react-pdf-highlighter": "^2.1.2",
+        "react-pdf-js": "^4.0.2",
+        "react-simple-dropdown": "^3.2.3",
+        "react-split-pane": "^0.1.85",
+        "react-table": "^6.9.2",
+        "request": "^2.88.0",
+        "request-promise": "^4.2.4",
+        "socket.io": "^2.2.0",
+        "socket.io-client": "^2.2.0",
+        "typescript-collections": "^1.3.2",
+        "url-loader": "^1.1.2",
+        "uuid": "^3.3.2",
+        "xoauth2": "^1.2.0"
+    }
 }
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 489c22a57..765ac0ae3 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -7,134 +7,134 @@ import { EditorState, Transaction, NodeSelection, } from "prosemirror-state";
 import { EditorView, } from "prosemirror-view";
 
 const pDOM: DOMOutputSpecArray = ["p", 0], blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"],
-  preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]
+    preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]
 
 // :: Object
 // [Specs](#model.NodeSpec) for the nodes defined in this schema.
 export const nodes: { [index: string]: NodeSpec } = {
-  // :: NodeSpec The top level document node.
-  doc: {
-    content: "block+"
-  },
-
-  // :: NodeSpec A plain paragraph textblock. Represented in the DOM
-  // as a `<p>` element.
-  paragraph: {
-    content: "inline*",
-    group: "block",
-    parseDOM: [{ tag: "p" }],
-    toDOM() { return pDOM }
-  },
-
-  // :: NodeSpec A blockquote (`<blockquote>`) wrapping one or more blocks.
-  blockquote: {
-    content: "block+",
-    group: "block",
-    defining: true,
-    parseDOM: [{ tag: "blockquote" }],
-    toDOM() { return blockquoteDOM }
-  },
-
-  // :: NodeSpec A horizontal rule (`<hr>`).
-  horizontal_rule: {
-    group: "block",
-    parseDOM: [{ tag: "hr" }],
-    toDOM() { return hrDOM }
-  },
-
-  // :: NodeSpec A heading textblock, with a `level` attribute that
-  // should hold the number 1 to 6. Parsed and serialized as `<h1>` to
-  // `<h6>` elements.
-  heading: {
-    attrs: { level: { default: 1 } },
-    content: "inline*",
-    group: "block",
-    defining: true,
-    parseDOM: [{ tag: "h1", attrs: { level: 1 } },
-    { tag: "h2", attrs: { level: 2 } },
-    { tag: "h3", attrs: { level: 3 } },
-    { tag: "h4", attrs: { level: 4 } },
-    { tag: "h5", attrs: { level: 5 } },
-    { tag: "h6", attrs: { level: 6 } }],
-    toDOM(node: any) { return ["h" + node.attrs.level, 0] }
-  },
-
-  // :: NodeSpec A code listing. Disallows marks or non-text inline
-  // nodes by default. Represented as a `<pre>` element with a
-  // `<code>` element inside of it.
-  code_block: {
-    content: "text*",
-    marks: "",
-    group: "block",
-    code: true,
-    defining: true,
-    parseDOM: [{ tag: "pre", preserveWhitespace: "full" }],
-    toDOM() { return preDOM }
-  },
-
-  // :: NodeSpec The text node.
-  text: {
-    group: "inline"
-  },
-
-  // :: NodeSpec An inline image (`<img>`) node. Supports `src`,
-  // `alt`, and `href` attributes. The latter two default to the empty
-  // string.
-  image: {
-    inline: true,
-    attrs: {
-      src: {},
-      alt: { default: null },
-      title: { default: null }
-    },
-    group: "inline",
-    draggable: true,
-    parseDOM: [{
-      tag: "img[src]", getAttrs(dom: any) {
-        return {
-          src: dom.getAttribute("src"),
-          title: dom.getAttribute("title"),
-          alt: dom.getAttribute("alt")
-        }
-      }
-    }],
-    toDOM(node: any) { return ["img", node.attrs] }
-  },
-
-  // :: NodeSpec A hard line break, represented in the DOM as `<br>`.
-  hard_break: {
-    inline: true,
-    group: "inline",
-    selectable: false,
-    parseDOM: [{ tag: "br" }],
-    toDOM() { return brDOM }
-  },
-
-  ordered_list: {
-    ...orderedList,
-    content: 'list_item+',
-    group: 'block'
-  },
-  //this doesn't currently work for some reason
-  bullet_list: {
-    ...bulletList,
-    content: 'list_item+',
-    group: 'block',
-    // parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }],
-    // toDOM() { return ulDOM }
-  },
-  //bullet_list: {
-  //  content: 'list_item+',
-  // group: 'block',
-  //active: blockActive(schema.nodes.bullet_list),
-  //enable: wrapInList(schema.nodes.bullet_list),
-  //run: wrapInList(schema.nodes.bullet_list),
-  //select: state => true,
-  // },
-  list_item: {
-    ...listItem,
-    content: 'paragraph block*'
-  }
+    // :: NodeSpec The top level document node.
+    doc: {
+        content: "block+"
+    },
+
+    // :: NodeSpec A plain paragraph textblock. Represented in the DOM
+    // as a `<p>` element.
+    paragraph: {
+        content: "inline*",
+        group: "block",
+        parseDOM: [{ tag: "p" }],
+        toDOM() { return pDOM }
+    },
+
+    // :: NodeSpec A blockquote (`<blockquote>`) wrapping one or more blocks.
+    blockquote: {
+        content: "block+",
+        group: "block",
+        defining: true,
+        parseDOM: [{ tag: "blockquote" }],
+        toDOM() { return blockquoteDOM }
+    },
+
+    // :: NodeSpec A horizontal rule (`<hr>`).
+    horizontal_rule: {
+        group: "block",
+        parseDOM: [{ tag: "hr" }],
+        toDOM() { return hrDOM }
+    },
+
+    // :: NodeSpec A heading textblock, with a `level` attribute that
+    // should hold the number 1 to 6. Parsed and serialized as `<h1>` to
+    // `<h6>` elements.
+    heading: {
+        attrs: { level: { default: 1 } },
+        content: "inline*",
+        group: "block",
+        defining: true,
+        parseDOM: [{ tag: "h1", attrs: { level: 1 } },
+        { tag: "h2", attrs: { level: 2 } },
+        { tag: "h3", attrs: { level: 3 } },
+        { tag: "h4", attrs: { level: 4 } },
+        { tag: "h5", attrs: { level: 5 } },
+        { tag: "h6", attrs: { level: 6 } }],
+        toDOM(node: any) { return ["h" + node.attrs.level, 0] }
+    },
+
+    // :: NodeSpec A code listing. Disallows marks or non-text inline
+    // nodes by default. Represented as a `<pre>` element with a
+    // `<code>` element inside of it.
+    code_block: {
+        content: "text*",
+        marks: "",
+        group: "block",
+        code: true,
+        defining: true,
+        parseDOM: [{ tag: "pre", preserveWhitespace: "full" }],
+        toDOM() { return preDOM }
+    },
+
+    // :: NodeSpec The text node.
+    text: {
+        group: "inline"
+    },
+
+    // :: NodeSpec An inline image (`<img>`) node. Supports `src`,
+    // `alt`, and `href` attributes. The latter two default to the empty
+    // string.
+    image: {
+        inline: true,
+        attrs: {
+            src: {},
+            alt: { default: null },
+            title: { default: null }
+        },
+        group: "inline",
+        draggable: true,
+        parseDOM: [{
+            tag: "img[src]", getAttrs(dom: any) {
+                return {
+                    src: dom.getAttribute("src"),
+                    title: dom.getAttribute("title"),
+                    alt: dom.getAttribute("alt")
+                }
+            }
+        }],
+        toDOM(node: any) { return ["img", node.attrs] }
+    },
+
+    // :: NodeSpec A hard line break, represented in the DOM as `<br>`.
+    hard_break: {
+        inline: true,
+        group: "inline",
+        selectable: false,
+        parseDOM: [{ tag: "br" }],
+        toDOM() { return brDOM }
+    },
+
+    ordered_list: {
+        ...orderedList,
+        content: 'list_item+',
+        group: 'block'
+    },
+    //this doesn't currently work for some reason
+    bullet_list: {
+        ...bulletList,
+        content: 'list_item+',
+        group: 'block',
+        // parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }],
+        // toDOM() { return ulDOM }
+    },
+    //bullet_list: {
+    //  content: 'list_item+',
+    // group: 'block',
+    //active: blockActive(schema.nodes.bullet_list),
+    //enable: wrapInList(schema.nodes.bullet_list),
+    //run: wrapInList(schema.nodes.bullet_list),
+    //select: state => true,
+    // },
+    list_item: {
+        ...listItem,
+        content: 'paragraph block*'
+    }
 }
 
 const emDOM: DOMOutputSpecArray = ["em", 0];
@@ -144,92 +144,179 @@ const underlineDOM: DOMOutputSpecArray = ["underline", 0];
 
 // :: Object [Specs](#model.MarkSpec) for the marks in the schema.
 export const marks: { [index: string]: MarkSpec } = {
-  // :: MarkSpec A link. Has `href` and `title` attributes. `title`
-  // defaults to the empty string. Rendered and parsed as an `<a>`
-  // element.
-  link: {
-    attrs: {
-      href: {},
-      title: { default: null }
-    },
-    inclusive: false,
-    parseDOM: [{
-      tag: "a[href]", getAttrs(dom: any) {
-        return { href: dom.getAttribute("href"), title: dom.getAttribute("title") }
-      }
-    }],
-    toDOM(node: any) { return ["a", node.attrs, 0] }
-  },
-
-  // :: MarkSpec An emphasis mark. Rendered as an `<em>` element.
-  // Has parse rules that also match `<i>` and `font-style: italic`.
-  em: {
-    parseDOM: [{ tag: "i" }, { tag: "em" }, { style: "font-style=italic" }],
-    toDOM() { return emDOM }
-  },
-
-  // :: MarkSpec A strong mark. Rendered as `<strong>`, parse rules
-  // also match `<b>` and `font-weight: bold`.
-  strong: {
-    parseDOM: [{ tag: "strong" },
-    { tag: "b" },
-    { style: "font-weight" }],
-    toDOM() { return strongDOM }
-  },
-
-  underline: {
-    parseDOM: [
-      { tag: 'u' },
-      { style: 'text-decoration=underline' }
-    ],
-    toDOM: () => ['span', {
-      style: 'text-decoration:underline'
-    }]
-  },
-
-  strikethrough: {
-    parseDOM: [
-      { tag: 'strike' },
-      { style: 'text-decoration=line-through' },
-      { style: 'text-decoration-line=line-through' }
-    ],
-    toDOM: () => ['span', {
-      style: 'text-decoration-line:line-through'
-    }]
-  },
-
-  subscript: {
-    excludes: 'superscript',
-    parseDOM: [
-      { tag: 'sub' },
-      { style: 'vertical-align=sub' }
-    ],
-    toDOM: () => ['sub']
-  },
-
-  superscript: {
-    excludes: 'subscript',
-    parseDOM: [
-      { tag: 'sup' },
-      { style: 'vertical-align=super' }
-    ],
-    toDOM: () => ['sup']
-  },
-
-
-  // :: MarkSpec Code font mark. Represented as a `<code>` element.
-  code: {
-    parseDOM: [{ tag: "code" }],
-    toDOM() { return codeDOM }
-  },
-
-
-  timesNewRoman: {
-    parseDOM: [{ style: 'font-family: "Times New Roman", Times, serif;' }],
-    toDOM: () => ['span', {
-      style: 'font-family: "Times New Roman", Times, serif;'
-    }]
-  },
+    // :: MarkSpec A link. Has `href` and `title` attributes. `title`
+    // defaults to the empty string. Rendered and parsed as an `<a>`
+    // element.
+    link: {
+        attrs: {
+            href: {},
+            title: { default: null }
+        },
+        inclusive: false,
+        parseDOM: [{
+            tag: "a[href]", getAttrs(dom: any) {
+                return { href: dom.getAttribute("href"), title: dom.getAttribute("title") }
+            }
+        }],
+        toDOM(node: any) { return ["a", node.attrs, 0] }
+    },
+
+    // :: MarkSpec An emphasis mark. Rendered as an `<em>` element.
+    // Has parse rules that also match `<i>` and `font-style: italic`.
+    em: {
+        parseDOM: [{ tag: "i" }, { tag: "em" }, { style: "font-style=italic" }],
+        toDOM() { return emDOM }
+    },
+
+    // :: MarkSpec A strong mark. Rendered as `<strong>`, parse rules
+    // also match `<b>` and `font-weight: bold`.
+    strong: {
+        parseDOM: [{ tag: "strong" },
+        { tag: "b" },
+        { style: "font-weight" }],
+        toDOM() { return strongDOM }
+    },
+
+    underline: {
+        parseDOM: [
+            { tag: 'u' },
+            { style: 'text-decoration=underline' }
+        ],
+        toDOM: () => ['span', {
+            style: 'text-decoration:underline'
+        }]
+    },
+
+    strikethrough: {
+        parseDOM: [
+            { tag: 'strike' },
+            { style: 'text-decoration=line-through' },
+            { style: 'text-decoration-line=line-through' }
+        ],
+        toDOM: () => ['span', {
+            style: 'text-decoration-line:line-through'
+        }]
+    },
+
+    subscript: {
+        excludes: 'superscript',
+        parseDOM: [
+            { tag: 'sub' },
+            { style: 'vertical-align=sub' }
+        ],
+        toDOM: () => ['sub']
+    },
+
+    superscript: {
+        excludes: 'subscript',
+        parseDOM: [
+            { tag: 'sup' },
+            { style: 'vertical-align=super' }
+        ],
+        toDOM: () => ['sup']
+    },
+
+
+    // :: MarkSpec Code font mark. Represented as a `<code>` element.
+    code: {
+        parseDOM: [{ tag: "code" }],
+        toDOM() { return codeDOM }
+    },
+
+
+    /* FONTS */
+    timesNewRoman: {
+        parseDOM: [{ style: 'font-family: "Times New Roman", Times, serif;' }],
+        toDOM: () => ['span', {
+            style: 'font-family: "Times New Roman", Times, serif;'
+        }]
+    },
+
+    arial: {
+        parseDOM: [{ style: 'font-family: Arial, Helvetica, sans-serif;' }],
+        toDOM: () => ['span', {
+            style: 'font-family: Arial, Helvetica, sans-serif;'
+        }]
+    },
+
+    georgia: {
+        parseDOM: [{ style: 'font-family: Georgia, serif;' }],
+        toDOM: () => ['span', {
+            style: 'font-family: Georgia, serif;'
+        }]
+    },
+
+    comicSans: {
+        parseDOM: [{ style: 'font-family: "Comic Sans MS", cursive, sans-serif;' }],
+        toDOM: () => ['span', {
+            style: 'font-family: "Comic Sans MS", cursive, sans-serif;'
+        }]
+    },
+
+    tahoma: {
+        parseDOM: [{ style: 'font-family: Tahoma, Geneva, sans-serif;' }],
+        toDOM: () => ['span', {
+            style: 'font-family: Tahoma, Geneva, sans-serif;'
+        }]
+    },
+
+    impact: {
+        parseDOM: [{ style: 'font-family: Impact, Charcoal, sans-serif;' }],
+        toDOM: () => ['span', {
+            style: 'font-family: Impact, Charcoal, sans-serif;'
+        }]
+    },
+
+    /** FONT SIZES */
+
+    p10: {
+        parseDOM: [{ style: 'font-size: 10px;' }],
+        toDOM: () => ['span', {
+            style: 'font-size: 10px;'
+        }]
+    },
+
+    p12: {
+        parseDOM: [{ style: 'font-size: 12px;' }],
+        toDOM: () => ['span', {
+            style: 'font-size: 12px;'
+        }]
+    },
+
+    p16: {
+        parseDOM: [{ style: 'font-size: 16px;' }],
+        toDOM: () => ['span', {
+            style: 'font-size: 16px;'
+        }]
+    },
+
+    p24: {
+        parseDOM: [{ style: 'font-size: 24px;' }],
+        toDOM: () => ['span', {
+            style: 'font-size: 24px;'
+        }]
+    },
+
+    p32: {
+        parseDOM: [{ style: 'font-size: 32px;' }],
+        toDOM: () => ['span', {
+            style: 'font-size: 32px;'
+        }]
+    },
+
+    p48: {
+        parseDOM: [{ style: 'font-size: 48px;' }],
+        toDOM: () => ['span', {
+            style: 'font-size: 48px;'
+        }]
+    },
+
+    p72: {
+        parseDOM: [{ style: 'font-size: 72px;' }],
+        toDOM: () => ['span', {
+            style: 'font-size: 72px;'
+        }]
+    },
 }
 
 // :: Schema
diff --git a/src/client/util/TooltipTextMenu.scss b/src/client/util/TooltipTextMenu.scss
index ea580d104..b23074239 100644
--- a/src/client/util/TooltipTextMenu.scss
+++ b/src/client/util/TooltipTextMenu.scss
@@ -1,5 +1,241 @@
 @import "../views/global_variables";
 
+.ProseMirror-textblock-dropdown {
+    min-width: 3em;
+  }
+  
+  .ProseMirror-menu {
+    margin: 0 -4px;
+    line-height: 1;
+  }
+  
+  .ProseMirror-tooltip .ProseMirror-menu {
+    width: -webkit-fit-content;
+    width: fit-content;
+    white-space: pre;
+  }
+  
+  .ProseMirror-menuitem {
+    margin-right: 3px;
+    display: inline-block;
+  }
+  
+  .ProseMirror-menuseparator {
+   // border-right: 1px solid #ddd;
+    margin-right: 3px;
+  }
+  
+  .ProseMirror-menu-dropdown, .ProseMirror-menu-dropdown-menu {
+    font-size: 90%;
+    white-space: nowrap;
+  }
+  
+  .ProseMirror-menu-dropdown {
+    vertical-align: 1px;
+    cursor: pointer;
+    position: relative;
+    padding-right: 15px;
+  }
+  
+  .ProseMirror-menu-dropdown-wrap {
+    padding: 1px 0 1px 4px;
+    display: inline-block;
+    position: relative;
+  }
+  
+  .ProseMirror-menu-dropdown:after {
+    content: "";
+    border-left: 4px solid transparent;
+    border-right: 4px solid transparent;
+    border-top: 4px solid currentColor;
+    opacity: .6;
+    position: absolute;
+    right: 4px;
+    top: calc(50% - 2px);
+  }
+  
+  .ProseMirror-menu-dropdown-menu, .ProseMirror-menu-submenu {
+    position: absolute;
+    background: $dark-color;
+    color:white;
+    border: 1px solid #aaa;
+    padding: 2px;
+  }
+  
+  .ProseMirror-menu-dropdown-menu {
+    z-index: 15;
+    min-width: 6em;
+  }
+  
+  .ProseMirror-menu-dropdown-item {
+    cursor: pointer;
+    padding: 2px 8px 2px 4px;
+    width: auto;
+  }
+  
+  .ProseMirror-menu-dropdown-item:hover {
+    background: #2e2b2b;
+  }
+  
+  .ProseMirror-menu-submenu-wrap {
+    position: relative;
+    margin-right: -4px;
+  }
+  
+  .ProseMirror-menu-submenu-label:after {
+    content: "";
+    border-top: 4px solid transparent;
+    border-bottom: 4px solid transparent;
+    border-left: 4px solid currentColor;
+    opacity: .6;
+    position: absolute;
+    right: 4px;
+    top: calc(50% - 4px);
+  }
+  
+  .ProseMirror-menu-submenu {
+    display: none;
+    min-width: 4em;
+    left: 100%;
+    top: -3px;
+  }
+  
+  .ProseMirror-menu-active {
+    background: #eee;
+    border-radius: 4px;
+  }
+  
+  .ProseMirror-menu-active {
+    background: #eee;
+    border-radius: 4px;
+  }
+  
+  .ProseMirror-menu-disabled {
+    opacity: .3;
+  }
+  
+  .ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu, .ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu {
+    display: block;
+  }
+  
+  .ProseMirror-menubar {
+    border-top-left-radius: inherit;
+    border-top-right-radius: inherit;
+    position: relative;
+    min-height: 1em;
+    color: white;
+    padding: 1px 6px;
+    top: 0; left: 0; right: 0;
+    border-bottom: 1px solid silver;
+    background:$dark-color;
+    z-index: 10;
+    -moz-box-sizing: border-box;
+    box-sizing: border-box;
+    overflow: visible;
+  }
+  
+  .ProseMirror-icon {
+    display: inline-block;
+    line-height: .8;
+    vertical-align: -2px; /* Compensate for padding */
+    padding: 2px 8px;
+    cursor: pointer;
+  }
+  
+  .ProseMirror-menu-disabled.ProseMirror-icon {
+    cursor: default;
+  }
+  
+  .ProseMirror-icon svg {
+    fill: currentColor;
+    height: 1em;
+  }
+  
+  .ProseMirror-icon span {
+    vertical-align: text-top;
+  }  
+.ProseMirror-example-setup-style hr {
+    padding: 2px 10px;
+    border: none;
+    margin: 1em 0;
+  }
+  
+  .ProseMirror-example-setup-style hr:after {
+    content: "";
+    display: block;
+    height: 1px;
+    background-color: silver;
+    line-height: 2px;
+  }
+  
+  .ProseMirror ul, .ProseMirror ol {
+    padding-left: 30px;
+  }
+  
+  .ProseMirror blockquote {
+    padding-left: 1em;
+    border-left: 3px solid #eee;
+    margin-left: 0; margin-right: 0;
+  }
+  
+  .ProseMirror-example-setup-style img {
+    cursor: default;
+  }
+  
+  .ProseMirror-prompt {
+    background: white;
+    padding: 5px 10px 5px 15px;
+    border: 1px solid silver;
+    position: fixed;
+    border-radius: 3px;
+    z-index: 11;
+    box-shadow: -.5px 2px 5px rgba(0, 0, 0, .2);
+  }
+  
+  .ProseMirror-prompt h5 {
+    margin: 0;
+    font-weight: normal;
+    font-size: 100%;
+    color: #444;
+  }
+  
+  .ProseMirror-prompt input[type="text"],
+  .ProseMirror-prompt textarea {
+    background: #eee;
+    border: none;
+    outline: none;
+  }
+  
+  .ProseMirror-prompt input[type="text"] {
+    padding: 0 4px;
+  }
+  
+  .ProseMirror-prompt-close {
+    position: absolute;
+    left: 2px; top: 1px;
+    color: #666;
+    border: none; background: transparent; padding: 0;
+  }
+  
+  .ProseMirror-prompt-close:after {
+    content: "✕";
+    font-size: 12px;
+  }
+  
+  .ProseMirror-invalid {
+    background: #ffc;
+    border: 1px solid #cc7;
+    border-radius: 4px;
+    padding: 5px 10px;
+    position: absolute;
+    min-width: 10em;
+  }
+  
+  .ProseMirror-prompt-buttons {
+    margin-top: 5px;
+    display: none;
+  }
+
 .tooltipMenu {
     position: absolute;
     z-index: 20;
@@ -39,7 +275,7 @@
     display: inline-block;
     border-right: 1px solid rgba(0, 0, 0, 0.2);
     //color: rgb(19, 18, 18);
-    color: $light-color;
+    color: white;
     line-height: 1;
     padding: 0px 2px;
     margin: 1px;
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";
     }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index e59179874..fdb1b97be 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -74,7 +74,12 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
                 history(),
                 keymap({ "Mod-z": undo, "Mod-y": redo }),
                 keymap(baseKeymap),
-                this.tooltipMenuPlugin()
+                this.tooltipMenuPlugin(),
+                new Plugin({
+                    props: {
+                        attributes: { class: "ProseMirror-example-setup-style" }
+                    }
+                })
             ]
         };
 
-- 
cgit v1.2.3-70-g09d2

