Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Side by Side Diff: chrome/browser/resources/print_preview/print_preview.js

Issue 10108001: Refactor print preview web ui (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address reviewer comments Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // require: cr/ui/print_preview_cloud.js 5 // TODO Might be a problem where might be in fetching destinations state, then
6 // to file selection state, then cancel, which results in the fetching
7 // destinations state being lost.
8
9 // TODO Move data/* into print_preview.data namespace
10
11 // TODO Handle case where cloud print is initial destination, but cloud print is
12 // not enabled.
6 13
7 var localStrings = new LocalStrings(); 14 var localStrings = new LocalStrings();
8 15
9 // If useCloudPrint is true we attempt to connect to cloud print 16 <include src="component.js"/>
10 // and populate the list of printers with cloud print printers. 17
11 var useCloudPrint = false; 18 cr.define('print_preview', function() {
12 19 'use strict';
13 // Store the last selected printer index. 20
14 var lastSelectedPrinterIndex = 0; 21 /**
15 22 * Container class for Chromium's print preview.
16 // Used to disable some printing options when the preview is not modifiable. 23 * @constructor
17 var previewModifiable = false; 24 * @extends {print_preview.Component}
18 25 */
19 // Used to identify whether the printing frame has specific page size style. 26 function PrintPreview() {
20 var hasPageSizeStyle = false; 27 print_preview.Component.call(this);
21 28
22 // Destination list special value constants. 29 /**
23 30 * Used to communicate with Chromium's print system.
24 /** @const */ var MANAGE_CLOUD_PRINTERS = 'manageCloudPrinters'; 31 * @type {!print_preview.NativeLayer}
25 /** @const */ var MANAGE_LOCAL_PRINTERS = 'manageLocalPrinters'; 32 * @private
26 /** @const */ var SIGN_IN = 'signIn'; 33 */
27 /** @const */ var PRINT_TO_PDF = 'Save as PDF'; 34 this.nativeLayer_ = new print_preview.NativeLayer();
28 /** @const */ var PRINT_WITH_CLOUD_PRINT = 'printWithCloudPrint'; 35
29 36 /**
30 // State of the print preview settings. 37 * Data store which holds print destinations.
31 var printSettings = new PrintSettings(); 38 * @type {!print_preview.DestinationStore}
32 39 * @private
33 // Print ready data index. 40 */
34 /** @const */ var PRINT_READY_DATA_INDEX = -1; 41 this.destinationStore_ = new print_preview.DestinationStore();
35 42
36 // The name of the default or last used printer. 43 /**
37 var defaultOrLastUsedPrinterName = ''; 44 * Storage of the print ticket used to create the print job.
38 45 * @type {!print_preview.PrintTicketStore}
39 // True when a pending print preview request exists. 46 * @private
40 var hasPendingPreviewRequest = false; 47 */
41 48 this.printTicketStore_ = new print_preview.PrintTicketStore(
42 // True when the first page is loaded in the plugin. 49 this.destinationStore_);
43 var isFirstPageLoaded = false; 50
44 51 /**
45 // The ID of the last preview request. 52 * Holds the print and cancel buttons and renders some document statistics.
46 var lastPreviewRequestID = -1; 53 * @type {!print_preview.PrintHeader}
47 54 * @private
48 // The ID of the initial preview request. 55 */
49 var initialPreviewRequestID = -1; 56 this.printHeader_ = new print_preview.PrintHeader(
50 57 this.printTicketStore_, this.destinationStore_);
51 // True when a pending print file request exists. 58 this.addChild(this.printHeader_);
52 var hasPendingPrintDocumentRequest = false; 59
53 60 /**
54 // True when the complete metafile for the previewed doc is ready. 61 * Component that renders the print destination.
55 var isPrintReadyMetafileReady = false; 62 * @type {!print_preview.DestinationSettings}
56 63 * @private
57 // True when preview tab is hidden. 64 */
58 var isTabHidden = false; 65 this.destinationSettings_ = new print_preview.DestinationSettings(
59 66 this.destinationStore_);
60 // True in kiosk mode where print preview can print automatically without 67 this.addChild(this.destinationSettings_);
61 // user intervention. See http://crbug.com/31395. 68
62 var printAutomaticallyInKioskMode = false; 69 /**
63 70 * Component that renders UI for entering in page range.
64 // @type {print_preview.PrintHeader} Holds the print and cancel buttons. 71 * @type {!print_preview.PageSettings}
65 var printHeader; 72 * @private
66 73 */
67 // @type {print_preview.PageSettings} Holds all the pages related settings. 74 this.pageSettings_ = new print_preview.PageSettings(this.printTicketStore_);
68 var pageSettings; 75 this.addChild(this.pageSettings_);
69 76
70 // @type {print_preview.CopiesSettings} Holds all the copies related settings. 77 /**
71 var copiesSettings; 78 * Component that renders the copies settings.
72 79 * @type {!print_preview.CopiesSettings}
73 // @type {print_preview.LayoutSettings} Holds all the layout related settings. 80 * @private
74 var layoutSettings; 81 */
75 82 this.copiesSettings_ = new print_preview.CopiesSettings(
76 // @type {print_preview.MarginSettings} Holds all the margin related settings. 83 this.printTicketStore_);
77 var marginSettings; 84 this.addChild(this.copiesSettings_);
78 85
79 // @type {print_preview.HeaderFooterSettings} Holds all the header footer 86 /**
80 // related settings. 87 * Component that renders the layout settings.
81 var headerFooterSettings; 88 * @type {!print_preview.LayoutSettings}
82 89 * @private
83 // @type {print_preview.ColorSettings} Holds all the color related settings. 90 */
84 var colorSettings; 91 this.layoutSettings_ = new print_preview.LayoutSettings(
85 92 this.printTicketStore_);
86 // @type {print_preview.PreviewArea} Holds information related to the preview 93 this.addChild(this.layoutSettings_);
87 // area (on the right). 94
88 var previewArea; 95 /**
89 96 * Component that renders the color options.
90 // True if the user has click 'Advanced...' in order to open the system print 97 * @type {!print_preview.ColorSettings}
91 // dialog. 98 * @private
92 var showingSystemDialog = false; 99 */
93 100 this.colorSettings_ = new print_preview.ColorSettings(
94 // True if the user has clicked 'Open PDF in Preview' option. 101 this.printTicketStore_);
95 var previewAppRequested = false; 102 this.addChild(this.colorSettings_);
96 103
97 // The range of options in the printer dropdown controlled by cloud print. 104 /**
98 var firstCloudPrintOptionPos = 0; 105 * Component that renders a select box for choosing margin settings.
99 var lastCloudPrintOptionPos = firstCloudPrintOptionPos; 106 * @type {!print_preview.MarginSettings}
100 107 * @private
101 // Store the current previewUid. 108 */
102 var currentPreviewUid = ''; 109 this.marginSettings_ = new print_preview.MarginSettings(
103 110 this.printTicketStore_);
104 // True if we need to generate draft preview data. 111 this.addChild(this.marginSettings_);
105 var generateDraftData = true; 112
106 113 /**
107 // The last element clicked with the mouse. 114 * Holds all the header footer related settings.
108 var lastClickedElement = null; 115 * @type {!print_preview.HeaderFooterSettings}
109 116 * @private
110 // A dictionary of cloud printers that have been added to the printer 117 */
111 // dropdown. 118 this.headerFooterSettings_ = new print_preview.HeaderFooterSettings(
112 var addedCloudPrinters = {}; 119 this.printTicketStore_);
113 120 this.addChild(this.headerFooterSettings_);
114 // The maximum number of cloud printers to allow in the dropdown. 121
115 /** @const */ var maxCloudPrinters = 10; 122 /**
116 123 * Area of the UI that holds the print preview.
117 /** @const */ var MIN_REQUEST_ID = 0; 124 * @type {!print_preview.PreviewArea}
118 /** @const */ var MAX_REQUEST_ID = 32000; 125 * @private
119 126 */
120 // Names of all the custom events used. 127 this.previewArea_ = new print_preview.PreviewArea(
121 var customEvents = { 128 this.destinationStore_, this.printTicketStore_, this.nativeLayer_);
122 // Fired when the mouse moves while a margin line is being dragged. 129 this.addChild(this.previewArea_);
123 MARGIN_LINE_DRAG: 'marginLineDrag', 130
124 // Fired when a mousedown event occurs on a margin line. 131 /**
125 MARGIN_LINE_MOUSE_DOWN: 'marginLineMouseDown', 132 * Interface to the Google Cloud Print API. Null if Google Cloud Print
126 // Fired when a margin textbox gains focus. 133 * integration is disabled.
127 MARGIN_TEXTBOX_FOCUSED: 'marginTextboxFocused', 134 * @type {cloudprint.CloudPrintInterface}
128 // Fired when a new preview might be needed because of margin changes. 135 * @private
129 MARGINS_MAY_HAVE_CHANGED: 'marginsMayHaveChanged', 136 */
130 // Fired when a pdf generation related error occurs. 137 this.cloudPrintInterface_ = null;
131 PDF_GENERATION_ERROR: 'PDFGenerationError', 138
132 // Fired once the first page of the pdf document is loaded in the plugin. 139 /**
133 PDF_LOADED: 'PDFLoaded', 140 * Whether in kiosk mode where print preview can print automatically without
134 // Fired when the selected printer capabilities change. 141 * user intervention. See http://crbug.com/31395. Print will start when
135 PRINTER_CAPABILITIES_UPDATED: 'printerCapabilitiesUpdated', 142 * both the print ticket has been initialized, and an initial printer has
136 // Fired when the print button needs to be updated. 143 * been selected.
137 UPDATE_PRINT_BUTTON: 'updatePrintButton', 144 * @type {boolean}
138 // Fired when the print summary needs to be updated. 145 * @private
139 UPDATE_SUMMARY: 'updateSummary' 146 */
140 }; 147 this.isInKioskAutoPrintMode_ = false;
141 148
142 /** 149 /**
143 * Window onload handler, sets up the page and starts print preview by getting 150 * State of the print preview UI.
144 * the printer list. 151 * @type {print_preview.PrintPreview.UiState_}
145 */ 152 * @private
146 function onLoad() { 153 */
147 initialPreviewRequestID = randomInteger(MIN_REQUEST_ID, MAX_REQUEST_ID); 154 this.uiState_ = PrintPreview.UiState_.INITIALIZING;
148 lastPreviewRequestID = initialPreviewRequestID; 155
149 156 /**
150 previewArea = print_preview.PreviewArea.getInstance(); 157 * Current state of fetching destinations.
151 printHeader = print_preview.PrintHeader.getInstance(); 158 * @type {print_preview.PrintPreview.FetchState_}
152 document.addEventListener(customEvents.PDF_GENERATION_ERROR, 159 * @private
153 cancelPendingPrintRequest); 160 */
154 document.addEventListener('click', setLastClickedElement); 161 this.fetchState_ = PrintPreview.FetchState_.READY;
155 162
156 if (!checkCompatiblePluginExists()) { 163 /**
157 disableInputElementsInSidebar(); 164 * Whether document preview generation is in progress.
158 $('cancel-button').focus(); 165 * @type {boolean}
159 previewArea.displayErrorMessageWithButtonAndNotify( 166 * @private
160 localStrings.getString('noPlugin'), 167 */
161 localStrings.getString('launchNativeDialog'), 168 this.isPreviewGenerationInProgress_ = true;
162 launchNativePrintDialog); 169
163 $('mainview').parentElement.removeChild($('dummy-viewer')); 170 this.tracker.add(window, 'DOMContentLoaded', this.onWindowLoad_.bind(this));
164 return; 171 };
165 } 172
166 173 /**
167 $('system-dialog-link').addEventListener('click', onSystemDialogLinkClicked); 174 * States of the print preview.
168 if (cr.isMac) { 175 * @enum {string}
169 $('open-pdf-in-preview-link').addEventListener( 176 * @private
170 'click', onOpenPdfInPreviewLinkClicked); 177 */
171 } 178 PrintPreview.UiState_ = {
172 $('mainview').parentElement.removeChild($('dummy-viewer')); 179 INITIALIZING: 'initializing',
173 180 READY: 'ready',
174 $('printer-list').disabled = true; 181 OPENING_PDF_PREVIEW: 'opening-pdf-preview',
175 182 OPENING_NATIVE_PRINT_DIALOG: 'opening-native-print-dialog',
176 pageSettings = print_preview.PageSettings.getInstance(); 183 PRINTING: 'printing',
177 copiesSettings = print_preview.CopiesSettings.getInstance(); 184 FILE_SELECTION: 'file-selection',
178 layoutSettings = print_preview.LayoutSettings.getInstance(); 185 CLOSING: 'closing',
179 marginSettings = print_preview.MarginSettings.getInstance(); 186 ERROR: 'error'
180 headerFooterSettings = print_preview.HeaderFooterSettings.getInstance(); 187 };
181 colorSettings = print_preview.ColorSettings.getInstance(); 188
182 $('printer-list').onchange = updateControlsWithSelectedPrinterCapabilities; 189 /**
183 190 * Bitfield of the states of fetching destinations.
184 previewArea.showLoadingAnimation(); 191 * @enum {number}
185 chrome.send('getInitialSettings'); 192 * @private
186 } 193 */
187 194 PrintPreview.FetchState_ = {
188 /** 195 READY: 1,
189 * @param {object} initialSettings An object containing all the initial 196 LOCAL_DESTINATIONS: 2,
190 * settings. 197 RECENT_CLOUD_DESTINATIONS: 4,
191 */ 198 ALL_CLOUD_DESTINATIONS: 8
192 function setInitialSettings(initialSettings) { 199 };
193 setInitiatorTabTitle(initialSettings['initiatorTabTitle']); 200
194 previewModifiable = initialSettings['previewModifiable']; 201 PrintPreview.prototype = {
195 if (previewModifiable) { 202 __proto__: print_preview.Component.prototype,
196 print_preview.MarginSettings.setNumberFormatAndMeasurementSystem( 203
197 initialSettings['numberFormat'], 204 /** @override */
198 initialSettings['measurementSystem']); 205 decorateInternal: function() {
199 marginSettings.setLastUsedMargins(initialSettings); 206 this.printHeader_.decorate($('print-header'));
200 } 207 this.destinationSettings_.decorate($('destination-settings'));
201 printAutomaticallyInKioskMode = 208 this.pageSettings_.decorate($('page-settings'));
202 initialSettings['printAutomaticallyInKioskMode']; 209 this.copiesSettings_.decorate($('copies-settings'));
203 headerFooterSettings.setChecked(initialSettings['headerFooterEnabled']); 210 this.layoutSettings_.decorate($('layout-settings'));
204 copiesSettings.previousDuplexMode = initialSettings['duplex']; 211 this.colorSettings_.decorate($('color-settings'));
205 setDefaultPrinter(initialSettings['printerName'], 212 this.marginSettings_.decorate($('margin-settings'));
206 initialSettings['cloudPrintData']); 213 this.headerFooterSettings_.decorate($('header-footer-settings'));
207 } 214 this.previewArea_.decorate($('preview-area'));
208 215
209 /** 216 setIsVisible($('cloud-print-dialog-link'), cr.isChromeOS);
210 * Disables the input elements in the sidebar. 217 setIsVisible($('system-dialog-link'), !cr.isChromeOS);
211 */ 218 setIsVisible($('open-pdf-in-preview-link'), cr.isMac);
212 function disableInputElementsInSidebar() { 219 },
213 var els = $('navbar-container').querySelectorAll('input, button, select'); 220
214 for (var i = 0; i < els.length; i++) { 221 /** @override */
215 if (els[i] == printHeader.cancelButton) 222 enterDocument: function() {
216 continue; 223 // Native layer events.
217 els[i].disabled = true; 224 this.tracker.add(
218 } 225 this.nativeLayer_,
219 } 226 print_preview.NativeLayer.EventType.INITIAL_SETTINGS_SET,
220 227 this.onInitialSettingsSet_.bind(this));
221 /** 228 this.tracker.add(
222 * Enables the input elements in the sidebar. 229 this.nativeLayer_,
223 */ 230 print_preview.NativeLayer.EventType.CLOUD_PRINT_ENABLE,
224 function enableInputElementsInSidebar() { 231 this.onCloudPrintEnable_.bind(this));
225 var els = $('navbar-container').querySelectorAll('input, button, select'); 232 this.tracker.add(
226 for (var i = 0; i < els.length; i++) 233 this.nativeLayer_,
227 els[i].disabled = false; 234 print_preview.NativeLayer.EventType.LOCAL_DESTINATIONS_SET,
228 } 235 this.onLocalDestinationsSet_.bind(this));
229 236 this.tracker.add(
230 /** 237 this.nativeLayer_,
231 * Keep track of the last element to receive a click. 238 print_preview.NativeLayer.EventType.CAPABILITIES_SET,
232 * @param {Event} e The click event. 239 this.onLocalDestinationCapabilitiesSet_.bind(this));
233 */ 240 this.tracker.add(
234 function setLastClickedElement(e) { 241 this.nativeLayer_,
235 lastClickedElement = e.target; 242 print_preview.NativeLayer.EventType.DESTINATIONS_RELOAD,
236 } 243 this.onDestinationsReload_.bind(this));
237 244 this.tracker.add(
238 /** 245 this.nativeLayer_,
239 * Disables the controls in the sidebar, shows the throbber and instructs the 246 print_preview.NativeLayer.EventType.PRINT_TO_CLOUD,
240 * backend to open the native print dialog. 247 this.onPrintToCloud_.bind(this));
241 */ 248 this.tracker.add(
242 function onSystemDialogLinkClicked() { 249 this.nativeLayer_,
243 if (showingSystemDialog) 250 print_preview.NativeLayer.EventType.FILE_SELECTION_CANCEL,
244 return; 251 this.onFileSelectionCancel_.bind(this));
245 showingSystemDialog = true; 252 this.tracker.add(
246 disableInputElementsInSidebar(); 253 this.nativeLayer_,
247 printHeader.disableCancelButton(); 254 print_preview.NativeLayer.EventType.FILE_SELECTION_COMPLETE,
248 $('system-dialog-throbber').hidden = false; 255 this.onFileSelectionComplete_.bind(this));
249 chrome.send('showSystemDialog'); 256 this.tracker.add(
250 } 257 this.nativeLayer_,
251 258 print_preview.NativeLayer.EventType.SETTINGS_INVALID,
252 /** 259 this.onSettingsInvalid_.bind(this));
253 * Disables the controls in the sidebar, shows the throbber and instructs the 260
254 * backend to open the pdf in native preview app. This is only for Mac. 261 this.tracker.add(
255 */ 262 $('system-dialog-link'),
256 function onOpenPdfInPreviewLinkClicked() { 263 'click',
257 if (previewAppRequested) 264 this.onSystemDialogLinkClicked_.bind(this));
258 return; 265 this.tracker.add(
259 previewAppRequested = true; 266 $('cloud-print-dialog-link'),
260 disableInputElementsInSidebar(); 267 'click',
261 $('open-preview-app-throbber').hidden = false; 268 this.onSystemDialogLinkClicked_.bind(this));
262 printHeader.disableCancelButton(); 269 this.tracker.add(
263 requestToPrintDocument(); 270 $('open-pdf-in-preview-link'),
264 } 271 'click',
265 272 this.onOpenPdfInPreviewLinkClick_.bind(this));
266 /** 273
267 * Similar to onSystemDialogLinkClicked(), but specific to the 274 this.tracker.add(
268 * 'Launch native print dialog' UI. 275 this.previewArea_,
269 */ 276 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS,
270 function launchNativePrintDialog() { 277 this.onPreviewGenerationInProgress_.bind(this));
271 if (showingSystemDialog) 278 this.tracker.add(
272 return; 279 this.previewArea_,
273 showingSystemDialog = true; 280 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE,
274 previewArea.errorButton.disabled = true; 281 this.onPreviewGenerationDone_.bind(this));
275 printHeader.disableCancelButton(); 282 this.tracker.add(
276 $('native-print-dialog-throbber').hidden = false; 283 this.previewArea_,
277 chrome.send('showSystemDialog'); 284 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_FAIL,
278 } 285 this.onPreviewGenerationFail_.bind(this));
279 286 this.tracker.add(
280 /** 287 this.previewArea_,
281 * Gets the selected printer capabilities and updates the controls accordingly. 288 print_preview.PreviewArea.EventType.OPEN_SYSTEM_DIALOG_CLICK,
282 */ 289 this.openSystemPrintDialog_.bind(this));
283 function updateControlsWithSelectedPrinterCapabilities() { 290
284 var printerList = $('printer-list'); 291 this.tracker.add(
285 var selectedIndex = printerList.selectedIndex; 292 this.destinationStore_,
286 if (selectedIndex < 0) 293 print_preview.DestinationStore.EventType.DESTINATION_SELECT,
287 return; 294 this.onDestinationSelect_.bind(this));
288 if (cr.isMac) 295
289 $('open-pdf-in-preview-link').disabled = false; 296 this.tracker.add(
290 297 this.printHeader_,
291 var skip_refresh = false; 298 print_preview.PrintHeader.EventType.PRINT_BUTTON_CLICK,
292 var selectedValue = printerList.options[selectedIndex].value; 299 this.onPrintButtonClick_.bind(this));
293 if (cloudprint.isCloudPrint(printerList.options[selectedIndex])) { 300 this.tracker.add(
294 cloudprint.updatePrinterCaps(printerList.options[selectedIndex], 301 this.printHeader_,
295 doUpdateCloudPrinterCapabilities); 302 print_preview.PrintHeader.EventType.CANCEL_BUTTON_CLICK,
296 skip_refresh = true; 303 this.onCancelButtonClick_.bind(this));
297 } else if (selectedValue == SIGN_IN || 304
298 selectedValue == MANAGE_CLOUD_PRINTERS || 305 this.tracker.add(window, 'keydown', this.onKeyDown_.bind(this));
299 selectedValue == MANAGE_LOCAL_PRINTERS) { 306 },
300 printerList.selectedIndex = lastSelectedPrinterIndex; 307
301 chrome.send(selectedValue); 308 /**
302 skip_refresh = true; 309 * Disables all of the controls within the print preview.
303 } else if (selectedValue == PRINT_TO_PDF || 310 * @private
304 selectedValue == PRINT_WITH_CLOUD_PRINT) { 311 */
305 updateWithPrinterCapabilities({ 312 disable_: function() {
306 'disableColorOption': true, 313 $('system-dialog-link').disabled = true;
307 'setColorAsDefault': true, 314 $('cloud-print-dialog-link').disabled = true;
308 'setDuplexAsDefault': false, 315 $('open-pdf-in-preview-link').disabled = true;
309 'printerColorModelForColor': print_preview.ColorSettings.COLOR, 316 this.printHeader_.isEnabled = false;
310 'printerDefaultDuplexValue': copiesSettings.UNKNOWN_DUPLEX_MODE, 317 this.destinationSettings_.isEnabled = false;
311 'disableCopiesOption': true}); 318 this.pageSettings_.isEnabled = false;
312 if (cr.isChromeOS && selectedValue == PRINT_WITH_CLOUD_PRINT) 319 this.copiesSettings_.isEnabled = false;
313 requestToPrintDocument(); 320 this.layoutSettings_.isEnabled = false;
314 } else { 321 this.colorSettings_.isEnabled = false;
315 // This message will call back to 'updateWithPrinterCapabilities' 322 this.marginSettings_.isEnabled = false;
316 // function. 323 this.headerFooterSettings_.isEnabled = false;
317 chrome.send('getPrinterCapabilities', [selectedValue]); 324 },
318 } 325
319 if (!skip_refresh) { 326 /**
320 lastSelectedPrinterIndex = selectedIndex; 327 * Creates a local PDF print destination.
321 328 * @return {!print_preview.Destination} Created print destination.
322 // Regenerate the preview data based on selected printer settings. 329 * @private
323 // Do not reset the margins if no preview request has been made. 330 */
324 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; 331 createLocalPdfPrintDestination_: function() {
325 setDefaultValuesAndRegeneratePreview(resetMargins); 332 var dest = new print_preview.Destination(
326 } 333 print_preview.Destination.GooglePromotedId.LOCAL_PDF,
327 } 334 localStrings.getString('printToPDF'),
328 335 false /*isRecent*/,
329 /** 336 true /*isLocal*/);
330 * Helper function to do the actual work of updating cloud printer 337 dest.capabilities = new print_preview.ChromiumCapabilities(
331 * capabilities. 338 false /*hasCopiesCapability*/,
332 * @param {Object} printer The printer object to set capabilities for. 339 '1' /*defaultCopiesStr*/,
333 */ 340 false /*hasCollateCapability*/,
334 function doUpdateCloudPrinterCapabilities(printer) { 341 false /*defaultIsCollateEnabled*/,
335 var settings = {'disableColorOption': !cloudprint.supportsColor(printer), 342 false /*hasDuplexCapability*/,
336 'setColorAsDefault': cloudprint.colorIsDefault(printer), 343 false /*defaultIsDuplexEnabled*/,
337 'disableCopiesOption': true, 344 true /*hasOrientationCapability*/,
338 'disableLandscapeOption': true}; 345 false /*defaultIsLandscapeEnabled*/,
339 updateWithPrinterCapabilities(settings); 346 true /*hasColorCapability*/,
340 var printerList = $('printer-list'); 347 true /*defaultIsColorEnabled*/);
341 var selectedIndex = printerList.selectedIndex; 348 return dest;
342 lastSelectedPrinterIndex = selectedIndex; 349 },
343 350
344 // Regenerate the preview data based on selected printer settings. 351 /**
345 // Do not reset the margins if no preview request has been made. 352 * Creates a new "Print with Cloud Print" print destination. NOTE: this
346 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; 353 * destination will appear as "Search for additional printers..." on
347 setDefaultValuesAndRegeneratePreview(resetMargins); 354 * Chrome OS.
348 } 355 * @return {!print_preview.Destination} Created print destination.
349 356 * @private
350 /** 357 */
351 * Notifies listeners of |customEvents.PRINTER_CAPABILITIES_UPDATED| about the 358 createPrintWithCloudPrintDestination_: function() {
352 * capabilities of the currently selected printer. It is called from C++ too. 359 var dest = new print_preview.Destination(
353 * @param {Object} settingInfo printer setting information. 360 print_preview.Destination.GooglePromotedId.PRINT_WITH_CLOUD_PRINT,
354 */ 361 localStrings.getString('printWithCloudPrint'),
355 function updateWithPrinterCapabilities(settingInfo) { 362 false /*isRecent*/,
356 var customEvent = new cr.Event(customEvents.PRINTER_CAPABILITIES_UPDATED); 363 false /*isLocal*/);
357 customEvent.printerCapabilities = settingInfo; 364 dest.capabilities = new print_preview.ChromiumCapabilities(
358 document.dispatchEvent(customEvent); 365 false /*hasCopiesCapability*/,
359 } 366 '1' /*defaultCopiesStr*/,
360 367 false /*hasCollateCapability*/,
361 /** 368 false /*defaultIsCollateEnabled*/,
362 * Reloads the printer list. 369 false /*hasDuplexCapability*/,
363 */ 370 false /*defaultIsDuplexEnabled*/,
364 function reloadPrintersList() { 371 true /*hasOrientationCapability*/,
365 $('printer-list').length = 0; 372 false /*defaultIsLandscapeEnabled*/,
366 firstCloudPrintOptionPos = 0; 373 true /*hasColorCapability*/,
367 lastCloudPrintOptionPos = 0; 374 true /*defaultIsColorEnabled*/);
368 chrome.send('getPrinters'); 375 return dest;
369 } 376 },
370 377
371 /** 378 /**
372 * Turn on the integration of Cloud Print. 379 * Prints the document or launches a pdf preview on the local system.
373 * @param {string} cloudPrintURL The URL to use for cloud print servers. 380 * @param {boolean} isPdfPreview Whether to launch the pdf preview.
374 */ 381 * @private
375 function setUseCloudPrint(cloudPrintURL) { 382 */
376 useCloudPrint = true; 383 printDocumentOrOpenPdfPreview_: function(isPdfPreview) {
377 cloudprint.setBaseURL(cloudPrintURL); 384 if (this.uiState_ != PrintPreview.UiState_.READY) {
378 } 385 throw Error(
379 386 'Print document request received when not in ready state: ' +
380 /** 387 this.uiState_);
381 * Take the PDF data handed to us and submit it to the cloud, closing the print 388 }
382 * preview tab once the upload is successful. 389 if (isPdfPreview) {
383 * @param {string} data Data to send as the print job. 390 this.uiState_ = PrintPreview.UiState_.OPENING_PDF_PREVIEW;
384 */ 391 } else if (this.destinationStore_.selectedDestination.isPrintToPdf) {
385 function printToCloud(data) { 392 this.uiState_ = PrintPreview.UiState_.FILE_SELECTION;
386 cloudprint.printToCloud(data, finishedCloudPrinting); 393 } else {
387 } 394 this.uiState_ = PrintPreview.UiState_.PRINTING;
388 395 }
389 /** 396 if (this.printIfReady_() &&
390 * Cloud print upload of the PDF file is finished, time to close the dialog. 397 this.destinationStore_.selectedDestination.isLocal &&
391 */ 398 !this.destinationStore_.selectedDestination.isPrintToPdf) {
392 function finishedCloudPrinting() { 399 // Hide the dialog for now. The actual print command will be issued when
393 closePrintPreviewTab(); 400 // the preview generation is done.
394 } 401 this.nativeLayer_.startHideDialog();
395 402 }
396 /** 403 },
397 * Checks whether the specified settings are valid. 404
398 * 405 /**
399 * @return {boolean} true if settings are valid, false if not. 406 * Attempts to print if needed and if ready.
400 */ 407 * @return {boolean} Whether a print request was issued.
401 function areSettingsValid() { 408 * @private
402 var selectedPrinter = getSelectedPrinterName(); 409 */
403 return pageSettings.isPageSelectionValid() && 410 printIfReady_: function() {
404 marginSettings.areMarginSettingsValid() && 411 if ((this.uiState_ == PrintPreview.UiState_.PRINTING ||
405 (copiesSettings.isValid() || selectedPrinter == PRINT_TO_PDF || 412 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW ||
406 selectedPrinter == PRINT_WITH_CLOUD_PRINT); 413 this.uiState_ == PrintPreview.UiState_.FILE_SELECTION ||
407 } 414 this.isInKioskAutoPrintMode_) &&
408 415 !this.isPreviewGenerationInProgress_ &&
409 /** 416 this.destinationStore_.selectedDestination &&
410 * Creates an object based on the values in the printer settings. 417 this.destinationStore_.selectedDestination.capabilities) {
411 * 418 if (!this.printTicketStore_.isTicketValid()) {
412 * @return {Object} Object containing print job settings. 419 throw Error('Trying to print with invalid ticket');
413 */ 420 }
414 function getSettings() { 421 this.nativeLayer_.startSaveDestinationAndTicket(
415 var deviceName = getSelectedPrinterName(); 422 this.destinationStore_.selectedDestination,
416 var printToPDF = deviceName == PRINT_TO_PDF; 423 this.printTicketStore_);
417 var printWithCloudPrint = deviceName == PRINT_WITH_CLOUD_PRINT; 424 this.nativeLayer_.startPrint(
418 425 this.destinationStore_.selectedDestination,
419 var settings = 426 this.printTicketStore_,
420 {'deviceName': deviceName, 427 this.cloudPrintInterface_);
421 'pageRange': pageSettings.selectedPageRanges, 428 return true;
422 'duplex': copiesSettings.duplexMode, 429 } else {
423 'copies': copiesSettings.numberOfCopies, 430 return false;
424 'collate': copiesSettings.isCollated(), 431 }
425 'landscape': layoutSettings.isLandscape(), 432 },
426 'color': colorSettings.colorMode, 433
427 'printToPDF': printToPDF, 434 /**
428 'printWithCloudPrint': printWithCloudPrint, 435 * Closes the print preview.
429 'isFirstRequest' : false, 436 * @private
430 'headerFooterEnabled': headerFooterSettings.hasHeaderFooter(), 437 */
431 'marginsType': marginSettings.selectedMarginsValue, 438 close_: function() {
432 'requestID': -1, 439 this.exitDocument();
433 'generateDraftData': generateDraftData, 440 this.uiState_ = PrintPreview.UiState_.CLOSING;
434 'previewModifiable': previewModifiable}; 441 this.nativeLayer_.startCloseDialog();
435 442 },
436 if (marginSettings.isCustomMarginsSelected()) 443
437 settings['marginsCustom'] = marginSettings.customMargins; 444 /**
438 445 * Opens the native system print dialog after disabling all controls.
439 var printerList = $('printer-list'); 446 * @private
440 var selectedPrinter = printerList.selectedIndex; 447 */
441 if (cloudprint.isCloudPrint(printerList.options[selectedPrinter])) { 448 openSystemPrintDialog_: function() {
442 settings['cloudPrintID'] = 449 if (this.uiState_ != PrintPreview.UiState_.READY) {
443 printerList.options[selectedPrinter].value; 450 throw Error(
444 } 451 'Request to open system dialog received when not in ready state: ' +
445 return settings; 452 this.uiState_);
446 } 453 }
447 454 this.disable_();
448 /** 455 this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
449 * Creates an object based on the values in the printer settings. 456 this.nativeLayer_.startShowSystemDialog();
450 * Note: |lastPreviewRequestID| is being modified every time this function is 457 },
451 * called. Only call this function when a preview request is actually sent, 458
452 * otherwise (for example when debugging) call getSettings(). 459 /**
453 * 460 * Window onload handler, sets up the page and starts print preview by
454 * @return {Object} Object containing print job settings. 461 * getting the printer list.
455 */ 462 * @private
456 function getSettingsWithRequestID() { 463 */
457 var settings = getSettings(); 464 onWindowLoad_: function() {
458 settings.requestID = generatePreviewRequestID(); 465 this.decorate($('print-preview'));
459 settings.isFirstRequest = isFirstPreviewRequest(); 466 i18nTemplate.process(document, templateData);
460 return settings; 467 if (!this.previewArea_.hasCompatiblePlugin) {
461 } 468 this.disable_();
462 469 }
463 /** 470 this.nativeLayer_.startGetInitialSettings();
464 * @return {number} The next unused preview request id. 471 },
465 */ 472
466 function generatePreviewRequestID() { 473 /**
467 return ++lastPreviewRequestID; 474 * Called when the native layer has initial settings to set. Sets the
468 } 475 * initial settings of the print preview and begins fetching print
469 476 * destinations.
470 /** 477 * @param {cr.Event} event Contains the initial print preview settings
471 * @return {boolean} True iff a preview has been requested. 478 * persisted through the session.
472 */ 479 * @private
473 function hasRequestedPreview() { 480 */
474 return lastPreviewRequestID != initialPreviewRequestID; 481 onInitialSettingsSet_: function(event) {
475 } 482 if (this.uiState_ != PrintPreview.UiState_.INITIALIZING) {
476 483 throw Error(
477 /** 484 'Updating initial settings when not in initializing state: ' +
478 * @return {boolean} True if |lastPreviewRequestID| corresponds to the initial 485 this.uiState_);
479 * preview request. 486 }
480 */ 487 this.uiState_ = PrintPreview.UiState_.READY;
481 function isFirstPreviewRequest() { 488
482 return lastPreviewRequestID == initialPreviewRequestID + 1; 489 this.isInKioskAutoPrintMode_ =
483 } 490 event.initialSettings.isInKioskAutoPrintMode;
484 491 this.destinationStore_.initialDestinationId =
485 /** 492 event.initialSettings.initialDestinationId;
486 * Checks if |previewResponseId| matches |lastPreviewRequestId|. Used to ignore 493 this.printTicketStore_.initialize(
487 * obsolete preview data responses. 494 event.initialSettings.isDocumentModifiable,
488 * @param {number} previewResponseId The id to check. 495 event.initialSettings.isDuplexEnabled,
489 * @return {boolean} True if previewResponseId reffers to the expected response. 496 event.initialSettings.isHeaderFooterEnabled,
490 */ 497 event.initialSettings.marginsType,
491 function isExpectedPreviewResponse(previewResponseId) { 498 event.initialSettings.customMargins,
492 return lastPreviewRequestID == previewResponseId; 499 event.initialSettings.thousandsDelimeter,
493 } 500 event.initialSettings.decimalDelimeter,
494 501 event.initialSettings.unitType);
495 /** 502
496 * Returns the name of the selected printer or the empty string if no 503 this.nativeLayer_.startGetLocalDestinations();
497 * printer is selected. 504 },
498 * @return {string} The name of the currently selected printer. 505
499 */ 506 /**
500 function getSelectedPrinterName() { 507 * Calls when the native layer enables Google Cloud Print integration.
501 var printerList = $('printer-list'); 508 * Fetches the user's cloud printers.
502 var selectedPrinter = printerList.selectedIndex; 509 * @param {cr.Event} event Contains the base URL of the Google Cloud Print
503 if (selectedPrinter < 0) 510 * service.
504 return ''; 511 * @private
505 return printerList.options[selectedPrinter].value; 512 */
506 } 513 onCloudPrintEnable_: function(event) {
507 514 this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface(
508 /** 515 event.baseCloudPrintUrl);
509 * Asks the browser to print the preview PDF based on current print 516 this.tracker.add(
510 * settings. If the preview is still loading, printPendingFile() will get 517 this.cloudPrintInterface_,
511 * called once the preview loads. 518 cloudprint.CloudPrintInterface.EventType.SEARCH_DONE,
512 */ 519 this.onCloudPrintSearchDone_.bind(this));
513 function requestToPrintDocument() { 520 this.tracker.add(
514 hasPendingPrintDocumentRequest = !isPrintReadyMetafileReady; 521 this.cloudPrintInterface_,
515 var selectedPrinterName = getSelectedPrinterName(); 522 cloudprint.CloudPrintInterface.EventType.PRINTER_DONE,
516 var printToPDF = selectedPrinterName == PRINT_TO_PDF; 523 this.onCloudPrintPrinterDone_.bind(this));
517 var printWithCloudPrint = selectedPrinterName == PRINT_WITH_CLOUD_PRINT; 524 this.tracker.add(
518 if (hasPendingPrintDocumentRequest) { 525 this.cloudPrintInterface_,
519 if (previewAppRequested) { 526 cloudprint.CloudPrintInterface.EventType.SUBMIT_DONE,
520 previewArea.showCustomMessage( 527 this.onCloudPrintSubmitDone_.bind(this));
528 this.tracker.add(
529 this.cloudPrintInterface_,
530 cloudprint.CloudPrintInterface.EventType.ERROR,
531 this.onCloudPrintError_.bind(this));
532
533 var printWithCloudPrintDest =
534 this.createPrintWithCloudPrintDestination_();
535 this.destinationStore_.insertDestination(printWithCloudPrintDest);
536
537 if (cr.isChromeOS) {
538 this.cloudPrintInterface_.search(true /*isRecent*/);
539 this.fetchState_ |= PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS;
540 }
541 },
542
543 /**
544 * Called when the native layer gets local destinations. Adds local
545 * destination objects received from the operating system to the destination
546 * store. Also adds a print-to-pdf printer.
547 * @param {cr.Event} Contains the local destinations to set.
548 * @private
549 */
550 onLocalDestinationsSet_: function(event) {
551 var localDestinations = [];
552 for (var destInfo, i = 0; destInfo = event.destinationInfos[i]; i++) {
553 localDestinations.push(
554 print_preview.LocalDestinationParser.parse(destInfo));
555 }
556 localDestinations.push(this.createLocalPdfPrintDestination_());
557 this.destinationStore_.insertDestinations(localDestinations);
558 this.fetchState_ &= ~PrintPreview.FetchState_.LOCAL_DESTINATIONS;
559 },
560
561 /**
562 * Called when the native layer retrieves the capabilities for the selected
563 * local destination.
564 * @param {cr.Event} event Contains the capabilities of the local print
565 * destination.
566 * @private
567 */
568 onLocalDestinationCapabilitiesSet_: function(event) {
569 // TODO There may be a race condition here. This method is assumed to
570 // return capabilities for the currently selected printer. But between the
571 // time the local printer was selected and the capabilities were
572 // retrieved, the selected printer can change. One way to address this is
573 // to include the destination ID in the settingsInfo parameter.
574 var selectedDestination = this.destinationStore_.selectedDestination;
575 if (selectedDestination.isLocal) {
576 var capabilities = print_preview.LocalCapabilitiesParser.parse(
577 event.settingsInfo);
578 selectedDestination.capabilities = capabilities;
579 this.printTicketStore_.updateDestinationCapabilities(capabilities);
580 this.printIfReady_();
581 }
582 },
583
584 /**
585 * Called from native layer after the user was requested to sign in, and did
586 * so successfully.
587 * @private
588 */
589 onDestinationsReload_: function() {
590 this.destinationStore_.clear();
591 this.nativeLayer_.startGetLocalDestinations();
592 if (this.cloudPrintInterface_) {
593 // Fetch recent printers.
594 this.cloudPrintInterface_.search(true /*isRecent*/);
595 // Fetch the full printer list.
596 this.cloudPrintInterface_.search(false /*isRecent*/);
597 }
598 this.fetchState_ =
599 PrintPreview.FetchState_.LOCAL_DESTINATIONS |
600 PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS |
601 PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS;
602 },
603
604 /**
605 * Called from the native layer when ready to print to Google Cloud Print.
606 * @param {cr.Event} event Contains the body to send in the HTTP request.
607 * @private
608 */
609 onPrintToCloud_: function(event) {
610 if (this.uiState_ != PrintPreview.UiState_.PRINTING) {
611 throw Error(
612 'Document ready to be sent to the cloud when not in printing ' +
613 'state: ' + this.uiState_);
614 }
615 if (this.cloudPrintInterface_) {
616 this.cloudPrintInterface_.submit(event.data);
617 } else {
618 throw Error('Google Cloud Print is not enabled');
619 }
620 },
621
622 /**
623 * Called from the native layer when the user cancels the save-to-pdf file
624 * selection dialog.
625 * @private
626 */
627 onFileSelectionCancel_: function() {
628 if (this.uiState_ != PrintPreview.UiState_.FILE_SELECTION) {
629 throw Error(
630 'File selection cancelled when not in file-selection state: ' +
631 this.uiState_);
632 }
633 // TODO Reenable controls.
634 this.uiState_ = PrintPreview.UiState_.READY;
635 },
636
637 /**
638 * Called from the native layer when save-to-pdf file selection is complete.
639 * @private
640 */
641 onFileSelectionComplete_: function() {
642 if (this.uiState_ != PrintPreview.UiState_.FILE_SELECTION) {
643 throw Error(
644 'File selection completed when not in file-selection state: ' +
645 this.uiState_);
646 }
647 this.disable_();
648 this.previewArea_.showCustomMessage(
649 localStrings.getString('printingToPDFInProgress'));
650 // TODO
651 },
652
653 /**
654 * Called when the Google Cloud Print search API call completes. Adds
655 * destinations to the printer store and selects one if it matches the
656 * initial destination.
657 * @param {cr.Event} event Contains the new cloud destinations.
658 * @private
659 */
660 onCloudPrintSearchDone_: function(event) {
661 this.destinationStore_.insertDestinations(event.printers);
662 if (event.isRecent) {
663 this.fetchState_ &= ~PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS;
664 } else {
665 this.fetchState_ &= ~PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS;
666 }
667 },
668
669 /**
670 * Called when the Google Cloud Print printer API call completes. Updates
671 * the UI with the newly received capabilities.
672 * @param {cr.Event} event Contains the destination returned in the printer
673 * API call.
674 */
675 onCloudPrintPrinterDone_: function(event) {
676 var dest = this.destinationStore_.updateDestination(event.printer);
677 if (this.destinationStore_.selectedDestination == dest) {
678 this.printTicketStore_.updateDestinationCapabilities(dest.capabilities);
679 this.printIfReady_();
680 }
681 },
682
683 onCloudPrintSubmitDone_: function(event) {
684 if (this.uiState_ != PrintPreview.UiState_.PRINTING) {
685 throw Error(
686 'Submited job to Google Cloud Print but not in printing state ' +
687 this.uiState_);
688 }
689 this.close_();
690 },
691
692 /**
693 * Called when there was an error communicating with Google Cloud print.
694 * Displays an error message in the print header.
695 * @param {cr.Event} event Contains the error message.
696 * @private
697 */
698 onCloudPrintError_: function(event) {
699 if (cr.isChromeOS && event.message == '403') {
700 this.nativeLayer_.startCloudPrintSignIn();
701 } else {
702 this.printHeader_.setErrorMessage(event.message);
703 }
704 this.fetchState_ &=
705 ~PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS &
706 ~PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS;
707 },
708
709 /**
710 * Called when a new destination has been selected. Fetches the
711 * destination's capability list.
712 * @private
713 */
714 onDestinationSelect_: function() {
715 var destination = this.destinationStore_.selectedDestination;
716
717 if (cr.isChromeOS && destination.isPrintWithCloudPrint) {
718 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
719 return;
720 }
721
722 // Fetch destination capabilities if necessary.
723 if (!destination.capabilities) {
724 if (destination.isLocal) {
725 this.nativeLayer_.startGetLocalDestinationCapabilities(
726 destination.id);
727 } else if (this.cloudPrintInterface_) {
728 this.cloudPrintInterface_.printer(destination.id);
729 } else {
730 // TODO Probably a cloud printer was initially selected, but cloud
731 // print is no longer available. Maybe default to the system's local
732 // default? What about Chrome OS?
733 throw Error(
734 'Selected destination is a cloud destination, but Google Cloud ' +
735 'Print is not enabled');
736 }
737 } else {
738 this.printTicketStore_.updateDestinationCapabilities(
739 destination.capabilities);
740 }
741
742 this.printIfReady_();
743 },
744
745 /**
746 * Called when the preview area's preview generation is in progress.
747 * @private
748 */
749 onPreviewGenerationInProgress_: function() {
750 this.isPreviewGenerationInProgress_ = true;
751 },
752
753 /**
754 * Called when the preview area's preview generation is complete.
755 * @private
756 */
757 onPreviewGenerationDone_: function() {
758 this.isPreviewGenerationInProgress_ = false;
759 this.printIfReady_();
760 },
761
762 /**
763 * Called when the preview area's preview failed to load.
764 * @private
765 */
766 onPreviewGenerationFail_: function() {
767 this.isPreviewGenerationInProgress_ = false;
768 if (this.uiState_ == PrintPreview.UiState_.PRINTING) {
769 this.nativeLayer_.startCancelPendingPrint();
770 }
771 },
772
773 onSystemDialogLinkClicked_: function() {
774 setIsVisible($('dialog-throbber'), true);
775 this.openSystemPrintDialog_();
776 },
777
778 /**
779 * Called when the 'Open pdf in preview' link is clicked. Launches the pdf
780 * preview app.
781 * @private
782 */
783 onOpenPdfInPreviewLinkClick_: function() {
784 if (this.uiState_ != PrintPreview.UiState_.READY) {
785 throw Error(
786 'Trying to open pdf in preview when not in ready state: ' +
787 this.uiState_);
788 }
789 setIsVisible($('open-preview-app-throbber'), true);
790 this.disable_();
791 this.previewArea_.showCustomMessage(
521 localStrings.getString('openingPDFInPreview')); 792 localStrings.getString('openingPDFInPreview'));
522 } else if (printToPDF) { 793 this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
523 sendPrintDocumentRequest(); 794 },
524 } else if (printWithCloudPrint) { 795
525 previewArea.showCustomMessage( 796 /**
526 localStrings.getString('printWithCloudPrintWait')); 797 * Called when the print header's print button is clicked. Prints the
527 disableInputElementsInSidebar(); 798 * document.
528 } else { 799 * @private
529 isTabHidden = true; 800 */
530 chrome.send('hidePreview'); 801 onPrintButtonClick_: function() {
802 if (this.uiState_ != PrintPreview.UiState_.READY) {
803 throw Error(
804 'Trying to print when not in ready state: ' + this.uiState_);
805 }
806 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
807 },
808
809 /**
810 * Called when the print header's cancel button is clicked. Closes the
811 * print dialog.
812 * @private
813 */
814 onCancelButtonClick_: function() {
815 this.close_();
816 },
817
818 /**
819 * Consume escape key presses and ctrl + shift + p. Delegate everything else
820 * to the preview area.
821 * @param {KeyboardEvent} e The keyboard event.
822 * @private
823 */
824 onKeyDown_: function(e) {
825 // Escape key closes the dialog.
826 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&
827 !e.metaKey) {
828 this.close_();
829 e.preventDefault();
830 return;
831 }
832
833 // Ctrl + Shift + p / Mac equivalent.
834 if (e.keyCode == 80) {
835 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
836 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
837 this.openSystemPrintDialog_();
838 e.preventDefault();
839 return;
840 }
841 }
842
843 // Pass certain directional keyboard events to the PDF viewer.
844 this.previewArea_.handleDirectionalKeyEvent(e);
845 },
846
847 /**
848 * Called when native layer receives invalid settings for a print request.
849 * @private
850 */
851 onSettingsInvalid_: function() {
852 this.uiState_ = PrintPreview.UiState_.ERROR;
853 this.previewArea_.showCustomMessage(
854 localStrings.getString('invalidPrinterSettings'));
531 } 855 }
532 return; 856 };
533 } 857
534 858 // Export
535 if (printToPDF || previewAppRequested) { 859 return {
536 sendPrintDocumentRequest(); 860 PrintPreview: PrintPreview
537 } else { 861 };
538 window.setTimeout(function() { sendPrintDocumentRequest(); }, 1000); 862 });
539 } 863
540 } 864 // Pull in all other scripts in a single shot.
541 865 <include src="data/page_number_set.js"/>
542 /** 866 <include src="data/destination.js"/>
543 * Sends a message to cancel the pending print request. 867 <include src="data/local_parsers.js"/>
544 */ 868 <include src="data/cloud_parsers.js"/>
545 function cancelPendingPrintRequest() { 869 <include src="data/chromium_capabilities.js"/>
546 if (isTabHidden) 870 <include src="data/cloud_capabilities.js"/>
547 chrome.send('cancelPendingPrintRequest'); 871 <include src="data/destination_store.js"/>
548 } 872 <include src="data/margins.js"/>
549 873 <include src="data/document_info.js"/>
550 /** 874 <include src="data/printable_area.js"/>
551 * Sends a message to initiate print workflow. 875 <include src="data/measurement_system.js"/>
552 */ 876 <include src="data/print_ticket_store.js"/>
553 function sendPrintDocumentRequest() { 877 <include src="data/coordinate2d.js"/>
554 var printerList = $('printer-list'); 878 <include src="data/size.js"/>
555 var printer = printerList[printerList.selectedIndex]; 879 <include src="data/capabilities_holder.js"/>
556 chrome.send('saveLastPrinter', [printer.value, cloudprint.getData(printer)]); 880
557 881 <include src="data/ticket_items/ticket_item.js"/>
558 var settings = getSettings(); 882
559 if (cr.isMac && previewAppRequested) 883 <include src="data/ticket_items/custom_margins.js"/>
560 settings.OpenPDFInPreview = true; 884 <include src="data/ticket_items/collate.js"/>
561 885 <include src="data/ticket_items/color.js"/>
562 chrome.send('print', [JSON.stringify(settings), 886 <include src="data/ticket_items/copies.js"/>
563 cloudprint.getPrintTicketJSON(printer)]); 887 <include src="data/ticket_items/duplex.js"/>
564 } 888 <include src="data/ticket_items/header_footer.js"/>
565 889 <include src="data/ticket_items/landscape.js"/>
566 /** 890 <include src="data/ticket_items/margins_type.js"/>
567 * Loads the selected preview pages. 891 <include src="data/ticket_items/page_range.js"/>
568 */ 892
569 function loadSelectedPages() { 893 <include src="native_layer.js"/>
570 pageSettings.updatePageSelection();
571 var pageSet = pageSettings.previouslySelectedPages;
572 var pageCount = pageSet.length;
573 if (pageCount == 0 || currentPreviewUid == '')
574 return;
575
576 cr.dispatchSimpleEvent(document, customEvents.UPDATE_SUMMARY);
577 for (var i = 0; i < pageCount; i++)
578 onDidPreviewPage(pageSet[i] - 1, currentPreviewUid, lastPreviewRequestID);
579 }
580
581 /**
582 * Asks the browser to generate a preview PDF based on current print settings.
583 */
584 function requestPrintPreview() {
585 if (!isTabHidden)
586 previewArea.showLoadingAnimation();
587
588 if (!hasPendingPreviewRequest && previewModifiable &&
589 hasOnlyPageSettingsChanged()) {
590 loadSelectedPages();
591 generateDraftData = false;
592 } else {
593 hasPendingPreviewRequest = true;
594 generateDraftData = true;
595 pageSettings.updatePageSelection();
596 }
597
598 printSettings.save();
599 layoutSettings.updateState();
600 previewArea.resetState();
601 isPrintReadyMetafileReady = false;
602 isFirstPageLoaded = false;
603
604 var totalPageCount = pageSettings.totalPageCount;
605 if (!previewModifiable && totalPageCount > 0)
606 generateDraftData = false;
607
608 var pageCount = totalPageCount != undefined ? totalPageCount : -1;
609 chrome.send('getPreview', [JSON.stringify(getSettingsWithRequestID()),
610 pageCount,
611 previewModifiable]);
612 }
613
614 /**
615 * Called from PrintPreviewUI::OnFileSelectionCancelled to notify the print
616 * preview tab regarding the file selection cancel event.
617 */
618 function fileSelectionCancelled() {
619 printHeader.enableCancelButton();
620 }
621
622 /**
623 * Called from PrintPreviewUI::OnFileSelectionCompleted to notify the print
624 * preview tab regarding the file selection completed event.
625 */
626 function fileSelectionCompleted() {
627 // If the file selection is completed and the tab is not already closed it
628 // means that a pending print to pdf request exists.
629 disableInputElementsInSidebar();
630 previewArea.showCustomMessage(
631 localStrings.getString('printingToPDFInProgress'));
632 }
633
634 /**
635 * Set the default printer. If there is one, generate a print preview.
636 * @param {string} printerName Name of the default printer. Empty if none.
637 * @param {string} cloudPrintData Cloud print related data to restore if
638 * the default printer is a cloud printer.
639 */
640 function setDefaultPrinter(printerName, cloudPrintData) {
641 // Add a placeholder value so the printer list looks valid.
642 addDestinationListOption('', '', true, true, true);
643 if (printerName) {
644 defaultOrLastUsedPrinterName = printerName;
645 if (cloudPrintData) {
646 cloudprint.setDefaultPrinter(printerName,
647 cloudPrintData,
648 addDestinationListOptionAtPosition,
649 doUpdateCloudPrinterCapabilities);
650 } else {
651 $('printer-list')[0].value = defaultOrLastUsedPrinterName;
652 updateControlsWithSelectedPrinterCapabilities();
653 }
654 }
655 chrome.send('getPrinters');
656 }
657
658 /**
659 * Fill the printer list drop down.
660 * Called from PrintPreviewHandler::SetupPrinterList().
661 * @param {Array} printers Array of printer info objects.
662 */
663 function setPrinters(printers) {
664 var printerList = $('printer-list');
665 // Remove empty entry added by setDefaultPrinter.
666 if (printerList[0] && printerList[0].textContent == '')
667 printerList.remove(0);
668 for (var i = 0; i < printers.length; ++i) {
669 var isDefault = (printers[i].deviceName == defaultOrLastUsedPrinterName);
670 addDestinationListOption(printers[i].printerName, printers[i].deviceName,
671 isDefault, false, false);
672 }
673
674 if (printers.length != 0)
675 addDestinationListOption('', '', false, true, true);
676
677 // Adding option for saving PDF to disk.
678 addDestinationListOption(localStrings.getString('printToPDF'),
679 PRINT_TO_PDF,
680 defaultOrLastUsedPrinterName == PRINT_TO_PDF,
681 false,
682 false);
683 addDestinationListOption('', '', false, true, true);
684 if (useCloudPrint) {
685 addDestinationListOption(localStrings.getString('printWithCloudPrint'),
686 PRINT_WITH_CLOUD_PRINT,
687 false,
688 false,
689 false);
690 addDestinationListOption('', '', false, true, true);
691 }
692 // Add options to manage printers.
693 if (!cr.isChromeOS) {
694 addDestinationListOption(localStrings.getString('managePrinters'),
695 MANAGE_LOCAL_PRINTERS, false, false, false);
696 } else if (useCloudPrint) {
697 // Fetch recent printers.
698 cloudprint.fetchPrinters(addDestinationListOptionAtPosition, false);
699 // Fetch the full printer list.
700 cloudprint.fetchPrinters(addDestinationListOptionAtPosition, true);
701 addDestinationListOption(localStrings.getString('managePrinters'),
702 MANAGE_CLOUD_PRINTERS, false, false, false);
703 }
704
705 printerList.disabled = false;
706
707 if (!hasRequestedPreview())
708 updateControlsWithSelectedPrinterCapabilities();
709 }
710
711 /**
712 * Creates an option that can be added to the printer destination list.
713 * @param {string} optionText specifies the option text content.
714 * @param {string} optionValue specifies the option value.
715 * @param {boolean} isDefault is true if the option needs to be selected.
716 * @param {boolean} isDisabled is true if the option needs to be disabled.
717 * @param {boolean} isSeparator is true if the option is a visual separator and
718 * needs to be disabled.
719 * @return {Object} The created option.
720 */
721 function createDestinationListOption(optionText, optionValue, isDefault,
722 isDisabled, isSeparator) {
723 var option = document.createElement('option');
724 option.textContent = optionText;
725 option.value = optionValue;
726 option.selected = isDefault;
727 option.disabled = isSeparator || isDisabled;
728 // Adding attribute for improved accessibility.
729 if (isSeparator)
730 option.setAttribute('role', 'separator');
731 return option;
732 }
733
734 /**
735 * Adds an option to the printer destination list.
736 * @param {string} optionText specifies the option text content.
737 * @param {string} optionValue specifies the option value.
738 * @param {boolean} isDefault is true if the option needs to be selected.
739 * @param {boolean} isDisabled is true if the option needs to be disabled.
740 * @param {boolean} isSeparator is true if the option serves just as a
741 * separator.
742 * @return {Object} The created option.
743 */
744 function addDestinationListOption(optionText, optionValue, isDefault,
745 isDisabled, isSeparator) {
746 var option = createDestinationListOption(optionText,
747 optionValue,
748 isDefault,
749 isDisabled,
750 isSeparator);
751 $('printer-list').add(option);
752 return option;
753 }
754
755 /**
756 * Adds an option to the printer destination list at a specified position.
757 * @param {number} position The index in the printer-list wher the option
758 should be created.
759 * @param {string} optionText specifies the option text content.
760 * @param {string} optionValue specifies the option value.
761 * @param {boolean} isDefault is true if the option needs to be selected.
762 * @param {boolean} isDisabled is true if the option needs to be disabled.
763 * @param {boolean} isSeparator is true if the option is a visual separator and
764 * needs to be disabled.
765 * @return {Object} The created option.
766 */
767 function addDestinationListOptionAtPosition(position,
768 optionText,
769 optionValue,
770 isDefault,
771 isDisabled,
772 isSeparator) {
773 var option = createDestinationListOption(optionText,
774 optionValue,
775 isDefault,
776 isDisabled,
777 isSeparator);
778 var printerList = $('printer-list');
779 var before = printerList[position];
780 printerList.add(option, before);
781 return option;
782 }
783 /**
784 * Sets the color mode for the PDF plugin.
785 * Called from PrintPreviewHandler::ProcessColorSetting().
786 * @param {boolean} color is true if the PDF plugin should display in color.
787 */
788 function setColor(color) {
789 if (!previewArea.pdfPlugin)
790 return;
791
792 previewArea.pdfPlugin.grayscale(!color);
793 var printerList = $('printer-list');
794 cloudprint.setColor(printerList[printerList.selectedIndex], color);
795 }
796
797 /**
798 * Display an error message when print preview fails.
799 * Called from PrintPreviewMessageHandler::OnPrintPreviewFailed().
800 */
801 function printPreviewFailed() {
802 previewArea.displayErrorMessageAndNotify(
803 localStrings.getString('previewFailed'));
804 }
805
806 /**
807 * Display an error message when encountered invalid printer settings.
808 * Called from PrintPreviewMessageHandler::OnInvalidPrinterSettings().
809 */
810 function invalidPrinterSettings() {
811 if (cr.isMac) {
812 if (previewAppRequested) {
813 $('open-preview-app-throbber').hidden = true;
814 previewArea.clearCustomMessageWithDots();
815 previewAppRequested = false;
816 hasPendingPrintDocumentRequest = false;
817 enableInputElementsInSidebar();
818 }
819 $('open-pdf-in-preview-link').disabled = true;
820 }
821 previewArea.displayErrorMessageAndNotify(
822 localStrings.getString('invalidPrinterSettings'));
823 }
824
825 /**
826 * Called when the PDF plugin loads its document.
827 */
828 function onPDFLoad() {
829 if (previewModifiable) {
830 setPluginPreviewPageCount();
831 }
832 // Instruct the plugin which page numbers to display in the page number
833 // indicator.
834 previewArea.pdfPlugin.setPageNumbers(
835 JSON.stringify(pageSettings.selectedPagesSet));
836 cr.dispatchSimpleEvent(document, customEvents.PDF_LOADED);
837 isFirstPageLoaded = true;
838 checkAndHideOverlayLayerIfValid();
839 sendPrintDocumentRequestIfNeeded();
840 if (printAutomaticallyInKioskMode)
841 printHeader.printButton.click();
842 }
843
844 function setPluginPreviewPageCount() {
845 previewArea.pdfPlugin.printPreviewPageCount(
846 pageSettings.previouslySelectedPages.length);
847 }
848
849 /**
850 * Update the page count and check the page range.
851 * Called from PrintPreviewUI::OnDidGetPreviewPageCount().
852 * @param {number} pageCount The number of pages.
853 * @param {number} previewResponseId The preview request id that resulted in
854 * this response.
855 */
856 function onDidGetPreviewPageCount(pageCount, previewResponseId) {
857 if (!isExpectedPreviewResponse(previewResponseId))
858 return;
859 pageSettings.updateState(pageCount);
860 if (!previewModifiable && pageSettings.requestPrintPreviewIfNeeded())
861 return;
862
863 cr.dispatchSimpleEvent(document, customEvents.UPDATE_SUMMARY);
864 }
865
866 /**
867 * @param {{contentWidth: number, contentHeight: number, marginLeft: number,
868 * marginRight: number, marginTop: number, marginBottom: number,
869 * printableAreaX: number, printableAreaY: number,
870 * printableAreaWidth: number, printableAreaHeight: number}} pageLayout
871 * Specifies default page layout details in points.
872 * @param {boolean} hasCustomPageSizeStyle Indicates whether the previewed
873 * document has a custom page size style.
874 */
875 function onDidGetDefaultPageLayout(pageLayout, hasCustomPageSizeStyle) {
876 hasPageSizeStyle = hasCustomPageSizeStyle;
877 marginSettings.currentDefaultPageLayout = new print_preview.PageLayout(
878 pageLayout.contentWidth,
879 pageLayout.contentHeight,
880 pageLayout.marginLeft,
881 pageLayout.marginTop,
882 pageLayout.marginRight,
883 pageLayout.marginBottom);
884 headerFooterSettings.checkAndHideHeaderFooterOption(
885 pageLayout, marginSettings.selectedMarginsValue);
886 }
887
888 /**
889 * This function sends a request to hide the overlay layer only if there is no
890 * pending print document request and we are not waiting for the print ready
891 * metafile.
892 */
893 function checkAndHideOverlayLayerIfValid() {
894 var selectedPrinter = getSelectedPrinterName();
895 var printToDialog = selectedPrinter == PRINT_TO_PDF ||
896 selectedPrinter == PRINT_WITH_CLOUD_PRINT;
897 if ((printToDialog || !previewModifiable) &&
898 !isPrintReadyMetafileReady && hasPendingPrintDocumentRequest) {
899 return;
900 }
901 previewArea.hideOverlayLayer();
902 }
903
904 /**
905 * Called when no pipelining previewed pages.
906 * @param {string} previewUid Preview unique identifier.
907 * @param {number} previewResponseId The preview request id that resulted in
908 * this response.
909 */
910 function reloadPreviewPages(previewUid, previewResponseId) {
911 if (!isExpectedPreviewResponse(previewResponseId))
912 return;
913
914 cr.dispatchSimpleEvent(document, customEvents.UPDATE_PRINT_BUTTON);
915 checkAndHideOverlayLayerIfValid();
916 var pageSet = pageSettings.previouslySelectedPages;
917 for (var i = 0; i < pageSet.length; i++) {
918 previewArea.pdfPlugin.loadPreviewPage(
919 getPageSrcURL(previewUid, pageSet[i] - 1), i);
920 }
921
922 hasPendingPreviewRequest = false;
923 isPrintReadyMetafileReady = true;
924 previewArea.pdfLoaded = true;
925 sendPrintDocumentRequestIfNeeded();
926 }
927
928 /**
929 * Notification that a print preview page has been rendered.
930 * Check if the settings have changed and request a regeneration if needed.
931 * Called from PrintPreviewUI::OnDidPreviewPage().
932 * @param {number} pageNumber The page number, 0-based.
933 * @param {string} previewUid Preview unique identifier.
934 * @param {number} previewResponseId The preview request id that resulted in
935 * this response.
936 */
937 function onDidPreviewPage(pageNumber, previewUid, previewResponseId) {
938 if (!isExpectedPreviewResponse(previewResponseId))
939 return;
940
941 // Refactor
942 if (!previewModifiable)
943 return;
944
945 if (pageSettings.requestPrintPreviewIfNeeded())
946 return;
947
948 var pageIndex = pageSettings.previouslySelectedPages.indexOf(pageNumber + 1);
949 if (pageIndex == -1)
950 return;
951
952 currentPreviewUid = previewUid;
953 if (pageIndex == 0)
954 previewArea.createOrReloadPDFPlugin(pageNumber);
955
956 previewArea.pdfPlugin.loadPreviewPage(
957 getPageSrcURL(previewUid, pageNumber), pageIndex);
958
959 if (pageIndex + 1 == pageSettings.previouslySelectedPages.length) {
960 hasPendingPreviewRequest = false;
961 if (pageIndex != 0)
962 sendPrintDocumentRequestIfNeeded();
963 }
964 }
965
966 /**
967 * Update the print preview when new preview data is available.
968 * Create the PDF plugin as needed.
969 * Called from PrintPreviewUI::PreviewDataIsAvailable().
970 * @param {string} previewUid Preview unique identifier.
971 * @param {number} previewResponseId The preview request id that resulted in
972 * this response.
973 */
974 function updatePrintPreview(previewUid, previewResponseId) {
975 if (!isExpectedPreviewResponse(previewResponseId))
976 return;
977 isPrintReadyMetafileReady = true;
978
979 if (!previewModifiable) {
980 // If the preview is not modifiable the plugin has not been created yet.
981 currentPreviewUid = previewUid;
982 hasPendingPreviewRequest = false;
983 previewArea.createOrReloadPDFPlugin(PRINT_READY_DATA_INDEX);
984 }
985
986 cr.dispatchSimpleEvent(document, customEvents.UPDATE_PRINT_BUTTON);
987 if (previewModifiable)
988 sendPrintDocumentRequestIfNeeded();
989 }
990
991 /**
992 * Checks to see if the requested print data is available for printing and
993 * sends a print document request if needed.
994 */
995 function sendPrintDocumentRequestIfNeeded() {
996 if (!hasPendingPrintDocumentRequest || !isFirstPageLoaded)
997 return;
998
999 // If the selected printer is PRINT_TO_PDF or PRINT_WITH_CLOUD_PRINT or
1000 // the preview source is not modifiable, we need the print ready data for
1001 // printing. If the preview source is modifiable, we need to wait till all
1002 // the requested pages are loaded in the plugin for printing.
1003 var selectedPrinter = getSelectedPrinterName();
1004 var printToDialog = selectedPrinter == PRINT_TO_PDF ||
1005 selectedPrinter == PRINT_WITH_CLOUD_PRINT;
1006 if (((printToDialog || !previewModifiable) && !isPrintReadyMetafileReady) ||
1007 (previewModifiable && hasPendingPreviewRequest)) {
1008 return;
1009 }
1010
1011 hasPendingPrintDocumentRequest = false;
1012
1013 if (!areSettingsValid()) {
1014 cancelPendingPrintRequest();
1015 return;
1016 }
1017 sendPrintDocumentRequest();
1018 }
1019
1020 /**
1021 * Check if only page selection has been changed since the last preview request
1022 * and is valid.
1023 * @return {boolean} true if the new page selection is valid.
1024 */
1025 function hasOnlyPageSettingsChanged() {
1026 var tempPrintSettings = new PrintSettings();
1027 tempPrintSettings.save();
1028
1029 return !!(printSettings.deviceName == tempPrintSettings.deviceName &&
1030 printSettings.isLandscape == tempPrintSettings.isLandscape &&
1031 printSettings.hasHeaderFooter ==
1032 tempPrintSettings.hasHeaderFooter &&
1033 pageSettings.hasPageSelectionChangedAndIsValid());
1034 }
1035
1036 /**
1037 * Called either when there is a scroll event or when the plugin size changes.
1038 */
1039 function onPreviewPositionChanged() {
1040 marginSettings.onPreviewPositionChanged();
1041 }
1042
1043 /**
1044 * @return {boolean} true if a compatible pdf plugin exists.
1045 */
1046 function checkCompatiblePluginExists() {
1047 var dummyPlugin = $('dummy-viewer');
1048 var pluginInterface = [dummyPlugin.onload,
1049 dummyPlugin.goToPage,
1050 dummyPlugin.removePrintButton,
1051 dummyPlugin.loadPreviewPage,
1052 dummyPlugin.printPreviewPageCount,
1053 dummyPlugin.resetPrintPreviewUrl,
1054 dummyPlugin.onPluginSizeChanged,
1055 dummyPlugin.onScroll,
1056 dummyPlugin.pageXOffset,
1057 dummyPlugin.pageYOffset,
1058 dummyPlugin.setZoomLevel,
1059 dummyPlugin.setPageNumbers,
1060 dummyPlugin.setPageXOffset,
1061 dummyPlugin.setPageYOffset,
1062 dummyPlugin.getHorizontalScrollbarThickness,
1063 dummyPlugin.getVerticalScrollbarThickness,
1064 dummyPlugin.getPageLocationNormalized,
1065 dummyPlugin.getHeight,
1066 dummyPlugin.getWidth];
1067
1068 for (var i = 0; i < pluginInterface.length; i++) {
1069 if (!pluginInterface[i])
1070 return false;
1071 }
1072 return true;
1073 }
1074
1075 /**
1076 * Sets the default values and sends a request to regenerate preview data.
1077 * Resets the margin options only if |resetMargins| is true.
1078 * @param {boolean} resetMargins True if margin settings should be resetted.
1079 */
1080 function setDefaultValuesAndRegeneratePreview(resetMargins) {
1081 if (resetMargins)
1082 marginSettings.resetMarginsIfNeeded();
1083 pageSettings.resetState();
1084 requestPrintPreview();
1085 }
1086
1087 /**
1088 * Class that represents the state of the print settings.
1089 * @constructor
1090 */
1091 function PrintSettings() {
1092 this.deviceName = '';
1093 this.isLandscape = '';
1094 this.hasHeaderFooter = '';
1095 }
1096
1097 /**
1098 * Takes a snapshot of the print settings.
1099 */
1100 PrintSettings.prototype.save = function() {
1101 this.deviceName = getSelectedPrinterName();
1102 this.isLandscape = layoutSettings.isLandscape();
1103 this.hasHeaderFooter = headerFooterSettings.hasHeaderFooter();
1104 };
1105
1106 /**
1107 * Updates the title of the print preview tab according to |initiatorTabTitle|.
1108 * @param {string} initiatorTabTitle The title of the initiator tab.
1109 */
1110 function setInitiatorTabTitle(initiatorTabTitle) {
1111 if (initiatorTabTitle == '')
1112 return;
1113 document.title = localStrings.getStringF(
1114 'printPreviewTitleFormat', initiatorTabTitle);
1115 }
1116
1117 /**
1118 * Closes this print preview tab.
1119 */
1120 function closePrintPreviewTab() {
1121 window.removeEventListener('keydown', onKeyDown);
1122 chrome.send('closePrintPreviewTab');
1123 chrome.send('DialogClose');
1124 }
1125
1126 /**
1127 * Pass certain directional keyboard events to the PDF viewer.
1128 * @param {Event} e The keydown event.
1129 */
1130 function tryToHandleDirectionKeyDown(e) {
1131 // Make sure the PDF plugin is there.
1132 if (!previewArea.pdfPlugin)
1133 return;
1134
1135 // We only care about: PageUp, PageDown, Left, Up, Right, Down.
1136 if (!(e.keyCode == 33 || e.keyCode == 34 ||
1137 (e.keyCode >= 37 && e.keyCode <= 40))) {
1138 return;
1139 }
1140
1141 // If the user is holding a modifier key, ignore.
1142 if (e.metaKey || e.altKey || e.shiftKey || e.ctrlKey)
1143 return;
1144
1145 // Don't handle the key event for these elements.
1146 var tagName = document.activeElement.tagName;
1147 if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'EMBED')
1148 return;
1149
1150 // For the most part, if any div of header was the last clicked element,
1151 // then the active element is the body. Starting with the last clicked
1152 // element, and work up the DOM tree to see if any element has a scrollbar.
1153 // If there exists a scrollbar, do not handle the key event here.
1154 var element = document.activeElement;
1155 if (element == document.body) {
1156 if (lastClickedElement)
1157 element = lastClickedElement;
1158 while (element) {
1159 if (element.scrollHeight > element.clientHeight)
1160 return;
1161 element = element.parentElement;
1162 }
1163 }
1164
1165 // No scroll bar anywhere, or the active element is something else, like a
1166 // button. Note: buttons have a bigger scrollHeight than clientHeight.
1167 previewArea.pdfPlugin.sendKeyEvent(e.keyCode);
1168 e.preventDefault();
1169 }
1170
1171 /**
1172 * Handle keyboard events.
1173 * @param {KeyboardEvent} e The keyboard event.
1174 */
1175 function onKeyDown(e) {
1176 // Escape key closes the dialog.
1177 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
1178 printHeader.disableCancelButton();
1179 closePrintPreviewTab();
1180 e.preventDefault();
1181 }
1182 // Ctrl + Shift + p / Mac equivalent.
1183 if (e.keyCode == 80) {
1184 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
1185 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
1186 window.removeEventListener('keydown', onKeyDown);
1187 onSystemDialogLinkClicked();
1188 e.preventDefault();
1189 }
1190 }
1191
1192 tryToHandleDirectionKeyDown(e);
1193 }
1194
1195 window.addEventListener('DOMContentLoaded', onLoad);
1196 window.addEventListener('keydown', onKeyDown);
1197
1198 /// Pull in all other scripts in a single shot.
1199 <include src="print_preview_animations.js"/> 894 <include src="print_preview_animations.js"/>
1200 <include src="print_preview_cloud.js"/> 895 <include src="cloud_print_interface.js"/>
1201 <include src="print_preview_utils.js"/> 896 <include src="print_preview_utils.js"/>
1202 <include src="print_header.js"/> 897 <include src="print_header.js"/>
1203 <include src="page_settings.js"/> 898
1204 <include src="copies_settings.js"/> 899 <include src="settings/page_settings.js"/>
1205 <include src="header_footer_settings.js"/> 900 <include src="settings/copies_settings.js"/>
1206 <include src="layout_settings.js"/> 901 <include src="settings/header_footer_settings.js"/>
1207 <include src="color_settings.js"/> 902 <include src="settings/layout_settings.js"/>
1208 <include src="margin_settings.js"/> 903 <include src="settings/color_settings.js"/>
1209 <include src="margin_textbox.js"/> 904 <include src="settings/margin_settings.js"/>
1210 <include src="margin_utils.js"/> 905 <include src="settings/destination_settings.js"/>
1211 <include src="margins_ui.js"/> 906
1212 <include src="margins_ui_pair.js"/> 907 <include src="previewarea/margin_control.js"/>
1213 <include src="preview_area.js"/> 908 <include src="previewarea/margin_control_container.js"/>
909 <include src="previewarea/preview_area.js"/>
910 <include src="preview_generator.js"/>
911
912 var printPreview = new print_preview.PrintPreview();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698