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 var localStrings = new LocalStrings(templateData);
9 <include src="component.js"/>
10 <include src="print_preview_focus_manager.js"/>
12 cr.define('print_preview', function() {
16 * Container class for Chromium's print preview.
18 * @extends {print_preview.Component}
20 function PrintPreview() {
21 print_preview.Component.call(this);
24 * Used to communicate with Chromium's print system.
25 * @type {!print_preview.NativeLayer}
28 this.nativeLayer_ = new print_preview.NativeLayer();
31 * Event target that contains information about the logged in user.
32 * @type {!print_preview.UserInfo}
35 this.userInfo_ = new print_preview.UserInfo();
39 * @type {!print_preview.AppState}
42 this.appState_ = new print_preview.AppState();
45 * Data model that holds information about the document to print.
46 * @type {!print_preview.DocumentInfo}
49 this.documentInfo_ = new print_preview.DocumentInfo();
52 * Data store which holds print destinations.
53 * @type {!print_preview.DestinationStore}
56 this.destinationStore_ = new print_preview.DestinationStore(
57 this.nativeLayer_, this.userInfo_, this.appState_);
60 * Storage of the print ticket used to create the print job.
61 * @type {!print_preview.PrintTicketStore}
64 this.printTicketStore_ = new print_preview.PrintTicketStore(
65 this.destinationStore_, this.appState_, this.documentInfo_);
68 * Holds the print and cancel buttons and renders some document statistics.
69 * @type {!print_preview.PrintHeader}
72 this.printHeader_ = new print_preview.PrintHeader(
73 this.printTicketStore_, this.destinationStore_);
74 this.addChild(this.printHeader_);
77 * Component used to search for print destinations.
78 * @type {!print_preview.DestinationSearch}
81 this.destinationSearch_ = new print_preview.DestinationSearch(
82 this.destinationStore_, this.userInfo_);
83 this.addChild(this.destinationSearch_);
86 * Component that renders the print destination.
87 * @type {!print_preview.DestinationSettings}
90 this.destinationSettings_ = new print_preview.DestinationSettings(
91 this.destinationStore_);
92 this.addChild(this.destinationSettings_);
95 * Component that renders UI for entering in page range.
96 * @type {!print_preview.PageSettings}
99 this.pageSettings_ = new print_preview.PageSettings(
100 this.printTicketStore_.pageRange);
101 this.addChild(this.pageSettings_);
104 * Component that renders the copies settings.
105 * @type {!print_preview.CopiesSettings}
108 this.copiesSettings_ = new print_preview.CopiesSettings(
109 this.printTicketStore_.copies, this.printTicketStore_.collate);
110 this.addChild(this.copiesSettings_);
113 * Component that renders the media size settings.
114 * @type {!print_preview.MediaSizeSettings}
117 this.mediaSizeSettings_ =
118 new print_preview.MediaSizeSettings(this.printTicketStore_.mediaSize);
119 this.addChild(this.mediaSizeSettings_);
122 * Component that renders the layout settings.
123 * @type {!print_preview.LayoutSettings}
126 this.layoutSettings_ =
127 new print_preview.LayoutSettings(this.printTicketStore_.landscape);
128 this.addChild(this.layoutSettings_);
131 * Component that renders the color options.
132 * @type {!print_preview.ColorSettings}
135 this.colorSettings_ =
136 new print_preview.ColorSettings(this.printTicketStore_.color);
137 this.addChild(this.colorSettings_);
140 * Component that renders a select box for choosing margin settings.
141 * @type {!print_preview.MarginSettings}
144 this.marginSettings_ =
145 new print_preview.MarginSettings(this.printTicketStore_.marginsType);
146 this.addChild(this.marginSettings_);
149 * Component that renders miscellaneous print options.
150 * @type {!print_preview.OtherOptionsSettings}
153 this.otherOptionsSettings_ = new print_preview.OtherOptionsSettings(
154 this.printTicketStore_.duplex,
155 this.printTicketStore_.fitToPage,
156 this.printTicketStore_.cssBackground,
157 this.printTicketStore_.selectionOnly,
158 this.printTicketStore_.headerFooter);
159 this.addChild(this.otherOptionsSettings_);
162 * Component that renders the advanced options button.
163 * @type {!print_preview.AdvancedOptionsSettings}
166 this.advancedOptionsSettings_ = new print_preview.AdvancedOptionsSettings(
167 this.destinationStore_);
168 this.addChild(this.advancedOptionsSettings_);
171 * Component used to search for print destinations.
172 * @type {!print_preview.AdvancedSettings}
175 this.advancedSettings_ = new print_preview.AdvancedSettings(
176 this.printTicketStore_);
177 this.addChild(this.advancedSettings_);
180 * Area of the UI that holds the print preview.
181 * @type {!print_preview.PreviewArea}
184 this.previewArea_ = new print_preview.PreviewArea(this.destinationStore_,
185 this.printTicketStore_,
188 this.addChild(this.previewArea_);
191 * Interface to the Google Cloud Print API. Null if Google Cloud Print
192 * integration is disabled.
193 * @type {cloudprint.CloudPrintInterface}
196 this.cloudPrintInterface_ = null;
199 * Whether in kiosk mode where print preview can print automatically without
200 * user intervention. See http://crbug.com/31395. Print will start when
201 * both the print ticket has been initialized, and an initial printer has
206 this.isInKioskAutoPrintMode_ = false;
209 * Whether Print Preview is in App Kiosk mode, basically, use only printers
210 * available for the device.
214 this.isInAppKioskMode_ = false;
217 * State of the print preview UI.
218 * @type {print_preview.PrintPreview.UiState_}
221 this.uiState_ = PrintPreview.UiState_.INITIALIZING;
224 * Whether document preview generation is in progress.
228 this.isPreviewGenerationInProgress_ = true;
232 * States of the print preview.
236 PrintPreview.UiState_ = {
237 INITIALIZING: 'initializing',
239 OPENING_PDF_PREVIEW: 'opening-pdf-preview',
240 OPENING_CLOUD_PRINT_DIALOG: 'opening-cloud-print-dialog',
241 OPENING_NATIVE_PRINT_DIALOG: 'opening-native-print-dialog',
242 PRINTING: 'printing',
243 FILE_SELECTION: 'file-selection',
249 * What can happen when print preview tries to print.
253 PrintPreview.PrintAttemptResult_ = {
254 NOT_READY: 'not-ready',
256 READY_WAITING_FOR_PREVIEW: 'ready-waiting-for-preview'
259 PrintPreview.prototype = {
260 __proto__: print_preview.Component.prototype,
262 /** Sets up the page and print preview by getting the printer list. */
263 initialize: function() {
264 this.decorate($('print-preview'));
265 i18nTemplate.process(document, templateData);
266 if (!this.previewArea_.hasCompatiblePlugin) {
267 this.setIsEnabled_(false);
269 this.nativeLayer_.startGetInitialSettings();
270 print_preview.PrintPreviewFocusManager.getInstance().initialize();
271 cr.ui.FocusOutlineManager.forDocument(document);
275 enterDocument: function() {
276 // Native layer events.
279 print_preview.NativeLayer.EventType.INITIAL_SETTINGS_SET,
280 this.onInitialSettingsSet_.bind(this));
283 print_preview.NativeLayer.EventType.CLOUD_PRINT_ENABLE,
284 this.onCloudPrintEnable_.bind(this));
287 print_preview.NativeLayer.EventType.PRINT_TO_CLOUD,
288 this.onPrintToCloud_.bind(this));
291 print_preview.NativeLayer.EventType.FILE_SELECTION_CANCEL,
292 this.onFileSelectionCancel_.bind(this));
295 print_preview.NativeLayer.EventType.FILE_SELECTION_COMPLETE,
296 this.onFileSelectionComplete_.bind(this));
299 print_preview.NativeLayer.EventType.SETTINGS_INVALID,
300 this.onSettingsInvalid_.bind(this));
303 print_preview.NativeLayer.EventType.DISABLE_SCALING,
304 this.onDisableScaling_.bind(this));
307 print_preview.NativeLayer.EventType.PRIVET_PRINT_FAILED,
308 this.onPrivetPrintFailed_.bind(this));
311 print_preview.NativeLayer.EventType.MANIPULATE_SETTINGS_FOR_TEST,
312 this.onManipulateSettingsForTest_.bind(this));
315 $('system-dialog-link'),
317 this.openSystemPrintDialog_.bind(this));
319 $('cloud-print-dialog-link'),
321 this.onCloudPrintDialogLinkClick_.bind(this));
323 $('open-pdf-in-preview-link'),
325 this.onOpenPdfInPreviewLinkClick_.bind(this));
329 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS,
330 this.onPreviewGenerationInProgress_.bind(this));
333 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE,
334 this.onPreviewGenerationDone_.bind(this));
337 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_FAIL,
338 this.onPreviewGenerationFail_.bind(this));
341 print_preview.PreviewArea.EventType.OPEN_SYSTEM_DIALOG_CLICK,
342 this.openSystemPrintDialog_.bind(this));
345 this.destinationStore_,
346 print_preview.DestinationStore.EventType.
347 SELECTED_DESTINATION_CAPABILITIES_READY,
348 this.printIfReady_.bind(this));
350 this.destinationStore_,
351 print_preview.DestinationStore.EventType.DESTINATION_SELECT,
352 this.onDestinationSelect_.bind(this));
354 this.destinationStore_,
355 print_preview.DestinationStore.EventType.DESTINATION_SEARCH_DONE,
356 this.onDestinationSearchDone_.bind(this));
360 print_preview.PrintHeader.EventType.PRINT_BUTTON_CLICK,
361 this.onPrintButtonClick_.bind(this));
364 print_preview.PrintHeader.EventType.CANCEL_BUTTON_CLICK,
365 this.onCancelButtonClick_.bind(this));
367 this.tracker.add(window, 'keydown', this.onKeyDown_.bind(this));
370 this.destinationSettings_,
371 print_preview.DestinationSettings.EventType.CHANGE_BUTTON_ACTIVATE,
372 this.onDestinationChangeButtonActivate_.bind(this));
375 this.destinationSearch_,
376 print_preview.DestinationSearch.EventType.MANAGE_CLOUD_DESTINATIONS,
377 this.onManageCloudDestinationsActivated_.bind(this));
379 this.destinationSearch_,
380 print_preview.DestinationSearch.EventType.MANAGE_LOCAL_DESTINATIONS,
381 this.onManageLocalDestinationsActivated_.bind(this));
383 this.destinationSearch_,
384 print_preview.DestinationSearch.EventType.ADD_ACCOUNT,
385 this.onCloudPrintSignInActivated_.bind(this, true /*addAccount*/));
387 this.destinationSearch_,
388 print_preview.DestinationSearch.EventType.SIGN_IN,
389 this.onCloudPrintSignInActivated_.bind(this, false /*addAccount*/));
391 this.destinationSearch_,
392 print_preview.DestinationListItem.EventType.REGISTER_PROMO_CLICKED,
393 this.onCloudPrintRegisterPromoClick_.bind(this));
396 this.advancedOptionsSettings_,
397 print_preview.AdvancedOptionsSettings.EventType.BUTTON_ACTIVATED,
398 this.onAdvancedOptionsButtonActivated_.bind(this));
400 // TODO(rltoscano): Move no-destinations-promo into its own component
401 // instead being part of PrintPreview.
403 this.getChildElement('#no-destinations-promo .close-button'),
405 this.onNoDestinationsPromoClose_.bind(this));
407 this.getChildElement('#no-destinations-promo .not-now-button'),
409 this.onNoDestinationsPromoClose_.bind(this));
411 this.getChildElement('#no-destinations-promo .add-printer-button'),
413 this.onNoDestinationsPromoClick_.bind(this));
417 decorateInternal: function() {
418 this.printHeader_.decorate($('print-header'));
419 this.destinationSearch_.decorate($('destination-search'));
420 this.destinationSettings_.decorate($('destination-settings'));
421 this.pageSettings_.decorate($('page-settings'));
422 this.copiesSettings_.decorate($('copies-settings'));
423 this.mediaSizeSettings_.decorate($('media-size-settings'));
424 this.layoutSettings_.decorate($('layout-settings'));
425 this.colorSettings_.decorate($('color-settings'));
426 this.marginSettings_.decorate($('margin-settings'));
427 this.otherOptionsSettings_.decorate($('other-options-settings'));
428 this.advancedOptionsSettings_.decorate($('advanced-options-settings'));
429 this.advancedSettings_.decorate($('advanced-settings'));
430 this.previewArea_.decorate($('preview-area'));
432 setIsVisible($('open-pdf-in-preview-link'), cr.isMac);
436 * Sets whether the controls in the print preview are enabled.
437 * @param {boolean} isEnabled Whether the controls in the print preview are
441 setIsEnabled_: function(isEnabled) {
442 $('system-dialog-link').disabled = !isEnabled;
443 $('cloud-print-dialog-link').disabled = !isEnabled;
444 $('open-pdf-in-preview-link').disabled = !isEnabled;
445 this.printHeader_.isEnabled = isEnabled;
446 this.destinationSettings_.isEnabled = isEnabled;
447 this.pageSettings_.isEnabled = isEnabled;
448 this.copiesSettings_.isEnabled = isEnabled;
449 this.mediaSizeSettings_.isEnabled = isEnabled;
450 this.layoutSettings_.isEnabled = isEnabled;
451 this.colorSettings_.isEnabled = isEnabled;
452 this.marginSettings_.isEnabled = isEnabled;
453 this.otherOptionsSettings_.isEnabled = isEnabled;
454 this.advancedOptionsSettings_.isEnabled = isEnabled;
458 * Prints the document or launches a pdf preview on the local system.
459 * @param {boolean} isPdfPreview Whether to launch the pdf preview.
462 printDocumentOrOpenPdfPreview_: function(isPdfPreview) {
463 assert(this.uiState_ == PrintPreview.UiState_.READY,
464 'Print document request received when not in ready state: ' +
467 this.uiState_ = PrintPreview.UiState_.OPENING_PDF_PREVIEW;
468 } else if (this.destinationStore_.selectedDestination.id ==
469 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
470 this.uiState_ = PrintPreview.UiState_.FILE_SELECTION;
472 this.uiState_ = PrintPreview.UiState_.PRINTING;
474 this.setIsEnabled_(false);
475 this.printHeader_.isCancelButtonEnabled = true;
476 var printAttemptResult = this.printIfReady_();
477 if (printAttemptResult == PrintPreview.PrintAttemptResult_.PRINTED ||
478 printAttemptResult ==
479 PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW) {
480 if ((this.destinationStore_.selectedDestination.isLocal &&
481 !this.destinationStore_.selectedDestination.isPrivet &&
482 this.destinationStore_.selectedDestination.id !=
483 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) ||
484 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW) {
485 // Hide the dialog for now. The actual print command will be issued
486 // when the preview generation is done.
487 this.nativeLayer_.startHideDialog();
493 * Attempts to print if needed and if ready.
494 * @return {PrintPreview.PrintAttemptResult_} Attempt result.
497 printIfReady_: function() {
499 (this.uiState_ == PrintPreview.UiState_.PRINTING ||
500 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW ||
501 this.uiState_ == PrintPreview.UiState_.FILE_SELECTION ||
502 this.uiState_ == PrintPreview.UiState_.OPENING_CLOUD_PRINT_DIALOG ||
503 this.isInKioskAutoPrintMode_) &&
504 this.destinationStore_.selectedDestination &&
505 this.destinationStore_.selectedDestination.capabilities;
507 return PrintPreview.PrintAttemptResult_.NOT_READY;
509 if (this.isPreviewGenerationInProgress_) {
510 return PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW;
512 assert(this.printTicketStore_.isTicketValid(),
513 'Trying to print with invalid ticket');
514 if (this.uiState_ == PrintPreview.UiState_.OPENING_CLOUD_PRINT_DIALOG) {
515 this.nativeLayer_.startShowCloudPrintDialog(
516 this.printTicketStore_.pageRange.getPageNumberSet().size);
518 this.nativeLayer_.startPrint(
519 this.destinationStore_.selectedDestination,
520 this.printTicketStore_,
521 this.cloudPrintInterface_,
523 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW);
525 return PrintPreview.PrintAttemptResult_.PRINTED;
529 * Closes the print preview.
534 this.uiState_ = PrintPreview.UiState_.CLOSING;
535 this.nativeLayer_.startCloseDialog();
539 * Opens the native system print dialog after disabling all controls.
542 openSystemPrintDialog_: function() {
543 setIsVisible($('system-dialog-throbber'), true);
544 this.setIsEnabled_(false);
545 this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
546 this.nativeLayer_.startShowSystemDialog();
550 * Called when the native layer has initial settings to set. Sets the
551 * initial settings of the print preview and begins fetching print
553 * @param {Event} event Contains the initial print preview settings
554 * persisted through the session.
557 onInitialSettingsSet_: function(event) {
558 assert(this.uiState_ == PrintPreview.UiState_.INITIALIZING,
559 'Updating initial settings when not in initializing state: ' +
561 this.uiState_ = PrintPreview.UiState_.READY;
563 var settings = event.initialSettings;
564 this.isInKioskAutoPrintMode_ = settings.isInKioskAutoPrintMode;
565 this.isInAppKioskMode_ = settings.isInAppKioskMode;
567 // The following components must be initialized in this order.
569 settings.serializedAppStateStr,
570 settings.systemDefaultDestinationId);
571 this.documentInfo_.init(
572 settings.isDocumentModifiable,
573 settings.documentTitle,
574 settings.documentHasSelection);
575 this.printTicketStore_.init(
576 settings.thousandsDelimeter,
577 settings.decimalDelimeter,
579 settings.selectionOnly);
580 this.destinationStore_.init(settings.isInAppKioskMode);
581 this.appState_.setInitialized();
583 $('document-title').innerText = settings.documentTitle;
584 setIsVisible($('system-dialog-link'),
585 !settings.hidePrintWithSystemDialogLink &&
586 !settings.isInAppKioskMode);
590 * Calls when the native layer enables Google Cloud Print integration.
591 * Fetches the user's cloud printers.
592 * @param {Event} event Contains the base URL of the Google Cloud Print
596 onCloudPrintEnable_: function(event) {
597 this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface(
598 event.baseCloudPrintUrl,
603 this.cloudPrintInterface_,
604 cloudprint.CloudPrintInterface.EventType.SUBMIT_DONE,
605 this.onCloudPrintSubmitDone_.bind(this));
607 this.cloudPrintInterface_,
608 cloudprint.CloudPrintInterface.EventType.SEARCH_FAILED,
609 this.onCloudPrintError_.bind(this));
611 this.cloudPrintInterface_,
612 cloudprint.CloudPrintInterface.EventType.SUBMIT_FAILED,
613 this.onCloudPrintError_.bind(this));
615 this.cloudPrintInterface_,
616 cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED,
617 this.onCloudPrintError_.bind(this));
619 this.cloudPrintInterface_,
620 cloudprint.CloudPrintInterface.EventType.
621 UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED,
622 this.onCloudPrintError_.bind(this));
624 this.destinationStore_.setCloudPrintInterface(this.cloudPrintInterface_);
625 if (this.destinationSearch_.getIsVisible()) {
626 this.destinationStore_.startLoadCloudDestinations();
631 * Called from the native layer when ready to print to Google Cloud Print.
632 * @param {Event} event Contains the body to send in the HTTP request.
635 onPrintToCloud_: function(event) {
636 assert(this.uiState_ == PrintPreview.UiState_.PRINTING,
637 'Document ready to be sent to the cloud when not in printing ' +
638 'state: ' + this.uiState_);
639 assert(this.cloudPrintInterface_ != null,
640 'Google Cloud Print is not enabled');
641 this.cloudPrintInterface_.submit(
642 this.destinationStore_.selectedDestination,
643 this.printTicketStore_,
649 * Called from the native layer when the user cancels the save-to-pdf file
653 onFileSelectionCancel_: function() {
654 assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,
655 'File selection cancelled when not in file-selection state: ' +
657 this.setIsEnabled_(true);
658 this.uiState_ = PrintPreview.UiState_.READY;
662 * Called from the native layer when save-to-pdf file selection is complete.
665 onFileSelectionComplete_: function() {
666 assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,
667 'File selection completed when not in file-selection state: ' +
669 this.previewArea_.showCustomMessage(
670 localStrings.getString('printingToPDFInProgress'));
671 this.uiState_ = PrintPreview.UiState_.PRINTING;
675 * Called after successfully submitting a job to Google Cloud Print.
676 * @param {!Event} event Contains the ID of the submitted print job.
679 onCloudPrintSubmitDone_: function(event) {
680 assert(this.uiState_ == PrintPreview.UiState_.PRINTING,
681 'Submited job to Google Cloud Print but not in printing state ' +
683 if (this.destinationStore_.selectedDestination.id ==
684 print_preview.Destination.GooglePromotedId.FEDEX) {
685 this.nativeLayer_.startForceOpenNewTab(
686 'https://www.google.com/cloudprint/fedexcode.html?jobid=' +
693 * Called when there was an error communicating with Google Cloud print.
694 * Displays an error message in the print header.
695 * @param {!Event} event Contains the error message.
698 onCloudPrintError_: function(event) {
699 if (event.status == 403) {
700 if (!this.isInAppKioskMode_) {
701 this.destinationSearch_.showCloudPrintPromo();
703 } else if (event.status == 0) {
704 return; // Ignore, the system does not have internet connectivity.
706 this.printHeader_.setErrorMessage(event.message);
708 if (event.status == 200) {
709 console.error('Google Cloud Print Error: (' + event.errorCode + ') ' +
712 console.error('Google Cloud Print Error: HTTP status ' + event.status);
717 * Called when the preview area's preview generation is in progress.
720 onPreviewGenerationInProgress_: function() {
721 this.isPreviewGenerationInProgress_ = true;
725 * Called when the preview area's preview generation is complete.
728 onPreviewGenerationDone_: function() {
729 this.isPreviewGenerationInProgress_ = false;
730 this.printHeader_.isPrintButtonEnabled = true;
731 this.nativeLayer_.previewReadyForTest();
732 this.printIfReady_();
736 * Called when the preview area's preview failed to load.
739 onPreviewGenerationFail_: function() {
740 this.isPreviewGenerationInProgress_ = false;
741 this.printHeader_.isPrintButtonEnabled = false;
742 if (this.uiState_ == PrintPreview.UiState_.PRINTING) {
743 this.nativeLayer_.startCancelPendingPrint();
744 } else if (this.uiState_ ==
745 PrintPreview.UiState_.OPENING_CLOUD_PRINT_DIALOG) {
746 this.uiState_ = PrintPreview.UiState_.READY;
751 * Called when the 'Open pdf in preview' link is clicked. Launches the pdf
755 onOpenPdfInPreviewLinkClick_: function() {
756 assert(this.uiState_ == PrintPreview.UiState_.READY,
757 'Trying to open pdf in preview when not in ready state: ' +
759 setIsVisible($('open-preview-app-throbber'), true);
760 this.previewArea_.showCustomMessage(
761 localStrings.getString('openingPDFInPreview'));
762 this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
766 * Called when the print header's print button is clicked. Prints the
770 onPrintButtonClick_: function() {
771 assert(this.uiState_ == PrintPreview.UiState_.READY,
772 'Trying to print when not in ready state: ' + this.uiState_);
773 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
777 * Called when the print header's cancel button is clicked. Closes the
781 onCancelButtonClick_: function() {
786 * Called when the register promo for Cloud Print is clicked.
789 onCloudPrintRegisterPromoClick_: function(e) {
790 var devicesUrl = 'chrome://devices/register?id=' + e.destination.id;
791 this.nativeLayer_.startForceOpenNewTab(devicesUrl);
792 this.destinationStore_.waitForRegister(e.destination.id);
796 * Consume escape key presses and ctrl + shift + p. Delegate everything else
797 * to the preview area.
798 * @param {KeyboardEvent} e The keyboard event.
801 onKeyDown_: function(e) {
802 // Escape key closes the dialog.
803 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&
805 <if expr="toolkit_views">
806 // On the toolkit_views environment, ESC key is handled by C++-side
807 // instead of JS-side.
810 <if expr="not toolkit_views">
817 // Ctrl + Shift + p / Mac equivalent.
818 if (e.keyCode == 80) {
819 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
820 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
821 this.openSystemPrintDialog_();
827 if (e.keyCode == 13 /*enter*/ &&
828 !document.querySelector('.overlay:not([hidden])') &&
829 this.destinationStore_.selectedDestination &&
830 this.printTicketStore_.isTicketValid()) {
831 assert(this.uiState_ == PrintPreview.UiState_.READY,
832 'Trying to print when not in ready state: ' + this.uiState_);
833 var activeElementTag = document.activeElement ?
834 document.activeElement.tagName.toUpperCase() : '';
835 if (activeElementTag != 'BUTTON' && activeElementTag != 'SELECT') {
836 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
842 // Pass certain directional keyboard events to the PDF viewer.
843 this.previewArea_.handleDirectionalKeyEvent(e);
847 * Called when native layer receives invalid settings for a print request.
850 onSettingsInvalid_: function() {
851 this.uiState_ = PrintPreview.UiState_.ERROR;
852 console.error('Invalid settings error reported from native layer');
853 this.previewArea_.showCustomMessage(
854 localStrings.getString('invalidPrinterSettings'));
858 * Called when the destination settings' change button is activated.
859 * Displays the destination search component.
862 onDestinationChangeButtonActivate_: function() {
863 this.destinationSearch_.setIsVisible(true);
864 this.destinationStore_.startLoadCloudDestinations();
865 this.destinationStore_.startLoadLocalDestinations();
866 this.destinationStore_.startLoadPrivetDestinations();
870 * Called when the destination settings' change button is activated.
871 * Displays the destination search component.
874 onAdvancedOptionsButtonActivated_: function() {
875 this.advancedSettings_.showForDestination(
876 this.destinationStore_.selectedDestination);
880 * Called when the destination search dispatches manage cloud destinations
881 * event. Calls corresponding native layer method.
884 onManageCloudDestinationsActivated_: function() {
885 this.nativeLayer_.startManageCloudDestinations();
889 * Called when the destination search dispatches manage local destinations
890 * event. Calls corresponding native layer method.
893 onManageLocalDestinationsActivated_: function() {
894 this.nativeLayer_.startManageLocalDestinations();
898 * Called when the user wants to sign in to Google Cloud Print. Calls the
899 * corresponding native layer event.
900 * @param {boolean} addAccount Whether to open an 'add a new account' or
901 * default sign in page.
904 onCloudPrintSignInActivated_: function(addAccount) {
905 this.nativeLayer_.startCloudPrintSignIn(addAccount);
909 * Called when the native layer dispatches a DISABLE_SCALING event. Resets
910 * fit-to-page selection and updates document info.
913 onDisableScaling_: function() {
914 this.printTicketStore_.fitToPage.updateValue(null);
915 this.documentInfo_.updateIsScalingDisabled(true);
919 * Called when privet printing fails.
920 * @param {Event} event Event object representing the failure.
923 onPrivetPrintFailed_: function(event) {
924 console.error('Privet printing failed with error code ' +
926 this.printHeader_.setErrorMessage(
927 localStrings.getString('couldNotPrint'));
931 * Called when the print preview settings need to be changed for testing.
932 * @param {Event} event Event object that contains the option that is to
933 * be changed and what to set that option.
936 onManipulateSettingsForTest_: function(event) {
937 if ('selectSaveAsPdfDestination' in event.settings) {
938 this.saveAsPdfForTest_(); // No parameters.
939 } else if ('layoutSettings' in event.settings) {
940 this.setLayoutSettingsForTest_(event.settings.layoutSettings.portrait);
941 } else if ('pageRange' in event.settings) {
942 this.setPageRangeForTest_(event.settings.pageRange);
943 } else if ('headersAndFooters' in event.settings) {
944 this.setHeadersAndFootersForTest_(event.settings.headersAndFooters);
945 } else if ('backgroundColorsAndImages' in event.settings) {
946 this.setBackgroundColorsAndImagesForTest_(
947 event.settings.backgroundColorsAndImages);
948 } else if ('margins' in event.settings) {
949 this.setMarginsForTest_(event.settings.margins);
954 * Called by onManipulateSettingsForTest_(). Sets the print destination
958 saveAsPdfForTest_: function() {
959 if (this.destinationStore_.selectedDestination &&
960 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ==
961 this.destinationStore_.selectedDestination.id) {
962 this.nativeLayer_.previewReadyForTest();
966 var destinations = this.destinationStore_.destinations();
967 var pdfDestination = null;
968 for (var i = 0; i < destinations.length; i++) {
969 if (destinations[i].id ==
970 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
971 pdfDestination = destinations[i];
977 this.destinationStore_.selectDestination(pdfDestination);
979 this.nativeLayer_.previewFailedForTest();
983 * Called by onManipulateSettingsForTest_(). Sets the layout settings to
984 * either portrait or landscape.
985 * @param {boolean} portrait Whether to use portrait page layout;
986 * if false: landscape.
989 setLayoutSettingsForTest_: function(portrait) {
990 var element = document.querySelector(portrait ?
991 '.layout-settings-portrait-radio' :
992 '.layout-settings-landscape-radio');
994 this.nativeLayer_.previewReadyForTest();
1000 * Called by onManipulateSettingsForTest_(). Sets the page range for
1001 * for the print preview settings.
1002 * @param {string} pageRange Sets the page range to the desired value(s).
1003 * Ex: "1-5,9" means pages 1 through 5 and page 9 will be printed.
1006 setPageRangeForTest_: function(pageRange) {
1007 var textbox = document.querySelector('.page-settings-custom-input');
1008 if (textbox.value == pageRange) {
1009 this.nativeLayer_.previewReadyForTest();
1011 textbox.value = pageRange;
1012 document.querySelector('.page-settings-custom-radio').click();
1017 * Called by onManipulateSettings_(). Checks or unchecks the headers and
1018 * footers option on print preview.
1019 * @param {boolean} headersAndFooters Whether the "Headers and Footers"
1020 * checkbox should be checked.
1023 setHeadersAndFootersForTest_: function(headersAndFooters) {
1024 var checkbox = document.querySelector('.header-footer-checkbox');
1025 if (headersAndFooters == checkbox.checked)
1026 this.nativeLayer_.previewReadyForTest();
1032 * Called by onManipulateSettings_(). Checks or unchecks the background
1033 * colors and images option on print preview.
1034 * @param {boolean} backgroundColorsAndImages If true, the checkbox should
1035 * be checked. Otherwise it should be unchecked.
1038 setBackgroundColorsAndImagesForTest_: function(backgroundColorsAndImages) {
1039 var checkbox = document.querySelector('.css-background-checkbox');
1040 if (backgroundColorsAndImages == checkbox.checked)
1041 this.nativeLayer_.previewReadyForTest();
1047 * Called by onManipulateSettings_(). Sets the margin settings
1048 * that are desired. Custom margin settings aren't currently supported.
1049 * @param {number} margins The desired margins combobox index. Must be
1050 * a valid index or else the test fails.
1053 setMarginsForTest_: function(margins) {
1054 var combobox = document.querySelector('.margin-settings-select');
1055 if (margins == combobox.selectedIndex) {
1056 this.nativeLayer_.previewReadyForTest();
1057 } else if (margins >= 0 && margins < combobox.length) {
1058 combobox.selectedIndex = margins;
1059 this.marginSettings_.onSelectChange_();
1061 this.nativeLayer_.previewFailedForTest();
1066 * Called when the open-cloud-print-dialog link is clicked. Opens the Google
1067 * Cloud Print web dialog.
1070 onCloudPrintDialogLinkClick_: function() {
1071 assert(this.uiState_ == PrintPreview.UiState_.READY,
1072 'Opening Google Cloud Print dialog when not in ready state: ' +
1074 setIsVisible($('cloud-print-dialog-throbber'), true);
1075 this.setIsEnabled_(false);
1076 this.uiState_ = PrintPreview.UiState_.OPENING_CLOUD_PRINT_DIALOG;
1077 this.printIfReady_();
1081 * Called when a print destination is selected. Shows/hides the "Print with
1082 * Cloud Print" link in the navbar.
1085 onDestinationSelect_: function() {
1086 var selectedDest = this.destinationStore_.selectedDestination;
1088 $('cloud-print-dialog-link'),
1089 selectedDest && !cr.isChromeOS && !selectedDest.isLocal);
1090 if (selectedDest && this.isInKioskAutoPrintMode_) {
1091 this.onPrintButtonClick_();
1096 * Called when the destination store loads a group of destinations. Shows
1097 * a promo on Chrome OS if the user has no print destinations promoting
1098 * Google Cloud Print.
1101 onDestinationSearchDone_: function() {
1102 var isPromoVisible = cr.isChromeOS &&
1103 this.cloudPrintInterface_ &&
1104 this.userInfo_.activeUser &&
1105 !this.appState_.isGcpPromoDismissed &&
1106 !this.destinationStore_.isLocalDestinationsSearchInProgress &&
1107 !this.destinationStore_.isCloudDestinationsSearchInProgress &&
1108 this.destinationStore_.hasOnlyDefaultCloudDestinations();
1109 setIsVisible(this.getChildElement('#no-destinations-promo'),
1111 if (isPromoVisible) {
1112 new print_preview.GcpPromoMetricsContext().record(
1113 print_preview.Metrics.GcpPromoBucket.PROMO_SHOWN);
1118 * Called when the close button on the no-destinations-promotion is clicked.
1119 * Hides the promotion.
1122 onNoDestinationsPromoClose_: function() {
1123 new print_preview.GcpPromoMetricsContext().record(
1124 print_preview.Metrics.GcpPromoBucket.PROMO_CLOSED);
1125 setIsVisible(this.getChildElement('#no-destinations-promo'), false);
1126 this.appState_.persistIsGcpPromoDismissed(true);
1130 * Called when the no-destinations promotion link is clicked. Opens the
1131 * Google Cloud Print management page and closes the print preview.
1134 onNoDestinationsPromoClick_: function() {
1135 new print_preview.GcpPromoMetricsContext().record(
1136 print_preview.Metrics.GcpPromoBucket.PROMO_CLICKED);
1137 this.appState_.persistIsGcpPromoDismissed(true);
1138 window.open(this.cloudPrintInterface_.baseUrl + '?user=' +
1139 this.userInfo_.activeUser + '#printers');
1146 PrintPreview: PrintPreview
1150 // Pull in all other scripts in a single shot.
1151 <include src="common/overlay.js"/>
1152 <include src="common/search_box.js"/>
1154 <include src="data/page_number_set.js"/>
1155 <include src="data/destination.js"/>
1156 <include src="data/local_parsers.js"/>
1157 <include src="data/cloud_parsers.js"/>
1158 <include src="data/destination_store.js"/>
1159 <include src="data/margins.js"/>
1160 <include src="data/document_info.js"/>
1161 <include src="data/printable_area.js"/>
1162 <include src="data/measurement_system.js"/>
1163 <include src="data/print_ticket_store.js"/>
1164 <include src="data/coordinate2d.js"/>
1165 <include src="data/size.js"/>
1166 <include src="data/capabilities_holder.js"/>
1167 <include src="data/user_info.js"/>
1168 <include src="data/app_state.js"/>
1170 <include src="data/ticket_items/ticket_item.js"/>
1172 <include src="data/ticket_items/custom_margins.js"/>
1173 <include src="data/ticket_items/collate.js"/>
1174 <include src="data/ticket_items/color.js"/>
1175 <include src="data/ticket_items/copies.js"/>
1176 <include src="data/ticket_items/duplex.js"/>
1177 <include src="data/ticket_items/header_footer.js"/>
1178 <include src="data/ticket_items/media_size.js"/>
1179 <include src="data/ticket_items/landscape.js"/>
1180 <include src="data/ticket_items/margins_type.js"/>
1181 <include src="data/ticket_items/page_range.js"/>
1182 <include src="data/ticket_items/fit_to_page.js"/>
1183 <include src="data/ticket_items/css_background.js"/>
1184 <include src="data/ticket_items/selection_only.js"/>
1186 <include src="native_layer.js"/>
1187 <include src="print_preview_animations.js"/>
1188 <include src="cloud_print_interface.js"/>
1189 <include src="print_preview_utils.js"/>
1190 <include src="print_header.js"/>
1191 <include src="metrics.js"/>
1193 <include src="settings/page_settings.js"/>
1194 <include src="settings/copies_settings.js"/>
1195 <include src="settings/media_size_settings.js"/>
1196 <include src="settings/layout_settings.js"/>
1197 <include src="settings/color_settings.js"/>
1198 <include src="settings/margin_settings.js"/>
1199 <include src="settings/destination_settings.js"/>
1200 <include src="settings/other_options_settings.js"/>
1201 <include src="settings/advanced_options_settings.js"/>
1202 <include src="settings/advanced_settings/advanced_settings.js"/>
1203 <include src="settings/advanced_settings/advanced_settings_item.js"/>
1205 <include src="previewarea/margin_control.js"/>
1206 <include src="previewarea/margin_control_container.js"/>
1207 <include src="../pdf/pdf_scripting_api.js" />
1208 <include src="previewarea/preview_area.js"/>
1209 <include src="preview_generator.js"/>
1211 <include src="search/destination_list.js"/>
1212 <include src="search/cloud_destination_list.js"/>
1213 <include src="search/recent_destination_list.js"/>
1214 <include src="search/destination_list_item.js"/>
1215 <include src="search/destination_search.js"/>
1216 <include src="search/fedex_tos.js"/>
1218 window.addEventListener('DOMContentLoaded', function() {
1219 printPreview = new print_preview.PrintPreview();
1220 printPreview.initialize();