From 1ebf40ba117ec063ff58ee750e6cc57aa3f3abfb Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 3 Apr 2019 15:49:42 -0400
Subject: fixed pen ink.  fixed alias dropping.  switched PDFs to use svg

---
 src/client/views/nodes/PDFBox.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 28a1f9757..3cb3cf782 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -439,7 +439,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
         let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField);
         let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight;
         return <div className="pdfBox-contentContainer" key="container" style={{ transform: `scale(${xf}, ${xf})` }}>
-            <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`}>
+            <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`} renderMode="svg">
                 <Measure onResize={this.setScaling}>
                     {({ measureRef }) =>
                         <div className="pdfBox-page" ref={measureRef}>
-- 
cgit v1.2.3-70-g09d2


From e70be930dc7c8ff1e999bf163bcbb511a60bae6f Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 4 Apr 2019 17:46:33 -0400
Subject: added close button and fixed some async stuff.

---
 src/client/views/DocumentDecorations.scss          | 17 +++++++---
 src/client/views/DocumentDecorations.tsx           | 38 +++++++++++++++++++---
 .../views/collections/CollectionViewBase.tsx       |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  9 +++--
 .../collections/collectionFreeForm/MarqueeView.tsx |  1 +
 src/client/views/nodes/PDFBox.tsx                  | 10 +++---
 6 files changed, 60 insertions(+), 17 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 080c9fa1e..d7137d7a2 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -7,7 +7,7 @@
     display: grid;
     z-index: 1000;
     grid-template-rows: 20px 8px 1fr 8px;
-    grid-template-columns: 8px 8px 1fr 8px;
+    grid-template-columns: 8px 8px 1fr 8px 8px;
     pointer-events: none;
 
     #documentDecorations-centerCont {
@@ -30,13 +30,14 @@
     #documentDecorations-topResizer,
     #documentDecorations-bottomResizer {
         grid-column-start: 2;
-        grid-column-end: 4;
+        grid-column-end: 5;
     }
 
     #documentDecorations-bottomRightResizer,
     #documentDecorations-topRightResizer,
     #documentDecorations-rightResizer {
-        grid-column:4
+        grid-column-start:5;
+        grid-column-end:7;
     }
 
     #documentDecorations-topLeftResizer,
@@ -61,11 +62,19 @@
     .title{
         background: lightblue;
         grid-column-start:3;
-        grid-column-end: 5;
+        grid-column-end: 4;
         pointer-events: auto;
     }
 }
 
+.documentDecorations-closeButton {
+    background:$alt-accent;
+    opacity: 0.8;
+    grid-column-start: 4;
+    grid-column-end: 6;
+    pointer-events: all;
+    text-align: center;
+}
 .documentDecorations-minimizeButton {
     background:$alt-accent;
     opacity: 0.8;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index a46087c9a..8bf1a42d1 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -142,6 +142,30 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         e.preventDefault();
     }
 
+    onCloseDown = (e: React.PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+            document.removeEventListener("pointermove", this.onCloseMove);
+            document.addEventListener("pointermove", this.onCloseMove);
+            document.removeEventListener("pointerup", this.onCloseUp);
+            document.addEventListener("pointerup", this.onCloseUp);
+        }
+    }
+    onCloseMove = (e: PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+        }
+    }
+    @action
+    onCloseUp = (e: PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+            SelectionManager.SelectedDocuments().map(dv => dv.props.RemoveDocument && dv.props.RemoveDocument(dv.props.Document));
+            SelectionManager.DeselectAll();
+            document.removeEventListener("pointermove", this.onCloseMove);
+            document.removeEventListener("pointerup", this.onCloseUp);
+        }
+    }
     onMinimizeDown = (e: React.PointerEvent): void => {
         e.stopPropagation();
         if (e.button === 0) {
@@ -219,7 +243,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         e.stopPropagation();
     }
 
-    onLinkButtonMoved = (e: PointerEvent): void => {
+    onLinkButtonMoved = async (e: PointerEvent) => {
         if (this._linkButton.current != null) {
             document.removeEventListener("pointermove", this.onLinkButtonMoved)
             document.removeEventListener("pointerup", this.onLinkButtonUp);
@@ -234,10 +258,13 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
             draggedDocs.push(...draggedFromDocs);
             if (draggedDocs.length) {
-                let dragData = new DragManager.DocumentDragData(draggedDocs.map(d => {
-                    let annot = d.GetT(KeyStore.AnnotationOn, Document); // bcz: ... needs to change ... the annotationOn document may not have been retrieved yet...
-                    return annot && annot != FieldWaiting ? annot : d;
-                }));
+                let moddrag = [] as Document[];
+                for (let i = 0; i < draggedDocs.length; i++) {
+                    let doc = await draggedDocs[i].GetTAsync(KeyStore.AnnotationOn, Document);
+                    if (doc)
+                        moddrag.push(doc);
+                }
+                let dragData = new DragManager.DocumentDragData(moddrag);
                 DragManager.StartDocumentDrag([this._linkButton.current], dragData, {
                     handlers: {
                         dragComplete: action(() => { }),
@@ -400,6 +427,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             }}>
                 <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>...</div>
                 <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
+                <div className="documentDecorations-closeButton" onPointerDown={this.onCloseDown}>X</div>
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index daeca69e2..9eee23a1d 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -128,6 +128,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
         }
         if (type.indexOf("pdf") !== -1) {
             ctor = Documents.PdfDocument;
+            options.nativeWidth = 600;
         }
         if (type.indexOf("html") !== -1) {
             if (path.includes('localhost')) {
@@ -177,7 +178,6 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             let item = e.dataTransfer.items[i];
             if (item.kind === "string" && item.type.indexOf("uri") != -1) {
                 e.dataTransfer.items[i].getAsString(action((s: string) => {
-                    let document: Document;
                     request.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s), (err, res, body) => {
                         let type = res.headers["content-type"];
                         if (type) {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3484e963e..1ddb84a99 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -20,6 +20,7 @@ import React = require("react");
 import v5 = require("uuid/v5");
 import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
 import { PreviewCursor } from "./PreviewCursor";
+import { NumberField } from "../../../../fields/NumberField";
 
 @observer
 export class CollectionFreeFormView extends CollectionViewBase {
@@ -83,13 +84,17 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 let dragDoc = de.data.droppedDocuments[0];
                 let dragX = dragDoc.GetNumber(KeyStore.X, 0);
                 let dragY = dragDoc.GetNumber(KeyStore.Y, 0);
-                droppedDocs.map(d => {
+                droppedDocs.map(async d => {
                     let docX = d.GetNumber(KeyStore.X, 0);
                     let docY = d.GetNumber(KeyStore.Y, 0);
                     d.SetNumber(KeyStore.X, x + (docX - dragX));
                     d.SetNumber(KeyStore.Y, y + (docY - dragY));
-                    if (!d.GetNumber(KeyStore.Width, 0)) {
+                    let docW = await d.GetTAsync(KeyStore.Width, NumberField);
+                    let docH = await d.GetTAsync(KeyStore.Height, NumberField);
+                    if (!docW) {
                         d.SetNumber(KeyStore.Width, 300);
+                    }
+                    if (!docH) {
                         d.SetNumber(KeyStore.Height, 300);
                     }
                     this.bringToFront(d);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index e2239c8be..df150a045 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -135,6 +135,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             this.marqueeInkDelete(inkData);
             // }, 100);
             this.cleanupInteractions();
+            SelectionManager.DeselectAll();
         }
     }
     @action
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3cb3cf782..c9fed7f66 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,5 +1,5 @@
 import * as htmlToImage from "html-to-image";
-import { action, computed, observable, reaction, IReactionDisposer, trace, keys } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
 import { observer } from "mobx-react";
 import 'react-image-lightbox/style.css';
 import Measure from "react-measure";
@@ -10,6 +10,7 @@ import { FieldWaiting, Opt } from '../../../fields/Field';
 import { ImageField } from '../../../fields/ImageField';
 import { KeyStore } from '../../../fields/KeyStore';
 import { PDFField } from '../../../fields/PDFField';
+import { RouteStore } from "../../../server/RouteStore";
 import { Utils } from '../../../Utils';
 import { Annotation } from './Annotation';
 import { FieldView, FieldViewProps } from './FieldView';
@@ -17,8 +18,6 @@ import "./ImageBox.scss";
 import "./PDFBox.scss";
 import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here
 import React = require("react")
-import { RouteStore } from "../../../server/RouteStore";
-import { NumberField } from "../../../fields/NumberField";
 
 /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx
  * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, 
@@ -378,8 +377,9 @@ export class PDFBox extends React.Component<FieldViewProps> {
     saveThumbnail = () => {
         setTimeout(() => {
             var me = this;
-            htmlToImage.toPng(this._mainDiv.current!,
-                { width: me.props.doc.GetNumber(KeyStore.NativeWidth, 0), height: me.props.doc.GetNumber(KeyStore.NativeHeight, 0), quality: 0.5 })
+            let nwidth = me.props.doc.GetNumber(KeyStore.NativeWidth, 0);
+            let nheight = me.props.doc.GetNumber(KeyStore.NativeHeight, 0);
+            htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 })
                 .then(function (dataUrl: string) {
                     me.props.doc.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField);
                     me.props.doc.SetNumber(KeyStore.ThumbnailPage, me.props.doc.GetNumber(KeyStore.CurPage, -1));
-- 
cgit v1.2.3-70-g09d2


From 4fde212cd00bd2f8fc2fa122309af3bb71bba2fd Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 4 Apr 2019 18:18:45 -0400
Subject: improved pdf bitmaps a bit, but still blurry.

---
 src/client/documents/Documents.ts                   |  2 +-
 src/client/views/collections/CollectionViewBase.tsx |  2 +-
 src/client/views/nodes/DocumentView.tsx             |  2 +-
 src/client/views/nodes/PDFBox.tsx                   | 20 +++++++++++---------
 4 files changed, 14 insertions(+), 12 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 0bf275df8..1f0744782 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -136,7 +136,7 @@ export namespace Documents {
     function GetPdfPrototype(): Document {
         if (!pdfProto) {
             pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"),
-                { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] });
+                { x: 0, y: 0, nativeWidth: 1200, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] });
             pdfProto.SetNumber(KeyStore.CurPage, 1);
             pdfProto.SetText(KeyStore.BackgroundLayout, PDFBox.LayoutString());
         }
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 9eee23a1d..458bae7ab 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -128,7 +128,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
         }
         if (type.indexOf("pdf") !== -1) {
             ctor = Documents.PdfDocument;
-            options.nativeWidth = 600;
+            options.nativeWidth = 1200;
         }
         if (type.indexOf("html") !== -1) {
             if (path.includes('localhost')) {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 714ab9447..b9329f269 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -249,7 +249,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         document.removeEventListener("pointermove", this.onPointerMove);
         document.removeEventListener("pointerup", this.onPointerUp);
         e.stopPropagation();
-        if (
+        if (!SelectionManager.IsSelected(this) &&
             Math.abs(e.clientX - this._downX) < 4 &&
             Math.abs(e.clientY - this._downY) < 4
         ) {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index c9fed7f66..f9f5bc8f8 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -18,6 +18,7 @@ import "./ImageBox.scss";
 import "./PDFBox.scss";
 import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here
 import React = require("react")
+import { SelectionManager } from "../../util/SelectionManager";
 
 /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx
  * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, 
@@ -57,6 +58,8 @@ export class PDFBox extends React.Component<FieldViewProps> {
     private _mainDiv = React.createRef<HTMLDivElement>()
     private _pdf = React.createRef<HTMLCanvasElement>();
 
+    @observable private _renderAsSvg = true;
+
     //very useful for keeping track of X and y position throughout the PDF Canvas
     private initX: number = 0;
     private initY: number = 0;
@@ -91,9 +94,9 @@ export class PDFBox extends React.Component<FieldViewProps> {
 
     componentDidMount() {
         this._reactionDisposer = reaction(
-            () => [this.curPage, this.thumbnailPage],
+            () => [SelectionManager.SelectedDocuments().slice()],
             () => {
-                if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage != this.thumbnailPage) {
+                if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage != this.thumbnailPage && !this.props.isSelected()) {
                     this.saveThumbnail();
                     this._interactive = true;
                 }
@@ -375,19 +378,21 @@ export class PDFBox extends React.Component<FieldViewProps> {
 
     @action
     saveThumbnail = () => {
+        this._renderAsSvg = false;
         setTimeout(() => {
             var me = this;
             let nwidth = me.props.doc.GetNumber(KeyStore.NativeWidth, 0);
             let nheight = me.props.doc.GetNumber(KeyStore.NativeHeight, 0);
             htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 })
-                .then(function (dataUrl: string) {
+                .then(action((dataUrl: string) => {
                     me.props.doc.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField);
                     me.props.doc.SetNumber(KeyStore.ThumbnailPage, me.props.doc.GetNumber(KeyStore.CurPage, -1));
-                })
+                    me._renderAsSvg = true;
+                }))
                 .catch(function (error: any) {
                     console.error('oops, something went wrong!', error);
                 });
-        }, 1000);
+        }, 250);
     }
 
     @action
@@ -427,9 +432,6 @@ export class PDFBox extends React.Component<FieldViewProps> {
             this.props.doc.SetNumber(KeyStore.Height, nativeHeight / nativeWidth * this.props.doc.GetNumber(KeyStore.Width, 0));
             this.props.doc.SetNumber(KeyStore.NativeHeight, nativeHeight);
         }
-        if (!this.props.doc.GetT(KeyStore.Thumbnail, ImageField)) {
-            this.saveThumbnail();
-        }
     }
 
     @computed
@@ -439,7 +441,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
         let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField);
         let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight;
         return <div className="pdfBox-contentContainer" key="container" style={{ transform: `scale(${xf}, ${xf})` }}>
-            <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`} renderMode="svg">
+            <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`} renderMode={this._renderAsSvg ? "svg" : ""}>
                 <Measure onResize={this.setScaling}>
                     {({ measureRef }) =>
                         <div className="pdfBox-page" ref={measureRef}>
-- 
cgit v1.2.3-70-g09d2


From dbe95611c72eece3767f80543c921e4afaeaf294 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Fri, 5 Apr 2019 02:30:07 -0400
Subject: upgraded typescript and fixed compile errors

---
 package.json                        |   2 +-
 src/client/util/TooltipTextMenu.tsx | 228 ++++++++++++++++++------------------
 src/client/views/nodes/PDFBox.tsx   |   4 +-
 3 files changed, 116 insertions(+), 118 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/package.json b/package.json
index 6e894fd20..e0d0a72dd 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
     "scss-loader": "0.0.1",
     "style-loader": "^0.23.1",
     "ts-node": "^7.0.1",
-    "typescript": "^3.3.3333",
+    "typescript": "^3.4.1",
     "webpack": "^4.29.6",
     "webpack-cli": "^3.2.3",
     "webpack-dev-middleware": "^3.6.1",
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 2a613ba8b..913472aa0 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -11,129 +11,127 @@ import "./TooltipTextMenu.scss";
 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 { faListUl } from '@fortawesome/free-solid-svg-icons';
 
 
 //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
 export class TooltipTextMenu {
 
-  private tooltip: HTMLElement;
-
-  constructor(view: EditorView) {
-    this.tooltip = document.createElement("div");
-    this.tooltip.className = "tooltipMenu";
-
-    //add the div which is the tooltip
-    view.dom.parentNode!.appendChild(this.tooltip);
-
-    //add additional icons
-    library.add(faListUl);
-
-    //add the buttons to the tooltip
-    let items = [
-      { command: toggleMark(schema.marks.strong), dom: this.icon("B", "strong") },
-      { command: toggleMark(schema.marks.em), dom: this.icon("i", "em") },
-      { command: toggleMark(schema.marks.underline), dom: this.icon("U", "underline") },
-      { command: toggleMark(schema.marks.strikethrough), dom: this.icon("S", "strikethrough") },
-      { command: toggleMark(schema.marks.superscript), dom: this.icon("s", "superscript") },
-      { command: toggleMark(schema.marks.subscript), dom: this.icon("s", "subscript") },
-      //this doesn't work currently - look into notion of active block
-      { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") },
-    ]
-    items.forEach(({ dom }) => this.tooltip.appendChild(dom));
-
-    //pointer down handler to activate button effects
-    this.tooltip.addEventListener("pointerdown", e => {
-      e.preventDefault();
-      view.focus();
-      items.forEach(({ command, dom }) => {
-        if (dom.contains(e.srcElement)) {
-          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"
+    private tooltip: HTMLElement;
+
+    constructor(view: EditorView) {
+        this.tooltip = document.createElement("div");
+        this.tooltip.className = "tooltipMenu";
+
+        //add the div which is the tooltip
+        view.dom.parentNode!.appendChild(this.tooltip);
+
+        //add additional icons
+        library.add(faListUl);
+
+        //add the buttons to the tooltip
+        let items = [
+            { command: toggleMark(schema.marks.strong), dom: this.icon("B", "strong") },
+            { command: toggleMark(schema.marks.em), dom: this.icon("i", "em") },
+            { command: toggleMark(schema.marks.underline), dom: this.icon("U", "underline") },
+            { command: toggleMark(schema.marks.strikethrough), dom: this.icon("S", "strikethrough") },
+            { command: toggleMark(schema.marks.superscript), dom: this.icon("s", "superscript") },
+            { command: toggleMark(schema.marks.subscript), dom: this.icon("s", "subscript") },
+            //this doesn't work currently - look into notion of active block
+            { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") },
+        ]
+        items.forEach(({ dom }) => this.tooltip.appendChild(dom));
+
+        //pointer down handler to activate button effects
+        this.tooltip.addEventListener("pointerdown", e => {
+            e.preventDefault();
+            view.focus();
+            items.forEach(({ command, dom }) => {
+                if (dom.contains(e.target as Node)) {
+                    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"
+                }
+            })
+        })
+
+        this.update(view, undefined);
+    }
+
+    // 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;
+        return span;
+    }
+
+    //adapted this method - use it to check if block has a tag (ie bulleting)
+    blockActive(type: NodeType<Schema<string, string>>, state: EditorState) {
+        let attrs = {};
+
+        if (state.selection instanceof NodeSelection) {
+            const sel: NodeSelection = state.selection;
+            let $from = sel.$from;
+            let to = sel.to;
+            let node = sel.node;
+
+            if (node) {
+                return node.hasMarkup(type, attrs);
+            }
+
+            return to <= $from.end() && $from.parent.hasMarkup(type, attrs);
         }
-      })
-    })
-
-    this.update(view, undefined);
-  }
-
-  // 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;
-    return span;
-  }
-
-  //adapted this method - use it to check if block has a tag (ie bulleting)
-  blockActive(type: NodeType<Schema<string, string>>, state: EditorState) {
-    let attrs = {};
-
-    if (state.selection instanceof NodeSelection) {
-      const sel: NodeSelection = state.selection;
-      let $from = sel.$from;
-      let to = sel.to;
-      let node = sel.node;
-
-      if (node) {
-        return node.hasMarkup(type, attrs);
-      }
-
-      return to <= $from.end() && $from.parent.hasMarkup(type, attrs);
     }
-  }
-
-  //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 fa fa-smile-o";
-    span.appendChild(icon);
-    return span;
-  }
-
-  // Create an icon for a heading at the given level
-  heading(level: number) {
-    return {
-      command: setBlockType(schema.nodes.heading, { level }),
-      dom: this.icon("H" + level, "heading")
+
+    //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 fa fa-smile-o";
+        span.appendChild(icon);
+        return span;
+    }
+
+    // Create an icon for a heading at the given level
+    heading(level: number) {
+        return {
+            command: setBlockType(schema.nodes.heading, { level }),
+            dom: this.icon("H" + level, "heading")
+        }
     }
-  }
-
-  //updates the tooltip menu when the selection changes
-  update(view: EditorView, lastState: EditorState | undefined) {
-    let state = view.state
-    // Don't do anything if the document/selection didn't change
-    if (lastState && lastState.doc.eq(state.doc) &&
-      lastState.selection.eq(state.selection)) return
-
-    // Hide the tooltip if the selection is empty
-    if (state.selection.empty) {
-      this.tooltip.style.display = "none"
-      return
+
+    //updates the tooltip menu when the selection changes
+    update(view: EditorView, lastState: EditorState | undefined) {
+        let state = view.state
+        // Don't do anything if the document/selection didn't change
+        if (lastState && lastState.doc.eq(state.doc) &&
+            lastState.selection.eq(state.selection)) return
+
+        // Hide the tooltip if the selection is empty
+        if (state.selection.empty) {
+            this.tooltip.style.display = "none"
+            return
+        }
+
+        // Otherwise, reposition it and update its content
+        this.tooltip.style.display = ""
+        let { from, to } = state.selection
+        let start = view.coordsAtPos(from), end = view.coordsAtPos(to)
+        // The box in which the tooltip is positioned, to use as base
+        let box = this.tooltip.offsetParent!.getBoundingClientRect()
+        // 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 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";
     }
 
-    // Otherwise, reposition it and update its content
-    this.tooltip.style.display = ""
-    let { from, to } = state.selection
-    let start = view.coordsAtPos(from), end = view.coordsAtPos(to)
-    // The box in which the tooltip is positioned, to use as base
-    let box = this.tooltip.offsetParent!.getBoundingClientRect()
-    // 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 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";
-  }
-
-  destroy() { this.tooltip.remove() }
+    destroy() { this.tooltip.remove() }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index f9f5bc8f8..7039b0c41 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -153,7 +153,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
      */
     makeEditableAndHighlight = (colour: string) => {
         var range, sel = window.getSelection();
-        if (sel.rangeCount && sel.getRangeAt) {
+        if (sel && sel.rangeCount && sel.getRangeAt) {
             range = sel.getRangeAt(0);
         }
         document.designMode = "on";
@@ -161,7 +161,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
             document.execCommand("HiliteColor", false, colour);
         }
 
-        if (range) {
+        if (range && sel) {
             sel.removeAllRanges();
             sel.addRange(range);
 
-- 
cgit v1.2.3-70-g09d2

