UNPKG

4.75 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * JavaScript code in this page
4 *
5 * Copyright 2022 Mozilla Foundation
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * @licend The above is the entire license notice for the
20 * JavaScript code in this page
21 */
22"use strict";
23
24Object.defineProperty(exports, "__esModule", {
25 value: true
26});
27exports.TextLayerBuilder = void 0;
28
29var _pdf = require("../pdf");
30
31const EXPAND_DIVS_TIMEOUT = 300;
32
33class TextLayerBuilder {
34 constructor({
35 textLayerDiv,
36 eventBus,
37 pageIndex,
38 viewport,
39 highlighter = null,
40 enhanceTextSelection = false
41 }) {
42 this.textLayerDiv = textLayerDiv;
43 this.eventBus = eventBus;
44 this.textContent = null;
45 this.textContentItemsStr = [];
46 this.textContentStream = null;
47 this.renderingDone = false;
48 this.pageNumber = pageIndex + 1;
49 this.viewport = viewport;
50 this.textDivs = [];
51 this.textLayerRenderTask = null;
52 this.highlighter = highlighter;
53 this.enhanceTextSelection = enhanceTextSelection;
54
55 this._bindMouse();
56 }
57
58 _finishRendering() {
59 this.renderingDone = true;
60
61 if (!this.enhanceTextSelection) {
62 const endOfContent = document.createElement("div");
63 endOfContent.className = "endOfContent";
64 this.textLayerDiv.append(endOfContent);
65 }
66
67 this.eventBus.dispatch("textlayerrendered", {
68 source: this,
69 pageNumber: this.pageNumber,
70 numTextDivs: this.textDivs.length
71 });
72 }
73
74 render(timeout = 0) {
75 if (!(this.textContent || this.textContentStream) || this.renderingDone) {
76 return;
77 }
78
79 this.cancel();
80 this.textDivs.length = 0;
81 this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr);
82 const textLayerFrag = document.createDocumentFragment();
83 this.textLayerRenderTask = (0, _pdf.renderTextLayer)({
84 textContent: this.textContent,
85 textContentStream: this.textContentStream,
86 container: textLayerFrag,
87 viewport: this.viewport,
88 textDivs: this.textDivs,
89 textContentItemsStr: this.textContentItemsStr,
90 timeout,
91 enhanceTextSelection: this.enhanceTextSelection
92 });
93 this.textLayerRenderTask.promise.then(() => {
94 this.textLayerDiv.append(textLayerFrag);
95
96 this._finishRendering();
97
98 this.highlighter?.enable();
99 }, function (reason) {});
100 }
101
102 cancel() {
103 if (this.textLayerRenderTask) {
104 this.textLayerRenderTask.cancel();
105 this.textLayerRenderTask = null;
106 }
107
108 this.highlighter?.disable();
109 }
110
111 setTextContentStream(readableStream) {
112 this.cancel();
113 this.textContentStream = readableStream;
114 }
115
116 setTextContent(textContent) {
117 this.cancel();
118 this.textContent = textContent;
119 }
120
121 _bindMouse() {
122 const div = this.textLayerDiv;
123 let expandDivsTimer = null;
124 div.addEventListener("mousedown", evt => {
125 if (this.enhanceTextSelection && this.textLayerRenderTask) {
126 this.textLayerRenderTask.expandTextDivs(true);
127
128 if (expandDivsTimer) {
129 clearTimeout(expandDivsTimer);
130 expandDivsTimer = null;
131 }
132
133 return;
134 }
135
136 const end = div.querySelector(".endOfContent");
137
138 if (!end) {
139 return;
140 }
141
142 let adjustTop = evt.target !== div;
143 adjustTop = adjustTop && window.getComputedStyle(end).getPropertyValue("-moz-user-select") !== "none";
144
145 if (adjustTop) {
146 const divBounds = div.getBoundingClientRect();
147 const r = Math.max(0, (evt.pageY - divBounds.top) / divBounds.height);
148 end.style.top = (r * 100).toFixed(2) + "%";
149 }
150
151 end.classList.add("active");
152 });
153 div.addEventListener("mouseup", () => {
154 if (this.enhanceTextSelection && this.textLayerRenderTask) {
155 expandDivsTimer = setTimeout(() => {
156 if (this.textLayerRenderTask) {
157 this.textLayerRenderTask.expandTextDivs(false);
158 }
159
160 expandDivsTimer = null;
161 }, EXPAND_DIVS_TIMEOUT);
162 return;
163 }
164
165 const end = div.querySelector(".endOfContent");
166
167 if (!end) {
168 return;
169 }
170
171 end.style.top = "";
172 end.classList.remove("active");
173 });
174 }
175
176}
177
178exports.TextLayerBuilder = TextLayerBuilder;
\No newline at end of file