1
0
Fork 0
mirror of https://github.com/Yetangitu/owncloud-apps.git synced 2025-10-02 14:49:17 +02:00

files_reader: more PDF work, functioning search, experimental search highlighting

This commit is contained in:
frankdelange 2017-03-30 19:25:34 +02:00
parent d8b4e395ca
commit fed0e9fdd7
8 changed files with 241 additions and 108 deletions

Binary file not shown.

View file

@ -4,78 +4,10 @@ PDFJS.reader.OutlineController = function(_outline) {
book = this.book,
outline = _outline || [];
var outlineView = document.getElementById("outlineView"),
baseUrl = location.href.split('#')[0],
lastToggleIsShow;
var outlineView = document.getElementById("outlineView");
var DEFAULT_TITLE = '\u2013';
var bindLink = function (element, item) {
var destination = item.dest;
if (item.url) {
PDFJS.addLinkAttributes (element, {
url: item.url,
target: (item.newWindow
? PDFJS.LinkTarget.BLANK
: undefined),
});
return;
} else {
element.href = getDestinationHash(destination);
element.onclick = function () {
if (destination) {
reader.navigateTo(destination);
}
return false;
};
}
};
var setStyles = function (element, item) {
var styleStr = "";
if (item.bold) {
styleStr += 'font-weight: bold;';
}
if (item.italic) {
styleStr += 'font-style: italic;';
}
if (styleStr) {
element.setAttribute('style', styleStr);
}
};
var getDestinationHash = function (destination) {
var url = baseUrl || "",
str;
if (typeof destination === 'string') {
url += "#"
+ (parseInt(destination) === destination)
? "nameddest="
: ""
+ escape(destination);
} else if (destination instanceof Array) {
url += "#"
+ escape(JSON.stringify(destination));
}
return url;
};
var generateOutlineItems = function (outline, level) {
var container = document.createElement("ul");
@ -83,6 +15,7 @@ PDFJS.reader.OutlineController = function(_outline) {
if(!level) level = 1;
outline.forEach(function (chapter) {
var listitem = document.createElement("li"),
link = document.createElement("a"),
toggle = document.createElement("a"),
@ -92,8 +25,8 @@ PDFJS.reader.OutlineController = function(_outline) {
listitem.classList.add('list_item');
link.textContent = PDFJS.removeNullCharacters(chapter.title) || DEFAULT_TITLE;
bindLink(link, chapter);
setStyles(link, chapter);
reader.bindLink(link, chapter);
reader.setStyles(link, chapter);
link.classList.add('outline_link');
listitem.appendChild(link);

View file

@ -152,6 +152,7 @@ PDFJS.reader.SearchController = function () {
matches.push(matchIdx);
}
this.pageMatches[pageIndex] = matches;
};
var calcFindWordMatch = function (
@ -189,6 +190,55 @@ PDFJS.reader.SearchController = function () {
this.pageMatchesLength[pageIndex]);
};
var getSnippet = function (pageIndex, position) {
var ellipse = '…',
match_length = this.state.query.length,
span = '<span class="search_match">',
span_close = '</span>',
limit = 160 + span.length + span_close.length,
leader,
trailer,
context;
leader = this.pageContents[pageIndex].substring(position - limit/2, position);
leader = leader.slice(leader.indexOf(" "));
trailer = this.pageContents[pageIndex].substring(position + match_length, position + limit/2 + match_length);
query = this.pageContents[pageIndex].substring(position, position + match_length);
context = ellipse + leader + span + query + span_close + trailer;
return reader.ellipsize(context, context.length - 10);
};
var createItem = function (pageIndex, position) {
var listitem = document.createElement("li"),
link = document.createElement("a"),
id = parseInt(pageIndex + 1) + ":" + position,
item = {
url: null,
dest: null,
bold: null,
italic: null
};
// for now only the pageIndex is used
item.dest = [pageIndex,position];
//link.textContent = getSnippet(pageIndex, position);
link.innerHTML = getSnippet(pageIndex, position);
listitem.classList.add("list_item");
listitem.id = "search-"+id;
listitem.dataset.position = position;
reader.bindLink(link, item);
link.classList.add("search_link");
listitem.appendChild(link);
return listitem;
};
var calcFindMatch = function (pageIndex) {
var pageContent = normalize(this.pageContents[pageIndex]);
var query = normalize(this.state.query);
@ -211,18 +261,6 @@ PDFJS.reader.SearchController = function () {
} else {
calcFindWordMatch(query, pageIndex, pageContent);
}
updatePage(pageIndex);
if (this.resumePageIdx === pageIndex) {
this.resumePageIdx = null;
nextPageMatch();
}
// Update the matches count
if (this.pageMatches[pageIndex].length > 0) {
this.matchCount += this.pageMatches[pageIndex].length;
updateUIResultsCount();
}
};
var extractText = function () {
@ -253,19 +291,12 @@ PDFJS.reader.SearchController = function () {
}
// Store the pageContent as a string.
self.pageContents.push(str.join(''));
self.pageContents.push(str.join(' ').replace(/\s\s+/g, ' '));
extractTextPromisesResolves[pageIndex](pageIndex);
if ((pageIndex + 1) < reader.settings.numPages) {
console.log("extracting text from page " + parseInt(pageIndex + 1));
extractPageText(pageIndex + 1);
} else {
console.log("finished extracting text");
for (var i=0;i < reader.settings.numPages;i++) {
console.log("PAGE: " + parseInt(i + 1));
console.log(self.pageContents[i]);
}
}
}
}
);
}
@ -287,7 +318,8 @@ PDFJS.reader.SearchController = function () {
clearTimeout(this.findTimeout);
if (cmd === 'find') {
// Only trigger the find action after 250ms of silence.
this.findTimeout = setTimeout(nextMatch.bind(this), 250);
//this.findTimeout = setTimeout(nextMatch.bind(this), 250);
generateMatchList();
} else {
nextMatch();
}
@ -309,6 +341,39 @@ PDFJS.reader.SearchController = function () {
//}
};
var generateMatchList = function () {
var container = document.getElementById("searchResults"),
numPages = reader.settings.numPages,
self = this;
for (var i = 0; i < numPages; i++) {
//var placeholder = document.createElement("li");
//placeholder.style.display = "none";
//container.appendChild(placeholder);
if (!(i in this.pendingFindMatches)) {
this.pendingFindMatches[i] = true;
this.extractTextPromises[i].then(function(pageIdx) {
delete self.pendingFindMatches[pageIdx];
calcFindMatch(pageIdx);
if (self.pageMatches[pageIdx].length > 0) {
reader.pageMatches[pageIdx] = self.pageMatches[pageIdx];
var fragment = document.createDocumentFragment();
var listitem = document.createElement("li");
listitem.textContent="page " + parseInt(pageIdx + 1);
listitem.classList.add("search_page_header");
fragment.appendChild(listitem);
self.pageMatches[pageIdx].forEach(function (match) {
fragment.appendChild(createItem(pageIdx, match));
});
container.appendChild(fragment);
}
});
}
}
};
var nextMatch = function () {
var previous = this.state.findPrevious;
@ -501,22 +566,20 @@ PDFJS.reader.SearchController = function () {
q = $searchBox.val();
}
if (q == '') {
if (q === '') {
clear();
return;
}
reader.SidebarController.changePanelTo("Search");
reset();
$searchResults.empty();
$searchResults.append("<li><p>Searching...</p></li>");
reader.SearchController.query = q;
//runQuery(q, $searchResults[0]);
this.query = q;
executeCommand('find', {query: q});
highlightQuery();
};
$searchBox.on("keydown", function(e) {
@ -537,12 +600,14 @@ PDFJS.reader.SearchController = function () {
});
$clear_search.on("click", function () {
reset();
unhighlight();
$searchResults.empty();
});
var clear = function () {
reset();
unhighlight();
$searchResults.empty();
@ -552,13 +617,13 @@ PDFJS.reader.SearchController = function () {
};
var highlightQuery = function(e) {
$("#viewer iframe").contents().find('body').highlight(reader.SearchController.query, { element: 'span' });
$("#text_left").contents().highlight(this.state.query, { element: 'span' });
$("#text_right").contents().highlight(this.state.query, { element: 'span' });
};
var unhighlight = function(e) {
$body = $("#viewer iframe").contents().find('body');
$body.unhighlight();
book.off("renderer:chapterDisplayed", highlightQuery);
$("#text_left").unhighlight();
$("#text_right").unhighlight();
};
@ -566,6 +631,8 @@ PDFJS.reader.SearchController = function () {
"show": onShow,
"hide": onHide,
"search": search,
"executeCommand": executeCommand
"executeCommand": executeCommand,
"highlightQuery": highlightQuery,
"unhighlight": unhighlight
};
};

View file

@ -116,12 +116,14 @@ PDFJS.Reader.TextLayerController.prototype.setTextContent = function (textConten
};
PDFJS.Reader.TextLayerController.prototype.convertMatches = function(matches, matchesLength) {
var reader = this;
var i = 0;
var iIndex = 0;
var bidiTexts = this.textContent.items;
var end = bidiTexts.length - 1;
var queryLen = (this.findController === null ?
0 : this.findController.state.query.length);
var queryLen = reader.search.query.length;
var ret = [];
if (!matches) {
return ret;
@ -177,6 +179,8 @@ PDFJS.Reader.TextLayerController.prototype.renderMatches = function (matches) {
return;
}
var reader = this;
var bidiTexts = this.textContent.items;
var textDivs = this.textDivs;
var prevEnd = null;

View file

@ -313,6 +313,7 @@ legend {
.search-results {
overflow-y: scroll;
overflow-wrap: break-word;
height: 95%;
height: calc(100vh - 5em);
}
@ -323,6 +324,11 @@ legend {
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
}
.search_match {
font-weight: bold;
font-decoration: underline;
}
.searchbox {
width: 80%;
float: left;
@ -345,6 +351,8 @@ legend {
#clear_search {
padding: 0;
padding-right: 0.5em;
position: absolute;
height: auto;
}
/* END search */

View file

@ -39,7 +39,7 @@ PDFJS.Reader = function(bookPath, _options) {
pageRenderDelay: PAGE_RENDER_DELAY,
canvasLimit: 0,
cssZoomOnly: false, // true || false, only zoom using CSS, render document at 100% size
textSelect: false, // true || false, add selectable text layer
textSelect: true, // true || false, add selectable text layer
doubleBuffer: true, // true || false, draw to off-screen canvas
cacheNext: true, // true || false, pre-render next page (by creathing thumbnail))
numPages: 0,
@ -129,6 +129,9 @@ PDFJS.Reader = function(bookPath, _options) {
this.renderQueue = false;
// used for search
this.pageMatches = [];
// define which zoom states to cycle through in cycleZoom
this.zoomCycle = {
'spread': 'fit_page',
@ -268,7 +271,9 @@ PDFJS.Reader.prototype.getThumb = function (pageNum, insert) {
renderContext,
renderTask;
if (reader.thumbs[pageNum] === undefined) {
if (pageNum > 0 &&
pageNum <= reader.settings.numPages &&
reader.thumbs[pageNum] === undefined) {
reader.thumbs[pageNum] = true;
@ -452,6 +457,8 @@ PDFJS.Reader.prototype.renderPage = function(pageNum) {
double_buffer = reader.settings.doubleBuffer;
cache_next = reader.settings.cacheNext;
textdiv.innerHTML = "";
if (pageNum <= this.settings.numPages && pageNum >= 1) {
if (resourcelst.renderTask) {
@ -944,3 +951,117 @@ PDFJS.Reader.prototype.getPageTextContent = function (pageIndex) {
});
};
PDFJS.Reader.prototype.getDestinationHash = function (destination) {
var url = location.href.split('#')[0],
str;
if (typeof destination === 'string') {
url += "#"
+ (parseInt(destination) === destination)
? "nameddest="
: ""
+ escape(destination);
} else if (destination instanceof Array) {
url += "#"
+ escape(JSON.stringify(destination));
}
return url;
};
PDFJS.Reader.prototype.setStyles = function (element, item) {
var styleStr = "";
if (item.bold) {
styleStr += 'font-weight: bold;';
}
if (item.italic) {
styleStr += 'font-style: italic;';
}
if (styleStr) {
element.setAttribute('style', styleStr);
}
};
PDFJS.Reader.prototype.bindLink = function (element, item) {
var reader = this,
destination = item.dest;
if (item.url) {
PDFJS.addLinkAttributes (element, {
url: item.url,
target: (item.newWindow
? PDFJS.LinkTarget.BLANK
: undefined),
});
return;
} else {
element.href = reader.getDestinationHash(destination);
element.onclick = function () {
if (destination) {
reader.navigateTo(destination);
}
return false;
};
}
};
// https://github.com/mvhenten/ellipsize/blob/master/index.js
PDFJS.Reader.prototype.ellipsize = function(str, max, opts) {
var defaults = {
ellipse: '…',
chars: [' ', '-'],
max: 140,
truncate: true
};
if (typeof str !== 'string' || str.length === 0) return '';
if (max === 0) return '';
opts = opts || {};
for (var key in defaults) {
if (opts[key] === null || typeof opts[key] === 'undefined') {
opts[key] = defaults[key];
}
}
opts.max = max || opts.max;
var last = 0,
c = '';
if (str.length < opts.max) return str;
for (var i = 0, len = str.length; i < len; i++) {
c = str.charAt(i);
if (opts.chars.indexOf(c) !== -1) {
last = i;
}
if (i < opts.max) continue;
if (last === 0) {
return !opts.truncate ? '' : str.substring(0, opts.max - 1) + opts.ellipse;
}
return str.substring(0, last) + opts.ellipse;
}
return str;
};