| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 var localStrings = new LocalStrings(); | 5 var localStrings = new LocalStrings(); |
| 6 | 6 |
| 7 // The total page count of the previewed document regardless of which pages the | 7 // The total page count of the previewed document regardless of which pages the |
| 8 // user has selected. | 8 // user has selected. |
| 9 var totalPageCount = -1; | 9 var totalPageCount = -1; |
| 10 | 10 |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 | 255 |
| 256 /** | 256 /** |
| 257 * Validates the copies text field value. | 257 * Validates the copies text field value. |
| 258 * NOTE: An empty copies field text is considered valid because the blur event | 258 * NOTE: An empty copies field text is considered valid because the blur event |
| 259 * listener of this field will set it back to a default value. | 259 * listener of this field will set it back to a default value. |
| 260 * @return {boolean} true if the number of copies is valid else returns false. | 260 * @return {boolean} true if the number of copies is valid else returns false. |
| 261 */ | 261 */ |
| 262 function isNumberOfCopiesValid() { | 262 function isNumberOfCopiesValid() { |
| 263 var copiesFieldText = $('copies').value.replace(/\s/g, ''); | 263 var copiesFieldText = $('copies').value; |
| 264 if (copiesFieldText == '') | 264 return copiesFieldText == '' ? true : isPositiveInteger(copiesFieldText); |
| 265 return true; | |
| 266 | |
| 267 return (isInteger(copiesFieldText) && Number(copiesFieldText) > 0); | |
| 268 } | 265 } |
| 269 | 266 |
| 270 /** | 267 /** |
| 271 * Returns true if |toTest| contains only digits. Leading and trailing | |
| 272 * whitespace is allowed. | |
| 273 * @param {string} toTest The string to be tested. | |
| 274 */ | |
| 275 function isInteger(toTest) { | |
| 276 var numericExp = /^\s*[0-9]+\s*$/; | |
| 277 return numericExp.test(toTest); | |
| 278 } | |
| 279 | |
| 280 /** | |
| 281 * Checks whether the preview layout setting is set to 'landscape' or not. | 268 * Checks whether the preview layout setting is set to 'landscape' or not. |
| 282 * | 269 * |
| 283 * @return {boolean} true if layout is 'landscape'. | 270 * @return {boolean} true if layout is 'landscape'. |
| 284 */ | 271 */ |
| 285 function isLandscape() { | 272 function isLandscape() { |
| 286 return $('landscape').checked; | 273 return $('landscape').checked; |
| 287 } | 274 } |
| 288 | 275 |
| 289 /** | 276 /** |
| 290 * Checks whether the preview color setting is set to 'color' or not. | 277 * Checks whether the preview color setting is set to 'color' or not. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 /** | 328 /** |
| 342 * Creates a JSON string based on the values in the printer settings. | 329 * Creates a JSON string based on the values in the printer settings. |
| 343 * | 330 * |
| 344 * @return {string} JSON string with print job settings. | 331 * @return {string} JSON string with print job settings. |
| 345 */ | 332 */ |
| 346 function getSettingsJSON() { | 333 function getSettingsJSON() { |
| 347 var printAll = $('all-pages').checked; | 334 var printAll = $('all-pages').checked; |
| 348 var deviceName = getSelectedPrinterName(); | 335 var deviceName = getSelectedPrinterName(); |
| 349 var printToPDF = (deviceName == PRINT_TO_PDF); | 336 var printToPDF = (deviceName == PRINT_TO_PDF); |
| 350 | 337 |
| 351 return JSON.stringify({'deviceName': deviceName, | 338 return JSON.stringify( |
| 352 'pageRange': getSelectedPageRanges(), | 339 {'deviceName': deviceName, |
| 353 'printAll': printAll, | 340 'pageRange': pageSetToPageRanges(getSelectedPagesSet()), |
| 354 'duplex': getDuplexMode(), | 341 'printAll': printAll, |
| 355 'copies': getCopies(), | 342 'duplex': getDuplexMode(), |
| 356 'collate': isCollated(), | 343 'copies': getCopies(), |
| 357 'landscape': isLandscape(), | 344 'collate': isCollated(), |
| 358 'color': isColor(), | 345 'landscape': isLandscape(), |
| 359 'printToPDF': printToPDF}); | 346 'color': isColor(), |
| 347 'printToPDF': printToPDF}); |
| 360 } | 348 } |
| 361 | 349 |
| 362 /** | 350 /** |
| 363 * Returns the name of the selected printer or the empty string if no | 351 * Returns the name of the selected printer or the empty string if no |
| 364 * printer is selected. | 352 * printer is selected. |
| 365 */ | 353 */ |
| 366 function getSelectedPrinterName() { | 354 function getSelectedPrinterName() { |
| 367 var printerList = $('printer-list') | 355 var printerList = $('printer-list') |
| 368 var selectedPrinter = printerList.selectedIndex; | 356 var selectedPrinter = printerList.selectedIndex; |
| 369 var deviceName = ''; | 357 var deviceName = ''; |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 if (hasPendingPrintFileRequest) | 616 if (hasPendingPrintFileRequest) |
| 629 printFile(); | 617 printFile(); |
| 630 } | 618 } |
| 631 | 619 |
| 632 /** | 620 /** |
| 633 * Create the PDF plugin or reload the existing one. | 621 * Create the PDF plugin or reload the existing one. |
| 634 * @param {string} previewUid Preview unique identifier. | 622 * @param {string} previewUid Preview unique identifier. |
| 635 */ | 623 */ |
| 636 function createPDFPlugin(previewUid) { | 624 function createPDFPlugin(previewUid) { |
| 637 // Enable the print button. | 625 // Enable the print button. |
| 638 if (!$('printer-list').disabled) { | 626 if (!$('printer-list').disabled) |
| 639 $('print-button').disabled = false; | 627 $('print-button').disabled = false; |
| 640 } | |
| 641 | 628 |
| 642 var pdfViewer = $('pdf-viewer'); | 629 var pdfViewer = $('pdf-viewer'); |
| 643 if (pdfViewer) { | 630 if (pdfViewer) { |
| 644 // Need to call this before the reload(), where the plugin resets its | 631 // Need to call this before the reload(), where the plugin resets its |
| 645 // internal page count. | 632 // internal page count. |
| 646 pdfViewer.goToPage('0'); | 633 pdfViewer.goToPage('0'); |
| 647 | 634 |
| 648 pdfViewer.reload(); | 635 pdfViewer.reload(); |
| 649 pdfViewer.grayscale(!isColor()); | 636 pdfViewer.grayscale(!isColor()); |
| 650 return; | 637 return; |
| 651 } | 638 } |
| 652 | 639 |
| 653 var pdfPlugin = document.createElement('embed'); | 640 pdfViewer = document.createElement('embed'); |
| 654 pdfPlugin.setAttribute('id', 'pdf-viewer'); | 641 pdfViewer.setAttribute('id', 'pdf-viewer'); |
| 655 pdfPlugin.setAttribute('type', 'application/pdf'); | 642 pdfViewer.setAttribute('type', 'application/pdf'); |
| 656 pdfPlugin.setAttribute('src', 'chrome://print/' + previewUid + '/print.pdf'); | 643 pdfViewer.setAttribute('src', 'chrome://print/' + previewUid + '/print.pdf'); |
| 657 var mainView = $('mainview'); | 644 $('mainview').appendChild(pdfViewer); |
| 658 mainView.appendChild(pdfPlugin); | 645 pdfViewer.onload('onPDFLoad()'); |
| 659 pdfPlugin.onload('onPDFLoad()'); | 646 pdfViewer.removePrintButton(); |
| 660 pdfPlugin.removePrintButton(); | 647 pdfViewer.grayscale(true); |
| 661 pdfPlugin.grayscale(true); | |
| 662 } | 648 } |
| 663 | 649 |
| 664 /** | 650 /** |
| 665 * Returns true if a compatible pdf plugin exists, false if it doesn't. | 651 * Returns true if a compatible pdf plugin exists, false if it doesn't. |
| 666 */ | 652 */ |
| 667 function checkCompatiblePluginExists() { | 653 function checkCompatiblePluginExists() { |
| 668 var dummyPlugin = $('dummy-viewer') | 654 var dummyPlugin = $('dummy-viewer') |
| 669 return (dummyPlugin.onload && | 655 return (dummyPlugin.onload && |
| 670 dummyPlugin.goToPage && | 656 dummyPlugin.goToPage && |
| 671 dummyPlugin.removePrintButton); | 657 dummyPlugin.removePrintButton); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 if (!printToPDF && !isNumberOfCopiesValid()) { | 750 if (!printToPDF && !isNumberOfCopiesValid()) { |
| 765 printSummary.innerHTML = localStrings.getString('invalidNumberOfCopies'); | 751 printSummary.innerHTML = localStrings.getString('invalidNumberOfCopies'); |
| 766 return; | 752 return; |
| 767 } | 753 } |
| 768 | 754 |
| 769 if (!isSelectedPagesValid()) { | 755 if (!isSelectedPagesValid()) { |
| 770 printSummary.innerHTML = ''; | 756 printSummary.innerHTML = ''; |
| 771 return; | 757 return; |
| 772 } | 758 } |
| 773 | 759 |
| 774 var pageList = getSelectedPagesSet(); | 760 var pageSet = getSelectedPagesSet(); |
| 775 var numOfSheets = pageList.length; | 761 var numOfSheets = pageSet.length; |
| 776 var sheetsLabel = localStrings.getString('printPreviewSheetsLabelSingular'); | 762 var sheetsLabel = localStrings.getString('printPreviewSheetsLabelSingular'); |
| 777 var numOfPagesText = ''; | 763 var numOfPagesText = ''; |
| 778 var pagesLabel = ''; | 764 var pagesLabel = ''; |
| 779 | 765 |
| 780 if (!printToPDF && isTwoSided()) | 766 if (!printToPDF && isTwoSided()) |
| 781 numOfSheets = Math.ceil(numOfSheets / 2); | 767 numOfSheets = Math.ceil(numOfSheets / 2); |
| 782 numOfSheets *= copies; | 768 numOfSheets *= copies; |
| 783 | 769 |
| 784 if (numOfSheets > 1) | 770 if (numOfSheets > 1) |
| 785 sheetsLabel = localStrings.getString('printPreviewSheetsLabelPlural'); | 771 sheetsLabel = localStrings.getString('printPreviewSheetsLabelPlural'); |
| 786 | 772 |
| 787 var html = ''; | 773 var html = ''; |
| 788 if (pageList.length * copies != numOfSheets) { | 774 if (pageSet.length * copies != numOfSheets) { |
| 789 numOfPagesText = pageList.length * copies; | 775 numOfPagesText = pageSet.length * copies; |
| 790 pagesLabel = localStrings.getString('printPreviewPageLabelPlural'); | 776 pagesLabel = localStrings.getString('printPreviewPageLabelPlural'); |
| 791 html = localStrings.getStringF('printPreviewSummaryFormatLong', | 777 html = localStrings.getStringF('printPreviewSummaryFormatLong', |
| 792 '<b>' + numOfSheets + '</b>', | 778 '<b>' + numOfSheets + '</b>', |
| 793 '<b>' + sheetsLabel + '</b>', | 779 '<b>' + sheetsLabel + '</b>', |
| 794 numOfPagesText, pagesLabel); | 780 numOfPagesText, pagesLabel); |
| 795 } else | 781 } else |
| 796 html = localStrings.getStringF('printPreviewSummaryFormatShort', | 782 html = localStrings.getStringF('printPreviewSummaryFormatShort', |
| 797 '<b>' + numOfSheets + '</b>', | 783 '<b>' + numOfSheets + '</b>', |
| 798 '<b>' + sheetsLabel + '</b>'); | 784 '<b>' + sheetsLabel + '</b>'); |
| 799 | 785 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 * Sets the default values and sends a request to regenerate preview data. | 822 * Sets the default values and sends a request to regenerate preview data. |
| 837 */ | 823 */ |
| 838 function setDefaultValuesAndRegeneratePreview() { | 824 function setDefaultValuesAndRegeneratePreview() { |
| 839 fadeOutElement($('individual-pages-hint')); | 825 fadeOutElement($('individual-pages-hint')); |
| 840 totalPageCount = -1; | 826 totalPageCount = -1; |
| 841 previouslySelectedPages.length = 0; | 827 previouslySelectedPages.length = 0; |
| 842 requestPrintPreview(); | 828 requestPrintPreview(); |
| 843 } | 829 } |
| 844 | 830 |
| 845 /** | 831 /** |
| 846 * Returns a list of all pages in the specified ranges. The pages are listed in | 832 * Returns the selected pages in ascending order without any duplicates. |
| 847 * the order they appear in the 'individual-pages' textbox and duplicates are | |
| 848 * not eliminated. If the page ranges can't be parsed an empty list is | |
| 849 * returned. | |
| 850 * | 833 * |
| 851 * @return {Array} | 834 * @return {Array} |
| 852 */ | 835 */ |
| 853 function getSelectedPages() { | 836 function getSelectedPagesSet() { |
| 854 var pageText = $('individual-pages').value; | 837 var pageRangeText = $('individual-pages').value; |
| 855 | 838 |
| 856 if ($('all-pages').checked || pageText.length == 0) | 839 if ($('all-pages').checked || pageRangeText.length == 0) |
| 857 pageText = '1-' + totalPageCount; | 840 pageRangeText = '1-' + totalPageCount; |
| 858 | 841 |
| 859 var pageList = []; | 842 var pageList = pageRangeTextToPageList(pageRangeText, totalPageCount); |
| 860 var parts = pageText.split(/,/); | 843 return pageListToPageSet(pageList); |
| 861 | |
| 862 for (var i = 0; i < parts.length; ++i) { | |
| 863 var part = parts[i]; | |
| 864 var match = part.match(/^\s*([0-9]+)\s*-\s*([0-9]*)\s*$/); | |
| 865 | |
| 866 if (match && match[1]) { | |
| 867 var from = parseInt(match[1], 10); | |
| 868 var to = match[2] ? parseInt(match[2], 10) : totalPageCount; | |
| 869 | |
| 870 if (from && to) { | |
| 871 for (var j = from; j <= to; ++j) | |
| 872 if (j <= totalPageCount) | |
| 873 pageList.push(j); | |
| 874 } | |
| 875 } else { | |
| 876 var singlePageNumber = parseInt(part, 10); | |
| 877 if (singlePageNumber && singlePageNumber > 0 && | |
| 878 singlePageNumber <= totalPageCount) { | |
| 879 pageList.push(parseInt(part, 10)); | |
| 880 } | |
| 881 } | |
| 882 } | |
| 883 return pageList; | |
| 884 } | 844 } |
| 885 | 845 |
| 886 /** | 846 /** |
| 887 * Validates the 'individual-pages' text field value. | 847 * Validates the 'individual-pages' text field value. |
| 888 * | 848 * |
| 889 * @return {boolean} true if the text is valid. | 849 * @return {boolean} true if the text is valid. |
| 890 */ | 850 */ |
| 891 function isSelectedPagesValid() { | 851 function isSelectedPagesValid() { |
| 892 var pageText = $('individual-pages').value; | 852 var pageRangeText = $('individual-pages').value; |
| 893 | 853 |
| 894 if ($('all-pages').checked || pageText.length == 0) | 854 if ($('all-pages').checked || pageRangeText.length == 0) |
| 895 return true; | 855 return true; |
| 896 | 856 |
| 897 var successfullyParsed = 0; | 857 return isPageRangeTextValid(pageRangeText, totalPageCount); |
| 898 var parts = pageText.split(/,/); | |
| 899 | |
| 900 for (var i = 0; i < parts.length; ++i) { | |
| 901 var part = parts[i].replace(/\s*/g, ''); | |
| 902 if (part.length == 0) | |
| 903 continue; | |
| 904 | |
| 905 var match = part.match(/^([0-9]+)-([0-9]*)$/); | |
| 906 if (match && isValidNonZeroPositiveInteger(match[1])) { | |
| 907 if (!match[2] && totalPageCount == -1) { | |
| 908 successfullyParsed += 1; | |
| 909 continue; | |
| 910 } | |
| 911 var from = parseInt(match[1], 10); | |
| 912 var to = match[2] ? parseInt(match[2], 10) : totalPageCount; | |
| 913 | |
| 914 if (!to || from > to) | |
| 915 return false; | |
| 916 } else if (!isValidNonZeroPositiveInteger(part) || (totalPageCount != -1 && | |
| 917 !(parseInt(part, 10) <= totalPageCount))) { | |
| 918 return false; | |
| 919 } | |
| 920 successfullyParsed += 1; | |
| 921 } | |
| 922 return successfullyParsed > 0 | |
| 923 } | 858 } |
| 924 | 859 |
| 925 /** | 860 /** |
| 926 * Returns true if |value| is a valid non zero positive integer. | |
| 927 * @param {string} value The string to be tested. | |
| 928 */ | |
| 929 function isValidNonZeroPositiveInteger(value) { | |
| 930 return isInteger(value) && parseInt(value, 10) > 0; | |
| 931 } | |
| 932 | |
| 933 /** | |
| 934 * Parses the selected page ranges, processes them and returns the results. | |
| 935 * It squashes whenever possible. Example '1-2,3,5-7' becomes 1-3,5-7 | |
| 936 * | |
| 937 * @return {Array} an array of page range objects. A page range object has | |
| 938 * fields 'from' and 'to'. | |
| 939 */ | |
| 940 function getSelectedPageRanges() { | |
| 941 var pageList = getSelectedPagesSet(); | |
| 942 var pageRanges = []; | |
| 943 for (var i = 0; i < pageList.length; ++i) { | |
| 944 tempFrom = pageList[i]; | |
| 945 while (i + 1 < pageList.length && pageList[i + 1] == pageList[i] + 1) | |
| 946 ++i; | |
| 947 tempTo = pageList[i]; | |
| 948 pageRanges.push({'from': tempFrom, 'to': tempTo}); | |
| 949 } | |
| 950 return pageRanges; | |
| 951 } | |
| 952 | |
| 953 /** | |
| 954 * Returns the selected pages in ascending order without any duplicates. | |
| 955 */ | |
| 956 function getSelectedPagesSet() { | |
| 957 var pageList = getSelectedPages(); | |
| 958 pageList.sort(function(a,b) { return a - b; }); | |
| 959 pageList = removeDuplicates(pageList); | |
| 960 return pageList; | |
| 961 } | |
| 962 | |
| 963 /** | |
| 964 * Removes duplicate elements from |inArray| and returns a new array. | |
| 965 * |inArray| is not affected. It assumes that the array is already sorted. | |
| 966 * | |
| 967 * @param {Array} inArray The array to be processed. | |
| 968 */ | |
| 969 function removeDuplicates(inArray) { | |
| 970 var out = []; | |
| 971 | |
| 972 if(inArray.length == 0) | |
| 973 return out; | |
| 974 | |
| 975 out.push(inArray[0]); | |
| 976 for (var i = 1; i < inArray.length; ++i) | |
| 977 if(inArray[i] != inArray[i - 1]) | |
| 978 out.push(inArray[i]); | |
| 979 return out; | |
| 980 } | |
| 981 | |
| 982 /** | |
| 983 * Whenever the page range textfield gains focus we add a timer to detect when | 861 * Whenever the page range textfield gains focus we add a timer to detect when |
| 984 * the user stops typing in order to update the print preview. | 862 * the user stops typing in order to update the print preview. |
| 985 */ | 863 */ |
| 986 function addTimerToPageRangeField() { | 864 function addTimerToPageRangeField() { |
| 987 timerId = window.setTimeout(onPageSelectionMayHaveChanged, 1000); | 865 timerId = window.setTimeout(onPageSelectionMayHaveChanged, 1000); |
| 988 } | 866 } |
| 989 | 867 |
| 990 /** | 868 /** |
| 991 * As the user types in the page range textfield, we need to reset this timer, | 869 * As the user types in the page range textfield, we need to reset this timer, |
| 992 * since the page ranges are still being edited. | 870 * since the page ranges are still being edited. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1015 updatePrintButtonState(); | 893 updatePrintButtonState(); |
| 1016 updatePrintSummary(); | 894 updatePrintSummary(); |
| 1017 return; | 895 return; |
| 1018 } | 896 } |
| 1019 | 897 |
| 1020 previouslySelectedPages = currentlySelectedPages; | 898 previouslySelectedPages = currentlySelectedPages; |
| 1021 requestPrintPreview(); | 899 requestPrintPreview(); |
| 1022 } | 900 } |
| 1023 | 901 |
| 1024 /** | 902 /** |
| 1025 * Returns true if the contents of the two arrays are equal. | |
| 1026 */ | |
| 1027 function areArraysEqual(array1, array2) { | |
| 1028 if (array1.length != array2.length) | |
| 1029 return false; | |
| 1030 for (var i = 0; i < array1.length; i++) | |
| 1031 if(array1[i] != array2[i]) | |
| 1032 return false; | |
| 1033 return true; | |
| 1034 } | |
| 1035 | |
| 1036 /** | |
| 1037 * Executed when the 'increment' or 'decrement' button is clicked. | 903 * Executed when the 'increment' or 'decrement' button is clicked. |
| 1038 */ | 904 */ |
| 1039 function onCopiesButtonsClicked(sign) { | 905 function onCopiesButtonsClicked(sign) { |
| 1040 var copiesField = $('copies'); | 906 var copiesField = $('copies'); |
| 1041 if (!isNumberOfCopiesValid()) | 907 if (!isNumberOfCopiesValid()) |
| 1042 copiesField.value = 1; | 908 copiesField.value = 1; |
| 1043 else { | 909 else { |
| 1044 var newValue = getCopies() + sign * 1; | 910 var newValue = getCopies() + sign * 1; |
| 1045 if (newValue < copiesField.min || newValue > copiesField.max) | 911 if (newValue < copiesField.min || newValue > copiesField.max) |
| 1046 return; | 912 return; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1057 this.isLandscape = ''; | 923 this.isLandscape = ''; |
| 1058 } | 924 } |
| 1059 | 925 |
| 1060 /** | 926 /** |
| 1061 * Takes a snapshot of the print settings. | 927 * Takes a snapshot of the print settings. |
| 1062 */ | 928 */ |
| 1063 PrintSettings.prototype.save = function() { | 929 PrintSettings.prototype.save = function() { |
| 1064 this.deviceName = getSelectedPrinterName(); | 930 this.deviceName = getSelectedPrinterName(); |
| 1065 this.isLandscape = isLandscape(); | 931 this.isLandscape = isLandscape(); |
| 1066 } | 932 } |
| OLD | NEW |