Moves thumbs logic into PDFThumbnailViewer.

This commit is contained in:
Yury Delendik 2014-09-12 14:48:44 -05:00
parent bfefadb87c
commit 3bce14761a
2 changed files with 118 additions and 63 deletions

View File

@ -14,16 +14,18 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* globals PDFView, mozL10n, RenderingStates */ /* globals mozL10n, RenderingStates, THUMBNAIL_SCROLL_MARGIN,
watchScroll, getVisibleElements, scrollIntoView */
'use strict'; 'use strict';
var ThumbnailView = function thumbnailView(container, id, defaultViewport) { var ThumbnailView = function thumbnailView(container, id, defaultViewport,
linkService, renderingQueue) {
var anchor = document.createElement('a'); var anchor = document.createElement('a');
anchor.href = PDFView.getAnchorUrl('#page=' + id); anchor.href = linkService.getAnchorUrl('#page=' + id);
anchor.title = mozL10n.get('thumb_page_title', {page: id}, 'Page {{page}}'); anchor.title = mozL10n.get('thumb_page_title', {page: id}, 'Page {{page}}');
anchor.onclick = function stopNavigation() { anchor.onclick = function stopNavigation() {
PDFView.page = id; linkService.page = id;
return false; return false;
}; };
@ -62,6 +64,7 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
this.hasImage = false; this.hasImage = false;
this.renderingState = RenderingStates.INITIAL; this.renderingState = RenderingStates.INITIAL;
this.renderingQueue = renderingQueue;
this.setPdfPage = function thumbnailViewSetPdfPage(pdfPage) { this.setPdfPage = function thumbnailViewSetPdfPage(pdfPage) {
this.pdfPage = pdfPage; this.pdfPage = pdfPage;
@ -125,7 +128,7 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
this.draw = function thumbnailViewDraw(callback) { this.draw = function thumbnailViewDraw(callback) {
if (!this.pdfPage) { if (!this.pdfPage) {
var promise = PDFView.getPage(this.id); var promise = this.renderingQueue.getPage(this.id);
promise.then(function(pdfPage) { promise.then(function(pdfPage) {
this.setPdfPage(pdfPage); this.setPdfPage(pdfPage);
this.draw(callback); this.draw(callback);
@ -150,7 +153,7 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
canvasContext: ctx, canvasContext: ctx,
viewport: drawViewport, viewport: drawViewport,
continueCallback: function(cont) { continueCallback: function(cont) {
if (PDFView.highestPriorityPage !== 'thumbnail' + self.id) { if (self.renderingQueue.highestPriorityPage !== 'thumbnail' + self.id) {
self.renderingState = RenderingStates.PAUSED; self.renderingState = RenderingStates.PAUSED;
self.resume = function() { self.resume = function() {
self.renderingState = RenderingStates.RUNNING; self.renderingState = RenderingStates.RUNNING;
@ -187,7 +190,7 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
this.setImage = function thumbnailViewSetImage(img) { this.setImage = function thumbnailViewSetImage(img) {
if (!this.pdfPage) { if (!this.pdfPage) {
var promise = PDFView.getPage(this.id); var promise = this.renderingQueue.getPage(this.id);
promise.then(function(pdfPage) { promise.then(function(pdfPage) {
this.setPdfPage(pdfPage); this.setPdfPage(pdfPage);
this.setImage(img); this.setImage(img);
@ -232,3 +235,95 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
}; };
ThumbnailView.tempImageCache = null; ThumbnailView.tempImageCache = null;
var PDFThumbnailViewer = (function pdfThumbnailViewer() {
function PDFThumbnailViewer(options) {
this.container = options.container;
this.renderingQueue = options.renderingQueue;
this.linkService = options.linkService;
this.scroll = watchScroll(this.container, this.scrollUpdated.bind(this));
this.thumbnails = [];
this.currentPage = -1;
}
PDFThumbnailViewer.prototype = {
scrollUpdated: function PDFThumbnailViewer_scrollUpdated() {
this.renderingQueue.renderHighestPriority();
},
getVisibleThumbs: function PDFThumbnailViewer_getVisibleThumbs() {
return getVisibleElements(this.container, this.thumbnails);
},
updatePage: function (page) {
var selected = document.querySelector('.thumbnail.selected');
if (selected) {
selected.classList.remove('selected');
}
var thumbnail = document.getElementById('thumbnailContainer' + page);
thumbnail.classList.add('selected');
var visibleThumbs = this.getVisibleThumbs();
var numVisibleThumbs = visibleThumbs.views.length;
// If the thumbnail isn't currently visible, scroll it into view.
if (numVisibleThumbs > 0) {
var first = visibleThumbs.first.id;
// Account for only one thumbnail being visible.
var last = (numVisibleThumbs > 1 ? visibleThumbs.last.id : first);
if (page <= first || page >= last) {
scrollIntoView(thumbnail, { top: THUMBNAIL_SCROLL_MARGIN });
}
}
this.currentPage = page;
},
updateRotation: function (pageRotation) {
for (var i = 0, l = this.thumbnails.length; i < l; i++) {
var thumb = this.thumbnails[i];
thumb.update(pageRotation);
}
},
cleanup: function PDFThumbnailViewer_cleanup() {
ThumbnailView.tempImageCache = null;
},
removeAllThumbnails: function PDFThumbnailViewer_cleanup() {
var thumbsView = this.container;
while (thumbsView.hasChildNodes()) {
thumbsView.removeChild(thumbsView.lastChild);
}
this.thumbnails = [];
},
addThumbnail: function PDFThumbnailViewer_addThumbnail(pageNum, viewport,
linkService) {
var thumbnail = new ThumbnailView(this.container, pageNum, viewport,
this.linkService, this.renderingQueue);
this.thumbnails.push(thumbnail);
return thumbnail;
},
ensureThumbnailVisible:
function PDFThumbnailViewer_ensureThumbnailVisible(page) {
// Ensure that the thumbnail of the current page is visible
// when switching from another view.
scrollIntoView(document.getElementById('thumbnailContainer' + page));
},
forceRendering: function () {
var visibleThumbs = this.getVisibleThumbs();
var thumbView = this.renderingQueue.getHighestPriority(visibleThumbs,
this.thumbnails,
this.scroll.down);
if (thumbView) {
this.renderingQueue.renderView(thumbView, 'thumbnail');
return true;
}
return false;
}
};
return PDFThumbnailViewer;
})();

View File

@ -17,7 +17,7 @@
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, ProgressBar, /* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, ProgressBar,
DownloadManager, getFileName, scrollIntoView, getPDFFileNameFromURL, DownloadManager, getFileName, scrollIntoView, getPDFFileNameFromURL,
PDFHistory, Preferences, SidebarView, ViewHistory, PageView, PDFHistory, Preferences, SidebarView, ViewHistory, PageView,
ThumbnailView, URL, noContextMenuHandler, SecondaryToolbar, PDFThumbnailViewer, URL, noContextMenuHandler, SecondaryToolbar,
PasswordPrompt, PresentationMode, HandTool, Promise, PasswordPrompt, PresentationMode, HandTool, Promise,
DocumentProperties, DocumentOutlineView, DocumentAttachmentsView, DocumentProperties, DocumentOutlineView, DocumentAttachmentsView,
OverlayManager, PDFFindController, PDFFindBar, getVisibleElements, OverlayManager, PDFFindController, PDFFindBar, getVisibleElements,
@ -108,19 +108,17 @@ var currentPageNumber = 1;
var PDFView = { var PDFView = {
pages: [], pages: [],
thumbnails: [],
currentScale: UNKNOWN_SCALE, currentScale: UNKNOWN_SCALE,
currentScaleValue: null, currentScaleValue: null,
initialBookmark: document.location.hash.substring(1), initialBookmark: document.location.hash.substring(1),
container: null, container: null,
thumbnailContainer: null,
initialized: false, initialized: false,
fellback: false, fellback: false,
pdfDocument: null, pdfDocument: null,
sidebarOpen: false, sidebarOpen: false,
printing: false, printing: false,
pageViewScroll: null, pageViewScroll: null,
thumbnailViewScroll: null, pdfThumbnailViewer: null,
pageRotation: 0, pageRotation: 0,
mouseScrollTimeStamp: 0, mouseScrollTimeStamp: 0,
mouseScrollDelta: 0, mouseScrollDelta: 0,
@ -137,12 +135,12 @@ var PDFView = {
var container = this.container = document.getElementById('viewerContainer'); var container = this.container = document.getElementById('viewerContainer');
this.pageViewScroll = watchScroll(container, updateViewarea); this.pageViewScroll = watchScroll(container, updateViewarea);
var thumbnailContainer = this.thumbnailContainer = var thumbnailContainer = document.getElementById('thumbnailView');
document.getElementById('thumbnailView'); this.pdfThumbnailViewer = new PDFThumbnailViewer({
this.thumbnailViewScroll = watchScroll(thumbnailContainer, function () { container: thumbnailContainer,
this.renderHighestPriority(); renderingQueue: this,
}.bind(this)); linkService: this
});
Preferences.initialize(); Preferences.initialize();
@ -591,10 +589,7 @@ var PDFView = {
this.pdfDocument.destroy(); this.pdfDocument.destroy();
this.pdfDocument = null; this.pdfDocument = null;
var thumbsView = document.getElementById('thumbnailView'); this.pdfThumbnailViewer.removeAllThumbnails();
while (thumbsView.hasChildNodes()) {
thumbsView.removeChild(thumbsView.lastChild);
}
var container = document.getElementById('viewer'); var container = document.getElementById('viewer');
while (container.hasChildNodes()) { while (container.hasChildNodes()) {
@ -953,7 +948,6 @@ var PDFView = {
var pages = this.pages = []; var pages = this.pages = [];
var pagesRefMap = this.pagesRefMap = {}; var pagesRefMap = this.pagesRefMap = {};
var thumbnails = this.thumbnails = [];
var resolvePagesPromise; var resolvePagesPromise;
var pagesPromise = new Promise(function (resolve) { var pagesPromise = new Promise(function (resolve) {
@ -963,7 +957,7 @@ var PDFView = {
var firstPagePromise = pdfDocument.getPage(1); var firstPagePromise = pdfDocument.getPage(1);
var container = document.getElementById('viewer'); var container = document.getElementById('viewer');
var thumbsView = document.getElementById('thumbnailView'); var thumbsViewer = this.pdfThumbnailViewer;
// Fetch a single page so we can get a viewport that will be the default // Fetch a single page so we can get a viewport that will be the default
// viewport for all pages // viewport for all pages
@ -974,11 +968,9 @@ var PDFView = {
var pageView = new PageView(container, pageNum, scale, var pageView = new PageView(container, pageNum, scale,
self.navigateTo.bind(self), self.navigateTo.bind(self),
viewportClone); viewportClone);
var thumbnailView = new ThumbnailView(thumbsView, pageNum, var thumbnailView = thumbsViewer.addThumbnail(pageNum, viewportClone);
viewportClone);
bindOnAfterDraw(pageView, thumbnailView); bindOnAfterDraw(pageView, thumbnailView);
pages.push(pageView); pages.push(pageView);
thumbnails.push(thumbnailView);
} }
// Fetch all the pages since the viewport is needed before printing // Fetch all the pages since the viewport is needed before printing
@ -1239,12 +1231,7 @@ var PDFView = {
} }
// No pages needed rendering so check thumbnails. // No pages needed rendering so check thumbnails.
if (this.sidebarOpen) { if (this.sidebarOpen) {
var visibleThumbs = this.getVisibleThumbs(); if (this.pdfThumbnailViewer.forceRendering()) {
var thumbView = this.getHighestPriority(visibleThumbs,
this.thumbnails,
this.thumbnailViewScroll.down);
if (thumbView) {
this.renderView(thumbView, 'thumbnail');
return; return;
} }
} }
@ -1268,7 +1255,7 @@ var PDFView = {
} }
this.pdfDocument.cleanup(); this.pdfDocument.cleanup();
ThumbnailView.tempImageCache = null; this.pdfThumbnailViewer.cleanup();
}, },
getHighestPriority: function pdfViewGetHighestPriority(visible, views, getHighestPriority: function pdfViewGetHighestPriority(visible, views,
@ -1424,10 +1411,7 @@ var PDFView = {
PDFView.renderHighestPriority(); PDFView.renderHighestPriority();
if (wasAnotherViewVisible) { if (wasAnotherViewVisible) {
// Ensure that the thumbnail of the current page is visible this.pdfThumbnailViewer.ensureThumbnailVisible(this.page);
// when switching from another view.
scrollIntoView(document.getElementById('thumbnailContainer' +
this.page));
} }
break; break;
@ -1472,10 +1456,6 @@ var PDFView = {
} }
}, },
getVisibleThumbs: function pdfViewGetVisibleThumbs() {
return getVisibleElements(this.thumbnailContainer, this.thumbnails);
},
// Helper function to parse query string (e.g. ?param1=value&parm2=...). // Helper function to parse query string (e.g. ?param1=value&parm2=...).
parseQueryString: function pdfViewParseQueryString(query) { parseQueryString: function pdfViewParseQueryString(query) {
var parts = query.split('&'); var parts = query.split('&');
@ -1552,10 +1532,7 @@ var PDFView = {
page.update(page.scale, this.pageRotation); page.update(page.scale, this.pageRotation);
} }
for (i = 0, l = this.thumbnails.length; i < l; i++) { this.pdfThumbnailViewer.updateRotation(this.pageRotation);
var thumb = this.thumbnails[i];
thumb.update(this.pageRotation);
}
this.setScale(this.currentScaleValue, true, true); this.setScale(this.currentScaleValue, true, true);
@ -2131,24 +2108,7 @@ window.addEventListener('pagechange', function pagechange(evt) {
var page = evt.pageNumber; var page = evt.pageNumber;
if (PDFView.previousPageNumber !== page) { if (PDFView.previousPageNumber !== page) {
document.getElementById('pageNumber').value = page; document.getElementById('pageNumber').value = page;
var selected = document.querySelector('.thumbnail.selected'); PDFView.pdfThumbnailViewer.updatePage(page);
if (selected) {
selected.classList.remove('selected');
}
var thumbnail = document.getElementById('thumbnailContainer' + page);
thumbnail.classList.add('selected');
var visibleThumbs = PDFView.getVisibleThumbs();
var numVisibleThumbs = visibleThumbs.views.length;
// If the thumbnail isn't currently visible, scroll it into view.
if (numVisibleThumbs > 0) {
var first = visibleThumbs.first.id;
// Account for only one thumbnail being visible.
var last = (numVisibleThumbs > 1 ? visibleThumbs.last.id : first);
if (page <= first || page >= last) {
scrollIntoView(thumbnail, { top: THUMBNAIL_SCROLL_MARGIN });
}
}
} }
var numPages = PDFView.pages.length; var numPages = PDFView.pages.length;