diff options
author | Andrew Kim <andrewdkim@users.noreply.github.com> | 2019-03-05 18:51:20 -0500 |
---|---|---|
committer | Andrew Kim <andrewdkim@users.noreply.github.com> | 2019-03-05 18:51:20 -0500 |
commit | 7f93e6639e8fee3e3760d13c69d65b343875091a (patch) | |
tree | d29b45310f92a53935177d969ce3c1bee9920c32 /src/views/nodes/PDFNode.tsx | |
parent | 9b839a93b98b850aa77087218d4862b97fb24d15 (diff) | |
parent | 2cc5eb6ff512dc6128d25903bcb852f25bcadcca (diff) |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into PDFNode
Diffstat (limited to 'src/views/nodes/PDFNode.tsx')
-rw-r--r-- | src/views/nodes/PDFNode.tsx | 452 |
1 files changed, 0 insertions, 452 deletions
diff --git a/src/views/nodes/PDFNode.tsx b/src/views/nodes/PDFNode.tsx deleted file mode 100644 index 8f30a3bec..000000000 --- a/src/views/nodes/PDFNode.tsx +++ /dev/null @@ -1,452 +0,0 @@ -import 'react-image-lightbox/style.css'; -import "./ImageBox.scss"; -import React = require("react") -import { FieldViewProps, FieldView } from './FieldView'; -import { observer } from "mobx-react" -import { observable, action } from 'mobx'; -import 'react-pdf/dist/Page/AnnotationLayer.css' -//@ts-ignore -import { Document, Page, PDFPageProxy, PageAnnotation} from "react-pdf"; -import { Utils } from '../../Utils'; -import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here -import { Annotation } from './Annotation'; -import { ObjectPositionProperty } from 'csstype'; -import { keydownHandler } from 'prosemirror-keymap'; - -/** ALSO LOOK AT: Annotation.tsx, Sticky.tsx - * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, - * area selection (I call it stickies), embedded ink node for directly annotating using a pen or - * mouse, and pagination. - * - * - * HOW TO USE: - * AREA selection: - * 1) Click on Area button. - * 2) click on any part of the PDF, and drag to get desired sized area shape - * 3) You can write on the area (hence the reason why it's called sticky) - * 4) to make another area, you need to click on area button AGAIN. - * - * HIGHLIGHT: (Buggy. No multiline/multidiv text highlighting for now...) - * 1) just click and drag on a text - * 2) click highlight - * 3) for annotation, just pull your cursor over to that text - * 4) another method: click on highlight first and then drag on your desired text - * 5) To make another highlight, you need to reclick on the button - * - * Draw: - * 1) click draw and select color. then just draw like there's no tomorrow. - * 2) once you finish drawing your masterpiece, just reclick on the draw button to end your drawing session. - * - * Pagination: - * 1) click on arrows. You'll notice that stickies will stay in those page. But... highlights won't. - * 2) to test this out, make few area/stickies and then click on next page then come back. You'll see that they are all saved. - * - * - * written by: Andrew Kim - */ -@observer -export class PDFNode extends React.Component<FieldViewProps> { - public static LayoutString() { return FieldView.LayoutString("PDFNode"); } - - private _mainDiv = React.createRef<HTMLDivElement>() - private _pdf = React.createRef<HTMLCanvasElement>(); - - //very useful for keeping track of X and y position throughout the PDF Canvas - private initX:number = 0; - private initY:number = 0; - - //checks if tool is on - private _toolOn:boolean = false; //checks if tool is on - private _pdfContext:any = null; //gets pdf context - private bool:Boolean = false; //general boolean debounce - private currSpan:any;//keeps track of current span (for highlighting) - - private _currTool: any; //keeps track of current tool button reference - private _drawToolOn:boolean = false; //boolean that keeps track of the drawing tool - private _drawTool = React.createRef<HTMLButtonElement>()//drawing tool button reference - - private _colorTool = React.createRef<HTMLButtonElement>(); //color button reference - private _currColor:string = "black"; //current color that user selected (for ink/pen) - - private _highlightTool = React.createRef<HTMLButtonElement>(); //highlighter button reference - private _highlightToolOn:boolean = false; - - @observable perPage:Object[] = []; //stores pageInfo - @observable pageInfo:any = {area:[], divs:[], anno: []}; //divs is array of objects linked to anno - - @observable private page:number = 1; //default is the first page. - @observable private numPage:number = 1; //default number of pages - private _pdfCanvas:any; - - /** - * for pagination backwards - */ - @action - onPageBack = () => { - if (this.page > 1){ - this.page -= 1; - this.currAnno = []; - this.perPage[this.page] = this.pageInfo - this.pageInfo = {area:[], divs:[], anno: []}; //resets the object to default - if (this.perPage[this.page - 1]){ - this.pageInfo = this.perPage[this.page - 1]; - } - } - } - - /** - * for pagination forwards - */ - @action - onPageForward = () => { - if (this.page < this.numPage){ - this.page += 1; - this.currAnno = []; - this.perPage[this.page - 2] = this.pageInfo; - this.pageInfo = {area:[], divs:[], anno: []}; //resets the object to default - if (this.perPage[this.page - 1]){ - this.pageInfo = this.perPage[this.page - 1]; - } - } - } - - /** - * selection tool used for area highlighting (stickies). Kinda temporary - */ - selectionTool = () => { - this._toolOn = true; - } - /** - * when user draws on the canvas. When mouse pointer is down - */ - drawDown = (e:PointerEvent) => { - this.initX = e.offsetX; - this.initY = e.offsetY; - this._pdfContext.beginPath(); - this._pdfContext.lineTo(this.initX, this.initY); - this._pdfContext.strokeStyle = this._currColor; - this._pdfCanvas.addEventListener("pointermove", this.drawMove); - this._pdfCanvas.addEventListener("pointerup", this.drawUp); - - } - //when user drags - drawMove = (e: PointerEvent):void =>{ - //x and y mouse movement - let x = this.initX += e.movementX, - y = this.initY += e.movementY; - //connects the point - this._pdfContext.lineTo(x, y); - this._pdfContext.stroke(); - } - - drawUp = (e:PointerEvent) => { - this._pdfContext.closePath(); - this._pdfCanvas.removeEventListener("pointermove", this.drawMove); - this._pdfCanvas.removeEventListener("pointerdown", this.drawDown); - this._pdfCanvas.addEventListener("pointerdown", this.drawDown); - } - - - /** - * highlighting helper function - */ - makeEditableAndHighlight = (colour:string) => { - var range, sel = window.getSelection(); - if (sel.rangeCount && sel.getRangeAt) { - range = sel.getRangeAt(0); - } - document.designMode = "on"; - if (!document.execCommand("HiliteColor", false, colour)) { - document.execCommand("HiliteColor", false, colour); - } - - if (range) { - sel.removeAllRanges(); - sel.addRange(range); - - let obj:Object = {parentDivs:[], spans:[]}; - //@ts-ignore - if (range.commonAncestorContainer.className == 'react-pdf__Page__textContent'){ //multiline highlighting case - obj = this.highlightNodes(range.commonAncestorContainer.childNodes) - } else{ //single line highlighting case - let parentDiv = range.commonAncestorContainer.parentElement - if (parentDiv){ - if (parentDiv.className == 'react-pdf__Page__textContent'){ //when highlight is overwritten - obj = this.highlightNodes(parentDiv.childNodes) - } else { - parentDiv.childNodes.forEach((child)=>{ - if (child.nodeName == 'SPAN'){ - //@ts-ignore - obj.parentDivs.push(parentDiv) - //@ts-ignore - child.id = "highlighted" - //@ts-ignore - obj.spans.push(child) - child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler - } - }) - } - } - } - this.pageInfo.divs.push(obj); - - } - document.designMode = "off"; - } - - highlightNodes = (nodes:NodeListOf<ChildNode>) => { - let temp = {parentDivs: [], spans: []} - nodes.forEach((div) => { - div.childNodes.forEach((child)=>{ - if (child.nodeName == 'SPAN'){ - //@ts-ignore - temp.parentDivs.push(div) - //@ts-ignore - child.id = "highlighted" - //@ts-ignore - temp.spans.push(child) - child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler - } - }) - - }) - return temp; - } - - /** - * when the cursor enters the highlight, it pops out annotation. ONLY WORKS FOR SINGLE DIV LINES - */ - @observable private currAnno:any = [] - @action - onEnter = (e:any) => { - let span:HTMLSpanElement = e.toElement; - let index:any; - this.pageInfo.divs.forEach((obj:any) =>{ - obj.spans.forEach((element:any) =>{ - if (element == span) { - if (!index){ - index = this.pageInfo.divs.indexOf(obj); - } - } - }) - }) - - if (this.pageInfo.anno.length >= index + 1){ - if (this.currAnno.length == 0){ - this.currAnno.push(this.pageInfo.anno[index]); - } - }else{ - if (this.currAnno.length == 0){ //if there are no current annotation - let div = span.offsetParent; - //@ts-ignore - let divX = div.style.left - //@ts-ignore - let divY = div.style.top - //slicing "px" from the end - divX = divX.slice(0, divX.length - 2); //gets X of the DIV element (parent of Span) - divY = divY.slice(0, divY.length - 2); //gets Y of the DIV element (parent of Span) - let annotation = <Annotation key ={Utils.GenerateGuid()} Span = {span} X = {divX} Y = {divY - 300} Highlights = {this.pageInfo.divs} Annotations = {this.pageInfo.anno} CurrAnno = {this.currAnno}/> - this.pageInfo.anno.push(annotation); - this.currAnno.push(annotation); - } - } - - } - - /** - * highlight function for highlighting actual text. This works fine. - */ - highlight = (color:string) => { - if (window.getSelection()) { - try { - if (!document.execCommand("hiliteColor", false, color)) { - this.makeEditableAndHighlight(color); - } - } catch (ex) { - this.makeEditableAndHighlight(color) - } - } - } - - /** - * controls the area highlighting (stickies) Kinda temporary - */ - onPointerDown = (e: React.PointerEvent) => { - if (this._toolOn){ - let mouse = e.nativeEvent; - this.initX = mouse.offsetX; - this.initY = mouse.offsetY; - - } - } - - /** - * controls area highlighting and partially highlighting. Kinda temporary - */ - @action - onPointerUp = (e:React.PointerEvent) => { - - if (this._highlightToolOn){ - this.highlight("rgba(76, 175, 80, 0.3)"); //highlights to this default color. - this._highlightToolOn = false; - } - if (this._toolOn){ - let mouse = e.nativeEvent; - let finalX = mouse.offsetX; - let finalY = mouse.offsetY; - let width = Math.abs(finalX - this.initX); //width - let height = Math.abs(finalY - this.initY); //height - - //these two if statements are bidirectional dragging. You can drag from any point to another point and generate sticky - if (finalX < this.initX){ - this.initX = finalX; - } - if (finalY < this.initY){ - this.initY = finalY; - } - - if (this._mainDiv.current){ - let sticky = <Sticky key ={Utils.GenerateGuid()} Height = {height} Width = {width} X = {this.initX} Y = {this.initY}/> - this.pageInfo.area.push(sticky); - } - this._toolOn = false; - } - - } - - /** - * starts drawing the line when user presses down. - */ - onDraw = () => { - if (this._currTool != null){ - this._currTool.style.backgroundColor = "grey"; - } - - if (this._drawTool.current){ - this._currTool = this._drawTool.current; - if (this._drawToolOn){ - this._drawToolOn = false; - this._pdfCanvas.removeEventListener("pointerdown", this.drawDown); - this._pdfCanvas.removeEventListener("pointerup", this.drawUp); - this._pdfCanvas.removeEventListener("pointermove", this.drawMove); - this._drawTool.current.style.backgroundColor = "grey"; - } else { - this._drawToolOn = true; - this._pdfCanvas.addEventListener("pointerdown", this.drawDown); - this._drawTool.current.style.backgroundColor = "cyan"; - } - } - } - - - /** - * for changing color (for ink/pen) - */ - onColorChange = (e:React.PointerEvent) => { - if (e.currentTarget.innerHTML == "Red"){ - this._currColor = "red"; - } else if (e.currentTarget.innerHTML == "Blue"){ - this._currColor = "blue"; - } else if (e.currentTarget.innerHTML == "Green"){ - this._currColor = "green"; - } else if (e.currentTarget.innerHTML == "Black"){ - this._currColor = "black"; - } - - } - - - /** - * For highlighting (text drag highlighting) - */ - onHighlight = () => { - this._drawToolOn = false; - if (this._currTool != null){ - this._currTool.style.backgroundColor = "grey"; - } - if (this._highlightTool.current){ - this._currTool = this._drawTool.current; - if (this._highlightToolOn){ - this._highlightToolOn = false; - this._highlightTool.current.style.backgroundColor = "grey"; - } else { - this._highlightToolOn = true; - this._highlightTool.current.style.backgroundColor = "orange"; - } - } - } - - - /** - * renders whole lot of shets, including pdf, stickies, and annotations. - */ - - reHighlight = () =>{ - let div = document.getElementsByClassName("react-pdf__Page__textContent"); - if (div){ - - } - - } - - - render() { - return ( - <div ref = {this._mainDiv} - onPointerDown ={this.onPointerDown} - onPointerUp = {this.onPointerUp} - > - - {this.pageInfo.area.filter( () => { - return this.pageInfo.area}).map((element: any) => { - return element - }) - } - {this.currAnno.map((element:any) => { - return element - })} - - <button onClick = {this.onPageBack}>{"<"}</button> - <button onClick = {this.onPageForward}>{">"}</button> - <button onClick ={this.selectionTool}>{"Area"}</button> - <button style ={{color: "white", backgroundColor: "grey"}} onClick = {this.onHighlight} ref = {this._highlightTool}>Highlight</button> - <button style ={{color: "white", backgroundColor: "grey"}} ref = {this._drawTool} onClick = {this.onDraw}>{"Draw"}</button> - <button ref = {this._colorTool} onPointerDown = {this.onColorChange}>{"Red"}</button> - <button ref = {this._colorTool} onPointerDown = {this.onColorChange}>{"Blue"}</button> - <button ref = {this._colorTool} onPointerDown = {this.onColorChange}>{"Green"}</button> - <button ref = {this._colorTool} onPointerDown = {this.onColorChange}>{"Black"}</button> - - <Document file={Utils.pdf_example}> - <Page - pageNumber={this.page} - onLoadSuccess={ - (page:any) => { - if (this._mainDiv.current){ - this._mainDiv.current.childNodes.forEach((element) => { - if (element.nodeName == "DIV"){ - element.childNodes[0].childNodes.forEach((e) => { - - if (e.nodeName == "CANVAS"){ - this._pdfCanvas = e; - //@ts-ignore - this._pdfContext = e.getContext("2d") - - } - - }) - } - }) - } - this.numPage = page.transport.numPages - if (this.perPage.length == 0){ //Makes sure it only runs once - this.perPage = [...Array(this.numPage)] - } - } - } - /> - </Document> - </div> - ); - } - -}
\ No newline at end of file |