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

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: Review feedback Created 8 years, 8 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
10 // and populate the list of printers with cloud print printers.
11 var useCloudPrint = false;
12
13 // Store the last selected printer index.
14 var lastSelectedPrinterIndex = 0;
15
16 // Used to disable some printing options when the preview is not modifiable.
17 var previewModifiable = false;
18
19 // Used to identify whether the printing frame has specific page size style.
20 var hasPageSizeStyle = false;
21
22 // Destination list special value constants. 16 // Destination list special value constants.
23 17 /** @const **/ var PRINT_TO_PDF = 'Save as PDF';
24 /** @const */ var MANAGE_CLOUD_PRINTERS = 'manageCloudPrinters'; 18
25 /** @const */ var MANAGE_LOCAL_PRINTERS = 'manageLocalPrinters'; 19 <include src="component.js"/>
26 /** @const */ var SIGN_IN = 'signIn'; 20
27 /** @const */ var PRINT_TO_PDF = 'Save as PDF'; 21 cr.define('print_preview', function() {
28 /** @const */ var PRINT_WITH_CLOUD_PRINT = 'printWithCloudPrint'; 22 'use strict';
29 23
30 // State of the print preview settings. 24 /**
31 var printSettings = new PrintSettings(); 25 * Container class for Chromium's print preview.
32 26 *
33 // Print ready data index. 27 * @param {!print_preview.NativeLayer} nativeLayer Used to communicate with
34 /** @const */ var PRINT_READY_DATA_INDEX = -1; 28 * Chromium's print system.
35 29 * @constructor
36 // The name of the default or last used printer. 30 * @extends {print_preview.Component}
37 var defaultOrLastUsedPrinterName = ''; 31 */
38 32 function PrintPreview(nativeLayer) {
39 // True when a pending print preview request exists. 33 print_preview.Component.call(this);
40 var hasPendingPreviewRequest = false; 34
41 35 /**
42 // True when the first page is loaded in the plugin. 36 * Used to communicate with Chromium's print system.
43 var isFirstPageLoaded = false; 37 * @type {!print_preview.NativeLayer}
44 38 * @private
45 // The ID of the last preview request. 39 */
46 var lastPreviewRequestID = -1; 40 this.nativeLayer_ = nativeLayer;
47 41
48 // The ID of the initial preview request. 42 /**
49 var initialPreviewRequestID = -1; 43 * Data store which holds print destinations.
50 44 * @type {!print_preview.DestinationStore}
51 // True when a pending print file request exists. 45 * @private
52 var hasPendingPrintDocumentRequest = false; 46 */
53 47 this.destinationStore_ = new print_preview.DestinationStore();
54 // True when the complete metafile for the previewed doc is ready. 48
55 var isPrintReadyMetafileReady = false; 49 /**
56 50 * Storage of the print ticket used to create the print job.
57 // True when preview tab is hidden. 51 * @type {!print_preview.PrintTicketStore}
58 var isTabHidden = false; 52 * @private
59 53 */
60 // True in kiosk mode where print preview can print automatically without 54 this.printTicketStore_ = new print_preview.PrintTicketStore(
61 // user intervention. See http://crbug.com/31395. 55 this.destinationStore_);
62 var printAutomaticallyInKioskMode = false; 56
63 57 /**
64 // @type {print_preview.PrintHeader} Holds the print and cancel buttons. 58 * Holds the print and cancel buttons and renders some document statistics.
65 var printHeader; 59 * @type {!print_preview.PrintHeader}
66 60 * @private
67 // @type {print_preview.PageSettings} Holds all the pages related settings. 61 */
68 var pageSettings; 62 this.printHeader_ = new print_preview.PrintHeader(
69 63 this.printTicketStore_, this.destinationStore_);
70 // @type {print_preview.CopiesSettings} Holds all the copies related settings. 64 this.addChild(this.printHeader_);
71 var copiesSettings; 65
72 66 /**
73 // @type {print_preview.LayoutSettings} Holds all the layout related settings. 67 * Component that renders the print destination.
74 var layoutSettings; 68 * @type {!print_preview.DestinationSettings}
75 69 * @private
76 // @type {print_preview.MarginSettings} Holds all the margin related settings. 70 */
77 var marginSettings; 71 this.destinationSettings_ = new print_preview.DestinationSettings(
78 72 this.destinationStore_);
79 // @type {print_preview.HeaderFooterSettings} Holds all the header footer 73 this.addChild(this.destinationSettings_);
80 // related settings. 74
81 var headerFooterSettings; 75 /**
82 76 * Component that renders UI for entering in page range.
83 // @type {print_preview.ColorSettings} Holds all the color related settings. 77 * @type {!print_preview.PageSettings}
84 var colorSettings; 78 * @private
85 79 */
86 // @type {print_preview.PreviewArea} Holds information related to the preview 80 this.pageSettings_ = new print_preview.PageSettings(this.printTicketStore_);
87 // area (on the right). 81 this.addChild(this.pageSettings_);
88 var previewArea; 82
89 83 /**
90 // True if the user has click 'Advanced...' in order to open the system print 84 * Component that renders the copies settings.
91 // dialog. 85 * @type {!print_preview.CopiesSettings}
92 var showingSystemDialog = false; 86 * @private
93 87 */
94 // True if the user has clicked 'Open PDF in Preview' option. 88 this.copiesSettings_ = new print_preview.CopiesSettings(
95 var previewAppRequested = false; 89 this.printTicketStore_);
96 90 this.addChild(this.copiesSettings_);
97 // The range of options in the printer dropdown controlled by cloud print. 91
98 var firstCloudPrintOptionPos = 0; 92 /**
99 var lastCloudPrintOptionPos = firstCloudPrintOptionPos; 93 * Component that renders the layout settings.
100 94 * @type {!print_preview.LayoutSettings}
101 // Store the current previewUid. 95 * @private
102 var currentPreviewUid = ''; 96 */
103 97 this.layoutSettings_ = new print_preview.LayoutSettings(
104 // True if we need to generate draft preview data. 98 this.printTicketStore_);
105 var generateDraftData = true; 99 this.addChild(this.layoutSettings_);
106 100
107 // The last element clicked with the mouse. 101 /**
108 var lastClickedElement = null; 102 * Component that renders the color options.
109 103 * @type {!print_preview.ColorSettings}
110 // A dictionary of cloud printers that have been added to the printer 104 * @private
111 // dropdown. 105 */
112 var addedCloudPrinters = {}; 106 this.colorSettings_ = new print_preview.ColorSettings(
113 107 this.printTicketStore_);
114 // The maximum number of cloud printers to allow in the dropdown. 108 this.addChild(this.colorSettings_);
115 /** @const */ var maxCloudPrinters = 10; 109
116 110 /**
117 /** @const */ var MIN_REQUEST_ID = 0; 111 * Component that renders a select box for choosing margin settings.
118 /** @const */ var MAX_REQUEST_ID = 32000; 112 * @type {!print_preview.MarginSettings}
119 113 * @private
120 // Names of all the custom events used. 114 */
121 var customEvents = { 115 this.marginSettings_ = new print_preview.MarginSettings(
122 // Fired when the mouse moves while a margin line is being dragged. 116 this.printTicketStore_);
123 MARGIN_LINE_DRAG: 'marginLineDrag', 117 this.addChild(this.marginSettings_);
124 // Fired when a mousedown event occurs on a margin line. 118
125 MARGIN_LINE_MOUSE_DOWN: 'marginLineMouseDown', 119 /**
126 // Fired when a margin textbox gains focus. 120 * Holds all the header footer related settings.
127 MARGIN_TEXTBOX_FOCUSED: 'marginTextboxFocused', 121 * @type {!print_preview.HeaderFooterSettings}
128 // Fired when a new preview might be needed because of margin changes. 122 * @private
129 MARGINS_MAY_HAVE_CHANGED: 'marginsMayHaveChanged', 123 */
130 // Fired when a pdf generation related error occurs. 124 this.headerFooterSettings_ = new print_preview.HeaderFooterSettings(
131 PDF_GENERATION_ERROR: 'PDFGenerationError', 125 this.printTicketStore_);
132 // Fired once the first page of the pdf document is loaded in the plugin. 126 this.addChild(this.headerFooterSettings_);
133 PDF_LOADED: 'PDFLoaded', 127
134 // Fired when the selected printer capabilities change. 128 /**
135 PRINTER_CAPABILITIES_UPDATED: 'printerCapabilitiesUpdated', 129 * Area of the UI that holds the print preview.
136 // Fired when the print button needs to be updated. 130 * @type {!print_preview.PreviewArea}
137 UPDATE_PRINT_BUTTON: 'updatePrintButton', 131 * @private
138 // Fired when the print summary needs to be updated. 132 */
139 UPDATE_SUMMARY: 'updateSummary' 133 this.previewArea_ = new print_preview.PreviewArea(
140 }; 134 this.destinationStore_, this.printTicketStore_, this.nativeLayer_);
141 135 this.addChild(this.previewArea_);
142 /** 136
143 * Window onload handler, sets up the page and starts print preview by getting 137 /**
144 * the printer list. 138 * Interface to the Google Cloud Print API. Null if Google Cloud Print
145 */ 139 * integration is disabled.
146 function onLoad() { 140 * @type {cloudprint.CloudPrintInterface}
147 initialPreviewRequestID = randomInteger(MIN_REQUEST_ID, MAX_REQUEST_ID); 141 * @private
148 lastPreviewRequestID = initialPreviewRequestID; 142 */
149 143 this.cloudPrintInterface_ = null;
150 previewArea = print_preview.PreviewArea.getInstance(); 144
151 printHeader = print_preview.PrintHeader.getInstance(); 145 /**
152 document.addEventListener(customEvents.PDF_GENERATION_ERROR, 146 * Whether in kiosk mode where print preview can print automatically without
153 cancelPendingPrintRequest); 147 * user intervention. See http://crbug.com/31395.
154 document.addEventListener('click', setLastClickedElement); 148 * TODO Use this variable.
155 149 * @type {boolean}
156 if (!checkCompatiblePluginExists()) { 150 * @private
157 disableInputElementsInSidebar(); 151 */
158 $('cancel-button').focus(); 152 this.isInKioskAutoPrintMode_ = false;
159 previewArea.displayErrorMessageWithButtonAndNotify( 153
160 localStrings.getString('noPlugin'), 154 /**
161 localStrings.getString('launchNativeDialog'), 155 * State of the print preview UI.
162 launchNativePrintDialog); 156 * @type {PrintPreview.UiState}
163 $('mainview').parentElement.removeChild($('dummy-viewer')); 157 * @private
164 return; 158 */
165 } 159 this.uiState_ = PrintPreview.UiState.INITIALIZING;
166 160
167 $('system-dialog-link').addEventListener('click', onSystemDialogLinkClicked); 161 /**
168 if (cr.isMac) { 162 * Current state of fetching destinations.
169 $('open-pdf-in-preview-link').addEventListener( 163 * @type {PrintPreview.FetchPrintersState}
170 'click', onOpenPdfInPreviewLinkClicked); 164 * @private
171 } 165 */
172 $('mainview').parentElement.removeChild($('dummy-viewer')); 166 this.fetchState_ = PrintPreview.FetchState.READY;
173 167
174 $('printer-list').disabled = true; 168 this.tracker.add(window, 'DOMContentLoaded', this.onWindowLoad_.bind(this));
175 169 };
176 pageSettings = print_preview.PageSettings.getInstance(); 170
177 copiesSettings = print_preview.CopiesSettings.getInstance(); 171 /**
178 layoutSettings = print_preview.LayoutSettings.getInstance(); 172 * States of the print preview.
179 marginSettings = print_preview.MarginSettings.getInstance(); 173 * @enum {string}
180 headerFooterSettings = print_preview.HeaderFooterSettings.getInstance(); 174 */
181 colorSettings = print_preview.ColorSettings.getInstance(); 175 PrintPreview.UiState = {
182 $('printer-list').onchange = updateControlsWithSelectedPrinterCapabilities; 176 INITIALIZING: 'initializing',
183 177 FETCHING_DESTINATIONS: 'fetching-destinations',
184 previewArea.showLoadingAnimation(); 178 READY: 'ready',
185 chrome.send('getInitialSettings'); 179 OPENING_PDF_PREVIEW: 'opening-pdf-preview',
186 } 180 OPENING_NATIVE_PRINT_DIALOG: 'opening-native-print-dialog',
187 181 PRINTING: 'printing',
188 /** 182 FILE_SELECTION: 'file-selection',
189 * @param {object} initialSettings An object containing all the initial 183 CLOSING: 'closing'
190 * settings. 184 };
191 */ 185
192 function setInitialSettings(initialSettings) { 186 /**
193 setInitiatorTabTitle(initialSettings['initiatorTabTitle']); 187 * Bitfield of the states of fetching destinations.
194 previewModifiable = initialSettings['previewModifiable']; 188 * @enum {number}
195 if (previewModifiable) { 189 * @private
196 print_preview.MarginSettings.setNumberFormatAndMeasurementSystem( 190 */
197 initialSettings['numberFormat'], 191 PrintPreview.FetchState = {
198 initialSettings['measurementSystem']); 192 READY: 1,
199 marginSettings.setLastUsedMargins(initialSettings); 193 LOCAL_DESTINATIONS: 2,
200 } 194 RECENT_CLOUD_DESTINATIONS: 4,
201 printAutomaticallyInKioskMode = 195 ALL_CLOUD_DESTINATIONS: 8
202 initialSettings['printAutomaticallyInKioskMode']; 196 };
203 headerFooterSettings.setChecked(initialSettings['headerFooterEnabled']); 197
204 copiesSettings.previousDuplexMode = initialSettings['duplex']; 198 PrintPreview.prototype = {
205 setDefaultPrinter(initialSettings['printerName'], 199 __proto__: print_preview.Component.prototype,
206 initialSettings['cloudPrintData']); 200
207 } 201 /** @override */
208 202 decorateInternal: function() {
209 /** 203 this.printHeader_.decorate($('print-header'));
210 * Disables the input elements in the sidebar. 204 this.destinationSettings_.decorate($('destination-settings'));
211 */ 205 this.pageSettings_.decorate($('page-settings'));
212 function disableInputElementsInSidebar() { 206 this.copiesSettings_.decorate($('copies-settings'));
213 var els = $('navbar-container').querySelectorAll('input, button, select'); 207 this.layoutSettings_.decorate($('layout-settings'));
214 for (var i = 0; i < els.length; i++) { 208 this.colorSettings_.decorate($('color-settings'));
215 if (els[i] == printHeader.cancelButton) 209 this.marginSettings_.decorate($('margin-settings'));
216 continue; 210 this.headerFooterSettings_.decorate($('header-footer-settings'));
217 els[i].disabled = true; 211 this.previewArea_.decorate($('preview-area'));
218 } 212 },
219 } 213
220 214 /** @override */
221 /** 215 enterDocument: function() {
222 * Enables the input elements in the sidebar. 216 // Native layer events.
223 */ 217 this.tracker.add(
224 function enableInputElementsInSidebar() { 218 this.nativeLayer_,
225 var els = $('navbar-container').querySelectorAll('input, button, select'); 219 print_preview.NativeLayer.Event.INITIAL_SETTINGS_SET,
226 for (var i = 0; i < els.length; i++) 220 this.onInitialSettingsSet_.bind(this));
227 els[i].disabled = false; 221 this.tracker.add(
228 } 222 this.nativeLayer_,
229 223 print_preview.NativeLayer.Event.CLOUD_PRINT_ENABLE,
230 /** 224 this.onCloudPrintEnable_.bind(this));
231 * Keep track of the last element to receive a click. 225 this.tracker.add(
232 * @param {Event} e The click event. 226 this.nativeLayer_,
233 */ 227 print_preview.NativeLayer.Event.LOCAL_DESTINATIONS_SET,
234 function setLastClickedElement(e) { 228 this.onLocalDestinationsSet_.bind(this));
235 lastClickedElement = e.target; 229 this.tracker.add(
236 } 230 this.nativeLayer_,
237 231 print_preview.NativeLayer.Event.CAPABILITIES_SET,
238 /** 232 this.onLocalDestinationCapabilitiesSet_.bind(this));
239 * Disables the controls in the sidebar, shows the throbber and instructs the 233 this.tracker.add(
240 * backend to open the native print dialog. 234 this.nativeLayer_,
241 */ 235 print_preview.NativeLayer.Event.DESTINATIONS_RELOAD,
242 function onSystemDialogLinkClicked() { 236 this.onDestinationsReload_.bind(this));
243 if (showingSystemDialog) 237 this.tracker.add(
244 return; 238 this.nativeLayer_,
245 showingSystemDialog = true; 239 print_preview.NativeLayer.Event.PRINT_TO_CLOUD,
246 disableInputElementsInSidebar(); 240 this.onPrintToCloud_.bind(this));
247 printHeader.disableCancelButton(); 241 this.tracker.add(
248 $('system-dialog-throbber').hidden = false; 242 this.nativeLayer_,
249 chrome.send('showSystemDialog'); 243 print_preview.NativeLayer.Event.FILE_SELECTION_CANCEL,
250 } 244 this.onFileSelectionCancel_.bind(this));
251 245 this.tracker.add(
252 /** 246 this.nativeLayer_,
253 * Disables the controls in the sidebar, shows the throbber and instructs the 247 print_preview.NativeLayer.Event.FILE_SELECTION_COMPLETE,
254 * backend to open the pdf in native preview app. This is only for Mac. 248 this.onFileSelectionComplete_.bind(this));
255 */ 249 this.tracker.add(
256 function onOpenPdfInPreviewLinkClicked() { 250 this.nativeLayer_,
257 if (previewAppRequested) 251 print_preview.NativeLayer.Event.SETTINGS_INVALID,
258 return; 252 this.onSettingsInvalid_.bind(this));
259 previewAppRequested = true; 253
260 disableInputElementsInSidebar(); 254 this.tracker.add(
261 $('open-preview-app-throbber').hidden = false; 255 this.destinationSettings_,
262 printHeader.disableCancelButton(); 256 print_preview.DestinationSettings.Event.MANAGE_PRINTERS_SELECT,
263 requestToPrintDocument(); 257 this.onManagePrintersSelect_.bind(this));
264 } 258
265 259 this.tracker.add(
266 /** 260 $('system-dialog-link'),
267 * Similar to onSystemDialogLinkClicked(), but specific to the 261 'click',
268 * 'Launch native print dialog' UI. 262 this.onSystemDialogLinkClicked_.bind(this));
269 */ 263
270 function launchNativePrintDialog() { 264 if (cr.isMac) {
271 if (showingSystemDialog) 265 this.tracker.add(
272 return; 266 $('open-pdf-in-preview-link'),
273 showingSystemDialog = true; 267 'click',
274 previewArea.errorButton.disabled = true; 268 this.onOpenPdfInPreviewLinkClick_.bind(this));
275 printHeader.disableCancelButton(); 269 }
276 $('native-print-dialog-throbber').hidden = false; 270
277 chrome.send('showSystemDialog'); 271 this.tracker.add(
278 } 272 this.previewArea_,
279 273 print_preview.PreviewArea.Event.PREVIEW_GENERATION_FAIL,
280 /** 274 this.onPreviewGenerationFail_.bind(this));
281 * Gets the selected printer capabilities and updates the controls accordingly. 275 this.tracker.add(
282 */ 276 this.previewArea_,
283 function updateControlsWithSelectedPrinterCapabilities() { 277 print_preview.PreviewArea.Event.OPEN_SYSTEM_DIALOG_CLICK,
284 var printerList = $('printer-list'); 278 this.openSystemPrintDialog_.bind(this));
285 var selectedIndex = printerList.selectedIndex; 279
286 if (selectedIndex < 0) 280 this.tracker.add(
287 return; 281 this.destinationStore_,
288 if (cr.isMac) 282 print_preview.DestinationStore.Event.DESTINATION_SELECT,
289 $('open-pdf-in-preview-link').disabled = false; 283 this.onDestinationSelect_.bind(this));
290 284
291 var skip_refresh = false; 285 this.tracker.add(
292 var selectedValue = printerList.options[selectedIndex].value; 286 this.printHeader_,
293 if (cloudprint.isCloudPrint(printerList.options[selectedIndex])) { 287 print_preview.PrintHeader.Event.PRINT_BUTTON_CLICK,
294 cloudprint.updatePrinterCaps(printerList.options[selectedIndex], 288 this.onPrintButtonClick_.bind(this));
295 doUpdateCloudPrinterCapabilities); 289 this.tracker.add(
296 skip_refresh = true; 290 this.printHeader_,
297 } else if (selectedValue == SIGN_IN || 291 print_preview.PrintHeader.Event.CANCEL_BUTTON_CLICK,
298 selectedValue == MANAGE_CLOUD_PRINTERS || 292 this.onCancelButtonClick_.bind(this));
299 selectedValue == MANAGE_LOCAL_PRINTERS) { 293
300 printerList.selectedIndex = lastSelectedPrinterIndex; 294 this.tracker.add(window, 'keydown', this.onKeyDown_.bind(this));
301 chrome.send(selectedValue); 295 },
302 skip_refresh = true; 296
303 } else if (selectedValue == PRINT_TO_PDF || 297 disable_: function() {
304 selectedValue == PRINT_WITH_CLOUD_PRINT) { 298 $('system-dialog-link').disabled = true;
305 updateWithPrinterCapabilities({ 299 if (cr.isMac) {
306 'disableColorOption': true, 300 $('open-pdf-in-preview-link').disabled = true;
307 'setColorAsDefault': true, 301 }
308 'setDuplexAsDefault': false, 302 this.printHeader_.isEnabled = false;
309 'printerColorModelForColor': print_preview.ColorSettings.COLOR, 303 this.destinationSettings_.isEnabled = false;
310 'printerDefaultDuplexValue': copiesSettings.UNKNOWN_DUPLEX_MODE, 304 this.pageSettings_.isEnabled = false;
311 'disableCopiesOption': true}); 305 this.copiesSettings_.isEnabled = false;
312 if (cr.isChromeOS && selectedValue == PRINT_WITH_CLOUD_PRINT) 306 this.layoutSettings_.isEnabled = false;
313 requestToPrintDocument(); 307 this.colorSettings_.isEnabled = false;
314 } else { 308 this.marginSettings_.isEnabled = false;
315 // This message will call back to 'updateWithPrinterCapabilities' 309 this.headerFooterSettings_.isEnabled = false;
316 // function. 310 },
317 chrome.send('getPrinterCapabilities', [selectedValue]); 311
318 } 312 /**
319 if (!skip_refresh) { 313 * Creates a local PDF print destination.
320 lastSelectedPrinterIndex = selectedIndex; 314 * @return {!print_preview.Destination} Created print destination.
321 315 * @private
322 // Regenerate the preview data based on selected printer settings. 316 */
323 // Do not reset the margins if no preview request has been made. 317 createLocalPdfPrintDestination_: function() {
324 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; 318 var dest = new print_preview.Destination(
325 setDefaultValuesAndRegeneratePreview(resetMargins); 319 PRINT_TO_PDF,
326 } 320 localStrings.getString('printToPDF'),
327 } 321 false /*isRecent*/,
328 322 true /*isLocal*/,
329 /** 323 [] /*tags*/);
330 * Helper function to do the actual work of updating cloud printer 324 dest.capabilities = new print_preview.ChromiumCapabilities(
331 * capabilities. 325 false /*hasCopiesCapability*/,
332 * @param {Object} printer The printer object to set capabilities for. 326 '1' /*defaultCopiesStr*/,
333 */ 327 false /*hasCollateCapability*/,
334 function doUpdateCloudPrinterCapabilities(printer) { 328 false /*defaultIsCollateEnabled*/,
335 var settings = {'disableColorOption': !cloudprint.supportsColor(printer), 329 false /*hasDuplexCapability*/,
336 'setColorAsDefault': cloudprint.colorIsDefault(printer), 330 false /*defaultIsDuplexEnabled*/,
337 'disableCopiesOption': true, 331 true /*hasOrientationCapability*/,
338 'disableLandscapeOption': true}; 332 false /*defaultIsLandscapeEnabled*/,
339 updateWithPrinterCapabilities(settings); 333 true /*hasColorCapability*/,
340 var printerList = $('printer-list'); 334 true /*defaultIsColorEnabled*/);
341 var selectedIndex = printerList.selectedIndex; 335 return dest;
342 lastSelectedPrinterIndex = selectedIndex; 336 },
343 337
344 // Regenerate the preview data based on selected printer settings. 338 /**
345 // Do not reset the margins if no preview request has been made. 339 * Creates a new "Print with Cloud Print" print destination. NOTE: this
346 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; 340 * destination will appear as "Search for additional printers..." on
347 setDefaultValuesAndRegeneratePreview(resetMargins); 341 * Chrome OS.
348 } 342 * @return {!print_preview.Destination} Created print destination.
349 343 * @private
350 /** 344 */
351 * Notifies listeners of |customEvents.PRINTER_CAPABILITIES_UPDATED| about the 345 createPrintWithCloudPrintDestination_: function() {
352 * capabilities of the currently selected printer. It is called from C++ too. 346 var dest = new print_preview.Destination(
353 * @param {Object} settingInfo printer setting information. 347 'printWithCloudPrint',
354 */ 348 localStrings.getString('printWithCloudPrint'),
355 function updateWithPrinterCapabilities(settingInfo) { 349 false /*isRecent*/,
356 var customEvent = new cr.Event(customEvents.PRINTER_CAPABILITIES_UPDATED); 350 false /*isLocal*/,
357 customEvent.printerCapabilities = settingInfo; 351 [] /*tags*/);
358 document.dispatchEvent(customEvent); 352 dest.capabilities = new print_preview.ChromiumCapabilities(
359 } 353 false /*hasCopiesCapability*/,
360 354 '1' /*defaultCopiesStr*/,
361 /** 355 false /*hasCollateCapability*/,
362 * Reloads the printer list. 356 false /*defaultIsCollateEnabled*/,
363 */ 357 false /*hasDuplexCapability*/,
364 function reloadPrintersList() { 358 false /*defaultIsDuplexEnabled*/,
365 $('printer-list').length = 0; 359 true /*hasOrientationCapability*/,
366 firstCloudPrintOptionPos = 0; 360 false /*defaultIsLandscapeEnabled*/,
367 lastCloudPrintOptionPos = 0; 361 true /*hasColorCapability*/,
368 chrome.send('getPrinters'); 362 true /*defaultIsColorEnabled*/);
369 } 363 return dest;
370 364 },
371 /** 365
372 * Turn on the integration of Cloud Print. 366 printDocumentOrOpenPdfPreview_: function(isPdfPreview) {
373 * @param {string} cloudPrintURL The URL to use for cloud print servers. 367 if (this.uiState_ != PrintPreview.UiState.READY &&
374 */ 368 this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
375 function setUseCloudPrint(cloudPrintURL) { 369 throw Error(
376 useCloudPrint = true; 370 'Print document request received when not in ready nor ' +
377 cloudprint.setBaseURL(cloudPrintURL); 371 'fetching-destinations state: ' + this.uiState_);
378 } 372 }
379 373 if (!this.printTicketStore_.isTicketValid()) {
380 /** 374 throw Error('Trying to print with an invalid print ticket');
381 * Take the PDF data handed to us and submit it to the cloud, closing the print 375 }
382 * preview tab once the upload is successful. 376 // TODO
383 * @param {string} data Data to send as the print job. 377 // this.nativeLayer_.startSaveDestinationAndTicket(
384 */ 378 // this.destinationStore_.selectedDestination.id,
385 function printToCloud(data) { 379 // this.printTicketStore_);
386 cloudprint.printToCloud(data, finishedCloudPrinting); 380 this.nativeLayer_.startPrint(
387 } 381 this.destinationStore_.selectedDestination,
388 382 this.printTicketStore_,
389 /** 383 this.cloudPrintInterface_);
390 * Cloud print upload of the PDF file is finished, time to close the dialog. 384 // TODO handle case when need to pop open file selection dialog.
391 */ 385 // if (isPdfPreview) {
392 function finishedCloudPrinting() { 386 // settings.OpenPDFInPreview = isPdfPreview;
393 closePrintPreviewTab(); 387 // }
394 } 388 this.uiState_ = isPdfPreview ?
395 389 PrintPreview.UiState.OPENING_PDF_PREVIEW :
396 /** 390 PrintPreview.UiState.PRINTING;
397 * Checks whether the specified settings are valid. 391 },
398 * 392
399 * @return {boolean} true if settings are valid, false if not. 393 /**
400 */ 394 * Closes the print preview.
401 function areSettingsValid() { 395 * @private
402 var selectedPrinter = getSelectedPrinterName(); 396 */
403 return pageSettings.isPageSelectionValid() && 397 close_: function() {
404 marginSettings.areMarginSettingsValid() && 398 this.exitDocument();
405 (copiesSettings.isValid() || selectedPrinter == PRINT_TO_PDF || 399 this.uiState_ = PrintPreview.UiState.CLOSING;
406 selectedPrinter == PRINT_WITH_CLOUD_PRINT); 400 this.nativeLayer_.startCloseDialog();
407 } 401 },
408 402
409 /** 403 openSystemPrintDialog_: function() {
410 * Creates an object based on the values in the printer settings. 404 if (this.uiState_ != PrintPreview.UiState.READY &&
411 * 405 this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
412 * @return {Object} Object containing print job settings. 406 throw Error(
413 */ 407 'Request to open system dialog received when not in ready nor ' +
414 function getSettings() { 408 'fetching-destinations state: ' + this.uiState_);
415 var deviceName = getSelectedPrinterName(); 409 }
416 var printToPDF = deviceName == PRINT_TO_PDF; 410 this.disable_();
417 var printWithCloudPrint = deviceName == PRINT_WITH_CLOUD_PRINT; 411 this.uiState_ = PrintPreview.UiState.OPENING_NATIVE_PRINT_DIALOG;
418 412 this.nativeLayer_.startShowSystemDialog();
419 var settings = 413 },
420 {'deviceName': deviceName, 414
421 'pageRange': pageSettings.selectedPageRanges, 415 /**
422 'duplex': copiesSettings.duplexMode, 416 * Window onload handler, sets up the page and starts print preview by
423 'copies': copiesSettings.numberOfCopies, 417 * getting the printer list.
424 'collate': copiesSettings.isCollated(), 418 * @private
425 'landscape': layoutSettings.isLandscape(), 419 */
426 'color': colorSettings.colorMode, 420 onWindowLoad_: function() {
427 'printToPDF': printToPDF, 421 this.decorate($('print-preview'));
428 'printWithCloudPrint': printWithCloudPrint, 422 i18nTemplate.process(document, templateData);
429 'isFirstRequest' : false, 423 if (!this.previewArea_.hasCompatiblePlugin) {
430 'headerFooterEnabled': headerFooterSettings.hasHeaderFooter(), 424 this.disable_();
431 'marginsType': marginSettings.selectedMarginsValue, 425 }
432 'requestID': -1, 426 this.nativeLayer_.startGetInitialSettings();
433 'generateDraftData': generateDraftData, 427 // TODO Remove me
434 'previewModifiable': previewModifiable}; 428 $('clear-log-button').onclick = function() {
435 429 $('log').innerHTML = '';
436 if (marginSettings.isCustomMarginsSelected()) 430 };
437 settings['marginsCustom'] = marginSettings.customMargins; 431 },
438 432
439 var printerList = $('printer-list'); 433 /**
440 var selectedPrinter = printerList.selectedIndex; 434 * Called when the native layer has initial settings to set. Sets the
441 if (cloudprint.isCloudPrint(printerList.options[selectedPrinter])) { 435 * initial settings of the print preview and begins fetching print
442 settings['cloudPrintID'] = 436 * destinations.
443 printerList.options[selectedPrinter].value; 437 * @param {cr.Event} evt Contains the initial print preview
444 } 438 * settings persisted through the session.
445 return settings; 439 * @private
446 } 440 */
447 441 onInitialSettingsSet_: function(evt) {
448 /** 442 if (this.uiState_ != PrintPreview.UiState.INITIALIZING) {
449 * Creates an object based on the values in the printer settings. 443 throw Error(
450 * Note: |lastPreviewRequestID| is being modified every time this function is 444 'Updating initial settings when not in initializing state: ' +
451 * called. Only call this function when a preview request is actually sent, 445 this.uiState_);
452 * otherwise (for example when debugging) call getSettings(). 446 }
453 * 447
454 * @return {Object} Object containing print job settings. 448 // TODO use this boolean
455 */ 449 this.isInKioskAutoPrintMode_ = evt.initialSettings.isInKioskAutoPrintMode;
456 function getSettingsWithRequestID() { 450 this.destinationStore_.initialDestinationId =
457 var settings = getSettings(); 451 evt.initialSettings.initialDestinationId;
458 settings.requestID = generatePreviewRequestID(); 452 this.printTicketStore_.initialize(
459 settings.isFirstRequest = isFirstPreviewRequest(); 453 evt.initialSettings.isDocumentModifiable,
460 return settings; 454 evt.initialSettings.isDuplexEnabled,
461 } 455 evt.initialSettings.isHeaderFooterEnabled,
462 456 evt.initialSettings.marginsType,
463 /** 457 evt.initialSettings.customMargins,
464 * @return {number} The next unused preview request id. 458 evt.initialSettings.measurementSystem);
465 */ 459
466 function generatePreviewRequestID() { 460 this.nativeLayer_.startGetLocalDestinations();
467 return ++lastPreviewRequestID; 461 this.uiState_ = PrintPreview.UiState.FETCHING_DESTINATIONS;
468 } 462 },
469 463
470 /** 464 /**
471 * @return {boolean} True iff a preview has been requested. 465 * Calls when the native layer enables Google Cloud Print integration.
472 */ 466 * Fetches the user's cloud printers.
473 function hasRequestedPreview() { 467 * @param {cr.Event} evt Contains the base URL of the Google Cloud Print
474 return lastPreviewRequestID != initialPreviewRequestID; 468 * service.
475 } 469 * @private
476 470 */
477 /** 471 onCloudPrintEnable_: function(evt) {
478 * @return {boolean} True if |lastPreviewRequestID| corresponds to the initial 472 if (this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
479 * preview request. 473 throw Error(
480 */ 474 'Enabling Google Cloud Print when not in fetching-destinations ' +
481 function isFirstPreviewRequest() { 475 'state: ' + this.uiState_);
482 return lastPreviewRequestID == initialPreviewRequestID + 1; 476 }
483 } 477 this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface(
484 478 evt.baseCloudPrintUrl);
485 /** 479 this.tracker.add(
486 * Checks if |previewResponseId| matches |lastPreviewRequestId|. Used to ignore 480 this.cloudPrintInterface_,
487 * obsolete preview data responses. 481 cloudprint.CloudPrintInterface.Event.SEARCH_DONE,
488 * @param {number} previewResponseId The id to check. 482 this.onCloudPrintSearchDone_.bind(this));
489 * @return {boolean} True if previewResponseId reffers to the expected response. 483 this.tracker.add(
490 */ 484 this.cloudPrintInterface_,
491 function isExpectedPreviewResponse(previewResponseId) { 485 cloudprint.CloudPrintInterface.Event.PRINTER_DONE,
492 return lastPreviewRequestID == previewResponseId; 486 this.onCloudPrintPrinterDone_.bind(this));
493 } 487 this.tracker.add(
494 488 this.cloudPrintInterface_,
495 /** 489 cloudprint.CloudPrintInterface.Event.SUBMIT_DONE,
496 * Returns the name of the selected printer or the empty string if no 490 this.onCloudPrintSubmitDone_.bind(this));
497 * printer is selected. 491 this.tracker.add(
498 * @return {string} The name of the currently selected printer. 492 this.cloudPrintInterface_,
499 */ 493 cloudprint.CloudPrintInterface.Event.ERROR,
500 function getSelectedPrinterName() { 494 this.onCloudPrintError_.bind(this));
501 var printerList = $('printer-list'); 495
502 var selectedPrinter = printerList.selectedIndex; 496 var printWithCloudPrintDest =
503 if (selectedPrinter < 0) 497 this.createPrintWithCloudPrintDestination_();
504 return ''; 498 this.destinationStore_.insertDestination(printWithCloudPrintDest);
505 return printerList.options[selectedPrinter].value; 499
506 } 500 if (cr.isChromeOS) {
507 501 // Fetch recent printers.
508 /** 502 this.cloudPrintInterface_.search(true /*isRecent*/);
509 * Asks the browser to print the preview PDF based on current print 503
510 * settings. If the preview is still loading, printPendingFile() will get 504 this.fetchState_ |=
511 * called once the preview loads. 505 PrintPreview.FetchState.RECENT_CLOUD_DESTINATIONS |
512 */ 506 PrintPreview.FetchState.ALL_CLOUD_DESTINATIONS;
513 function requestToPrintDocument() { 507 }
514 hasPendingPrintDocumentRequest = !isPrintReadyMetafileReady; 508 },
515 var selectedPrinterName = getSelectedPrinterName(); 509
516 var printToPDF = selectedPrinterName == PRINT_TO_PDF; 510 /**
517 var printWithCloudPrint = selectedPrinterName == PRINT_WITH_CLOUD_PRINT; 511 * Called when the native layer gets local destinations. Adds local
518 if (hasPendingPrintDocumentRequest) { 512 * destination objects received from the operating system to the destination
519 if (previewAppRequested) { 513 * store.
514 * @param {cr.Event} Contains the local destinations to set.
515 * @private
516 */
517 onLocalDestinationsSet_: function(evt) {
518 if (this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
519 throw Error(
520 'Received local destinations when not in fetching-destinations ' +
521 'state: ' + this.uiState_);
522 }
523
524 var localDestinations = [];
525
526 // Add local destinations.
527 for (var destInfo, i = 0; destInfo = evt.destinationInfos[i]; i++) {
528 localDestinations.push(
529 print_preview.LocalDestinationParser.parse(destInfo));
530 }
531
532 // Add print-to-pdf destination.
533 localDestinations.push(this.createLocalPdfPrintDestination_());
534
535 this.destinationStore_.insertDestinations(localDestinations);
536
537 this.fetchState_ &= ~PrintPreview.FetchState.LOCAL_DESTINATIONS;
538 if (this.fetchState_ == PrintPreview.FetchState.READY) {
539 this.uiState_ = PrintPreview.UiState.READY;
540 }
541 },
542
543 /**
544 * Called when the native layer retrieves the capabilities for the selected
545 * local destination.
546 * @param {cr.Event} evt Contains the capabilities of the local print
547 * destination.
548 * @private
549 */
550 onLocalDestinationCapabilitiesSet_: function(evt) {
551 // TODO There may be a race condition here. This method is assumed to
552 // return capabilities for the currently selected printer. But between the
553 // time the local printer was selected and the capabilities were
554 // retrieved, the selected printer can change. One way to address this is
555 // to include the destination ID in the settingsInfo parameter.
556 // TODO Change data type of Destination.capabilities to
557 // ChromiumCapabilities.
558 var capabilities = print_preview.LocalCapabilitiesParser.parse(
559 evt.settingsInfo);
560 this.destinationStore_.selectedDestination.capabilities = capabilities;
561 this.printTicketStore_.updateDestinationCapabilities(capabilities);
562 },
563
564 /**
565 * Called from native layer after the user was requested to sign in, and did
566 * so successfully.
567 * @private
568 */
569 onDestinationsReload_: function() {
570 if (this.uiState_ != PrintPreview.UiState.READY) {
571 throw Error(
572 'Reload request received but not in ready state: ' + this.uiState_);
573 }
574 this.destinationStore_.clear();
575 this.nativeLayer_.startGetLocalDestinations();
576 if (this.cloudPrintInterface_) {
577 // Fetch recent printers.
578 this.cloudPrintInterface_.search(true /*isRecent*/);
579 // Fetch the full printer list.
580 this.cloudPrintInterface_.search(false /*isRecent*/);
581 }
582 this.uiState_ = PrintPreview.UiState.FETCHING_DESTINATIONS;
583 this.fetchState_ =
584 PrintPreview.FetchState.LOCAL_DESTINATIONS |
585 PrintPreview.FetchState.ALL_CLOUD_DESTINATIONS |
586 PrintPreview.FetchState.RECENT_CLOUD_DESTINATIONS;
587 },
588
589 /**
590 * Called from the native layer when ready to print to Google Cloud Print.
591 * @param {cr.Event} evt Contains the body to send in the HTTP request.
592 * @private
593 */
594 onPrintToCloud_: function(evt) {
595 if (this.uiState_ != PrintPreview.UiState.PRINTING) {
596 throw Error(
597 'Document ready to be sent to the cloud when not in printing ' +
598 'state: ' + this.uiState_);
599 }
600 if (this.cloudPrintInterface_) {
601 this.cloudPrintInterface_.submit(evt.data);
602 } else {
603 throw Error('Google Cloud Print is not enabled');
604 }
605 },
606
607 /**
608 * Called from the native layer when the user cancels the save-to-pdf file
609 * selection dialog.
610 * @private
611 */
612 onFileSelectionCancel_: function() {
613 if (this.uiState_ != PrintPreview.UiState.FILE_SELECTION) {
614 throw Error(
615 'File selection cancelled when not in file-selection state: ' +
616 this.uiState_);
617 }
618 // TODO Reenable controls.
619 this.uiState_ = PrintPreview.UiState.READY;
620 },
621
622 /**
623 * Called from the native layer when save-to-pdf file selection is complete.
624 * @private
625 */
626 onFileSelectionComplete_: function() {
627 this.disable_();
628 this.previewArea_.showCustomMessage(
629 localStrings.getString('printingToPDFInProgress'));
630 // TODO
631 },
632
633 /**
634 * Called when the Google Cloud Print search API call completes. Adds
635 * destinations to the printer store and selects one if it matches the
636 * initial destination.
637 * @param {cr.Event} evt Contains the new cloud destinations.
638 * @private
639 */
640 onCloudPrintSearchDone_: function(evt) {
641 this.destinationStore_.insertDestinations(evt.printers);
642
643 if (evt.isRecent) {
644 this.fetchState_ &= ~PrintPreview.FetchState.RECENT_CLOUD_DESTINATIONS;
645 } else {
646 this.fetchState_ &= ~PrintPreview.FetchState.ALL_CLOUD_DESTINATIONS;
647 }
648 if (this.fetchState_ == PrintPreview.FetchState.READY) {
649 this.uiState_ = PrintPreview.UiState.READY;
650 }
651 },
652
653 /**
654 * Called when the Google Cloud Print printer API call completes. Updates
655 * the UI with the newly received capabilities.
656 * @param {cr.Event} evt Contains the destination returned in the printer
657 * API call.
658 */
659 onCloudPrintPrinterDone_: function(evt) {
660 var dest = this.destinationStore_.updateDestination(evt.printer);
661 if (this.destinationStore_.selectedDestination == dest) {
662 this.printTicketStore_.updateDestinationCapabilities(dest.capabilities);
663 }
664 },
665
666 onCloudPrintSubmitDone_: function(evt) {
667 this.close_();
668 },
669
670 /**
671 * Called when there was an error communicating with Google Cloud print.
672 * Displays an error message in the print header.
673 * @param {cr.Event} evt Contains the error message.
674 * @private
675 */
676 onCloudPrintError_: function(evt) {
677 this.printHeader_.setErrorMessage(evt.message);
678 this.fetchState_ &=
679 (~PrintPreview.FetchState.RECENT_CLOUD_DESTINATIONS &
680 ~PrintPreview.FetchState.ALL_CLOUD_DESTINATIONS);
681 if (this.fetchState_ == PrintPreview.FetchState.READY) {
682 this.uiState_ = PrintPreview.UiState.READY;
683 }
684 },
685
686 onCloudPrintSignInRequested_: function() {
687 this.nativeLayer_.startCloudPrintSignIn();
688 },
689
690 /**
691 * Called when a new destination has been selected. Fetches the
692 * destination's capability list.
693 * @private
694 */
695 onDestinationSelect_: function() {
696 var destination = this.destinationStore_.selectedDestination;
697
698 if (cr.isChromeOS && destination.isPrintWithCloudPrint) {
699 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
700 return;
701 }
702
703 // Fetch destination capabilities if necessary.
704 if (!destination.capabilities) {
705 if (destination.isLocal) {
706 this.nativeLayer_.startGetLocalDestinationCapabilities(
707 destination.id);
708 } else if (this.cloudPrintInterface_) {
709 this.cloudPrintInterface_.printer(destination.id);
710 } else {
711 // TODO Probably a cloud printer was initially selected, but cloud
712 // print is no longer available. Maybe default to the system's local
713 // default? What about Chrome OS?
714 throw Error(
715 'Selected destination is a cloud destination, but Google Cloud ' +
716 'Print is not enabled');
717 }
718 } else {
719 this.printTicketStore_.updateDestinationCapabilities(
720 destination.capabilities);
721 }
722 },
723
724 /**
725 * Called when the preview area's preview failed to load.
726 * @private
727 */
728 onPreviewGenerationFail_: function() {
729 if (this.uiState_ == PrintPreview.UiState.PRINTING) {
730 this.nativeLayer_.startCancelPendingPrint();
731 }
732 },
733
734 onSystemDialogLinkClicked_: function() {
735 $('system-dialog-throbber').hidden = false;
736 this.openSystemPrintDialog_();
737 },
738
739 /**
740 * Called when the 'Open pdf in preview' link is clicked. Launches the pdf
741 * preview app.
742 * @private
743 */
744 onOpenPdfInPreviewLinkClick_: function() {
745 if (this.uiState_ != PrintPreview.UiState.READY &&
746 this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
747 throw Error(
748 'Trying to open pdf in preview when not in ready nor ' +
749 'fetching-destinations state: ' + this.uiState_);
750 }
751 $('open-preview-app-throbber').hidden = false;
752 this.disable_();
520 previewArea.showCustomMessage( 753 previewArea.showCustomMessage(
521 localStrings.getString('openingPDFInPreview')); 754 localStrings.getString('openingPDFInPreview'));
522 } else if (printToPDF) { 755 this.uiState_ = PrintPreview.UiState.OPENING_PDF_PREVIEW;
523 sendPrintDocumentRequest(); 756 this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
524 } else if (printWithCloudPrint) { 757 },
525 previewArea.showCustomMessage( 758
526 localStrings.getString('printWithCloudPrintWait')); 759 /**
527 disableInputElementsInSidebar(); 760 * Called when the print header's print button is clicked. Prints the
528 } else { 761 * document.
529 isTabHidden = true; 762 * @private
530 chrome.send('hidePreview'); 763 */
764 onPrintButtonClick_: function() {
765 if (this.uiState_ != PrintPreview.UiState.READY &&
766 this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
767 throw Error(
768 'Trying to print when not in ready nor fetching-destinations ' +
769 'state: ' + this.uiState_);
770 }
771 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
772 },
773
774 /**
775 * Called when the print header's cancel button is clicked. Closes the
776 * print dialog.
777 * @private
778 */
779 onCancelButtonClick_: function() {
780 this.close_();
781 },
782
783 /**
784 * Consume escape key presses and ctrl + shift + p. Delegate everything else
785 * to the preview area.
786 * @param {KeyboardEvent} e The keyboard event.
787 * @private
788 */
789 onKeyDown_: function(e) {
790 // Escape key closes the dialog.
791 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&
792 !e.metaKey) {
793 this.close_();
794 e.preventDefault();
795 return;
796 }
797
798 // Ctrl + Shift + p / Mac equivalent.
799 if (e.keyCode == 80) {
800 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
801 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
802 this.openSystemPrintDialog_();
803 e.preventDefault();
804 return;
805 }
806 }
807
808 // Pass certain directional keyboard events to the PDF viewer.
809 this.previewArea_.handleDirectionalKeyEvent(e);
810 },
811
812 /**
813 * Called when native layer receives invalid settings for a print request.
814 * @private
815 */
816 onSettingsInvalid_: function() {
817 // TODO UI state change
818 // if (cr.isMac) {
819 // if (previewAppRequested) {
820 // $('open-preview-app-throbber').hidden = true;
821 // this.previewArea_.clearCustomMessageWithDots();
822 // previewAppRequested = false;
823 // hasPendingPrintDocumentRequest = false;
824 // enableInputElementsInSidebar();
825 // }
826 // $('open-pdf-in-preview-link').disabled = true;
827 // }
828 this.previewArea_.showCustomMessage(
829 localStrings.getString('invalidPrinterSettings'));
830 },
831
832 onManagePrintersSelect_: function() {
833 if (cr.isChromeOS) {
834 this.nativeLayer_.startManageCloudPrinters();
835 } else {
836 this.nativeLayer_.startManageLocalPrinters();
837 }
531 } 838 }
532 return; 839 };
533 } 840
534 841 return {
535 if (printToPDF || previewAppRequested) { 842 PrintPreview: PrintPreview
536 sendPrintDocumentRequest(); 843 };
537 } else { 844 });
538 window.setTimeout(function() { sendPrintDocumentRequest(); }, 1000); 845
539 } 846 function log(message) {
847 $('log').appendChild(document.createTextNode(message));
848 $('log').appendChild(document.createElement('br'));
540 } 849 }
541 850
542 /** 851 // Pull in all other scripts in a single shot.
543 * Sends a message to cancel the pending print request. 852 <include src="data/page_number_set.js"/>
544 */ 853 <include src="data/destination.js"/>
545 function cancelPendingPrintRequest() { 854 <include src="data/local_parsers.js"/>
546 if (isTabHidden) 855 <include src="data/cloud_parsers.js"/>
547 chrome.send('cancelPendingPrintRequest'); 856 <include src="data/chromium_capabilities.js"/>
548 } 857 <include src="data/cloud_capabilities.js"/>
549 858 <include src="data/destination_store.js"/>
550 /** 859 <include src="data/margins.js"/>
551 * Sends a message to initiate print workflow. 860 <include src="data/printable_area.js"/>
552 */ 861 <include src="data/measurement_system.js"/>
553 function sendPrintDocumentRequest() { 862 <include src="data/print_ticket_store.js"/>
554 var printerList = $('printer-list'); 863 <include src="data/coordinate2d.js"/>
555 var printer = printerList[printerList.selectedIndex]; 864 <include src="data/size.js"/>
556 chrome.send('saveLastPrinter', [printer.value, cloudprint.getData(printer)]); 865 <include src="native_layer.js"/>
557
558 var settings = getSettings();
559 if (cr.isMac && previewAppRequested)
560 settings.OpenPDFInPreview = true;
561
562 chrome.send('print', [JSON.stringify(settings),
563 cloudprint.getPrintTicketJSON(printer)]);
564 }
565
566 /**
567 * Loads the selected preview pages.
568 */
569 function loadSelectedPages() {
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"/> 866 <include src="print_preview_animations.js"/>
1200 <include src="print_preview_cloud.js"/> 867 <include src="cloud_print_interface.js"/>
1201 <include src="print_preview_utils.js"/> 868 <include src="print_preview_utils.js"/>
1202 <include src="print_header.js"/> 869 <include src="print_header.js"/>
1203 <include src="page_settings.js"/> 870 <include src="settings/page_settings.js"/>
1204 <include src="copies_settings.js"/> 871 <include src="settings/copies_settings.js"/>
1205 <include src="header_footer_settings.js"/> 872 <include src="settings/header_footer_settings.js"/>
1206 <include src="layout_settings.js"/> 873 <include src="settings/layout_settings.js"/>
1207 <include src="color_settings.js"/> 874 <include src="settings/color_settings.js"/>
1208 <include src="margin_settings.js"/> 875 <include src="settings/margin_settings.js"/>
1209 <include src="margin_textbox.js"/> 876 <include src="settings/destination_settings.js"/>
1210 <include src="margin_utils.js"/> 877 <include src="previewarea/margin_utils.js"/>
1211 <include src="margins_ui.js"/> 878 <include src="previewarea/custom_margins.js"/>
1212 <include src="margins_ui_pair.js"/> 879 <include src="previewarea/margin_control.js"/>
1213 <include src="preview_area.js"/> 880 <include src="previewarea/preview_area.js"/>
881 <include src="preview_generator.js"/>
882
883 var printPreview = new print_preview.PrintPreview(nativeLayer);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698