- Migrated from https://github.com/Yetangitu/owncloud-apps
- substantial bit rot accrued in 4 years of non-maintenance which made Reader unusable - Reader now works reliably on public pages - or at least it _Works For Me™_ - Refactored a substantial part of the code to comply to the "current" (ha ha) Nextcloud API - Dropped Owncloud compatibility for lack of a testing installation - Dropped IE (<11) support - Dropped compatibility with older (<20) Nextcloud versions - Dropped app-specific ajax code, now handled by SettingsController - Updated dependencies where applicable
This commit is contained in:
parent
16afbe45fe
commit
b190e180ef
137 changed files with 30984 additions and 2 deletions
59
vendor/pdfjs/controllers/annotationlayer_controller.js
vendored
Normal file
59
vendor/pdfjs/controllers/annotationlayer_controller.js
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
PDFJS.Reader.AnnotationLayerController = function (options, reader) {
|
||||
|
||||
this.reader = reader;
|
||||
this.annotationDiv = options.annotationDiv;
|
||||
this.pdfPage = options.pdfPage;
|
||||
this.renderInteractiveForms = options.renderInteractiveForms;
|
||||
this.linkService = options.linkService;
|
||||
this.downloadManager = options.downloadManager;
|
||||
|
||||
this.div = null;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PDFJS.Reader.AnnotationLayerController.prototype.render = function (viewport, intent) {
|
||||
var self = this;
|
||||
var parameters = {
|
||||
intent: (intent === undefined ? 'display' : intent),
|
||||
};
|
||||
|
||||
this.pdfPage.getAnnotations(parameters).then(function (annotations) {
|
||||
viewport = viewport.clone({ dontFlip: true });
|
||||
parameters = {
|
||||
viewport: viewport,
|
||||
div: self.div,
|
||||
annotations: annotations,
|
||||
page: self.pdfPage,
|
||||
renderInteractiveForms: self.renderInteractiveForms,
|
||||
linkService: self.linkService,
|
||||
downloadManager: self.downloadManager,
|
||||
};
|
||||
|
||||
if (self.div) {
|
||||
// If an annotationLayer already exists, refresh its children's
|
||||
// transformation matrices.
|
||||
PDFJS.AnnotationLayer.update(parameters);
|
||||
} else {
|
||||
// Create an annotation layer div and render the annotations
|
||||
// if there is at least one annotation.
|
||||
if (annotations.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.div = self.annotationDiv;
|
||||
parameters.div = self.div;
|
||||
|
||||
PDFJS.AnnotationLayer.render(parameters);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PDFJS.Reader.AnnotationLayerController.prototype.hide = function () {
|
||||
|
||||
if (!this.div) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.div.setAttribute('hidden', 'true');
|
||||
};
|
72
vendor/pdfjs/controllers/bookmarks_controller.js
vendored
Normal file
72
vendor/pdfjs/controllers/bookmarks_controller.js
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
PDFJS.reader.BookmarksController = function() {
|
||||
|
||||
var reader = this,
|
||||
eventBus = this.eventBus,
|
||||
book = this.book,
|
||||
annotations = reader.settings.annotations;
|
||||
|
||||
var $bookmarks = $("#bookmarksView"),
|
||||
$list = $bookmarks.find("#bookmarks"),
|
||||
$bookmark = $("#bookmark");
|
||||
|
||||
var show = function() {
|
||||
$bookmarks.addClass('open');
|
||||
};
|
||||
|
||||
var hide = function() {
|
||||
$bookmarks.removeClass('open');
|
||||
};
|
||||
|
||||
var addBookmarkItem = function (bookmark) {
|
||||
$list.append(reader.NotesController.createItem(bookmark));
|
||||
//reader.settings.session.setBookmark(bookmark.id, bookmark.anchor, bookmark.type, bookmark);
|
||||
};
|
||||
|
||||
eventBus.on('bookmarkcreated', function createBookmark1(e) {
|
||||
var id = e.id,
|
||||
$item = $("#"+id);
|
||||
|
||||
addBookmarkItem(reader.getAnnotation(id));
|
||||
|
||||
if (id === reader.pageToId(reader.settings.currentPage))
|
||||
$bookmark
|
||||
.addClass("icon-turned_in")
|
||||
.removeClass("icon-turned_in_not");
|
||||
});
|
||||
|
||||
eventBus.on('bookmarkremoved', function removeBookmark1(e) {
|
||||
var id = e.id,
|
||||
$item = $("#"+id);
|
||||
|
||||
console.log($item);
|
||||
|
||||
console.log("event bookmarkremoved caught:",e,id);
|
||||
|
||||
if (reader.isBookmarked(id)) {
|
||||
//delete reader.settings.annotations[id];
|
||||
//reader.settings.session.deleteBookmark(id);
|
||||
console.log("removing bookmark ", $item, reader.pageToId(reader.settings.currentPage), id);
|
||||
|
||||
$item.remove();
|
||||
$item.remove();
|
||||
$item.remove();
|
||||
$item.remove();
|
||||
|
||||
if (id === reader.pageToId(reader.settings.currentPage))
|
||||
$bookmark
|
||||
.removeClass("icon-turned_in")
|
||||
.addClass("icon-turned_in_not");
|
||||
}
|
||||
});
|
||||
|
||||
for (var bookmark in annotations) {
|
||||
if (annotations.hasOwnProperty(bookmark) && (annotations[bookmark].type === "bookmark"))
|
||||
addBookmarkItem(annotations[bookmark]);
|
||||
};
|
||||
|
||||
return {
|
||||
"show" : show,
|
||||
"hide" : hide,
|
||||
"addItem" : addBookmarkItem,
|
||||
};
|
||||
};
|
344
vendor/pdfjs/controllers/controls_controller.js
vendored
Normal file
344
vendor/pdfjs/controllers/controls_controller.js
vendored
Normal file
|
@ -0,0 +1,344 @@
|
|||
PDFJS.reader.ControlsController = function(book) {
|
||||
var reader = this,
|
||||
eventBus = this.eventBus,
|
||||
settings = reader.settings,
|
||||
customStyles = reader.settings.customStyles,
|
||||
activeStyles = reader.settings.activeStyles;
|
||||
|
||||
var $store = $("#store"),
|
||||
$viewer = $("#viewer"),
|
||||
$fullscreen = $("#fullscreen"),
|
||||
$fullscreenicon = $("#fullscreenicon"),
|
||||
$cancelfullscreenicon = $("#cancelfullscreenicon"),
|
||||
$slider = $("#slider"),
|
||||
$main = $("#main"),
|
||||
$sidebar = $("#sidebar"),
|
||||
$titlebar = $("#titlebar"),
|
||||
$settings = $("#setting"),
|
||||
$bookmark = $("#bookmark"),
|
||||
$note = $("#note"),
|
||||
$togglelayout = $("#toggle-layout"),
|
||||
$zoom_icon = $("#zoom_icon"),
|
||||
$zoom_options = $("#zoom_options"),
|
||||
$zoom_option = $(".zoom_option"),
|
||||
$rotate_icon = $("#rotate_icon"),
|
||||
$rotate_options = $("#rotate_options"),
|
||||
$rotate_option = $(".rotate_option"),
|
||||
$rotate_left = $("#rotate_left"),
|
||||
$rotate_right = $("#rotate_right"),
|
||||
$page_num = $("#page_num"),
|
||||
$total_pages = $("#total_pages"),
|
||||
$status_message_left = $("#status_message_left"),
|
||||
$status_message_right = $("#status_message_right"),
|
||||
$nightmode = $("#nightmode"),
|
||||
$nightshift = $(".nightshift");
|
||||
|
||||
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");
|
||||
};
|
||||
|
||||
var hide = function () {
|
||||
$titlebar.addClass("hide");
|
||||
};
|
||||
|
||||
var toggle = function () {
|
||||
$titlebar.toggleClass("hide");
|
||||
};
|
||||
|
||||
$viewer.on("touchstart", function(e) {
|
||||
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 () {
|
||||
if(reader.sidebarOpen) {
|
||||
reader.SidebarController.hide();
|
||||
} else {
|
||||
reader.SidebarController.show();
|
||||
}
|
||||
});
|
||||
|
||||
if(typeof screenfull !== 'undefined') {
|
||||
$fullscreen.on("click", function() {
|
||||
screenfull.toggle($('#container')[0]);
|
||||
});
|
||||
if(screenfull.raw) {
|
||||
document.addEventListener(screenfull.raw.fullscreenchange, function() {
|
||||
fullscreen = screenfull.isFullscreen;
|
||||
if(fullscreen) {
|
||||
$fullscreen
|
||||
.addClass("icon-fullscreen_exit")
|
||||
.removeClass("icon-fullscreen");
|
||||
} else {
|
||||
$fullscreen
|
||||
.addClass("icon-fullscreen")
|
||||
.removeClass("icon-fullscreen_exit");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$settings.on("click", function() {
|
||||
reader.SettingsController.show();
|
||||
});
|
||||
|
||||
$note.on("click", function() {
|
||||
reader.SidebarController.changePanelTo("Notes");
|
||||
});
|
||||
|
||||
$bookmark.on("click", function() {
|
||||
var currentPage = reader.settings.currentPage,
|
||||
id = reader.pageToId(currentPage);
|
||||
|
||||
if (!reader.isBookmarked(id))
|
||||
reader.addBookmark(currentPage)
|
||||
else
|
||||
reader.removeBookmark(currentPage);
|
||||
});
|
||||
|
||||
/* select works fine on most browsers, but - of course - apple mobile has 'special needs' so
|
||||
* a custom select is needed...
|
||||
*/
|
||||
|
||||
/* custom select, supports icons in drop-down list */
|
||||
// zooooooooooooooom
|
||||
$zoom_icon.on("click", function () {
|
||||
var offset = $(this).offset();
|
||||
$zoom_options.css("opacity", 0);
|
||||
$zoom_options.toggleClass("hide");
|
||||
$zoom_options.css({
|
||||
'left': parseInt(offset.left - ($zoom_options.width() / 2)) + "px",
|
||||
'top' : parseInt(parseInt(offset.top) + parseInt($zoom_icon.height())) + "px"
|
||||
});
|
||||
|
||||
$zoom_options.css("opacity", "");
|
||||
});
|
||||
|
||||
var setZoomIcon = function(zoom) {
|
||||
$zoom_icon[0].className="";
|
||||
var $current_zoom_option = $zoom_options.find("[data-value='" + zoom + "']");
|
||||
if ($current_zoom_option.data("class")) {
|
||||
$zoom_icon.addClass($current_zoom_option.data("class"));
|
||||
} else {
|
||||
$zoom_icon[0].textContent = $current_zoom_option.data("text");
|
||||
}
|
||||
};
|
||||
|
||||
setZoomIcon(settings.zoomLevel);
|
||||
|
||||
$zoom_option.on("click", function () {
|
||||
var $this = $(this);
|
||||
reader.setZoom($this.data("value"));
|
||||
$zoom_icon[0].className="";
|
||||
$zoom_icon[0].textContent = "";
|
||||
if ($this.data("class")) {
|
||||
$zoom_icon.addClass($this.data("class"));
|
||||
} else {
|
||||
$zoom_icon[0].textContent = $this.data("text");
|
||||
}
|
||||
$zoom_options.addClass("hide");
|
||||
});
|
||||
|
||||
// rotate
|
||||
var setRotateIcon = function (rotation) {
|
||||
$rotate_icon[0].className = "";
|
||||
$rotate_icon[0].className = "icon-rotate_" + rotation;
|
||||
};
|
||||
|
||||
setRotateIcon(settings.rotation);
|
||||
|
||||
$rotate_icon.on("click", function () {
|
||||
var offset = $(this).offset();
|
||||
$rotate_options.css("opacity", 0);
|
||||
$rotate_options.toggleClass("hide");
|
||||
$rotate_options.css({
|
||||
'left': parseInt(offset.left - ($rotate_options.width() / 2)) + "px",
|
||||
'top' : parseInt(parseInt(offset.top) + parseInt($rotate_icon.height())) + "px"
|
||||
});
|
||||
|
||||
$rotate_options.css("opacity", "");
|
||||
});
|
||||
|
||||
$rotate_option.on("click", function () {
|
||||
var $this = $(this);
|
||||
reader.setRotation($this.data("value"));
|
||||
$rotate_icon[0].className="";
|
||||
$rotate_icon[0].textContent = "";
|
||||
if ($this.data("class")) {
|
||||
$rotate_icon.addClass($this.data("class"));
|
||||
} else {
|
||||
$rotate_icon[0].textContent = $this.data("text");
|
||||
}
|
||||
$rotate_options.addClass("hide");
|
||||
});
|
||||
|
||||
$rotate_left.on("click", function () {
|
||||
// add 360 to avoid negative rotation value
|
||||
var rotation = (settings.rotation - 90 + 360) % 360;
|
||||
reader.setRotation(rotation);
|
||||
$rotate_icon[0].className = "";
|
||||
$rotate_icon[0].className = "icon-rotate_" + rotation;
|
||||
});
|
||||
|
||||
$rotate_right.on("click", function () {
|
||||
var rotation = (settings.rotation + 90) % 360;
|
||||
reader.setRotation(rotation);
|
||||
$rotate_icon[0].className = "";
|
||||
$rotate_icon[0].className = "icon-rotate_" + rotation;
|
||||
});
|
||||
/* end custom select */
|
||||
|
||||
var setNightmodeIcon = function (mode) {
|
||||
if (mode)
|
||||
$nightmode.removeClass("icon-brightness_low2").addClass("icon-brightness_4");
|
||||
else
|
||||
$nightmode.removeClass("icon-brightness_4").addClass("icon-brightness_low2");
|
||||
};
|
||||
|
||||
$nightshift.off('click').on('click', function () {
|
||||
if (settings.nightMode) {
|
||||
reader.disableStyle(customStyles.nightMode);
|
||||
settings.nightMode = false;
|
||||
} else {
|
||||
reader.enableStyle(customStyles.nightMode);
|
||||
settings.nightMode = true;
|
||||
}
|
||||
|
||||
setNightmodeIcon(settings.nightMode);
|
||||
});
|
||||
|
||||
var enterPageNum = function(e) {
|
||||
var text = e.target,
|
||||
page;
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 27: // escape - cancel, discard changes
|
||||
$page_num[0].removeEventListener("keydown", enterPageNum, false);
|
||||
$page_num.removeClass("editable");
|
||||
$page_num.prop("contenteditable",false);
|
||||
$page_num.text($page_num.data("content"));
|
||||
break;
|
||||
case 13: // enter - accept changes
|
||||
$page_num[0].removeEventListener("keydown", enterPageNum, false);
|
||||
$page_num.removeClass("editable");
|
||||
$page_num.attr("contenteditable", false);
|
||||
page = parseInt($page_num.text());
|
||||
if (page > 0 && page <= reader.settings.numPages) {
|
||||
reader.queuePage(page);
|
||||
} else {
|
||||
$page_num.text($page_num.data("content"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
|
||||
$page_num.on("click", function() {
|
||||
$page_num.data("content", $page_num.text());
|
||||
$page_num.text("");
|
||||
$page_num.prop("contenteditable", true);
|
||||
$page_num.addClass("editable");
|
||||
$page_num[0].addEventListener("keydown", enterPageNum, false);
|
||||
});
|
||||
|
||||
eventBus.on("renderer:pagechanged", function toggleControls1(e) {
|
||||
var page = e.pageNum,
|
||||
id = reader.pageToId(page);
|
||||
|
||||
if (reader.isBookmarked(id))
|
||||
$bookmark
|
||||
.addClass("icon-turned_in")
|
||||
.removeClass("icon-turned_in_not");
|
||||
else
|
||||
$bookmark
|
||||
.removeClass("icon-turned_in")
|
||||
.addClass("icon-turned_in_not");
|
||||
});
|
||||
|
||||
var setPageCount = function (_numPages) {
|
||||
|
||||
var numPages = _numPages || reader.settings.numPages;
|
||||
|
||||
$total_pages[0].textContent = parseInt(numPages).toString();
|
||||
};
|
||||
|
||||
var setCurrentPage = function (_page) {
|
||||
|
||||
var page = _page || reader.settings.currentPage,
|
||||
zoom = reader.settings.zoomLevel,
|
||||
oddPageRight = reader.settings.oddPageRight,
|
||||
total_pages = reader.settings.numPages,
|
||||
text;
|
||||
|
||||
if (zoom === "spread") {
|
||||
if (oddPageRight === true) {
|
||||
page -= page % 2;
|
||||
} else {
|
||||
page -= (page + 1) % 2;
|
||||
}
|
||||
|
||||
if (page >= 0 && page <= total_pages) {
|
||||
if (page === total_pages) {
|
||||
text = reader.getPageLabel(page);
|
||||
} else if (page === 0) {
|
||||
text = reader.getPageLabel(page + 1);
|
||||
} else {
|
||||
text = reader.getPageLabel(page) + "-" + reader.getPageLabel(page + 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
text = reader.getPageLabel(page);
|
||||
}
|
||||
|
||||
$page_num[0].textContent = text;
|
||||
};
|
||||
|
||||
return {
|
||||
"show": show,
|
||||
"hide": hide,
|
||||
"toggle": toggle,
|
||||
"setZoomIcon": setZoomIcon,
|
||||
"setRotateIcon": setRotateIcon,
|
||||
"setNightmodeIcon": setNightmodeIcon,
|
||||
"setCurrentPage": setCurrentPage,
|
||||
"setPageCount": setPageCount,
|
||||
"setStatus": setStatus
|
||||
};
|
||||
};
|
14
vendor/pdfjs/controllers/meta_controller.js
vendored
Normal file
14
vendor/pdfjs/controllers/meta_controller.js
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
PDFJS.reader.MetaController = function(meta) {
|
||||
var title = meta.bookTitle,
|
||||
author = meta.creator;
|
||||
|
||||
var $title = $("#book-title"),
|
||||
$author = $("#chapter-title"),
|
||||
$dash = $("#title-seperator");
|
||||
|
||||
document.title = title+" – "+author;
|
||||
|
||||
$title.html(title);
|
||||
$author.html(author);
|
||||
$dash.show();
|
||||
};
|
427
vendor/pdfjs/controllers/notes_controller.js
vendored
Normal file
427
vendor/pdfjs/controllers/notes_controller.js
vendored
Normal file
|
@ -0,0 +1,427 @@
|
|||
PDFJS.reader.NotesController = function(book) {
|
||||
|
||||
var book = this.book,
|
||||
reader = this,
|
||||
eventBus = this.eventBus,
|
||||
$notesView = $("#notesView"),
|
||||
$notes = $("#notes"),
|
||||
$text = $("#note-text"),
|
||||
$anchor = $("#note-anchor"),
|
||||
$next = $("#next"),
|
||||
$prev = $("#prev"),
|
||||
$touch_nav = $("#touch_nav"),
|
||||
$viewer = $("#viewer"),
|
||||
annotations = reader.settings.annotations,
|
||||
renderer = book.renderer,
|
||||
popups = [];
|
||||
|
||||
var show = function() {
|
||||
$notesView.addClass('open');
|
||||
$text.focus();
|
||||
};
|
||||
|
||||
var hide = function() {
|
||||
$notesView.removeClass('open');
|
||||
};
|
||||
|
||||
$text.on("keydown", function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
var insertAtPoint = function(e) {
|
||||
var range,
|
||||
textNode,
|
||||
offset,
|
||||
doc = document,
|
||||
loc,
|
||||
annotation;
|
||||
|
||||
// standard
|
||||
if (doc.caretPositionFromPoint) {
|
||||
range = doc.caretPositionFromPoint(e.clientX, e.clientY);
|
||||
textNode = range.offsetNode;
|
||||
offset = range.offset;
|
||||
// WebKit
|
||||
} else if (doc.caretRangeFromPoint) {
|
||||
range = doc.caretRangeFromPoint(e.clientX, e.clientY);
|
||||
textNode = range.startContainer;
|
||||
offset = range.startOffset;
|
||||
}
|
||||
|
||||
console.log("textNode", textNode, "offset", offset);
|
||||
console.log(e);
|
||||
|
||||
if (textNode.nodeType !== 3) {
|
||||
for (var i=0; i < textNode.childNodes.length; i++) {
|
||||
if (textNode.childNodes[i].nodeType == 3) {
|
||||
textNode = textNode.childNodes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the end of the sentence
|
||||
offset = textNode.textContent.indexOf(".", offset);
|
||||
if(offset === -1){
|
||||
offset = textNode.length; // Last item
|
||||
} else {
|
||||
offset += 1; // After the period
|
||||
}
|
||||
|
||||
loc = "";
|
||||
|
||||
annotation = new reader.Annotation('annotation', loc, $text.val());
|
||||
|
||||
// save...
|
||||
reader.addAnnotation(annotation);
|
||||
|
||||
// show...
|
||||
addAnnotationItem(annotation);
|
||||
// add marker...
|
||||
placeMarker(annotation);
|
||||
|
||||
// clear entry
|
||||
$text.val('');
|
||||
$anchor.removeClass("icon-location_off");
|
||||
$anchor.addClass("icon-room");
|
||||
$text.prop("disabled", false);
|
||||
|
||||
book.off("renderer:click", insertAtPoint);
|
||||
};
|
||||
|
||||
var addAnnotationItem = function(annotation) {
|
||||
$notes.append(createItem(annotation));
|
||||
//reader.settings.session.setBookmark(annotation.id, annotation.anchor, annotation.type, annotation);
|
||||
};
|
||||
|
||||
var removeAnnotation = function (id) {
|
||||
|
||||
if (annotations[id] !== undefined) {
|
||||
if (annotations[id].type == "bookmark")
|
||||
eventBus.dispatch("bookmarkremoved", {
|
||||
source: this,
|
||||
id: id
|
||||
});
|
||||
deleteAnnotationItem(id);
|
||||
delete annotations[id];
|
||||
reader.settings.session.deleteBookmark(id);
|
||||
}
|
||||
};
|
||||
|
||||
var deleteAnnotationItem = function (id) {
|
||||
var item = document.getElementById(id);
|
||||
|
||||
if (item)
|
||||
item.remove();
|
||||
};
|
||||
|
||||
/* items are HTML-representations of annotations */
|
||||
var createItem = function(annotation){
|
||||
var item = document.createElement("li");
|
||||
var text = document.createElement("div");
|
||||
var date = document.createElement("div");
|
||||
var edit = document.createElement("span");
|
||||
var del = document.createElement("span");
|
||||
var link = document.createElement("a");
|
||||
var div = document.createElement("div");
|
||||
var save = document.createElement("span");
|
||||
var cancel = document.createElement("span");
|
||||
|
||||
text.textContent = annotation.body;
|
||||
date.textContent = new Date(annotation.edited).toUTCString();
|
||||
item.classList.add("note");
|
||||
del.classList.add("item-delete", "item-control", "icon-delete");
|
||||
edit.classList.add("item-edit", "item-control", "icon-rate_review");
|
||||
link.classList.add("note-link");
|
||||
//link.classList.add("note-link", "icon-link2");
|
||||
date.classList.add("item-date");
|
||||
del.setAttribute("title", "delete");
|
||||
edit.setAttribute("title", "edit");
|
||||
link.setAttribute("title", "context");
|
||||
item.setAttribute("id", annotation.id);
|
||||
save.classList.add("item-save", "edit-control", "hide", "icon-check");
|
||||
cancel.classList.add("item-cancel", "edit-control", "hide", "icon-close");
|
||||
save.setAttribute("display", "none");
|
||||
cancel.setAttribute("display", "none");
|
||||
|
||||
link.href = "#"+annotation.anchor;
|
||||
link.textContent = "Page " + annotation.anchor;
|
||||
|
||||
link.onclick = function(){
|
||||
reader.queuePage(annotation.anchor);
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
if (!annotation.readonly) {
|
||||
del.onclick = function() {
|
||||
var id = this.parentNode.parentNode.getAttribute("id");
|
||||
deleteAnnotationItem(id);
|
||||
reader.removeAnnotation(id);
|
||||
};
|
||||
|
||||
save.onclick = function() {
|
||||
var id = this.parentNode.parentNode.getAttribute("id");
|
||||
var annotation = annotations[id];
|
||||
var text = this.parentNode.parentNode.firstChild;
|
||||
try {
|
||||
annotation.body = text.textContent;
|
||||
reader.updateAnnotation(annotation);
|
||||
} catch (e) {
|
||||
console.log("Updating annotation failed: " + e);
|
||||
}
|
||||
closeEditor(id);
|
||||
};
|
||||
|
||||
cancel.onclick = function () {
|
||||
var id = this.parentNode.parentNode.getAttribute("id");
|
||||
var text = this.parentNode.parentNode.firstChild;
|
||||
text.textContent = annotations[id].body;
|
||||
closeEditor(id);
|
||||
};
|
||||
|
||||
edit.onclick = function() {
|
||||
openEditor(this.parentNode.parentNode.getAttribute("id"));
|
||||
};
|
||||
|
||||
div.appendChild(cancel);
|
||||
div.appendChild(save);
|
||||
div.appendChild(del);
|
||||
div.appendChild(edit);
|
||||
}
|
||||
|
||||
div.appendChild(link);
|
||||
item.appendChild(text);
|
||||
if (!annotation.readonly)
|
||||
item.appendChild(date);
|
||||
item.appendChild(div);
|
||||
return item;
|
||||
};
|
||||
|
||||
var editAnnotation = function (e) {
|
||||
var text = e.target;
|
||||
var id = text.parentNode.getAttribute("id");
|
||||
if (e.keyCode === 27) { // escape - cancel editor, discard changes
|
||||
text.textContent = annotations[id].body;
|
||||
closeEditor(id);
|
||||
}
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
var openEditor = function(id) {
|
||||
var item = document.getElementById(id);
|
||||
var text = item.firstChild;
|
||||
$(item).find(".item-control").toggleClass("hide");
|
||||
$(item).find(".edit-control").toggleClass("hide");
|
||||
text.setAttribute("contenteditable", "true");
|
||||
text.classList.add("editable");
|
||||
text.addEventListener("keydown", editAnnotation, false);
|
||||
};
|
||||
|
||||
var closeEditor = function (id) {
|
||||
var item = document.getElementById(id);
|
||||
var text = item.firstChild;
|
||||
$(item).find(".item-control").toggleClass("hide");
|
||||
$(item).find(".edit-control").toggleClass("hide");
|
||||
text.classList.remove("editable");
|
||||
text.removeAttribute("contenteditable");
|
||||
text.removeEventListener("keydown", editAnnotation, false);
|
||||
};
|
||||
|
||||
var findIndex = function (id) {
|
||||
// list has items
|
||||
var i,
|
||||
list = $notes[0].getElementsByTagName("li");
|
||||
|
||||
for (i = 0; i < list.length; i++) {
|
||||
if (list[i].getAttribute("id") === id)
|
||||
break;
|
||||
}
|
||||
|
||||
return i+1;
|
||||
};
|
||||
|
||||
var placeMarker = function(annotation){
|
||||
var doc = book.renderer.doc,
|
||||
marker = document.createElement("span"),
|
||||
mark = document.createElement("a");
|
||||
|
||||
marker.classList.add("note-marker", "footnotesuperscript", "reader_generated");
|
||||
marker.id = "note-" + annotation.id;
|
||||
mark.innerHTML = findIndex(annotation.id) + "[Reader]";
|
||||
|
||||
marker.appendChild(mark);
|
||||
// epubcfi.addMarker(annotation.anchor, doc, marker);
|
||||
|
||||
markerEvents(marker, annotation.body);
|
||||
renumberMarkers();
|
||||
}
|
||||
|
||||
var markerEvents = function(item, txt){
|
||||
var id = item.id;
|
||||
|
||||
var showPop = function(){
|
||||
var poppos,
|
||||
iheight = renderer.height,
|
||||
iwidth = renderer.width,
|
||||
tip,
|
||||
pop,
|
||||
maxHeight = 225,
|
||||
itemRect,
|
||||
left,
|
||||
top,
|
||||
pos;
|
||||
|
||||
|
||||
//-- create a popup with endnote inside of it
|
||||
if(!popups[id]) {
|
||||
popups[id] = document.createElement("div");
|
||||
popups[id].setAttribute("class", "popup");
|
||||
|
||||
pop_content = document.createElement("div");
|
||||
|
||||
popups[id].appendChild(pop_content);
|
||||
|
||||
pop_content.innerHTML = txt;
|
||||
pop_content.setAttribute("class", "pop_content");
|
||||
|
||||
renderer.render.document.body.appendChild(popups[id]);
|
||||
|
||||
//-- TODO: will these leak memory? - Fred
|
||||
popups[id].addEventListener("mouseover", onPop, false);
|
||||
popups[id].addEventListener("mouseout", offPop, false);
|
||||
|
||||
//-- Add hide on page change
|
||||
renderer.on("renderer:locationChanged", hidePop, this);
|
||||
renderer.on("renderer:locationChanged", offPop, this);
|
||||
// chapter.book.on("renderer:chapterDestroy", hidePop, this);
|
||||
}
|
||||
|
||||
pop = popups[id];
|
||||
|
||||
|
||||
//-- get location of item
|
||||
itemRect = item.getBoundingClientRect();
|
||||
left = itemRect.left;
|
||||
top = itemRect.top;
|
||||
|
||||
//-- show the popup
|
||||
pop.classList.add("show");
|
||||
|
||||
//-- locations of popup
|
||||
popRect = pop.getBoundingClientRect();
|
||||
|
||||
//-- position the popup
|
||||
pop.style.left = left - popRect.width / 2 + "px";
|
||||
pop.style.top = top + "px";
|
||||
|
||||
|
||||
//-- Adjust max height
|
||||
if(maxHeight > iheight / 2.5) {
|
||||
maxHeight = iheight / 2.5;
|
||||
pop_content.style.maxHeight = maxHeight + "px";
|
||||
}
|
||||
|
||||
//-- switch above / below
|
||||
if(popRect.height + top >= iheight - 25) {
|
||||
pop.style.top = top - popRect.height + "px";
|
||||
pop.classList.add("above");
|
||||
}else{
|
||||
pop.classList.remove("above");
|
||||
}
|
||||
|
||||
//-- switch left
|
||||
if(left - popRect.width <= 0) {
|
||||
pop.style.left = left + "px";
|
||||
pop.classList.add("left");
|
||||
}else{
|
||||
pop.classList.remove("left");
|
||||
}
|
||||
|
||||
//-- switch right
|
||||
if(left + popRect.width / 2 >= iwidth) {
|
||||
//-- TEMP MOVE: 300
|
||||
pop.style.left = left - 300 + "px";
|
||||
|
||||
popRect = pop.getBoundingClientRect();
|
||||
pop.style.left = left - popRect.width + "px";
|
||||
//-- switch above / below again
|
||||
if(popRect.height + top >= iheight - 25) {
|
||||
pop.style.top = top - popRect.height + "px";
|
||||
pop.classList.add("above");
|
||||
}else{
|
||||
pop.classList.remove("above");
|
||||
}
|
||||
|
||||
pop.classList.add("right");
|
||||
}else{
|
||||
pop.classList.remove("right");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var onPop = function(){
|
||||
popups[id].classList.add("on");
|
||||
}
|
||||
|
||||
var offPop = function(){
|
||||
popups[id].classList.remove("on");
|
||||
}
|
||||
|
||||
var hidePop = function(){
|
||||
setTimeout(function(){
|
||||
popups[id].classList.remove("show");
|
||||
}, 100);
|
||||
}
|
||||
|
||||
var openSidebar = function(){
|
||||
reader.SidebarController.changePanelTo('Notes');
|
||||
reader.SidebarController.show();
|
||||
};
|
||||
|
||||
item.addEventListener("mouseover", showPop, false);
|
||||
item.addEventListener("mouseout", hidePop, false);
|
||||
item.addEventListener("click", openSidebar, false);
|
||||
|
||||
}
|
||||
|
||||
$anchor.on("click", function(e){
|
||||
if ($anchor[0].classList.contains("icon-room")) {
|
||||
$anchor.removeClass("icon-room");
|
||||
$anchor.addClass("icon-location_off");
|
||||
$text.prop("disabled", true);
|
||||
// disable extra-wide navigation as it interferes with anchor placment
|
||||
if ($prev.hasClass("touch_nav")) {
|
||||
$prev.removeClass("touch_nav");
|
||||
$next.removeClass("touch_nav");
|
||||
$prev.addClass("restore_touch_nav");
|
||||
}
|
||||
// listen for selection
|
||||
$viewer.on("click", insertAtPoint);
|
||||
} else {
|
||||
$text.prop("disabled", false);
|
||||
$anchor.removeClass("icon-location_off");
|
||||
$anchor.addClass("icon-room");
|
||||
if ($prev.hasClass("restore_touch_nav")) {
|
||||
$prev.removeClass("restore_touch_nav");
|
||||
$prev.addClass("touch_nav");
|
||||
$next.addClass("touch_nav");
|
||||
}
|
||||
|
||||
$viewer.off("click", insertAtPoint);
|
||||
}
|
||||
});
|
||||
|
||||
for (var note in annotations) {
|
||||
if (annotations.hasOwnProperty(note) && (annotations[note].type === "annotation"))
|
||||
addAnnotationItem(annotations[note]);
|
||||
};
|
||||
|
||||
return {
|
||||
"show" : show,
|
||||
"hide" : hide,
|
||||
"createItem": createItem,
|
||||
"addItem" : addAnnotationItem,
|
||||
"removeAnnotation" : removeAnnotation
|
||||
};
|
||||
};
|
74
vendor/pdfjs/controllers/outline_controller.js
vendored
Normal file
74
vendor/pdfjs/controllers/outline_controller.js
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
PDFJS.reader.OutlineController = function(_outline) {
|
||||
|
||||
var reader = this,
|
||||
book = this.book,
|
||||
outline = _outline || [];
|
||||
|
||||
var outlineView = document.getElementById("outlineView");
|
||||
|
||||
var DEFAULT_TITLE = '\u2013';
|
||||
|
||||
var generateOutlineItems = function (outline, level) {
|
||||
|
||||
var container = document.createElement("ul");
|
||||
|
||||
if(!level) level = 1;
|
||||
|
||||
outline.forEach(function (chapter) {
|
||||
|
||||
var listitem = document.createElement("li"),
|
||||
link = document.createElement("a"),
|
||||
toggle = document.createElement("a"),
|
||||
subitems;
|
||||
|
||||
listitem.id = "outline-"+chapter.dest;
|
||||
listitem.classList.add('list_item');
|
||||
|
||||
link.textContent = PDFJS.removeNullCharacters(chapter.title) || DEFAULT_TITLE;
|
||||
reader.bindLink(link, chapter);
|
||||
reader.setStyles(link, chapter);
|
||||
link.classList.add('outline_link');
|
||||
|
||||
listitem.appendChild(link);
|
||||
|
||||
if(chapter.items.length > 0) {
|
||||
level++;
|
||||
subitems = generateOutlineItems(chapter.items, level);
|
||||
toggle.classList.add('outline_toggle');
|
||||
listitem.insertBefore(toggle, link);
|
||||
listitem.appendChild(subitems);
|
||||
}
|
||||
|
||||
container.appendChild(listitem);
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
var onShow = function() {
|
||||
outlineView.classList.add('open');
|
||||
};
|
||||
|
||||
var onHide = function() {
|
||||
outlineView.classList.remove('open');
|
||||
};
|
||||
|
||||
outlineView.appendChild(generateOutlineItems(outline));
|
||||
|
||||
$(outlineView).find(".outline_toggle").on("click", function(event){
|
||||
var $el = $(this).parent('li'),
|
||||
open = $el.hasClass("openChapter");
|
||||
|
||||
event.preventDefault();
|
||||
if(open){
|
||||
$el.removeClass("openChapter");
|
||||
} else {
|
||||
$el.addClass("openChapter");
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
"show" : onShow,
|
||||
"hide" : onHide
|
||||
};
|
||||
};
|
57
vendor/pdfjs/controllers/progress_controller.js
vendored
Normal file
57
vendor/pdfjs/controllers/progress_controller.js
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
PDFJS.reader.ProgressController = function() {
|
||||
var reader = this,
|
||||
settings = reader.settings,
|
||||
percentage = 0;
|
||||
|
||||
var $progress = $("#progress"),
|
||||
$bar = $(".bar"),
|
||||
$download_icon = $("#download_icon"),
|
||||
$message = $(".message-text");
|
||||
|
||||
var show = function () {
|
||||
$progress.removeClass("hide");
|
||||
};
|
||||
|
||||
var hide = function () {
|
||||
$progress.addClass("hide");
|
||||
};
|
||||
|
||||
var setSize = function (size) {
|
||||
settings.fileSize = size;
|
||||
};
|
||||
|
||||
var setProgress = function (progress) {
|
||||
|
||||
if (percentage < 1)
|
||||
$download_icon.addClass("active");
|
||||
|
||||
percentage = Math.floor((progress.loaded / progress.total) * 100);
|
||||
$bar.css("width", percentage + "%");
|
||||
|
||||
if (percentage === 100)
|
||||
$download_icon.removeClass("active").addClass("ok");
|
||||
};
|
||||
|
||||
var reset = function() {
|
||||
$bar.css("width", 0);
|
||||
};
|
||||
|
||||
var setMessage = function (text, category, state) {
|
||||
|
||||
var $category_icon = $("#" + category + "_icon");
|
||||
|
||||
$message.text(text);
|
||||
|
||||
$category_icon[0].classList.remove("ok", "active", "error");
|
||||
$category_icon.addClass(state);
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
"show": show,
|
||||
"hide": hide,
|
||||
"setSize": setSize,
|
||||
"setProgress": setProgress,
|
||||
"setMessage": setMessage
|
||||
};
|
||||
};
|
166
vendor/pdfjs/controllers/reader_controller.js
vendored
Normal file
166
vendor/pdfjs/controllers/reader_controller.js
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
PDFJS.reader.ReaderController = function() {
|
||||
var $main = $("#main"),
|
||||
$viewer = $("#viewer"),
|
||||
$divider = $("#divider"),
|
||||
$loader = $("#loader"),
|
||||
$next = $("#next"),
|
||||
$prev = $("#prev"),
|
||||
$sidebarReflow = $('#sidebarReflow'),
|
||||
$metainfo = $("#metainfo"),
|
||||
$use_custom_colors = $("#use_custom_colors"),
|
||||
$container = $("#container"),
|
||||
$fullscreen = $("#fullscreen"),
|
||||
$bookmark = $("#bookmark"),
|
||||
$note = $("#note"),
|
||||
$nightmode = $("#nightmode"),
|
||||
$rotate_left = $("#rotate_left"),
|
||||
$rotate_right = $("#rotate_right"),
|
||||
$clear_search = $("#clear_search");
|
||||
|
||||
var reader = this,
|
||||
book = this.book,
|
||||
settings = reader.settings;
|
||||
|
||||
var slideIn = function() {
|
||||
if (reader.viewerResized) {
|
||||
var currentPosition = settings.currentPage;
|
||||
reader.viewerResized = false;
|
||||
}
|
||||
};
|
||||
|
||||
var slideOut = function() {
|
||||
var currentPosition = settings.currentPage;
|
||||
reader.viewerResized = true;
|
||||
};
|
||||
|
||||
var showLoader = function() {
|
||||
$loader.show();
|
||||
hideDivider();
|
||||
};
|
||||
|
||||
var hideLoader = function() {
|
||||
$loader.hide();
|
||||
};
|
||||
|
||||
var showDivider = function() {
|
||||
$divider.addClass("show");
|
||||
};
|
||||
|
||||
var hideDivider = function() {
|
||||
$divider.removeClass("show");
|
||||
};
|
||||
|
||||
var keylock = false;
|
||||
|
||||
var showActive = function (obj) {
|
||||
keylock = true;
|
||||
obj.addClass("active");
|
||||
setTimeout(function () {
|
||||
keylock = false;
|
||||
obj.removeClass("active");
|
||||
}, 100);
|
||||
};
|
||||
|
||||
var keyCommands = function(e) {
|
||||
|
||||
var page_no = false;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
switch (settings.keyboard[e.keyCode]) {
|
||||
case 'previous':
|
||||
$prev.click();
|
||||
break;
|
||||
case 'next':
|
||||
$next.click();
|
||||
break;
|
||||
case 'first':
|
||||
page_no = 1;
|
||||
break;
|
||||
case 'last':
|
||||
page_no = reader.settings.numPages;
|
||||
break;
|
||||
case 'annotate':
|
||||
$note.click();
|
||||
break;
|
||||
case 'bookmark':
|
||||
$bookmark.click();
|
||||
break;
|
||||
case 'toggleTitlebar':
|
||||
reader.ControlsController.toggle();
|
||||
break;
|
||||
case 'toggleSidebar':
|
||||
reader.SidebarController.toggle();
|
||||
break;
|
||||
case 'closeSidebar':
|
||||
reader.SidebarController.hide();
|
||||
break;
|
||||
case 'toggleFullscreen':
|
||||
$fullscreen.click();
|
||||
break;
|
||||
case 'toggleNight':
|
||||
$nightmode.click();
|
||||
break;
|
||||
case 'rotateLeft':
|
||||
$rotate_left.click();
|
||||
break;
|
||||
case 'rotateRight':
|
||||
$rotate_right.click();
|
||||
break;
|
||||
case 'cycleZoom':
|
||||
reader.cycleZoom();
|
||||
break;
|
||||
case 'previousMatch':
|
||||
reader.SearchController.nextMatch(true);
|
||||
break;
|
||||
case 'nextMatch':
|
||||
if (e.shiftKey)
|
||||
reader.SearchController.nextMatch(true);
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
if (page_no) {
|
||||
reader.queuePage(page_no);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', keyCommands, false);
|
||||
|
||||
$next.on("click", function(e){
|
||||
|
||||
reader.nextPage();
|
||||
showActive($next);
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$prev.on("click", function(e){
|
||||
|
||||
reader.prevPage();
|
||||
showActive($prev);
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
return {
|
||||
"slideOut" : slideOut,
|
||||
"slideIn" : slideIn,
|
||||
"showLoader" : showLoader,
|
||||
"hideLoader" : hideLoader,
|
||||
"showDivider" : showDivider,
|
||||
"hideDivider" : hideDivider,
|
||||
"keyCommands" : keyCommands
|
||||
};
|
||||
};
|
591
vendor/pdfjs/controllers/search_controller.js
vendored
Normal file
591
vendor/pdfjs/controllers/search_controller.js
vendored
Normal file
|
@ -0,0 +1,591 @@
|
|||
PDFJS.reader.SearchController = function () {
|
||||
|
||||
var reader = this,
|
||||
book = this.book;
|
||||
|
||||
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
|
||||
'\u201B': '\'', // Single high-reversed-9 quotation mark
|
||||
'\u201C': '"', // Left double quotation mark
|
||||
'\u201D': '"', // Right double quotation mark
|
||||
'\u201E': '"', // Double low-9 quotation mark
|
||||
'\u201F': '"', // Double high-reversed-9 quotation mark
|
||||
'\u00BC': '1/4', // Vulgar fraction one quarter
|
||||
'\u00BD': '1/2', // Vulgar fraction one half
|
||||
'\u00BE': '3/4', // Vulgar fraction three quarters
|
||||
};
|
||||
|
||||
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(''),
|
||||
normalizationRegex = new RegExp('[' + replace + ']', 'g');
|
||||
|
||||
var reset = function () {
|
||||
|
||||
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,
|
||||
at_start: false,
|
||||
at_end: false
|
||||
};
|
||||
updatePage();
|
||||
};
|
||||
|
||||
var normalize = function (text) {
|
||||
return text.replace(normalizationRegex, function (ch) {
|
||||
return CHARACTERS_TO_NORMALIZE[ch];
|
||||
});
|
||||
};
|
||||
|
||||
// Helper for multiple search - fills matchesWithLength array
|
||||
// and takes into account cases when one search term
|
||||
// include another search term (for example, "tamed tame" or "this is").
|
||||
// Looking for intersecting terms in the 'matches' and
|
||||
// leave elements with a longer match-length.
|
||||
|
||||
var _prepareMatches = function (
|
||||
matchesWithLength, matches, matchesLength) {
|
||||
|
||||
function isSubTerm(matchesWithLength, currentIndex) {
|
||||
var currentElem, prevElem, nextElem;
|
||||
currentElem = matchesWithLength[currentIndex];
|
||||
nextElem = matchesWithLength[currentIndex + 1];
|
||||
// checking for cases like "TAMEd TAME"
|
||||
if (currentIndex < matchesWithLength.length - 1 &&
|
||||
currentElem.match === nextElem.match) {
|
||||
currentElem.skipped = true;
|
||||
return true;
|
||||
}
|
||||
// checking for cases like "thIS IS"
|
||||
for (var i = currentIndex - 1; i >= 0; i--) {
|
||||
prevElem = matchesWithLength[i];
|
||||
if (prevElem.skipped) {
|
||||
continue;
|
||||
}
|
||||
if (prevElem.match + prevElem.matchLength < currentElem.match) {
|
||||
break;
|
||||
}
|
||||
if (prevElem.match + prevElem.matchLength >=
|
||||
currentElem.match + currentElem.matchLength) {
|
||||
currentElem.skipped = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var i, len;
|
||||
// Sorting array of objects { match: <match>, matchLength: <matchLength> }
|
||||
// in increasing index first and then the lengths.
|
||||
matchesWithLength.sort(function(a, b) {
|
||||
return a.match === b.match ?
|
||||
a.matchLength - b.matchLength : a.match - b.match;
|
||||
});
|
||||
for (i = 0, len = matchesWithLength.length; i < len; i++) {
|
||||
if (isSubTerm(matchesWithLength, i)) {
|
||||
continue;
|
||||
}
|
||||
matches.push(matchesWithLength[i].match);
|
||||
matchesLength.push(matchesWithLength[i].matchLength);
|
||||
}
|
||||
};
|
||||
|
||||
var calcFindPhraseMatch = function (
|
||||
query, pageIndex, pageContent) {
|
||||
var matches = [];
|
||||
var queryLen = query.length;
|
||||
var matchIdx = -queryLen;
|
||||
while (true) {
|
||||
matchIdx = pageContent.indexOf(query, matchIdx + queryLen);
|
||||
if (matchIdx === -1) {
|
||||
break;
|
||||
}
|
||||
matches.push(matchIdx);
|
||||
}
|
||||
reader.pageMatches[pageIndex] = matches;
|
||||
|
||||
};
|
||||
|
||||
var calcFindWordMatch = function (
|
||||
query, pageIndex, pageContent) {
|
||||
var matchesWithLength = [];
|
||||
// Divide the query into pieces and search for text on each piece.
|
||||
var queryArray = query.match(/\S+/g);
|
||||
var subquery, subqueryLen, matchIdx;
|
||||
for (var i = 0, len = queryArray.length; i < len; i++) {
|
||||
subquery = queryArray[i];
|
||||
subqueryLen = subquery.length;
|
||||
matchIdx = -subqueryLen;
|
||||
while (true) {
|
||||
matchIdx = pageContent.indexOf(subquery, matchIdx + subqueryLen);
|
||||
if (matchIdx === -1) {
|
||||
break;
|
||||
}
|
||||
// Other searches do not, so we store the length.
|
||||
matchesWithLength.push({
|
||||
match: matchIdx,
|
||||
matchLength: subqueryLen,
|
||||
skipped: false
|
||||
});
|
||||
}
|
||||
}
|
||||
// Prepare arrays for store the matches.
|
||||
if (!reader.pageMatchesLength) {
|
||||
reader.pageMatchesLength = [];
|
||||
}
|
||||
reader.pageMatchesLength[pageIndex] = [];
|
||||
reader.pageMatches[pageIndex] = [];
|
||||
// Sort matchesWithLength, clean up intersecting terms
|
||||
// and put the result into the two arrays.
|
||||
_prepareMatches(matchesWithLength, reader.pageMatches[pageIndex],
|
||||
reader.pageMatchesLength[pageIndex]);
|
||||
|
||||
};
|
||||
|
||||
var getSnippet = function (pageIndex, position) {
|
||||
|
||||
var ellipse = '…',
|
||||
match_length = reader.search_state.query.length,
|
||||
span = '<span class="search_match">',
|
||||
span_close = '</span>',
|
||||
limit = 160 + span.length + span_close.length,
|
||||
leader,
|
||||
trailer,
|
||||
context;
|
||||
|
||||
leader = reader.pageContents[pageIndex].substring(position - limit/2, position);
|
||||
leader = leader.slice(leader.indexOf(" "));
|
||||
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;
|
||||
|
||||
return reader.ellipsize(context, context.length - 10);
|
||||
};
|
||||
|
||||
var createItem = function (pageIndex, position) {
|
||||
|
||||
var listitem = document.createElement("li"),
|
||||
link = document.createElement("a"),
|
||||
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);
|
||||
listitem.dataset.index = ++matchCount;
|
||||
link.innerHTML = '<span class="match_label">' + matchCount + '</span>' + getSnippet(pageIndex, position);
|
||||
listitem.classList.add("list_item");
|
||||
reader.bindLink(link, item);
|
||||
link.classList.add("search_link");
|
||||
listitem.appendChild(link);
|
||||
|
||||
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(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) {
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!caseSensitive) {
|
||||
pageContent = pageContent.toLowerCase();
|
||||
query = query.toLowerCase();
|
||||
}
|
||||
|
||||
if (phraseSearch) {
|
||||
calcFindPhraseMatch(query, pageIndex, pageContent);
|
||||
} else {
|
||||
calcFindWordMatch(query, pageIndex, pageContent);
|
||||
}
|
||||
};
|
||||
|
||||
var extractText = function () {
|
||||
|
||||
if (startedTextExtraction) {
|
||||
return;
|
||||
}
|
||||
startedTextExtraction = true;
|
||||
|
||||
reader.pageContents = [];
|
||||
var extractTextPromisesResolves = [];
|
||||
var numPages = reader.settings.numPages;
|
||||
|
||||
for (var i = 0; i < numPages; i++) {
|
||||
extractTextPromises.push(new Promise(function (resolve) {
|
||||
extractTextPromisesResolves.push(resolve);
|
||||
}));
|
||||
}
|
||||
|
||||
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 = [];
|
||||
|
||||
for (var i = 0, len = textItems.length; i < len; i++) {
|
||||
str.push(textItems[i].str);
|
||||
}
|
||||
|
||||
// Store the pageContent as a string.
|
||||
reader.pageContents.push(str.join(''));
|
||||
|
||||
extractTextPromisesResolves[pageIndex](pageIndex);
|
||||
if ((pageIndex + 1) < reader.settings.numPages) {
|
||||
extractPageText(pageIndex + 1);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
extractPageText(0);
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var executeCommand = function (cmd, state) {
|
||||
|
||||
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();
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
var generateMatchList = function () {
|
||||
|
||||
var container = document.getElementById("searchResults"),
|
||||
numPages = reader.settings.numPages,
|
||||
currentIdx = reader.settings.currentPage - 1,
|
||||
i;
|
||||
|
||||
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 (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 (previous) {
|
||||
|
||||
/* don't try to follow non-existing matches */
|
||||
if (!reader.search_active ||
|
||||
reader.pageMatches.length === 0)
|
||||
return;
|
||||
|
||||
var numPages = reader.settings.numPages,
|
||||
selected = reader.selected,
|
||||
leftIdx = idxOrNull(reader.resourcelst[0].pageNum),
|
||||
rightIdx = idxOrNull(reader.resourcelst[1].pageNum),
|
||||
try_match = false;
|
||||
|
||||
/* prevent match cycling on first or last page */
|
||||
if (!((previous && selected.at_start) || (!previous && selected.at_end))) {
|
||||
|
||||
selected.at_start = selected.at_end = false;
|
||||
|
||||
/* when in spread view, start at left (forward search) or right (backward search) page
|
||||
* if not iterating over matches on currently visible pages
|
||||
*/
|
||||
if (!(selected.matchIdx !== -1 && isVisible(selected.pageIdx))) {
|
||||
if (previous) {
|
||||
selected.pageIdx = (typeof rightIdx === "number") ? rightIdx : leftIdx;
|
||||
} else {
|
||||
selected.pageIdx = (typeof leftIdx === "number") ? leftIdx : rightIdx;
|
||||
}
|
||||
try_match = true;
|
||||
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function idxOrNull(num) {
|
||||
|
||||
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,
|
||||
matchlist,
|
||||
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");
|
||||
|
||||
updateMatchCounter(match.dataset.index);
|
||||
|
||||
//matchlist = document.getElementsByClassName("match:" + selected.pageIdx + ":" + selected.matchIdx);
|
||||
//for (i = 0; i < matchlist.length; i++)
|
||||
// matchlist[i].classList.add("selected_again");
|
||||
|
||||
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 updateMatchCounter = function (index) {
|
||||
|
||||
var prefix = "";
|
||||
|
||||
if (index)
|
||||
prefix = index + "/";
|
||||
|
||||
$match_count[0].textContent = prefix + matchCount;
|
||||
};
|
||||
|
||||
var resetMatchCounter = function () {
|
||||
$match_count[0].textContent = "0";
|
||||
$match_count.hide();
|
||||
};
|
||||
|
||||
var search = function(q) {
|
||||
if (q === undefined) {
|
||||
q = $searchBox.val();
|
||||
}
|
||||
|
||||
if (q === '') {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
reader.SidebarController.changePanelTo("Search");
|
||||
|
||||
reset();
|
||||
$searchResults.empty();
|
||||
|
||||
executeCommand('find', {query: q});
|
||||
};
|
||||
|
||||
$searchBox.on("keydown", function(e) {
|
||||
// Show the clear button if text input value is not empty
|
||||
$clearBtn.css("visibility", (this.value.length) ? "visible" : "hidden");
|
||||
|
||||
// run search when Enter is pressed
|
||||
if (e.keyCode === 13) {
|
||||
search();
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$clearBtn.on("click", function() {
|
||||
$(this).css("visibility", "hidden");
|
||||
$searchBox.val("");
|
||||
});
|
||||
|
||||
$clear_search.on("click", function () {
|
||||
reset();
|
||||
$searchResults.empty();
|
||||
$searchBox.val("");
|
||||
});
|
||||
|
||||
var clear = function () {
|
||||
|
||||
reset();
|
||||
$searchResults.empty();
|
||||
|
||||
if (reader.SidebarController.getActivePanel() == "Search") {
|
||||
reader.SidebarController.changePanelTo("Toc");
|
||||
}
|
||||
};
|
||||
|
||||
// initialize search
|
||||
reset();
|
||||
|
||||
if (reader.settings.preloadTextcontent) {
|
||||
reader.firstPagePromise.then(function() {
|
||||
setTimeout(function() {
|
||||
extractText();
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
var onShow = function() {
|
||||
$searchView.addClass("open");
|
||||
$searchBox.focus();
|
||||
};
|
||||
|
||||
var onHide = function() {
|
||||
$searchView.removeClass("open");
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
"show": onShow,
|
||||
"hide": onHide,
|
||||
"search": search,
|
||||
"executeCommand": executeCommand,
|
||||
"nextMatch": nextMatch
|
||||
|
||||
};
|
||||
};
|
119
vendor/pdfjs/controllers/settings_controller.js
vendored
Normal file
119
vendor/pdfjs/controllers/settings_controller.js
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
PDFJS.reader.SettingsController = function() {
|
||||
|
||||
var reader = this,
|
||||
book = this.book,
|
||||
settings = reader.settings;
|
||||
|
||||
var $settings = $("#settingsView"),
|
||||
$viewer = $("#viewer"),
|
||||
$overlay = $(".overlay"),
|
||||
$next = $("#next"),
|
||||
$prev = $("#prev"),
|
||||
$close = $("#close"),
|
||||
$sidebarReflow = $('#sidebarReflow'),
|
||||
$scrollToTop = $('#scrollToTop'),
|
||||
$touch_nav = $("#touch_nav"),
|
||||
$page_turn_arrows = $("#page_turn_arrows"),
|
||||
$prev_arrow = $("#prev :first-child"),
|
||||
$next_arrow = $("#next :first-child");
|
||||
|
||||
var show = function() {
|
||||
$settings.addClass('open');
|
||||
};
|
||||
|
||||
var hide = function() {
|
||||
$settings.removeClass('open');
|
||||
};
|
||||
|
||||
if (settings.scrollToTop) {
|
||||
$scrollToTop.prop('checked', true);
|
||||
} else {
|
||||
$scrollToTop.prop('checked', false);
|
||||
}
|
||||
|
||||
$scrollToTop.off('click').on('click', function() {
|
||||
settings.scrollToTop = !settings.scrollToTop;
|
||||
settings.session.setDefault("scrollToTop", settings.scrollToTop);
|
||||
});
|
||||
|
||||
if (settings.sidebarReflow) {
|
||||
$sidebarReflow.prop('checked', true);
|
||||
} else {
|
||||
$sidebarReflow.prop('checked', false);
|
||||
}
|
||||
|
||||
$sidebarReflow.off('click').on('click', function() {
|
||||
settings.sidebarReflow = !settings.sidebarReflow;
|
||||
if (settings.sidebarReflow && reader.sidebarOpen) reader.ReaderController.slideOut();
|
||||
if (!settings.sidebarReflow && !reader.sidebarOpen) reader.ReaderController.slideIn();
|
||||
settings.session.setDefault("sidebarReflow", settings.sidebarReflow);
|
||||
});
|
||||
|
||||
$settings.find(".closer").on("click", function() {
|
||||
hide();
|
||||
});
|
||||
|
||||
$overlay.on("click", function() {
|
||||
hide();
|
||||
});
|
||||
|
||||
// only enable close button when launched in an iframe default
|
||||
if (parent !== window) {
|
||||
$close.show();
|
||||
$close.on("click", function () {
|
||||
reader.book.destroy();
|
||||
parent.OCA.Files_Reader.Plugin.hide();
|
||||
});
|
||||
}
|
||||
|
||||
// default for extra wide navigation controls;
|
||||
// devices with touch navigation: on
|
||||
// devices without touch navigation: off
|
||||
$touch_nav.prop('checked', !('ontouchstart' in document.documentElement));
|
||||
if (!($touch_nav.prop('checked'))) {
|
||||
$next.addClass("touch_nav");
|
||||
$prev.addClass("touch_nav");
|
||||
}
|
||||
|
||||
// extra wide nagivation controls
|
||||
$touch_nav.off('change').on('change', function() {
|
||||
if ($(this).prop('checked')) {
|
||||
$prev.removeClass("touch_nav");
|
||||
$next.removeClass("touch_nav");
|
||||
} else {
|
||||
$prev.addClass("touch_nav");
|
||||
$next.addClass("touch_nav");
|
||||
}
|
||||
});
|
||||
|
||||
// page turn arrows default
|
||||
if (settings.pageArrows) {
|
||||
$page_turn_arrows.prop('checked', true);
|
||||
$prev_arrow.removeClass("translucent");
|
||||
$next_arrow.removeClass("translucent");
|
||||
} else {
|
||||
$page_turn_arrows.prop('checked', false);
|
||||
$prev_arrow.addClass("translucent");
|
||||
$next_arrow.addClass("translucent");
|
||||
}
|
||||
|
||||
// page turn arrows
|
||||
$page_turn_arrows.off('change').on('change', function() {
|
||||
if ($(this).prop('checked')) {
|
||||
settings.pageArrows = true;
|
||||
$prev_arrow.removeClass("translucent");
|
||||
$next_arrow.removeClass("translucent");
|
||||
} else {
|
||||
settings.pageArrows = false;
|
||||
$prev_arrow.addClass("translucent");
|
||||
$next_arrow.addClass("translucent");
|
||||
}
|
||||
|
||||
settings.session.setDefault("pageArrows", settings.pageArrows);
|
||||
});
|
||||
|
||||
return {
|
||||
"show" : show,
|
||||
"hide" : hide
|
||||
};
|
||||
};
|
76
vendor/pdfjs/controllers/sidebar_controller.js
vendored
Normal file
76
vendor/pdfjs/controllers/sidebar_controller.js
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
PDFJS.reader.SidebarController = function(book) {
|
||||
var reader = this,
|
||||
settings = reader.settings;
|
||||
|
||||
var $sidebar = $("#sidebar"),
|
||||
$panels = $("#panels"),
|
||||
$views = $("#views"),
|
||||
$close = $("#hide-Sidebar");
|
||||
$slider = $("#slider");
|
||||
|
||||
var activePanel = "Toc";
|
||||
|
||||
var changePanelTo = function(viewName) {
|
||||
var controllerName = viewName + "Controller";
|
||||
|
||||
if (!(activePanel == viewName || typeof reader[controllerName] === 'undefined' )) {
|
||||
reader[activePanel+ "Controller"].hide();
|
||||
reader[controllerName].show();
|
||||
activePanel = viewName;
|
||||
|
||||
//$panels.find('.open').removeClass("open");
|
||||
$sidebar.find('.open').removeClass("open");
|
||||
$panels.find("#show-" + viewName ).addClass("open");
|
||||
$views.find("#" + viewName.toLowerCase() + "View").addClass("open");
|
||||
}
|
||||
show();
|
||||
};
|
||||
|
||||
var getActivePanel = function() {
|
||||
return activePanel;
|
||||
};
|
||||
|
||||
var show = function() {
|
||||
reader.sidebarOpen = true;
|
||||
if (settings.sidebarReflow) reader.ReaderController.slideOut();
|
||||
$slider.hide();
|
||||
$sidebar.addClass("open");
|
||||
if (getActivePanel() === "Toc")
|
||||
reader.TocController.scrollToPage(settings.currentPage);
|
||||
}
|
||||
|
||||
var hide = function() {
|
||||
reader.sidebarOpen = false;
|
||||
$slider.show();
|
||||
reader.ReaderController.slideIn();
|
||||
$sidebar.removeClass("open");
|
||||
};
|
||||
|
||||
var toggle = function () {
|
||||
(reader.sidebarOpen) ? hide() : show();
|
||||
};
|
||||
|
||||
$close.on("click", function () {
|
||||
reader.SidebarController.hide();
|
||||
// $slider.addClass("icon-menu");
|
||||
// $slider.removeClass("icon-right");
|
||||
|
||||
});
|
||||
|
||||
$panels.find(".show_view").on("click", function(e) {
|
||||
var view = $(this).data("view");
|
||||
|
||||
changePanelTo(view);
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$sidebar.css("width", "calc(" + parseInt(settings.thumbnailWidth) + "px + 2em)");
|
||||
|
||||
return {
|
||||
'show' : show,
|
||||
'hide' : hide,
|
||||
'toggle' : toggle,
|
||||
'getActivePanel' : getActivePanel,
|
||||
'changePanelTo' : changePanelTo
|
||||
};
|
||||
};
|
93
vendor/pdfjs/controllers/styles_controller.js
vendored
Normal file
93
vendor/pdfjs/controllers/styles_controller.js
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
PDFJS.reader.StylesController = function (renderer) {
|
||||
|
||||
var reader = this,
|
||||
settings = reader.settings,
|
||||
customStyles = reader.settings.customStyles,
|
||||
activeStyles = reader.settings.activeStyles,
|
||||
$main = $("#main"),
|
||||
$nightmode_form = $('#nightmode_form'),
|
||||
$nightmode_reset = $('#nightmode_reset'),
|
||||
$night_brightness = $('#night_brightness'),
|
||||
$night_contrast = $('#night_contrast'),
|
||||
$night_sepia = $('#night_sepia'),
|
||||
$night_huerotate = $('#night_huerotate'),
|
||||
$night_saturate = $('#night_saturate'),
|
||||
$nightshift = $('.nightshift');
|
||||
|
||||
this.addStyle("nightMode", "*", {
|
||||
filter: 'invert(1) sepia(' + $night_sepia.val() + ') hue-rotate(' + $night_huerotate.val() + 'deg) brightness(' + $night_brightness.val() + ') contrast(' + $night_contrast.val() + ') saturate(' + $night_saturate.val() + ')'
|
||||
});
|
||||
|
||||
this.addStyle("appleBugs", "document, html, body, p, span, div", {
|
||||
"cursor": "pointer"
|
||||
});
|
||||
|
||||
// fix click-bug in apple products
|
||||
if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g))
|
||||
activeStyles['appleBugs'] = true;
|
||||
|
||||
for (var style in activeStyles) {
|
||||
if (!activeStyles.hasOwnProperty(style)) continue;
|
||||
|
||||
switch (style) {
|
||||
case "nightMode":
|
||||
reader.ControlsController.setNightmodeIcon(true);
|
||||
break;
|
||||
case "appleBugs":
|
||||
console.log("Apple mobile bugs detected, applying workarounds...");
|
||||
break;
|
||||
}
|
||||
|
||||
reader.enableStyle(customStyles[style]);
|
||||
}
|
||||
|
||||
$night_brightness.off('change').on('change', function() {
|
||||
updateNightmode();
|
||||
});
|
||||
|
||||
$night_contrast.off('change').on('change', function() {
|
||||
updateNightmode();
|
||||
});
|
||||
|
||||
$night_sepia.off('change').on('change', function() {
|
||||
updateNightmode();
|
||||
});
|
||||
|
||||
$night_huerotate.off('change').on('change', function() {
|
||||
updateNightmode();
|
||||
});
|
||||
|
||||
$night_saturate.off('change').on('change', function() {
|
||||
updateNightmode();
|
||||
});
|
||||
|
||||
$nightmode_form.off('reset').on('reset', function () {
|
||||
setTimeout(function() {
|
||||
updateNightmode();
|
||||
}, 10);
|
||||
});
|
||||
|
||||
var parseFilter = function(str, element) {
|
||||
var re = new RegExp(element+'\\(([\\d.]+)\\S*\\)'),
|
||||
value = null;
|
||||
|
||||
if (re.test(str))
|
||||
value = str.match(re)[1];
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
var updateNightmode = function() {
|
||||
customStyles.nightMode.rules.filter = 'invert(1) sepia(' + $night_sepia.val() + ') hue-rotate(' + $night_huerotate.val() + 'deg) brightness(' + $night_brightness.val() + ') contrast(' + $night_contrast.val() + ') saturate(' + $night_saturate.val() + ')';
|
||||
reader.updateStyle(customStyles.nightMode);
|
||||
};
|
||||
|
||||
$night_brightness.val(parseFilter(customStyles.nightMode.rules.filter,"brightness"));
|
||||
$night_contrast.val(parseFilter(customStyles.nightMode.rules.filter,"contrast"));
|
||||
$night_sepia.val(parseFilter(customStyles.nightMode.rules.filter,"sepia"));
|
||||
$night_huerotate.val(parseFilter(customStyles.nightMode.rules.filter,"hue-rotate"));
|
||||
$night_saturate.val(parseFilter(customStyles.nightMode.rules.filter,"saturate"));
|
||||
|
||||
return {
|
||||
};
|
||||
};
|
345
vendor/pdfjs/controllers/textlayer_controller.js
vendored
Normal file
345
vendor/pdfjs/controllers/textlayer_controller.js
vendored
Normal file
|
@ -0,0 +1,345 @@
|
|||
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;
|
||||
this.renderingDone = false;
|
||||
this.pageIdx = options.pageIndex;
|
||||
this.pageNumber = this.pageIdx + 1;
|
||||
this.matches = [];
|
||||
this.viewport = options.viewport;
|
||||
this.textDivs = [];
|
||||
this.textLayerRenderTask = null;
|
||||
this.enhanceTextSelection = options.enhanceTextSelection;
|
||||
this._bindMouse();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PDFJS.Reader.TextLayerController.prototype._finishRendering = function () {
|
||||
this.renderingDone = true;
|
||||
|
||||
if (!this.enhanceTextSelection) {
|
||||
var endOfContent = document.createElement('div');
|
||||
endOfContent.className = 'endOfContent';
|
||||
this.textLayerDiv.appendChild(endOfContent);
|
||||
}
|
||||
|
||||
if (this.eventBus !== null) {
|
||||
this.eventBus.dispatch('textlayerrendered', {
|
||||
source: this,
|
||||
pageNumber: this.pageNumber,
|
||||
numTextDivs: this.textDivs.length,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the text layer.
|
||||
* @param {number} timeout (optional) if specified, the rendering waits
|
||||
* for specified amount of ms.
|
||||
*/
|
||||
PDFJS.Reader.TextLayerController.prototype.render = function(timeout) {
|
||||
if (!this.textContent || this.renderingDone) {
|
||||
return;
|
||||
}
|
||||
this.cancel();
|
||||
|
||||
this.textDivs = [];
|
||||
var textLayerFrag = document.createDocumentFragment();
|
||||
this.textLayerRenderTask = PDFJS.renderTextLayer({
|
||||
textContent: this.textContent,
|
||||
container: textLayerFrag,
|
||||
viewport: this.viewport,
|
||||
textDivs: this.textDivs,
|
||||
timeout: timeout,
|
||||
enhanceTextSelection: this.enhanceTextSelection,
|
||||
});
|
||||
this.textLayerRenderTask.promise.then(function () {
|
||||
this.textLayerDiv.appendChild(textLayerFrag);
|
||||
this._finishRendering();
|
||||
this.updateMatches();
|
||||
}.bind(this), function (reason) {
|
||||
// cancelled or failed to render text layer -- skipping errors
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancels rendering of the text layer.
|
||||
*/
|
||||
PDFJS.Reader.TextLayerController.prototype.cancel = function () {
|
||||
if (this.textLayerRenderTask) {
|
||||
this.textLayerRenderTask.cancel();
|
||||
this.textLayerRenderTask = null;
|
||||
}
|
||||
};
|
||||
|
||||
PDFJS.Reader.TextLayerController.prototype.setTextContent = function (textContent) {
|
||||
this.cancel();
|
||||
this.textContent = textContent;
|
||||
};
|
||||
|
||||
PDFJS.Reader.TextLayerController.prototype.convertMatches = function(matches, matchesLength) {
|
||||
|
||||
var reader = this.reader;
|
||||
|
||||
var i = 0;
|
||||
var iIndex = 0;
|
||||
var bidiTexts = this.textContent.items;
|
||||
var end = bidiTexts.length - 1;
|
||||
var queryLen = reader.search_state ?
|
||||
reader.search_state.query.length : null;
|
||||
var ret = [];
|
||||
if (!matches) {
|
||||
return ret;
|
||||
}
|
||||
for (var m = 0, len = matches.length; m < len; m++) {
|
||||
// Calculate the start position.
|
||||
var matchIdx = matches[m];
|
||||
|
||||
// Loop over the divIdxs.
|
||||
while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
|
||||
iIndex += bidiTexts[i].str.length;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i === bidiTexts.length) {
|
||||
console.error('Could not find a matching mapping');
|
||||
}
|
||||
|
||||
var match = {
|
||||
begin: {
|
||||
divIdx: i,
|
||||
offset: matchIdx - iIndex
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate the end position.
|
||||
if (matchesLength) { // multiterm search
|
||||
matchIdx += matchesLength[m];
|
||||
} else { // phrase search
|
||||
matchIdx += queryLen;
|
||||
}
|
||||
|
||||
// Somewhat the same array as above, but use > instead of >= to get
|
||||
// the end position right.
|
||||
while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
|
||||
iIndex += bidiTexts[i].str.length;
|
||||
i++;
|
||||
}
|
||||
|
||||
match.end = {
|
||||
divIdx: i,
|
||||
offset: matchIdx - iIndex
|
||||
};
|
||||
ret.push(match);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
PDFJS.Reader.TextLayerController.prototype.renderMatches = function (matches) {
|
||||
// Early exit if there is nothing to render.
|
||||
if (matches.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var reader = this.reader;
|
||||
|
||||
var bidiTexts = this.textContent.items;
|
||||
var textDivs = this.textDivs;
|
||||
var prevEnd = null;
|
||||
var pageIdx = this.pageIdx;
|
||||
var isSelectedPage = (pageIdx === reader.selected.pageIdx);
|
||||
var selectedMatchIdx = reader.selected.matchIdx;
|
||||
var highlightAll = true;
|
||||
var infinity = {
|
||||
divIdx: -1,
|
||||
offset: undefined
|
||||
};
|
||||
|
||||
function beginText(begin, className) {
|
||||
var divIdx = begin.divIdx;
|
||||
textDivs[divIdx].textContent = '';
|
||||
appendTextToDiv(divIdx, 0, begin.offset, className);
|
||||
}
|
||||
|
||||
function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
|
||||
var div = textDivs[divIdx];
|
||||
var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset);
|
||||
var node = document.createTextNode(content);
|
||||
if (className) {
|
||||
var span = document.createElement('span');
|
||||
span.className = className;
|
||||
span.appendChild(node);
|
||||
div.appendChild(span);
|
||||
return;
|
||||
}
|
||||
div.appendChild(node);
|
||||
}
|
||||
|
||||
var i0 = selectedMatchIdx, i1 = i0 + 1;
|
||||
if (highlightAll) {
|
||||
i0 = 0;
|
||||
i1 = matches.length;
|
||||
} else if (!isSelectedPage) {
|
||||
// Not highlighting all and this isn't the selected page, so do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = i0; i < i1; i++) {
|
||||
var match = matches[i];
|
||||
var begin = match.begin;
|
||||
var end = match.end;
|
||||
var isSelected = (isSelectedPage && i === selectedMatchIdx);
|
||||
var id = "match:" + pageIdx + ":" + i;
|
||||
var highlightSuffix = (isSelected ? ' selected ' + id : ' ' + id);
|
||||
|
||||
// Match inside new div.
|
||||
if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
|
||||
// If there was a previous div, then add the text at the end.
|
||||
if (prevEnd !== null) {
|
||||
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
|
||||
}
|
||||
// Clear the divs and set the content until the starting point.
|
||||
beginText(begin);
|
||||
} else {
|
||||
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
|
||||
}
|
||||
|
||||
if (begin.divIdx === end.divIdx) {
|
||||
appendTextToDiv(begin.divIdx, begin.offset, end.offset,
|
||||
'highlight' + highlightSuffix);
|
||||
} else {
|
||||
appendTextToDiv(begin.divIdx, begin.offset, infinity.offset,
|
||||
'highlight begin' + highlightSuffix);
|
||||
for (var n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
|
||||
textDivs[n0].className = 'highlight middle' + highlightSuffix;
|
||||
}
|
||||
beginText(end, 'highlight end' + highlightSuffix);
|
||||
}
|
||||
prevEnd = end;
|
||||
}
|
||||
|
||||
if (prevEnd) {
|
||||
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
|
||||
}
|
||||
};
|
||||
|
||||
PDFJS.Reader.TextLayerController.prototype.updateMatches = function () {
|
||||
// Only show matches when all rendering is done.
|
||||
if (!this.renderingDone) {
|
||||
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;
|
||||
var bidiTexts = this.textContent.items;
|
||||
var clearedUntilDivIdx = -1;
|
||||
|
||||
// Clear all current matches.
|
||||
for (var i = 0, len = matches.length; i < len; i++) {
|
||||
var match = matches[i];
|
||||
var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
|
||||
for (var n = begin, end = match.end.divIdx; n <= end; n++) {
|
||||
var div = textDivs[n];
|
||||
div.textContent = bidiTexts[n].str;
|
||||
div.className = '';
|
||||
}
|
||||
clearedUntilDivIdx = match.end.divIdx + 1;
|
||||
}
|
||||
|
||||
// Convert the matches on the page controller into the match format
|
||||
// used for the textLayer.
|
||||
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);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fixes text selection: adds additional div where mouse was clicked.
|
||||
* This reduces flickering of the content if mouse slowly dragged down/up.
|
||||
* @private
|
||||
*/
|
||||
PDFJS.Reader.TextLayerController.prototype._bindMouse = function () {
|
||||
var div = this.textLayerDiv;
|
||||
var self = this;
|
||||
var expandDivsTimer = null;
|
||||
|
||||
div.addEventListener('mousedown', function (e) {
|
||||
if (self.enhanceTextSelection && self.textLayerRenderTask) {
|
||||
self.textLayerRenderTask.expandTextDivs(true);
|
||||
if ((typeof PDFJSDev === 'undefined' ||
|
||||
!PDFJSDev.test('FIREFOX || MOZCENTRAL')) &&
|
||||
expandDivsTimer) {
|
||||
clearTimeout(expandDivsTimer);
|
||||
expandDivsTimer = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var end = div.querySelector('.endOfContent');
|
||||
if (!end) {
|
||||
return;
|
||||
}
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
!PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
|
||||
// On non-Firefox browsers, the selection will feel better if the height
|
||||
// of the endOfContent div will be adjusted to start at mouse click
|
||||
// location -- this will avoid flickering when selections moves up.
|
||||
// However it does not work when selection started on empty space.
|
||||
var adjustTop = e.target !== div;
|
||||
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
||||
adjustTop = adjustTop && window.getComputedStyle(end).
|
||||
getPropertyValue('-moz-user-select') !== 'none';
|
||||
}
|
||||
if (adjustTop) {
|
||||
var divBounds = div.getBoundingClientRect();
|
||||
var r = Math.max(0, (e.pageY - divBounds.top) / divBounds.height);
|
||||
end.style.top = (r * 100).toFixed(2) + '%';
|
||||
}
|
||||
}
|
||||
end.classList.add('active');
|
||||
});
|
||||
|
||||
div.addEventListener('mouseup', function (e) {
|
||||
if (self.enhanceTextSelection && self.textLayerRenderTask) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
!PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
|
||||
expandDivsTimer = setTimeout(function() {
|
||||
if (self.textLayerRenderTask) {
|
||||
self.textLayerRenderTask.expandTextDivs(false);
|
||||
}
|
||||
expandDivsTimer = null;
|
||||
}, 300);
|
||||
} else {
|
||||
self.textLayerRenderTask.expandTextDivs(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var end = div.querySelector('.endOfContent');
|
||||
if (!end) {
|
||||
return;
|
||||
}
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
!PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
|
||||
end.style.top = '';
|
||||
}
|
||||
end.classList.remove('active');
|
||||
});
|
||||
};
|
||||
|
185
vendor/pdfjs/controllers/textlayer_controller.js.simple
vendored
Normal file
185
vendor/pdfjs/controllers/textlayer_controller.js.simple
vendored
Normal file
|
@ -0,0 +1,185 @@
|
|||
PDFJS.reader.TextLayerController = function() {
|
||||
|
||||
var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) {
|
||||
var textLayerFrag = document.createDocumentFragment();
|
||||
|
||||
this.textLayerDiv = textLayerDiv;
|
||||
this.layoutDone = false;
|
||||
this.divContentDone = false;
|
||||
this.pageIdx = pageIdx;
|
||||
this.matches = [];
|
||||
|
||||
this.beginLayout = function textLayerBuilderBeginLayout() {
|
||||
this.textDivs = [];
|
||||
this.renderingDone = false;
|
||||
};
|
||||
|
||||
this.endLayout = function textLayerBuilderEndLayout() {
|
||||
this.layoutDone = true;
|
||||
this.insertDivContent();
|
||||
};
|
||||
|
||||
this.renderLayer = function textLayerBuilderRenderLayer() {
|
||||
var textDivs = this.textDivs;
|
||||
var bidiTexts = this.textContent.bidiTexts;
|
||||
var textLayerDiv = this.textLayerDiv;
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// No point in rendering so many divs as it'd make the browser unusable
|
||||
// even after the divs are rendered
|
||||
var MAX_TEXT_DIVS_TO_RENDER = 100000;
|
||||
if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER)
|
||||
return;
|
||||
|
||||
for (var i = 0, ii = textDivs.length; i < ii; i++) {
|
||||
var textDiv = textDivs[i];
|
||||
if ('isWhitespace' in textDiv.dataset) {
|
||||
continue;
|
||||
}
|
||||
textLayerFrag.appendChild(textDiv);
|
||||
|
||||
ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
|
||||
var width = ctx.measureText(textDiv.textContent).width;
|
||||
|
||||
if (width > 0) {
|
||||
var textScale = textDiv.dataset.canvasWidth / width;
|
||||
|
||||
var transform = 'scale(' + textScale + ', 1)';
|
||||
if (bidiTexts[i].dir === 'ttb') {
|
||||
transform = 'rotate(90deg) ' + transform;
|
||||
}
|
||||
CustomStyle.setProp('transform', textDiv, transform);
|
||||
CustomStyle.setProp('transformOrigin', textDiv, '0% 0%');
|
||||
|
||||
textLayerDiv.appendChild(textDiv);
|
||||
}
|
||||
}
|
||||
|
||||
this.renderingDone = true;
|
||||
|
||||
textLayerDiv.appendChild(textLayerFrag);
|
||||
};
|
||||
|
||||
this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
|
||||
// Schedule renderLayout() if user has been scrolling, otherwise
|
||||
// run it right away
|
||||
var RENDER_DELAY = 200; // in ms
|
||||
var self = this;
|
||||
//0 was originally PDFView.lastScroll
|
||||
if (Date.now() - 0 > RENDER_DELAY) {
|
||||
// Render right away
|
||||
this.renderLayer();
|
||||
} else {
|
||||
// Schedule
|
||||
if (this.renderTimer)
|
||||
clearTimeout(this.renderTimer);
|
||||
this.renderTimer = setTimeout(function () {
|
||||
self.setupRenderLayoutTimer();
|
||||
}, RENDER_DELAY);
|
||||
}
|
||||
};
|
||||
|
||||
this.appendText = function textLayerBuilderAppendText(geom) {
|
||||
var textDiv = document.createElement('div');
|
||||
|
||||
// vScale and hScale already contain the scaling to pixel units
|
||||
var fontHeight = geom.fontSize * Math.abs(geom.vScale);
|
||||
textDiv.dataset.canvasWidth = geom.canvasWidth * geom.hScale;
|
||||
textDiv.dataset.fontName = geom.fontName;
|
||||
|
||||
textDiv.style.fontSize = fontHeight + 'px';
|
||||
textDiv.style.fontFamily = geom.fontFamily;
|
||||
textDiv.style.left = geom.x + 'px';
|
||||
textDiv.style.top = (geom.y - fontHeight) + 'px';
|
||||
|
||||
// The content of the div is set in the `setTextContent` function.
|
||||
|
||||
this.textDivs.push(textDiv);
|
||||
};
|
||||
|
||||
this.insertDivContent = function textLayerUpdateTextContent() {
|
||||
// Only set the content of the divs once layout has finished, the content
|
||||
// for the divs is available and content is not yet set on the divs.
|
||||
if (!this.layoutDone || this.divContentDone || !this.textContent)
|
||||
return;
|
||||
|
||||
this.divContentDone = true;
|
||||
|
||||
var textDivs = this.textDivs;
|
||||
var bidiTexts = this.textContent.bidiTexts;
|
||||
|
||||
for (var i = 0; i < bidiTexts.length; i++) {
|
||||
var bidiText = bidiTexts[i];
|
||||
var textDiv = textDivs[i];
|
||||
if (!/\S/.test(bidiText.str)) {
|
||||
textDiv.dataset.isWhitespace = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
textDiv.textContent = bidiText.str;
|
||||
// bidiText.dir may be 'ttb' for vertical texts.
|
||||
textDiv.dir = bidiText.dir === 'rtl' ? 'rtl' : 'ltr';
|
||||
}
|
||||
|
||||
this.setupRenderLayoutTimer();
|
||||
};
|
||||
|
||||
this.setTextContent = function textLayerBuilderSetTextContent(textContent) {
|
||||
this.textContent = textContent;
|
||||
this.insertDivContent();
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
var CustomStyle = (function CustomStyleClosure() {
|
||||
|
||||
// As noted on: http://www.zachstronaut.com/posts/2009/02/17/
|
||||
// animate-css-transforms-firefox-webkit.html
|
||||
// in some versions of IE9 it is critical that ms appear in this list
|
||||
// before Moz
|
||||
var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
|
||||
var _cache = { };
|
||||
|
||||
function CustomStyle() {
|
||||
}
|
||||
|
||||
CustomStyle.getProp = function get(propName, element) {
|
||||
// check cache only when no element is given
|
||||
if (arguments.length == 1 && typeof _cache[propName] == 'string') {
|
||||
return _cache[propName];
|
||||
}
|
||||
|
||||
element = element || document.documentElement;
|
||||
var style = element.style, prefixed, uPropName;
|
||||
|
||||
// test standard property first
|
||||
if (typeof style[propName] == 'string') {
|
||||
return (_cache[propName] = propName);
|
||||
}
|
||||
|
||||
// capitalize
|
||||
uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
|
||||
|
||||
// test vendor specific properties
|
||||
for (var i = 0, l = prefixes.length; i < l; i++) {
|
||||
prefixed = prefixes[i] + uPropName;
|
||||
if (typeof style[prefixed] == 'string') {
|
||||
return (_cache[propName] = prefixed);
|
||||
}
|
||||
}
|
||||
|
||||
//if all fails then set to undefined
|
||||
return (_cache[propName] = 'undefined');
|
||||
};
|
||||
|
||||
CustomStyle.setProp = function set(propName, element, str) {
|
||||
var prop = this.getProp(propName);
|
||||
if (prop != 'undefined')
|
||||
element.style[prop] = str;
|
||||
};
|
||||
|
||||
return CustomStyle;
|
||||
})();
|
||||
|
||||
|
202
vendor/pdfjs/controllers/toc_controller.js
vendored
Normal file
202
vendor/pdfjs/controllers/toc_controller.js
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
PDFJS.reader.TocController = function() {
|
||||
|
||||
var reader = this,
|
||||
book = this.book,
|
||||
settings = reader.settings,
|
||||
toc = document.getElementById("toc"),
|
||||
tovView = document.getElementById("tocView"),
|
||||
$toc_populate = $("#toc_populate"),
|
||||
timeout;
|
||||
|
||||
var isVisible = function (element) {
|
||||
|
||||
var viewport = element.getBoundingClientRect(),
|
||||
visible,
|
||||
offset = settings.preloadOffset;
|
||||
|
||||
visible = (
|
||||
viewport.top >= (0 - offset)
|
||||
&& viewport.left >= (0 - offset)
|
||||
&& viewport.right < (window.innerWidth + offset)
|
||||
&& viewport.bottom < (window.innerHeight + offset)
|
||||
);
|
||||
|
||||
return visible;
|
||||
};
|
||||
|
||||
var lazyLoad = function () {
|
||||
|
||||
var elements = toc.querySelectorAll('img[data-pagenum]'),
|
||||
pagenum,
|
||||
count;
|
||||
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
if (isVisible(elements[i])) {
|
||||
pagenum = elements[i].getAttribute("data-pagenum");
|
||||
elements[i].removeAttribute("data-pagenum");
|
||||
reader.getThumb(parseInt(pagenum), true);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!elements.length || count === elements.length ) {
|
||||
removeLazyLoader(tocView);
|
||||
}
|
||||
};
|
||||
|
||||
var lazyLoader = function () {
|
||||
timeout = setTimeout( function () {
|
||||
lazyLoad();
|
||||
}, settings.lazyDelay);
|
||||
};
|
||||
|
||||
var addLazyLoader = function (_element) {
|
||||
|
||||
var element = _element || window;
|
||||
|
||||
element.addEventListener("scroll", lazyLoader, false);
|
||||
element.addEventListener("load", lazyLoader, false);
|
||||
};
|
||||
|
||||
var removeLazyLoader = function (_element) {
|
||||
|
||||
var element = _element || window;
|
||||
|
||||
element.removeEventListener("scroll", lazyLoader);
|
||||
element.removeEventListener("load", lazyLoader);
|
||||
};
|
||||
|
||||
var tocCreate = function (no_pages, width, height, populate) {
|
||||
|
||||
var canvas = document.createElement("canvas"),
|
||||
ctx = canvas.getContext("2d"),
|
||||
aspect,
|
||||
imgsrc,
|
||||
preloadcount,
|
||||
scale,
|
||||
timeout;
|
||||
|
||||
aspect = parseFloat(width / height);
|
||||
|
||||
// create small placeholder image
|
||||
canvas.width = 10;
|
||||
canvas.height = parseInt(canvas.width / aspect);
|
||||
|
||||
placeholder_width = reader.settings.thumbnailWidth;
|
||||
placeholder_height = parseInt(reader.settings.thumbnailWidth / aspect);
|
||||
|
||||
// fill with transparent black, style in CSS
|
||||
ctx.fillStyle = "rgba(0, 0, 0, 0)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
imgsrc = canvas.toDataURL();
|
||||
|
||||
for(var i = 0; i < no_pages; i++) {
|
||||
var item = document.createElement('li'),
|
||||
placeholder = new Image(),
|
||||
label = document.createElement('span'),
|
||||
page_label = reader.pageLabels[i + 1];
|
||||
|
||||
item.setAttribute("id", "page_" + parseInt(i + 1));
|
||||
placeholder.src = imgsrc;
|
||||
placeholder.style.width = reader.settings.thumbnailWidth;
|
||||
placeholder.style.height = parseInt(reader.settings.thumbnailWidth / aspect);
|
||||
placeholder.classList.add("placeholder");
|
||||
label.innerHTML = page_label || (i + 1).toString();
|
||||
label.classList.add("page_label");
|
||||
//label.style.left = width;
|
||||
item.appendChild(placeholder);
|
||||
item.appendChild(label);
|
||||
toc.appendChild(item);
|
||||
if (populate) {
|
||||
reader.getThumb(i + 1, true);
|
||||
} else {
|
||||
placeholder.setAttribute("data-pagenum", parseInt(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (!populate) {
|
||||
|
||||
// preload first screenfull of thumbnails
|
||||
scale = parseFloat(settings.thumbnailWidth / width);
|
||||
preloadcount = parseInt(window.innerHeight / placeholder_height) + 2;
|
||||
if (preloadcount > settings.numPages)
|
||||
preloadcount = settings.numPages;
|
||||
|
||||
var _timeout = setTimeout(function () {
|
||||
for (var i = 1; i <= preloadcount; i++) {
|
||||
reader.getThumb(i, true);
|
||||
}
|
||||
}, settings.initialLazyDelay);
|
||||
}
|
||||
};
|
||||
|
||||
var tocInsert = function (image, page, replace) {
|
||||
var placeholder = toc.children[page - 1].firstChild;
|
||||
if (replace === true) {
|
||||
placeholder.parentNode.replaceChild(image, placeholder);
|
||||
}
|
||||
|
||||
toc.children[page - 1].addEventListener('click', function (e) {
|
||||
reader.queuePage(page);
|
||||
});
|
||||
};
|
||||
|
||||
var tocPopulate = function () {
|
||||
var i = 0;
|
||||
while (i < reader.settings.numPages) {
|
||||
reader.getThumb(i, true);
|
||||
i++;
|
||||
}
|
||||
|
||||
reader.thumbnails = true;
|
||||
$toc_populate.addClass("hide");
|
||||
remove_lazy_loader();
|
||||
};
|
||||
|
||||
if (!settings.thumbnails) {
|
||||
addLazyLoader(tocView);
|
||||
}
|
||||
|
||||
reader.book.getPage(1).then(function(page) {
|
||||
var width,
|
||||
height,
|
||||
viewport,
|
||||
page_rotation,
|
||||
rotation;
|
||||
|
||||
page_rotation = page.rotate;
|
||||
rotation = (page_rotation + reader.settings.rotation) % 360;
|
||||
|
||||
viewport = page.getViewport(1, rotation);
|
||||
|
||||
width = viewport.width;
|
||||
height = viewport.height;
|
||||
|
||||
tocCreate(settings.numPages, width, height, settings.thumbnails);
|
||||
});
|
||||
|
||||
var onShow = function() {
|
||||
tocView.classList.add('open');
|
||||
scrollToPage(settings.currentPage);
|
||||
};
|
||||
|
||||
var onHide = function() {
|
||||
tocView.classList.remove('open');
|
||||
};
|
||||
|
||||
var scrollToPage = function (pageNum) {
|
||||
if (pageNum > 0 && pageNum <= settings.numPages) {
|
||||
thumb = document.getElementById("page_" + pageNum);
|
||||
if (thumb)
|
||||
thumb.scrollIntoView();
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
"show" : onShow,
|
||||
"hide" : onHide,
|
||||
"tocInsert": tocInsert,
|
||||
"totPopulate": tocPopulate,
|
||||
"scrollToPage": scrollToPage
|
||||
};
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue