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

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: Remove extra files 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 dest.capabilities.hasPageRangeCapability = true;
332 * @param {Object} printer The printer object to set capabilities for. 326 dest.capabilities.hasOrientationCapability = true;
333 */ 327 dest.capabilities.hasColorCapability = true;
334 function doUpdateCloudPrinterCapabilities(printer) { 328 dest.capabilities.defaultIsColorEnabled = true;
335 var settings = {'disableColorOption': !cloudprint.supportsColor(printer), 329 dest.capabilities.hasMarginsCapability = true;
336 'setColorAsDefault': cloudprint.colorIsDefault(printer), 330 dest.capabilities.hasHeaderFooterCapability = true;
337 'disableCopiesOption': true, 331 return dest;
338 'disableLandscapeOption': true}; 332 },
339 updateWithPrinterCapabilities(settings); 333
340 var printerList = $('printer-list'); 334 /**
341 var selectedIndex = printerList.selectedIndex; 335 * Creates a new "Print with Cloud Print" print destination. NOTE: this
342 lastSelectedPrinterIndex = selectedIndex; 336 * destination will appear as "Search for additional printers..." on
343 337 * Chrome OS.
344 // Regenerate the preview data based on selected printer settings. 338 * @return {print_preview.Destination!} Created print destination.
345 // Do not reset the margins if no preview request has been made. 339 * @private
346 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; 340 */
347 setDefaultValuesAndRegeneratePreview(resetMargins); 341 createPrintWithCloudPrintDestination_: function() {
348 } 342 var dest = new print_preview.Destination(
349 343 'printWithCloudPrint',
350 /** 344 localStrings.getString('printWithCloudPrint'),
351 * Notifies listeners of |customEvents.PRINTER_CAPABILITIES_UPDATED| about the 345 false /*isRecent*/,
352 * capabilities of the currently selected printer. It is called from C++ too. 346 false /*isLocal*/,
353 * @param {Object} settingInfo printer setting information. 347 [] /*tags*/);
354 */ 348 dest.capabilities = new print_preview.ChromiumCapabilities();
355 function updateWithPrinterCapabilities(settingInfo) { 349 dest.capabilities.hasPageRangeCapability = true;
356 var customEvent = new cr.Event(customEvents.PRINTER_CAPABILITIES_UPDATED); 350 dest.capabilities.hasOrientationCapability = true;
357 customEvent.printerCapabilities = settingInfo; 351 dest.capabilities.hasColorCapability = true;
358 document.dispatchEvent(customEvent); 352 dest.capabilities.defaultIsColorEnabled = true;
359 } 353 dest.capabilities.hasMarginsCapability = true;
360 354 dest.capabilities.hasHeaderFooterCapability = true;
361 /** 355 return dest;
362 * Reloads the printer list. 356 },
363 */ 357
364 function reloadPrintersList() { 358 printDocumentOrOpenPdfPreview_: function(isPdfPreview) {
365 $('printer-list').length = 0; 359 if (this.uiState_ != PrintPreview.UiState.READY &&
366 firstCloudPrintOptionPos = 0; 360 this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
367 lastCloudPrintOptionPos = 0; 361 throw Error(
368 chrome.send('getPrinters'); 362 'Print document request received when not in ready nor ' +
369 } 363 'fetching-destinations state: ' + this.uiState_);
370 364 }
371 /** 365 if (!this.printTicketStore_.isTicketValid()) {
372 * Turn on the integration of Cloud Print. 366 throw Error('Trying to print with an invalid print ticket');
373 * @param {string} cloudPrintURL The URL to use for cloud print servers. 367 }
374 */ 368 // TODO
375 function setUseCloudPrint(cloudPrintURL) { 369 // this.nativeLayer_.startSaveDestinationAndTicket(
376 useCloudPrint = true; 370 // this.destinationStore_.selectedDestination.id,
377 cloudprint.setBaseURL(cloudPrintURL); 371 // this.printTicketStore_);
378 } 372 this.nativeLayer_.startPrint(
379 373 this.destinationStore_.selectedDestination,
380 /** 374 this.printTicketStore_,
381 * Take the PDF data handed to us and submit it to the cloud, closing the print 375 this.cloudPrintInterface_);
382 * preview tab once the upload is successful. 376 // TODO handle case when need to pop open file selection dialog.
383 * @param {string} data Data to send as the print job. 377 // if (isPdfPreview) {
384 */ 378 // settings.OpenPDFInPreview = isPdfPreview;
385 function printToCloud(data) { 379 // }
386 cloudprint.printToCloud(data, finishedCloudPrinting); 380 this.uiState_ = isPdfPreview ?
387 } 381 PrintPreview.UiState.OPENING_PDF_PREVIEW :
388 382 PrintPreview.UiState.PRINTING;
389 /** 383 },
390 * Cloud print upload of the PDF file is finished, time to close the dialog. 384
391 */ 385 /**
392 function finishedCloudPrinting() { 386 * Closes the print preview.
393 closePrintPreviewTab(); 387 * @private
394 } 388 */
395 389 close_: function() {
396 /** 390 this.exitDocument();
397 * Checks whether the specified settings are valid. 391 this.uiState_ = PrintPreview.UiState.CLOSING;
398 * 392 this.nativeLayer_.startCloseDialog();
399 * @return {boolean} true if settings are valid, false if not. 393 },
400 */ 394
401 function areSettingsValid() { 395 openSystemPrintDialog_: function() {
402 var selectedPrinter = getSelectedPrinterName(); 396 if (this.uiState_ != PrintPreview.UiState.READY &&
403 return pageSettings.isPageSelectionValid() && 397 this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
404 marginSettings.areMarginSettingsValid() && 398 throw Error(
405 (copiesSettings.isValid() || selectedPrinter == PRINT_TO_PDF || 399 'Request to open system dialog received when not in ready nor ' +
406 selectedPrinter == PRINT_WITH_CLOUD_PRINT); 400 'fetching-destinations state: ' + this.uiState_);
407 } 401 }
408 402 this.disable_();
409 /** 403 this.uiState_ = PrintPreview.UiState.OPENING_NATIVE_PRINT_DIALOG;
410 * Creates an object based on the values in the printer settings. 404 this.nativeLayer_.startShowSystemDialog();
411 * 405 },
412 * @return {Object} Object containing print job settings. 406
413 */ 407 /**
414 function getSettings() { 408 * Window onload handler, sets up the page and starts print preview by
415 var deviceName = getSelectedPrinterName(); 409 * getting the printer list.
416 var printToPDF = deviceName == PRINT_TO_PDF; 410 * @private
417 var printWithCloudPrint = deviceName == PRINT_WITH_CLOUD_PRINT; 411 */
418 412 onWindowLoad_: function() {
419 var settings = 413 this.decorate($('print-preview'));
420 {'deviceName': deviceName, 414 i18nTemplate.process(document, templateData);
421 'pageRange': pageSettings.selectedPageRanges, 415 if (!this.previewArea_.hasCompatiblePlugin) {
422 'duplex': copiesSettings.duplexMode, 416 this.disable_();
423 'copies': copiesSettings.numberOfCopies, 417 }
424 'collate': copiesSettings.isCollated(), 418 this.nativeLayer_.startGetInitialSettings();
425 'landscape': layoutSettings.isLandscape(), 419 // TODO Remove me
426 'color': colorSettings.colorMode, 420 $('clear-log-button').onclick = function() {
427 'printToPDF': printToPDF, 421 $('log').innerHTML = '';
428 'printWithCloudPrint': printWithCloudPrint, 422 };
429 'isFirstRequest' : false, 423 },
430 'headerFooterEnabled': headerFooterSettings.hasHeaderFooter(), 424
431 'marginsType': marginSettings.selectedMarginsValue, 425 /**
432 'requestID': -1, 426 * Called when the native layer has initial settings to set. Sets the
433 'generateDraftData': generateDraftData, 427 * initial settings of the print preview and begins fetching print
434 'previewModifiable': previewModifiable}; 428 * destinations.
435 429 * @param {cr.Event} evt Contains the initial print preview
436 if (marginSettings.isCustomMarginsSelected()) 430 * settings persisted through the session.
437 settings['marginsCustom'] = marginSettings.customMargins; 431 * @private
438 432 */
439 var printerList = $('printer-list'); 433 onInitialSettingsSet_: function(evt) {
440 var selectedPrinter = printerList.selectedIndex; 434 if (this.uiState_ != PrintPreview.UiState.INITIALIZING) {
441 if (cloudprint.isCloudPrint(printerList.options[selectedPrinter])) { 435 throw Error(
442 settings['cloudPrintID'] = 436 'Updating initial settings when not in initializing state: ' +
443 printerList.options[selectedPrinter].value; 437 this.uiState_);
444 } 438 }
445 return settings; 439
446 } 440 var initialSettings = evt.initialSettings;
447 441
448 /** 442 // Not using initialSettings['initiatorTabTitle'] since the print preview
449 * Creates an object based on the values in the printer settings. 443 // no longer opens in a new tab. And because of this,
450 * Note: |lastPreviewRequestID| is being modified every time this function is 444 // localStrings.getStringF('printPreviewTitleFormat', initiatorTabTitle)
451 * called. Only call this function when a preview request is actually sent, 445 // is also not used.
452 * otherwise (for example when debugging) call getSettings(). 446
453 * 447 // TODO Move this parsing into NativeLayer.
454 * @return {Object} Object containing print job settings. 448
455 */ 449 // TODO use this boolean
456 function getSettingsWithRequestID() { 450 this.isInKioskAutoPrintMode_ =
457 var settings = getSettings(); 451 initialSettings['printAutomaticallyInKioskMode'];
458 settings.requestID = generatePreviewRequestID(); 452
459 settings.isFirstRequest = isFirstPreviewRequest(); 453 var customMargins = null;
460 return settings; 454 if (initialSettings.hasOwnProperty('marginTop') &&
461 } 455 initialSettings.hasOwnProperty('marginRight') &&
462 456 initialSettings.hasOwnProperty('marginBottom') &&
463 /** 457 initialSettings.hasOwnProperty('marginLeft')) {
464 * @return {number} The next unused preview request id. 458 customMargins = [
465 */ 459 initialSettings['marginTop'],
466 function generatePreviewRequestID() { 460 initialSettings['marginRight'],
467 return ++lastPreviewRequestID; 461 initialSettings['marginBottom'],
468 } 462 initialSettings['marginLeft']
469 463 ];
470 /** 464 }
471 * @return {boolean} True iff a preview has been requested. 465
472 */ 466 // TODO Use initialSettings['cloudPrintData'] somehow. Btw,
473 function hasRequestedPreview() { 467 // initialSettings['cloudPrintData'] is the JSON form of the cloud
474 return lastPreviewRequestID != initialPreviewRequestID; 468 // printer's capabilities.
475 } 469
476 470 this.printTicketStore_.initialize(
477 /** 471 initialSettings['previewModifiable'],
478 * @return {boolean} True if |lastPreviewRequestID| corresponds to the initial 472 initialSettings['duplex'],
479 * preview request. 473 initialSettings['headerFooterEnabled'],
480 */ 474 initialSettings['marginsType'],
481 function isFirstPreviewRequest() { 475 customMargins,
482 return lastPreviewRequestID == initialPreviewRequestID + 1; 476 initialSettings['numberFormat'],
483 } 477 initialSettings['measurementSystem']);
484 478
485 /** 479 this.destinationStore_.initialDestinationId =
486 * Checks if |previewResponseId| matches |lastPreviewRequestId|. Used to ignore 480 initialSettings['printerName'];
487 * obsolete preview data responses. 481
488 * @param {number} previewResponseId The id to check. 482 this.nativeLayer_.startGetLocalDestinations();
489 * @return {boolean} True if previewResponseId reffers to the expected response. 483 this.uiState_ = PrintPreview.UiState.FETCHING_DESTINATIONS;
490 */ 484 },
491 function isExpectedPreviewResponse(previewResponseId) { 485
492 return lastPreviewRequestID == previewResponseId; 486 /**
493 } 487 * Calls when the native layer enables Google Cloud Print integration.
494 488 * Fetches the user's cloud printers.
495 /** 489 * @param {cr.Event} evt Contains the base URL of the Google Cloud Print
496 * Returns the name of the selected printer or the empty string if no 490 * service.
497 * printer is selected. 491 * @private
498 * @return {string} The name of the currently selected printer. 492 */
499 */ 493 onCloudPrintEnable_: function(evt) {
500 function getSelectedPrinterName() { 494 if (this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
501 var printerList = $('printer-list'); 495 throw Error(
502 var selectedPrinter = printerList.selectedIndex; 496 'Enabling Google Cloud Print when not in fetching-destinations ' +
503 if (selectedPrinter < 0) 497 'state: ' + this.uiState_);
504 return ''; 498 }
505 return printerList.options[selectedPrinter].value; 499 this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface(
506 } 500 evt.baseCloudPrintUrl);
507 501 this.tracker.add(
508 /** 502 this.cloudPrintInterface_,
509 * Asks the browser to print the preview PDF based on current print 503 cloudprint.CloudPrintInterface.Event.SEARCH_DONE,
510 * settings. If the preview is still loading, printPendingFile() will get 504 this.onCloudPrintSearchDone_.bind(this));
511 * called once the preview loads. 505 this.tracker.add(
512 */ 506 this.cloudPrintInterface_,
513 function requestToPrintDocument() { 507 cloudprint.CloudPrintInterface.Event.PRINTER_DONE,
514 hasPendingPrintDocumentRequest = !isPrintReadyMetafileReady; 508 this.onCloudPrintPrinterDone_.bind(this));
515 var selectedPrinterName = getSelectedPrinterName(); 509 this.tracker.add(
516 var printToPDF = selectedPrinterName == PRINT_TO_PDF; 510 this.cloudPrintInterface_,
517 var printWithCloudPrint = selectedPrinterName == PRINT_WITH_CLOUD_PRINT; 511 cloudprint.CloudPrintInterface.Event.SUBMIT_DONE,
518 if (hasPendingPrintDocumentRequest) { 512 this.onCloudPrintSubmitDone_.bind(this));
519 if (previewAppRequested) { 513 this.tracker.add(
514 this.cloudPrintInterface_,
515 cloudprint.CloudPrintInterface.Event.ERROR,
516 this.onCloudPrintError_.bind(this));
517
518 var printWithCloudPrintDest =
519 this.createPrintWithCloudPrintDestination_();
520 this.destinationStore_.insertDestination(printWithCloudPrintDest);
521
522 if (cr.isChromeOS) {
523 // Fetch recent printers.
524 this.cloudPrintInterface_.search(true /*isRecent*/);
525
526 this.fetchState_ |=
527 PrintPreview.FetchState.RECENT_CLOUD_DESTINATIONS |
528 PrintPreview.FetchState.ALL_CLOUD_DESTINATIONS;
529 }
530 },
531
532 /**
533 * Called when the native layer gets local destinations. Adds local
534 * destination objects received from the operating system to the destination
535 * store.
536 * @param {cr.Event} Contains the local destinations to set.
537 * @private
538 */
539 onLocalDestinationsSet_: function(evt) {
540 if (this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
541 throw Error(
542 'Received local destinations when not in fetching-destinations ' +
543 'state: ' + this.uiState_);
544 }
545
546 var localDestinations = [];
547
548 // Add local destinations.
549 for (var destInfo, i = 0; destInfo = evt.destinationInfos[i]; i++) {
550 localDestinations.push(
551 print_preview.LocalDestinationParser.parse(destInfo));
552 }
553
554 // Add print-to-pdf destination.
555 localDestinations.push(this.createLocalPdfPrintDestination_());
556
557 this.destinationStore_.insertDestinations(localDestinations);
558
559 this.fetchState_ &= ~PrintPreview.FetchState.LOCAL_DESTINATIONS;
560 if (this.fetchState_ == PrintPreview.FetchState.READY) {
561 this.uiState_ = PrintPreview.UiState.READY;
562 }
563 },
564
565 /**
566 * Called when the native layer retrieves the capabilities for the selected
567 * local destination.
568 * @param {cr.Event} evt Contains the capabilities of the local print
569 * destination.
570 * @private
571 */
572 onLocalDestinationCapabilitiesSet_: function(evt) {
573 // TODO There may be a race condition here. This method is assumed to
574 // return capabilities for the currently selected printer. But between the
575 // time the local printer was selected and the capabilities were
576 // retrieved, the selected printer can change. One way to address this is
577 // to include the destination ID in the settingsInfo parameter.
578 // TODO Change data type of Destination.capabilities to
579 // ChromiumCapabilities.
580 var capabilities = print_preview.LocalCapabilitiesParser.parse(
581 evt.settingsInfo);
582 this.destinationStore_.selectedDestination.capabilities = capabilities;
583 this.printTicketStore_.updateDestinationCapabilities(capabilities);
584 },
585
586 /**
587 * Called from native layer after the user was requested to sign in, and did
588 * so successfully.
589 * @private
590 */
591 onDestinationsReload_: function() {
592 if (this.uiState_ != PrintPreview.UiState.READY) {
593 throw Error(
594 'Reload request received but not in ready state: ' + this.uiState_);
595 }
596 this.destinationStore_.clear();
597 this.nativeLayer_.startGetLocalDestinations();
598 if (this.cloudPrintInterface_) {
599 // Fetch recent printers.
600 this.cloudPrintInterface_.search(true /*isRecent*/);
601 // Fetch the full printer list.
602 this.cloudPrintInterface_.search(false /*isRecent*/);
603 }
604 this.uiState_ = PrintPreview.UiState.FETCHING_DESTINATIONS;
605 this.fetchState_ =
606 PrintPreview.FetchState.LOCAL_DESTINATIONS |
607 PrintPreview.FetchState.ALL_CLOUD_DESTINATIONS |
608 PrintPreview.FetchState.RECENT_CLOUD_DESTINATIONS;
609 },
610
611 /**
612 * Called from the native layer when ready to print to Google Cloud Print.
613 * @param {cr.Event} evt Contains the body to send in the HTTP request.
614 * @private
615 */
616 onPrintToCloud_: function(evt) {
617 if (this.uiState_ != PrintPreview.UiState.PRINTING) {
618 throw Error(
619 'Document ready to be sent to the cloud when not in printing ' +
620 'state: ' + this.uiState_);
621 }
622 if (this.cloudPrintInterface_) {
623 this.cloudPrintInterface_.submit(evt.data);
624 } else {
625 throw Error('Google Cloud Print is not enabled');
626 }
627 },
628
629 /**
630 * Called from the native layer when the user cancels the save-to-pdf file
631 * selection dialog.
632 * @private
633 */
634 onFileSelectionCancel_: function() {
635 if (this.uiState_ != PrintPreview.UiState.FILE_SELECTION) {
636 throw Error(
637 'File selection cancelled when not in file-selection state: ' +
638 this.uiState_);
639 }
640 // TODO Reenable controls.
641 this.uiState_ = PrintPreview.UiState.READY;
642 },
643
644 /**
645 * Called from the native layer when save-to-pdf file selection is complete.
646 * @private
647 */
648 onFileSelectionComplete_: function() {
649 this.disable_();
650 this.previewArea_.showCustomMessage(
651 localStrings.getString('printingToPDFInProgress'));
652 // TODO
653 },
654
655 /**
656 * Called when the Google Cloud Print search API call completes. Adds
657 * destinations to the printer store and selects one if it matches the
658 * initial destination.
659 * @param {cr.Event} evt Contains the new cloud destinations.
660 * @private
661 */
662 onCloudPrintSearchDone_: function(evt) {
663 this.destinationStore_.insertDestinations(evt.printers);
664
665 if (evt.isRecent) {
666 this.fetchState_ &= ~PrintPreview.FetchState.RECENT_CLOUD_DESTINATIONS;
667 } else {
668 this.fetchState_ &= ~PrintPreview.FetchState.ALL_CLOUD_DESTINATIONS;
669 }
670 if (this.fetchState_ == PrintPreview.FetchState.READY) {
671 this.uiState_ = PrintPreview.UiState.READY;
672 }
673 },
674
675 /**
676 * Called when the Google Cloud Print printer API call completes. Updates
677 * the UI with the newly received capabilities.
678 * @param {cr.Event} evt Contains the destination returned in the printer
679 * API call.
680 */
681 onCloudPrintPrinterDone_: function(evt) {
682 var dest = this.destinationStore_.updateDestination(evt.printer);
683 if (this.destinationStore_.selectedDestination == dest) {
684 this.printTicketStore_.updateDestinationCapabilities(dest.capabilities);
685 }
686 },
687
688 onCloudPrintSubmitDone_: function(evt) {
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} evt Contains the error message.
696 * @private
697 */
698 onCloudPrintError_: function(evt) {
699 this.printHeader_.setErrorMessage(evt.message);
700 this.fetchState_ &=
701 (~PrintPreview.FetchState.RECENT_CLOUD_DESTINATIONS &
702 ~PrintPreview.FetchState.ALL_CLOUD_DESTINATIONS);
703 if (this.fetchState_ == PrintPreview.FetchState.READY) {
704 this.uiState_ = PrintPreview.UiState.READY;
705 }
706 },
707
708 onCloudPrintSignInRequested_: function() {
709 this.nativeLayer_.startCloudPrintSignIn();
710 },
711
712 /**
713 * Called when a new destination has been selected. Fetches the
714 * destination's capability list.
715 * @private
716 */
717 onDestinationSelect_: function() {
718 var destination = this.destinationStore_.selectedDestination;
719
720 if (cr.isChromeOS && destination.isPrintWithCloudPrint) {
721 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
722 return;
723 }
724
725 // Fetch destination capabilities if necessary.
726 if (!destination.capabilities) {
727 if (destination.isLocal) {
728 this.nativeLayer_.startGetLocalDestinationCapabilities(
729 destination.id);
730 } else if (this.cloudPrintInterface_) {
731 this.cloudPrintInterface_.printer(destination.id);
732 } else {
733 // TODO Probably a cloud printer was initially selected, but cloud
734 // print is no longer available. Maybe default to the system's local
735 // default? What about Chrome OS?
736 throw Error(
737 'Selected destination is a cloud destination, but Google Cloud ' +
738 'Print is not enabled');
739 }
740 } else {
741 this.printTicketStore_.updateDestinationCapabilities(
742 destination.capabilities);
743 }
744 },
745
746 /**
747 * Called when the preview area's preview failed to load.
748 * @private
749 */
750 onPreviewGenerationFail_: function() {
751 if (this.uiState_ == PrintPreview.UiState.PRINTING) {
752 this.nativeLayer_.startCancelPendingPrint();
753 }
754 },
755
756 onSystemDialogLinkClicked_: function() {
757 $('system-dialog-throbber').hidden = false;
758 this.openSystemPrintDialog_();
759 },
760
761 /**
762 * Called when the 'Open pdf in preview' link is clicked. Launches the pdf
763 * preview app.
764 * @private
765 */
766 onOpenPdfInPreviewLinkClick_: function() {
767 if (this.uiState_ != PrintPreview.UiState.READY &&
768 this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
769 throw Error(
770 'Trying to open pdf in preview when not in ready nor ' +
771 'fetching-destinations state: ' + this.uiState_);
772 }
773 $('open-preview-app-throbber').hidden = false;
774 this.disable_();
520 previewArea.showCustomMessage( 775 previewArea.showCustomMessage(
521 localStrings.getString('openingPDFInPreview')); 776 localStrings.getString('openingPDFInPreview'));
522 } else if (printToPDF) { 777 this.uiState_ = PrintPreview.UiState.OPENING_PDF_PREVIEW;
523 sendPrintDocumentRequest(); 778 this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
524 } else if (printWithCloudPrint) { 779 },
525 previewArea.showCustomMessage( 780
526 localStrings.getString('printWithCloudPrintWait')); 781 /**
527 disableInputElementsInSidebar(); 782 * Called when the print header's print button is clicked. Prints the
528 } else { 783 * document.
529 isTabHidden = true; 784 * @private
530 chrome.send('hidePreview'); 785 */
786 onPrintButtonClick_: function() {
787 if (this.uiState_ != PrintPreview.UiState.READY &&
788 this.uiState_ != PrintPreview.UiState.FETCHING_DESTINATIONS) {
789 throw Error(
790 'Trying to print when not in ready nor fetching-destinations ' +
791 'state: ' + this.uiState_);
792 }
793 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
794 },
795
796 /**
797 * Called when the print header's cancel button is clicked. Closes the
798 * print dialog.
799 * @private
800 */
801 onCancelButtonClick_: function() {
802 this.close_();
803 },
804
805 /**
806 * Consume escape key presses and ctrl + shift + p. Delegate everything else
807 * to the preview area.
808 * @param {KeyboardEvent} e The keyboard event.
809 * @private
810 */
811 onKeyDown_: function(e) {
812 // Escape key closes the dialog.
813 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&
814 !e.metaKey) {
815 this.close_();
816 e.preventDefault();
817 return;
818 }
819
820 // Ctrl + Shift + p / Mac equivalent.
821 if (e.keyCode == 80) {
822 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
823 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
824 this.openSystemPrintDialog_();
825 e.preventDefault();
826 return;
827 }
828 }
829
830 // Pass certain directional keyboard events to the PDF viewer.
831 this.previewArea_.handleDirectionalKeyEvent(e);
832 },
833
834 /**
835 * Called when native layer receives invalid settings for a print request.
836 * @private
837 */
838 onSettingsInvalid_: function() {
839 // TODO UI state change
840 // if (cr.isMac) {
841 // if (previewAppRequested) {
842 // $('open-preview-app-throbber').hidden = true;
843 // this.previewArea_.clearCustomMessageWithDots();
844 // previewAppRequested = false;
845 // hasPendingPrintDocumentRequest = false;
846 // enableInputElementsInSidebar();
847 // }
848 // $('open-pdf-in-preview-link').disabled = true;
849 // }
850 this.previewArea_.showCustomMessage(
851 localStrings.getString('invalidPrinterSettings'));
852 },
853
854 onManagePrintersSelect_: function() {
855 if (cr.isChromeOS) {
856 this.nativeLayer_.startManageCloudPrinters();
857 } else {
858 this.nativeLayer_.startManageLocalPrinters();
859 }
531 } 860 }
532 return; 861 };
533 } 862
534 863 return {
535 if (printToPDF || previewAppRequested) { 864 PrintPreview: PrintPreview
536 sendPrintDocumentRequest(); 865 };
537 } else { 866 });
538 window.setTimeout(function() { sendPrintDocumentRequest(); }, 1000); 867
539 } 868 function log(message) {
869 $('log').appendChild(document.createTextNode(message));
870 $('log').appendChild(document.createElement('br'));
540 } 871 }
541 872
542 /** 873 // Pull in all other scripts in a single shot.
543 * Sends a message to cancel the pending print request. 874 <include src="native_layer.js"/>
544 */ 875 <include src="data/page_number_set.js"/>
545 function cancelPendingPrintRequest() { 876 <include src="data/destination.js"/>
546 if (isTabHidden) 877 <include src="data/local_parsers.js"/>
547 chrome.send('cancelPendingPrintRequest'); 878 <include src="data/cloud_parsers.js"/>
548 } 879 <include src="data/chromium_capabilities.js"/>
549 880 <include src="data/cloud_capabilities.js"/>
550 /** 881 <include src="data/destination_store.js"/>
551 * Sends a message to initiate print workflow. 882 <include src="data/margins.js"/>
552 */ 883 <include src="data/printable_area.js"/>
553 function sendPrintDocumentRequest() { 884 <include src="data/measurement_system.js"/>
554 var printerList = $('printer-list'); 885 <include src="data/print_ticket_store.js"/>
555 var printer = printerList[printerList.selectedIndex]; 886 <include src="data/coordinate2d.js"/>
556 chrome.send('saveLastPrinter', [printer.value, cloudprint.getData(printer)]); 887 <include src="data/size.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.displayErrorMessageWithButtonAndNotify(
803 localStrings.getString('previewFailed'),
804 localStrings.getString('launchNativeDialog'),
805 launchNativePrintDialog);
806 }
807
808 /**
809 * Display an error message when encountered invalid printer settings.
810 * Called from PrintPreviewMessageHandler::OnInvalidPrinterSettings().
811 */
812 function invalidPrinterSettings() {
813 if (cr.isMac) {
814 if (previewAppRequested) {
815 $('open-preview-app-throbber').hidden = true;
816 previewArea.clearCustomMessageWithDots();
817 previewAppRequested = false;
818 hasPendingPrintDocumentRequest = false;
819 enableInputElementsInSidebar();
820 }
821 $('open-pdf-in-preview-link').disabled = true;
822 }
823 previewArea.displayErrorMessageAndNotify(
824 localStrings.getString('invalidPrinterSettings'));
825 }
826
827 /**
828 * Called when the PDF plugin loads its document.
829 */
830 function onPDFLoad() {
831 if (previewModifiable) {
832 setPluginPreviewPageCount();
833 }
834 // Instruct the plugin which page numbers to display in the page number
835 // indicator.
836 previewArea.pdfPlugin.setPageNumbers(
837 JSON.stringify(pageSettings.selectedPagesSet));
838 cr.dispatchSimpleEvent(document, customEvents.PDF_LOADED);
839 isFirstPageLoaded = true;
840 checkAndHideOverlayLayerIfValid();
841 sendPrintDocumentRequestIfNeeded();
842 if (printAutomaticallyInKioskMode)
843 printHeader.printButton.click();
844 }
845
846 function setPluginPreviewPageCount() {
847 previewArea.pdfPlugin.printPreviewPageCount(
848 pageSettings.previouslySelectedPages.length);
849 }
850
851 /**
852 * Update the page count and check the page range.
853 * Called from PrintPreviewUI::OnDidGetPreviewPageCount().
854 * @param {number} pageCount The number of pages.
855 * @param {number} previewResponseId The preview request id that resulted in
856 * this response.
857 */
858 function onDidGetPreviewPageCount(pageCount, previewResponseId) {
859 if (!isExpectedPreviewResponse(previewResponseId))
860 return;
861 pageSettings.updateState(pageCount);
862 if (!previewModifiable && pageSettings.requestPrintPreviewIfNeeded())
863 return;
864
865 cr.dispatchSimpleEvent(document, customEvents.UPDATE_SUMMARY);
866 }
867
868 /**
869 * @param {{contentWidth: number, contentHeight: number, marginLeft: number,
870 * marginRight: number, marginTop: number, marginBottom: number,
871 * printableAreaX: number, printableAreaY: number,
872 * printableAreaWidth: number, printableAreaHeight: number}} pageLayout
873 * Specifies default page layout details in points.
874 * @param {boolean} hasCustomPageSizeStyle Indicates whether the previewed
875 * document has a custom page size style.
876 */
877 function onDidGetDefaultPageLayout(pageLayout, hasCustomPageSizeStyle) {
878 hasPageSizeStyle = hasCustomPageSizeStyle;
879 marginSettings.currentDefaultPageLayout = new print_preview.PageLayout(
880 pageLayout.contentWidth,
881 pageLayout.contentHeight,
882 pageLayout.marginLeft,
883 pageLayout.marginTop,
884 pageLayout.marginRight,
885 pageLayout.marginBottom);
886 headerFooterSettings.checkAndHideHeaderFooterOption(
887 pageLayout, marginSettings.selectedMarginsValue);
888 }
889
890 /**
891 * This function sends a request to hide the overlay layer only if there is no
892 * pending print document request and we are not waiting for the print ready
893 * metafile.
894 */
895 function checkAndHideOverlayLayerIfValid() {
896 var selectedPrinter = getSelectedPrinterName();
897 var printToDialog = selectedPrinter == PRINT_TO_PDF ||
898 selectedPrinter == PRINT_WITH_CLOUD_PRINT;
899 if ((printToDialog || !previewModifiable) &&
900 !isPrintReadyMetafileReady && hasPendingPrintDocumentRequest) {
901 return;
902 }
903 previewArea.hideOverlayLayer();
904 }
905
906 /**
907 * Called when no pipelining previewed pages.
908 * @param {string} previewUid Preview unique identifier.
909 * @param {number} previewResponseId The preview request id that resulted in
910 * this response.
911 */
912 function reloadPreviewPages(previewUid, previewResponseId) {
913 if (!isExpectedPreviewResponse(previewResponseId))
914 return;
915
916 cr.dispatchSimpleEvent(document, customEvents.UPDATE_PRINT_BUTTON);
917 checkAndHideOverlayLayerIfValid();
918 var pageSet = pageSettings.previouslySelectedPages;
919 for (var i = 0; i < pageSet.length; i++) {
920 previewArea.pdfPlugin.loadPreviewPage(
921 getPageSrcURL(previewUid, pageSet[i] - 1), i);
922 }
923
924 hasPendingPreviewRequest = false;
925 isPrintReadyMetafileReady = true;
926 previewArea.pdfLoaded = true;
927 sendPrintDocumentRequestIfNeeded();
928 }
929
930 /**
931 * Notification that a print preview page has been rendered.
932 * Check if the settings have changed and request a regeneration if needed.
933 * Called from PrintPreviewUI::OnDidPreviewPage().
934 * @param {number} pageNumber The page number, 0-based.
935 * @param {string} previewUid Preview unique identifier.
936 * @param {number} previewResponseId The preview request id that resulted in
937 * this response.
938 */
939 function onDidPreviewPage(pageNumber, previewUid, previewResponseId) {
940 if (!isExpectedPreviewResponse(previewResponseId))
941 return;
942
943 // Refactor
944 if (!previewModifiable)
945 return;
946
947 if (pageSettings.requestPrintPreviewIfNeeded())
948 return;
949
950 var pageIndex = pageSettings.previouslySelectedPages.indexOf(pageNumber + 1);
951 if (pageIndex == -1)
952 return;
953
954 currentPreviewUid = previewUid;
955 if (pageIndex == 0)
956 previewArea.createOrReloadPDFPlugin(pageNumber);
957
958 previewArea.pdfPlugin.loadPreviewPage(
959 getPageSrcURL(previewUid, pageNumber), pageIndex);
960
961 if (pageIndex + 1 == pageSettings.previouslySelectedPages.length) {
962 hasPendingPreviewRequest = false;
963 if (pageIndex != 0)
964 sendPrintDocumentRequestIfNeeded();
965 }
966 }
967
968 /**
969 * Update the print preview when new preview data is available.
970 * Create the PDF plugin as needed.
971 * Called from PrintPreviewUI::PreviewDataIsAvailable().
972 * @param {string} previewUid Preview unique identifier.
973 * @param {number} previewResponseId The preview request id that resulted in
974 * this response.
975 */
976 function updatePrintPreview(previewUid, previewResponseId) {
977 if (!isExpectedPreviewResponse(previewResponseId))
978 return;
979 isPrintReadyMetafileReady = true;
980
981 if (!previewModifiable) {
982 // If the preview is not modifiable the plugin has not been created yet.
983 currentPreviewUid = previewUid;
984 hasPendingPreviewRequest = false;
985 previewArea.createOrReloadPDFPlugin(PRINT_READY_DATA_INDEX);
986 }
987
988 cr.dispatchSimpleEvent(document, customEvents.UPDATE_PRINT_BUTTON);
989 if (previewModifiable)
990 sendPrintDocumentRequestIfNeeded();
991 }
992
993 /**
994 * Checks to see if the requested print data is available for printing and
995 * sends a print document request if needed.
996 */
997 function sendPrintDocumentRequestIfNeeded() {
998 if (!hasPendingPrintDocumentRequest || !isFirstPageLoaded)
999 return;
1000
1001 // If the selected printer is PRINT_TO_PDF or PRINT_WITH_CLOUD_PRINT or
1002 // the preview source is not modifiable, we need the print ready data for
1003 // printing. If the preview source is modifiable, we need to wait till all
1004 // the requested pages are loaded in the plugin for printing.
1005 var selectedPrinter = getSelectedPrinterName();
1006 var printToDialog = selectedPrinter == PRINT_TO_PDF ||
1007 selectedPrinter == PRINT_WITH_CLOUD_PRINT;
1008 if (((printToDialog || !previewModifiable) && !isPrintReadyMetafileReady) ||
1009 (previewModifiable && hasPendingPreviewRequest)) {
1010 return;
1011 }
1012
1013 hasPendingPrintDocumentRequest = false;
1014
1015 if (!areSettingsValid()) {
1016 cancelPendingPrintRequest();
1017 return;
1018 }
1019 sendPrintDocumentRequest();
1020 }
1021
1022 /**
1023 * Check if only page selection has been changed since the last preview request
1024 * and is valid.
1025 * @return {boolean} true if the new page selection is valid.
1026 */
1027 function hasOnlyPageSettingsChanged() {
1028 var tempPrintSettings = new PrintSettings();
1029 tempPrintSettings.save();
1030
1031 return !!(printSettings.deviceName == tempPrintSettings.deviceName &&
1032 printSettings.isLandscape == tempPrintSettings.isLandscape &&
1033 printSettings.hasHeaderFooter ==
1034 tempPrintSettings.hasHeaderFooter &&
1035 pageSettings.hasPageSelectionChangedAndIsValid());
1036 }
1037
1038 /**
1039 * Called either when there is a scroll event or when the plugin size changes.
1040 */
1041 function onPreviewPositionChanged() {
1042 marginSettings.onPreviewPositionChanged();
1043 }
1044
1045 /**
1046 * @return {boolean} true if a compatible pdf plugin exists.
1047 */
1048 function checkCompatiblePluginExists() {
1049 var dummyPlugin = $('dummy-viewer');
1050 var pluginInterface = [dummyPlugin.onload,
1051 dummyPlugin.goToPage,
1052 dummyPlugin.removePrintButton,
1053 dummyPlugin.loadPreviewPage,
1054 dummyPlugin.printPreviewPageCount,
1055 dummyPlugin.resetPrintPreviewUrl,
1056 dummyPlugin.onPluginSizeChanged,
1057 dummyPlugin.onScroll,
1058 dummyPlugin.pageXOffset,
1059 dummyPlugin.pageYOffset,
1060 dummyPlugin.setZoomLevel,
1061 dummyPlugin.setPageNumbers,
1062 dummyPlugin.setPageXOffset,
1063 dummyPlugin.setPageYOffset,
1064 dummyPlugin.getHorizontalScrollbarThickness,
1065 dummyPlugin.getVerticalScrollbarThickness,
1066 dummyPlugin.getPageLocationNormalized,
1067 dummyPlugin.getHeight,
1068 dummyPlugin.getWidth];
1069
1070 for (var i = 0; i < pluginInterface.length; i++) {
1071 if (!pluginInterface[i])
1072 return false;
1073 }
1074 return true;
1075 }
1076
1077 /**
1078 * Sets the default values and sends a request to regenerate preview data.
1079 * Resets the margin options only if |resetMargins| is true.
1080 * @param {boolean} resetMargins True if margin settings should be resetted.
1081 */
1082 function setDefaultValuesAndRegeneratePreview(resetMargins) {
1083 if (resetMargins)
1084 marginSettings.resetMarginsIfNeeded();
1085 pageSettings.resetState();
1086 requestPrintPreview();
1087 }
1088
1089 /**
1090 * Class that represents the state of the print settings.
1091 * @constructor
1092 */
1093 function PrintSettings() {
1094 this.deviceName = '';
1095 this.isLandscape = '';
1096 this.hasHeaderFooter = '';
1097 }
1098
1099 /**
1100 * Takes a snapshot of the print settings.
1101 */
1102 PrintSettings.prototype.save = function() {
1103 this.deviceName = getSelectedPrinterName();
1104 this.isLandscape = layoutSettings.isLandscape();
1105 this.hasHeaderFooter = headerFooterSettings.hasHeaderFooter();
1106 };
1107
1108 /**
1109 * Updates the title of the print preview tab according to |initiatorTabTitle|.
1110 * @param {string} initiatorTabTitle The title of the initiator tab.
1111 */
1112 function setInitiatorTabTitle(initiatorTabTitle) {
1113 if (initiatorTabTitle == '')
1114 return;
1115 document.title = localStrings.getStringF(
1116 'printPreviewTitleFormat', initiatorTabTitle);
1117 }
1118
1119 /**
1120 * Closes this print preview tab.
1121 */
1122 function closePrintPreviewTab() {
1123 window.removeEventListener('keydown', onKeyDown);
1124 chrome.send('closePrintPreviewTab');
1125 chrome.send('DialogClose');
1126 }
1127
1128 /**
1129 * Pass certain directional keyboard events to the PDF viewer.
1130 * @param {Event} e The keydown event.
1131 */
1132 function tryToHandleDirectionKeyDown(e) {
1133 // Make sure the PDF plugin is there.
1134 if (!previewArea.pdfPlugin)
1135 return;
1136
1137 // We only care about: PageUp, PageDown, Left, Up, Right, Down.
1138 if (!(e.keyCode == 33 || e.keyCode == 34 ||
1139 (e.keyCode >= 37 && e.keyCode <= 40))) {
1140 return;
1141 }
1142
1143 // If the user is holding a modifier key, ignore.
1144 if (e.metaKey || e.altKey || e.shiftKey || e.ctrlKey)
1145 return;
1146
1147 // Don't handle the key event for these elements.
1148 var tagName = document.activeElement.tagName;
1149 if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'EMBED')
1150 return;
1151
1152 // For the most part, if any div of header was the last clicked element,
1153 // then the active element is the body. Starting with the last clicked
1154 // element, and work up the DOM tree to see if any element has a scrollbar.
1155 // If there exists a scrollbar, do not handle the key event here.
1156 var element = document.activeElement;
1157 if (element == document.body) {
1158 if (lastClickedElement)
1159 element = lastClickedElement;
1160 while (element) {
1161 if (element.scrollHeight > element.clientHeight)
1162 return;
1163 element = element.parentElement;
1164 }
1165 }
1166
1167 // No scroll bar anywhere, or the active element is something else, like a
1168 // button. Note: buttons have a bigger scrollHeight than clientHeight.
1169 previewArea.pdfPlugin.sendKeyEvent(e.keyCode);
1170 e.preventDefault();
1171 }
1172
1173 /**
1174 * Handle keyboard events.
1175 * @param {KeyboardEvent} e The keyboard event.
1176 */
1177 function onKeyDown(e) {
1178 // Escape key closes the dialog.
1179 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
1180 printHeader.disableCancelButton();
1181 closePrintPreviewTab();
1182 e.preventDefault();
1183 }
1184 // Ctrl + Shift + p / Mac equivalent.
1185 if (e.keyCode == 80) {
1186 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
1187 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
1188 window.removeEventListener('keydown', onKeyDown);
1189 onSystemDialogLinkClicked();
1190 e.preventDefault();
1191 }
1192 }
1193
1194 tryToHandleDirectionKeyDown(e);
1195 }
1196
1197 window.addEventListener('DOMContentLoaded', onLoad);
1198 window.addEventListener('keydown', onKeyDown);
1199
1200 /// Pull in all other scripts in a single shot.
1201 <include src="print_preview_animations.js"/> 888 <include src="print_preview_animations.js"/>
1202 <include src="print_preview_cloud.js"/> 889 <include src="cloud_print_interface.js"/>
1203 <include src="print_preview_utils.js"/> 890 <include src="print_preview_utils.js"/>
1204 <include src="print_header.js"/> 891 <include src="print_header.js"/>
1205 <include src="page_settings.js"/> 892 <include src="settings/page_settings.js"/>
1206 <include src="copies_settings.js"/> 893 <include src="settings/copies_settings.js"/>
1207 <include src="header_footer_settings.js"/> 894 <include src="settings/header_footer_settings.js"/>
1208 <include src="layout_settings.js"/> 895 <include src="settings/layout_settings.js"/>
1209 <include src="color_settings.js"/> 896 <include src="settings/color_settings.js"/>
1210 <include src="margin_settings.js"/> 897 <include src="settings/margin_settings.js"/>
1211 <include src="margin_textbox.js"/> 898 <include src="settings/destination_settings.js"/>
1212 <include src="margin_utils.js"/> 899 <include src="previewarea/margin_utils.js"/>
1213 <include src="margins_ui.js"/> 900 <include src="previewarea/custom_margins.js"/>
1214 <include src="margins_ui_pair.js"/> 901 <include src="previewarea/margin_control.js"/>
1215 <include src="preview_area.js"/> 902 <include src="previewarea/preview_area.js"/>
903 <include src="preview_generator.js"/>
904
905 var printPreview = new print_preview.PrintPreview(nativeLayer);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698