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:
parent
d8b4e395ca
commit
fed0e9fdd7
8 changed files with 241 additions and 108 deletions
Binary file not shown.
BIN
files_reader/vendor/pdfjs/.pdf.reader.js.swp
vendored
BIN
files_reader/vendor/pdfjs/.pdf.reader.js.swp
vendored
Binary file not shown.
Binary file not shown.
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
8
files_reader/vendor/pdfjs/css/sidebar.css
vendored
8
files_reader/vendor/pdfjs/css/sidebar.css
vendored
|
@ -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 */
|
||||
|
|
125
files_reader/vendor/pdfjs/pdf.reader.js
vendored
125
files_reader/vendor/pdfjs/pdf.reader.js
vendored
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue