PdfListView.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. (function (name, context, definition) {
  2. if (typeof module != 'undefined' && module.exports) module.exports = definition()
  3. else if (typeof define == 'function' && define.amd) define(definition)
  4. else context[name] = definition()
  5. })('PDFListView', this, function (name, context) {
  6. //#expand __BUNDLE__
  7. function Logger() {
  8. this.logLevel = Logger.INFO;
  9. var self = this;
  10. if (typeof(console) == "object" && typeof(console.log) == "function") {
  11. this.debug = function() {
  12. if (self.logLevel <= Logger.DEBUG) {
  13. console.log.apply(console, arguments);
  14. }
  15. };
  16. this.info = function() {
  17. if (self.logLevel <= Logger.INFO) {
  18. console.log.apply(console, arguments);
  19. }
  20. };
  21. this.error = function() {
  22. if (self.logLevel <= Logger.ERROR) {
  23. console.log.apply(console, arguments);
  24. }
  25. };
  26. } else {
  27. this.debug = this.info = this.error = function nop() {};
  28. }
  29. }
  30. Logger.DEBUG = 0;
  31. Logger.INFO = 1;
  32. Logger.ERROR = 2;
  33. var logger = new Logger();
  34. function _flat(arr) {
  35. var res = arr.reduce(function(a, b) {
  36. return a.concat(b);
  37. });
  38. return res;
  39. }
  40. function failDumper(err) {
  41. logger.error(err);
  42. }
  43. if (typeof(PDFJS) === "undefined") {
  44. logger.error("PDF.js is not yet loaded.");
  45. }
  46. // -----------------------------------------------------------------------------
  47. /**
  48. * Wrapper around the raw PDF.JS document.
  49. */
  50. function Document(url, password, onProgress) {
  51. this.pdfDocument = null;
  52. this.pages = null;
  53. var parameters = {password: password};
  54. if (typeof url === 'string') { // URL
  55. parameters.url = url;
  56. } else if (url && 'byteLength' in url) { // ArrayBuffer
  57. parameters.data = url;
  58. }
  59. this.initialized = new PDFJS.LegacyPromise();
  60. PDFJS.getDocument(parameters, null, null, onProgress).then(this.loadPages.bind(this), failDumper);
  61. }
  62. Document.prototype.loadPages = function(pdfDocument) {
  63. this.pdfDocument = pdfDocument;
  64. var pagesCount = this.pagesCount = pdfDocument.numPages;
  65. var pagePromises = [];
  66. for (var i = 1; i <= pagesCount; i++) {
  67. pagePromises.push(pdfDocument.getPage(i));
  68. }
  69. this.pageRefMap = pageRefMap = {};
  70. var pagesPromise = Promise.all(pagePromises);
  71. var doc = this
  72. pagesPromise.then(function(promisedPages) {
  73. doc.pages = promisedPages.map(function(pdfPage, i) {
  74. var pageRef = pdfPage.ref
  75. pageRefMap[pageRef.num + ' ' + pageRef.gen] = i;
  76. return new Page(pdfPage);
  77. });
  78. });
  79. var destinationsPromise = pdfDocument.getDestinations();
  80. destinationsPromise.then(function(destinations) {
  81. doc.destinations = destinations;
  82. });
  83. Promise.all([pagesPromise, destinationsPromise]).then(function() {
  84. doc.initialized.resolve();
  85. }, failDumper);
  86. };
  87. /**
  88. * Handles the rendering. Multiple ListViews can be bound to a RenderController.
  89. * In that case, the RenderController figures out what's page has the highest
  90. * priority to render
  91. */
  92. function RenderController() {
  93. this.listViews = [];
  94. this.renderList = [];
  95. }
  96. RenderController.prototype = {
  97. addListView: function(listView) {
  98. // TODO: assert listView not already in list of this.listView
  99. this.listViews.push(listView);
  100. },
  101. updateRenderList: function() {
  102. this.renderList = _flat(this.listViews.map(function(listView) {
  103. return listView.getPagesToRender();
  104. }));
  105. // TODO: Some "highest-priority" sorting algorithm on the renderList.
  106. this.doRender();
  107. },
  108. pageToRender: function() {
  109. if (this.renderList.length === 0) return null;
  110. return this.renderList[0];
  111. },
  112. doRender: function() {
  113. var pageToRender = this.pageToRender();
  114. if (!pageToRender) return;
  115. pageToRender.render(this);
  116. },
  117. finishedRendering: function(pageView) {
  118. var idx = this.renderList.indexOf(pageView);
  119. // If the finished pageView is in the list of pages to render,
  120. // then remove it from the list and render start rendering the
  121. // next page.
  122. if (idx !== -1) {
  123. this.renderList.splice(idx, 1);
  124. this.doRender();
  125. }
  126. },
  127. onResize: function() {
  128. var renderAgain = false
  129. this.listViews.map(function(listView) {
  130. if (listView.calculateScale()) {
  131. listView.layout();
  132. renderAgain = true;
  133. }
  134. });
  135. if (renderAgain) {
  136. this.updateRenderList();
  137. }
  138. }
  139. };
  140. var LAYOUT_SINGLE = 'layout_single';
  141. var SCALE_MODE_AUTO = 'scale_mode_auto';
  142. var SCALE_MODE_VALUE = 'scale_mode_value';
  143. var SCALE_MODE_FIT_WIDTH = 'scale_mode_fit_width';
  144. var SCALE_MODE_FIT_HEIGHT = 'scale_mode_fit_height';
  145. /**
  146. * Main view that holds the single pageContainer/pageViews of the pdfDoc.
  147. */
  148. function ListView(dom, options) {
  149. this.dom = dom;
  150. this.options = options;
  151. this.pageLayout = LAYOUT_SINGLE;
  152. this.scaleMode = SCALE_MODE_VALUE;
  153. this.scale = 1.0;
  154. this.pageWidthOffset = 0;
  155. this.pageHeightOffset = 0;
  156. this.pageViews = [];
  157. this.containerViews = [];
  158. }
  159. ListView.prototype = {
  160. setDocument: function(pdfDoc) {
  161. this.clearPages();
  162. this.pdfDoc = pdfDoc;
  163. this.assignPagesToContainer();
  164. this.layout();
  165. },
  166. clearPages: function() {
  167. var self = this;
  168. this.containerViews.map(function(container) {
  169. self.dom.removeChild(container.dom);
  170. });
  171. this.pageViews = [];
  172. this.containerViews = [];
  173. },
  174. assignPagesToContainer: function() {
  175. // TODO: Handle multiple layout types here. For now, assume to have one page
  176. // per pageContainer.
  177. this.pdfDoc.pages.map(function(page) {
  178. var pageView = new PageView(page, this);
  179. this.pageViews.push(pageView);
  180. var container = new PageContainerView(this);
  181. container.setPageView(pageView, 0);
  182. this.containerViews.push(container);
  183. this.dom.appendChild(container.dom);
  184. }, this);
  185. },
  186. layout: function() {
  187. this.savePdfPosition();
  188. this.containerViews.forEach(function(containerView) {
  189. containerView.layout();
  190. });
  191. this.restorePdfPosition();
  192. },
  193. getScale: function() {
  194. return this.scale;
  195. },
  196. getScaleMode: function() {
  197. return this.scaleMode;
  198. },
  199. setScaleMode: function(scaleMode, scale) {
  200. this.scaleMode = scaleMode;
  201. if (scaleMode == SCALE_MODE_VALUE) {
  202. this.scale = scale;
  203. }
  204. this.calculateScale();
  205. this.layout();
  206. },
  207. setScale: function(scale) {
  208. this.setScaleMode(SCALE_MODE_VALUE, scale);
  209. },
  210. setToAutoScale: function() {
  211. this.setScaleMode(SCALE_MODE_AUTO);
  212. },
  213. setToFitWidth: function() {
  214. this.setScaleMode(SCALE_MODE_FIT_WIDTH);
  215. },
  216. setToFitHeight: function() {
  217. this.setScaleMode(SCALE_MODE_FIT_HEIGHT);
  218. },
  219. // Calculates the new scale. Returns `true` if the scale changed.
  220. calculateScale: function() {
  221. var newScale = this.scale;
  222. var oldScale = newScale;
  223. var scaleMode = this.scaleMode;
  224. if (scaleMode === SCALE_MODE_FIT_WIDTH || scaleMode === SCALE_MODE_AUTO) {
  225. var clientWidth = this.dom.clientWidth;
  226. if (clientWidth == 0) {
  227. logger.debug("LIST VIEW NOT VISIBLE")
  228. return false;
  229. }
  230. var maxNormalWidth = 0;
  231. this.containerViews.forEach(function(containerView) {
  232. maxNormalWidth = Math.max(maxNormalWidth, containerView.normalWidth);
  233. });
  234. var scale = (clientWidth - this.pageWidthOffset)/maxNormalWidth;
  235. if (scaleMode === SCALE_MODE_AUTO) {
  236. scale = Math.min(1.0, scale);
  237. }
  238. newScale = scale;
  239. } else if (scaleMode === SCALE_MODE_FIT_HEIGHT) {
  240. var clientHeight = this.dom.clientHeight;
  241. if (clientHeight == 0) {
  242. logger.debug("LIST VIEW NOT VISIBLE")
  243. return false;
  244. }
  245. var maxNormalHeight = 0;
  246. this.containerViews.forEach(function(containerView) {
  247. maxNormalHeight = Math.max(maxNormalHeight, containerView.normalHeight);
  248. });
  249. newScale = (clientHeight - this.pageHeightOffset)/maxNormalHeight;
  250. }
  251. this.scale = newScale;
  252. return newScale !== oldScale;
  253. },
  254. getPagesToRender: function() {
  255. // Cache these results to avoid dom access.
  256. this.scrollTop = this.dom.scrollTop;
  257. this.scrollBottom = this.scrollTop + this.dom.clientHeight;
  258. // TODO: For now, this only returns the visible pages and not
  259. // +1/-1 one to render in advance.
  260. return this.pageViews.filter(function(pageView) {
  261. var isVisible = pageView.isVisible();
  262. if (isVisible && !pageView.isRendered) {
  263. return true;
  264. }
  265. });
  266. },
  267. navigateTo: function(destRef) {
  268. var destination = this.pdfDoc.destinations[destRef]
  269. if (typeof destination !== "object") {
  270. return;
  271. }
  272. logger.debug("NAVIGATING TO", destination);
  273. var pageRef = destination[0];
  274. var pageNumber = this.pdfDoc.pageRefMap[pageRef.num + ' ' + pageRef.gen];
  275. if (typeof pageNumber !== "number") {
  276. return;
  277. }
  278. logger.debug("PAGE NUMBER", pageNumber);
  279. var pageView = this.pageViews[pageNumber];
  280. var destinationType = destination[1].name;
  281. switch(destinationType) {
  282. case "XYZ":
  283. var x = destination[2];
  284. var y = destination[3];
  285. break;
  286. default:
  287. // TODO
  288. return;
  289. }
  290. var position = pageView.getPdfPositionInViewer(x,y);
  291. this.dom.scrollTop = position.top;
  292. this.dom.scrollLeft = position.left;
  293. },
  294. savePdfPosition: function() {
  295. this.pdfPosition = this.getPdfPosition();
  296. logger.debug("SAVED PDF POSITION", this.pdfPosition);
  297. },
  298. restorePdfPosition: function() {
  299. logger.debug("RESTORING PDF POSITION", this.pdfPosition);
  300. this.setPdfPosition(this.pdfPosition);
  301. },
  302. getPdfPosition: function() {
  303. var pdfPosition = null;
  304. for (var i = 0; i < this.pageViews.length; i++) {
  305. var pageView = this.pageViews[i];
  306. var pdfOffset = pageView.getUppermostVisiblePdfOffset();
  307. if (pdfOffset !== null) {
  308. pdfPosition = {
  309. page: i,
  310. offset: {
  311. top: pdfOffset,
  312. left: 0 // TODO
  313. }
  314. }
  315. break;
  316. }
  317. }
  318. return pdfPosition;
  319. },
  320. setPdfPosition: function(pdfPosition) {
  321. if (typeof pdfPosition !== "undefined" && pdfPosition != null) {
  322. var offset = pdfPosition.offset;
  323. var page_index = pdfPosition.page;
  324. var pageView = this.pageViews[page_index];
  325. var position = pageView.getPdfPositionInViewer(offset.left, offset.top);
  326. this.dom.scrollTop = position.top;
  327. }
  328. }
  329. };
  330. /*
  331. * A PageContainerView holds multiple PageViews. E.g. in a two-page layout,
  332. * every pageContainerView holds two PageViews and is responsible to layout
  333. * them.
  334. */
  335. function PageContainerView(listView) {
  336. this.listView = listView;
  337. var dom = this.dom = document.createElement('div');
  338. dom.className = 'plv-page-container page-container';
  339. this.pages = [];
  340. }
  341. PageContainerView.prototype = {
  342. setPageView: function(pageView, idx) {
  343. // TODO: handle case if there is already a page here
  344. this.pages[idx] = pageView;
  345. // TODO: handle page idx properly
  346. this.dom.appendChild(pageView.dom);
  347. },
  348. removePageView: function(idx) {
  349. // TODO: check if idx is set on page[]
  350. this.dom.removeChild(this.pages[idx].dom);
  351. },
  352. layout: function() {
  353. var scale = this.listView.scale;
  354. var normalWidth = 0;
  355. var normalHeight = 0;
  356. this.pages.forEach(function(pageView) {
  357. pageView.layout();
  358. normalWidth += pageView.normalWidth;
  359. normalHeight = Math.max(pageView.normalHeight, normalHeight);
  360. });
  361. this.normalWidth = normalWidth;
  362. this.normalHeight = normalHeight;
  363. this.dom.style.width = (normalWidth * scale) + 'px';
  364. this.dom.style.height = (normalHeight * scale) + 'px';
  365. }
  366. };
  367. var RenderingStates = {
  368. INITIAL: 0,
  369. RUNNING: 1,
  370. PAUSED: 2,
  371. FINISHED: 3
  372. };
  373. var idCounter = 0;
  374. /**
  375. * The view for a single page.
  376. */
  377. function PageView(page, listView) {
  378. this.page = page;
  379. this.listView = listView;
  380. this.id = idCounter++;
  381. this.number = this.page.number;
  382. this.rotation = 0;
  383. this.isRendered = false;
  384. this.renderState = RenderingStates.INITIAL;
  385. var dom = this.dom = document.createElement('div');
  386. dom.className = "plv-page-view page-view";
  387. this.createNewCanvas();
  388. }
  389. PageView.prototype = {
  390. layout: function() {
  391. var scale = this.listView.scale;
  392. var viewport = this.viewport =
  393. this.page.pdfPage.getViewport(scale, this.rotation);
  394. this.normalWidth = viewport.width / scale;
  395. this.normalHeight = viewport.height / scale;
  396. // Only change the width/height property of the canvas if it really
  397. // changed. Every assignment to the width/height property clears the
  398. // content of the canvas.
  399. var newWidth = Math.floor(viewport.width);
  400. var newHeight = Math.floor(viewport.height);
  401. if (this.canvas.width !== newWidth) {
  402. this.canvas.width = newWidth;
  403. this.resetRenderState();
  404. }
  405. if (this.canvas.height !== newHeight) {
  406. this.canvas.height = newHeight;
  407. this.resetRenderState();
  408. }
  409. this.width = viewport.width;
  410. this.height = viewport.height;
  411. },
  412. isVisible: function() {
  413. var listView = this.listView;
  414. var dom = this.dom;
  415. var offsetTop = dom.offsetTop;
  416. var offsetBottom = offsetTop + this.height;
  417. return offsetBottom >= listView.scrollTop &&
  418. offsetTop <= listView.scrollBottom;
  419. },
  420. resetRenderState: function() {
  421. this.renderState = RenderingStates.INITIAL;
  422. this.isRendered = false;
  423. if (this.textLayerDiv) {
  424. this.dom.removeChild(this.textLayerDiv);
  425. delete this.textLayerDiv;
  426. }
  427. if (this.annotationsLayerDiv) {
  428. this.dom.removeChild(this.annotationsLayerDiv);
  429. delete this.annotationsLayerDiv;
  430. }
  431. },
  432. render: function(renderController) {
  433. return this.page.render(this, renderController);
  434. },
  435. getCanvasContext: function() {
  436. return this.canvas.getContext('2d');
  437. },
  438. createNewCanvas: function() {
  439. if (this.canvas) {
  440. this.dom.removeChild(this.canvas);
  441. }
  442. var canvas = this.canvas = document.createElement('canvas');
  443. this.dom.appendChild(canvas);
  444. this.layout();
  445. },
  446. pdfPositionToPixels: function(x, y) {
  447. return this.viewport.convertToViewportPoint(x, y);
  448. },
  449. getCanvasPositionInViewer: function() {
  450. return {
  451. left: this.canvas.offsetLeft + this.dom.offsetLeft,
  452. top: this.canvas.offsetTop + this.dom.offsetTop
  453. }
  454. },
  455. getPdfPositionInViewer: function(x, y) {
  456. pageOffset = this.pdfPositionToPixels(x, y);
  457. canvasOffset = this.getCanvasPositionInViewer();
  458. return {
  459. left: canvasOffset.left + pageOffset[0],
  460. top: canvasOffset.top + pageOffset[1]
  461. }
  462. },
  463. getUppermostVisibleCanvasOffset: function() {
  464. var pagePosition = this.getCanvasPositionInViewer();
  465. var pageHeight = this.canvas.height;
  466. var viewportTop = this.listView.dom.scrollTop;
  467. var viewportHeight = this.listView.dom.clientHeight;
  468. // Check if the top of the page is showing, i.e:
  469. // _______________
  470. // | |
  471. // | ........ |
  472. // | . . |
  473. // ----.------.---
  474. // . .
  475. // ........
  476. var topVisible = (pagePosition.top > viewportTop && pagePosition.top < viewportTop + viewportHeight);
  477. // Check if at least some of the page is showing, i.e:
  478. // ........ ........
  479. // ____.______.___ ---.------.---
  480. // | . . | or | . . |
  481. // | . . | | . . |
  482. // | ........ | | . . |
  483. // --------------- ---.------.---
  484. // ........
  485. var someContentVisible = (pagePosition.top < viewportTop && pagePosition.top + pageHeight > viewportTop);
  486. if (topVisible) {
  487. return 0;
  488. } else if (someContentVisible) {
  489. return viewportTop - pagePosition.top;
  490. } else {
  491. return null;
  492. }
  493. },
  494. getUppermostVisiblePdfOffset: function() {
  495. var canvasOffset = this.getUppermostVisibleCanvasOffset();
  496. if (canvasOffset === null) {
  497. return null;
  498. }
  499. var pdfOffset = this.viewport.convertToPdfPoint(0, canvasOffset);
  500. return pdfOffset[1];
  501. }
  502. };
  503. /**
  504. * An abstraction around the raw page object of PDF.JS, that also handles the
  505. * rendering logic of (maybe multiple) pageView(s) that are based on this page.
  506. */
  507. function Page(pdfPage, number) {
  508. this.number = number;
  509. this.pdfPage = pdfPage;
  510. this.renderContextList = {};
  511. }
  512. Page.prototype = {
  513. render: function(pageView, renderController) {
  514. var renderContext;
  515. // FEATURE: If the page was rendered already once, then use the old
  516. // version as a placeholder until the new version is rendered at the
  517. // expected quality.
  518. // FEATURE: If the page can be rendered at low quality (thumbnail) and
  519. // there is already a higher resolution rendering, then use this one
  520. // instead of rerendering from scratch again.
  521. // PageView is not layouted.
  522. if (!pageView.viewport) return;
  523. // Nothing todo.
  524. if (pageView.isRendered) return;
  525. // Not most important page to render ATM.
  526. if (renderController.pageToRender() !== pageView) return;
  527. var self = this;
  528. var viewport;
  529. if (renderContext = this.renderContextList[pageView.id]) {
  530. viewport = renderContext.viewport;
  531. // TODO: handle rotation
  532. if (viewport.height !== pageView.viewport.height ||
  533. viewport.height !== pageView.viewport.height)
  534. {
  535. // The viewport changed -> need to rerender.
  536. renderContext.abandon = true;
  537. delete self.renderContextList[pageView.id];
  538. pageView.createNewCanvas();
  539. self.render(pageView, renderController);
  540. } else if (renderContext.state === RenderingStates.PAUSED) {
  541. // There is already a not finished renderState ->
  542. logger.debug('RESUME', pageView.id);
  543. renderContext.resume();
  544. }
  545. }
  546. if (!renderContext) {
  547. viewport = pageView.viewport;
  548. // No rendering data yet -> create a new renderContext and start
  549. // the rendering process.
  550. var textLayer;
  551. var textLayerBuilder = pageView.listView.options.textLayerBuilder;
  552. if (textLayerBuilder) {
  553. var textLayerDiv = pageView.textLayerDiv = document.createElement("div");
  554. textLayerDiv.className = 'plv-text-layer text-layer';
  555. pageView.dom.appendChild(textLayerDiv);
  556. textLayer = new textLayerBuilder(textLayerDiv);
  557. this.pdfPage.getTextContent().then(
  558. function(textContent) {
  559. textLayer.setTextContent(textContent);
  560. }
  561. );
  562. }
  563. var annotationsLayerBuilder = pageView.listView.options.annotationsLayerBuilder;
  564. if (annotationsLayerBuilder) {
  565. var annotationsLayerDiv = pageView.annotationsLayerDiv = document.createElement("div");
  566. annotationsLayerDiv.className = 'plv-annotations-layer annotations-layer';
  567. pageView.dom.appendChild(annotationsLayerDiv);
  568. var annotationsLayer = new annotationsLayerBuilder(pageView, annotationsLayerDiv);
  569. this.pdfPage.getAnnotations().then(
  570. function(annotations) {
  571. annotationsLayer.setAnnotations(annotations)
  572. }
  573. );
  574. }
  575. renderContext = {
  576. canvasContext: pageView.getCanvasContext(),
  577. viewport: viewport,
  578. textLayer: textLayer,
  579. continueCallback: function pdfViewContinueCallback(cont) {
  580. if (renderContext.abandon) {
  581. logger.debug("ABANDON", pageView.id);
  582. return;
  583. }
  584. if (renderController.pageToRender() !== pageView) {
  585. logger.debug('PAUSE', pageView.id);
  586. renderContext.state = RenderingStates.PAUSED;
  587. renderContext.resume = function resumeCallback() {
  588. renderContext.state = RenderingStates.RUNNING;
  589. cont();
  590. };
  591. return;
  592. }
  593. logger.debug('CONT', pageView.id);
  594. cont();
  595. }
  596. };
  597. this.renderContextList[pageView.id] = renderContext;
  598. logger.debug("BEGIN", pageView.id);
  599. renderContext.renderPromise = this.pdfPage.render(renderContext).promise;
  600. renderContext.renderPromise.then(
  601. function pdfPageRenderCallback() {
  602. logger.debug('DONE', pageView.id);
  603. pageView.isRendered = true;
  604. renderController.finishedRendering(pageView);
  605. },
  606. failDumper
  607. );
  608. }
  609. return renderContext.renderPromise;
  610. }
  611. };
  612. function PDFListView(mainDiv, options) {
  613. if (typeof(options) != "object") {
  614. options = {};
  615. }
  616. if (typeof(options.logLevel) != "number") {
  617. options.logLevel = Logger.INFO;
  618. }
  619. logger.logLevel = options.logLevel;
  620. this.listView = new ListView(mainDiv, options);
  621. this.renderController = new RenderController();
  622. this.renderController.addListView(this.listView);
  623. this.renderController.updateRenderList();
  624. var self = this;
  625. mainDiv.addEventListener('scroll', function() {
  626. // This will update the list AND start rendering if needed.
  627. self.renderController.updateRenderList();
  628. });
  629. window.addEventListener('resize', function() {
  630. // Check if the scale changed due to the resizing.
  631. if (self.listView.calculateScale()) {
  632. // Update the layout and start rendering. Changing the layout
  633. // of the PageView makes it rendering stop.
  634. self.listView.layout();
  635. self.renderController.updateRenderList();
  636. }
  637. });
  638. }
  639. PDFListView.prototype = {
  640. loadPdf: function(url, onProgress) {
  641. this.doc = new Document(url, null, onProgress);
  642. var self = this;
  643. var promise = this.doc.initialized;
  644. promise.then(function() {
  645. logger.debug('LOADED');
  646. self.listView.setDocument(self.doc);
  647. self.renderController.updateRenderList();
  648. }, failDumper);
  649. return promise;
  650. },
  651. getScale: function() {
  652. return this.listView.getScale();
  653. },
  654. getScaleMode: function() {
  655. return this.listView.getScaleMode()
  656. },
  657. setScaleMode: function(scaleMode, scale) {
  658. this.listView.setScaleMode(scaleMode, scale);
  659. this.renderController.updateRenderList();
  660. },
  661. setScale: function(scale) {
  662. this.listView.setScale(scale);
  663. this.renderController.updateRenderList();
  664. },
  665. setToAutoScale: function() {
  666. this.listView.setToAutoScale();
  667. this.renderController.updateRenderList();
  668. },
  669. setToFitWidth: function() {
  670. this.listView.setToFitWidth();
  671. this.renderController.updateRenderList();
  672. },
  673. setToFitHeight: function() {
  674. this.listView.setToFitHeight();
  675. this.renderController.updateRenderList();
  676. },
  677. onResize: function() {
  678. this.renderController.onResize();
  679. },
  680. getPdfPosition: function() {
  681. return this.listView.getPdfPosition();
  682. },
  683. setPdfPosition: function(pdfPosition) {
  684. this.listView.setPdfPosition(pdfPosition)
  685. }
  686. };
  687. PDFListView.Logger = Logger;
  688. return PDFListView;
  689. });