OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 'use strict'; | 5 'use strict'; |
6 | 6 |
7 /** | 7 /** |
8 * @return {number} Width of a scrollbar in pixels | 8 * @return {number} Width of a scrollbar in pixels |
9 */ | 9 */ |
10 function getScrollbarWidth() { | 10 function getScrollbarWidth() { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 */ | 88 */ |
89 PDFViewer.MIN_TOOLBAR_OFFSET = 15; | 89 PDFViewer.MIN_TOOLBAR_OFFSET = 15; |
90 | 90 |
91 /** | 91 /** |
92 * The height of the toolbar along the top of the page. The document will be | 92 * The height of the toolbar along the top of the page. The document will be |
93 * shifted down by this much in the viewport. | 93 * shifted down by this much in the viewport. |
94 */ | 94 */ |
95 PDFViewer.MATERIAL_TOOLBAR_HEIGHT = 56; | 95 PDFViewer.MATERIAL_TOOLBAR_HEIGHT = 56; |
96 | 96 |
97 /** | 97 /** |
| 98 * The light-gray background color used for print preview. |
| 99 */ |
| 100 PDFViewer.LIGHT_BACKGROUND_COLOR = '0xFFCCCCCC'; |
| 101 |
| 102 /** |
| 103 * The dark-gray background color used for the regular viewer. |
| 104 */ |
| 105 PDFViewer.DARK_BACKGROUND_COLOR = '0xFF525659'; |
| 106 |
| 107 /** |
98 * Creates a new PDFViewer. There should only be one of these objects per | 108 * Creates a new PDFViewer. There should only be one of these objects per |
99 * document. | 109 * document. |
100 * @constructor | 110 * @constructor |
101 * @param {!BrowserApi} browserApi An object providing an API to the browser. | 111 * @param {!BrowserApi} browserApi An object providing an API to the browser. |
102 */ | 112 */ |
103 function PDFViewer(browserApi) { | 113 function PDFViewer(browserApi) { |
104 this.browserApi_ = browserApi; | 114 this.browserApi_ = browserApi; |
105 this.loadState_ = LoadState.LOADING; | 115 this.loadState_ = LoadState.LOADING; |
106 this.parentWindow_ = null; | 116 this.parentWindow_ = null; |
107 this.parentOrigin_ = null; | 117 this.parentOrigin_ = null; |
108 | 118 |
109 this.delayedScriptingMessages_ = []; | 119 this.delayedScriptingMessages_ = []; |
110 | 120 |
111 this.isPrintPreview_ = this.browserApi_.getStreamInfo().originalUrl.indexOf( | 121 this.isPrintPreview_ = this.browserApi_.getStreamInfo().originalUrl.indexOf( |
112 'chrome://print') == 0; | 122 'chrome://print') == 0; |
113 this.isMaterial_ = location.pathname.substring(1) === 'index-material.html'; | 123 this.isMaterial_ = location.pathname.substring(1) === 'index-material.html'; |
114 | 124 |
115 // The sizer element is placed behind the plugin element to cause scrollbars | 125 // The sizer element is placed behind the plugin element to cause scrollbars |
116 // to be displayed in the window. It is sized according to the document size | 126 // to be displayed in the window. It is sized according to the document size |
117 // of the pdf and zoom level. | 127 // of the pdf and zoom level. |
118 this.sizer_ = $('sizer'); | 128 this.sizer_ = $('sizer'); |
119 this.toolbar_ = $('toolbar'); | 129 this.toolbar_ = $('toolbar'); |
120 this.pageIndicator_ = $('page-indicator'); | 130 if (!this.isMaterial_ || this.isPrintPreview_) |
| 131 this.pageIndicator_ = $('page-indicator'); |
121 this.progressBar_ = $('progress-bar'); | 132 this.progressBar_ = $('progress-bar'); |
122 this.passwordScreen_ = $('password-screen'); | 133 this.passwordScreen_ = $('password-screen'); |
123 this.passwordScreen_.addEventListener('password-submitted', | 134 this.passwordScreen_.addEventListener('password-submitted', |
124 this.onPasswordSubmitted_.bind(this)); | 135 this.onPasswordSubmitted_.bind(this)); |
125 this.errorScreen_ = $('error-screen'); | 136 this.errorScreen_ = $('error-screen'); |
126 if (chrome.tabs) | 137 if (chrome.tabs) |
127 this.errorScreen_.reloadFn = chrome.tabs.reload; | 138 this.errorScreen_.reloadFn = chrome.tabs.reload; |
128 | 139 |
129 // Create the viewport. | 140 // Create the viewport. |
130 var topToolbarHeight = | 141 var topToolbarHeight = |
131 this.isMaterial_ ? PDFViewer.MATERIAL_TOOLBAR_HEIGHT : 0; | 142 (this.isMaterial_ && !this.isPrintPreview_) ? |
| 143 PDFViewer.MATERIAL_TOOLBAR_HEIGHT : 0; |
132 this.viewport_ = new Viewport(window, | 144 this.viewport_ = new Viewport(window, |
133 this.sizer_, | 145 this.sizer_, |
134 this.viewportChanged_.bind(this), | 146 this.viewportChanged_.bind(this), |
135 this.beforeZoom_.bind(this), | 147 this.beforeZoom_.bind(this), |
136 this.afterZoom_.bind(this), | 148 this.afterZoom_.bind(this), |
137 getScrollbarWidth(), | 149 getScrollbarWidth(), |
138 this.browserApi_.getDefaultZoom(), | 150 this.browserApi_.getDefaultZoom(), |
139 topToolbarHeight); | 151 topToolbarHeight); |
140 | 152 |
141 // Create the plugin object dynamically so we can set its src. The plugin | 153 // Create the plugin object dynamically so we can set its src. The plugin |
(...skipping 18 matching lines...) Expand all Loading... |
160 this.browserApi_.getStreamInfo().originalUrl); | 172 this.browserApi_.getStreamInfo().originalUrl); |
161 this.plugin_.setAttribute('stream-url', | 173 this.plugin_.setAttribute('stream-url', |
162 this.browserApi_.getStreamInfo().streamUrl); | 174 this.browserApi_.getStreamInfo().streamUrl); |
163 var headers = ''; | 175 var headers = ''; |
164 for (var header in this.browserApi_.getStreamInfo().responseHeaders) { | 176 for (var header in this.browserApi_.getStreamInfo().responseHeaders) { |
165 headers += header + ': ' + | 177 headers += header + ': ' + |
166 this.browserApi_.getStreamInfo().responseHeaders[header] + '\n'; | 178 this.browserApi_.getStreamInfo().responseHeaders[header] + '\n'; |
167 } | 179 } |
168 this.plugin_.setAttribute('headers', headers); | 180 this.plugin_.setAttribute('headers', headers); |
169 | 181 |
170 if (this.isMaterial_) { | 182 var backgroundColor = PDFViewer.DARK_BACKGROUND_COLOR; |
171 this.plugin_.setAttribute('is-material', ''); | 183 if (!this.isMaterial_) |
172 this.plugin_.setAttribute('top-toolbar-height', | 184 backgroundColor = PDFViewer.LIGHT_BACKGROUND_COLOR; |
173 PDFViewer.MATERIAL_TOOLBAR_HEIGHT); | 185 this.plugin_.setAttribute('background-color', backgroundColor); |
174 } | 186 this.plugin_.setAttribute('top-toolbar-height', topToolbarHeight); |
175 | 187 |
176 if (!this.browserApi_.getStreamInfo().embedded) | 188 if (!this.browserApi_.getStreamInfo().embedded) |
177 this.plugin_.setAttribute('full-frame', ''); | 189 this.plugin_.setAttribute('full-frame', ''); |
178 document.body.appendChild(this.plugin_); | 190 document.body.appendChild(this.plugin_); |
179 | 191 |
180 // Setup the button event listeners. | 192 // Setup the button event listeners. |
181 if (!this.isMaterial_) { | 193 if (!this.isMaterial_) { |
182 $('fit-to-width-button').addEventListener('click', | 194 $('fit-to-width-button').addEventListener('click', |
183 this.viewport_.fitToWidth.bind(this.viewport_)); | 195 this.viewport_.fitToWidth.bind(this.viewport_)); |
184 $('fit-to-page-button').addEventListener('click', | 196 $('fit-to-page-button').addEventListener('click', |
(...skipping 10 matching lines...) Expand all Loading... |
195 this.zoomToolbar_ = $('zoom-toolbar'); | 207 this.zoomToolbar_ = $('zoom-toolbar'); |
196 this.zoomToolbar_.addEventListener('fit-to-width', | 208 this.zoomToolbar_.addEventListener('fit-to-width', |
197 this.viewport_.fitToWidth.bind(this.viewport_)); | 209 this.viewport_.fitToWidth.bind(this.viewport_)); |
198 this.zoomToolbar_.addEventListener('fit-to-page', | 210 this.zoomToolbar_.addEventListener('fit-to-page', |
199 this.fitToPage_.bind(this)); | 211 this.fitToPage_.bind(this)); |
200 this.zoomToolbar_.addEventListener('zoom-in', | 212 this.zoomToolbar_.addEventListener('zoom-in', |
201 this.viewport_.zoomIn.bind(this.viewport_)); | 213 this.viewport_.zoomIn.bind(this.viewport_)); |
202 this.zoomToolbar_.addEventListener('zoom-out', | 214 this.zoomToolbar_.addEventListener('zoom-out', |
203 this.viewport_.zoomOut.bind(this.viewport_)); | 215 this.viewport_.zoomOut.bind(this.viewport_)); |
204 | 216 |
205 this.materialToolbar_ = $('material-toolbar'); | 217 if (!this.isPrintPreview_) { |
206 this.materialToolbar_.addEventListener('save', this.save_.bind(this)); | 218 this.materialToolbar_ = $('material-toolbar'); |
207 this.materialToolbar_.addEventListener('print', this.print_.bind(this)); | 219 this.materialToolbar_.addEventListener('save', this.save_.bind(this)); |
208 this.materialToolbar_.addEventListener('rotate-right', | 220 this.materialToolbar_.addEventListener('print', this.print_.bind(this)); |
209 this.rotateClockwise_.bind(this)); | 221 this.materialToolbar_.addEventListener('rotate-right', |
210 this.materialToolbar_.addEventListener('rotate-left', | 222 this.rotateClockwise_.bind(this)); |
211 this.rotateCounterClockwise_.bind(this)); | 223 this.materialToolbar_.addEventListener('rotate-left', |
| 224 this.rotateCounterClockwise_.bind(this)); |
| 225 // Must attach to mouseup on the plugin element, since it eats mousedown |
| 226 // and click events. |
| 227 this.plugin_.addEventListener('mouseup', |
| 228 this.materialToolbar_.hideDropdowns.bind(this.materialToolbar_)); |
| 229 } |
212 | 230 |
213 document.body.addEventListener('change-page', function(e) { | 231 document.body.addEventListener('change-page', function(e) { |
214 this.viewport_.goToPage(e.detail.page); | 232 this.viewport_.goToPage(e.detail.page); |
215 }.bind(this)); | 233 }.bind(this)); |
216 | 234 |
217 this.toolbarManager_ = | 235 this.toolbarManager_ = |
218 new ToolbarManager(window, this.materialToolbar_, this.zoomToolbar_); | 236 new ToolbarManager(window, this.materialToolbar_, this.zoomToolbar_); |
219 | |
220 // Must attach to mouseup on the plugin element, since it eats mousedown and | |
221 // click events. | |
222 this.plugin_.addEventListener( | |
223 'mouseup', | |
224 this.materialToolbar_.hideDropdowns.bind(this.materialToolbar_)); | |
225 } | 237 } |
226 | 238 |
227 // Set up the ZoomManager. | 239 // Set up the ZoomManager. |
228 this.zoomManager_ = new ZoomManager( | 240 this.zoomManager_ = new ZoomManager( |
229 this.viewport_, this.browserApi_.setZoom.bind(this.browserApi_), | 241 this.viewport_, this.browserApi_.setZoom.bind(this.browserApi_), |
230 this.browserApi_.getInitialZoom()); | 242 this.browserApi_.getInitialZoom()); |
231 this.browserApi_.addZoomEventListener( | 243 this.browserApi_.addZoomEventListener( |
232 this.zoomManager_.onBrowserZoomChange.bind(this.zoomManager_)); | 244 this.zoomManager_.onBrowserZoomChange.bind(this.zoomManager_)); |
233 | 245 |
234 // Setup the keyboard event listener. | 246 // Setup the keyboard event listener. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 case 65: // a key. | 358 case 65: // a key. |
347 if (e.ctrlKey || e.metaKey) { | 359 if (e.ctrlKey || e.metaKey) { |
348 this.plugin_.postMessage({ | 360 this.plugin_.postMessage({ |
349 type: 'selectAll' | 361 type: 'selectAll' |
350 }); | 362 }); |
351 // Since we do selection ourselves. | 363 // Since we do selection ourselves. |
352 e.preventDefault(); | 364 e.preventDefault(); |
353 } | 365 } |
354 return; | 366 return; |
355 case 71: // g key. | 367 case 71: // g key. |
356 if (this.isMaterial_ && (e.ctrlKey || e.metaKey)) { | 368 if (this.isMaterial_ && this.materialToolbar_ && |
| 369 (e.ctrlKey || e.metaKey)) { |
357 this.toolbarManager_.showToolbars(); | 370 this.toolbarManager_.showToolbars(); |
358 this.materialToolbar_.selectPageNumber(); | 371 this.materialToolbar_.selectPageNumber(); |
359 // To prevent the default "find text" behaviour in Chrome. | 372 // To prevent the default "find text" behaviour in Chrome. |
360 e.preventDefault(); | 373 e.preventDefault(); |
361 } | 374 } |
362 return; | 375 return; |
363 case 219: // left bracket. | 376 case 219: // left bracket. |
364 if (e.ctrlKey) | 377 if (e.ctrlKey) |
365 this.rotateCounterClockwise_(); | 378 this.rotateCounterClockwise_(); |
366 return; | 379 return; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 this.viewport_.setZoom(viewportPosition.zoom); | 494 this.viewport_.setZoom(viewportPosition.zoom); |
482 }, | 495 }, |
483 | 496 |
484 /** | 497 /** |
485 * @private | 498 * @private |
486 * Update the loading progress of the document in response to a progress | 499 * Update the loading progress of the document in response to a progress |
487 * message being received from the plugin. | 500 * message being received from the plugin. |
488 * @param {number} progress the progress as a percentage. | 501 * @param {number} progress the progress as a percentage. |
489 */ | 502 */ |
490 updateProgress_: function(progress) { | 503 updateProgress_: function(progress) { |
491 if (this.isMaterial_) | 504 if (this.isMaterial_) { |
492 this.materialToolbar_.loadProgress = progress; | 505 if (this.materialToolbar_) |
493 else | 506 this.materialToolbar_.loadProgress = progress; |
| 507 } else { |
494 this.progressBar_.progress = progress; | 508 this.progressBar_.progress = progress; |
| 509 } |
495 | 510 |
496 if (progress == -1) { | 511 if (progress == -1) { |
497 // Document load failed. | 512 // Document load failed. |
498 this.errorScreen_.show(); | 513 this.errorScreen_.show(); |
499 this.sizer_.style.display = 'none'; | 514 this.sizer_.style.display = 'none'; |
500 if (!this.isMaterial_) | 515 if (!this.isMaterial_) |
501 this.toolbar_.style.visibility = 'hidden'; | 516 this.toolbar_.style.visibility = 'hidden'; |
502 if (this.passwordScreen_.active) { | 517 if (this.passwordScreen_.active) { |
503 this.passwordScreen_.deny(); | 518 this.passwordScreen_.deny(); |
504 this.passwordScreen_.active = false; | 519 this.passwordScreen_.active = false; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 handlePluginMessage_: function(message) { | 558 handlePluginMessage_: function(message) { |
544 switch (message.data.type.toString()) { | 559 switch (message.data.type.toString()) { |
545 case 'documentDimensions': | 560 case 'documentDimensions': |
546 this.documentDimensions_ = message.data; | 561 this.documentDimensions_ = message.data; |
547 this.viewport_.setDocumentDimensions(this.documentDimensions_); | 562 this.viewport_.setDocumentDimensions(this.documentDimensions_); |
548 // If we received the document dimensions, the password was good so we | 563 // If we received the document dimensions, the password was good so we |
549 // can dismiss the password screen. | 564 // can dismiss the password screen. |
550 if (this.passwordScreen_.active) | 565 if (this.passwordScreen_.active) |
551 this.passwordScreen_.accept(); | 566 this.passwordScreen_.accept(); |
552 | 567 |
| 568 if (this.pageIndicator_) |
| 569 this.pageIndicator_.initialFadeIn(); |
| 570 |
553 if (this.isMaterial_) { | 571 if (this.isMaterial_) { |
554 this.materialToolbar_.docLength = | 572 if (this.materialToolbar_) { |
555 this.documentDimensions_.pageDimensions.length; | 573 this.materialToolbar_.docLength = |
| 574 this.documentDimensions_.pageDimensions.length; |
| 575 } |
556 } else { | 576 } else { |
557 this.pageIndicator_.initialFadeIn(); | |
558 this.toolbar_.initialFadeIn(); | 577 this.toolbar_.initialFadeIn(); |
559 } | 578 } |
560 break; | 579 break; |
561 case 'email': | 580 case 'email': |
562 var href = 'mailto:' + message.data.to + '?cc=' + message.data.cc + | 581 var href = 'mailto:' + message.data.to + '?cc=' + message.data.cc + |
563 '&bcc=' + message.data.bcc + '&subject=' + message.data.subject + | 582 '&bcc=' + message.data.bcc + '&subject=' + message.data.subject + |
564 '&body=' + message.data.body; | 583 '&body=' + message.data.body; |
565 window.location.href = href; | 584 window.location.href = href; |
566 break; | 585 break; |
567 case 'getAccessibilityJSONReply': | 586 case 'getAccessibilityJSONReply': |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 chrome.mimeHandlerPrivate.abortStream(); | 631 chrome.mimeHandlerPrivate.abortStream(); |
613 break; | 632 break; |
614 case 'metadata': | 633 case 'metadata': |
615 if (message.data.title) { | 634 if (message.data.title) { |
616 document.title = message.data.title; | 635 document.title = message.data.title; |
617 } else { | 636 } else { |
618 document.title = | 637 document.title = |
619 getFilenameFromURL(this.browserApi_.getStreamInfo().originalUrl); | 638 getFilenameFromURL(this.browserApi_.getStreamInfo().originalUrl); |
620 } | 639 } |
621 this.bookmarks_ = message.data.bookmarks; | 640 this.bookmarks_ = message.data.bookmarks; |
622 if (this.isMaterial_) { | 641 if (this.isMaterial_ && this.materialToolbar_) { |
623 this.materialToolbar_.docTitle = document.title; | 642 this.materialToolbar_.docTitle = document.title; |
624 this.materialToolbar_.bookmarks = this.bookmarks; | 643 this.materialToolbar_.bookmarks = this.bookmarks; |
625 } | 644 } |
626 break; | 645 break; |
627 case 'setIsSelecting': | 646 case 'setIsSelecting': |
628 this.viewportScroller_.setEnableScrolling(message.data.isSelecting); | 647 this.viewportScroller_.setEnableScrolling(message.data.isSelecting); |
629 break; | 648 break; |
630 case 'getNamedDestinationReply': | 649 case 'getNamedDestinationReply': |
631 this.paramsParser_.onNamedDestinationReceived( | 650 this.paramsParser_.onNamedDestinationReceived( |
632 message.data.pageNumber); | 651 message.data.pageNumber); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 this.toolbar_.style.bottom = toolbarBottom + 'px'; | 716 this.toolbar_.style.bottom = toolbarBottom + 'px'; |
698 // Hide the toolbar if it doesn't fit in the viewport. | 717 // Hide the toolbar if it doesn't fit in the viewport. |
699 if (this.toolbar_.offsetLeft < 0 || this.toolbar_.offsetTop < 0) | 718 if (this.toolbar_.offsetLeft < 0 || this.toolbar_.offsetTop < 0) |
700 this.toolbar_.style.visibility = 'hidden'; | 719 this.toolbar_.style.visibility = 'hidden'; |
701 else | 720 else |
702 this.toolbar_.style.visibility = 'visible'; | 721 this.toolbar_.style.visibility = 'visible'; |
703 } | 722 } |
704 | 723 |
705 // Update the page indicator. | 724 // Update the page indicator. |
706 var visiblePage = this.viewport_.getMostVisiblePage(); | 725 var visiblePage = this.viewport_.getMostVisiblePage(); |
707 if (this.isMaterial_) { | 726 |
| 727 if (this.materialToolbar_) |
708 this.materialToolbar_.pageNo = visiblePage + 1; | 728 this.materialToolbar_.pageNo = visiblePage + 1; |
709 } else { | 729 |
| 730 // TODO(raymes): Give pageIndicator_ the same API as materialToolbar_. |
| 731 if (this.pageIndicator_) { |
710 this.pageIndicator_.index = visiblePage; | 732 this.pageIndicator_.index = visiblePage; |
711 if (this.documentDimensions_.pageDimensions.length > 1 && | 733 if (this.documentDimensions_.pageDimensions.length > 1 && |
712 hasScrollbars.vertical) { | 734 hasScrollbars.vertical) { |
713 this.pageIndicator_.style.visibility = 'visible'; | 735 this.pageIndicator_.style.visibility = 'visible'; |
714 } else { | 736 } else { |
715 this.pageIndicator_.style.visibility = 'hidden'; | 737 this.pageIndicator_.style.visibility = 'hidden'; |
716 } | 738 } |
717 } | 739 } |
718 | 740 |
719 var visiblePageDimensions = this.viewport_.getPageScreenRect(visiblePage); | 741 var visiblePageDimensions = this.viewport_.getPageScreenRect(visiblePage); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 this.lastViewportPosition_ = this.viewport_.position; | 811 this.lastViewportPosition_ = this.viewport_.position; |
790 | 812 |
791 // TODO(raymes): Disable these properly in the plugin. | 813 // TODO(raymes): Disable these properly in the plugin. |
792 var printButton = $('print-button'); | 814 var printButton = $('print-button'); |
793 if (printButton) | 815 if (printButton) |
794 printButton.parentNode.removeChild(printButton); | 816 printButton.parentNode.removeChild(printButton); |
795 var saveButton = $('save-button'); | 817 var saveButton = $('save-button'); |
796 if (saveButton) | 818 if (saveButton) |
797 saveButton.parentNode.removeChild(saveButton); | 819 saveButton.parentNode.removeChild(saveButton); |
798 | 820 |
799 if (!this.isMaterial_) | 821 this.pageIndicator_.pageLabels = message.data.pageNumbers; |
800 this.pageIndicator_.pageLabels = message.data.pageNumbers; | |
801 | 822 |
802 this.plugin_.postMessage({ | 823 this.plugin_.postMessage({ |
803 type: 'resetPrintPreviewMode', | 824 type: 'resetPrintPreviewMode', |
804 url: message.data.url, | 825 url: message.data.url, |
805 grayscale: message.data.grayscale, | 826 grayscale: message.data.grayscale, |
806 // If the PDF isn't modifiable we send 0 as the page count so that no | 827 // If the PDF isn't modifiable we send 0 as the page count so that no |
807 // blank placeholder pages get appended to the PDF. | 828 // blank placeholder pages get appended to the PDF. |
808 pageCount: (message.data.modifiable ? | 829 pageCount: (message.data.modifiable ? |
809 message.data.pageNumbers.length : 0) | 830 message.data.pageNumbers.length : 0) |
810 }); | 831 }); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 * Each bookmark is an Object containing a: | 872 * Each bookmark is an Object containing a: |
852 * - title | 873 * - title |
853 * - page (optional) | 874 * - page (optional) |
854 * - array of children (themselves bookmarks) | 875 * - array of children (themselves bookmarks) |
855 * @type {Array} the top-level bookmarks of the PDF. | 876 * @type {Array} the top-level bookmarks of the PDF. |
856 */ | 877 */ |
857 get bookmarks() { | 878 get bookmarks() { |
858 return this.bookmarks_; | 879 return this.bookmarks_; |
859 } | 880 } |
860 }; | 881 }; |
OLD | NEW |