// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var localStrings = new LocalStrings();
// The total page count of the previewed document regardless of which pages the
// user has selected.
var totalPageCount = -1;
// The previously selected pages by the user. It is used in
// onPageSelectionMayHaveChanged() to make sure that a new preview is not
// requested more often than necessary.
var previouslySelectedPages = [];
// The previously selected layout mode. It is used in order to prevent the
// preview from updating when the user clicks on the already selected layout
// mode.
var previouslySelectedLayout = null;
// Timer id of the page range textfield. It is used to reset the timer whenever
// needed.
var timerId;
// Store the last selected printer index.
var lastSelectedPrinterIndex = 0;
// Indicates whether a preview has been requested but not received yet.
var isPreviewStillLoading = true;
// Currently selected printer capabilities.
var printerCapabilities;
// Used to disable some printing options when the preview is not modifiable.
var previewModifiable = false;
// Destination list special value constants.
const PRINT_TO_PDF = 'Print To PDF';
const MANAGE_PRINTERS = 'Manage Printers';
/**
* Window onload handler, sets up the page and starts print preview by getting
* the printer list.
*/
function onLoad() {
$('system-dialog-link').addEventListener('click', showSystemDialog);
$('cancel-button').addEventListener('click', handleCancelButtonClick);
if (!checkCompatiblePluginExists()) {
displayErrorMessage(localStrings.getString('noPlugin'), false);
$('mainview').parentElement.removeChild($('dummy-viewer'));
return;
}
$('mainview').parentElement.removeChild($('dummy-viewer'));
$('printer-list').disabled = true;
$('print-button').disabled = true;
$('print-button').addEventListener('click', printFile);
$('all-pages').addEventListener('click', onPageSelectionMayHaveChanged);
$('copies').addEventListener('input', copiesFieldChanged);
$('print-pages').addEventListener('click', handleIndividualPagesCheckbox);
$('individual-pages').addEventListener('blur', function() {
clearTimeout(timerId);
onPageSelectionMayHaveChanged();
});
$('individual-pages').addEventListener('focus', addTimerToPageRangeField);
$('individual-pages').addEventListener('input', resetPageRangeFieldTimer);
$('two-sided').addEventListener('click', handleTwoSidedClick)
$('landscape').addEventListener('click', onLayoutModeToggle);
$('portrait').addEventListener('click', onLayoutModeToggle);
$('color').addEventListener('click', function() { setColor(true); });
$('bw').addEventListener('click', function() { setColor(false); });
$('printer-list').addEventListener(
'change', updateControlsWithSelectedPrinterCapabilities);
$('increment').addEventListener('click',
function() { onCopiesButtonsClicked(1); });
$('decrement').addEventListener('click',
function() { onCopiesButtonsClicked(-1); });
$('controls').onsubmit = function() { return false; };
$('dancing-dots').classList.remove('invisible');
chrome.send('getPrinters');
}
/**
* Asks the browser to close the preview tab.
*/
function handleCancelButtonClick() {
chrome.send('closePrintPreviewTab');
}
/**
* Asks the browser to show the native print dialog for printing.
*/
function showSystemDialog() {
chrome.send('showSystemDialog');
}
/**
* Disables the controls which need the initiator tab to generate preview
* data. This function is called when the initiator tab is closed.
* @param {string} initiatorTabURL The URL of the initiator tab.
*/
function onInitiatorTabClosed(initiatorTabURL) {
$('reopen-page').addEventListener('click', function() {
window.location = initiatorTabURL;
});
displayErrorMessage(localStrings.getString('initiatorTabClosed'), true);
}
/**
* Gets the selected printer capabilities and updates the controls accordingly.
*/
function updateControlsWithSelectedPrinterCapabilities() {
var printerList = $('printer-list');
var selectedIndex = printerList.selectedIndex;
if (selectedIndex < 0)
return;
var selectedValue = printerList.options[selectedIndex].value;
if (selectedValue == PRINT_TO_PDF) {
updateWithPrinterCapabilities({'disableColorOption': true,
'setColorAsDefault': true});
} else if (selectedValue == MANAGE_PRINTERS) {
printerList.selectedIndex = lastSelectedPrinterIndex;
chrome.send('managePrinters');
return;
} else {
// This message will call back to 'updateWithPrinterCapabilities'
// function.
chrome.send('getPrinterCapabilities', [selectedValue]);
}
lastSelectedPrinterIndex = selectedIndex;
// Regenerate the preview data based on selected printer settings.
setDefaultValuesAndRegeneratePreview();
}
/**
* Updates the controls with printer capabilities information.
* @param {Object} settingInfo printer setting information.
*/
function updateWithPrinterCapabilities(settingInfo) {
printerCapabilities = settingInfo;
if (isPreviewStillLoading)
return;
var disableColorOption = settingInfo.disableColorOption;
var setColorAsDefault = settingInfo.setColorAsDefault;
var colorOption = $('color');
var bwOption = $('bw');
if (disableColorOption)
$('color-options').classList.add("hidden");
else
$('color-options').classList.remove("hidden");
if (colorOption.checked != setColorAsDefault) {
colorOption.checked = setColorAsDefault;
bwOption.checked = !setColorAsDefault;
setColor(colorOption.checked);
}
}
/**
* Disables or enables all controls in the options pane except for the cancel
* button.
*/
function setControlsDisabled(disabled) {
var elementList = $('controls').elements;
for (var i = 0; i < elementList.length; ++i) {
if (elementList[i] == $('cancel-button'))
continue;
elementList[i].disabled = disabled;
}
}
/**
* Validates the copies text field value.
* NOTE: An empty copies field text is considered valid because the blur event
* listener of this field will set it back to a default value.
* @return {boolean} true if the number of copies is valid else returns false.
*/
function isNumberOfCopiesValid() {
var copiesFieldText = $('copies').value.replace(/\s/g, '');
if (copiesFieldText == '')
return true;
return (isInteger(copiesFieldText) && Number(copiesFieldText) > 0);
}
/**
* Returns true if |toTest| contains only digits. Leading and trailing
* whitespace is allowed.
* @param {string} toTest The string to be tested.
*/
function isInteger(toTest) {
var numericExp = /^\s*[0-9]+\s*$/;
return numericExp.test(toTest);
}
/**
* Parses the page ranges textfield and returns a suggestion.
* For example: '1-3,2,4,8,9-10,4,4' becomes '1-4, 8-10'. If it can't parse the
* whole string it will suggest only the part that was parsed.
* For example: '1-3,2,4,8,abcdef,9-10,4,4' becomes '1-4, 8-10'.
*/
function getPageRangesSuggestion() {
var pageRanges = getSelectedPageRanges();
var parsedPageRanges = '';
var individualPagesField = $('individual-pages');
for (var i = 0; i < pageRanges.length; ++i) {
if (pageRanges[i].from == pageRanges[i].to)
parsedPageRanges += pageRanges[i].from;
else
parsedPageRanges += pageRanges[i].from + '-' + pageRanges[i].to;
if (i < pageRanges.length - 1)
parsedPageRanges += ', ';
}
return parsedPageRanges;
}
/**
* Checks whether the preview layout setting is set to 'landscape' or not.
*
* @return {boolean} true if layout is 'landscape'.
*/
function isLandscape() {
return $('landscape').checked;
}
/**
* Checks whether the preview color setting is set to 'color' or not.
*
* @return {boolean} true if color is 'color'.
*/
function isColor() {
return $('color').checked;
}
/**
* Checks whether the preview collate setting value is set or not.
*
* @return {boolean} true if collate setting is enabled and checked.
*/
function isCollated() {
var collateField = $('collate');
return !collateField.disabled && collateField.checked;
}
/**
* Returns the number of copies currently indicated in the copies textfield. If
* the contents of the textfield can not be converted to a number or if <1 it
* returns 1.
*
* @return {number} number of copies.
*/
function getCopies() {
var copies = parseInt($('copies').value, 10);
if (!copies || copies <= 1)
copies = 1;
return copies;
}
/**
* Checks whether the preview two-sided checkbox is checked.
*
* @return {boolean} true if two-sided is checked.
*/
function isTwoSided() {
return $('two-sided').checked;
}
/**
* Gets the duplex mode for printing.
* @return {number} duplex mode.
*/
function getDuplexMode() {
// Constants values matches printing::DuplexMode enum.
const SIMPLEX = 0;
const LONG_EDGE = 1;
return !isTwoSided() ? SIMPLEX : LONG_EDGE;
}
/**
* Creates a JSON string based on the values in the printer settings.
*
* @return {string} JSON string with print job settings.
*/
function getSettingsJSON() {
var printerList = $('printer-list')
var selectedPrinter = printerList.selectedIndex;
var deviceName = '';
if (selectedPrinter >= 0)
deviceName = printerList.options[selectedPrinter].value;
var printAll = $('all-pages').checked;
var printToPDF = (deviceName == PRINT_TO_PDF);
return JSON.stringify({'deviceName': deviceName,
'pageRange': getSelectedPageRanges(),
'printAll': printAll,
'duplex': getDuplexMode(),
'copies': getCopies(),
'collate': isCollated(),
'landscape': isLandscape(),
'color': isColor(),
'printToPDF': printToPDF});
}
/**
* Asks the browser to print the preview PDF based on current print settings.
*/
function printFile() {
chrome.send('print', [getSettingsJSON()]);
}
/**
* Asks the browser to generate a preview PDF based on current print settings.
*/
function requestPrintPreview() {
isPreviewStillLoading = true;
setControlsDisabled(true);
$('dancing-dots').classList.remove('invisible');
chrome.send('getPreview', [getSettingsJSON()]);
}
/**
* Fill the printer list drop down.
* Called from PrintPreviewHandler::SendPrinterList().
* @param {Array} printers Array of printer info objects.
* @param {number} defaultPrinterIndex The index of the default printer.
*/
function setPrinters(printers, defaultPrinterIndex) {
var printerList = $('printer-list');
for (var i = 0; i < printers.length; ++i) {
addDestinationListOption(printers[i].printerName, printers[i].deviceName,
i == defaultPrinterIndex, false);
}
addDestinationListOption('','',false, true);
// Adding option for saving PDF to disk.
addDestinationListOption(localStrings.getString('printToPDF'),
PRINT_TO_PDF, false, false);
addDestinationListOption('','',false, true);
// Add an option to manage printers.
addDestinationListOption(localStrings.getString('managePrinters'),
MANAGE_PRINTERS, false, false);
printerList.disabled = false;
updateControlsWithSelectedPrinterCapabilities();
}
/**
* Adds an option to the printer destination list.
* @param {String} optionText specifies the option text content.
* @param {String} optionValue specifies the option value.
* @param {boolean} isDefault is true if the option needs to be selected.
* @param {boolean} isDisabled is true if the option needs to be disabled.
*/
function addDestinationListOption(optionText, optionValue, isDefault,
isDisabled) {
var option = document.createElement('option');
option.textContent = optionText;
option.value = optionValue;
$('printer-list').add(option);
option.selected = isDefault;
option.disabled = isDisabled;
}
/**
* Sets the color mode for the PDF plugin.
* Called from PrintPreviewHandler::ProcessColorSetting().
* @param {boolean} color is true if the PDF plugin should display in color.
*/
function setColor(color) {
var pdfViewer = $('pdf-viewer');
if (!pdfViewer) {
return;
}
pdfViewer.grayscale(!color);
}
/**
* Display an error message in the center of the preview area.
* @param {string} errorMessage The error message to be displayed.
* @param {boolean} showButton Indivates whether the "Reopen the page" button
* should be displayed.
*/
function displayErrorMessage(errorMessage, showButton) {
isPreviewStillLoading = false;
$('dancing-dots').classList.remove('invisible');
$('dancing-dots-text').classList.add('hidden');
$('error-text').innerHTML = errorMessage;
$('error-text').classList.remove('hidden');
if (showButton)
$('reopen-page').classList.remove('hidden');
else
$('reopen-page').classList.add('hidden');
setControlsDisabled(true);
var pdfViewer = $('pdf-viewer');
if (pdfViewer)
$('mainview').removeChild(pdfViewer);
}
/**
* Display an error message when print preview fails.
* Called from PrintPreviewMessageHandler::OnPrintPreviewFailed().
*/
function printPreviewFailed() {
displayErrorMessage(localStrings.getString('previewFailed'), false);
}
/**
* Called when the PDF plugin loads its document.
*/
function onPDFLoad() {
if (isLandscape())
$('pdf-viewer').fitToWidth();
else
$('pdf-viewer').fitToHeight();
$('dancing-dots').classList.add('invisible');
setControlsDisabled(false);
if (!previewModifiable) {
$('landscape').disabled = true;
$('portrait').disabled = true;
}
updateCopiesButtonsState();
updateWithPrinterCapabilities(printerCapabilities);
}
/**
* Update the print preview when new preview data is available.
* Create the PDF plugin as needed.
* Called from PrintPreviewUI::PreviewDataIsAvailable().
* @param {number} pageCount The expected total pages count.
* @param {string} jobTitle The print job title.
* @param {boolean} modifiable If the preview is modifiable.
*
*/
function updatePrintPreview(pageCount, jobTitle, modifiable) {
previewModifiable = modifiable;
if (totalPageCount == -1)
totalPageCount = pageCount;
if (previouslySelectedPages.length == 0)
for (var i = 0; i < totalPageCount; i++)
previouslySelectedPages.push(i+1);
if (previouslySelectedLayout == null)
previouslySelectedLayout = $('portrait');
// Update the current tab title.
document.title = localStrings.getStringF('printPreviewTitleFormat', jobTitle);
createPDFPlugin();
isPreviewStillLoading = false;
updatePrintSummary();
}
/**
* Create the PDF plugin or reload the existing one.
*/
function createPDFPlugin() {
// Enable the print button.
if (!$('printer-list').disabled) {
$('print-button').disabled = false;
}
var pdfViewer = $('pdf-viewer');
if (pdfViewer) {
// Older version of the PDF plugin may not have this method.
// TODO(thestig) Eventually remove this check.
if (pdfViewer.goToPage) {
// Need to call this before the reload(), where the plugin resets its
// internal page count.
pdfViewer.goToPage('0');
}
pdfViewer.reload();
pdfViewer.grayscale(!isColor());
return;
}
var pdfPlugin = document.createElement('embed');
pdfPlugin.setAttribute('id', 'pdf-viewer');
pdfPlugin.setAttribute('type', 'application/pdf');
pdfPlugin.setAttribute('src', 'chrome://print/print.pdf');
var mainView = $('mainview');
mainView.appendChild(pdfPlugin);
pdfPlugin.onload('onPDFLoad()');
// Older version of the PDF plugin may not have this method.
// TODO(thestig) Eventually remove this check.
if (pdfPlugin.removePrintButton) {
pdfPlugin.removePrintButton();
}
pdfPlugin.grayscale(true);
}
/**
* Returns true if a compatible pdf plugin exists, false if it doesn't.
*/
function checkCompatiblePluginExists() {
var dummyPlugin = $('dummy-viewer')
return !!dummyPlugin.onload;
}
/**
* Updates the state of print button depending on the user selection.
* The button is enabled only when the following conditions are true.
* 1) The selected page ranges are valid.
* 2) The number of copies is valid.
*/
function updatePrintButtonState() {
$('print-button').disabled = (!isNumberOfCopiesValid() ||
getSelectedPagesValidityLevel() != 1);
}
window.addEventListener('DOMContentLoaded', onLoad);
/**
* Listener function that executes whenever a change occurs in the 'copies'
* field.
*/
function copiesFieldChanged() {
updateCopiesButtonsState();
updatePrintButtonState();
$('collate-option').hidden = getCopies() <= 1;
updatePrintSummary();
}
/**
* Executes whenever a blur event occurs on the 'individual-pages'
* field or when the timer expires. It takes care of
* 1) showing/hiding warnings/suggestions
* 2) updating print button/summary
*/
function pageRangesFieldChanged() {
var currentlySelectedPages = getSelectedPagesSet();
var individualPagesField = $('individual-pages');
var individualPagesHint = $('individual-pages-hint');
var validityLevel = getSelectedPagesValidityLevel();
if (validityLevel == 1)
individualPagesField.classList.remove('invalid');
else
individualPagesField.classList.add('invalid');
if (individualPagesField.value.length == 0) {
hideInvalidHint(individualPagesHint);
} else if (currentlySelectedPages.length == 0) {
individualPagesHint.classList.remove('suggestion');
individualPagesHint.classList.add('invalid');
individualPagesHint.innerHTML =
localStrings.getStringF('pageRangeInstruction',
localStrings.getString(
'examplePageRangeText'));
showInvalidHint(individualPagesHint);
} else if (individualPagesField.value.replace(/\s*/g,'') !=
getPageRangesSuggestion().replace(/\s*/g,'')) {
individualPagesHint.innerHTML =
localStrings.getStringF('didYouMean', getPageRangesSuggestion());
individualPagesHint.classList.remove('invalid');
individualPagesHint.classList.add('suggestion');
showInvalidHint(individualPagesHint);
} else if (individualPagesField.value.replace(/\s*/g,'') ==
getPageRangesSuggestion().replace(/\s*/g,'')) {
hideInvalidHint(individualPagesHint);
}
resetPageRangeFieldTimer();
updatePrintButtonState();
updatePrintSummary();
}
/**
* Updates the state of the increment/decrement buttons based on the current
* 'copies' value.
*/
function updateCopiesButtonsState() {
var copiesField = $('copies');
if (!isNumberOfCopiesValid()) {
copiesField.classList.add('invalid');
$('increment').disabled = false;
$('decrement').disabled = false;
showInvalidHint($('copies-hint'));
}
else {
copiesField.classList.remove('invalid');
$('increment').disabled = (getCopies() == copiesField.max) ? true : false;
$('decrement').disabled = (getCopies() == copiesField.min) ? true : false;
hideInvalidHint($('copies-hint'));
}
}
/**
* Updates the print summary based on the currently selected user options.
*
*/
function updatePrintSummary() {
var copies = getCopies();
var printSummary = $('print-summary');
if (!isNumberOfCopiesValid()) {
printSummary.innerHTML = localStrings.getString('invalidNumberOfCopies');
return;
}
if (getSelectedPagesValidityLevel() != 1) {
printSummary.innerHTML = localStrings.getString('invalidPageRange');
return;
}
var pageList = getSelectedPagesSet();
var numOfSheets = pageList.length;
var sheetsLabel = localStrings.getString('printPreviewSheetsLabelSingular');
var numOfPagesText = '';
var pagesLabel = '';
if (isTwoSided())
numOfSheets = Math.ceil(numOfSheets / 2);
numOfSheets *= copies;
if (numOfSheets > 1)
sheetsLabel = localStrings.getString('printPreviewSheetsLabelPlural');
var html = '';
if (pageList.length * copies != numOfSheets) {
numOfPagesText = pageList.length * copies;
pagesLabel = localStrings.getString('printPreviewPageLabelPlural');
html = localStrings.getStringF('printPreviewSummaryFormatLong',
'' + numOfSheets + '',
'' + sheetsLabel + '',
numOfPagesText, pagesLabel);
} else
html = localStrings.getStringF('printPreviewSummaryFormatShort',
'' + numOfSheets + '',
'' + sheetsLabel + '');
// Removing extra spaces from within the string.
html = html.replace(/\s{2,}/g, ' ');
printSummary.innerHTML = html;
}
/**
* Handles a click event on the two-sided option.
*/
function handleTwoSidedClick() {
updatePrintSummary();
}
/**
* Gives focus to the individual pages textfield when 'print-pages' textbox is
* clicked.
*/
function handleIndividualPagesCheckbox() {
$('individual-pages').focus();
}
/**
* When the user switches printing orientation mode the page field selection is
* reset to "all pages selected". After the change the number of pages will be
* different and currently selected page numbers might no longer be valid.
* Even if they are still valid the content of these pages will be different.
*/
function onLayoutModeToggle() {
var currentlySelectedLayout = $('portrait').checked ? $('portrait') :
$('landscape');
// If the chosen layout is same as before, nothing needs to be done.
if (previouslySelectedLayout == currentlySelectedLayout)
return;
previouslySelectedLayout = currentlySelectedLayout;
$('individual-pages').classList.remove('invalid');
setDefaultValuesAndRegeneratePreview();
}
/**
* Sets the default values and sends a request to regenerate preview data.
*/
function setDefaultValuesAndRegeneratePreview() {
$('individual-pages').value = '';
hideInvalidHint($('individual-pages-hint'));
$('all-pages').checked = true;
totalPageCount = -1;
previouslySelectedPages.length = 0;
requestPrintPreview();
}
/**
* Returns a list of all pages in the specified ranges. The pages are listed in
* the order they appear in the 'individual-pages' textbox and duplicates are
* not eliminated. If the page ranges can't be parsed an empty list is
* returned.
*
* @return {Array}
*/
function getSelectedPages() {
var pageText = $('individual-pages').value;
if ($('all-pages').checked || pageText.length == 0)
pageText = '1-' + totalPageCount;
var pageList = [];
var parts = pageText.split(/,/);
for (var i = 0; i < parts.length; ++i) {
var part = parts[i];
var match = part.match(/^\s*([0-9]+)\s*-\s*([0-9]+)\s*$/);
if (match && match[1] && match[2]) {
var from = parseInt(match[1], 10);
var to = parseInt(match[2], 10);
if (from && to) {
for (var j = from; j <= to; ++j)
if (j <= totalPageCount)
pageList.push(j);
}
} else {
var singlePageNumber = parseInt(part, 10);
if (singlePageNumber && singlePageNumber > 0 &&
singlePageNumber <= totalPageCount) {
pageList.push(parseInt(part, 10));
}
}
}
return pageList;
}
/**
* Checks the 'individual-pages' field and returns -1 if nothing is valid, 0 if
* it is partially valid, 1 if it is completely valid.
* Note: This function is stricter than getSelectedPages(), in other words this
* could return -1 and getSelectedPages() might still extract some pages.
*/
function getSelectedPagesValidityLevel() {
var pageText = $('individual-pages').value;
if ($('all-pages').checked || pageText.length == 0)
return 1;
var successfullyParsed = 0;
var failedToParse = 0;
var parts = pageText.split(/,/);
for (var i = 0; i < parts.length; ++i) {
var part = parts[i].replace(/\s*/g, '');
if (part.length == 0)
continue;
var match = part.match(/^([0-9]+)-([0-9]+)$/);
if (match && match[1] && match[2]) {
var from = parseInt(match[1], 10);
var to = parseInt(match[2], 10);
if (from && to && from < to && to <= totalPageCount)
successfullyParsed += 1;
else
failedToParse += 1;
} else if (isInteger(part) && parseInt(part, 10) <= totalPageCount)
successfullyParsed += 1;
else
failedToParse += 1;
}
if (successfullyParsed > 0 && failedToParse == 0)
return 1;
else if (successfullyParsed > 0 && failedToParse > 0)
return 0;
else
return -1;
}
function isSelectedPagesFieldValid() {
return (getSelectedPages().length != 0)
}
/**
* Parses the selected page ranges, processes them and returns the results.
* It squashes whenever possible. Example '1-2,3,5-7' becomes 1-3,5-7
*
* @return {Array} an array of page range objects. A page range object has
* fields 'from' and 'to'.
*/
function getSelectedPageRanges() {
var pageList = getSelectedPagesSet();
var pageRanges = [];
for (var i = 0; i < pageList.length; ++i) {
tempFrom = pageList[i];
while (i + 1 < pageList.length && pageList[i + 1] == pageList[i] + 1)
++i;
tempTo = pageList[i];
pageRanges.push({'from': tempFrom, 'to': tempTo});
}
return pageRanges;
}
/**
* Returns the selected pages in ascending order without any duplicates.
*/
function getSelectedPagesSet() {
var pageList = getSelectedPages();
pageList.sort(function(a,b) { return a - b; });
pageList = removeDuplicates(pageList);
return pageList;
}
/**
* Removes duplicate elements from |inArray| and returns a new array.
* |inArray| is not affected. It assumes that the array is already sorted.
*
* @param {Array} inArray The array to be processed.
*/
function removeDuplicates(inArray) {
var out = [];
if(inArray.length == 0)
return out;
out.push(inArray[0]);
for (var i = 1; i < inArray.length; ++i)
if(inArray[i] != inArray[i - 1])
out.push(inArray[i]);
return out;
}
/**
* Whenever the page range textfield gains focus we add a timer to detect when
* the user stops typing in order to update the print preview.
*/
function addTimerToPageRangeField() {
timerId = window.setTimeout(onPageSelectionMayHaveChanged, 1000);
}
/**
* As the user types in the page range textfield, we need to reset this timer,
* since the page ranges are still being edited.
*/
function resetPageRangeFieldTimer() {
clearTimeout(timerId);
addTimerToPageRangeField();
}
/**
* When the user stops typing in the page range textfield or clicks on the
* 'all-pages' checkbox, a new print preview is requested, only if
* 1) The input is compeletely valid (it can be parsed in its entirety).
* 2) The newly selected pages differ from the previously selected.
*/
function onPageSelectionMayHaveChanged() {
if ($('print-pages').checked)
pageRangesFieldChanged();
var validityLevel = getSelectedPagesValidityLevel();
var currentlySelectedPages = getSelectedPagesSet();
// Toggling between "all pages"/"some pages" radio buttons while having an
// invalid entry in the page selection textfield still requires updating the
// print summary and print button.
if (validityLevel < 1 ||
areArraysEqual(previouslySelectedPages, currentlySelectedPages)) {
updatePrintButtonState();
updatePrintSummary();
return;
}
previouslySelectedPages = currentlySelectedPages;
requestPrintPreview();
}
/**
* Returns true if the contents of the two arrays are equal.
*/
function areArraysEqual(array1, array2) {
if (array1.length != array2.length)
return false;
for (var i = 0; i < array1.length; i++)
if(array1[i] != array2[i])
return false;
return true;
}
/**
* Executed when the 'increment' or 'decrement' button is clicked.
*/
function onCopiesButtonsClicked(sign) {
var copiesField = $('copies');
if (!isNumberOfCopiesValid())
copiesField.value = 1;
else {
var newValue = getCopies() + sign * 1;
if (newValue < copiesField.min || newValue > copiesField.max)
return;
copiesField.value = newValue;
}
copiesFieldChanged();
}