diff --git a/web/viewer.css b/web/viewer.css
index a1ef92810..56d513f70 100644
--- a/web/viewer.css
+++ b/web/viewer.css
@@ -172,9 +172,47 @@ span#info {
box-shadow: 0px 2px 10px #ff0;
}
+#searchScrollView {
+ position: absolute;
+ top: 10px;
+ bottom: 10px;
+ left: 10px;
+ width: 280px;
+}
+
+#searchToolbar {
+ padding-left: 0px;
+ right: 0px;
+ padding-top: 0px;
+ padding-bottom: 5px;
+}
+
+#searchToolbar > input {
+ width: 220px;
+}
+
+#searchResults {
+ overflow: auto;
+ background-color: #fff;
+ position: absolute;
+ top: 30px;
+ bottom: 0px;
+ left: 0px;
+ right: 0;
+ font-size: smaller;
+ opacity: 0.7;
+}
+
+#searchResults a {
+ display: block;
+ white-space: pre;
+ text-decoration: none;
+ color: black;
+}
+
#sidebarControls {
position:absolute;
- width: 120px;
+ width: 180px;
height: 32px;
left: 15px;
bottom: 35px;
diff --git a/web/viewer.html b/web/viewer.html
index 53ca2a247..98c19a53c 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -124,6 +124,13 @@
+
diff --git a/web/viewer.js b/web/viewer.js
index 465df5ab5..340586a94 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -310,18 +310,69 @@ var PDFView = {
else
this.page = 1;
+ // loosing pdf reference here, starting text indexing in 500ms
setTimeout((function loadStartTextExtraction() {
this.startTextExtraction(pdf);
}).bind(this), 500);
+ delete PDFView.extractedText;
},
- startTextExtraction: function(pdf) {
+ startTextExtraction: function pdfViewStartTextExtraction(pdf) {
+ var searchResults = document.getElementById('searchResults');
+ searchResults.textContent = '';
+
pdf.textExtracted = function pdfTextExtracted(index) {
- console.log(index.join());
+ PDFView.extractedText = index;
};
pdf.extractText();
},
+ search: function pdfViewStartSearch() {
+ function bindLink(link, pageNumber) {
+ link.href = '#' + pageNumber;
+ link.onclick = function searchBindLink() {
+ PDFView.page = pageNumber;
+ return false;
+ };
+ }
+
+ var searchResults = document.getElementById('searchResults');
+ if (!('extractedText' in PDFView)) {
+ // not indexed yet, repeat in 1 second
+ searchResults.textContent = 'Searching...';
+ setTimeout(this.search.bind(this), 1000);
+ return;
+ }
+
+ var searchTermsInput = document.getElementById('searchTermsInput');
+ searchResults.removeAttribute('hidden');
+ searchResults.textContent = '';
+
+ var terms = searchTermsInput.value;
+ // simple search: removing spaces and hyphens, then scanning every
+ terms = terms.replace(/\s-/g, '').toLowerCase();
+ var index = PDFView.extractedText;
+ var pageFound = false;
+ for (var i = 0, ii = index.length; i < ii; i++) {
+ var pageText = index[i].replace(/\s-/g, '').toLowerCase();
+ var j = pageText.indexOf(terms);
+ if (j < 0)
+ continue;
+
+ var pageNumber = i + 1;
+ var textSample = index[i].substr(j, 50);
+ var link = document.createElement('a');
+ bindLink(link, pageNumber);
+ link.textContent = 'Page ' + pageNumber + ': ' + textSample;
+ searchResults.appendChild(link);
+
+ pageFound = true;
+ }
+ if (!pageFound) {
+ searchResults.textContent = '(Not found)';
+ }
+ },
+
setHash: function pdfViewSetHash(hash) {
if (!hash)
return;
@@ -361,23 +412,36 @@ var PDFView = {
switchSidebarView: function pdfViewSwitchSidebarView(view) {
var thumbsScrollView = document.getElementById('sidebarScrollView');
- var outlineScrollView = document.getElementById('outlineScrollView');
var thumbsSwitchButton = document.getElementById('thumbsSwitch');
+ if (view == 'thumbs') {
+ thumbsScrollView.removeAttribute('hidden');
+ thumbsSwitchButton.setAttribute('data-selected', true);
+ } else {
+ thumbsScrollView.setAttribute('hidden', 'true');
+ thumbsSwitchButton.removeAttribute('data-selected');
+ }
+
+ var outlineScrollView = document.getElementById('outlineScrollView');
var outlineSwitchButton = document.getElementById('outlineSwitch');
- switch (view) {
- case 'thumbs':
- thumbsScrollView.removeAttribute('hidden');
- outlineScrollView.setAttribute('hidden', 'true');
- thumbsSwitchButton.setAttribute('data-selected', true);
- outlineSwitchButton.removeAttribute('data-selected');
- updateThumbViewArea();
- break;
- case 'outline':
- thumbsScrollView.setAttribute('hidden', 'true');
- outlineScrollView.removeAttribute('hidden');
- thumbsSwitchButton.removeAttribute('data-selected');
- outlineSwitchButton.setAttribute('data-selected', true);
- break;
+ if (view == 'outline') {
+ outlineScrollView.removeAttribute('hidden');
+ outlineSwitchButton.setAttribute('data-selected', true);
+ } else {
+ outlineScrollView.setAttribute('hidden', 'true');
+ outlineSwitchButton.removeAttribute('data-selected');
+ }
+
+ var searchScrollView = document.getElementById('searchScrollView');
+ var searchSwitchButton = document.getElementById('searchSwitch');
+ if (view == 'search') {
+ searchScrollView.removeAttribute('hidden');
+ searchSwitchButton.setAttribute('data-selected', true);
+
+ var searchTermsInput = document.getElementById('searchTermsInput');
+ searchTermsInput.focus();
+ } else {
+ searchScrollView.setAttribute('hidden', 'true');
+ searchSwitchButton.removeAttribute('data-selected');
}
},