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.
- checksums.yaml +4 -4
- data/README.md +4 -1
- data/app/assets/javascripts/pdf.worker.js +85404 -39091
- data/app/assets/javascripts/viewerjs/ODFViewerPlugin.js +7 -6
- data/app/assets/javascripts/viewerjs/PDFViewerPlugin.js.erb +1 -1
- data/app/assets/javascripts/viewerjs/PluginLoader.js +0 -1
- data/app/assets/javascripts/viewerjs/compatibility.js +403 -383
- data/app/assets/javascripts/viewerjs/pdf.js +7202 -7216
- data/app/assets/javascripts/viewerjs/pdf_find_bar.js +135 -133
- data/app/assets/javascripts/viewerjs/pdf_find_controller.js +291 -289
- data/app/assets/javascripts/viewerjs/text_layer_builder.js +327 -327
- data/app/assets/javascripts/viewerjs/ui_utils.js +181 -181
- data/app/assets/javascripts/viewerjs/{viewer.js → viewer.js.erb} +19 -19
- data/app/assets/javascripts/viewerjs/webodf.js +11863 -606
- data/app/assets/stylesheets/ODFViewerPlugin.css.scss +1 -1
- data/app/assets/stylesheets/PDFViewerPlugin.css.scss +18 -13
- data/app/assets/stylesheets/example.local.css.scss +6 -12
- data/app/assets/stylesheets/viewer.css.scss +36 -36
- data/lib/viewerjs/rails/version.rb +1 -1
- data/lib/viewerjs/view_helpers.rb +63 -54
- metadata +2 -2
@@ -27,149 +27,151 @@
|
|
27
27
|
*/
|
28
28
|
var PDFFindBar = {
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
30
|
+
opened: false,
|
31
|
+
bar: null,
|
32
|
+
toggleButton: null,
|
33
|
+
findField: null,
|
34
|
+
highlightAll: null,
|
35
|
+
caseSensitive: null,
|
36
|
+
findMsg: null,
|
37
|
+
findStatusIcon: null,
|
38
|
+
findPreviousButton: null,
|
39
|
+
findNextButton: null,
|
40
|
+
|
41
|
+
initialize: function (options) {
|
42
|
+
if (typeof PDFFindController === 'undefined' || PDFFindController === null) {
|
43
|
+
throw 'PDFFindBar cannot be initialized ' +
|
44
|
+
'without a PDFFindController instance.';
|
45
|
+
}
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
47
|
+
this.bar = options.bar;
|
48
|
+
this.toggleButton = options.toggleButton;
|
49
|
+
this.findField = options.findField;
|
50
|
+
this.highlightAll = options.highlightAllCheckbox;
|
51
|
+
this.caseSensitive = options.caseSensitiveCheckbox;
|
52
|
+
this.findMsg = options.findMsg;
|
53
|
+
this.findStatusIcon = options.findStatusIcon;
|
54
|
+
this.findPreviousButton = options.findPreviousButton;
|
55
|
+
this.findNextButton = options.findNextButton;
|
56
|
+
|
57
|
+
var self = this;
|
58
|
+
this.toggleButton.addEventListener('click', function () {
|
59
|
+
self.toggle();
|
60
|
+
});
|
61
|
+
|
62
|
+
this.findField.addEventListener('input', function () {
|
63
|
+
self.dispatchEvent('');
|
64
|
+
});
|
65
|
+
|
66
|
+
this.bar.addEventListener('keydown', function (evt) {
|
67
|
+
switch (evt.keyCode) {
|
68
|
+
case 13: // Enter
|
69
|
+
if (evt.target === self.findField) {
|
70
|
+
self.dispatchEvent('again', evt.shiftKey);
|
71
|
+
}
|
72
|
+
break;
|
73
|
+
case 27: // Escape
|
74
|
+
self.close();
|
75
|
+
break;
|
76
|
+
}
|
77
|
+
});
|
78
|
+
|
79
|
+
this.findPreviousButton.addEventListener('click',
|
80
|
+
function () {
|
81
|
+
self.dispatchEvent('again', true);
|
82
|
+
}
|
83
|
+
);
|
84
|
+
|
85
|
+
this.findNextButton.addEventListener('click', function () {
|
86
|
+
self.dispatchEvent('again', false);
|
87
|
+
});
|
88
|
+
|
89
|
+
this.highlightAll.addEventListener('click', function () {
|
90
|
+
self.dispatchEvent('highlightallchange');
|
91
|
+
});
|
92
|
+
|
93
|
+
this.caseSensitive.addEventListener('click', function () {
|
94
|
+
self.dispatchEvent('casesensitivitychange');
|
95
|
+
});
|
96
|
+
},
|
97
|
+
|
98
|
+
dispatchEvent: function (aType, aFindPrevious) {
|
99
|
+
var event = document.createEvent('CustomEvent');
|
100
|
+
event.initCustomEvent('find' + aType, true, true, {
|
101
|
+
query: this.findField.value,
|
102
|
+
caseSensitive: this.caseSensitive.checked,
|
103
|
+
highlightAll: this.highlightAll.checked,
|
104
|
+
findPrevious: aFindPrevious
|
105
|
+
});
|
106
|
+
return window.dispatchEvent(event);
|
107
|
+
},
|
108
|
+
|
109
|
+
updateUIState: function (state, previous) {
|
110
|
+
var notFound = false;
|
111
|
+
var findMsg = '';
|
112
|
+
var status = '';
|
113
|
+
|
114
|
+
switch (state) {
|
115
|
+
case FindStates.FIND_FOUND:
|
116
|
+
break;
|
117
|
+
|
118
|
+
case FindStates.FIND_PENDING:
|
119
|
+
status = 'pending';
|
120
|
+
break;
|
121
|
+
|
122
|
+
case FindStates.FIND_NOTFOUND:
|
123
|
+
findMsg = mozL10n.get('find_not_found', null, 'Phrase not found');
|
124
|
+
notFound = true;
|
125
|
+
break;
|
126
|
+
|
127
|
+
case FindStates.FIND_WRAPPED:
|
128
|
+
if (previous) {
|
129
|
+
findMsg = mozL10n.get('find_reached_top', null,
|
130
|
+
'Reached top of document, continued from bottom');
|
131
|
+
} else {
|
132
|
+
findMsg = mozL10n.get('find_reached_bottom', null,
|
133
|
+
'Reached end of document, continued from top');
|
134
|
+
}
|
135
|
+
break;
|
132
136
|
}
|
133
|
-
break;
|
134
|
-
}
|
135
137
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
if (notFound) {
|
139
|
+
this.findField.classList.add('notFound');
|
140
|
+
} else {
|
141
|
+
this.findField.classList.remove('notFound');
|
142
|
+
}
|
141
143
|
|
142
|
-
|
143
|
-
|
144
|
-
|
144
|
+
this.findField.setAttribute('data-status', status);
|
145
|
+
this.findMsg.textContent = findMsg;
|
146
|
+
},
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
148
|
+
open: function () {
|
149
|
+
if (!this.opened) {
|
150
|
+
this.opened = true;
|
151
|
+
this.toggleButton.classList.add('toggled');
|
152
|
+
this.bar.classList.remove('hidden');
|
153
|
+
}
|
152
154
|
|
153
|
-
|
154
|
-
|
155
|
-
|
155
|
+
this.findField.select();
|
156
|
+
this.findField.focus();
|
157
|
+
},
|
156
158
|
|
157
|
-
|
158
|
-
|
159
|
+
close: function () {
|
160
|
+
if (!this.opened) return;
|
159
161
|
|
160
|
-
|
161
|
-
|
162
|
-
|
162
|
+
this.opened = false;
|
163
|
+
this.toggleButton.classList.remove('toggled');
|
164
|
+
this.bar.classList.add('hidden');
|
163
165
|
|
164
|
-
|
165
|
-
|
166
|
+
PDFFindController.active = false;
|
167
|
+
},
|
166
168
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
169
|
+
toggle: function () {
|
170
|
+
if (this.opened) {
|
171
|
+
this.close();
|
172
|
+
} else {
|
173
|
+
this.open();
|
174
|
+
}
|
172
175
|
}
|
173
|
-
}
|
174
176
|
};
|
175
177
|
|
@@ -24,332 +24,334 @@
|
|
24
24
|
*/
|
25
25
|
|
26
26
|
var PDFFindController = {
|
27
|
-
|
27
|
+
startedTextExtraction: false,
|
28
28
|
|
29
|
-
|
29
|
+
extractTextPromises: [],
|
30
30
|
|
31
|
-
|
31
|
+
pendingFindMatches: {},
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
// If active, find results will be highlighted.
|
34
|
+
active: false,
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
// Stores the text for each page.
|
37
|
+
pageContents: [],
|
38
38
|
|
39
|
-
|
39
|
+
pageMatches: [],
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
// Currently selected match.
|
42
|
+
selected: {
|
43
|
+
pageIdx: -1,
|
44
|
+
matchIdx: -1
|
45
|
+
},
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
// Where find algorithm currently is in the document.
|
48
|
+
offset: {
|
49
|
+
pageIdx: null,
|
50
|
+
matchIdx: null
|
51
|
+
},
|
52
52
|
|
53
|
-
|
53
|
+
resumePageIdx: null,
|
54
54
|
|
55
|
-
|
55
|
+
state: null,
|
56
56
|
|
57
|
-
|
57
|
+
dirtyMatch: false,
|
58
58
|
|
59
|
-
|
59
|
+
findTimeout: null,
|
60
60
|
|
61
|
-
|
61
|
+
pdfPageSource: null,
|
62
62
|
|
63
|
-
|
63
|
+
integratedFind: false,
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
initialize: function (options) {
|
66
|
+
if (typeof PDFFindBar === 'undefined' || PDFFindBar === null) {
|
67
|
+
throw 'PDFFindController cannot be initialized ' +
|
68
|
+
'without a PDFFindController instance';
|
69
|
+
}
|
70
70
|
|
71
|
-
|
72
|
-
|
71
|
+
this.pdfPageSource = options.pdfPageSource;
|
72
|
+
this.integratedFind = options.integratedFind;
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
var events = [
|
75
|
+
'find',
|
76
|
+
'findagain',
|
77
|
+
'findhighlightallchange',
|
78
|
+
'findcasesensitivitychange'
|
79
|
+
];
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
this.firstPagePromise = new Promise(function (resolve) {
|
82
|
+
this.resolveFirstPage = resolve;
|
83
|
+
}.bind(this));
|
84
|
+
this.handleEvent = this.handleEvent.bind(this);
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
86
|
+
for (var i = 0; i < events.length; i++) {
|
87
|
+
window.addEventListener(events[i], this.handleEvent);
|
88
|
+
}
|
89
|
+
},
|
90
|
+
|
91
|
+
reset: function pdfFindControllerReset() {
|
92
|
+
this.startedTextExtraction = false;
|
93
|
+
this.extractTextPromises = [];
|
94
|
+
this.active = false;
|
95
|
+
},
|
96
|
+
|
97
|
+
calcFindMatch: function (pageIndex) {
|
98
|
+
var pageContent = this.pageContents[pageIndex];
|
99
|
+
var query = this.state.query;
|
100
|
+
var caseSensitive = this.state.caseSensitive;
|
101
|
+
var queryLen = query.length;
|
102
|
+
|
103
|
+
if (queryLen === 0) {
|
104
|
+
// Do nothing the matches should be wiped out already.
|
105
|
+
return;
|
106
|
+
}
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
108
|
+
if (!caseSensitive) {
|
109
|
+
pageContent = pageContent.toLowerCase();
|
110
|
+
query = query.toLowerCase();
|
111
|
+
}
|
112
112
|
|
113
|
-
|
113
|
+
var matches = [];
|
114
114
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
115
|
+
var matchIdx = -queryLen;
|
116
|
+
while (true) {
|
117
|
+
matchIdx = pageContent.indexOf(query, matchIdx + queryLen);
|
118
|
+
if (matchIdx === -1) {
|
119
|
+
break;
|
120
|
+
}
|
121
121
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
122
|
+
matches.push(matchIdx);
|
123
|
+
}
|
124
|
+
this.pageMatches[pageIndex] = matches;
|
125
|
+
this.updatePage(pageIndex);
|
126
|
+
if (this.resumePageIdx === pageIndex) {
|
127
|
+
this.resumePageIdx = null;
|
128
|
+
this.nextPageMatch();
|
129
|
+
}
|
130
|
+
},
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
132
|
+
extractText: function () {
|
133
|
+
if (this.startedTextExtraction) {
|
134
|
+
return;
|
135
|
+
}
|
136
|
+
this.startedTextExtraction = true;
|
137
|
+
|
138
|
+
this.pageContents = [];
|
139
|
+
var extractTextPromisesResolves = [];
|
140
|
+
for (var i = 0, ii = this.pdfPageSource.pdfDocument.numPages; i < ii; i++) {
|
141
|
+
this.extractTextPromises.push(new Promise(function (resolve) {
|
142
|
+
extractTextPromisesResolves.push(resolve);
|
143
|
+
}));
|
144
|
+
}
|
145
|
+
|
146
|
+
var self = this;
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
var str = '';
|
148
|
+
function extractPageText(pageIndex) {
|
149
|
+
self.pdfPageSource.pages[pageIndex].getTextContent().then(
|
150
|
+
function textContentResolved(bidiTexts) {
|
151
|
+
var str = '';
|
151
152
|
|
152
|
-
|
153
|
-
|
154
|
-
|
153
|
+
for (var i = 0; i < bidiTexts.length; i++) {
|
154
|
+
str += bidiTexts[i].str;
|
155
|
+
}
|
155
156
|
|
156
|
-
|
157
|
-
|
157
|
+
// Store the pageContent as a string.
|
158
|
+
self.pageContents.push(str);
|
158
159
|
|
159
|
-
|
160
|
-
|
161
|
-
|
160
|
+
extractTextPromisesResolves[pageIndex](pageIndex);
|
161
|
+
if ((pageIndex + 1) < self.pdfPageSource.pages.length)
|
162
|
+
extractPageText(pageIndex + 1);
|
163
|
+
}
|
164
|
+
);
|
162
165
|
}
|
163
|
-
);
|
164
|
-
}
|
165
|
-
extractPageText(0);
|
166
|
-
},
|
167
166
|
|
168
|
-
|
169
|
-
|
170
|
-
this.dirtyMatch = true;
|
171
|
-
}
|
172
|
-
this.state = e.detail;
|
173
|
-
this.updateUIState(FindStates.FIND_PENDING);
|
174
|
-
|
175
|
-
this.firstPagePromise.then(function() {
|
176
|
-
this.extractText();
|
177
|
-
|
178
|
-
clearTimeout(this.findTimeout);
|
179
|
-
if (e.type === 'find') {
|
180
|
-
// Only trigger the find action after 250ms of silence.
|
181
|
-
this.findTimeout = setTimeout(this.nextMatch.bind(this), 250);
|
182
|
-
} else {
|
183
|
-
this.nextMatch();
|
184
|
-
}
|
185
|
-
}.bind(this));
|
186
|
-
},
|
187
|
-
|
188
|
-
updatePage: function(idx) {
|
189
|
-
var page = this.pdfPageSource.pages[idx];
|
190
|
-
|
191
|
-
if (this.selected.pageIdx === idx) {
|
192
|
-
// If the page is selected, scroll the page into view, which triggers
|
193
|
-
// rendering the page, which adds the textLayer. Once the textLayer is
|
194
|
-
// build, it will scroll onto the selected match.
|
195
|
-
page.scrollIntoView();
|
196
|
-
}
|
167
|
+
extractPageText(0);
|
168
|
+
},
|
197
169
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
if (!(i in this.pendingFindMatches)) {
|
227
|
-
this.pendingFindMatches[i] = true;
|
228
|
-
this.extractTextPromises[i].then(function(pageIdx) {
|
229
|
-
delete self.pendingFindMatches[pageIdx];
|
230
|
-
self.calcFindMatch(pageIdx);
|
231
|
-
});
|
170
|
+
handleEvent: function (e) {
|
171
|
+
if (this.state === null || e.type !== 'findagain') {
|
172
|
+
this.dirtyMatch = true;
|
173
|
+
}
|
174
|
+
this.state = e.detail;
|
175
|
+
this.updateUIState(FindStates.FIND_PENDING);
|
176
|
+
|
177
|
+
this.firstPagePromise.then(function () {
|
178
|
+
this.extractText();
|
179
|
+
|
180
|
+
clearTimeout(this.findTimeout);
|
181
|
+
if (e.type === 'find') {
|
182
|
+
// Only trigger the find action after 250ms of silence.
|
183
|
+
this.findTimeout = setTimeout(this.nextMatch.bind(this), 250);
|
184
|
+
} else {
|
185
|
+
this.nextMatch();
|
186
|
+
}
|
187
|
+
}.bind(this));
|
188
|
+
},
|
189
|
+
|
190
|
+
updatePage: function (idx) {
|
191
|
+
var page = this.pdfPageSource.pages[idx];
|
192
|
+
|
193
|
+
if (this.selected.pageIdx === idx) {
|
194
|
+
// If the page is selected, scroll the page into view, which triggers
|
195
|
+
// rendering the page, which adds the textLayer. Once the textLayer is
|
196
|
+
// build, it will scroll onto the selected match.
|
197
|
+
page.scrollIntoView();
|
232
198
|
}
|
233
|
-
}
|
234
|
-
}
|
235
199
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
200
|
+
if (page.textLayer) {
|
201
|
+
page.textLayer.updateMatches();
|
202
|
+
}
|
203
|
+
},
|
204
|
+
|
205
|
+
nextMatch: function () {
|
206
|
+
var previous = this.state.findPrevious;
|
207
|
+
var currentPageIndex = this.pdfPageSource.page - 1;
|
208
|
+
var numPages = this.pdfPageSource.pages.length;
|
209
|
+
|
210
|
+
this.active = true;
|
211
|
+
|
212
|
+
if (this.dirtyMatch) {
|
213
|
+
// Need to recalculate the matches, reset everything.
|
214
|
+
this.dirtyMatch = false;
|
215
|
+
this.selected.pageIdx = this.selected.matchIdx = -1;
|
216
|
+
this.offset.pageIdx = currentPageIndex;
|
217
|
+
this.offset.matchIdx = null;
|
218
|
+
this.hadMatch = false;
|
219
|
+
this.resumePageIdx = null;
|
220
|
+
this.pageMatches = [];
|
221
|
+
var self = this;
|
222
|
+
|
223
|
+
for (var i = 0; i < numPages; i++) {
|
224
|
+
// Wipe out any previous highlighted matches.
|
225
|
+
this.updatePage(i);
|
226
|
+
|
227
|
+
// As soon as the text is extracted start finding the matches.
|
228
|
+
if (!(i in this.pendingFindMatches)) {
|
229
|
+
this.pendingFindMatches[i] = true;
|
230
|
+
this.extractTextPromises[i].then(function (pageIdx) {
|
231
|
+
delete self.pendingFindMatches[pageIdx];
|
232
|
+
self.calcFindMatch(pageIdx);
|
233
|
+
});
|
234
|
+
}
|
235
|
+
}
|
236
|
+
}
|
241
237
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
238
|
+
// If there's no query there's no point in searching.
|
239
|
+
if (this.state.query === '') {
|
240
|
+
this.updateUIState(FindStates.FIND_FOUND);
|
241
|
+
return;
|
242
|
+
}
|
246
243
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
if (offset.matchIdx !== null) {
|
251
|
-
var numPageMatches = this.pageMatches[offset.pageIdx].length;
|
252
|
-
if ((!previous && offset.matchIdx + 1 < numPageMatches) ||
|
253
|
-
(previous && offset.matchIdx > 0)) {
|
254
|
-
// The simple case, we just have advance the matchIdx to select the next
|
255
|
-
// match on the page.
|
256
|
-
this.hadMatch = true;
|
257
|
-
offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
|
258
|
-
this.updateMatch(true);
|
259
|
-
return;
|
260
|
-
}
|
261
|
-
// We went beyond the current page's matches, so we advance to the next
|
262
|
-
// page.
|
263
|
-
this.advanceOffsetPage(previous);
|
264
|
-
}
|
265
|
-
// Start searching through the page.
|
266
|
-
this.nextPageMatch();
|
267
|
-
},
|
268
|
-
|
269
|
-
matchesReady: function(matches) {
|
270
|
-
var offset = this.offset;
|
271
|
-
var numMatches = matches.length;
|
272
|
-
var previous = this.state.findPrevious;
|
273
|
-
if (numMatches) {
|
274
|
-
// There were matches for the page, so initialize the matchIdx.
|
275
|
-
this.hadMatch = true;
|
276
|
-
offset.matchIdx = previous ? numMatches - 1 : 0;
|
277
|
-
this.updateMatch(true);
|
278
|
-
// matches were found
|
279
|
-
return true;
|
280
|
-
} else {
|
281
|
-
// No matches attempt to search the next page.
|
282
|
-
this.advanceOffsetPage(previous);
|
283
|
-
if (offset.wrapped) {
|
284
|
-
offset.matchIdx = null;
|
285
|
-
if (!this.hadMatch) {
|
286
|
-
// No point in wrapping there were no matches.
|
287
|
-
this.updateMatch(false);
|
288
|
-
// while matches were not found, searching for a page
|
289
|
-
// with matches should nevertheless halt.
|
290
|
-
return true;
|
244
|
+
// If we're waiting on a page, we return since we can't do anything else.
|
245
|
+
if (this.resumePageIdx) {
|
246
|
+
return;
|
291
247
|
}
|
292
|
-
}
|
293
|
-
// matches were not found (and searching is not done)
|
294
|
-
return false;
|
295
|
-
}
|
296
|
-
},
|
297
248
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
249
|
+
var offset = this.offset;
|
250
|
+
// If there's already a matchIdx that means we are iterating through a
|
251
|
+
// page's matches.
|
252
|
+
if (offset.matchIdx !== null) {
|
253
|
+
var numPageMatches = this.pageMatches[offset.pageIdx].length;
|
254
|
+
if ((!previous && offset.matchIdx + 1 < numPageMatches) ||
|
255
|
+
(previous && offset.matchIdx > 0)) {
|
256
|
+
// The simple case, we just have advance the matchIdx to select the next
|
257
|
+
// match on the page.
|
258
|
+
this.hadMatch = true;
|
259
|
+
offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
|
260
|
+
this.updateMatch(true);
|
261
|
+
return;
|
262
|
+
}
|
263
|
+
// We went beyond the current page's matches, so we advance to the next
|
264
|
+
// page.
|
265
|
+
this.advanceOffsetPage(previous);
|
266
|
+
}
|
267
|
+
// Start searching through the page.
|
268
|
+
this.nextPageMatch();
|
269
|
+
},
|
270
|
+
|
271
|
+
matchesReady: function (matches) {
|
272
|
+
var offset = this.offset;
|
273
|
+
var numMatches = matches.length;
|
274
|
+
var previous = this.state.findPrevious;
|
275
|
+
if (numMatches) {
|
276
|
+
// There were matches for the page, so initialize the matchIdx.
|
277
|
+
this.hadMatch = true;
|
278
|
+
offset.matchIdx = previous ? numMatches - 1 : 0;
|
279
|
+
this.updateMatch(true);
|
280
|
+
// matches were found
|
281
|
+
return true;
|
282
|
+
} else {
|
283
|
+
// No matches attempt to search the next page.
|
284
|
+
this.advanceOffsetPage(previous);
|
285
|
+
if (offset.wrapped) {
|
286
|
+
offset.matchIdx = null;
|
287
|
+
if (!this.hadMatch) {
|
288
|
+
// No point in wrapping there were no matches.
|
289
|
+
this.updateMatch(false);
|
290
|
+
// while matches were not found, searching for a page
|
291
|
+
// with matches should nevertheless halt.
|
292
|
+
return true;
|
293
|
+
}
|
294
|
+
}
|
295
|
+
// matches were not found (and searching is not done)
|
296
|
+
return false;
|
297
|
+
}
|
298
|
+
},
|
345
299
|
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
300
|
+
nextPageMatch: function () {
|
301
|
+
if (this.resumePageIdx !== null) {
|
302
|
+
console.error('There can only be one pending page.');
|
303
|
+
}
|
304
|
+
do {
|
305
|
+
var pageIdx = this.offset.pageIdx;
|
306
|
+
var matches = this.pageMatches[pageIdx];
|
307
|
+
if (!matches) {
|
308
|
+
// The matches don't exist yet for processing by "matchesReady",
|
309
|
+
// so set a resume point for when they do exist.
|
310
|
+
this.resumePageIdx = pageIdx;
|
311
|
+
break;
|
312
|
+
}
|
313
|
+
} while (!this.matchesReady(matches));
|
314
|
+
},
|
315
|
+
|
316
|
+
advanceOffsetPage: function (previous) {
|
317
|
+
var offset = this.offset;
|
318
|
+
var numPages = this.extractTextPromises.length;
|
319
|
+
offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
|
320
|
+
offset.matchIdx = null;
|
321
|
+
if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
|
322
|
+
offset.pageIdx = previous ? numPages - 1 : 0;
|
323
|
+
offset.wrapped = true;
|
324
|
+
return;
|
325
|
+
}
|
326
|
+
},
|
327
|
+
|
328
|
+
updateMatch: function (found) {
|
329
|
+
var state = FindStates.FIND_NOTFOUND;
|
330
|
+
var wrapped = this.offset.wrapped;
|
331
|
+
this.offset.wrapped = false;
|
332
|
+
if (found) {
|
333
|
+
var previousPage = this.selected.pageIdx;
|
334
|
+
this.selected.pageIdx = this.offset.pageIdx;
|
335
|
+
this.selected.matchIdx = this.offset.matchIdx;
|
336
|
+
state = wrapped ? FindStates.FIND_WRAPPED : FindStates.FIND_FOUND;
|
337
|
+
// Update the currently selected page to wipe out any selected matches.
|
338
|
+
if (previousPage !== -1 && previousPage !== this.selected.pageIdx) {
|
339
|
+
this.updatePage(previousPage);
|
340
|
+
}
|
341
|
+
}
|
342
|
+
this.updateUIState(state, this.state.findPrevious);
|
343
|
+
if (this.selected.pageIdx !== -1) {
|
344
|
+
this.updatePage(this.selected.pageIdx, true);
|
345
|
+
}
|
346
|
+
},
|
347
|
+
|
348
|
+
updateUIState: function (state, previous) {
|
349
|
+
if (this.integratedFind) {
|
350
|
+
FirefoxCom.request('updateFindControlState',
|
351
|
+
{result: state, findPrevious: previous});
|
352
|
+
return;
|
353
|
+
}
|
354
|
+
PDFFindBar.updateUIState(state, previous);
|
351
355
|
}
|
352
|
-
PDFFindBar.updateUIState(state, previous);
|
353
|
-
}
|
354
356
|
};
|
355
357
|
|