aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts2
-rw-r--r--src/client/views/pdf/PDFViewer.tsx373
-rw-r--r--src/client/views/pdf/Page.scss16
-rw-r--r--src/client/views/pdf/Page.tsx52
4 files changed, 178 insertions, 265 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index 502540eb0..bad875f0d 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -132,6 +132,8 @@ export function WithKeys(obj: any, keys: string[], addKeyFunc?: (dup: any) => vo
return dup;
}
+export function numberRange(num: number) { return Array.from(Array(num)).map((v, i) => i); }
+
export function returnTrue() { return true; }
export function returnFalse() { return false; }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 9abb22553..411857223 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -5,16 +5,16 @@ import * as Pdfjs from "pdfjs-dist";
import "pdfjs-dist/web/pdf_viewer.css";
import * as rp from "request-promise";
import { Dictionary } from "typescript-collections";
-import { Doc, DocListCast } from "../../../new_fields/Doc";
+import { Doc, DocListCast, FieldResult } from "../../../new_fields/Doc";
import { Id } from "../../../new_fields/FieldSymbols";
import { List } from "../../../new_fields/List";
import { ScriptField } from "../../../new_fields/ScriptField";
import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
-import { emptyFunction, Utils } from "../../../Utils";
+import { Utils, numberRange } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { Docs, DocUtils } from "../../documents/Documents";
import { KeyCodes } from "../../northstar/utils/KeyCodes";
-import { CompileResult, CompileScript } from "../../util/Scripting";
+import { CompileScript, CompiledScript } from "../../util/Scripting";
import Annotation from "./Annotation";
import Page from "./Page";
import "./PDFViewer.scss";
@@ -48,7 +48,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
@observable private _pageSizes: { width: number, height: number }[] = [];
@observable private _annotations: Doc[] = [];
@observable private _savedAnnotations: Dictionary<number, HTMLDivElement[]> = new Dictionary<number, HTMLDivElement[]>();
- @observable private _script: CompileResult | undefined = CompileScript("return true");
+ @observable private _script: CompiledScript = CompileScript("return true") as CompiledScript;
@observable private _searching: boolean = false;
@observable private Index: number = -1;
@@ -64,18 +64,32 @@ export class PDFViewer extends React.Component<IViewerProps> {
private _searchString: string = "";
private _selectionText: string = "";
- componentDidUpdate = (prevProps: IViewerProps) => {
- this.scrollY !== prevProps.scrollY && this.renderPages();
+ @computed get scrollY(): number { return this.props.scrollY; }
+
+ // startIndex: where to start rendering pages
+ @computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.scrollY) - this._pageBuffer); }
+
+ // endIndex: where to end rendering pages
+ @computed get endIndex(): number {
+ return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY + (this._pageSizes[0] ? this._pageSizes[0].height : 0)) + this._pageBuffer);
}
- @action
- componentDidMount = () => {
+ @computed get filteredAnnotations() {
+ return this._annotations.filter(anno => {
+ let run = this._script.run({ this: anno });
+ return run.success ? run.result : true;
+ });
+ }
+
+ componentDidUpdate = (prevProps: IViewerProps) => this.scrollY !== prevProps.scrollY && this.renderPages();
+
+ componentDidMount = async () => {
+ await this.initialLoad();
+
this._reactionDisposer = reaction(
() => [this.props.active(), this.startIndex, this._pageSizes.length ? this.endIndex : 0],
- async () => {
- await this.initialLoad();
- this.renderPages();
- }, { fireImmediately: true });
+ () => this.renderPages(),
+ { fireImmediately: true });
this._annotationReactionDisposer = reaction(
() => this.props.fieldExtensionDoc && DocListCast(this.props.fieldExtensionDoc.annotations),
@@ -83,17 +97,12 @@ export class PDFViewer extends React.Component<IViewerProps> {
{ fireImmediately: true });
this._filterReactionDisposer = reaction(
- () => this.props.Document.filterScript,
- action(() => {
- let scriptfield = Cast(this.props.Document.filterScript, ScriptField);
- this._script = scriptfield ? scriptfield.script : CompileScript("return true");
- DocListCast(this.props.fieldExtensionDoc.annotations).forEach(d => {
- if (this._script && this._script.compiled) {
- let run = this._script.run(d);
- if (run.success) {
- d.opacity = run.result ? 1 : 0;
- }
- }
+ () => ({ scriptField: Cast(this.props.Document.filterScript, ScriptField), annos: this._annotations.slice() }),
+ action(({ scriptField, annos }: { scriptField: FieldResult<ScriptField>, annos: Doc[] }) => {
+ this._script = scriptField && scriptField.script.compiled ? scriptField.script : CompileScript("return true") as CompiledScript;
+ annos.forEach(d => {
+ let run = this._script.run(d);
+ d.opacity = !run.success || run.result ? 1 : 0;
});
this.Index = -1;
}),
@@ -111,13 +120,11 @@ export class PDFViewer extends React.Component<IViewerProps> {
document.removeEventListener("copy", this.copy);
}
- private copy = (e: ClipboardEvent) => {
+ copy = (e: ClipboardEvent) => {
if (this.props.active() && e.clipboardData) {
- let text = this._selectionText;
- let annoDoc = this.makeAnnotationDocument(undefined, 0, "#0390fc");
- e.clipboardData.setData("text/plain", text);
+ e.clipboardData.setData("text/plain", this._selectionText);
e.clipboardData.setData("dash/pdfOrigin", this.props.Document[Id]);
- e.clipboardData.setData("dash/pdfRegion", annoDoc[Id]);
+ e.clipboardData.setData("dash/pdfRegion", this.makeAnnotationDocument(undefined, 0, "#0390fc")[Id]);
e.preventDefault();
}
}
@@ -130,9 +137,13 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
}
- setSelectionText = (text: string) => {
- this._selectionText = text;
- }
+ searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => this._searchString = e.currentTarget.value;
+
+ pageLoaded = (page: Pdfjs.PDFPageViewport): void => this.props.loaded(page.width, page.height, this.props.pdf.numPages);
+
+ setSelectionText = (text: string) => this._selectionText = text;
+
+ getIndex = () => this.Index;
@action
initialLoad = async () => {
@@ -157,32 +168,27 @@ export class PDFViewer extends React.Component<IViewerProps> {
@action
makeAnnotationDocument = (sourceDoc: Doc | undefined, s: number, color: string, createLink: boolean = true): Doc => {
- let annoDocs: Doc[] = [];
let mainAnnoDoc = Docs.Create.InstanceFromProto(new Doc(), "", {});
+ let annoDocs: Doc[] = [];
+ let minY = Number.MAX_VALUE;
+ this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => value.map(anno => {
+ let annoDoc = new Doc();
+ if (anno.style.left) annoDoc.x = parseInt(anno.style.left) / scale;
+ if (anno.style.top) annoDoc.y = parseInt(anno.style.top) / scale;
+ if (anno.style.height) annoDoc.height = parseInt(anno.style.height) / scale;
+ if (anno.style.width) annoDoc.width = parseInt(anno.style.width) / scale;
+ annoDoc.page = key;
+ annoDoc.target = sourceDoc;
+ annoDoc.group = mainAnnoDoc;
+ annoDoc.color = color;
+ annoDoc.type = AnnotationTypes.Region;
+ annoDocs.push(annoDoc);
+ anno.remove();
+ (annoDoc.y !== undefined) && (minY = Math.min(NumCast(annoDoc.y), minY));
+ }));
mainAnnoDoc.title = "Annotation on " + StrCast(this.props.Document.title);
mainAnnoDoc.pdfDoc = this.props.Document;
- let minY = Number.MAX_VALUE;
- this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => {
- for (let anno of value) {
- let annoDoc = new Doc();
- if (anno.style.left) annoDoc.x = parseInt(anno.style.left) / scale;
- if (anno.style.top) {
- annoDoc.y = parseInt(anno.style.top) / scale;
- minY = Math.min(parseInt(anno.style.top), minY);
- }
- if (anno.style.height) annoDoc.height = parseInt(anno.style.height) / scale;
- if (anno.style.width) annoDoc.width = parseInt(anno.style.width) / scale;
- annoDoc.page = key;
- annoDoc.target = sourceDoc;
- annoDoc.group = mainAnnoDoc;
- annoDoc.color = color;
- annoDoc.type = AnnotationTypes.Region;
- annoDocs.push(annoDoc);
- anno.remove();
- }
- });
-
mainAnnoDoc.y = Math.max(minY, 0);
mainAnnoDoc.annotations = new List<Doc>(annoDocs);
if (sourceDoc && createLink) {
@@ -193,15 +199,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
return mainAnnoDoc;
}
- /**
- * Called by the Page class when it gets rendered, initializes the lists and
- * puts a placeholder with all of the correct page sizes when all of the pages have been loaded.
- */
- @action
- pageLoaded = (page: Pdfjs.PDFPageViewport): void => {
- this.props.loaded(page.width, page.height, this.props.pdf.numPages);
- }
-
@action
getPlaceholderPage = (page: number) => {
if (this._isPage[page] !== "none") {
@@ -218,25 +215,19 @@ export class PDFViewer extends React.Component<IViewerProps> {
getRenderedPage = (page: number) => {
if (this._isPage[page] !== "page") {
this._isPage[page] = "page";
- this._visibleElements[page] = (
- <Page
- setSelectionText={this.setSelectionText}
- size={this._pageSizes[page]}
- pdf={this.props.pdf}
- page={page}
- numPages={this.props.pdf.numPages}
- key={`${this.props.url}-rendered-${page + 1}`}
- name={`${this.props.pdf.fingerprint + `-page${page + 1}`}`}
- pageLoaded={this.pageLoaded}
- fieldExtensionDoc={this.props.fieldExtensionDoc}
- Document={this.props.Document}
- renderAnnotations={this.renderAnnotations}
- createAnnotation={this.createAnnotation}
- sendAnnotations={this.receiveAnnotations}
- makeAnnotationDocuments={this.makeAnnotationDocument}
- getScrollFromPage={this.getScrollFromPage}
- {...this.props} />
- );
+ this._visibleElements[page] = (<Page {...this.props}
+ size={this._pageSizes[page]}
+ numPages={this.props.pdf.numPages}
+ setSelectionText={this.setSelectionText}
+ page={page}
+ key={`${this.props.url}-rendered-${page + 1}`}
+ name={`${this.props.pdf.fingerprint + `-page${page + 1}`}`}
+ pageLoaded={this.pageLoaded}
+ renderAnnotations={this.renderAnnotations}
+ createAnnotation={this.createAnnotation}
+ sendAnnotations={this.receiveAnnotations}
+ makeAnnotationDocuments={this.makeAnnotationDocument}
+ getScrollFromPage={this.getScrollFromPage} />);
}
}
@@ -244,13 +235,12 @@ export class PDFViewer extends React.Component<IViewerProps> {
// file address of the pdf
@action
getPageImage = async (page: number) => {
- let handleError = () => this.getRenderedPage(page);
if (this._isPage[page] !== "image") {
this._isPage[page] = "image";
try {
let res = JSON.parse(await rp.get(Utils.prepend(`/thumbnail${this.props.url.substring("files/".length, this.props.url.length - ".pdf".length)}-${page + 1}.PNG`)));
runInAction(() => this._visibleElements[page] =
- <img key={res.path} src={res.path} onError={handleError}
+ <img key={res.path} src={res.path} onError={() => this.getRenderedPage(page)}
style={{ width: `${parseInt(res.width) * scale}px`, height: `${parseInt(res.height) * scale}px` }} />);
} catch (e) {
console.log(e);
@@ -258,26 +248,14 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
}
- @computed get scrollY(): number { return this.props.scrollY; }
-
- // startIndex: where to start rendering pages
- @computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.scrollY) - this._pageBuffer); }
-
- // endIndex: where to end rendering pages
- @computed get endIndex(): number {
- return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY + (this._pageSizes[0] ? this._pageSizes[0].height : 0)) + this._pageBuffer);
- }
-
- @action
renderPages = () => {
- Array.from(Array(this.props.pdf.numPages).keys()).filter(p => this._isPage[p] !== undefined).map(i =>
+ numberRange(this.props.pdf.numPages).filter(p => this._isPage[p] !== undefined).map(i =>
(i < this.startIndex || i > this.endIndex) ? this.getPlaceholderPage(i) : // pages outside of the pdf use empty stand-in divs
- this.props.active() ? this.getRenderedPage(i) : this.getPageImage(i)
- );
+ this.props.active() ? this.getRenderedPage(i) : this.getPageImage(i));
}
@action
- private renderAnnotations = (annotations: Doc[], removeOldAnnotations: boolean): void => {
+ renderAnnotations = (annotations: Doc[], removeOldAnnotations: boolean): void => {
if (removeOldAnnotations) {
this._annotations = annotations;
}
@@ -288,6 +266,21 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
@action
+ prevAnnotation = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ this.Index = Math.max(this.Index - 1, 0);
+ }
+
+ @action
+ nextAnnotation = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ this.Index = Math.min(this.Index + 1, this.filteredAnnotations.length - 1);
+ }
+
+ sendAnnotations = (page: number) => {
+ return this._savedAnnotations.getValue(page);
+ }
+
receiveAnnotations = (annotations: HTMLDivElement[], page: number) => {
if (page === -1) {
this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
@@ -298,10 +291,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
}
- sendAnnotations = (page: number): HTMLDivElement[] | undefined => {
- return this._savedAnnotations.getValue(page);
- }
-
// get the page index that the vertical offset passed in is on
getPageFromScroll = (vOffset: number) => {
let index = 0;
@@ -313,13 +302,10 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
getScrollFromPage = (index: number): number => {
- let counter = 0;
- for (let i = 0; i < Math.min(this.props.pdf.numPages, index); i++) {
- counter += this._pageSizes[i].height;
- }
- return counter;
+ return numberRange(Math.min(this.props.pdf.numPages, index)).reduce((counter, i) => counter + this._pageSizes[i].height, 0);
}
+ @action
createAnnotation = (div: HTMLDivElement, page: number) => {
if (this._annotationLayer.current) {
if (div.style.top) {
@@ -337,8 +323,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
}
- getIndex = () => this.Index;
-
@action
search = (searchString: string) => {
if (this._pdfViewer._pageViewsReady) {
@@ -350,27 +334,16 @@ export class PDFViewer extends React.Component<IViewerProps> {
query: searchString
});
}
- else {
- if (this._mainCont.current) {
- this._mainCont.current.addEventListener("pagesloaded", () =>
- this._pdfFindController.executeCommand('find', {
- caseSensitive: false,
- findPrevious: undefined,
- highlightAll: true,
- phraseSearch: true,
- query: searchString
- })
- );
- this._mainCont.current.addEventListener("pagerendered", () =>
- this._pdfFindController.executeCommand('find', {
- caseSensitive: false,
- findPrevious: undefined,
- highlightAll: true,
- phraseSearch: true,
- query: searchString
- })
- );
- }
+ else if (this._mainCont.current) {
+ let executeFind = () => this._pdfFindController.executeCommand('find', {
+ caseSensitive: false,
+ findPrevious: undefined,
+ highlightAll: true,
+ phraseSearch: true,
+ query: searchString
+ });
+ this._mainCont.current.addEventListener("pagesloaded", executeFind);
+ this._mainCont.current.addEventListener("pagerendered", executeFind);
}
// let viewer = this._viewer.current;
@@ -416,9 +389,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
// }
}
- searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
- this._searchString = e.currentTarget.value;
- }
@action
toggleSearch = (e: React.MouseEvent) => {
@@ -426,23 +396,19 @@ export class PDFViewer extends React.Component<IViewerProps> {
this._searching = !this._searching;
if (this._searching) {
- let container = this._mainCont.current;
-
- if (!this._pdfFindController) {
- if (container && this._viewer.current) {
- let simpleLinkService = new SimpleLinkService();
- this._pdfViewer = new PDFJSViewer.PDFViewer({
- container: container,
- viewer: this._viewer.current,
- linkService: simpleLinkService
- });
- simpleLinkService.setPdf(this.props.pdf);
- container.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = 1);
- container.addEventListener("pagerendered", () => console.log("rendered"));
- this._pdfViewer.setDocument(this.props.pdf);
- this._pdfFindController = new PDFJSViewer.PDFFindController(this._pdfViewer);
- this._pdfViewer.findController = this._pdfFindController;
- }
+ if (!this._pdfFindController && this._mainCont.current && this._viewer.current) {
+ let simpleLinkService = new SimpleLinkService();
+ this._pdfViewer = new PDFJSViewer.PDFViewer({
+ container: this._mainCont.current,
+ viewer: this._viewer.current,
+ linkService: simpleLinkService
+ });
+ simpleLinkService.setPdf(this.props.pdf);
+ this._mainCont.current.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = 1);
+ this._mainCont.current.addEventListener("pagerendered", () => console.log("rendered"));
+ this._pdfViewer.setDocument(this.props.pdf);
+ this._pdfFindController = new PDFJSViewer.PDFFindController(this._pdfViewer);
+ this._pdfViewer.findController = this._pdfFindController;
}
}
else {
@@ -456,86 +422,47 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
}
- @action
- prevAnnotation = (e: React.MouseEvent) => {
- e.stopPropagation();
- this.Index = Math.max(this.Index - 1, 0);
- }
-
- @action
- nextAnnotation = (e: React.MouseEvent) => {
- e.stopPropagation();
-
- let compiled = this._script;
- let filtered = this._annotations.filter(anno => {
- if (compiled && compiled.compiled) {
- let run = compiled.run({ this: anno });
- if (run.success) {
- return run.result;
- }
- }
- return true;
- });
- this.Index = Math.min(this.Index + 1, filtered.length - 1);
- }
-
render() {
- return (
- <div className="pdfViewer-viewer" ref={this._mainCont} >
- <div className="pdfViewer-visibleElements" style={this._searching ? { position: "absolute", top: 0 } : {}}>
- {this._visibleElements}
+ return (<div className="pdfViewer-viewer" ref={this._mainCont} >
+ <div className="pdfViewer-visibleElements" style={this._searching ? { position: "absolute", top: 0 } : {}}>
+ {this._visibleElements}
+ </div>
+ <div className="pdfViewer-text" ref={this._viewer} />
+ <div className="pdfViewer-annotationLayer" style={{ height: NumCast(this.props.Document.nativeHeight) }} ref={this._annotationLayer}>
+ {this.filteredAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map((anno, index) =>
+ <Annotation {...this.props} ParentIndex={this.getIndex} anno={anno} index={index} key={`${anno[Id]}-annotation`} />)}
+ </div>
+ <div className="pdfViewer-overlayCont" onPointerDown={(e) => e.stopPropagation()}
+ style={{ nbottom: -this.props.scrollY, left: `${this._searching ? 0 : 100}%` }}>
+ <button className="pdfViewer-overlayButton" title="Open Search Bar" />
+ <input className="pdfViewer-overlaySearchBar" placeholder="Search" onChange={this.searchStringChanged}
+ onKeyDown={(e: React.KeyboardEvent) => e.keyCode === KeyCodes.ENTER ? this.search(this._searchString) : e.keyCode === KeyCodes.BACKSPACE ? e.stopPropagation() : true} />
+ <button title="Search" onClick={() => this.search(this._searchString)}><FontAwesomeIcon icon="search" size="3x" color="white" /></button>
+ </div>
+ <button className="pdfViewer-overlayButton" onClick={this.prevAnnotation} title="Previous Annotation"
+ style={{ bottom: -this.props.scrollY + 280, right: 10, display: this.props.active() ? "flex" : "none" }}>
+ <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
+ <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="3x" />
</div>
- <div className="pdfViewer-text" ref={this._viewer} />
- <div className="pdfViewer-annotationLayer" style={{ height: NumCast(this.props.Document.nativeHeight) }} ref={this._annotationLayer}>
- {this._annotations.filter(anno => {
- if (this._script && this._script.compiled) {
- let run = this._script.run({ this: anno });
- if (run.success) {
- return run.result;
- }
- }
- return true;
- }).sort((a: Doc, b: Doc) => NumCast(a.y) - NumCast(b.y))
- .map((anno: Doc, index: number) =>
- <Annotation anno={anno} scrollTo={this.props.scrollTo} fieldExtensionDoc={this.props.fieldExtensionDoc} ParentIndex={this.getIndex} addDocTab={this.props.addDocTab} index={index} key={`${anno[Id]}-annotation`} />
- )}
+ </button>
+ <button className="pdfViewer-overlayButton" onClick={this.nextAnnotation} title="Next Annotation"
+ style={{ bottom: -this.props.scrollY + 200, right: 10, display: this.props.active() ? "flex" : "none" }}>
+ <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
+ <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="3x" />
</div>
- <div className="pdfViewer-overlayCont" onPointerDown={(e) => e.stopPropagation()}
- style={{
- bottom: -this.props.scrollY,
- left: `${this._searching ? 0 : 100}%`
- }}>
- <button className="pdfViewer-overlayButton" title="Open Search Bar"></button>
- <input className="pdfViewer-overlaySearchBar" onKeyDown={(e: React.KeyboardEvent) => e.keyCode === KeyCodes.ENTER ? this.search(this._searchString) : e.keyCode === KeyCodes.BACKSPACE ? e.stopPropagation() : true} placeholder="Search" onChange={this.searchStringChanged} />
- <button title="Search" onClick={() => this.search(this._searchString)}><FontAwesomeIcon icon="search" size="3x" color="white" /></button>
+ </button>
+ <button className="pdfViewer-overlayButton" onClick={this.toggleSearch} title="Open Search Bar"
+ style={{ bottom: -this.props.scrollY + 10, right: 0, display: this.props.active() ? "flex" : "none" }}>
+ <div className="pdfViewer-overlayButton-arrow" onPointerDown={(e) => e.stopPropagation()}></div>
+ <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
+ <FontAwesomeIcon style={{ color: "white" }} icon={this._searching ? "times" : "search"} size="3x" />
</div>
- <button className="pdfViewer-overlayButton" onClick={this.prevAnnotation} title="Previous Annotation"
- style={{ bottom: -this.props.scrollY + 280, right: 10, display: this.props.active() ? "flex" : "none" }}>
- <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
- <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="3x" />
- </div>
- </button>
- <button className="pdfViewer-overlayButton" onClick={this.nextAnnotation} title="Next Annotation"
- style={{ bottom: -this.props.scrollY + 200, right: 10, display: this.props.active() ? "flex" : "none" }}>
- <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
- <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="3x" />
- </div>
- </button>
- <button className="pdfViewer-overlayButton" onClick={this.toggleSearch} title="Open Search Bar"
- style={{ bottom: -this.props.scrollY + 10, right: 0, display: this.props.active() ? "flex" : "none" }}>
- <div className="pdfViewer-overlayButton-arrow" onPointerDown={(e) => e.stopPropagation()}></div>
- <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
- <FontAwesomeIcon style={{ color: "white" }} icon={this._searching ? "times" : "search"} size="3x" />
- </div>
- </button>
- </div >
- );
+ </button>
+ </div >);
}
}
-export enum AnnotationTypes {
- Region
-}
+export enum AnnotationTypes { Region }
class SimpleLinkService {
externalLinkTarget: any = null;
diff --git a/src/client/views/pdf/Page.scss b/src/client/views/pdf/Page.scss
index 6467c4979..af1628a6f 100644
--- a/src/client/views/pdf/Page.scss
+++ b/src/client/views/pdf/Page.scss
@@ -1,21 +1,21 @@
.pdfPage-cont {
+ position: relative;
+
+ .pdfPage-canvasContainer {
+ position: absolute;
+ }
.pdfPage-dragAnnotationBox {
position: absolute;
background-color: transparent;
opacity: 0.1;
}
- .pdfPage-annotationLayer {
- pointer-events: none;
+
+ .pdfPage-textLayer {
+ position: absolute;
width: 100%;
height: 100%;
- position: relative;
- top: -100%;
- }
-
- .PdfPage-textLayer {
- position: relative;
div {
user-select: text;
}
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 47f2e7b56..fd4fbfb21 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -49,30 +49,21 @@ export default class Page extends React.Component<IPageProps> {
private _startY: number = 0;
private _startX: number = 0;
- componentDidMount = (): void => {
- this.loadPage(this.props.pdf);
- }
+ componentDidMount = (): void => this.loadPage(this.props.pdf);
- componentDidUpdate = (): void => {
- this.loadPage(this.props.pdf);
- }
+ componentDidUpdate = (): void => this.loadPage(this.props.pdf);
- componentWillUnmount = (): void => {
- this._reactionDisposer && this._reactionDisposer();
- }
+ componentWillUnmount = (): void => this._reactionDisposer && this._reactionDisposer();
- private loadPage = (pdf: Pdfjs.PDFDocumentProxy): void => {
- this._state !== "rendering" && !this._page && pdf.getPage(this._currPage).then(
- (page: Pdfjs.PDFPageProxy): void => {
- this._state = "rendering";
- this.renderPage(page);
- });
+ loadPage = (pdf: Pdfjs.PDFDocumentProxy): void => {
+ pdf.getPage(this._currPage).then(page => this.renderPage(page));
}
@action
- private renderPage = (page: Pdfjs.PDFPageProxy): void => {
+ renderPage = (page: Pdfjs.PDFPageProxy): void => {
// lower scale = easier to read at small sizes, higher scale = easier to read at large sizes
- if (this._canvas.current && this._textLayer.current) {
+ if (this._state !== "rendering" && !this._page && this._canvas.current && this._textLayer.current) {
+ this._state = "rendering";
let viewport = page.getViewport(scale);
this._canvas.current.width = this._width = viewport.width;
this._canvas.current.height = this._height = viewport.height;
@@ -113,7 +104,7 @@ export default class Page extends React.Component<IPageProps> {
if (this._textLayer.current) {
let targetDoc = Docs.Create.TextDocument({ width: 200, height: 200, title: "New Annotation" });
targetDoc.targetPage = this.props.page;
- let annotationDoc = this.highlight(undefined, "pink");
+ let annotationDoc = this.highlight(undefined, "red");
annotationDoc.linkedToDoc = false;
let dragData = new DragManager.AnnotationDragData(this.props.Document, annotationDoc, targetDoc);
DragManager.StartAnnotationDrag([ele], dragData, e.pageX, e.pageY, {
@@ -293,23 +284,16 @@ export default class Page extends React.Component<IPageProps> {
render() {
return (
<div className={"pdfPage-cont"} onPointerDown={this.onPointerDown} onDoubleClick={this.doubleClick} style={{ "width": this._width, "height": this._height }}>
- <div className="PdfPage-canvasContainer">
- <canvas ref={this._canvas} />
- </div>
- <div className="pdfPage-annotationLayer">
- <div className="pdfPage-dragAnnotationBox" ref={this._marquee}
- style={{
- left: `${this._marqueeX}px`, top: `${this._marqueeY}px`,
- width: `${this._marqueeWidth}px`, height: `${this._marqueeHeight}px`,
- border: `${this._marqueeWidth === 0 ? "" : "10px dashed black"}`
- }}>
- </div>
+ <canvas className="PdfPage-canvasContainer" ref={this._canvas} />
+ <div className="pdfPage-dragAnnotationBox" ref={this._marquee}
+ style={{
+ left: `${this._marqueeX}px`, top: `${this._marqueeY}px`,
+ width: `${this._marqueeWidth}px`, height: `${this._marqueeHeight}px`,
+ border: `${this._marqueeWidth === 0 ? "" : "10px dashed black"}`
+ }}>
</div>
- <div className="pdfPage-textlayer"
- ref={this._textLayer}
- style={{ top: `-${2 * this._height}px`, height: `${this._height}px` }}
- />
+ <div className="pdfPage-textlayer" ref={this._textLayer} />
</div>
);
}
-}
+} \ No newline at end of file