diff options
author | bobzel <zzzman@gmail.com> | 2019-09-21 00:50:32 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2019-09-21 00:50:32 -0400 |
commit | fbc3e35a52aee959ce3621f3bc58ffb2e869904d (patch) | |
tree | 48a89826cba23e47f183c36bae88f78f4f77ea9f /src | |
parent | 75cf84dd29e7b397e829a137a7c9845134d05984 (diff) |
fixed searching with pdf.
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 93 | ||||
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 71 | ||||
-rw-r--r-- | src/client/views/pdf/Page.scss | 5 |
3 files changed, 90 insertions, 79 deletions
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index ffec9f29b..764051d62 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -4,12 +4,13 @@ import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; import 'react-image-lightbox/style.css'; -import { Doc, WidthSym, Opt } from "../../../new_fields/Doc"; +import { Doc, Opt, WidthSym } from "../../../new_fields/Doc"; import { makeInterface } from "../../../new_fields/Schema"; -import { ScriptField, ComputedField } from '../../../new_fields/ScriptField'; -import { BoolCast, Cast, NumCast } from "../../../new_fields/Types"; +import { ComputedField, ScriptField } from '../../../new_fields/ScriptField'; +import { Cast, NumCast } from "../../../new_fields/Types"; import { PdfField } from "../../../new_fields/URLField"; import { KeyCodes } from '../../northstar/utils/KeyCodes'; +import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { DocComponent } from "../DocComponent"; import { InkingControl } from "../InkingControl"; import { PDFViewer } from "../pdf/PDFViewer"; @@ -18,24 +19,13 @@ import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); -import { Scripting } from '../../util/Scripting'; -type PdfDocument = makeInterface<[typeof documentSchema, typeof pageSchema]>; -const PdfDocument = makeInterface(documentSchema, pageSchema); -export const handleBackspace = (e: React.KeyboardEvent) => { if (e.keyCode === KeyCodes.BACKSPACE) e.stopPropagation(); }; +type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; +const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @observer export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocument) { public static LayoutString() { return FieldView.LayoutString(PDFBox); } - - @observable private _flyout: boolean = false; - @observable private _alt = false; - @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>; - - @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); } - - @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplate ? this.props.DataDoc : Doc.GetProto(this.props.Document); } - private _mainCont: React.RefObject<HTMLDivElement> = React.createRef(); private _reactionDisposer?: IReactionDisposer; private _keyValue: string = ""; @@ -45,19 +35,26 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen private _valueRef: React.RefObject<HTMLInputElement> = React.createRef(); private _scriptRef: React.RefObject<HTMLInputElement> = React.createRef(); + @observable private _flyout: boolean = false; + @observable private _alt = false; + @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>; + + @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); } + + @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplate ? this.props.DataDoc : Doc.GetProto(this.props.Document); } + componentDidMount() { this.props.setPdfBox && this.props.setPdfBox(this); - this.props.Document.pdfDoc = this.dataDoc; - this.props.Document.curPage = ComputedField.MakeFunction("Math.floor(Number(this.panY) / Number(this.pdfDoc.nativeHeight) + 1)"); + this.props.Document.curPage = ComputedField.MakeFunction("Math.floor(Number(this.panY) / Number(this.nativeHeight) + 1)"); const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); if (pdfUrl instanceof PdfField) { Pdfjs.getDocument(pdfUrl.url.pathname).promise.then(pdf => runInAction(() => this._pdf = pdf)); } this._reactionDisposer = reaction( - () => this.props.Document.panY, - () => this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.panY), behavior: "auto" }) + () => this.Document.panY, + () => this._mainCont.current && this._mainCont.current.scrollTo({ top: this.Document.panY || 0, behavior: "auto" }) ); } @@ -66,22 +63,22 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen } public GetPage() { - return Math.floor(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1; + return Math.floor((this.Document.panY || 0) / (this.Document.nativeHeight || 0)) + 1; } @action public BackPage() { - let cp = Math.ceil(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1; + let cp = Math.ceil((this.Document.panY || 0) / (this.Document.nativeHeight || 0)) + 1; cp = cp - 1; if (cp > 0) { - this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight); + this.Document.panY = (cp - 1) * (this.Document.nativeHeight || 0); } } @action - public GotoPage(p: number) { + public GotoPage = (p: number) => { if (p > 0 && p <= NumCast(this.dataDoc.numPages)) { - this.props.Document.panY = (p - 1) * NumCast(this.dataDoc.nativeHeight); + this.Document.panY = (p - 1) * (this.Document.nativeHeight || 0); } } @@ -89,20 +86,19 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen public ForwardPage() { let cp = this.GetPage() + 1; if (cp <= NumCast(this.dataDoc.numPages)) { - this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight); + this.Document.panY = (cp - 1) * (this.Document.nativeHeight || 0); } } @action setPanY = (y: number) => { - this.props.ContainingCollectionDoc && (this.props.ContainingCollectionDoc.panY = y); + this.Document.panY = y; } @action private applyFilter = () => { - let scriptText = this._scriptValue.length > 0 ? this._scriptValue : - this._keyValue.length > 0 && this._valueValue.length > 0 ? - `this.${this._keyValue} === ${this._valueValue}` : "true"; + let scriptText = this._scriptValue ? this._scriptValue : + this._keyValue && this._valueValue ? `this.${this._keyValue} === ${this._valueValue}` : "true"; this.props.Document.filterScript = ScriptField.MakeFunction(scriptText); } @@ -111,8 +107,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen } private resetFilters = () => { - this._keyValue = this._valueValue = ""; - this._scriptValue = ""; + this._keyValue = this._valueValue = this._scriptValue = ""; this._keyRef.current && (this._keyRef.current.value = ""); this._valueRef.current && (this._valueRef.current.value = ""); this._scriptRef.current && (this._scriptRef.current.value = ""); @@ -126,7 +121,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen return !this.props.active() ? (null) : (<div className="pdfBox-settingsCont" onPointerDown={(e) => e.stopPropagation()}> <button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings" - style={{ marginTop: `${this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.panY) : 0}px` }}> + style={{ marginTop: `${this.Document.panY || 0}px` }}> <div className="pdfBox-settingsButton-arrow" style={{ borderTop: `25px solid ${this._flyout ? "#121721" : "transparent"}`, @@ -143,13 +138,13 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen Annotation View Settings </div> <div className="pdfBox-settingsFlyout-kvpInput"> - <input placeholder="Key" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newKeyChange} + <input placeholder="Key" className="pdfBox-settingsFlyout-input" onChange={this.newKeyChange} style={{ gridColumn: 1 }} ref={this._keyRef} /> - <input placeholder="Value" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newValueChange} + <input placeholder="Value" className="pdfBox-settingsFlyout-input" onChange={this.newValueChange} style={{ gridColumn: 3 }} ref={this._valueRef} /> </div> <div className="pdfBox-settingsFlyout-kvpInput"> - <input placeholder="Custom Script" onChange={this.newScriptChange} onKeyDown={handleBackspace} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} /> + <input placeholder="Custom Script" onChange={this.newScriptChange} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} /> </div> <div className="pdfBox-settingsFlyout-kvpInput"> <button style={{ gridColumn: 1 }} onClick={this.resetFilters}> @@ -167,20 +162,20 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen loaded = (nw: number, nh: number, np: number) => { this.dataDoc.numPages = np; - if (!this.dataDoc.nativeWidth || !this.dataDoc.nativeHeight || !this.dataDoc.scrollHeight) { - let oldaspect = NumCast(this.dataDoc.nativeHeight) / NumCast(this.dataDoc.nativeWidth, 1); - this.dataDoc.nativeWidth = nw; - this.dataDoc.nativeHeight = this.dataDoc.nativeHeight ? nw * oldaspect : nh; - this.dataDoc.height = this.dataDoc[WidthSym]() * (nh / nw); - this.dataDoc.scrollHeight = np * this.dataDoc.nativeHeight; + if (!this.Document.nativeWidth || !this.Document.nativeHeight || !this.Document.scrollHeight) { + let oldaspect = (this.Document.nativeHeight || 0) / (this.Document.nativeWidth || 1); + this.Document.nativeWidth = nw; + this.Document.nativeHeight = this.Document.nativeHeight ? nw * oldaspect : nh; + this.Document.height = this.Document[WidthSym]() * (nh / nw); + this.Document.scrollHeight = np * this.Document.nativeHeight; } } @action onScroll = (e: React.UIEvent<HTMLDivElement>) => { if (e.currentTarget && this.props.ContainingCollectionDoc) { - this.props.ContainingCollectionDoc.panTransformType = "None"; - this.props.ContainingCollectionDoc.panY = e.currentTarget.scrollTop; + this.props.Document.panTransformType = "None"; + this.Document.panY = e.currentTarget.scrollTop; } } @@ -192,12 +187,12 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen <div>{`pdf, ${this.dataDoc[this.props.fieldKey]}, not found`}</div> : <div className={classname} onScroll={this.onScroll} - style={{ marginTop: `${this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.panY) : 0}px` }} + style={{ marginTop: `${(this.Document.panY || 0)}px` }} ref={this._mainCont}> - do<div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + (NumCast(this.props.Document.nativeHeight) - NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.scale, 1)), width: "100%" }} /> - <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={NumCast(this.props.Document.panY)} - Document={this.props.Document} DataDoc={this.props.DataDoc} - addDocTab={this.props.addDocTab} setPanY={this.setPanY} + <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + ((this.Document.nativeHeight || 0) - (this.Document.nativeHeight || 0) / (this.Document.scale || 1)) }} /> + <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={this.Document.panY || 0} + Document={this.props.Document} DataDoc={this.dataDoc} + addDocTab={this.props.addDocTab} setPanY={this.setPanY} GoToPage={this.GotoPage} pinToPres={this.props.pinToPres} addDocument={this.props.addDocument} fieldKey={this.props.fieldKey} fieldExtensionDoc={this.extensionDoc} /> {this.settingsPanel()} diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 4afed0b95..c94b4e3a4 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; +import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; @@ -19,6 +19,7 @@ import Annotation from "./Annotation"; import Page from "./Page"; import "./PDFViewer.scss"; import React = require("react"); +import requestPromise = require("request-promise"); const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer"); export const scale = 2; @@ -35,6 +36,7 @@ interface IViewerProps { scrollTo: (y: number) => void; active: () => boolean; setPanY?: (n: number) => void; + GoToPage?: (n: number) => void; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean; @@ -61,7 +63,7 @@ export class PDFViewer extends React.Component<IViewerProps> { private _filterReactionDisposer?: IReactionDisposer; private _viewer: React.RefObject<HTMLDivElement> = React.createRef(); private _mainCont: React.RefObject<HTMLDivElement> = React.createRef(); - private _pdfViewer: any; + public _pdfViewer: any; private _pdfFindController: any; private _searchString: string = ""; private _selectionText: string = ""; @@ -363,7 +365,7 @@ export class PDFViewer extends React.Component<IViewerProps> { @action search = (searchString: string) => { if (this._pdfViewer._pageViewsReady) { - this._pdfFindController.executeCommand('find', { + this._pdfFindController.executeCommand('findagain', { caseSensitive: false, findPrevious: undefined, highlightAll: true, @@ -372,13 +374,15 @@ export class PDFViewer extends React.Component<IViewerProps> { }); } else if (this._mainCont.current) { - let executeFind = () => this._pdfFindController.executeCommand('find', { - caseSensitive: false, - findPrevious: undefined, - highlightAll: true, - phraseSearch: true, - query: searchString - }); + 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); } @@ -391,14 +395,14 @@ export class PDFViewer extends React.Component<IViewerProps> { this._searching = !this._searching; if (this._searching) { - if (!this._pdfFindController && this._mainCont.current && this._viewer.current) { - let simpleLinkService = new SimpleLinkService(); + if (!this._pdfFindController && this._mainCont.current && this._viewer.current && !this._pdfViewer) { + let simpleLinkService = new SimpleLinkService(this); this._pdfViewer = new PDFJSViewer.PDFViewer({ container: this._mainCont.current, viewer: this._viewer.current, linkService: simpleLinkService - }); - simpleLinkService.setPdf(this.props.pdf); + }) + simpleLinkService.setPDFJSview(this._pdfViewer); this._mainCont.current.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = 1); this._mainCont.current.addEventListener("pagerendered", () => console.log("rendered")); this._pdfViewer.setDocument(this.props.pdf); @@ -406,21 +410,16 @@ export class PDFViewer extends React.Component<IViewerProps> { this._pdfViewer.findController = this._pdfFindController; } } - else { - this._pdfFindController = null; - if (this._viewer.current) { - let cns = this._viewer.current.childNodes; - for (let i = cns.length - 1; i >= 0; i--) { - cns.item(i).remove(); - } - } - } + } + @computed get visibleElementWrapper() { + trace(); + return this._visibleElements; } render() { return (<div className="pdfViewer-viewer" ref={this._mainCont} > <div className="pdfViewer-visibleElements" style={this._searching ? { position: "absolute", top: 0 } : {}}> - {this._visibleElements} + {this.visibleElementWrapper} </div> <div className="pdfViewer-text" ref={this._viewer} /> <div className="pdfViewer-annotationLayer" style={{ height: NumCast(this.props.Document.nativeHeight) }} ref={this._annotationLayer}> @@ -458,9 +457,13 @@ export class PDFViewer extends React.Component<IViewerProps> { export enum AnnotationTypes { Region } class SimpleLinkService { - externalLinkTarget: any = null; - externalLinkRel: any = null; - pdf: any = null; + _viewer: PDFViewer; + _pdfjsView: any; + + constructor(viewer: PDFViewer) { + this._viewer = viewer; + } + setPDFJSview(v: any) { this._pdfjsView = v; } navigateTo() { } @@ -470,15 +473,23 @@ class SimpleLinkService { setHash() { } + isPageVisible(page: number) { return true; } + executeNamedAction() { } cachePageRef() { } - get pagesCount() { return this.pdf ? this.pdf.numPages : 0; } + get pagesCount() { return this._viewer._pdfViewer.pagesCount; } - get page() { return 0; } + get page() { return NumCast(this._viewer.props.Document.curPage); } + set page(p: number) { + this._pdfjsView._ensurePdfPageLoaded(this._pdfjsView._pages[p - 1]).then(() => { + this._pdfjsView.renderingQueue.renderView(this._pdfjsView._pages[p - 1]); + if (this._viewer.props.GoToPage) + this._viewer.props.GoToPage(p); + }); + } - setPdf(pdf: any) { this.pdf = pdf; } get rotation() { return 0; } set rotation(value: any) { } diff --git a/src/client/views/pdf/Page.scss b/src/client/views/pdf/Page.scss index af1628a6f..d8034b4b4 100644 --- a/src/client/views/pdf/Page.scss +++ b/src/client/views/pdf/Page.scss @@ -1,4 +1,9 @@ +.pdfViewer-text { + .page { + position: relative; + } +} .pdfPage-cont { position: relative; |