1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // TODO(rltoscano): Move data/* into print_preview.data namespace
7 <include src
="component.js">
8 <include src
="print_preview_focus_manager.js">
10 cr
.define('print_preview', function() {
14 * Container class for Chromium's print preview.
16 * @extends {print_preview.Component}
18 function PrintPreview() {
19 print_preview
.Component
.call(this);
22 * Used to communicate with Chromium's print system.
23 * @type {!print_preview.NativeLayer}
26 this.nativeLayer_
= new print_preview
.NativeLayer();
29 * Event target that contains information about the logged in user.
30 * @type {!print_preview.UserInfo}
33 this.userInfo_
= new print_preview
.UserInfo();
37 * @type {!print_preview.AppState}
40 this.appState_
= new print_preview
.AppState();
43 * Data model that holds information about the document to print.
44 * @type {!print_preview.DocumentInfo}
47 this.documentInfo_
= new print_preview
.DocumentInfo();
50 * Data store which holds print destinations.
51 * @type {!print_preview.DestinationStore}
54 this.destinationStore_
= new print_preview
.DestinationStore(
55 this.nativeLayer_
, this.userInfo_
, this.appState_
);
58 * Data store which holds printer sharing invitations.
59 * @type {!print_preview.InvitationStore}
62 this.invitationStore_
= new print_preview
.InvitationStore(this.userInfo_
);
65 * Storage of the print ticket used to create the print job.
66 * @type {!print_preview.PrintTicketStore}
69 this.printTicketStore_
= new print_preview
.PrintTicketStore(
70 this.destinationStore_
, this.appState_
, this.documentInfo_
);
73 * Holds the print and cancel buttons and renders some document statistics.
74 * @type {!print_preview.PrintHeader}
77 this.printHeader_
= new print_preview
.PrintHeader(
78 this.printTicketStore_
, this.destinationStore_
);
79 this.addChild(this.printHeader_
);
82 * Component used to search for print destinations.
83 * @type {!print_preview.DestinationSearch}
86 this.destinationSearch_
= new print_preview
.DestinationSearch(
87 this.destinationStore_
, this.invitationStore_
, this.userInfo_
);
88 this.addChild(this.destinationSearch_
);
91 * Component that renders the print destination.
92 * @type {!print_preview.DestinationSettings}
95 this.destinationSettings_
= new print_preview
.DestinationSettings(
96 this.destinationStore_
);
97 this.addChild(this.destinationSettings_
);
100 * Component that renders UI for entering in page range.
101 * @type {!print_preview.PageSettings}
104 this.pageSettings_
= new print_preview
.PageSettings(
105 this.printTicketStore_
.pageRange
);
106 this.addChild(this.pageSettings_
);
109 * Component that renders the copies settings.
110 * @type {!print_preview.CopiesSettings}
113 this.copiesSettings_
= new print_preview
.CopiesSettings(
114 this.printTicketStore_
.copies
, this.printTicketStore_
.collate
);
115 this.addChild(this.copiesSettings_
);
118 * Component that renders the media size settings.
119 * @type {!print_preview.MediaSizeSettings}
122 this.mediaSizeSettings_
=
123 new print_preview
.MediaSizeSettings(this.printTicketStore_
.mediaSize
);
124 this.addChild(this.mediaSizeSettings_
);
127 * Component that renders the layout settings.
128 * @type {!print_preview.LayoutSettings}
131 this.layoutSettings_
=
132 new print_preview
.LayoutSettings(this.printTicketStore_
.landscape
);
133 this.addChild(this.layoutSettings_
);
136 * Component that renders the color options.
137 * @type {!print_preview.ColorSettings}
140 this.colorSettings_
=
141 new print_preview
.ColorSettings(this.printTicketStore_
.color
);
142 this.addChild(this.colorSettings_
);
145 * Component that renders a select box for choosing margin settings.
146 * @type {!print_preview.MarginSettings}
149 this.marginSettings_
=
150 new print_preview
.MarginSettings(this.printTicketStore_
.marginsType
);
151 this.addChild(this.marginSettings_
);
154 * Component that renders the DPI settings.
155 * @type {!print_preview.DpiSettings}
159 new print_preview
.DpiSettings(this.printTicketStore_
.dpi
);
160 this.addChild(this.dpiSettings_
);
163 * Component that renders miscellaneous print options.
164 * @type {!print_preview.OtherOptionsSettings}
167 this.otherOptionsSettings_
= new print_preview
.OtherOptionsSettings(
168 this.printTicketStore_
.duplex
,
169 this.printTicketStore_
.fitToPage
,
170 this.printTicketStore_
.cssBackground
,
171 this.printTicketStore_
.selectionOnly
,
172 this.printTicketStore_
.headerFooter
,
173 this.printTicketStore_
.distillPage
);
174 this.addChild(this.otherOptionsSettings_
);
177 * Component that renders the advanced options button.
178 * @type {!print_preview.AdvancedOptionsSettings}
181 this.advancedOptionsSettings_
= new print_preview
.AdvancedOptionsSettings(
182 this.printTicketStore_
.vendorItems
, this.destinationStore_
);
183 this.addChild(this.advancedOptionsSettings_
);
186 * Component used to search for print destinations.
187 * @type {!print_preview.AdvancedSettings}
190 this.advancedSettings_
= new print_preview
.AdvancedSettings(
191 this.printTicketStore_
);
192 this.addChild(this.advancedSettings_
);
194 var settingsSections
= [
195 this.destinationSettings_
,
197 this.copiesSettings_
,
198 this.mediaSizeSettings_
,
199 this.layoutSettings_
,
200 this.marginSettings_
,
203 this.otherOptionsSettings_
,
204 this.advancedOptionsSettings_
];
206 * Component representing more/less settings button.
207 * @type {!print_preview.MoreSettings}
210 this.moreSettings_
= new print_preview
.MoreSettings(
211 this.destinationStore_
, settingsSections
);
212 this.addChild(this.moreSettings_
);
215 * Area of the UI that holds the print preview.
216 * @type {!print_preview.PreviewArea}
219 this.previewArea_
= new print_preview
.PreviewArea(this.destinationStore_
,
220 this.printTicketStore_
,
223 this.addChild(this.previewArea_
);
226 * Interface to the Google Cloud Print API. Null if Google Cloud Print
227 * integration is disabled.
228 * @type {cloudprint.CloudPrintInterface}
231 this.cloudPrintInterface_
= null;
234 * Whether in kiosk mode where print preview can print automatically without
235 * user intervention. See http://crbug.com/31395. Print will start when
236 * both the print ticket has been initialized, and an initial printer has
241 this.isInKioskAutoPrintMode_
= false;
244 * Whether Print Preview is in App Kiosk mode, basically, use only printers
245 * available for the device.
249 this.isInAppKioskMode_
= false;
252 * Whether Print with System Dialog link should be hidden. Overrides the
253 * default rules for System dialog link visibility.
257 this.hideSystemDialogLink_
= true;
260 * State of the print preview UI.
261 * @type {print_preview.PrintPreview.UiState_}
264 this.uiState_
= PrintPreview
.UiState_
.INITIALIZING
;
267 * Whether document preview generation is in progress.
271 this.isPreviewGenerationInProgress_
= true;
274 * Whether to show system dialog before next printing.
278 this.showSystemDialogBeforeNextPrint_
= false;
282 * States of the print preview.
286 PrintPreview
.UiState_
= {
287 INITIALIZING
: 'initializing',
289 OPENING_PDF_PREVIEW
: 'opening-pdf-preview',
290 OPENING_NATIVE_PRINT_DIALOG
: 'opening-native-print-dialog',
291 PRINTING
: 'printing',
292 FILE_SELECTION
: 'file-selection',
298 * What can happen when print preview tries to print.
302 PrintPreview
.PrintAttemptResult_
= {
303 NOT_READY
: 'not-ready',
305 READY_WAITING_FOR_PREVIEW
: 'ready-waiting-for-preview'
308 PrintPreview
.prototype = {
309 __proto__
: print_preview
.Component
.prototype,
311 /** Sets up the page and print preview by getting the printer list. */
312 initialize: function() {
313 this.decorate($('print-preview'));
314 if (!this.previewArea_
.hasCompatiblePlugin
) {
315 this.setIsEnabled_(false);
317 this.nativeLayer_
.startGetInitialSettings();
318 print_preview
.PrintPreviewFocusManager
.getInstance().initialize();
319 cr
.ui
.FocusOutlineManager
.forDocument(document
);
323 enterDocument: function() {
324 // Native layer events.
327 print_preview
.NativeLayer
.EventType
.INITIAL_SETTINGS_SET
,
328 this.onInitialSettingsSet_
.bind(this));
331 print_preview
.NativeLayer
.EventType
.CLOUD_PRINT_ENABLE
,
332 this.onCloudPrintEnable_
.bind(this));
335 print_preview
.NativeLayer
.EventType
.PRINT_TO_CLOUD
,
336 this.onPrintToCloud_
.bind(this));
339 print_preview
.NativeLayer
.EventType
.FILE_SELECTION_CANCEL
,
340 this.onFileSelectionCancel_
.bind(this));
343 print_preview
.NativeLayer
.EventType
.FILE_SELECTION_COMPLETE
,
344 this.onFileSelectionComplete_
.bind(this));
347 print_preview
.NativeLayer
.EventType
.SETTINGS_INVALID
,
348 this.onSettingsInvalid_
.bind(this));
351 print_preview
.NativeLayer
.EventType
.PRINT_PRESET_OPTIONS
,
352 this.onPrintPresetOptionsFromDocument_
.bind(this));
355 print_preview
.NativeLayer
.EventType
.PRIVET_PRINT_FAILED
,
356 this.onPrivetPrintFailed_
.bind(this));
359 print_preview
.NativeLayer
.EventType
.MANIPULATE_SETTINGS_FOR_TEST
,
360 this.onManipulateSettingsForTest_
.bind(this));
363 print_preview
.NativeLayer
.EventType
.ALLOW_DISTILL_PAGE
,
364 this.onAllowDistillPage_
.bind(this));
366 if ($('system-dialog-link')) {
368 $('system-dialog-link'),
370 this.openSystemPrintDialog_
.bind(this));
372 if ($('open-pdf-in-preview-link')) {
374 $('open-pdf-in-preview-link'),
376 this.onOpenPdfInPreviewLinkClick_
.bind(this));
381 print_preview
.PreviewArea
.EventType
.PREVIEW_GENERATION_IN_PROGRESS
,
382 this.onPreviewGenerationInProgress_
.bind(this));
385 print_preview
.PreviewArea
.EventType
.PREVIEW_GENERATION_DONE
,
386 this.onPreviewGenerationDone_
.bind(this));
389 print_preview
.PreviewArea
.EventType
.PREVIEW_GENERATION_FAIL
,
390 this.onPreviewGenerationFail_
.bind(this));
393 print_preview
.PreviewArea
.EventType
.OPEN_SYSTEM_DIALOG_CLICK
,
394 this.openSystemPrintDialog_
.bind(this));
397 this.destinationStore_
,
398 print_preview
.DestinationStore
.EventType
.
399 SELECTED_DESTINATION_CAPABILITIES_READY
,
400 this.printIfReady_
.bind(this));
402 this.destinationStore_
,
403 print_preview
.DestinationStore
.EventType
.DESTINATION_SELECT
,
404 this.onDestinationSelect_
.bind(this));
406 this.destinationStore_
,
407 print_preview
.DestinationStore
.EventType
.DESTINATION_SEARCH_DONE
,
408 this.onDestinationSearchDone_
.bind(this));
412 print_preview
.PrintHeader
.EventType
.PRINT_BUTTON_CLICK
,
413 this.onPrintButtonClick_
.bind(this));
416 print_preview
.PrintHeader
.EventType
.CANCEL_BUTTON_CLICK
,
417 this.onCancelButtonClick_
.bind(this));
419 this.tracker
.add(window
, 'keydown', this.onKeyDown_
.bind(this));
420 this.previewArea_
.setPluginKeyEventCallback(this.onKeyDown_
.bind(this));
423 this.destinationSettings_
,
424 print_preview
.DestinationSettings
.EventType
.CHANGE_BUTTON_ACTIVATE
,
425 this.onDestinationChangeButtonActivate_
.bind(this));
428 this.destinationSearch_
,
429 print_preview
.DestinationSearch
.EventType
.MANAGE_CLOUD_DESTINATIONS
,
430 this.onManageCloudDestinationsActivated_
.bind(this));
432 this.destinationSearch_
,
433 print_preview
.DestinationSearch
.EventType
.MANAGE_LOCAL_DESTINATIONS
,
434 this.onManageLocalDestinationsActivated_
.bind(this));
436 this.destinationSearch_
,
437 print_preview
.DestinationSearch
.EventType
.ADD_ACCOUNT
,
438 this.onCloudPrintSignInActivated_
.bind(this, true /*addAccount*/));
440 this.destinationSearch_
,
441 print_preview
.DestinationSearch
.EventType
.SIGN_IN
,
442 this.onCloudPrintSignInActivated_
.bind(this, false /*addAccount*/));
444 this.destinationSearch_
,
445 print_preview
.DestinationListItem
.EventType
.REGISTER_PROMO_CLICKED
,
446 this.onCloudPrintRegisterPromoClick_
.bind(this));
449 this.advancedOptionsSettings_
,
450 print_preview
.AdvancedOptionsSettings
.EventType
.BUTTON_ACTIVATED
,
451 this.onAdvancedOptionsButtonActivated_
.bind(this));
453 // TODO(rltoscano): Move no-destinations-promo into its own component
454 // instead being part of PrintPreview.
456 this.getChildElement('#no-destinations-promo .close-button'),
458 this.onNoDestinationsPromoClose_
.bind(this));
460 this.getChildElement('#no-destinations-promo .not-now-button'),
462 this.onNoDestinationsPromoClose_
.bind(this));
464 this.getChildElement('#no-destinations-promo .add-printer-button'),
466 this.onNoDestinationsPromoClick_
.bind(this));
470 decorateInternal: function() {
471 this.printHeader_
.decorate($('print-header'));
472 this.destinationSearch_
.decorate($('destination-search'));
473 this.destinationSettings_
.decorate($('destination-settings'));
474 this.pageSettings_
.decorate($('page-settings'));
475 this.copiesSettings_
.decorate($('copies-settings'));
476 this.mediaSizeSettings_
.decorate($('media-size-settings'));
477 this.layoutSettings_
.decorate($('layout-settings'));
478 this.colorSettings_
.decorate($('color-settings'));
479 this.marginSettings_
.decorate($('margin-settings'));
480 this.dpiSettings_
.decorate($('dpi-settings'));
481 this.otherOptionsSettings_
.decorate($('other-options-settings'));
482 this.advancedOptionsSettings_
.decorate($('advanced-options-settings'));
483 this.advancedSettings_
.decorate($('advanced-settings'));
484 this.moreSettings_
.decorate($('more-settings'));
485 this.previewArea_
.decorate($('preview-area'));
489 * Sets whether the controls in the print preview are enabled.
490 * @param {boolean} isEnabled Whether the controls in the print preview are
494 setIsEnabled_: function(isEnabled
) {
495 if ($('system-dialog-link'))
496 $('system-dialog-link').classList
.toggle('disabled', !isEnabled
);
497 if ($('open-pdf-in-preview-link'))
498 $('open-pdf-in-preview-link').classList
.toggle('disabled', !isEnabled
);
499 this.printHeader_
.isEnabled
= isEnabled
;
500 this.destinationSettings_
.isEnabled
= isEnabled
;
501 this.pageSettings_
.isEnabled
= isEnabled
;
502 this.copiesSettings_
.isEnabled
= isEnabled
;
503 this.mediaSizeSettings_
.isEnabled
= isEnabled
;
504 this.layoutSettings_
.isEnabled
= isEnabled
;
505 this.colorSettings_
.isEnabled
= isEnabled
;
506 this.marginSettings_
.isEnabled
= isEnabled
;
507 this.dpiSettings_
.isEnabled
= isEnabled
;
508 this.otherOptionsSettings_
.isEnabled
= isEnabled
;
509 this.advancedOptionsSettings_
.isEnabled
= isEnabled
;
513 * Prints the document or launches a pdf preview on the local system.
514 * @param {boolean} isPdfPreview Whether to launch the pdf preview.
517 printDocumentOrOpenPdfPreview_: function(isPdfPreview
) {
518 assert(this.uiState_
== PrintPreview
.UiState_
.READY
,
519 'Print document request received when not in ready state: ' +
522 this.uiState_
= PrintPreview
.UiState_
.OPENING_PDF_PREVIEW
;
523 } else if (this.destinationStore_
.selectedDestination
.id
==
524 print_preview
.Destination
.GooglePromotedId
.SAVE_AS_PDF
) {
525 this.uiState_
= PrintPreview
.UiState_
.FILE_SELECTION
;
527 this.uiState_
= PrintPreview
.UiState_
.PRINTING
;
529 this.setIsEnabled_(false);
530 this.printHeader_
.isCancelButtonEnabled
= true;
531 var printAttemptResult
= this.printIfReady_();
532 if (printAttemptResult
== PrintPreview
.PrintAttemptResult_
.PRINTED
||
533 printAttemptResult
==
534 PrintPreview
.PrintAttemptResult_
.READY_WAITING_FOR_PREVIEW
) {
535 if ((this.destinationStore_
.selectedDestination
.isLocal
&&
536 !this.destinationStore_
.selectedDestination
.isPrivet
&&
537 !this.destinationStore_
.selectedDestination
.isExtension
&&
538 this.destinationStore_
.selectedDestination
.id
!=
539 print_preview
.Destination
.GooglePromotedId
.SAVE_AS_PDF
) ||
540 this.uiState_
== PrintPreview
.UiState_
.OPENING_PDF_PREVIEW
) {
541 // Hide the dialog for now. The actual print command will be issued
542 // when the preview generation is done.
543 this.nativeLayer_
.startHideDialog();
549 * Attempts to print if needed and if ready.
550 * @return {PrintPreview.PrintAttemptResult_} Attempt result.
553 printIfReady_: function() {
555 (this.uiState_
== PrintPreview
.UiState_
.PRINTING
||
556 this.uiState_
== PrintPreview
.UiState_
.OPENING_PDF_PREVIEW
||
557 this.uiState_
== PrintPreview
.UiState_
.FILE_SELECTION
||
558 this.isInKioskAutoPrintMode_
) &&
559 this.destinationStore_
.selectedDestination
&&
560 this.destinationStore_
.selectedDestination
.capabilities
;
562 return PrintPreview
.PrintAttemptResult_
.NOT_READY
;
564 if (this.isPreviewGenerationInProgress_
) {
565 return PrintPreview
.PrintAttemptResult_
.READY_WAITING_FOR_PREVIEW
;
567 assert(this.printTicketStore_
.isTicketValid(),
568 'Trying to print with invalid ticket');
569 if (getIsVisible(this.moreSettings_
.getElement())) {
570 new print_preview
.PrintSettingsUiMetricsContext().record(
571 this.moreSettings_
.isExpanded
?
572 print_preview
.Metrics
.PrintSettingsUiBucket
.
573 PRINT_WITH_SETTINGS_EXPANDED
:
574 print_preview
.Metrics
.PrintSettingsUiBucket
.
575 PRINT_WITH_SETTINGS_COLLAPSED
);
577 this.nativeLayer_
.startPrint(
578 this.destinationStore_
.selectedDestination
,
579 this.printTicketStore_
,
580 this.cloudPrintInterface_
,
582 this.uiState_
== PrintPreview
.UiState_
.OPENING_PDF_PREVIEW
,
583 this.showSystemDialogBeforeNextPrint_
);
584 this.showSystemDialogBeforeNextPrint_
= false;
585 return PrintPreview
.PrintAttemptResult_
.PRINTED
;
589 * Closes the print preview.
594 this.uiState_
= PrintPreview
.UiState_
.CLOSING
;
595 this.nativeLayer_
.startCloseDialog();
599 * Opens the native system print dialog after disabling all controls.
602 openSystemPrintDialog_: function() {
603 if (!this.shouldShowSystemDialogLink_())
605 if ($('system-dialog-link').classList
.contains('disabled'))
608 this.showSystemDialogBeforeNextPrint_
= true;
609 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
612 setIsVisible(getRequiredElement('system-dialog-throbber'), true);
613 this.setIsEnabled_(false);
614 this.uiState_
= PrintPreview
.UiState_
.OPENING_NATIVE_PRINT_DIALOG
;
615 this.nativeLayer_
.startShowSystemDialog();
619 * Called when the native layer has initial settings to set. Sets the
620 * initial settings of the print preview and begins fetching print
622 * @param {Event} event Contains the initial print preview settings
623 * persisted through the session.
626 onInitialSettingsSet_: function(event
) {
627 assert(this.uiState_
== PrintPreview
.UiState_
.INITIALIZING
,
628 'Updating initial settings when not in initializing state: ' +
630 this.uiState_
= PrintPreview
.UiState_
.READY
;
632 var settings
= event
.initialSettings
;
633 this.isInKioskAutoPrintMode_
= settings
.isInKioskAutoPrintMode
;
634 this.isInAppKioskMode_
= settings
.isInAppKioskMode
;
636 // The following components must be initialized in this order.
638 settings
.serializedAppStateStr
,
639 settings
.systemDefaultDestinationId
);
640 this.documentInfo_
.init(
641 settings
.isDocumentModifiable
,
642 settings
.documentTitle
,
643 settings
.documentHasSelection
);
644 this.printTicketStore_
.init(
645 settings
.thousandsDelimeter
,
646 settings
.decimalDelimeter
,
648 settings
.selectionOnly
);
649 this.destinationStore_
.init(settings
.isInAppKioskMode
);
650 this.appState_
.setInitialized();
652 $('document-title').innerText
= settings
.documentTitle
;
653 this.hideSystemDialogLink_
= settings
.hidePrintWithSystemDialogLink
||
654 settings
.isInAppKioskMode
;
655 if ($('system-dialog-link')) {
656 setIsVisible($('system-dialog-link'),
657 this.shouldShowSystemDialogLink_());
662 * Calls when the native layer enables Google Cloud Print integration.
663 * Fetches the user's cloud printers.
664 * @param {Event} event Contains the base URL of the Google Cloud Print
668 onCloudPrintEnable_: function(event
) {
669 this.cloudPrintInterface_
= new cloudprint
.CloudPrintInterface(
670 event
.baseCloudPrintUrl
,
675 this.cloudPrintInterface_
,
676 cloudprint
.CloudPrintInterface
.EventType
.SUBMIT_DONE
,
677 this.onCloudPrintSubmitDone_
.bind(this));
679 this.cloudPrintInterface_
,
680 cloudprint
.CloudPrintInterface
.EventType
.SEARCH_FAILED
,
681 this.onCloudPrintError_
.bind(this));
683 this.cloudPrintInterface_
,
684 cloudprint
.CloudPrintInterface
.EventType
.SUBMIT_FAILED
,
685 this.onCloudPrintError_
.bind(this));
687 this.cloudPrintInterface_
,
688 cloudprint
.CloudPrintInterface
.EventType
.PRINTER_FAILED
,
689 this.onCloudPrintError_
.bind(this));
691 this.cloudPrintInterface_
,
692 cloudprint
.CloudPrintInterface
.EventType
.
693 UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED
,
694 this.onCloudPrintError_
.bind(this));
696 this.destinationStore_
.setCloudPrintInterface(this.cloudPrintInterface_
);
697 this.invitationStore_
.setCloudPrintInterface(this.cloudPrintInterface_
);
698 if (this.destinationSearch_
.getIsVisible()) {
699 this.destinationStore_
.startLoadCloudDestinations();
700 this.invitationStore_
.startLoadingInvitations();
705 * Called from the native layer when ready to print to Google Cloud Print.
706 * @param {Event} event Contains the body to send in the HTTP request.
709 onPrintToCloud_: function(event
) {
710 assert(this.uiState_
== PrintPreview
.UiState_
.PRINTING
,
711 'Document ready to be sent to the cloud when not in printing ' +
712 'state: ' + this.uiState_
);
713 assert(this.cloudPrintInterface_
!= null,
714 'Google Cloud Print is not enabled');
715 this.cloudPrintInterface_
.submit(
716 this.destinationStore_
.selectedDestination
,
717 this.printTicketStore_
,
723 * Called from the native layer when the user cancels the save-to-pdf file
727 onFileSelectionCancel_: function() {
728 assert(this.uiState_
== PrintPreview
.UiState_
.FILE_SELECTION
,
729 'File selection cancelled when not in file-selection state: ' +
731 this.setIsEnabled_(true);
732 this.uiState_
= PrintPreview
.UiState_
.READY
;
736 * Called from the native layer when save-to-pdf file selection is complete.
739 onFileSelectionComplete_: function() {
740 assert(this.uiState_
== PrintPreview
.UiState_
.FILE_SELECTION
,
741 'File selection completed when not in file-selection state: ' +
743 this.previewArea_
.showCustomMessage(
744 loadTimeData
.getString('printingToPDFInProgress'));
745 this.uiState_
= PrintPreview
.UiState_
.PRINTING
;
749 * Called after successfully submitting a job to Google Cloud Print.
750 * @param {!Event} event Contains the ID of the submitted print job.
753 onCloudPrintSubmitDone_: function(event
) {
754 assert(this.uiState_
== PrintPreview
.UiState_
.PRINTING
,
755 'Submited job to Google Cloud Print but not in printing state ' +
757 if (this.destinationStore_
.selectedDestination
.id
==
758 print_preview
.Destination
.GooglePromotedId
.FEDEX
) {
759 this.nativeLayer_
.startForceOpenNewTab(
760 'https://www.google.com/cloudprint/fedexcode.html?jobid=' +
767 * Called when there was an error communicating with Google Cloud print.
768 * Displays an error message in the print header.
769 * @param {!Event} event Contains the error message.
772 onCloudPrintError_: function(event
) {
773 if (event
.status
== 403) {
774 if (!this.isInAppKioskMode_
) {
775 this.destinationSearch_
.showCloudPrintPromo();
777 } else if (event
.status
== 0) {
778 return; // Ignore, the system does not have internet connectivity.
780 this.printHeader_
.setErrorMessage(event
.message
);
782 if (event
.status
== 200) {
783 console
.error('Google Cloud Print Error: (' + event
.errorCode
+ ') ' +
786 console
.error('Google Cloud Print Error: HTTP status ' + event
.status
);
791 * Called when the preview area's preview generation is in progress.
794 onPreviewGenerationInProgress_: function() {
795 this.isPreviewGenerationInProgress_
= true;
799 * Called when the preview area's preview generation is complete.
802 onPreviewGenerationDone_: function() {
803 this.isPreviewGenerationInProgress_
= false;
804 this.printHeader_
.isPrintButtonEnabled
= true;
805 this.nativeLayer_
.previewReadyForTest();
806 this.printIfReady_();
810 * Called when the preview area's preview failed to load.
813 onPreviewGenerationFail_: function() {
814 this.isPreviewGenerationInProgress_
= false;
815 this.printHeader_
.isPrintButtonEnabled
= false;
816 if (this.uiState_
== PrintPreview
.UiState_
.PRINTING
)
817 this.nativeLayer_
.startCancelPendingPrint();
821 * Called when the 'Open pdf in preview' link is clicked. Launches the pdf
825 onOpenPdfInPreviewLinkClick_: function() {
826 if ($('open-pdf-in-preview-link').classList
.contains('disabled'))
828 assert(this.uiState_
== PrintPreview
.UiState_
.READY
,
829 'Trying to open pdf in preview when not in ready state: ' +
831 setIsVisible(getRequiredElement('open-preview-app-throbber'), true);
832 this.previewArea_
.showCustomMessage(
833 loadTimeData
.getString('openingPDFInPreview'));
834 this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
838 * Called when the print header's print button is clicked. Prints the
842 onPrintButtonClick_: function() {
843 assert(this.uiState_
== PrintPreview
.UiState_
.READY
,
844 'Trying to print when not in ready state: ' + this.uiState_
);
845 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
849 * Called when the print header's cancel button is clicked. Closes the
853 onCancelButtonClick_: function() {
858 * Called when the register promo for Cloud Print is clicked.
861 onCloudPrintRegisterPromoClick_: function(e
) {
862 var devicesUrl
= 'chrome://devices/register?id=' + e
.destination
.id
;
863 this.nativeLayer_
.startForceOpenNewTab(devicesUrl
);
864 this.destinationStore_
.waitForRegister(e
.destination
.id
);
868 * Consume escape key presses and ctrl + shift + p. Delegate everything else
869 * to the preview area.
870 * @param {KeyboardEvent} e The keyboard event.
872 * @suppress {uselessCode}
873 * Current compiler preprocessor leaves all the code inside all the <if>s,
874 * so the compiler claims that code after first return is unreachable.
876 onKeyDown_: function(e
) {
877 // Escape key closes the dialog.
878 if (e
.keyCode
== 27 && !e
.shiftKey
&& !e
.ctrlKey
&& !e
.altKey
&&
880 // On non-mac with toolkit-views, ESC key is handled by C++-side instead
889 // On Mac, Cmd- should close the print dialog.
890 if (cr
.isMac
&& e
.keyCode
== 189 && e
.metaKey
) {
896 // Ctrl + Shift + p / Mac equivalent.
897 if (e
.keyCode
== 80) {
898 if ((cr
.isMac
&& e
.metaKey
&& e
.altKey
&& !e
.shiftKey
&& !e
.ctrlKey
) ||
899 (!cr
.isMac
&& e
.shiftKey
&& e
.ctrlKey
&& !e
.altKey
&& !e
.metaKey
)) {
900 this.openSystemPrintDialog_();
906 if (e
.keyCode
== 13 /*enter*/ &&
907 !document
.querySelector('.overlay:not([hidden])') &&
908 this.destinationStore_
.selectedDestination
&&
909 this.printTicketStore_
.isTicketValid() &&
910 this.printHeader_
.isPrintButtonEnabled
) {
911 assert(this.uiState_
== PrintPreview
.UiState_
.READY
,
912 'Trying to print when not in ready state: ' + this.uiState_
);
913 var activeElementTag
= document
.activeElement
.tagName
.toUpperCase();
914 if (activeElementTag
!= 'BUTTON' && activeElementTag
!= 'SELECT' &&
915 activeElementTag
!= 'A') {
916 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
922 // Pass certain directional keyboard events to the PDF viewer.
923 this.previewArea_
.handleDirectionalKeyEvent(e
);
927 * Called when native layer receives invalid settings for a print request.
930 onSettingsInvalid_: function() {
931 this.uiState_
= PrintPreview
.UiState_
.ERROR
;
932 console
.error('Invalid settings error reported from native layer');
933 this.previewArea_
.showCustomMessage(
934 loadTimeData
.getString('invalidPrinterSettings'));
938 * Called when the destination settings' change button is activated.
939 * Displays the destination search component.
942 onDestinationChangeButtonActivate_: function() {
943 this.destinationSearch_
.setIsVisible(true);
947 * Called when the destination settings' change button is activated.
948 * Displays the destination search component.
951 onAdvancedOptionsButtonActivated_: function() {
952 this.advancedSettings_
.showForDestination(
953 assert(this.destinationStore_
.selectedDestination
));
957 * Called when the destination search dispatches manage cloud destinations
958 * event. Calls corresponding native layer method.
961 onManageCloudDestinationsActivated_: function() {
962 this.nativeLayer_
.startManageCloudDestinations(this.userInfo_
.activeUser
);
966 * Called when the destination search dispatches manage local destinations
967 * event. Calls corresponding native layer method.
970 onManageLocalDestinationsActivated_: function() {
971 this.nativeLayer_
.startManageLocalDestinations();
975 * Called when the user wants to sign in to Google Cloud Print. Calls the
976 * corresponding native layer event.
977 * @param {boolean} addAccount Whether to open an 'add a new account' or
978 * default sign in page.
981 onCloudPrintSignInActivated_: function(addAccount
) {
982 this.nativeLayer_
.startCloudPrintSignIn(addAccount
);
986 * Updates printing options according to source document presets.
987 * @param {Event} event Contains options from source document.
990 onPrintPresetOptionsFromDocument_: function(event
) {
991 if (event
.optionsFromDocument
.disableScaling
) {
992 this.printTicketStore_
.fitToPage
.updateValue(null);
993 this.documentInfo_
.updateIsScalingDisabled(true);
996 if (event
.optionsFromDocument
.copies
> 0 &&
997 this.printTicketStore_
.copies
.isCapabilityAvailable()) {
998 this.printTicketStore_
.copies
.updateValue(
999 event
.optionsFromDocument
.copies
);
1002 if (event
.optionsFromDocument
.duplex
>= 0 &&
1003 this.printTicketStore_
.duplex
.isCapabilityAvailable()) {
1004 this.printTicketStore_
.duplex
.updateValue(
1005 event
.optionsFromDocument
.duplex
);
1010 * Called when privet printing fails.
1011 * @param {Event} event Event object representing the failure.
1014 onPrivetPrintFailed_: function(event
) {
1015 console
.error('Privet printing failed with error code ' +
1017 this.printHeader_
.setErrorMessage(
1018 loadTimeData
.getString('couldNotPrint'));
1022 * Called when the native layer has detected that the "Distill page"
1023 * option should be allowed.
1026 onAllowDistillPage_: function(event
) {
1027 this.printTicketStore_
.distillPage
.setIsCapabilityAvailable(true);
1031 * Called when the print preview settings need to be changed for testing.
1032 * @param {Event} event Event object that contains the option that is to
1033 * be changed and what to set that option.
1036 onManipulateSettingsForTest_: function(event
) {
1038 /** @type {print_preview.PreviewSettings} */(event
.settings
);
1039 if ('selectSaveAsPdfDestination' in settings
) {
1040 this.saveAsPdfForTest_(); // No parameters.
1041 } else if ('layoutSettings' in settings
) {
1042 this.setLayoutSettingsForTest_(settings
.layoutSettings
.portrait
);
1043 } else if ('pageRange' in settings
) {
1044 this.setPageRangeForTest_(settings
.pageRange
);
1045 } else if ('headersAndFooters' in settings
) {
1046 this.setHeadersAndFootersForTest_(settings
.headersAndFooters
);
1047 } else if ('backgroundColorsAndImages' in settings
) {
1048 this.setBackgroundColorsAndImagesForTest_(
1049 settings
.backgroundColorsAndImages
);
1050 } else if ('margins' in settings
) {
1051 this.setMarginsForTest_(settings
.margins
);
1056 * Called by onManipulateSettingsForTest_(). Sets the print destination
1060 saveAsPdfForTest_: function() {
1061 if (this.destinationStore_
.selectedDestination
&&
1062 print_preview
.Destination
.GooglePromotedId
.SAVE_AS_PDF
==
1063 this.destinationStore_
.selectedDestination
.id
) {
1064 this.nativeLayer_
.previewReadyForTest();
1068 var destinations
= this.destinationStore_
.destinations();
1069 var pdfDestination
= null;
1070 for (var i
= 0; i
< destinations
.length
; i
++) {
1071 if (destinations
[i
].id
==
1072 print_preview
.Destination
.GooglePromotedId
.SAVE_AS_PDF
) {
1073 pdfDestination
= destinations
[i
];
1079 this.destinationStore_
.selectDestination(pdfDestination
);
1081 this.nativeLayer_
.previewFailedForTest();
1085 * Called by onManipulateSettingsForTest_(). Sets the layout settings to
1086 * either portrait or landscape.
1087 * @param {boolean} portrait Whether to use portrait page layout;
1088 * if false: landscape.
1091 setLayoutSettingsForTest_: function(portrait
) {
1092 var combobox
= document
.querySelector('.layout-settings-select');
1093 if (combobox
.value
== 'portrait') {
1094 this.nativeLayer_
.previewReadyForTest();
1096 combobox
.value
= 'landscape';
1097 this.layoutSettings_
.onSelectChange_();
1102 * Called by onManipulateSettingsForTest_(). Sets the page range for
1103 * for the print preview settings.
1104 * @param {string} pageRange Sets the page range to the desired value(s).
1105 * Ex: "1-5,9" means pages 1 through 5 and page 9 will be printed.
1108 setPageRangeForTest_: function(pageRange
) {
1109 var textbox
= document
.querySelector('.page-settings-custom-input');
1110 if (textbox
.value
== pageRange
) {
1111 this.nativeLayer_
.previewReadyForTest();
1113 textbox
.value
= pageRange
;
1114 document
.querySelector('.page-settings-custom-radio').click();
1119 * Called by onManipulateSettings_(). Checks or unchecks the headers and
1120 * footers option on print preview.
1121 * @param {boolean} headersAndFooters Whether the "Headers and Footers"
1122 * checkbox should be checked.
1125 setHeadersAndFootersForTest_: function(headersAndFooters
) {
1126 var checkbox
= document
.querySelector('.header-footer-checkbox');
1127 if (headersAndFooters
== checkbox
.checked
)
1128 this.nativeLayer_
.previewReadyForTest();
1134 * Called by onManipulateSettings_(). Checks or unchecks the background
1135 * colors and images option on print preview.
1136 * @param {boolean} backgroundColorsAndImages If true, the checkbox should
1137 * be checked. Otherwise it should be unchecked.
1140 setBackgroundColorsAndImagesForTest_: function(backgroundColorsAndImages
) {
1141 var checkbox
= document
.querySelector('.css-background-checkbox');
1142 if (backgroundColorsAndImages
== checkbox
.checked
)
1143 this.nativeLayer_
.previewReadyForTest();
1149 * Called by onManipulateSettings_(). Sets the margin settings
1150 * that are desired. Custom margin settings aren't currently supported.
1151 * @param {number} margins The desired margins combobox index. Must be
1152 * a valid index or else the test fails.
1155 setMarginsForTest_: function(margins
) {
1156 var combobox
= document
.querySelector('.margin-settings-select');
1157 if (margins
== combobox
.selectedIndex
) {
1158 this.nativeLayer_
.previewReadyForTest();
1159 } else if (margins
>= 0 && margins
< combobox
.length
) {
1160 combobox
.selectedIndex
= margins
;
1161 this.marginSettings_
.onSelectChange_();
1163 this.nativeLayer_
.previewFailedForTest();
1168 * Returns true if "Print using system dialog" link should be shown for
1169 * current destination.
1170 * @return {boolean} Returns true if link should be shown.
1172 shouldShowSystemDialogLink_: function() {
1173 if (cr
.isChromeOS
|| this.hideSystemDialogLink_
)
1177 var selectedDest
= this.destinationStore_
.selectedDestination
;
1178 return !!selectedDest
&&
1179 selectedDest
.origin
== print_preview
.Destination
.Origin
.LOCAL
&&
1181 print_preview
.Destination
.GooglePromotedId
.SAVE_AS_PDF
;
1185 * Called when a print destination is selected. Shows/hides the "Print with
1186 * Cloud Print" link in the navbar.
1189 onDestinationSelect_: function() {
1190 if ($('system-dialog-link')) {
1191 setIsVisible($('system-dialog-link'),
1192 this.shouldShowSystemDialogLink_());
1194 if (this.destinationStore_
.selectedDestination
&&
1195 this.isInKioskAutoPrintMode_
) {
1196 this.onPrintButtonClick_();
1201 * Called when the destination store loads a group of destinations. Shows
1202 * a promo on Chrome OS if the user has no print destinations promoting
1203 * Google Cloud Print.
1206 onDestinationSearchDone_: function() {
1207 var isPromoVisible
= cr
.isChromeOS
&&
1208 this.cloudPrintInterface_
&&
1209 this.userInfo_
.activeUser
&&
1210 !this.appState_
.isGcpPromoDismissed
&&
1211 !this.destinationStore_
.isLocalDestinationSearchInProgress
&&
1212 !this.destinationStore_
.isCloudDestinationSearchInProgress
&&
1213 this.destinationStore_
.hasOnlyDefaultCloudDestinations();
1214 setIsVisible(this.getChildElement('#no-destinations-promo'),
1216 if (isPromoVisible
) {
1217 new print_preview
.GcpPromoMetricsContext().record(
1218 print_preview
.Metrics
.GcpPromoBucket
.PROMO_SHOWN
);
1223 * Called when the close button on the no-destinations-promotion is clicked.
1224 * Hides the promotion.
1227 onNoDestinationsPromoClose_: function() {
1228 new print_preview
.GcpPromoMetricsContext().record(
1229 print_preview
.Metrics
.GcpPromoBucket
.PROMO_CLOSED
);
1230 setIsVisible(this.getChildElement('#no-destinations-promo'), false);
1231 this.appState_
.persistIsGcpPromoDismissed(true);
1235 * Called when the no-destinations promotion link is clicked. Opens the
1236 * Google Cloud Print management page and closes the print preview.
1239 onNoDestinationsPromoClick_: function() {
1240 new print_preview
.GcpPromoMetricsContext().record(
1241 print_preview
.Metrics
.GcpPromoBucket
.PROMO_CLICKED
);
1242 this.appState_
.persistIsGcpPromoDismissed(true);
1243 window
.open(this.cloudPrintInterface_
.baseUrl
+ '?user=' +
1244 this.userInfo_
.activeUser
+ '#printers');
1251 PrintPreview
: PrintPreview
1255 // Pull in all other scripts in a single shot.
1256 <include src
="common/overlay.js">
1257 <include src
="common/search_box.js">
1258 <include src
="common/search_bubble.js">
1260 <include src
="data/page_number_set.js">
1261 <include src
="data/destination.js">
1262 <include src
="data/local_parsers.js">
1263 <include src
="data/cloud_parsers.js">
1264 <include src
="data/destination_store.js">
1265 <include src
="data/invitation.js">
1266 <include src
="data/invitation_store.js">
1267 <include src
="data/margins.js">
1268 <include src
="data/document_info.js">
1269 <include src
="data/printable_area.js">
1270 <include src
="data/measurement_system.js">
1271 <include src
="data/print_ticket_store.js">
1272 <include src
="data/coordinate2d.js">
1273 <include src
="data/size.js">
1274 <include src
="data/capabilities_holder.js">
1275 <include src
="data/user_info.js">
1276 <include src
="data/app_state.js">
1278 <include src
="data/ticket_items/ticket_item.js">
1280 <include src
="data/ticket_items/custom_margins.js">
1281 <include src
="data/ticket_items/collate.js">
1282 <include src
="data/ticket_items/color.js">
1283 <include src
="data/ticket_items/copies.js">
1284 <include src
="data/ticket_items/dpi.js">
1285 <include src
="data/ticket_items/duplex.js">
1286 <include src
="data/ticket_items/header_footer.js">
1287 <include src
="data/ticket_items/distill_page.js">
1288 <include src
="data/ticket_items/media_size.js">
1289 <include src
="data/ticket_items/landscape.js">
1290 <include src
="data/ticket_items/margins_type.js">
1291 <include src
="data/ticket_items/page_range.js">
1292 <include src
="data/ticket_items/fit_to_page.js">
1293 <include src
="data/ticket_items/css_background.js">
1294 <include src
="data/ticket_items/selection_only.js">
1295 <include src
="data/ticket_items/vendor_items.js">
1297 <include src
="native_layer.js">
1298 <include src
="print_preview_animations.js">
1299 <include src
="cloud_print_interface.js">
1300 <include src
="print_preview_utils.js">
1301 <include src
="print_header.js">
1302 <include src
="metrics.js">
1304 <include src
="settings/settings_section.js">
1305 <include src
="settings/settings_section_select.js">
1306 <include src
="settings/page_settings.js">
1307 <include src
="settings/copies_settings.js">
1308 <include src
="settings/dpi_settings.js">
1309 <include src
="settings/media_size_settings.js">
1310 <include src
="settings/layout_settings.js">
1311 <include src
="settings/color_settings.js">
1312 <include src
="settings/margin_settings.js">
1313 <include src
="settings/destination_settings.js">
1314 <include src
="settings/other_options_settings.js">
1315 <include src
="settings/advanced_options_settings.js">
1316 <include src
="settings/advanced_settings/advanced_settings.js">
1317 <include src
="settings/advanced_settings/advanced_settings_item.js">
1318 <include src
="settings/more_settings.js">
1320 <include src
="previewarea/margin_control.js">
1321 <include src
="previewarea/margin_control_container.js">
1322 <include src
="../pdf/pdf_scripting_api.js">
1323 <include src
="previewarea/preview_area.js">
1324 <include src
="preview_generator.js">
1326 <include src
="search/destination_list.js">
1327 <include src
="search/cloud_destination_list.js">
1328 <include src
="search/recent_destination_list.js">
1329 <include src
="search/destination_list_item.js">
1330 <include src
="search/destination_search.js">
1331 <include src
="search/fedex_tos.js">
1332 <include src
="search/provisional_destination_resolver.js">
1334 window
.addEventListener('DOMContentLoaded', function() {
1335 printPreview
= new print_preview
.PrintPreview();
1336 printPreview
.initialize();