viewerjs-rails 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,356 +30,356 @@ var FIND_SCROLL_OFFSET_LEFT = -400;
30
30
  * text that is being searched for.
31
31
  */
32
32
  var TextLayerBuilder = function textLayerBuilder(options) {
33
- var textLayerFrag = document.createDocumentFragment();
34
-
35
- this.textLayerDiv = options.textLayerDiv;
36
- this.layoutDone = false;
37
- this.divContentDone = false;
38
- this.pageIdx = options.pageIndex;
39
- this.matches = [];
40
- this.lastScrollSource = options.lastScrollSource;
41
- this.viewport = options.viewport;
42
- this.isViewerInPresentationMode = options.isViewerInPresentationMode;
43
-
44
- if(typeof PDFFindController === 'undefined') {
45
- window.PDFFindController = null;
46
- }
47
-
48
- if(typeof this.lastScrollSource === 'undefined') {
49
- this.lastScrollSource = null;
50
- }
51
-
52
- this.beginLayout = function textLayerBuilderBeginLayout() {
53
- this.textDivs = [];
54
- this.renderingDone = false;
55
- };
56
-
57
- this.endLayout = function textLayerBuilderEndLayout() {
58
- this.layoutDone = true;
59
- this.insertDivContent();
60
- };
61
-
62
- this.renderLayer = function textLayerBuilderRenderLayer() {
63
- var self = this;
64
- var textDivs = this.textDivs;
65
- var bidiTexts = this.textContent;
66
- var textLayerDiv = this.textLayerDiv;
67
- var canvas = document.createElement('canvas');
68
- var ctx = canvas.getContext('2d');
69
-
70
- // No point in rendering so many divs as it'd make the browser unusable
71
- // even after the divs are rendered
72
- var MAX_TEXT_DIVS_TO_RENDER = 100000;
73
- if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER)
74
- return;
75
-
76
- for (var i = 0, ii = textDivs.length; i < ii; i++) {
77
- var textDiv = textDivs[i];
78
- if ('isWhitespace' in textDiv.dataset) {
79
- continue;
80
- }
81
-
82
- ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
83
- var width = ctx.measureText(textDiv.textContent).width;
84
-
85
- if (width > 0) {
86
- textLayerFrag.appendChild(textDiv);
87
- var textScale = textDiv.dataset.canvasWidth / width;
88
- var rotation = textDiv.dataset.angle;
89
- var transform = 'scale(' + textScale + ', 1)';
90
- transform = 'rotate(' + rotation + 'deg) ' + transform;
91
- CustomStyle.setProp('transform' , textDiv, transform);
92
- CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
93
- }
33
+ var textLayerFrag = document.createDocumentFragment();
34
+
35
+ this.textLayerDiv = options.textLayerDiv;
36
+ this.layoutDone = false;
37
+ this.divContentDone = false;
38
+ this.pageIdx = options.pageIndex;
39
+ this.matches = [];
40
+ this.lastScrollSource = options.lastScrollSource;
41
+ this.viewport = options.viewport;
42
+ this.isViewerInPresentationMode = options.isViewerInPresentationMode;
43
+
44
+ if (typeof PDFFindController === 'undefined') {
45
+ window.PDFFindController = null;
94
46
  }
95
47
 
96
- textLayerDiv.appendChild(textLayerFrag);
97
- this.renderingDone = true;
98
- this.updateMatches();
99
- };
100
-
101
- this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
102
- // Schedule renderLayout() if user has been scrolling, otherwise
103
- // run it right away
104
- var RENDER_DELAY = 200; // in ms
105
- var self = this;
106
- var lastScroll = this.lastScrollSource === null ?
107
- 0 : this.lastScrollSource.lastScroll;
108
-
109
- if (Date.now() - lastScroll > RENDER_DELAY) {
110
- // Render right away
111
- this.renderLayer();
112
- } else {
113
- // Schedule
114
- if (this.renderTimer)
115
- clearTimeout(this.renderTimer);
116
- this.renderTimer = setTimeout(function() {
117
- self.setupRenderLayoutTimer();
118
- }, RENDER_DELAY);
119
- }
120
- };
121
-
122
- this.appendText = function textLayerBuilderAppendText(geom) {
123
- var textDiv = document.createElement('div');
124
-
125
- // vScale and hScale already contain the scaling to pixel units
126
- var fontHeight = geom.fontSize * Math.abs(geom.vScale);
127
- textDiv.dataset.canvasWidth = geom.canvasWidth * Math.abs(geom.hScale);
128
- textDiv.dataset.fontName = geom.fontName;
129
- textDiv.dataset.angle = geom.angle * (180 / Math.PI);
130
-
131
- textDiv.style.fontSize = fontHeight + 'px';
132
- textDiv.style.fontFamily = geom.fontFamily;
133
- var fontAscent = geom.ascent ? geom.ascent * fontHeight :
134
- geom.descent ? (1 + geom.descent) * fontHeight : fontHeight;
135
- textDiv.style.left = (geom.x + (fontAscent * Math.sin(geom.angle))) + 'px';
136
- textDiv.style.top = (geom.y - (fontAscent * Math.cos(geom.angle))) + 'px';
137
-
138
- // The content of the div is set in the `setTextContent` function.
139
-
140
- this.textDivs.push(textDiv);
141
- };
142
-
143
- this.insertDivContent = function textLayerUpdateTextContent() {
144
- // Only set the content of the divs once layout has finished, the content
145
- // for the divs is available and content is not yet set on the divs.
146
- if (!this.layoutDone || this.divContentDone || !this.textContent)
147
- return;
148
-
149
- this.divContentDone = true;
150
-
151
- var textDivs = this.textDivs;
152
- var bidiTexts = this.textContent;
153
-
154
- for (var i = 0; i < bidiTexts.length; i++) {
155
- var bidiText = bidiTexts[i];
156
- var textDiv = textDivs[i];
157
- if (!/\S/.test(bidiText.str)) {
158
- textDiv.dataset.isWhitespace = true;
159
- continue;
160
- }
161
-
162
- textDiv.textContent = bidiText.str;
163
- // TODO refactor text layer to use text content position
164
- /**
165
- * var arr = this.viewport.convertToViewportPoint(bidiText.x, bidiText.y);
166
- * textDiv.style.left = arr[0] + 'px';
167
- * textDiv.style.top = arr[1] + 'px';
168
- */
169
- // bidiText.dir may be 'ttb' for vertical texts.
170
- textDiv.dir = bidiText.dir;
48
+ if (typeof this.lastScrollSource === 'undefined') {
49
+ this.lastScrollSource = null;
171
50
  }
172
51
 
173
- this.setupRenderLayoutTimer();
174
- };
175
-
176
- this.setTextContent = function textLayerBuilderSetTextContent(textContent) {
177
- this.textContent = textContent;
178
- this.insertDivContent();
179
- };
180
-
181
- this.convertMatches = function textLayerBuilderConvertMatches(matches) {
182
- var i = 0;
183
- var iIndex = 0;
184
- var bidiTexts = this.textContent;
185
- var end = bidiTexts.length - 1;
186
- var queryLen = PDFFindController === null ?
187
- 0 : PDFFindController.state.query.length;
188
-
189
- var lastDivIdx = -1;
190
- var pos;
191
-
192
- var ret = [];
193
-
194
- // Loop over all the matches.
195
- for (var m = 0; m < matches.length; m++) {
196
- var matchIdx = matches[m];
197
- // # Calculate the begin position.
198
-
199
- // Loop over the divIdxs.
200
- while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
201
- iIndex += bidiTexts[i].str.length;
202
- i++;
203
- }
204
-
205
- // TODO: Do proper handling here if something goes wrong.
206
- if (i == bidiTexts.length) {
207
- console.error('Could not find matching mapping');
208
- }
209
-
210
- var match = {
211
- begin: {
212
- divIdx: i,
213
- offset: matchIdx - iIndex
52
+ this.beginLayout = function textLayerBuilderBeginLayout() {
53
+ this.textDivs = [];
54
+ this.renderingDone = false;
55
+ };
56
+
57
+ this.endLayout = function textLayerBuilderEndLayout() {
58
+ this.layoutDone = true;
59
+ this.insertDivContent();
60
+ };
61
+
62
+ this.renderLayer = function textLayerBuilderRenderLayer() {
63
+ var self = this;
64
+ var textDivs = this.textDivs;
65
+ var bidiTexts = this.textContent;
66
+ var textLayerDiv = this.textLayerDiv;
67
+ var canvas = document.createElement('canvas');
68
+ var ctx = canvas.getContext('2d');
69
+
70
+ // No point in rendering so many divs as it'd make the browser unusable
71
+ // even after the divs are rendered
72
+ var MAX_TEXT_DIVS_TO_RENDER = 100000;
73
+ if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER)
74
+ return;
75
+
76
+ for (var i = 0, ii = textDivs.length; i < ii; i++) {
77
+ var textDiv = textDivs[i];
78
+ if ('isWhitespace' in textDiv.dataset) {
79
+ continue;
80
+ }
81
+
82
+ ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
83
+ var width = ctx.measureText(textDiv.textContent).width;
84
+
85
+ if (width > 0) {
86
+ textLayerFrag.appendChild(textDiv);
87
+ var textScale = textDiv.dataset.canvasWidth / width;
88
+ var rotation = textDiv.dataset.angle;
89
+ var transform = 'scale(' + textScale + ', 1)';
90
+ transform = 'rotate(' + rotation + 'deg) ' + transform;
91
+ CustomStyle.setProp('transform', textDiv, transform);
92
+ CustomStyle.setProp('transformOrigin', textDiv, '0% 0%');
93
+ }
214
94
  }
215
- };
216
-
217
- // # Calculate the end position.
218
- matchIdx += queryLen;
219
-
220
- // Somewhat same array as above, but use a > instead of >= to get the end
221
- // position right.
222
- while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
223
- iIndex += bidiTexts[i].str.length;
224
- i++;
225
- }
226
-
227
- match.end = {
228
- divIdx: i,
229
- offset: matchIdx - iIndex
230
- };
231
- ret.push(match);
232
- }
233
95
 
234
- return ret;
235
- };
96
+ textLayerDiv.appendChild(textLayerFrag);
97
+ this.renderingDone = true;
98
+ this.updateMatches();
99
+ };
236
100
 
237
- this.renderMatches = function textLayerBuilder_renderMatches(matches) {
238
- // Early exit if there is nothing to render.
239
- if (matches.length === 0) {
240
- return;
241
- }
101
+ this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
102
+ // Schedule renderLayout() if user has been scrolling, otherwise
103
+ // run it right away
104
+ var RENDER_DELAY = 200; // in ms
105
+ var self = this;
106
+ var lastScroll = this.lastScrollSource === null ?
107
+ 0 : this.lastScrollSource.lastScroll;
108
+
109
+ if (Date.now() - lastScroll > RENDER_DELAY) {
110
+ // Render right away
111
+ this.renderLayer();
112
+ } else {
113
+ // Schedule
114
+ if (this.renderTimer)
115
+ clearTimeout(this.renderTimer);
116
+ this.renderTimer = setTimeout(function () {
117
+ self.setupRenderLayoutTimer();
118
+ }, RENDER_DELAY);
119
+ }
120
+ };
242
121
 
243
- var bidiTexts = this.textContent;
244
- var textDivs = this.textDivs;
245
- var prevEnd = null;
246
- var isSelectedPage = PDFFindController === null ?
247
- false : (this.pageIdx === PDFFindController.selected.pageIdx);
122
+ this.appendText = function textLayerBuilderAppendText(geom) {
123
+ var textDiv = document.createElement('div');
248
124
 
249
- var selectedMatchIdx = PDFFindController === null ?
250
- -1 : PDFFindController.selected.matchIdx;
125
+ // vScale and hScale already contain the scaling to pixel units
126
+ var fontHeight = geom.fontSize * Math.abs(geom.vScale);
127
+ textDiv.dataset.canvasWidth = geom.canvasWidth * Math.abs(geom.hScale);
128
+ textDiv.dataset.fontName = geom.fontName;
129
+ textDiv.dataset.angle = geom.angle * (180 / Math.PI);
251
130
 
252
- var highlightAll = PDFFindController === null ?
253
- false : PDFFindController.state.highlightAll;
131
+ textDiv.style.fontSize = fontHeight + 'px';
132
+ textDiv.style.fontFamily = geom.fontFamily;
133
+ var fontAscent = geom.ascent ? geom.ascent * fontHeight :
134
+ geom.descent ? (1 + geom.descent) * fontHeight : fontHeight;
135
+ textDiv.style.left = (geom.x + (fontAscent * Math.sin(geom.angle))) + 'px';
136
+ textDiv.style.top = (geom.y - (fontAscent * Math.cos(geom.angle))) + 'px';
254
137
 
255
- var infty = {
256
- divIdx: -1,
257
- offset: undefined
138
+ // The content of the div is set in the `setTextContent` function.
139
+
140
+ this.textDivs.push(textDiv);
258
141
  };
259
142
 
260
- function beginText(begin, className) {
261
- var divIdx = begin.divIdx;
262
- var div = textDivs[divIdx];
263
- div.textContent = '';
264
-
265
- var content = bidiTexts[divIdx].str.substring(0, begin.offset);
266
- var node = document.createTextNode(content);
267
- if (className) {
268
- var isSelected = isSelectedPage &&
269
- divIdx === selectedMatchIdx;
270
- var span = document.createElement('span');
271
- span.className = className + (isSelected ? ' selected' : '');
272
- span.appendChild(node);
273
- div.appendChild(span);
274
- return;
275
- }
276
- div.appendChild(node);
277
- }
143
+ this.insertDivContent = function textLayerUpdateTextContent() {
144
+ // Only set the content of the divs once layout has finished, the content
145
+ // for the divs is available and content is not yet set on the divs.
146
+ if (!this.layoutDone || this.divContentDone || !this.textContent)
147
+ return;
148
+
149
+ this.divContentDone = true;
150
+
151
+ var textDivs = this.textDivs;
152
+ var bidiTexts = this.textContent;
153
+
154
+ for (var i = 0; i < bidiTexts.length; i++) {
155
+ var bidiText = bidiTexts[i];
156
+ var textDiv = textDivs[i];
157
+ if (!/\S/.test(bidiText.str)) {
158
+ textDiv.dataset.isWhitespace = true;
159
+ continue;
160
+ }
161
+
162
+ textDiv.textContent = bidiText.str;
163
+ // TODO refactor text layer to use text content position
164
+ /**
165
+ * var arr = this.viewport.convertToViewportPoint(bidiText.x, bidiText.y);
166
+ * textDiv.style.left = arr[0] + 'px';
167
+ * textDiv.style.top = arr[1] + 'px';
168
+ */
169
+ // bidiText.dir may be 'ttb' for vertical texts.
170
+ textDiv.dir = bidiText.dir;
171
+ }
278
172
 
279
- function appendText(from, to, className) {
280
- var divIdx = from.divIdx;
281
- var div = textDivs[divIdx];
282
-
283
- var content = bidiTexts[divIdx].str.substring(from.offset, to.offset);
284
- var node = document.createTextNode(content);
285
- if (className) {
286
- var span = document.createElement('span');
287
- span.className = className;
288
- span.appendChild(node);
289
- div.appendChild(span);
290
- return;
291
- }
292
- div.appendChild(node);
293
- }
173
+ this.setupRenderLayoutTimer();
174
+ };
294
175
 
295
- function highlightDiv(divIdx, className) {
296
- textDivs[divIdx].className = className;
297
- }
176
+ this.setTextContent = function textLayerBuilderSetTextContent(textContent) {
177
+ this.textContent = textContent;
178
+ this.insertDivContent();
179
+ };
298
180
 
299
- var i0 = selectedMatchIdx, i1 = i0 + 1, i;
181
+ this.convertMatches = function textLayerBuilderConvertMatches(matches) {
182
+ var i = 0;
183
+ var iIndex = 0;
184
+ var bidiTexts = this.textContent;
185
+ var end = bidiTexts.length - 1;
186
+ var queryLen = PDFFindController === null ?
187
+ 0 : PDFFindController.state.query.length;
188
+
189
+ var lastDivIdx = -1;
190
+ var pos;
191
+
192
+ var ret = [];
193
+
194
+ // Loop over all the matches.
195
+ for (var m = 0; m < matches.length; m++) {
196
+ var matchIdx = matches[m];
197
+ // # Calculate the begin position.
198
+
199
+ // Loop over the divIdxs.
200
+ while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
201
+ iIndex += bidiTexts[i].str.length;
202
+ i++;
203
+ }
204
+
205
+ // TODO: Do proper handling here if something goes wrong.
206
+ if (i == bidiTexts.length) {
207
+ console.error('Could not find matching mapping');
208
+ }
209
+
210
+ var match = {
211
+ begin: {
212
+ divIdx: i,
213
+ offset: matchIdx - iIndex
214
+ }
215
+ };
216
+
217
+ // # Calculate the end position.
218
+ matchIdx += queryLen;
219
+
220
+ // Somewhat same array as above, but use a > instead of >= to get the end
221
+ // position right.
222
+ while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
223
+ iIndex += bidiTexts[i].str.length;
224
+ i++;
225
+ }
226
+
227
+ match.end = {
228
+ divIdx: i,
229
+ offset: matchIdx - iIndex
230
+ };
231
+ ret.push(match);
232
+ }
300
233
 
301
- if (highlightAll) {
302
- i0 = 0;
303
- i1 = matches.length;
304
- } else if (!isSelectedPage) {
305
- // Not highlighting all and this isn't the selected page, so do nothing.
306
- return;
307
- }
234
+ return ret;
235
+ };
308
236
 
309
- for (i = i0; i < i1; i++) {
310
- var match = matches[i];
311
- var begin = match.begin;
312
- var end = match.end;
313
-
314
- var isSelected = isSelectedPage && i === selectedMatchIdx;
315
- var highlightSuffix = (isSelected ? ' selected' : '');
316
- if (isSelected && !this.isViewerInPresentationMode) {
317
- scrollIntoView(textDivs[begin.divIdx], { top: FIND_SCROLL_OFFSET_TOP,
318
- left: FIND_SCROLL_OFFSET_LEFT });
319
- }
320
-
321
- // Match inside new div.
322
- if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
323
- // If there was a previous div, then add the text at the end
324
- if (prevEnd !== null) {
325
- appendText(prevEnd, infty);
237
+ this.renderMatches = function textLayerBuilder_renderMatches(matches) {
238
+ // Early exit if there is nothing to render.
239
+ if (matches.length === 0) {
240
+ return;
326
241
  }
327
- // clears the divs and set the content until the begin point.
328
- beginText(begin);
329
- } else {
330
- appendText(prevEnd, begin);
331
- }
332
-
333
- if (begin.divIdx === end.divIdx) {
334
- appendText(begin, end, 'highlight' + highlightSuffix);
335
- } else {
336
- appendText(begin, infty, 'highlight begin' + highlightSuffix);
337
- for (var n = begin.divIdx + 1; n < end.divIdx; n++) {
338
- highlightDiv(n, 'highlight middle' + highlightSuffix);
242
+
243
+ var bidiTexts = this.textContent;
244
+ var textDivs = this.textDivs;
245
+ var prevEnd = null;
246
+ var isSelectedPage = PDFFindController === null ?
247
+ false : (this.pageIdx === PDFFindController.selected.pageIdx);
248
+
249
+ var selectedMatchIdx = PDFFindController === null ?
250
+ -1 : PDFFindController.selected.matchIdx;
251
+
252
+ var highlightAll = PDFFindController === null ?
253
+ false : PDFFindController.state.highlightAll;
254
+
255
+ var infty = {
256
+ divIdx: -1,
257
+ offset: undefined
258
+ };
259
+
260
+ function beginText(begin, className) {
261
+ var divIdx = begin.divIdx;
262
+ var div = textDivs[divIdx];
263
+ div.textContent = '';
264
+
265
+ var content = bidiTexts[divIdx].str.substring(0, begin.offset);
266
+ var node = document.createTextNode(content);
267
+ if (className) {
268
+ var isSelected = isSelectedPage &&
269
+ divIdx === selectedMatchIdx;
270
+ var span = document.createElement('span');
271
+ span.className = className + (isSelected ? ' selected' : '');
272
+ span.appendChild(node);
273
+ div.appendChild(span);
274
+ return;
275
+ }
276
+ div.appendChild(node);
339
277
  }
340
- beginText(end, 'highlight end' + highlightSuffix);
341
- }
342
- prevEnd = end;
343
- }
344
278
 
345
- if (prevEnd) {
346
- appendText(prevEnd, infty);
347
- }
348
- };
349
-
350
- this.updateMatches = function textLayerUpdateMatches() {
351
- // Only show matches, once all rendering is done.
352
- if (!this.renderingDone)
353
- return;
354
-
355
- // Clear out all matches.
356
- var matches = this.matches;
357
- var textDivs = this.textDivs;
358
- var bidiTexts = this.textContent;
359
- var clearedUntilDivIdx = -1;
360
-
361
- // Clear out all current matches.
362
- for (var i = 0; i < matches.length; i++) {
363
- var match = matches[i];
364
- var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
365
- for (var n = begin; n <= match.end.divIdx; n++) {
366
- var div = textDivs[n];
367
- div.textContent = bidiTexts[n].str;
368
- div.className = '';
369
- }
370
- clearedUntilDivIdx = match.end.divIdx + 1;
371
- }
279
+ function appendText(from, to, className) {
280
+ var divIdx = from.divIdx;
281
+ var div = textDivs[divIdx];
282
+
283
+ var content = bidiTexts[divIdx].str.substring(from.offset, to.offset);
284
+ var node = document.createTextNode(content);
285
+ if (className) {
286
+ var span = document.createElement('span');
287
+ span.className = className;
288
+ span.appendChild(node);
289
+ div.appendChild(span);
290
+ return;
291
+ }
292
+ div.appendChild(node);
293
+ }
372
294
 
373
- if (PDFFindController === null || !PDFFindController.active)
374
- return;
295
+ function highlightDiv(divIdx, className) {
296
+ textDivs[divIdx].className = className;
297
+ }
375
298
 
376
- // Convert the matches on the page controller into the match format used
377
- // for the textLayer.
378
- this.matches = matches =
379
- this.convertMatches(PDFFindController === null ?
380
- [] : (PDFFindController.pageMatches[this.pageIdx] || []));
299
+ var i0 = selectedMatchIdx, i1 = i0 + 1, i;
381
300
 
382
- this.renderMatches(this.matches);
383
- };
301
+ if (highlightAll) {
302
+ i0 = 0;
303
+ i1 = matches.length;
304
+ } else if (!isSelectedPage) {
305
+ // Not highlighting all and this isn't the selected page, so do nothing.
306
+ return;
307
+ }
308
+
309
+ for (i = i0; i < i1; i++) {
310
+ var match = matches[i];
311
+ var begin = match.begin;
312
+ var end = match.end;
313
+
314
+ var isSelected = isSelectedPage && i === selectedMatchIdx;
315
+ var highlightSuffix = (isSelected ? ' selected' : '');
316
+ if (isSelected && !this.isViewerInPresentationMode) {
317
+ scrollIntoView(textDivs[begin.divIdx], { top: FIND_SCROLL_OFFSET_TOP,
318
+ left: FIND_SCROLL_OFFSET_LEFT });
319
+ }
320
+
321
+ // Match inside new div.
322
+ if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
323
+ // If there was a previous div, then add the text at the end
324
+ if (prevEnd !== null) {
325
+ appendText(prevEnd, infty);
326
+ }
327
+ // clears the divs and set the content until the begin point.
328
+ beginText(begin);
329
+ } else {
330
+ appendText(prevEnd, begin);
331
+ }
332
+
333
+ if (begin.divIdx === end.divIdx) {
334
+ appendText(begin, end, 'highlight' + highlightSuffix);
335
+ } else {
336
+ appendText(begin, infty, 'highlight begin' + highlightSuffix);
337
+ for (var n = begin.divIdx + 1; n < end.divIdx; n++) {
338
+ highlightDiv(n, 'highlight middle' + highlightSuffix);
339
+ }
340
+ beginText(end, 'highlight end' + highlightSuffix);
341
+ }
342
+ prevEnd = end;
343
+ }
344
+
345
+ if (prevEnd) {
346
+ appendText(prevEnd, infty);
347
+ }
348
+ };
349
+
350
+ this.updateMatches = function textLayerUpdateMatches() {
351
+ // Only show matches, once all rendering is done.
352
+ if (!this.renderingDone)
353
+ return;
354
+
355
+ // Clear out all matches.
356
+ var matches = this.matches;
357
+ var textDivs = this.textDivs;
358
+ var bidiTexts = this.textContent;
359
+ var clearedUntilDivIdx = -1;
360
+
361
+ // Clear out all current matches.
362
+ for (var i = 0; i < matches.length; i++) {
363
+ var match = matches[i];
364
+ var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
365
+ for (var n = begin; n <= match.end.divIdx; n++) {
366
+ var div = textDivs[n];
367
+ div.textContent = bidiTexts[n].str;
368
+ div.className = '';
369
+ }
370
+ clearedUntilDivIdx = match.end.divIdx + 1;
371
+ }
372
+
373
+ if (PDFFindController === null || !PDFFindController.active)
374
+ return;
375
+
376
+ // Convert the matches on the page controller into the match format used
377
+ // for the textLayer.
378
+ this.matches = matches =
379
+ this.convertMatches(PDFFindController === null ?
380
+ [] : (PDFFindController.pageMatches[this.pageIdx] || []));
381
+
382
+ this.renderMatches(this.matches);
383
+ };
384
384
  };
385
385