1 define([ ], function () {
2 function serializeCsvCell(text) {
3 if (typeof text === 'undefined' || text === null) {
4 return serializeCsvCell('N/A');
5 } else if (/[",]/.test(text)) {
6 return '"' + text.replace(/"/g, '""') + '"';
13 var th = document.createElement('th');
14 th.textContent = text;
19 var td = document.createElement('td');
20 td.textContent = text;
25 var tr = document.createElement('tr');
26 cells.forEach(function (cell) {
33 makeTableLayout: function tabulate(sourceTable) {
34 function levelKeys(level) {
35 return Object.keys(level).filter(function (key) {
36 return !/^\$/.test(key);
47 // Array name means vertical; string name means horizontal
49 levels.forEach(function (level, i) {
50 switch (level.$mode) {
54 name: levelKeys(level),
60 if (i === levels.length - 1) {
61 // If the last level is vertical, insert a new column
74 levelKeys(level).forEach(function (name) {
86 var verticalSizes = [ ];
89 levels.forEach(function (level) {
90 verticalSizes.unshift(currentSize);
92 switch (level.$mode) {
95 currentSize *= levelKeys(level).length;
99 levelKeys(level).slice(1).forEach(function () {
100 verticalSizes.unshift(currentSize);
107 columns.forEach(function (column, i) {
108 column.rowSpan = verticalSizes[i];
113 rowCount: currentSize
117 tableTemplate: function table(rootPath, layout) {
118 var table = document.createElement('table');
119 var header = document.createElement('thead');
120 table.appendChild(header);
122 header.appendChild(tr(layout.columns.map(function (column) {
123 return th(column.title);
126 var body = document.createElement('tbody');
127 table.appendChild(body);
129 var rowIndex, columnIndex;
130 for (rowIndex = 0; rowIndex < layout.rowCount; ++rowIndex) {
131 var path = [ rootPath ];
133 for (columnIndex = 0; columnIndex < layout.columns.length; ++columnIndex) {
134 var column = layout.columns[columnIndex];
137 var name = column.name;
138 if (Array.isArray(name)) {
139 name = name[Math.floor(rowIndex / column.rowSpan) % name.length];
140 cell = th(column.level[name]);
144 cell.setAttribute('data-property', name);
147 if (column.level.$errors) {
148 var errorMessageEl = document.createElement('span');
149 errorMessageEl.className = 'error-message';
150 cell.appendChild(errorMessageEl);
153 if (rowIndex % column.rowSpan === 0) {
154 cell.rowSpan = column.rowSpan;
155 columnEls.push(cell);
159 var rowEl = tr(columnEls);
160 rowEl.id = path.join('-');
161 rowEl.className = 'test';
162 body.appendChild(rowEl);
168 csvByTable: function csvByTable(records) {
169 return records.map(function (record) {
170 return record.map(serializeCsvCell).join(',');
174 csvByObject: function csvByObject(object) {
177 function write(object, stack) {
178 if (object && typeof object.valueOf === 'function') {
179 object = object.valueOf();
182 if (object === null) {
186 switch (typeof object) {
188 Object.keys(object).forEach(function (key) {
189 write(object[key], stack.concat([ key ]));
196 records.push(stack.concat([ String(object) ]));
200 throw new TypeError('Cannot serialize object ' + object);
205 return report.csvByTable(records);
208 csvByLayout: function csv(data, layout, prefix) {
209 function getValue(object, path) {
211 while (object && path.length) {
212 object = object[path.shift()];
219 var rowIndex, columnIndex;
220 for (rowIndex = 0; rowIndex < layout.rowCount; ++rowIndex) {
222 var record = prefix.slice(); // PREFIX IS A HACK FIXME
223 records.push(record);
224 for (columnIndex = 0; columnIndex < layout.columns.length; ++columnIndex) {
225 var column = layout.columns[columnIndex];
228 var name = column.name;
229 if (Array.isArray(name)) {
230 name = name[Math.floor(rowIndex / column.rowSpan) % name.length];
231 cell = column.level[name];
233 } else if (name === null) {
234 cell = getValue(data, path);
236 cell = getValue(data, path.concat([ name ]));
243 return report.csvByTable(records);