mirror of
https://github.com/Yetangitu/owncloud-apps.git
synced 2025-10-02 14:49:17 +02:00
files_reader: More PDF madness, next/previous search hit navigation w/highlighting, etc...
This commit is contained in:
parent
640256c49b
commit
f909cd0f1b
11 changed files with 448 additions and 458 deletions
Binary file not shown.
|
@ -1,4 +1,3 @@
|
|||
- search
|
||||
- bookmarks
|
||||
- annotations
|
||||
- settings
|
||||
|
@ -6,5 +5,7 @@
|
|||
- rtl and ltr
|
||||
|
||||
- test canvas size restriction
|
||||
- test internal links
|
||||
|
||||
- add IDs to highlights so they can be marked when hovered - or when related list item is hovered
|
||||
|
||||
- add preload/postload of X pages around current position (optional), store resulting rendered pages in off-screen canvas?
|
||||
|
|
|
@ -258,6 +258,8 @@
|
|||
<a id="slider" class="icon-menu">
|
||||
<?php p($l->t("menu")); ?>
|
||||
</a>
|
||||
<div id="status_message_left">
|
||||
</div>
|
||||
</div>
|
||||
<div id="metainfo" class="nightshift">
|
||||
<span id="book-title">
|
||||
|
@ -273,23 +275,11 @@
|
|||
</span>
|
||||
</div>
|
||||
<div id="title-controls">
|
||||
<!-- select works fine, except for the fact that - as usual - apple mobile does not support icons...
|
||||
<label for="zoomlevel">zoom: </label>
|
||||
<select id="zoomlevel">
|
||||
<option value="spread" data-icon="" data-text="2-page"></option>
|
||||
<option value="fit_page" data-icon="" data-text="fit page"></option>
|
||||
<option value="fit_width" data-icon="" data-text="fit width"></option>
|
||||
<option value="0.25" class="text">25%</option>
|
||||
<option value="0.5" class="text">50%</option>
|
||||
<option value="0.75" class="text">75%</option>
|
||||
<option value="1" class="text">100%</option>
|
||||
<option value="1.25" class="text">125%</option>
|
||||
<option value="1.5" class="text">150%</option>
|
||||
<option value="2" class="text">200%</option>
|
||||
<option value="3" class="text">300%</option>
|
||||
<option value="4" class="text">400%</option>
|
||||
</select>
|
||||
-->
|
||||
<div id="status_message_right">
|
||||
</div>
|
||||
<div id="match_count">
|
||||
</div>
|
||||
<!-- select works fine, except for the fact that - as usual - apple mobile acts up... -->
|
||||
<div id="zoom_options" class="hide">
|
||||
<div class="zoom_option icon-double_page_mode" data-value="spread" data-class="icon-double_page_mode" data-text=""></div>
|
||||
<div class="zoom_option icon-single_page_mode" data-value="fit_page" data-class="icon-single_page_mode" data-text=""></div>
|
||||
|
|
|
@ -24,11 +24,18 @@ PDFJS.reader.ControlsController = function(book) {
|
|||
$rotate_left = $("#rotate_left"),
|
||||
$rotate_right = $("#rotate_right"),
|
||||
$page_num = $("#page_num"),
|
||||
$total_pages = $("#total_pages");
|
||||
$total_pages = $("#total_pages"),
|
||||
$status_message_left = $("#status_message_left"),
|
||||
$status_message_right = $("#status_message_right");
|
||||
|
||||
var STATUS_MESSAGE_LENGTH = 30,
|
||||
STATUS_MESSAGE_TIMEOUT = 3000,
|
||||
status_timeout_left,
|
||||
status_timeout_right;
|
||||
|
||||
if (reader.isMobile() === true) {
|
||||
$titlebar.addClass("background_visible");
|
||||
};
|
||||
}
|
||||
|
||||
var show = function () {
|
||||
$titlebar.removeClass("hide");
|
||||
|
@ -46,6 +53,31 @@ PDFJS.reader.ControlsController = function(book) {
|
|||
reader.ControlsController.toggle();
|
||||
});
|
||||
|
||||
var setStatus = function (message, right) {
|
||||
|
||||
$status_message = (right) ? $status_message_right : $status_message_left;
|
||||
status_timeout = (right) ? status_timeout_right : status_timeout_left;
|
||||
|
||||
$status_message[0].textContent = reader.ellipsize(message, STATUS_MESSAGE_LENGTH);
|
||||
//$status_message[0].textContent = message;
|
||||
|
||||
if (typeof status_timeout === "number") {
|
||||
clearTimeout(status_timeout);
|
||||
status_timeout = undefined;
|
||||
}
|
||||
|
||||
status_timeout = setTimeout(function () {
|
||||
$status_message[0].textContent = "";
|
||||
}, STATUS_MESSAGE_TIMEOUT);
|
||||
|
||||
if (right) {
|
||||
status_timeout_right = status_timeout;
|
||||
} else {
|
||||
status_timeout_left = status_timeout;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var fullscreen = false;
|
||||
|
||||
$slider.on("click", function () {
|
||||
|
@ -105,21 +137,8 @@ PDFJS.reader.ControlsController = function(book) {
|
|||
|
||||
});
|
||||
|
||||
/* select works fine on most browsers, but - of course - apple mobile has 'special needs'
|
||||
* in that it does not support any styling in the drop-down list, and as such can not display
|
||||
* icons there. Due to the unfortunate fact that many still buy these apple-encumbered devices
|
||||
/* select works fine on most browsers, but - of course - apple mobile has 'special needs' so
|
||||
* a custom select is needed...
|
||||
*
|
||||
$zoomlevel.val(settings.zoomLevel);
|
||||
|
||||
$zoomlevel.on("change", function () {
|
||||
reader.setZoom($(this).val());
|
||||
var $option = $zoomlevel.find(":selected");
|
||||
if ($option.data("icon") !== undefined)
|
||||
$("#zoom_icon")[0].textContent = $option.data("icon");
|
||||
});
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
/* custom select, supports icons in drop-down list */
|
||||
|
@ -245,7 +264,7 @@ PDFJS.reader.ControlsController = function(book) {
|
|||
break;
|
||||
}
|
||||
|
||||
e.stopPropagation;
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
|
||||
|
@ -278,7 +297,6 @@ PDFJS.reader.ControlsController = function(book) {
|
|||
} else {
|
||||
page -= (page + 1) % 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (page >= 0 && page <= total_pages) {
|
||||
if (page === total_pages) {
|
||||
|
@ -289,6 +307,9 @@ PDFJS.reader.ControlsController = function(book) {
|
|||
text = reader.getPageLabel(page) + "-" + reader.getPageLabel(page + 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
text = reader.getPageLabel(page);
|
||||
}
|
||||
|
||||
$page_num[0].textContent = text;
|
||||
};
|
||||
|
@ -332,6 +353,7 @@ PDFJS.reader.ControlsController = function(book) {
|
|||
"setZoomIcon": setZoomIcon,
|
||||
"setRotateIcon": setRotateIcon,
|
||||
"setCurrentPage": setCurrentPage,
|
||||
"setPageCount": setPageCount
|
||||
"setPageCount": setPageCount,
|
||||
"setStatus": setStatus
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
PDFJS.reader.ReaderController = function(book) {
|
||||
PDFJS.reader.ReaderController = function() {
|
||||
var $main = $("#main"),
|
||||
$viewer = $("#viewer"),
|
||||
$divider = $("#divider"),
|
||||
|
@ -13,7 +13,8 @@ PDFJS.reader.ReaderController = function(book) {
|
|||
$bookmark = $("#bookmark"),
|
||||
$note = $("#note"),
|
||||
$rotate_left = $("#rotate_left"),
|
||||
$rotate_right = $("#rotate_right");
|
||||
$rotate_right = $("#rotate_right"),
|
||||
$clear_search = $("#clear_search");
|
||||
|
||||
var reader = this,
|
||||
book = this.book,
|
||||
|
@ -76,6 +77,8 @@ PDFJS.reader.ReaderController = function(book) {
|
|||
|
||||
var page_no = false;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
switch (settings.keyboard[e.keyCode]) {
|
||||
case 'previous':
|
||||
$prev.click();
|
||||
|
@ -121,6 +124,22 @@ PDFJS.reader.ReaderController = function(book) {
|
|||
break;
|
||||
case 'cycleZoom':
|
||||
reader.cycleZoom();
|
||||
break;
|
||||
case 'previousMatch':
|
||||
reader.SearchController.nextMatch(true);
|
||||
break;
|
||||
case 'nextMatch':
|
||||
reader.SearchController.nextMatch(false);
|
||||
break;
|
||||
case 'clearSearch':
|
||||
$clear_search.click();
|
||||
break;
|
||||
case 'search':
|
||||
if (e.shiftKey) {
|
||||
reader.SidebarController.changePanelTo("Search");
|
||||
reader.SearchController.show();
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
console.log("unsupported keyCode: " + e.keyCode);
|
||||
|
@ -129,7 +148,7 @@ PDFJS.reader.ReaderController = function(book) {
|
|||
if (page_no) {
|
||||
reader.queuePage(page_no);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', keyCommands, false);
|
||||
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
var FindStates = {
|
||||
FIND_FOUND: 0,
|
||||
FIND_NOTFOUND: 1,
|
||||
FIND_WRAPPED: 2,
|
||||
FIND_PENDING: 3
|
||||
};
|
||||
PDFJS.reader.SearchController = function () {
|
||||
|
||||
var FIND_SCROLL_OFFSET_TOP = -50;
|
||||
var FIND_SCROLL_OFFSET_LEFT = -400;
|
||||
var reader = this,
|
||||
book = this.book;
|
||||
|
||||
var CHARACTERS_TO_NORMALIZE = {
|
||||
var $searchBox = $("#searchBox"),
|
||||
$clearBtn = $("#searchBox").next(),
|
||||
$clear_search = $("#clear_search"),
|
||||
$searchResults = $("#searchResults"),
|
||||
$searchView = $("#searchView"),
|
||||
$body = $("#viewer iframe").contents().find('body'),
|
||||
$sidebar = $("#sidebar"),
|
||||
$match_count = $("#match_count");
|
||||
|
||||
/* search logic, partly from Mozilla pdfViewer */
|
||||
var CHARACTERS_TO_NORMALIZE = {
|
||||
'\u2018': '\'', // Left single quotation mark
|
||||
'\u2019': '\'', // Right single quotation mark
|
||||
'\u201A': '\'', // Single low-9 quotation mark
|
||||
|
@ -20,68 +25,37 @@ var CHARACTERS_TO_NORMALIZE = {
|
|||
'\u00BC': '1/4', // Vulgar fraction one quarter
|
||||
'\u00BD': '1/2', // Vulgar fraction one half
|
||||
'\u00BE': '3/4', // Vulgar fraction three quarters
|
||||
};
|
||||
|
||||
PDFJS.reader.SearchController = function () {
|
||||
|
||||
var reader = this,
|
||||
book = this.book,
|
||||
query = "";
|
||||
|
||||
var $searchBox = $("#searchBox"),
|
||||
$clearBtn = $("#searchBox").next(),
|
||||
$clear_search = $("#clear_search"),
|
||||
$searchResults = $("#searchResults"),
|
||||
$searchView = $("#searchView"),
|
||||
$body = $("#viewer iframe").contents().find('body'),
|
||||
$sidebar = $("#sidebar");
|
||||
|
||||
var onShow = function() {
|
||||
$searchView.addClass("open");
|
||||
$searchBox.focus();
|
||||
};
|
||||
|
||||
var onHide = function() {
|
||||
unhighlight();
|
||||
$searchView.removeClass("open");
|
||||
};
|
||||
|
||||
this.onUpdateResultsCount = null;
|
||||
this.onUpdateState = null;
|
||||
var startedTextExtraction = false,
|
||||
extractTextPromises = [],
|
||||
matchCount = 0,
|
||||
pendingFindMatches = Object.create(null);
|
||||
|
||||
// Compile the regular expression for text normalization once.
|
||||
var replace = Object.keys(CHARACTERS_TO_NORMALIZE).join('');
|
||||
this.normalizationRegex = new RegExp('[' + replace + ']', 'g');
|
||||
var replace = Object.keys(CHARACTERS_TO_NORMALIZE).join(''),
|
||||
normalizationRegex = new RegExp('[' + replace + ']', 'g');
|
||||
|
||||
var reset = function () {
|
||||
this.startedTextExtraction = false;
|
||||
this.extractTextPromises = [];
|
||||
this.pendingFindMatches = Object.create(null);
|
||||
this.active = false; // If active, find results will be highlighted.
|
||||
this.pageContents = []; // Stores the text for each page.
|
||||
this.pageMatches = [];
|
||||
this.pageMatchesLength = null;
|
||||
this.matchCount = 0;
|
||||
this.selected = { // Currently selected match.
|
||||
|
||||
pendingFindMatches = Object.create(null);
|
||||
reader.search_active = false; // If active, find results will be highlighted.
|
||||
reader.pageMatches.length = 0;
|
||||
reader.pageMatchesLength = null;
|
||||
reader.search_state = null;
|
||||
matchCount = 0;
|
||||
resetMatchCounter();
|
||||
reader.selected = { // Currently selected match.
|
||||
pageIdx: -1,
|
||||
matchIdx: -1
|
||||
matchIdx: -1,
|
||||
at_start: false,
|
||||
at_end: false
|
||||
};
|
||||
this.offset = { // Where the find algorithm currently is in the document.
|
||||
pageIdx: null,
|
||||
matchIdx: null
|
||||
updatePage();
|
||||
};
|
||||
this.pagesToSearch = null;
|
||||
this.resumePageIdx = null;
|
||||
this.state = null;
|
||||
this.dirtyMatch = false;
|
||||
this.findTimeout = null;
|
||||
};
|
||||
|
||||
reset();
|
||||
|
||||
|
||||
var normalize = function (text) {
|
||||
return text.replace(this.normalizationRegex, function (ch) {
|
||||
return text.replace(normalizationRegex, function (ch) {
|
||||
return CHARACTERS_TO_NORMALIZE[ch];
|
||||
});
|
||||
};
|
||||
|
@ -151,7 +125,7 @@ PDFJS.reader.SearchController = function () {
|
|||
}
|
||||
matches.push(matchIdx);
|
||||
}
|
||||
this.pageMatches[pageIndex] = matches;
|
||||
reader.pageMatches[pageIndex] = matches;
|
||||
|
||||
};
|
||||
|
||||
|
@ -179,21 +153,22 @@ PDFJS.reader.SearchController = function () {
|
|||
}
|
||||
}
|
||||
// Prepare arrays for store the matches.
|
||||
if (!this.pageMatchesLength) {
|
||||
this.pageMatchesLength = [];
|
||||
if (!reader.pageMatchesLength) {
|
||||
reader.pageMatchesLength = [];
|
||||
}
|
||||
this.pageMatchesLength[pageIndex] = [];
|
||||
this.pageMatches[pageIndex] = [];
|
||||
reader.pageMatchesLength[pageIndex] = [];
|
||||
reader.pageMatches[pageIndex] = [];
|
||||
// Sort matchesWithLength, clean up intersecting terms
|
||||
// and put the result into the two arrays.
|
||||
_prepareMatches(matchesWithLength, this.pageMatches[pageIndex],
|
||||
this.pageMatchesLength[pageIndex]);
|
||||
_prepareMatches(matchesWithLength, reader.pageMatches[pageIndex],
|
||||
reader.pageMatchesLength[pageIndex]);
|
||||
|
||||
};
|
||||
|
||||
var getSnippet = function (pageIndex, position) {
|
||||
|
||||
var ellipse = '…',
|
||||
match_length = this.state.query.length,
|
||||
match_length = reader.search_state.query.length,
|
||||
span = '<span class="search_match">',
|
||||
span_close = '</span>',
|
||||
limit = 160 + span.length + span_close.length,
|
||||
|
@ -201,10 +176,10 @@ PDFJS.reader.SearchController = function () {
|
|||
trailer,
|
||||
context;
|
||||
|
||||
leader = this.pageContents[pageIndex].substring(position - limit/2, position);
|
||||
leader = reader.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);
|
||||
trailer = reader.pageContents[pageIndex].substring(position + match_length, position + limit/2 + match_length);
|
||||
query = reader.pageContents[pageIndex].substring(position, position + match_length);
|
||||
|
||||
context = ellipse + leader + span + query + span_close + trailer;
|
||||
|
||||
|
@ -215,7 +190,6 @@ PDFJS.reader.SearchController = function () {
|
|||
|
||||
var listitem = document.createElement("li"),
|
||||
link = document.createElement("a"),
|
||||
id = parseInt(pageIndex + 1) + ":" + position,
|
||||
item = {
|
||||
url: null,
|
||||
dest: null,
|
||||
|
@ -227,10 +201,9 @@ PDFJS.reader.SearchController = function () {
|
|||
item.dest = [pageIndex,position];
|
||||
|
||||
//link.textContent = getSnippet(pageIndex, position);
|
||||
link.innerHTML = getSnippet(pageIndex, position);
|
||||
listitem.dataset.index = ++matchCount;
|
||||
link.innerHTML = '<span class="match_label">' + matchCount + '</span>' + 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);
|
||||
|
@ -238,16 +211,40 @@ PDFJS.reader.SearchController = function () {
|
|||
return listitem;
|
||||
};
|
||||
|
||||
var createItemList = function (pageIdx) {
|
||||
|
||||
var currentIdx = reader.settings.currentPage - 1,
|
||||
item,
|
||||
i = 0;
|
||||
|
||||
// currentIdx can be up to 2 different from pageIdx due to oddPageFirst and spread rendering
|
||||
if (Math.abs(pageIdx - currentIdx) <= 2)
|
||||
updatePage(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);
|
||||
reader.pageMatches[pageIdx].forEach(function (match) {
|
||||
item = createItem(pageIdx, match);
|
||||
item.id = "match:" + pageIdx + ":" + i;
|
||||
item.classList.add("match:" + pageIdx + ":" + i++);
|
||||
fragment.appendChild(item);
|
||||
updateMatchCounter();
|
||||
});
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
var calcFindMatch = function (pageIndex) {
|
||||
var pageContent = normalize(this.pageContents[pageIndex]);
|
||||
var query = normalize(this.state.query);
|
||||
var caseSensitive = this.state.caseSensitive;
|
||||
var phraseSearch = this.state.phraseSearch;
|
||||
var pageContent = normalize(reader.pageContents[pageIndex]);
|
||||
var query = normalize(reader.search_state.query);
|
||||
var caseSensitive = reader.search_state.caseSensitive;
|
||||
var phraseSearch = reader.search_state.phraseSearch;
|
||||
var queryLen = query.length;
|
||||
|
||||
if (queryLen === 0) {
|
||||
// Do nothing: the matches should be wiped out already.
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -265,24 +262,25 @@ PDFJS.reader.SearchController = function () {
|
|||
|
||||
var extractText = function () {
|
||||
|
||||
if (this.startedTextExtraction) {
|
||||
if (startedTextExtraction) {
|
||||
return;
|
||||
}
|
||||
this.startedTextExtraction = true;
|
||||
startedTextExtraction = true;
|
||||
|
||||
this.pageContents = [];
|
||||
reader.pageContents = [];
|
||||
var extractTextPromisesResolves = [];
|
||||
var numPages = reader.settings.numPages;
|
||||
|
||||
for (var i = 0; i < numPages; i++) {
|
||||
this.extractTextPromises.push(new Promise(function (resolve) {
|
||||
extractTextPromises.push(new Promise(function (resolve) {
|
||||
extractTextPromisesResolves.push(resolve);
|
||||
}));
|
||||
}
|
||||
|
||||
var self = this;
|
||||
function extractPageText(pageIndex) {
|
||||
reader.getPageTextContent(pageIndex).then(
|
||||
function textContentResolved(textContent) {
|
||||
reader.ControlsController.setStatus("extracting text page " + parseInt(pageIndex + 1),true);
|
||||
var textItems = textContent.items;
|
||||
var str = [];
|
||||
|
||||
|
@ -291,7 +289,7 @@ PDFJS.reader.SearchController = function () {
|
|||
}
|
||||
|
||||
// Store the pageContent as a string.
|
||||
self.pageContents.push(str.join(' ').replace(/\s\s+/g, ' '));
|
||||
reader.pageContents.push(str.join(''));
|
||||
|
||||
extractTextPromisesResolves[pageIndex](pageIndex);
|
||||
if ((pageIndex + 1) < reader.settings.numPages) {
|
||||
|
@ -303,264 +301,211 @@ PDFJS.reader.SearchController = function () {
|
|||
extractPageText(0);
|
||||
};
|
||||
|
||||
var executeCommand = function (cmd, state) {
|
||||
if (this.state === null || cmd !== 'findagain') {
|
||||
this.dirtyMatch = true;
|
||||
var updatePage = function (pageIdx) {
|
||||
|
||||
var pageNum = (pageIdx) ? pageIdx + 1 : null;
|
||||
|
||||
if (reader.resourcelst) {
|
||||
|
||||
reader.resourcelst.forEach(function(list) {
|
||||
|
||||
if (list.textLayer && (pageNum === list.pageNum || pageNum === null)) {
|
||||
list.textLayer.updateMatches();
|
||||
}
|
||||
this.state = state;
|
||||
updateUIState(FindStates.FIND_PENDING);
|
||||
|
||||
console.log("execute command ", cmd, " with state ", state);
|
||||
|
||||
reader.firstPagePromise.then(function() {
|
||||
extractText();
|
||||
|
||||
clearTimeout(this.findTimeout);
|
||||
if (cmd === 'find') {
|
||||
// Only trigger the find action after 250ms of silence.
|
||||
//this.findTimeout = setTimeout(nextMatch.bind(this), 250);
|
||||
generateMatchList();
|
||||
} else {
|
||||
nextMatch();
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
var updatePage = function (index) {
|
||||
var executeCommand = function (cmd, state) {
|
||||
|
||||
if (this.selected.pageIdx === index) {
|
||||
// If the page is selected, scroll the page into view, which triggers
|
||||
// rendering the page, which adds the textLayer. Once the textLayer is
|
||||
// build, it will scroll onto the selected match.
|
||||
reader.settings.currentPage = index + 1;
|
||||
reader.search_state = state;
|
||||
|
||||
reader.firstPagePromise.then(function() {
|
||||
if (reader.pageContents.length < reader.settings.numPages)
|
||||
extractText();
|
||||
|
||||
if (cmd === 'find') {
|
||||
reader.search_active = true;
|
||||
$match_count.show();
|
||||
generateMatchList();
|
||||
}
|
||||
|
||||
//var page = this.pdfViewer.getPageView(index);
|
||||
//if (page.textLayer) {
|
||||
// page.textLayer.updateMatches();
|
||||
//}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
var generateMatchList = function () {
|
||||
|
||||
var container = document.getElementById("searchResults"),
|
||||
numPages = reader.settings.numPages,
|
||||
self = this;
|
||||
currentIdx = reader.settings.currentPage - 1,
|
||||
i;
|
||||
|
||||
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];
|
||||
if (reader.pageContents.length !== numPages) {
|
||||
extractText();
|
||||
for (i = 0; i < numPages; i++) {
|
||||
if (!(i in pendingFindMatches)) {
|
||||
pendingFindMatches[i] = true;
|
||||
extractTextPromises[i].then(function(pageIdx) {
|
||||
delete 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);
|
||||
if (reader.pageMatches[pageIdx].length > 0) {
|
||||
container.appendChild(createItemList(pageIdx));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < numPages; i++) {
|
||||
calcFindMatch(i);
|
||||
if (reader.pageMatches[i].length > 0) {
|
||||
container.appendChild(createItemList(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var nextMatch = function () {
|
||||
var nextMatch = function (previous) {
|
||||
|
||||
var previous = this.state.findPrevious;
|
||||
var currentPageIndex = reader.settings.currentPage - 1;
|
||||
var numPages = reader.settings.numPages;
|
||||
|
||||
this.active = true;
|
||||
|
||||
if (this.dirtyMatch) {
|
||||
// Need to recalculate the matches, reset everything.
|
||||
this.dirtyMatch = false;
|
||||
this.selected.pageIdx = this.selected.matchIdx = -1;
|
||||
this.offset.pageIdx = currentPageIndex;
|
||||
this.offset.matchIdx = null;
|
||||
this.hadMatch = false;
|
||||
this.resumePageIdx = null;
|
||||
this.pageMatches = [];
|
||||
this.matchCount = 0;
|
||||
this.pageMatchesLength = null;
|
||||
var self = this;
|
||||
|
||||
for (var i = 0; i < numPages; i++) {
|
||||
// Wipe out any previous highlighted matches.
|
||||
updatePage(i);
|
||||
|
||||
// As soon as the text is extracted start finding the matches.
|
||||
if (!(i in this.pendingFindMatches)) {
|
||||
this.pendingFindMatches[i] = true;
|
||||
this.extractTextPromises[i].then(function(pageIdx) {
|
||||
delete self.pendingFindMatches[pageIdx];
|
||||
calcFindMatch(pageIdx);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there's no query there's no point in searching.
|
||||
if (this.state.query === '') {
|
||||
updateUIState(FindStates.FIND_FOUND);
|
||||
/* don't try to follow non-existing matches */
|
||||
if (!reader.search_active ||
|
||||
reader.pageMatches.length === 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're waiting on a page, we return since we can't do anything else.
|
||||
if (this.resumePageIdx) {
|
||||
return;
|
||||
}
|
||||
var numPages = reader.settings.numPages,
|
||||
selected = reader.selected,
|
||||
leftIdx = idxOrNull(reader.resourcelst[0].pageNum),
|
||||
rightIdx = idxOrNull(reader.resourcelst[1].pageNum),
|
||||
try_match = false;
|
||||
|
||||
var offset = this.offset;
|
||||
// Keep track of how many pages we should maximally iterate through.
|
||||
this.pagesToSearch = numPages;
|
||||
// If there's already a matchIdx that means we are iterating through a
|
||||
// page's matches.
|
||||
if (offset.matchIdx !== null) {
|
||||
var numPageMatches = this.pageMatches[offset.pageIdx].length;
|
||||
if ((!previous && offset.matchIdx + 1 < numPageMatches) ||
|
||||
(previous && offset.matchIdx > 0)) {
|
||||
// The simple case; we just have advance the matchIdx to select
|
||||
// the next match on the page.
|
||||
this.hadMatch = true;
|
||||
offset.matchIdx = (previous ? offset.matchIdx - 1 :
|
||||
offset.matchIdx + 1);
|
||||
updateMatch(true);
|
||||
return;
|
||||
}
|
||||
// We went beyond the current page's matches, so we advance to
|
||||
// the next page.
|
||||
advanceOffsetPage(previous);
|
||||
}
|
||||
// Start searching through the page.
|
||||
nextPageMatch();
|
||||
};
|
||||
/* prevent match cycling on first or last page */
|
||||
if (!((previous && selected.at_start) || (!previous && selected.at_end))) {
|
||||
|
||||
var matchesReady = function (matches) {
|
||||
var offset = this.offset;
|
||||
var numMatches = matches.length;
|
||||
var previous = this.state.findPrevious;
|
||||
selected.at_start = selected.at_end = false;
|
||||
|
||||
if (numMatches) {
|
||||
// There were matches for the page, so initialize the matchIdx.
|
||||
this.hadMatch = true;
|
||||
offset.matchIdx = (previous ? numMatches - 1 : 0);
|
||||
updateMatch(true);
|
||||
return true;
|
||||
}
|
||||
// No matches, so attempt to search the next page.
|
||||
advanceOffsetPage(previous);
|
||||
if (offset.wrapped) {
|
||||
offset.matchIdx = null;
|
||||
if (this.pagesToSearch < 0) {
|
||||
// No point in wrapping again, there were no matches.
|
||||
updateMatch(false);
|
||||
// while matches were not found, searching for a page
|
||||
// with matches should nevertheless halt.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Matches were not found (and searching is not done).
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* The method is called back from the text layer when match presentation
|
||||
* is updated.
|
||||
* @param {number} pageIndex - page index.
|
||||
* @param {number} index - match index.
|
||||
* @param {Array} elements - text layer div elements array.
|
||||
* @param {number} beginIdx - start index of the div array for the match.
|
||||
/* when in spread view, start at left (forward search) or right (backward search) page
|
||||
* if not iterating over matches on currently visible pages
|
||||
*/
|
||||
var updateMatchPosition = function (
|
||||
pageIndex, index, elements, beginIdx) {
|
||||
if (this.selected.matchIdx === index &&
|
||||
this.selected.pageIdx === pageIndex) {
|
||||
//var spot = {
|
||||
// top: FIND_SCROLL_OFFSET_TOP,
|
||||
// left: FIND_SCROLL_OFFSET_LEFT
|
||||
//};
|
||||
//scrollIntoView(elements[beginIdx], spot,
|
||||
// /* skipOverflowHiddenElements = */ true);
|
||||
if (!(selected.matchIdx !== -1 && isVisible(selected.pageIdx))) {
|
||||
if (previous) {
|
||||
selected.pageIdx = (typeof rightIdx === "number") ? rightIdx : leftIdx;
|
||||
} else {
|
||||
selected.pageIdx = (typeof leftIdx === "number") ? leftIdx : rightIdx;
|
||||
}
|
||||
console.log("would scroll into view here except for the fact that Reader is a non-scrolling reader...");
|
||||
};
|
||||
try_match = true;
|
||||
|
||||
var nextPageMatch = function () {
|
||||
if (this.resumePageIdx !== null) {
|
||||
console.error('There can only be one pending page.');
|
||||
} else {
|
||||
|
||||
var numPageMatches = reader.pageMatches[selected.pageIdx].length;
|
||||
|
||||
if ((!previous && selected.matchIdx + 1 < numPageMatches) || (previous && selected.matchIdx > 0)) {
|
||||
selected.matchIdx = (previous ? selected.matchIdx - 1 : selected.matchIdx + 1);
|
||||
updateOrQueue();
|
||||
return;
|
||||
} else {
|
||||
selected.pageIdx += (previous) ? -1 : 1;
|
||||
try_match = true;
|
||||
}
|
||||
}
|
||||
do {
|
||||
var pageIdx = this.offset.pageIdx;
|
||||
var matches = this.pageMatches[pageIdx];
|
||||
if (!matches) {
|
||||
// The matches don't exist yet for processing by "matchesReady",
|
||||
// so set a resume point for when they do exist.
|
||||
this.resumePageIdx = pageIdx;
|
||||
break;
|
||||
}
|
||||
} while (!matchesReady(matches));
|
||||
};
|
||||
|
||||
var advanceOffsetPage = function (previous) {
|
||||
var offset = this.offset;
|
||||
var numPages = this.extractTextPromises.length;
|
||||
offset.pageIdx = (previous ? offset.pageIdx - 1 : offset.pageIdx + 1);
|
||||
offset.matchIdx = null;
|
||||
if (try_match && nextPageMatch(previous)) {
|
||||
updateOrQueue();
|
||||
return;
|
||||
} else {
|
||||
if (previous) {
|
||||
reader.ControlsController.setStatus("at first match", true);
|
||||
selected.at_start = true;
|
||||
} else {
|
||||
reader.ControlsController.setStatus("at last match", true);
|
||||
selected.at_end = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.pagesToSearch--;
|
||||
function idxOrNull(num) {
|
||||
|
||||
if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
|
||||
offset.pageIdx = (previous ? numPages - 1 : 0);
|
||||
offset.wrapped = true;
|
||||
if (typeof num === "number") {
|
||||
return num - 1;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function isVisible (idx) {
|
||||
return (idx === leftIdx || idx === rightIdx);
|
||||
}
|
||||
|
||||
function nextPageMatch (previous) {
|
||||
|
||||
var i,
|
||||
found;
|
||||
|
||||
if (previous) {
|
||||
for (i = selected.pageIdx; i >= -1 && reader.pageMatches[i] === undefined; i--) {}
|
||||
} else {
|
||||
for (i = selected.pageIdx; i <= numPages && reader.pageMatches[i] === undefined; i++) {}
|
||||
}
|
||||
|
||||
if (i < 0 || i >= numPages) {
|
||||
i = -1;
|
||||
//selected.pageIdx = selected.matchIdx = -1;
|
||||
selected.matchIdx = -1;
|
||||
found = false;
|
||||
} else {
|
||||
selected.pageIdx = i;
|
||||
selected.matchIdx = (previous) ? reader.pageMatches[i].length - 1 : 0;
|
||||
found = true;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
function updateOrQueue() {
|
||||
|
||||
var root = document.getElementById("searchResults"),
|
||||
item,
|
||||
match,
|
||||
i;
|
||||
|
||||
item = root.getElementsByClassName("selected");
|
||||
while (item.length)
|
||||
item[0].classList.remove("selected");
|
||||
|
||||
match = document.getElementById("match:" + selected.pageIdx + ":" + selected.matchIdx);
|
||||
match.classList.add("selected");
|
||||
match = document.getElementsByClassName("match:" + selected.pageIdx + ":" + selected.matchIdx);
|
||||
for (i = 0; i < match.length; i++)
|
||||
match[i].classList.add("selected_again");
|
||||
|
||||
|
||||
updateMatchCounter(match.dataset.index);
|
||||
if (!reader.isVisible(match))
|
||||
match.scrollIntoView();
|
||||
|
||||
if (isVisible(selected.pageIdx)) {
|
||||
[ leftIdx, rightIdx ].forEach(function (idx) {
|
||||
if (typeof idx === "number") updatePage(idx);
|
||||
});
|
||||
} else {
|
||||
reader.queuePage(selected.pageIdx + 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var updateMatch = function (found) {
|
||||
var state = FindStates.FIND_NOTFOUND;
|
||||
var wrapped = this.offset.wrapped;
|
||||
this.offset.wrapped = false;
|
||||
var updateMatchCounter = function (index) {
|
||||
|
||||
if (found) {
|
||||
var previousPage = this.selected.pageIdx;
|
||||
this.selected.pageIdx = this.offset.pageIdx;
|
||||
this.selected.matchIdx = this.offset.matchIdx;
|
||||
state = (wrapped ? FindStates.FIND_WRAPPED : FindStates.FIND_FOUND);
|
||||
// Update the currently selected page to wipe out any selected matches.
|
||||
if (previousPage !== -1 && previousPage !== this.selected.pageIdx) {
|
||||
updatePage(previousPage);
|
||||
}
|
||||
}
|
||||
var prefix = "";
|
||||
|
||||
updateUIState(state, this.state.findPrevious);
|
||||
if (this.selected.pageIdx !== -1) {
|
||||
updatePage(this.selected.pageIdx);
|
||||
}
|
||||
if (index)
|
||||
prefix = index + "/";
|
||||
|
||||
$match_count[0].textContent = prefix + matchCount;
|
||||
};
|
||||
|
||||
var updateUIResultsCount = function () {
|
||||
if (this.onUpdateResultsCount) {
|
||||
onUpdateResultsCount(this.matchCount);
|
||||
}
|
||||
var resetMatchCounter = function () {
|
||||
$match_count[0].textContent = "0";
|
||||
$match_count.hide();
|
||||
};
|
||||
|
||||
var updateUIState = function (state, previous) {
|
||||
if (this.onUpdateState) {
|
||||
onUpdateState(state, previous, this.matchCount);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var search = function(q) {
|
||||
if (q === undefined) {
|
||||
q = $searchBox.val();
|
||||
|
@ -576,10 +521,7 @@ PDFJS.reader.SearchController = function () {
|
|||
reset();
|
||||
$searchResults.empty();
|
||||
|
||||
this.query = q;
|
||||
|
||||
executeCommand('find', {query: q});
|
||||
highlightQuery();
|
||||
};
|
||||
|
||||
$searchBox.on("keydown", function(e) {
|
||||
|
@ -601,14 +543,13 @@ PDFJS.reader.SearchController = function () {
|
|||
|
||||
$clear_search.on("click", function () {
|
||||
reset();
|
||||
unhighlight();
|
||||
$searchResults.empty();
|
||||
$searchBox.val("");
|
||||
});
|
||||
|
||||
var clear = function () {
|
||||
|
||||
reset();
|
||||
unhighlight();
|
||||
$searchResults.empty();
|
||||
|
||||
if (reader.SidebarController.getActivePanel() == "Search") {
|
||||
|
@ -616,14 +557,24 @@ PDFJS.reader.SearchController = function () {
|
|||
}
|
||||
};
|
||||
|
||||
var highlightQuery = function(e) {
|
||||
$("#text_left").contents().highlight(this.state.query, { element: 'span' });
|
||||
$("#text_right").contents().highlight(this.state.query, { element: 'span' });
|
||||
// initialize search
|
||||
reset();
|
||||
|
||||
if (reader.settings.preloadTextcontent) {
|
||||
reader.firstPagePromise.then(function() {
|
||||
setTimeout(function() {
|
||||
extractText();
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
var onShow = function() {
|
||||
$searchView.addClass("open");
|
||||
$searchBox.focus();
|
||||
};
|
||||
|
||||
var unhighlight = function(e) {
|
||||
$("#text_left").unhighlight();
|
||||
$("#text_right").unhighlight();
|
||||
var onHide = function() {
|
||||
$searchView.removeClass("open");
|
||||
};
|
||||
|
||||
|
||||
|
@ -632,7 +583,7 @@ PDFJS.reader.SearchController = function () {
|
|||
"hide": onHide,
|
||||
"search": search,
|
||||
"executeCommand": executeCommand,
|
||||
"highlightQuery": highlightQuery,
|
||||
"unhighlight": unhighlight
|
||||
"nextMatch": nextMatch
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,40 +1,8 @@
|
|||
/* Copyright 2012 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} TextLayerBuilderOptions
|
||||
* @property {HTMLDivElement} textLayerDiv - The text layer container.
|
||||
* @property {EventBus} eventBus - The application event bus.
|
||||
* @property {number} pageIndex - The page index.
|
||||
* @property {PageViewport} viewport - The viewport of the text layer.
|
||||
* @property {PDFFindController} findController
|
||||
* @property {boolean} enhanceTextSelection - Option to turn on improved
|
||||
* text selection.
|
||||
*/
|
||||
|
||||
/**
|
||||
* TextLayerBuilder provides text-selection functionality for the PDF.
|
||||
* It does this by creating overlay divs over the PDF text. These divs
|
||||
* contain text that matches the PDF text they are overlaying. This object
|
||||
* also provides a way to highlight text that is being searched for.
|
||||
* @class
|
||||
*/
|
||||
PDFJS.Reader.TextLayerController = function (options) {
|
||||
PDFJS.Reader.TextLayerController = function (options, reader) {
|
||||
|
||||
var EXPAND_DIVS_TIMEOUT = 300; // ms
|
||||
|
||||
this.reader = reader;
|
||||
this.textLayerDiv = options.textLayerDiv;
|
||||
this.eventBus = options.eventBus || null;
|
||||
this.textContent = null;
|
||||
|
@ -44,7 +12,6 @@ PDFJS.Reader.TextLayerController = function (options) {
|
|||
this.matches = [];
|
||||
this.viewport = options.viewport;
|
||||
this.textDivs = [];
|
||||
this.findController = options.findController || null;
|
||||
this.textLayerRenderTask = null;
|
||||
this.enhanceTextSelection = options.enhanceTextSelection;
|
||||
this._bindMouse();
|
||||
|
@ -117,13 +84,14 @@ PDFJS.Reader.TextLayerController.prototype.setTextContent = function (textConten
|
|||
|
||||
PDFJS.Reader.TextLayerController.prototype.convertMatches = function(matches, matchesLength) {
|
||||
|
||||
var reader = this;
|
||||
var reader = this.reader;
|
||||
|
||||
var i = 0;
|
||||
var iIndex = 0;
|
||||
var bidiTexts = this.textContent.items;
|
||||
var end = bidiTexts.length - 1;
|
||||
var queryLen = reader.search.query.length;
|
||||
var queryLen = reader.search_state ?
|
||||
reader.search_state.query.length : null;
|
||||
var ret = [];
|
||||
if (!matches) {
|
||||
return ret;
|
||||
|
@ -179,18 +147,15 @@ PDFJS.Reader.TextLayerController.prototype.renderMatches = function (matches) {
|
|||
return;
|
||||
}
|
||||
|
||||
var reader = this;
|
||||
var reader = this.reader;
|
||||
|
||||
var bidiTexts = this.textContent.items;
|
||||
var textDivs = this.textDivs;
|
||||
var prevEnd = null;
|
||||
var pageIdx = this.pageIdx;
|
||||
var isSelectedPage = (this.findController === null ?
|
||||
false : (pageIdx === this.findController.selected.pageIdx));
|
||||
var selectedMatchIdx = (this.findController === null ?
|
||||
-1 : this.findController.selected.matchIdx);
|
||||
var highlightAll = (this.findController === null ?
|
||||
false : this.findController.state.highlightAll);
|
||||
var isSelectedPage = (pageIdx === reader.selected.pageIdx);
|
||||
var selectedMatchIdx = reader.selected.matchIdx;
|
||||
var highlightAll = true;
|
||||
var infinity = {
|
||||
divIdx: -1,
|
||||
offset: undefined
|
||||
|
@ -230,12 +195,8 @@ PDFJS.Reader.TextLayerController.prototype.renderMatches = function (matches) {
|
|||
var begin = match.begin;
|
||||
var end = match.end;
|
||||
var isSelected = (isSelectedPage && i === selectedMatchIdx);
|
||||
var highlightSuffix = (isSelected ? ' selected' : '');
|
||||
|
||||
if (this.findController) {
|
||||
this.findController.updateMatchPosition(pageIdx, i, textDivs,
|
||||
begin.divIdx);
|
||||
}
|
||||
var id = "match:" + pageIdx + ":" + i;
|
||||
var highlightSuffix = (isSelected ? ' selected ' + id : ' ' + id);
|
||||
|
||||
// Match inside new div.
|
||||
if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
|
||||
|
@ -274,6 +235,13 @@ PDFJS.Reader.TextLayerController.prototype.updateMatches = function () {
|
|||
return;
|
||||
}
|
||||
|
||||
var reader = this.reader;
|
||||
|
||||
// Only show matches when search is active
|
||||
if (reader.search_active !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear all matches.
|
||||
var matches = this.matches;
|
||||
var textDivs = this.textDivs;
|
||||
|
@ -292,18 +260,12 @@ PDFJS.Reader.TextLayerController.prototype.updateMatches = function () {
|
|||
clearedUntilDivIdx = match.end.divIdx + 1;
|
||||
}
|
||||
|
||||
if (this.findController === null || !this.findController.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert the matches on the page controller into the match format
|
||||
// used for the textLayer.
|
||||
var pageMatches, pageMatchesLength;
|
||||
if (this.findController !== null) {
|
||||
pageMatches = this.findController.pageMatches[this.pageIdx] || null;
|
||||
pageMatchesLength = (this.findController.pageMatchesLength) ?
|
||||
this.findController.pageMatchesLength[this.pageIdx] || null : null;
|
||||
}
|
||||
var pageMatches = reader.pageMatches[this.pageIdx] || null,
|
||||
pageMatchesLength = reader.pageMatchesLength ?
|
||||
reader.pageMatchesLength[this.pageIdx] || null : null;
|
||||
|
||||
|
||||
this.matches = this.convertMatches(pageMatches, pageMatchesLength);
|
||||
this.renderMatches(this.matches);
|
||||
|
|
|
@ -120,7 +120,7 @@ PDFJS.reader.TocController = function() {
|
|||
scale = parseFloat(settings.thumbnailWidth / width);
|
||||
preloadcount = parseInt(window.innerHeight / placeholder_height) + 2;
|
||||
if (preloadcount > settings.numPages)
|
||||
preloadcount = numPages;
|
||||
preloadcount = settings.numPages;
|
||||
|
||||
var _timeout = setTimeout(function () {
|
||||
for (var i = 1; i <= preloadcount; i++) {
|
||||
|
|
9
files_reader/vendor/pdfjs/css/main.css
vendored
9
files_reader/vendor/pdfjs/css/main.css
vendored
|
@ -125,6 +125,15 @@ body {
|
|||
left: 0;
|
||||
}
|
||||
|
||||
#status_message_left {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
#status_message_right,
|
||||
#match_count {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
#metainfo {
|
||||
position: fixed;
|
||||
/* width: 80%;
|
||||
|
|
18
files_reader/vendor/pdfjs/css/sidebar.css
vendored
18
files_reader/vendor/pdfjs/css/sidebar.css
vendored
|
@ -122,6 +122,10 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
.list_item.selected a {
|
||||
color: #D2D2D2;
|
||||
}
|
||||
|
||||
legend {
|
||||
margin-left: 1em;
|
||||
padding: 0.5em;
|
||||
|
@ -329,6 +333,20 @@ legend {
|
|||
font-decoration: underline;
|
||||
}
|
||||
|
||||
.search_page_header {
|
||||
text-align: right;
|
||||
color: #DDD;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.match_label {
|
||||
background-color: #DDD;
|
||||
color: black;
|
||||
box-shadow: 1px 1px 10px rgba(0,0,0,0.5);
|
||||
border-radius: 3px;
|
||||
padding: 0.2em;
|
||||
}
|
||||
|
||||
.searchbox {
|
||||
width: 80%;
|
||||
float: left;
|
||||
|
|
62
files_reader/vendor/pdfjs/pdf.reader.js
vendored
62
files_reader/vendor/pdfjs/pdf.reader.js
vendored
|
@ -37,6 +37,7 @@ PDFJS.Reader = function(bookPath, _options) {
|
|||
bookPath: bookPath,
|
||||
textRenderDelay: TEXT_RENDER_DELAY,
|
||||
pageRenderDelay: PAGE_RENDER_DELAY,
|
||||
preloadTextcontent: true, // true || false, preload text content to speed up first full-text search operation
|
||||
canvasLimit: 0,
|
||||
cssZoomOnly: false, // true || false, only zoom using CSS, render document at 100% size
|
||||
textSelect: true, // true || false, add selectable text layer
|
||||
|
@ -70,9 +71,13 @@ PDFJS.Reader = function(bookPath, _options) {
|
|||
83: 'toggleSidebar',// s
|
||||
84: 'toggleTitlebar', // t
|
||||
68: 'toggleDay', // d
|
||||
78: 'toggleNight', // n
|
||||
//78: 'toggleNight', // n
|
||||
55: 'search', // '/'
|
||||
80: 'previousMatch', // p
|
||||
78: 'nextMatch', // n
|
||||
70: 'toggleFullscreen', // f
|
||||
27: 'closeSidebar' // esc
|
||||
27: 'closeSidebar', // esc
|
||||
114: 'nextMatch' // F3
|
||||
},
|
||||
nightMode: false,
|
||||
dayMode: false,
|
||||
|
@ -129,8 +134,17 @@ PDFJS.Reader = function(bookPath, _options) {
|
|||
|
||||
this.renderQueue = false;
|
||||
|
||||
// used for search
|
||||
// used for search, textlayer, hightlight etc
|
||||
this.pageContents = [];
|
||||
this.pageMatches = [];
|
||||
this.pageMatchesLength = null;
|
||||
this.search_state = null;
|
||||
this.selected = {
|
||||
pageIdx: -1,
|
||||
matchIdx: -1,
|
||||
at_start: false,
|
||||
at_end: false
|
||||
};
|
||||
|
||||
// define which zoom states to cycle through in cycleZoom
|
||||
this.zoomCycle = {
|
||||
|
@ -184,7 +198,7 @@ PDFJS.Reader = function(bookPath, _options) {
|
|||
|
||||
function(_book) {
|
||||
reader.book = book = _book;
|
||||
console.log(book);
|
||||
//console.log(book);
|
||||
reader.settings.numPages = reader.book.numPages;
|
||||
document.getElementById('total_pages').textContent = reader.settings.numPages;
|
||||
if(!$.isEmptyObject(reader.settings.session.cursor)) {
|
||||
|
@ -439,6 +453,8 @@ PDFJS.Reader.prototype.renderPage = function(pageNum) {
|
|||
reader.resourcelst[1].canvas.style.display = "none";
|
||||
// clear text layer
|
||||
reader.resourcelst[1].textdiv.innerHTML = "";
|
||||
// clear page number
|
||||
reader.resourcelst[1].pageNum = null;
|
||||
|
||||
// don't try to render non-existing page 0 (which is used
|
||||
// to indicate the empty left page when oddPageRight === true)
|
||||
|
@ -480,7 +496,6 @@ PDFJS.Reader.prototype.renderPage = function(pageNum) {
|
|||
//console.log(page);
|
||||
page_rotation = page.rotate;
|
||||
rotation = (page_rotation + reader.settings.rotation) % 360;
|
||||
//initial_viewport = page.getViewport({scale: 1, rotation: rotation});
|
||||
initial_viewport = page.getViewport(1, rotation);
|
||||
page_width = initial_viewport.width;
|
||||
page_height = initial_viewport.height;
|
||||
|
@ -491,21 +506,6 @@ PDFJS.Reader.prototype.renderPage = function(pageNum) {
|
|||
scale_height = parseFloat(max_view_height / page_height);
|
||||
scale_width = parseFloat(max_view_width / page_width);
|
||||
|
||||
/*
|
||||
console.log("m_v_w: " + max_view_width
|
||||
+ " m_v_h: " + max_view_height
|
||||
+ " p_w: " + page_width
|
||||
+ " p_h: " + page_height
|
||||
+ " d_a: " + document_aspect
|
||||
+ " v_a: " + view_aspect
|
||||
+ " s_w: " + scale_width
|
||||
+ " s_h: " + scale_height
|
||||
+ " p_r: " + page_rotation
|
||||
+ " r: " + rotation
|
||||
+ " o: " + outputscale);
|
||||
console.log("fraction: ", fraction);
|
||||
*/
|
||||
|
||||
switch (reader.settings.zoomLevel) {
|
||||
|
||||
case "spread":
|
||||
|
@ -604,10 +604,10 @@ PDFJS.Reader.prototype.renderPage = function(pageNum) {
|
|||
page.getTextContent({ normalizeWhitespace: true }).then(function (textContent) {
|
||||
resourcelst.textLayer = textLayer = new PDFJS.Reader.TextLayerController({
|
||||
textLayerDiv: textdiv,
|
||||
pageIdx: pageNum - 1,
|
||||
pageIndex: pageNum - 1,
|
||||
viewport: viewport,
|
||||
enhanceTextSelection: true
|
||||
});
|
||||
}, reader);
|
||||
textLayer.setTextContent(textContent);
|
||||
});
|
||||
} else {
|
||||
|
@ -661,6 +661,8 @@ PDFJS.Reader.prototype.renderPage = function(pageNum) {
|
|||
canvas.style.width = reader.roundToDivide(max_view_width, fraction[1]) + 'px';
|
||||
canvas.style.height = reader.roundToDivide(max_view_height, fraction[1]) + 'px';
|
||||
}
|
||||
// reset pageNum
|
||||
resourcelst.pageNum = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1065,3 +1067,19 @@ PDFJS.Reader.prototype.ellipsize = function(str, max, opts) {
|
|||
return str;
|
||||
};
|
||||
|
||||
PDFJS.Reader.prototype.isVisible = function (element) {
|
||||
|
||||
var reader = this,
|
||||
viewport = element.getBoundingClientRect(),
|
||||
visible;
|
||||
|
||||
visible = (
|
||||
viewport.top >= 0
|
||||
&& viewport.left >= 0
|
||||
&& viewport.right < window.innerWidth
|
||||
&& viewport.bottom < window.innerHeight
|
||||
);
|
||||
|
||||
return visible;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue