1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Inherit the prototype methods from one constructor into another.
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction inherits(childCtor, parentCtor) {
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  function tempCtor() {};
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tempCtor.prototype = parentCtor.prototype;
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  childCtor.superClass_ = parentCtor.prototype;
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  childCtor.prototype = new tempCtor();
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  childCtor.prototype.constructor = childCtor;
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Sets the width (in pixels) on a DOM node.
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction setNodeWidth(node, widthPx) {
20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  node.style.width = widthPx.toFixed(0) + 'px';
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Sets the height (in pixels) on a DOM node.
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction setNodeHeight(node, heightPx) {
27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  node.style.height = heightPx.toFixed(0) + 'px';
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Sets the position and size of a DOM node (in pixels).
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction setNodePosition(node, leftPx, topPx, widthPx, heightPx) {
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  node.style.left = leftPx.toFixed(0) + 'px';
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  node.style.top = topPx.toFixed(0) + 'px';
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  setNodeWidth(node, widthPx);
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  setNodeHeight(node, heightPx);
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Sets the visibility for a DOM node.
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction setNodeDisplay(node, isVisible) {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  node.style.display = isVisible ? '' : 'none';
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Adds a node to |parentNode|, of type |tagName|.
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction addNode(parentNode, tagName) {
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var elem = parentNode.ownerDocument.createElement(tagName);
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  parentNode.appendChild(elem);
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return elem;
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Adds |text| to node |parentNode|.
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction addTextNode(parentNode, text) {
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var textNode = parentNode.ownerDocument.createTextNode(text);
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  parentNode.appendChild(textNode);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return textNode;
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Adds a node to |parentNode|, of type |tagName|.  Then adds
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * |text| to the new node.
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickfunction addNodeWithText(parentNode, tagName, text) {
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var elem = parentNode.ownerDocument.createElement(tagName);
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parentNode.appendChild(elem);
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  addTextNode(elem, text);
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return elem;
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick/**
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Adds or removes a CSS class to |node|.
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction changeClassName(node, classNameToAddOrRemove, isAdd) {
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Multiple classes can be separated by spaces.
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  var currentNames = node.className.split(' ');
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (isAdd) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!(classNameToAddOrRemove in currentNames)) {
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      currentNames.push(classNameToAddOrRemove);
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (var i = 0; i < currentNames.length; ++i) {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (currentNames[i] == classNameToAddOrRemove) {
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        currentNames.splice(i, 1);
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  node.className = currentNames.join(' ');
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction getKeyWithValue(map, value) {
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (key in map) {
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (map[key] == value)
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return key;
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return '?';
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Looks up |key| in |map|, and returns the resulting entry, if  there is one.
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Otherwise, returns |key|.  Intended primarily for use with incomplete
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * tables, and for reasonable behavior with system enumerations that may be
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * extended in the future.
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickfunction tryGetValueWithKey(map, key) {
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (key in map)
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return map[key];
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return key;
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick/**
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Builds a string by repeating |str| |count| times.
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction makeRepeatedString(str, count) {
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var out = [];
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (var i = 0; i < count; ++i)
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.push(str);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return out.join('');
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * TablePrinter is a helper to format a table as ascii art or an HTML table.
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Usage: call addRow() and addCell() repeatedly to specify the data.
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * addHeaderCell() can optionally be called to specify header cells for a
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * single header row.  The header row appears at the top of an HTML formatted
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * table, and uses thead and th tags.  In ascii tables, the header is separated
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * from the table body by a partial row of dashes.
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * setTitle() can optionally be used to set a title that is displayed before
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * the header row.  In HTML tables, it uses the title class and in ascii tables
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * it's between two rows of dashes.
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Once all the fields have been input, call toText() to format it as text or
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * toHTML() to format it as HTML.
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction TablePrinter() {
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  this.rows_ = [];
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  this.hasHeaderRow_ = false;
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  this.title_ = null;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick/**
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * Links are only used in HTML tables.
154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick */
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction TablePrinterCell(value) {
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  this.text = '' + value;
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  this.link = null;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  this.alignRight = false;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  this.allowOverflow = false;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Starts a new row.
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTablePrinter.prototype.addRow = function() {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  this.rows_.push([]);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Adds a column to the current row, setting its value to cellText.
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @returns {!TablePrinterCell} the cell that was added.
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTablePrinter.prototype.addCell = function(cellText) {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var r = this.rows_[this.rows_.length - 1];
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var cell = new TablePrinterCell(cellText);
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  r.push(cell);
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return cell;
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTablePrinter.prototype.setTitle = function(title) {
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  this.title_ = title;
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick/**
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Adds a header row, if not already present, and adds a new column to it,
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * setting its contents to |headerText|.
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @returns {!TablePrinterCell} the cell that was added.
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTablePrinter.prototype.addHeaderCell = function(headerText) {
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Insert empty new row at start of |rows_| if currently no header row.
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!this.hasHeaderRow_) {
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    this.rows_.splice(0, 0, []);
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    this.hasHeaderRow_ = true;
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var cell = new TablePrinterCell(headerText);
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  this.rows_[0].push(cell);
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return cell;
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Returns the maximum number of columns this table contains.
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTablePrinter.prototype.getNumColumns = function() {
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var numColumns = 0;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (var i = 0; i < this.rows_.length; ++i) {
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    numColumns = Math.max(numColumns, this.rows_[i].length);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return numColumns;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Returns the cell at position (rowIndex, columnIndex), or null if there is
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * no such cell.
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTablePrinter.prototype.getCell_ = function(rowIndex, columnIndex) {
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rowIndex >= this.rows_.length)
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return null;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var row = this.rows_[rowIndex];
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (columnIndex >= row.length)
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return null;
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return row[columnIndex];
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Returns a formatted text representation of the table data.
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * |spacing| indicates number of extra spaces, if any, to add between
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * columns.
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTablePrinter.prototype.toText = function(spacing) {
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var numColumns = this.getNumColumns();
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Figure out the maximum width of each column.
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var columnWidths = [];
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  columnWidths.length = numColumns;
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (var i = 0; i < numColumns; ++i)
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    columnWidths[i] = 0;
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If header row is present, temporarily add a spacer row to |rows_|.
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (this.hasHeaderRow_) {
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    var headerSpacerRow = [];
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    for (var c = 0; c < numColumns; ++c) {
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      var cell = this.getCell_(0, c);
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (!cell)
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        continue;
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      var spacerStr = makeRepeatedString('-', cell.text.length);
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      headerSpacerRow.push(new TablePrinterCell(spacerStr));
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    this.rows_.splice(1, 0, headerSpacerRow);
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var numRows = this.rows_.length;
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (var c = 0; c < numColumns; ++c) {
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (var r = 0; r < numRows; ++r) {
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      var cell = this.getCell_(r, c);
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (cell && !cell.allowOverflow) {
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        columnWidths[c] = Math.max(columnWidths[c], cell.text.length);
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var out = [];
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Print title, if present.
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (this.title_) {
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    var titleSpacerStr = makeRepeatedString('-', this.title_.length);
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    out.push(titleSpacerStr);
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    out.push('\n');
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    out.push(this.title_);
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    out.push('\n');
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    out.push(titleSpacerStr);
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    out.push('\n');
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Print each row.
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var spacingStr = makeRepeatedString(' ', spacing);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (var r = 0; r < numRows; ++r) {
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (var c = 0; c < numColumns; ++c) {
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      var cell = this.getCell_(r, c);
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (cell) {
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // Pad the cell with spaces to make it fit the maximum column width.
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        var padding = columnWidths[c] - cell.text.length;
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        var paddingStr = makeRepeatedString(' ', padding);
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (cell.alignRight) {
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          out.push(paddingStr);
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          out.push(cell.text);
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          out.push(cell.text);
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          out.push(paddingStr);
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        out.push(spacingStr);
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.push('\n');
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Remove spacer row under the header row, if one was added.
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (this.hasHeaderRow_)
3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    this.rows_.splice(1, 1);
3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return out.join('');
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick/**
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Adds a new HTML table to the node |parent| using the specified style.
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTablePrinter.prototype.toHTML = function(parent, style) {
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var numRows = this.rows_.length;
3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var numColumns = this.getNumColumns();
3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var table = addNode(parent, 'table');
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  table.setAttribute('class', style);
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var thead = addNode(table, 'thead');
3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  var tbody = addNode(table, 'tbody');
3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Add title, if needed.
3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (this.title_) {
3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    var tableTitleRow = addNode(thead, 'tr');
3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    var tableTitle = addNodeWithText(tableTitleRow, 'th', this.title_);
3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    tableTitle.colSpan = numColumns;
3243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    changeClassName(tableTitle, 'title', true);
3253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Fill table body, adding header row first, if needed.
3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (var r = 0; r < numRows; ++r) {
3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    var cellType;
3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    var row;
3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (r == 0 && this.hasHeaderRow_) {
3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      row = addNode(thead, 'tr');
3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cellType = 'th';
3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      row = addNode(tbody, 'tr');
3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cellType = 'td';
3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
3383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    for (var c = 0; c < numColumns; ++c) {
3393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      var cell = this.getCell_(r, c);
3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (cell) {
341731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        var tableCell = addNode(row, cellType, cell.text);
3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        if (cell.alignRight)
3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          tableCell.alignRight = true;
3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // If allowing overflow on the rightmost cell of a row,
3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // make the cell span the rest of the columns.  Otherwise,
3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // ignore the flag.
3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        if (cell.allowOverflow && !this.getCell_(r, c + 1))
3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          tableCell.colSpan = numColumns - c;
349731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        if (cell.link) {
350731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          var linkNode = addNodeWithText(tableCell, 'a', cell.text);
351731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          linkNode.href = cell.link;
352731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        } else {
353731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          addTextNode(tableCell, cell.text);
354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        }
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return table;
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
361