summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources/print_preview/print_preview_utils.js
blob: e16c445381d3a5b7f6c3be502c748de515235def (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// 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.

/**
 * 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);
}

/**
 * Returns true if |value| is a valid non zero positive integer.
 * @param {string} value The string to be tested.
 *
 * @return {boolean} true if the |value| is valid non zero positive integer.
 */
function isPositiveInteger(value) {
  return isInteger(value) && parseInt(value, 10) > 0;
}

/**
 * Returns true if the contents of the two arrays are equal.
 * @param {Array} array1 The first array.
 * @param {Array} array1 The second array.
 *
 * @return {boolean} true if the 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;
}

/**
 * Removes duplicate elements from |inArray| and returns a new array.
 * |inArray| is not affected. It assumes that |inArray| 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;
}

/**
 * Checks if |pageRangeText| represents a valid page selection.
 * A valid selection has a parsable format and every page identifier is
 * <= |totalPageCount| unless wildcards are used (see examples).
 * Example: "1-4, 9, 3-6, 10, 11" is valid, assuming |totalPageCount| >= 11.
 * Example: "1-4, 6-6" is valid, assuming |totalPageCount| >= 6.
 * Example: "2-" is valid, assuming |totalPageCount| >= 2, means from 2 to the
 * end.
 * Example: "1-10000" is valid, regardless of |totalPageCount|, means from 1 to
 * the end if |totalPageCount| < 10000.
 * Example: "1-4dsf, 11" is invalid regardless of |totalPageCount|.
 * Example: "4-2, 11, -6" is invalid regardless of |totalPageCount|.
 *
 * Note: If |totalPageCount| is undefined the validation does not take
 * |totalPageCount| into account.
 * Example: "34853253" is valid.
 * Example: "1-4, 9, 3-6, 10, 11" is valid.
 *
 * @return {boolean} true if the |pageRangeText| is valid.
 */
function isPageRangeTextValid(pageRangeText, totalPageCount) {
  var regex = /^\s*([0-9]+)\s*-\s*([0-9]*)\s*$/;
  var successfullyParsed = 0;

  // Splitting around commas.
  var parts = pageRangeText.split(/,/);

  for (var i = 0; i < parts.length; ++i) {
    // Removing whitespace.
    parts[i] = parts[i].replace(/\s*/g, '');
    var match = parts[i].match(regex);
    if (parts[i].length == 0)
      continue;

    if (match && match[1] && isPositiveInteger(match[1])) {
      var from = parseInt(match[1], 10);
      var to = isPositiveInteger(match[2]) ? parseInt(match[2], 10) :
          totalPageCount;
      if (from > to || from > totalPageCount)
        return false;
    } else if (!isPositiveInteger(parts[i]) || (totalPageCount != -1 &&
          parseInt(parts[i], 10) > totalPageCount)) {
      return false;
    }
    successfullyParsed++;
  }
  return successfullyParsed > 0;
}

/**
 * Returns a list of all pages specified in |pagesRangeText|. The pages are
 * listed in the order they appear in |pageRangeText| and duplicates are not
 * eliminated. If |pageRangeText| is not valid according to
 * isPageRangeTextValid(), or |totalPageCount| is undefined an empty list is
 * returned.
 *
 * @return {Array}
 */
function pageRangeTextToPageList(pageRangeText, totalPageCount) {
  var pageList = [];
  if ((totalPageCount && !isPageRangeTextValid(pageRangeText, totalPageCount))
      || !totalPageCount) {
    return pageList;
  }

  var regex = /^\s*([0-9]+)\s*-\s*([0-9]*)\s*$/;
  var parts = pageRangeText.split(/,/);

  for (var i = 0; i < parts.length; ++i) {
    var match = parts[i].match(regex);

    if (match && match[1]) {
      var from = parseInt(match[1], 10);
      var to = match[2] ? parseInt(match[2], 10) : totalPageCount;

      for (var j = from; j <= Math.min(to, totalPageCount); ++j)
        pageList.push(j);
    } else {
      var singlePageNumber = parseInt(parts[i], 10);
      if (isPositiveInteger(singlePageNumber) &&
          singlePageNumber <= totalPageCount) {
        pageList.push(singlePageNumber);
      }
    }
  }
  return pageList;
}

/**
 * Returns the contents of |pageList| in ascending order and without any
 * duplicates. |pageList| is not affected.
 *
 * @return {Array}
 */
function pageListToPageSet(pageList) {
  var pageSet = [];
  if (pageList.length == 0)
    return pageSet;
  pageSet = pageList.slice(0);
  pageSet.sort(function(a,b) { return a - b; });
  pageSet = removeDuplicates(pageSet);
  return pageSet;
}

/**
 * Converts |pageSet| to page ranges. 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 pageSetToPageRanges(pageSet) {
  var pageRanges = [];
  for (var i = 0; i < pageSet.length; ++i) {
    tempFrom = pageSet[i];
    while (i + 1 < pageSet.length && pageSet[i + 1] == pageSet[i] + 1)
      ++i;
    tempTo = pageSet[i];
    pageRanges.push({'from': tempFrom, 'to': tempTo});
  }
  return pageRanges;
}

/**
 * Constructs a url for getting a specific page.
 * @param {string} id The id of the preview data.
 * @param {number} pageNumber The number of the desired page.
 * @return {string} The constructed URL.
 */
function getPageSrcURL(id, pageNumber) {
  return 'chrome://print/' + id + '/' + pageNumber + '/print.pdf';
}

/**
 * Returns a random integer within the specified range, |endPointA| and
 * |endPointB| are included.
 * @param {number} endPointA One end of the desired range.
 * @param {number} endPointB  The other end of the desired range.
 * @return {number} The random integer.
 */
function randomInteger(endPointA, endPointB) {
  from = Math.min(endPointA, endPointB);
  to = Math.max(endPointA, endPointB);
  return Math.floor(Math.random() * (to - from + 1) + from);
}

// Number of points per inch.
var POINTS_PER_INCH = 72;
// Number of points per millimeter.
var POINTS_PER_MILLIMETER = 2.83464567;

/**
 * Converts |value| from inches to points.
 * @param {number} value The number in inches.
 * @return {number} |value| in points.
 */
function convertInchesToPoints(value) {
  return value * POINTS_PER_INCH;
}

/**
 * Converts |value| from points to inches.
 * @param {number} value The number in points.
 * @return {number} |value| in inches.
 */
function convertPointsToInches(value) {
  return value / POINTS_PER_INCH;
}

/**
 * Converts |value| from millimeters to points.
 * @param {number} value The number in millimeters.
 * @return {number} |value| in points.
 */
function convertMillimetersToPoints(value) {
  return value * POINTS_PER_MILLIMETER;
}

/**
 * Converts |value| from points to millimeters.
 * @param {number} value The number in points.
 * @return {number} |value| in millimeters.
 */
function convertPointsToMillimeters(value) {
  return value / POINTS_PER_MILLIMETER;
}