aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Main.tsx7
-rw-r--r--src/documents/Documents.ts8
-rw-r--r--src/views/nodes/Annotation.tsx12
-rw-r--r--src/views/nodes/DocumentView.tsx3
-rw-r--r--src/views/nodes/ImageBox.tsx386
-rw-r--r--src/views/nodes/PDFNode.tsx52
6 files changed, 62 insertions, 406 deletions
diff --git a/src/Main.tsx b/src/Main.tsx
index f29dd192e..e2e1137da 100644
--- a/src/Main.tsx
+++ b/src/Main.tsx
@@ -48,9 +48,10 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
let doc2 = doc1.MakeDelegate();
doc2.Set(KS.X, new NumberField(150));
doc2.Set(KS.Y, new NumberField(20));
- let doc3 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
- x:0, y: 0, width: 500, height: 500,title: "cat 1"
- });
+
+ //let doc3 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
+ //x:0, y: 0, width: 500, height: 500,title: "cat 1"
+ //});
// const schemaDocs = Array.from(Array(5).keys()).map(v => Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
// x: 50 + 100 * v, y: 50, width: 100, height: 100, title: "cat" + v
diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts
index 56ebbf565..657856801 100644
--- a/src/documents/Documents.ts
+++ b/src/documents/Documents.ts
@@ -135,14 +135,14 @@ export namespace Documents {
let PDFProto = new Document();
PDFProtoId = PDFProto.Id;
PDFProto.Set(KeyStore.Title, new TextField("PDF PROTO"));
- PDFProto.Set(KeyStore.X, new NumberField(0));
+ PDFProto.Set(KeyStore.X, new NumberField(0));
PDFProto.Set(KeyStore.Y, new NumberField(0));
PDFProto.Set(KeyStore.Width, new NumberField(300));
- PDFProto.Set(KeyStore.Height, new NumberField(300));
- PDFProto.Set(KeyStore.Layout, new TextField(PDFNode.LayoutString()));
+ PDFProto.Set(KeyStore.Height, new NumberField(300));
+ PDFProto.Set(KeyStore.Layout, new TextField(PDFNode.LayoutString()));
PDFProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
Server.AddDocument(PDFProto);
- return PDFProto;
+ return PDFProto;
}
return Server.GetDocument(PDFProtoId, true)!;
}
diff --git a/src/views/nodes/Annotation.tsx b/src/views/nodes/Annotation.tsx
index 6929aea76..0ba05ba3d 100644
--- a/src/views/nodes/Annotation.tsx
+++ b/src/views/nodes/Annotation.tsx
@@ -8,6 +8,7 @@ interface IProps{
Span: HTMLSpanElement;
X: number;
Y: number;
+ Highlights: any[];
}
@@ -47,8 +48,15 @@ export class Annotation extends React.Component<IProps> {
let nodesArray = this.props.Span.parentElement.childNodes;
nodesArray.forEach((e) => {
if (e == this.props.Span){
- if (this.props.Span.parentElement){
- e.remove();
+ if (this.props.Span.parentElement){
+ this.props.Highlights.forEach((item) => {
+ if (item == e){
+ item.remove();
+ }
+ })
+ e.remove();
+
+
}
}
diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx
index 81353cd60..df97a0281 100644
--- a/src/views/nodes/DocumentView.tsx
+++ b/src/views/nodes/DocumentView.tsx
@@ -13,6 +13,7 @@ import { CollectionSchemaView } from "../collections/CollectionSchemaView";
import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "../collections/CollectionViewBase";
import { FormattedTextBox } from "../nodes/FormattedTextBox";
import { ImageBox } from "../nodes/ImageBox";
+import {PDFNode} from "../nodes/PDFNode";
import "./NodeView.scss";
import React = require("react");
const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
@@ -141,7 +142,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return (
<div className="node" ref={this._mainCont} style={{ width: "100%", height: "100%", }}>
<JsxParser
- components={{ FormattedTextBox: FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
+ components={{ FormattedTextBox: FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, PDFNode}}
bindings={bindings}
jsx={this.layout}
showWarnings={true}
diff --git a/src/views/nodes/ImageBox.tsx b/src/views/nodes/ImageBox.tsx
index c145280a1..566e5716e 100644
--- a/src/views/nodes/ImageBox.tsx
+++ b/src/views/nodes/ImageBox.tsx
@@ -8,393 +8,13 @@ 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 { Sticky } from './Sticky';
import { Annotation } from './Annotation';
-/** ALSO LOOK AT: Annotation.tsx, Sticky.tsx
- *
- * Ok, so I know I built PDFNode on a ImageBox, but this method works... maybe make a duplicate
- * and call it PDFNode.
- * 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.
- *
- * Clearly, everything works perfectly. No bugs. Might as well publish it.
- *
- * ps watch out for some bugs. When highlighting, just highlight a section of one line... do not multiline highlight... plz
- *
- *
- *
- *
- *
- * 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
+/** PDF has been moved to PDFNode now. This is now a dummy ImageBox that should be replaced with current
+ * ImageBox.
*/
@observer
export class ImageBox extends React.Component<FieldViewProps> {
public static LayoutString() { return FieldView.LayoutString("ImageBox"); }
-
- 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 private stickies:any[] = [] //for storing CURRENT stickies
- @observable private page:number = 1; //default is the first page.
- @observable private numPage:number = 1; //default number of pages
- @observable private stickiesPerPage: any = null; //for indexing stickies for EVERY PAGE
- @observable private annotations:any[] = []; //keeps track of annotations
-
- /**
- * for pagination backwards
- */
- @action
- onPageBack = () => {
- if (this.page > 1){
- this.page -= 1;
- this.stickiesPerPage[this.page] = this.stickies; //stores previous sticky and indexes to stickiesPerPage
- this.stickies = []; //sets stickies to null array
- if (this.stickies){//checks stickies is null or not
- this.stickies = this.stickiesPerPage[this.page - 1]; //pulls up stickies for this page
- }
-
- }
- }
-
- /**
- * for pagination forwards
- */
- @action
- onPageForward = () => {
- if (this.page < this.numPage){
- this.page += 1;
- this.stickiesPerPage[this.page - 2] = this.stickies; //stores previous sticky and indexes to stickiesPerPage
- this.stickies = []; //sets stickies to null array
- if (this.stickiesPerPage[this.page - 1]){
- this.stickies = this.stickiesPerPage[this.page - 1]; //pulls up sticky for this page
- }
- }
- }
-
- /**
- * 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;
- document.addEventListener("pointermove", this.drawMove);
- document.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();
- document.removeEventListener("pointermove", this.drawMove);
- document.removeEventListener("pointerdown", this.drawDown);
- document.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 element = range.commonAncestorContainer.parentElement
- if (element){
- let childNodes = element.childNodes;
- childNodes.forEach((e) => {
- if (e.nodeName == "SPAN"){
- let span = e;
- span.addEventListener("mouseover", this.onEnter);
- }
- })
- }
- }
- document.designMode = "off";
- }
-
- /**
- * when the cursor enters the highlight, it pops out annotation. ONLY WORKS FOR SINGLE DIV LINES
- */
- @action
- onEnter = (e:any) => {
- let span:HTMLSpanElement = e.toElement;
- this.currSpan = span;
- if (e.toElement instanceof HTMLSpanElement){
- this.bool = true;
- this.currSpan = span;
- if(span.children.length == 0){ //this is why it only works for one div text lines... needs fix
- if(span.offsetParent){
- 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 = {this.currSpan} X = {divX} Y = {divY - 300} />
- this.annotations.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);
- }
- //when the color is not the highlight 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.stickies.push(sticky);
- }
- this._toolOn = false;
- }
-
- }
-
- /**
- * starts drawing the line when user presses down.
- */
- onDraw = () => {
- if (this._currTool != null){
- this._currTool.style.backgroundColor = "grey";
- }
- this._highlightToolOn = false;
- if (this._drawTool.current){
- this._currTool = this._drawTool.current;
- if (this._drawToolOn){
- this._drawToolOn = false;
- document.removeEventListener("pointerdown", this.drawDown);
- document.removeEventListener("pointerup", this.drawUp);
- document.removeEventListener("pointermove", this.drawMove);
- this._drawTool.current.style.backgroundColor = "grey";
- } else {
- this._drawToolOn = true;
- document.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.highlight("rgba(76, 175, 80, 0.3)");
- this._highlightTool.current.style.backgroundColor = "orange";
- }
- }
- }
-
-
- /**
- * renders whole lot of shets, including pdf, stickies, and annotations.
- */
-
- render() {
- return (
- <div ref = {this._mainDiv}
- onPointerDown ={this.onPointerDown}
- onPointerUp = {this.onPointerUp}
- >
- {this.stickies.filter( () => { //for loading stickies (area)
- return this.stickies[this.stickies.length - 1]
- }).map( (element: any) => {
- return element
- })
- }
- {this.annotations.filter( () => { //for loading annotations
- return this.annotations[this.annotations.length - 1]
- }).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"){
- //@ts-ignore
- this._pdfContext = e.getContext("2d")
- }
- })
- }
- })
- }
- this.numPage = page.transport.numPages
- if (this.stickiesPerPage == null){ //only runs once, when stickiesPerPage is null
- this.stickiesPerPage = [...Array(this.numPage)].map(() => Array(1));
- }
- }
- }
- />
- </Document>
- </div>
- );
- }
} \ No newline at end of file
diff --git a/src/views/nodes/PDFNode.tsx b/src/views/nodes/PDFNode.tsx
index 814a59500..d55e4d6d7 100644
--- a/src/views/nodes/PDFNode.tsx
+++ b/src/views/nodes/PDFNode.tsx
@@ -12,9 +12,6 @@ import { Sticky } from './Sticky'; //you should look at sticky and annotation, b
import { Annotation } from './Annotation';
/** ALSO LOOK AT: Annotation.tsx, Sticky.tsx
- *
- * Ok, so I know I built PDFNode on a ImageBox, but this method works... maybe make a duplicate
- * and call it PDFNode.
* 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.
@@ -22,10 +19,7 @@ import { Annotation } from './Annotation';
* Clearly, everything works perfectly. No bugs. Might as well publish it.
*
* ps watch out for some bugs. When highlighting, just highlight a section of one line... do not multiline highlight... plz
- *
- *
- *
- *
+ * Annotations and Stickies save per page. Highlights do not.
*
* HOW TO USE:
* AREA selection:
@@ -54,7 +48,7 @@ import { Annotation } from './Annotation';
*/
@observer
export class PDFNode extends React.Component<FieldViewProps> {
- public static LayoutString() { return FieldView.LayoutString("ImageBox"); }
+ public static LayoutString() { return FieldView.LayoutString("PDFNode"); }
private _mainDiv = React.createRef<HTMLDivElement>()
private _pdf = React.createRef<HTMLCanvasElement>();
@@ -78,12 +72,17 @@ export class PDFNode extends React.Component<FieldViewProps> {
private _highlightTool = React.createRef<HTMLButtonElement>(); //highlighter button reference
private _highlightToolOn:boolean = false;
-
- @observable private stickies:any[] = [] //for storing CURRENT stickies
+
+
@observable private page:number = 1; //default is the first page.
@observable private numPage:number = 1; //default number of pages
- @observable private stickiesPerPage: any = null; //for indexing stickies for EVERY PAGE
+ @observable private stickies:any[] = [] //for storing CURRENT stickies
+ @observable private stickiesPerPage: any = null; //for indexing stickies for EVERY PAGE
@observable private annotations:any[] = []; //keeps track of annotations
+ @observable private annotationsPerPage: any = null; // for indexing annotations for EVERY PAGE
+ @observable private highlights:any[] = []; //keeps track of highlights.
+ @observable private highlightsPerPage:any = null; // for indexing highlights for EVERY PAGE
+
/**
* for pagination backwards
@@ -94,9 +93,20 @@ export class PDFNode extends React.Component<FieldViewProps> {
this.page -= 1;
this.stickiesPerPage[this.page] = this.stickies; //stores previous sticky and indexes to stickiesPerPage
this.stickies = []; //sets stickies to null array
+ this.annotationsPerPage[this.page] = this.annotations;
+ this.annotations = [];
+ this.highlightsPerPage[this.page] = this.highlights;
+ this.highlights = [];
if (this.stickies){//checks stickies is null or not
this.stickies = this.stickiesPerPage[this.page - 1]; //pulls up stickies for this page
}
+ if (this.annotations){//checks if annotation is null or not
+ this.annotations = this.annotationsPerPage[this.page - 1];
+ }
+ if (this.highlights){//checks if annotation is null or not
+ this.highlights = this.highlightsPerPage[this.page - 1];
+ }
+
}
}
@@ -104,15 +114,28 @@ export class PDFNode extends React.Component<FieldViewProps> {
/**
* for pagination forwards
*/
+
@action
onPageForward = () => {
+
if (this.page < this.numPage){
this.page += 1;
this.stickiesPerPage[this.page - 2] = this.stickies; //stores previous sticky and indexes to stickiesPerPage
this.stickies = []; //sets stickies to null array
+ this.annotationsPerPage[this.page - 2] = this.annotations;
+ this.annotations = [];
+ this.highlightsPerPage[this.page - 2] = this.highlights;
+ this.highlights = [];
if (this.stickiesPerPage[this.page - 1]){
this.stickies = this.stickiesPerPage[this.page - 1]; //pulls up sticky for this page
}
+ if (this.annotationsPerPage[this.page - 1]){
+ this.annotations = this.annotationsPerPage[this.page - 1]; //similar to sticky, it binds to previous annotation.
+ }
+ if (this.annotationsPerPage[this.page - 1]){
+ this.highlights = this.highlightsPerPage[this.page - 1]; //similar to sticky, it binds to previous highlight.
+ }
+
}
}
@@ -176,7 +199,8 @@ export class PDFNode extends React.Component<FieldViewProps> {
childNodes.forEach((e) => {
if (e.nodeName == "SPAN"){
let span = e;
- span.addEventListener("mouseover", this.onEnter);
+ this.highlights.push(span); //pushes span into highglights.
+ span.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
}
})
}
@@ -204,7 +228,7 @@ export class PDFNode extends React.Component<FieldViewProps> {
//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 = {this.currSpan} X = {divX} Y = {divY - 300} />
+ let annotation = <Annotation key ={Utils.GenerateGuid()} Span = {this.currSpan} X = {divX} Y = {divY - 300} Highlights = {this.highlights}/>
this.annotations.push(annotation);
}
}
@@ -389,6 +413,8 @@ export class PDFNode extends React.Component<FieldViewProps> {
this.numPage = page.transport.numPages
if (this.stickiesPerPage == null){ //only runs once, when stickiesPerPage is null
this.stickiesPerPage = [...Array(this.numPage)].map(() => Array(1));
+ this.annotationsPerPage = [...Array(this.numPage).map(()=> Array(1))];
+ this.highlightsPerPage = [...Array(this.numPage).map(() => Array(1))];
}
}
}