Fix infinite recursion on hiding panel when created during fullscreen mode.
[chromium-blink-merge.git] / chrome / browser / resources / print_preview / print_preview.js
bloba85ce2c6b8a9fe7c0d94004192e8105f3d41893e
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"/>
11 cr.define('print_preview', function() {
12 'use strict';
14 /**
15 * Container class for Chromium's print preview.
16 * @constructor
17 * @extends {print_preview.Component}
19 function PrintPreview() {
20 print_preview.Component.call(this);
22 /**
23 * Used to communicate with Chromium's print system.
24 * @type {!print_preview.NativeLayer}
25 * @private
27 this.nativeLayer_ = new print_preview.NativeLayer();
29 /**
30 * Event target that contains information about the logged in user.
31 * @type {!print_preview.UserInfo}
32 * @private
34 this.userInfo_ = new print_preview.UserInfo();
36 /**
37 * Metrics object used to report usage statistics.
38 * @type {!print_preview.Metrics}
39 * @private
41 this.metrics_ = new print_preview.Metrics();
43 /**
44 * Application state.
45 * @type {!print_preview.AppState}
46 * @private
48 this.appState_ = new print_preview.AppState();
50 /**
51 * Data model that holds information about the document to print.
52 * @type {!print_preview.DocumentInfo}
53 * @private
55 this.documentInfo_ = new print_preview.DocumentInfo();
57 /**
58 * Data store which holds print destinations.
59 * @type {!print_preview.DestinationStore}
60 * @private
62 this.destinationStore_ = new print_preview.DestinationStore(
63 this.nativeLayer_, this.appState_, this.metrics_);
65 /**
66 * Storage of the print ticket used to create the print job.
67 * @type {!print_preview.PrintTicketStore}
68 * @private
70 this.printTicketStore_ = new print_preview.PrintTicketStore(
71 this.destinationStore_, this.appState_, this.documentInfo_);
73 /**
74 * Holds the print and cancel buttons and renders some document statistics.
75 * @type {!print_preview.PrintHeader}
76 * @private
78 this.printHeader_ = new print_preview.PrintHeader(
79 this.printTicketStore_, this.destinationStore_);
80 this.addChild(this.printHeader_);
82 /**
83 * Component used to search for print destinations.
84 * @type {!print_preview.DestinationSearch}
85 * @private
87 this.destinationSearch_ = new print_preview.DestinationSearch(
88 this.destinationStore_, this.userInfo_, this.metrics_);
89 this.addChild(this.destinationSearch_);
91 /**
92 * Component that renders the print destination.
93 * @type {!print_preview.DestinationSettings}
94 * @private
96 this.destinationSettings_ = new print_preview.DestinationSettings(
97 this.destinationStore_);
98 this.addChild(this.destinationSettings_);
101 * Component that renders UI for entering in page range.
102 * @type {!print_preview.PageSettings}
103 * @private
105 this.pageSettings_ = new print_preview.PageSettings(
106 this.printTicketStore_.pageRange);
107 this.addChild(this.pageSettings_);
110 * Component that renders the copies settings.
111 * @type {!print_preview.CopiesSettings}
112 * @private
114 this.copiesSettings_ = new print_preview.CopiesSettings(
115 this.printTicketStore_.copies, this.printTicketStore_.collate);
116 this.addChild(this.copiesSettings_);
119 * Component that renders the layout settings.
120 * @type {!print_preview.LayoutSettings}
121 * @private
123 this.layoutSettings_ =
124 new print_preview.LayoutSettings(this.printTicketStore_.landscape);
125 this.addChild(this.layoutSettings_);
128 * Component that renders the color options.
129 * @type {!print_preview.ColorSettings}
130 * @private
132 this.colorSettings_ =
133 new print_preview.ColorSettings(this.printTicketStore_.color);
134 this.addChild(this.colorSettings_);
137 * Component that renders a select box for choosing margin settings.
138 * @type {!print_preview.MarginSettings}
139 * @private
141 this.marginSettings_ =
142 new print_preview.MarginSettings(this.printTicketStore_.marginsType);
143 this.addChild(this.marginSettings_);
146 * Component that renders miscellaneous print options.
147 * @type {!print_preview.OtherOptionsSettings}
148 * @private
150 this.otherOptionsSettings_ = new print_preview.OtherOptionsSettings(
151 this.printTicketStore_.duplex,
152 this.printTicketStore_.fitToPage,
153 this.printTicketStore_.cssBackground,
154 this.printTicketStore_.selectionOnly,
155 this.printTicketStore_.headerFooter);
156 this.addChild(this.otherOptionsSettings_);
159 * Area of the UI that holds the print preview.
160 * @type {!print_preview.PreviewArea}
161 * @private
163 this.previewArea_ = new print_preview.PreviewArea(this.destinationStore_,
164 this.printTicketStore_,
165 this.nativeLayer_,
166 this.documentInfo_);
167 this.addChild(this.previewArea_);
170 * Interface to the Google Cloud Print API. Null if Google Cloud Print
171 * integration is disabled.
172 * @type {cloudprint.CloudPrintInterface}
173 * @private
175 this.cloudPrintInterface_ = null;
178 * Whether in kiosk mode where print preview can print automatically without
179 * user intervention. See http://crbug.com/31395. Print will start when
180 * both the print ticket has been initialized, and an initial printer has
181 * been selected.
182 * @type {boolean}
183 * @private
185 this.isInKioskAutoPrintMode_ = false;
188 * State of the print preview UI.
189 * @type {print_preview.PrintPreview.UiState_}
190 * @private
192 this.uiState_ = PrintPreview.UiState_.INITIALIZING;
195 * Whether document preview generation is in progress.
196 * @type {boolean}
197 * @private
199 this.isPreviewGenerationInProgress_ = true;
203 * States of the print preview.
204 * @enum {string}
205 * @private
207 PrintPreview.UiState_ = {
208 INITIALIZING: 'initializing',
209 READY: 'ready',
210 OPENING_PDF_PREVIEW: 'opening-pdf-preview',
211 OPENING_NATIVE_PRINT_DIALOG: 'opening-native-print-dialog',
212 PRINTING: 'printing',
213 FILE_SELECTION: 'file-selection',
214 CLOSING: 'closing',
215 ERROR: 'error'
219 * What can happen when print preview tries to print.
220 * @enum {string}
221 * @private
223 PrintPreview.PrintAttemptResult_ = {
224 NOT_READY: 'not-ready',
225 PRINTED: 'printed',
226 READY_WAITING_FOR_PREVIEW: 'ready-waiting-for-preview'
229 PrintPreview.prototype = {
230 __proto__: print_preview.Component.prototype,
232 /** Sets up the page and print preview by getting the printer list. */
233 initialize: function() {
234 this.decorate($('print-preview'));
235 i18nTemplate.process(document, templateData);
236 if (!this.previewArea_.hasCompatiblePlugin) {
237 this.setIsEnabled_(false);
239 this.nativeLayer_.startGetInitialSettings();
240 cr.ui.FocusOutlineManager.forDocument(document);
243 /** @override */
244 enterDocument: function() {
245 // Native layer events.
246 this.tracker.add(
247 this.nativeLayer_,
248 print_preview.NativeLayer.EventType.INITIAL_SETTINGS_SET,
249 this.onInitialSettingsSet_.bind(this));
250 this.tracker.add(
251 this.nativeLayer_,
252 print_preview.NativeLayer.EventType.CLOUD_PRINT_ENABLE,
253 this.onCloudPrintEnable_.bind(this));
254 this.tracker.add(
255 this.nativeLayer_,
256 print_preview.NativeLayer.EventType.PRINT_TO_CLOUD,
257 this.onPrintToCloud_.bind(this));
258 this.tracker.add(
259 this.nativeLayer_,
260 print_preview.NativeLayer.EventType.FILE_SELECTION_CANCEL,
261 this.onFileSelectionCancel_.bind(this));
262 this.tracker.add(
263 this.nativeLayer_,
264 print_preview.NativeLayer.EventType.FILE_SELECTION_COMPLETE,
265 this.onFileSelectionComplete_.bind(this));
266 this.tracker.add(
267 this.nativeLayer_,
268 print_preview.NativeLayer.EventType.SETTINGS_INVALID,
269 this.onSettingsInvalid_.bind(this));
270 this.tracker.add(
271 this.nativeLayer_,
272 print_preview.NativeLayer.EventType.DISABLE_SCALING,
273 this.onDisableScaling_.bind(this));
274 this.tracker.add(
275 this.nativeLayer_,
276 print_preview.NativeLayer.EventType.PRIVET_PRINT_FAILED,
277 this.onPrivetPrintFailed_.bind(this));
280 this.tracker.add(
281 $('system-dialog-link'),
282 'click',
283 this.openSystemPrintDialog_.bind(this));
284 this.tracker.add(
285 $('cloud-print-dialog-link'),
286 'click',
287 this.onCloudPrintDialogLinkClick_.bind(this));
288 this.tracker.add(
289 $('open-pdf-in-preview-link'),
290 'click',
291 this.onOpenPdfInPreviewLinkClick_.bind(this));
293 this.tracker.add(
294 this.previewArea_,
295 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS,
296 this.onPreviewGenerationInProgress_.bind(this));
297 this.tracker.add(
298 this.previewArea_,
299 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE,
300 this.onPreviewGenerationDone_.bind(this));
301 this.tracker.add(
302 this.previewArea_,
303 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_FAIL,
304 this.onPreviewGenerationFail_.bind(this));
305 this.tracker.add(
306 this.previewArea_,
307 print_preview.PreviewArea.EventType.OPEN_SYSTEM_DIALOG_CLICK,
308 this.openSystemPrintDialog_.bind(this));
310 this.tracker.add(
311 this.destinationStore_,
312 print_preview.DestinationStore.EventType.
313 SELECTED_DESTINATION_CAPABILITIES_READY,
314 this.printIfReady_.bind(this));
315 this.tracker.add(
316 this.destinationStore_,
317 print_preview.DestinationStore.EventType.DESTINATION_SELECT,
318 this.onDestinationSelect_.bind(this));
319 this.tracker.add(
320 this.destinationStore_,
321 print_preview.DestinationStore.EventType.DESTINATION_SEARCH_DONE,
322 this.onDestinationSearchDone_.bind(this));
324 this.tracker.add(
325 this.printHeader_,
326 print_preview.PrintHeader.EventType.PRINT_BUTTON_CLICK,
327 this.onPrintButtonClick_.bind(this));
328 this.tracker.add(
329 this.printHeader_,
330 print_preview.PrintHeader.EventType.CANCEL_BUTTON_CLICK,
331 this.onCancelButtonClick_.bind(this));
333 this.tracker.add(window, 'keydown', this.onKeyDown_.bind(this));
335 this.tracker.add(
336 this.destinationSettings_,
337 print_preview.DestinationSettings.EventType.CHANGE_BUTTON_ACTIVATE,
338 this.onDestinationChangeButtonActivate_.bind(this));
340 this.tracker.add(
341 this.destinationSearch_,
342 print_preview.DestinationSearch.EventType.MANAGE_CLOUD_DESTINATIONS,
343 this.onManageCloudDestinationsActivated_.bind(this));
344 this.tracker.add(
345 this.destinationSearch_,
346 print_preview.DestinationSearch.EventType.MANAGE_LOCAL_DESTINATIONS,
347 this.onManageLocalDestinationsActivated_.bind(this));
348 this.tracker.add(
349 this.destinationSearch_,
350 print_preview.DestinationSearch.EventType.SIGN_IN,
351 this.onCloudPrintSignInActivated_.bind(this));
352 this.tracker.add(
353 this.destinationSearch_,
354 print_preview.DestinationListItem.EventType.REGISTER_PROMO_CLICKED,
355 this.onCloudPrintRegisterPromoClick_.bind(this));
357 // TODO(rltoscano): Move no-destinations-promo into its own component
358 // instead being part of PrintPreview.
359 this.tracker.add(
360 this.getChildElement('#no-destinations-promo .close-button'),
361 'click',
362 this.onNoDestinationsPromoClose_.bind(this));
363 this.tracker.add(
364 this.getChildElement('#no-destinations-promo .not-now-button'),
365 'click',
366 this.onNoDestinationsPromoClose_.bind(this));
367 this.tracker.add(
368 this.getChildElement('#no-destinations-promo .add-printer-button'),
369 'click',
370 this.onNoDestinationsPromoClick_.bind(this));
373 /** @override */
374 decorateInternal: function() {
375 this.printHeader_.decorate($('print-header'));
376 this.destinationSearch_.decorate($('destination-search'));
377 this.destinationSettings_.decorate($('destination-settings'));
378 this.pageSettings_.decorate($('page-settings'));
379 this.copiesSettings_.decorate($('copies-settings'));
380 this.layoutSettings_.decorate($('layout-settings'));
381 this.colorSettings_.decorate($('color-settings'));
382 this.marginSettings_.decorate($('margin-settings'));
383 this.otherOptionsSettings_.decorate($('other-options-settings'));
384 this.previewArea_.decorate($('preview-area'));
386 setIsVisible($('open-pdf-in-preview-link'), cr.isMac);
390 * Sets whether the controls in the print preview are enabled.
391 * @param {boolean} isEnabled Whether the controls in the print preview are
392 * enabled.
393 * @private
395 setIsEnabled_: function(isEnabled) {
396 $('system-dialog-link').disabled = !isEnabled;
397 $('cloud-print-dialog-link').disabled = !isEnabled;
398 $('open-pdf-in-preview-link').disabled = !isEnabled;
399 this.printHeader_.isEnabled = isEnabled;
400 this.destinationSettings_.isEnabled = isEnabled;
401 this.pageSettings_.isEnabled = isEnabled;
402 this.copiesSettings_.isEnabled = isEnabled;
403 this.layoutSettings_.isEnabled = isEnabled;
404 this.colorSettings_.isEnabled = isEnabled;
405 this.marginSettings_.isEnabled = isEnabled;
406 this.otherOptionsSettings_.isEnabled = isEnabled;
410 * Prints the document or launches a pdf preview on the local system.
411 * @param {boolean} isPdfPreview Whether to launch the pdf preview.
412 * @private
414 printDocumentOrOpenPdfPreview_: function(isPdfPreview) {
415 assert(this.uiState_ == PrintPreview.UiState_.READY,
416 'Print document request received when not in ready state: ' +
417 this.uiState_);
418 if (isPdfPreview) {
419 this.uiState_ = PrintPreview.UiState_.OPENING_PDF_PREVIEW;
420 } else if (this.destinationStore_.selectedDestination.id ==
421 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
422 this.uiState_ = PrintPreview.UiState_.FILE_SELECTION;
423 } else {
424 this.uiState_ = PrintPreview.UiState_.PRINTING;
426 this.setIsEnabled_(false);
427 this.printHeader_.isCancelButtonEnabled = true;
428 var printAttemptResult = this.printIfReady_();
429 if (printAttemptResult == PrintPreview.PrintAttemptResult_.PRINTED ||
430 printAttemptResult ==
431 PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW) {
432 if ((this.destinationStore_.selectedDestination.isLocal &&
433 !this.destinationStore_.selectedDestination.isPrivet &&
434 this.destinationStore_.selectedDestination.id !=
435 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) ||
436 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW) {
437 // Hide the dialog for now. The actual print command will be issued
438 // when the preview generation is done.
439 this.nativeLayer_.startHideDialog();
445 * Attempts to print if needed and if ready.
446 * @return {PrintPreview.PrintAttemptResult_} Attempt result.
447 * @private
449 printIfReady_: function() {
450 var okToPrint =
451 (this.uiState_ == PrintPreview.UiState_.PRINTING ||
452 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW ||
453 this.uiState_ == PrintPreview.UiState_.FILE_SELECTION ||
454 this.isInKioskAutoPrintMode_) &&
455 this.destinationStore_.selectedDestination &&
456 this.destinationStore_.selectedDestination.capabilities;
457 if (!okToPrint) {
458 return PrintPreview.PrintAttemptResult_.NOT_READY;
460 if (this.isPreviewGenerationInProgress_) {
461 return PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW;
463 assert(this.printTicketStore_.isTicketValid(),
464 'Trying to print with invalid ticket');
465 this.nativeLayer_.startPrint(
466 this.destinationStore_.selectedDestination,
467 this.printTicketStore_,
468 this.cloudPrintInterface_,
469 this.documentInfo_,
470 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW);
471 return PrintPreview.PrintAttemptResult_.PRINTED;
475 * Closes the print preview.
476 * @private
478 close_: function() {
479 this.exitDocument();
480 this.uiState_ = PrintPreview.UiState_.CLOSING;
481 this.nativeLayer_.startCloseDialog();
485 * Opens the native system print dialog after disabling all controls.
486 * @private
488 openSystemPrintDialog_: function() {
489 setIsVisible($('system-dialog-throbber'), true);
490 this.setIsEnabled_(false);
491 this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
492 this.nativeLayer_.startShowSystemDialog();
496 * Called when the native layer has initial settings to set. Sets the
497 * initial settings of the print preview and begins fetching print
498 * destinations.
499 * @param {Event} event Contains the initial print preview settings
500 * persisted through the session.
501 * @private
503 onInitialSettingsSet_: function(event) {
504 assert(this.uiState_ == PrintPreview.UiState_.INITIALIZING,
505 'Updating initial settings when not in initializing state: ' +
506 this.uiState_);
507 this.uiState_ = PrintPreview.UiState_.READY;
509 var settings = event.initialSettings;
510 this.isInKioskAutoPrintMode_ = settings.isInKioskAutoPrintMode;
512 // The following components must be initialized in this order.
513 this.appState_.init(settings.serializedAppStateStr);
514 this.documentInfo_.init(
515 settings.isDocumentModifiable,
516 settings.documentTitle,
517 settings.documentHasSelection);
518 this.printTicketStore_.init(
519 settings.thousandsDelimeter,
520 settings.decimalDelimeter,
521 settings.unitType,
522 settings.selectionOnly);
523 this.destinationStore_.init(settings.systemDefaultDestinationId);
524 this.appState_.setInitialized();
526 $('document-title').innerText = settings.documentTitle;
527 setIsVisible($('system-dialog-link'),
528 !settings.hidePrintWithSystemDialogLink);
532 * Calls when the native layer enables Google Cloud Print integration.
533 * Fetches the user's cloud printers.
534 * @param {Event} event Contains the base URL of the Google Cloud Print
535 * service.
536 * @private
538 onCloudPrintEnable_: function(event) {
539 this.cloudPrintInterface_ =
540 new cloudprint.CloudPrintInterface(event.baseCloudPrintUrl,
541 this.nativeLayer_);
542 this.tracker.add(
543 this.cloudPrintInterface_,
544 cloudprint.CloudPrintInterface.EventType.SUBMIT_DONE,
545 this.onCloudPrintSubmitDone_.bind(this));
546 this.tracker.add(
547 this.cloudPrintInterface_,
548 cloudprint.CloudPrintInterface.EventType.SEARCH_FAILED,
549 this.onCloudPrintError_.bind(this));
550 this.tracker.add(
551 this.cloudPrintInterface_,
552 cloudprint.CloudPrintInterface.EventType.SUBMIT_FAILED,
553 this.onCloudPrintError_.bind(this));
554 this.tracker.add(
555 this.cloudPrintInterface_,
556 cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED,
557 this.onCloudPrintError_.bind(this));
558 this.tracker.add(
559 this.cloudPrintInterface_,
560 cloudprint.CloudPrintInterface.EventType.
561 UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED,
562 this.onCloudPrintError_.bind(this));
564 this.userInfo_.setCloudPrintInterface(this.cloudPrintInterface_);
565 this.destinationStore_.setCloudPrintInterface(this.cloudPrintInterface_);
566 if (this.destinationSearch_.getIsVisible()) {
567 this.destinationStore_.startLoadCloudDestinations();
572 * Called from the native layer when ready to print to Google Cloud Print.
573 * @param {Event} event Contains the body to send in the HTTP request.
574 * @private
576 onPrintToCloud_: function(event) {
577 assert(this.uiState_ == PrintPreview.UiState_.PRINTING,
578 'Document ready to be sent to the cloud when not in printing ' +
579 'state: ' + this.uiState_);
580 assert(this.cloudPrintInterface_ != null,
581 'Google Cloud Print is not enabled');
582 this.cloudPrintInterface_.submit(
583 this.destinationStore_.selectedDestination,
584 this.printTicketStore_,
585 this.documentInfo_,
586 event.data);
590 * Called from the native layer when the user cancels the save-to-pdf file
591 * selection dialog.
592 * @private
594 onFileSelectionCancel_: function() {
595 assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,
596 'File selection cancelled when not in file-selection state: ' +
597 this.uiState_);
598 this.setIsEnabled_(true);
599 this.uiState_ = PrintPreview.UiState_.READY;
603 * Called from the native layer when save-to-pdf file selection is complete.
604 * @private
606 onFileSelectionComplete_: function() {
607 assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,
608 'File selection completed when not in file-selection state: ' +
609 this.uiState_);
610 this.previewArea_.showCustomMessage(
611 localStrings.getString('printingToPDFInProgress'));
612 this.uiState_ = PrintPreview.UiState_.PRINTING;
616 * Called after successfully submitting a job to Google Cloud Print.
617 * @param {!Event} event Contains the ID of the submitted print job.
618 * @private
620 onCloudPrintSubmitDone_: function(event) {
621 assert(this.uiState_ == PrintPreview.UiState_.PRINTING,
622 'Submited job to Google Cloud Print but not in printing state ' +
623 this.uiState_);
624 if (this.destinationStore_.selectedDestination.id ==
625 print_preview.Destination.GooglePromotedId.FEDEX) {
626 this.nativeLayer_.startForceOpenNewTab(
627 'https://www.google.com/cloudprint/fedexcode.html?jobid=' +
628 event.jobId);
630 this.close_();
634 * Called when there was an error communicating with Google Cloud print.
635 * Displays an error message in the print header.
636 * @param {!Event} event Contains the error message.
637 * @private
639 onCloudPrintError_: function(event) {
640 if (event.status == 403) {
641 this.destinationSearch_.showCloudPrintPromo();
642 } else if (event.status == 0) {
643 return; // Ignore, the system does not have internet connectivity.
644 } else {
645 this.printHeader_.setErrorMessage(event.message);
647 if (event.status == 200) {
648 console.error('Google Cloud Print Error: (' + event.errorCode + ') ' +
649 event.message);
650 } else {
651 console.error('Google Cloud Print Error: HTTP status ' + event.status);
656 * Called when the preview area's preview generation is in progress.
657 * @private
659 onPreviewGenerationInProgress_: function() {
660 this.isPreviewGenerationInProgress_ = true;
664 * Called when the preview area's preview generation is complete.
665 * @private
667 onPreviewGenerationDone_: function() {
668 this.isPreviewGenerationInProgress_ = false;
669 this.printHeader_.isPrintButtonEnabled = true;
670 this.printIfReady_();
674 * Called when the preview area's preview failed to load.
675 * @private
677 onPreviewGenerationFail_: function() {
678 this.isPreviewGenerationInProgress_ = false;
679 this.printHeader_.isPrintButtonEnabled = false;
680 if (this.uiState_ == PrintPreview.UiState_.PRINTING) {
681 this.nativeLayer_.startCancelPendingPrint();
686 * Called when the 'Open pdf in preview' link is clicked. Launches the pdf
687 * preview app.
688 * @private
690 onOpenPdfInPreviewLinkClick_: function() {
691 assert(this.uiState_ == PrintPreview.UiState_.READY,
692 'Trying to open pdf in preview when not in ready state: ' +
693 this.uiState_);
694 setIsVisible($('open-preview-app-throbber'), true);
695 this.previewArea_.showCustomMessage(
696 localStrings.getString('openingPDFInPreview'));
697 this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
701 * Called when the print header's print button is clicked. Prints the
702 * document.
703 * @private
705 onPrintButtonClick_: function() {
706 assert(this.uiState_ == PrintPreview.UiState_.READY,
707 'Trying to print when not in ready state: ' + this.uiState_);
708 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
712 * Called when the print header's cancel button is clicked. Closes the
713 * print dialog.
714 * @private
716 onCancelButtonClick_: function() {
717 this.close_();
721 * Called when the register promo for Cloud Print is clicked.
722 * @private
724 onCloudPrintRegisterPromoClick_: function(e) {
725 this.metrics_.incrementDestinationSearchBucket(
726 print_preview.Metrics.DestinationSearchBucket.REGISTER_PROMO_SELECTED);
727 var devicesUrl = 'chrome://devices/register?id=' + e.destination.id;
728 this.nativeLayer_.startForceOpenNewTab(devicesUrl);
729 this.destinationStore_.waitForRegister(e.destination.id);
733 * Consume escape key presses and ctrl + shift + p. Delegate everything else
734 * to the preview area.
735 * @param {KeyboardEvent} e The keyboard event.
736 * @private
738 onKeyDown_: function(e) {
739 // Escape key closes the dialog.
740 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&
741 !e.metaKey) {
742 if (this.destinationSearch_.getIsVisible()) {
743 this.destinationSearch_.setIsVisible(false);
744 this.metrics_.incrementDestinationSearchBucket(
745 print_preview.Metrics.DestinationSearchBucket.CANCELED);
746 } else {
747 <if expr="toolkit_views">
748 // On the toolkit_views environment, ESC key is handled by C++-side
749 // instead of JS-side.
750 return;
751 </if>
752 <if expr="not toolkit_views">
753 this.close_();
754 </if>
756 e.preventDefault();
757 return;
760 // Ctrl + Shift + p / Mac equivalent.
761 if (e.keyCode == 80) {
762 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
763 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
764 this.openSystemPrintDialog_();
765 e.preventDefault();
766 return;
770 if (e.keyCode == 13 /*enter*/ &&
771 !this.destinationSearch_.getIsVisible() &&
772 this.printTicketStore_.isTicketValid()) {
773 assert(this.uiState_ == PrintPreview.UiState_.READY,
774 'Trying to print when not in ready state: ' + this.uiState_);
775 var activeElementTag = document.activeElement ?
776 document.activeElement.tagName.toUpperCase() : '';
777 if (activeElementTag != 'BUTTON' && activeElementTag != 'SELECT') {
778 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
779 e.preventDefault();
781 return;
784 // Pass certain directional keyboard events to the PDF viewer.
785 this.previewArea_.handleDirectionalKeyEvent(e);
789 * Called when native layer receives invalid settings for a print request.
790 * @private
792 onSettingsInvalid_: function() {
793 this.uiState_ = PrintPreview.UiState_.ERROR;
794 console.error('Invalid settings error reported from native layer');
795 this.previewArea_.showCustomMessage(
796 localStrings.getString('invalidPrinterSettings'));
800 * Called when the destination settings' change button is activated.
801 * Displays the destination search component.
802 * @private
804 onDestinationChangeButtonActivate_: function() {
805 this.destinationSearch_.setIsVisible(true);
806 this.destinationStore_.startLoadCloudDestinations();
807 this.destinationStore_.startLoadLocalDestinations();
808 this.destinationStore_.startLoadPrivetDestinations();
809 this.metrics_.incrementDestinationSearchBucket(
810 print_preview.Metrics.DestinationSearchBucket.SHOWN);
814 * Called when the destination search dispatches manage cloud destinations
815 * event. Calls corresponding native layer method.
816 * @private
818 onManageCloudDestinationsActivated_: function() {
819 this.nativeLayer_.startManageCloudDestinations();
823 * Called when the destination search dispatches manage local destinations
824 * event. Calls corresponding native layer method.
825 * @private
827 onManageLocalDestinationsActivated_: function() {
828 this.nativeLayer_.startManageLocalDestinations();
832 * Called when the user wants to sign in to Google Cloud Print. Calls the
833 * corresponding native layer event.
834 * @private
836 onCloudPrintSignInActivated_: function() {
837 this.nativeLayer_.startCloudPrintSignIn();
841 * Called when the native layer dispatches a DISABLE_SCALING event. Resets
842 * fit-to-page selection and updates document info.
843 * @private
845 onDisableScaling_: function() {
846 this.printTicketStore_.fitToPage.updateValue(null);
847 this.documentInfo_.updateIsScalingDisabled(true);
851 * Called when privet printing fails.
852 * @param {Event} event Event object representing the failure.
853 * @private
855 onPrivetPrintFailed_: function(event) {
856 console.error('Privet printing failed with error code ' +
857 event.httpError);
858 this.printHeader_.setErrorMessage(
859 localStrings.getString('couldNotPrint'));
863 * Called when the open-cloud-print-dialog link is clicked. Opens the Google
864 * Cloud Print web dialog.
865 * @private
867 onCloudPrintDialogLinkClick_: function() {
868 assert(this.uiState_ == PrintPreview.UiState_.READY,
869 'Opening Google Cloud Print dialog when not in ready state: ' +
870 this.uiState_);
871 setIsVisible($('cloud-print-dialog-throbber'), true);
872 this.setIsEnabled_(false);
873 this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
874 this.nativeLayer_.startShowCloudPrintDialog(
875 this.printTicketStore_.pageRange.getPageNumberSet().size);
879 * Called when a print destination is selected. Shows/hides the "Print with
880 * Cloud Print" link in the navbar.
881 * @private
883 onDestinationSelect_: function() {
884 var selectedDest = this.destinationStore_.selectedDestination;
885 setIsVisible($('cloud-print-dialog-link'),
886 !cr.isChromeOS && !selectedDest.isLocal);
890 * Called when the destination store loads a group of destinations. Shows
891 * a promo on Chrome OS if the user has no print destinations promoting
892 * Google Cloud Print.
893 * @private
895 onDestinationSearchDone_: function() {
896 var isPromoVisible = cr.isChromeOS &&
897 this.cloudPrintInterface_ &&
898 this.userInfo_.getUserEmail() &&
899 !this.appState_.isGcpPromoDismissed &&
900 !this.destinationStore_.isLocalDestinationsSearchInProgress &&
901 !this.destinationStore_.isCloudDestinationsSearchInProgress &&
902 this.destinationStore_.hasOnlyDefaultCloudDestinations();
903 setIsVisible(this.getChildElement('#no-destinations-promo'),
904 isPromoVisible);
905 if (isPromoVisible) {
906 this.metrics_.incrementGcpPromoBucket(
907 print_preview.Metrics.GcpPromoBucket.SHOWN);
912 * Called when the close button on the no-destinations-promotion is clicked.
913 * Hides the promotion.
914 * @private
916 onNoDestinationsPromoClose_: function() {
917 this.metrics_.incrementGcpPromoBucket(
918 print_preview.Metrics.GcpPromoBucket.DISMISSED);
919 setIsVisible(this.getChildElement('#no-destinations-promo'), false);
920 this.appState_.persistIsGcpPromoDismissed(true);
924 * Called when the no-destinations promotion link is clicked. Opens the
925 * Google Cloud Print management page and closes the print preview.
926 * @private
928 onNoDestinationsPromoClick_: function() {
929 this.metrics_.incrementGcpPromoBucket(
930 print_preview.Metrics.GcpPromoBucket.CLICKED);
931 this.appState_.persistIsGcpPromoDismissed(true);
932 window.open(this.cloudPrintInterface_.baseUrl + '?user=' +
933 this.userInfo_.getUserEmail() + '#printers');
934 this.close_();
938 // Export
939 return {
940 PrintPreview: PrintPreview
944 // Pull in all other scripts in a single shot.
945 <include src="data/page_number_set.js"/>
946 <include src="data/destination.js"/>
947 <include src="data/local_parsers.js"/>
948 <include src="data/cloud_parsers.js"/>
949 <include src="data/destination_store.js"/>
950 <include src="data/margins.js"/>
951 <include src="data/document_info.js"/>
952 <include src="data/printable_area.js"/>
953 <include src="data/measurement_system.js"/>
954 <include src="data/print_ticket_store.js"/>
955 <include src="data/coordinate2d.js"/>
956 <include src="data/size.js"/>
957 <include src="data/capabilities_holder.js"/>
958 <include src="data/user_info.js"/>
959 <include src="data/app_state.js"/>
961 <include src="data/ticket_items/ticket_item.js"/>
963 <include src="data/ticket_items/custom_margins.js"/>
964 <include src="data/ticket_items/collate.js"/>
965 <include src="data/ticket_items/color.js"/>
966 <include src="data/ticket_items/copies.js"/>
967 <include src="data/ticket_items/duplex.js"/>
968 <include src="data/ticket_items/header_footer.js"/>
969 <include src="data/ticket_items/landscape.js"/>
970 <include src="data/ticket_items/margins_type.js"/>
971 <include src="data/ticket_items/page_range.js"/>
972 <include src="data/ticket_items/fit_to_page.js"/>
973 <include src="data/ticket_items/css_background.js"/>
974 <include src="data/ticket_items/selection_only.js"/>
976 <include src="native_layer.js"/>
977 <include src="print_preview_animations.js"/>
978 <include src="cloud_print_interface.js"/>
979 <include src="print_preview_utils.js"/>
980 <include src="print_header.js"/>
981 <include src="metrics.js"/>
983 <include src="settings/page_settings.js"/>
984 <include src="settings/copies_settings.js"/>
985 <include src="settings/layout_settings.js"/>
986 <include src="settings/color_settings.js"/>
987 <include src="settings/margin_settings.js"/>
988 <include src="settings/destination_settings.js"/>
989 <include src="settings/other_options_settings.js"/>
991 <include src="previewarea/margin_control.js"/>
992 <include src="previewarea/margin_control_container.js"/>
993 <include src="previewarea/preview_area.js"/>
994 <include src="preview_generator.js"/>
996 <include src="search/destination_list.js"/>
997 <include src="search/cloud_destination_list.js"/>
998 <include src="search/recent_destination_list.js"/>
999 <include src="search/destination_list_item.js"/>
1000 <include src="search/destination_search.js"/>
1001 <include src="search/search_box.js"/>
1002 <include src="search/fedex_tos.js"/>
1004 window.addEventListener('DOMContentLoaded', function() {
1005 printPreview = new print_preview.PrintPreview();
1006 printPreview.initialize();