jqwidgets-framework
Version:
jQWidgets is an advanced Angular, Vue, Blazor, React, Web Components, jquery, ASP .NET MVC, Custom Elements and HTML5 UI framework.
1,413 lines (1,145 loc) • 138 kB
JavaScript
/* tslint:disable */
/* eslint-disable */
(function ($) {
window.jqxToDash = function(value) {
return value.split(/(?=[A-Z])/).join('-').toLowerCase();
}
class DataExporter {
constructor(exportDetails, groupBy, filterBy, conditionalFormatting) {
const that = this;
if (!exportDetails) {
exportDetails = {};
}
/*
* "style" object definition (all properties are optional):
*
* «any valid CSS property» - applied to whole table
* header (Object)
* «any valid CSS property» - applied to header cells
* «any column name» (Object)
* «any valid CSS property» - applied to particular column header cell
* columns (Object)
* «any valid CSS property» - applied to column cells
* «any column name» (Object)
* «any valid CSS property» - applied to the cells of particular column
* format - applicable to numeric and date columns
* «n» (Object), where «n» is a row index (related to use of "ConditionalFormatting" object)
* background
* border
* color
* rows (Object)
* «any valid CSS property» - applied to rows
* alternationCount
* alternationStart
* alternationEnd
* alternationIndex«n»Color, where «n» is an integer
* alternationIndex«n»BorderColor, where «n» is an integer
* alternationIndex«n»BackgroundColor, where «n» is an integer
* «n» (Object), where «n» is a row index
* «any valid CSS property» - applied to particular row
*/
that.style = exportDetails.style;
that.header = exportDetails.header;
that.exportHeader = exportDetails.exportHeader || true;
that.hierarchical = exportDetails.hierarchical;
that.expandChar = exportDetails.expandChar || '+';
that.collapseChar = exportDetails.collapseChar || '-';
that.pageOrientation = exportDetails.pageOrientation;
if (!that.hierarchical && groupBy && groupBy.length > 0) {
that.groupBy = groupBy;
}
else {
that.mergedCells = exportDetails.mergedCells;
}
if (!that.groupBy && filterBy && Object.keys(filterBy).length > 0) {
that.filterBy = filterBy;
}
if (conditionalFormatting) {
that.conditionalFormatting = conditionalFormatting;
}
that.timeBetween1900And1970 = new Date(1970, 0, 1).getTime() - new Date(1900, 0, 1).getTime();
}
/**
* Generates and downloads a file.
*/
downloadFile(data, type, fileName) {
let file;
if (!fileName) {
return data;
}
if (data instanceof Blob) {
file = data;
}
else {
file = new Blob([data], { type: type });
}
if (window.navigator.msSaveOrOpenBlob) { // Edge
window.navigator.msSaveOrOpenBlob(file, fileName);
}
else { // Chrome, Firefox, Safari
const a = document.createElement('a'),
url = URL.createObjectURL(file);
a.href = url;
a.download = fileName;
a.style.position = 'absolute';
a.style.visibility = 'hidden';
document.body.appendChild(a);
a.click();
setTimeout(function () {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
}
/**
* Exports data.
*/
exportData(data, format, fileName, callback) {
const that = this;
that.actualHierarchy = that.hierarchical;
format = format.toLowerCase();
if (that.exportHeader) {
if (that.header) {
data = data.slice(0);
if (data.length === 0) {
that.actualHierarchy = false;
}
that.processComplexHeader(that.header, data, format);
}
else if (data.length === 1) {
that.actualHierarchy = false;
}
}
if (data.length === 0) {
// eslint-disable-next-line
console.warn('No data to export.');
return;
}
if (format === 'xlsx') {
that.xlsxStartIndex = that.complexHeader ? that.complexHeader.length : +that.exportHeader;
}
if (that.actualHierarchy) {
data = that.processHierarchicalData(data, format);
}
that.getDatafields(data);
if (fileName && fileName.slice(fileName.length - format.length - 1, fileName.length) !== '.' + format) {
fileName += '.' + format;
}
let output = null;
switch (format) {
case 'csv':
output = that.exportToCSVAndTSV(data, { delimiter: ', ', MIME: 'text/csv', toRemove: 2 }, fileName);
break;
case 'html':
output = that.exportToHTML(data, fileName);
break;
case 'jpeg':
case 'png':
that.exportToImage(data, fileName, format, callback);
break;
case 'json':
output = that.exportToJSON(data, fileName);
break;
case 'pdf':
output = that.exportToPDF(data, fileName);
break;
case 'tsv':
output = that.exportToCSVAndTSV(data, { delimiter: '\t', MIME: 'text/tab-separated-values', toRemove: 1 }, fileName);
break;
case 'xlsx':
output = that.exportToXLSX(data, fileName);
break;
case 'xml':
output = that.exportToXML(data, fileName);
break;
}
if (callback && output) {
callback(output);
}
delete that.complexHeader;
return output;
}
/**
* Exports to CSV and TSV.
*/
exportToCSVAndTSV(data, formatOptions, fileName) {
const that = this,
datafields = that.datafields;
let stringResult = '';
for (let i = 0; i < data.length; i++) {
const currentRecord = data[i];
let stringifiedCurrentRecord = '';
for (let j = 0; j < datafields.length; j++) {
if (that.actualHierarchy && j === 0) {
stringifiedCurrentRecord += ('""' + formatOptions.delimiter).repeat(currentRecord._level - 1) +
'"' + currentRecord[datafields[j]] + '"' + formatOptions.delimiter +
('""' + formatOptions.delimiter).repeat(that.maxLevel - currentRecord._level);
continue;
}
stringifiedCurrentRecord += '"' + currentRecord[datafields[j]] + '"' + formatOptions.delimiter;
}
stringifiedCurrentRecord = stringifiedCurrentRecord.slice(0, stringifiedCurrentRecord.length - formatOptions.toRemove) + '\n';
stringResult += stringifiedCurrentRecord;
}
return this.downloadFile(stringResult, formatOptions.MIME, fileName);
}
/**
* Exports to HTML.
*/
exportToHTML(data, fileName) {
const that = this,
datafields = that.datafields,
style = that.style;
let header = '',
startIndex = 0,
html2canvas = '';
data = that.processGroupingInformation(data);
that.data = data;
if (that.exportHeader) {
header = that.getHTMLHeader(datafields, data);
startIndex = 1;
}
if (arguments[2]) {
const scripts = Array.from(document.getElementsByTagName('script')),
html2canvasScript = scripts.find(script => script.src.indexOf('html2canvas') !== -1);
html2canvas = `<script type="text/javascript" src="${html2canvasScript.src}"></script>`;
}
let htmlContent = `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
${that.getRowStyle()}${that.getColumnStyle()}
</style>${html2canvas}${that.toggleableFunctionality()}
</head>
<body>
<table${that.getTableStyle()}>${header}
<tbody>\n`;
const mergedMainCells = {},
mergedSecondaryCells = {},
groupsHandled = [];
that.getMergedCellsInfo(mergedMainCells, mergedSecondaryCells);
mainLoop:
for (let i = startIndex; i < data.length; i++) {
const currentRecord = data[i],
row = i - startIndex;
let n = that.getAlternationIndex(row, ' rowN'),
toCollapse = '',
level = '',
groupId = '',
outlineLevel = 0;
if (that.actualHierarchy) {
if (currentRecord._collapsed) {
toCollapse = ' collapsed';
}
level = ` level="${currentRecord._level}"`;
}
else if (that.groupBy) {
for (let k = 0; k < that.groupBy.length; k++) {
const datafield = that.groupBy[k],
currentGroup = currentRecord[datafield],
currentGroupLabel = that.groups[datafield][currentGroup];
groupId += currentGroup;
if (groupsHandled.indexOf(groupId) === -1) {
htmlContent += ` <tr class="row">
<td class="column group" style="padding-left: ${outlineLevel * 25}px;" colspan="${that.datafields.length}">${currentGroupLabel}</td>
</tr>`;
groupsHandled.push(groupId);
i--;
continue mainLoop;
}
outlineLevel++;
}
}
let currentContent = ` <tr class="row row${row}${n}${toCollapse}"${level}`;
if (!fileName) {
currentContent += ' style="page-break-inside: avoid;"'
}
currentContent += '>\n';
for (let j = 0; j < datafields.length; j++) {
const cellCode = j + ',' + (row);
let colspan = 1, rowspan = 1;
if (mergedMainCells[cellCode]) {
colspan = mergedMainCells[cellCode].colspan;
rowspan = mergedMainCells[cellCode].rowspan;
}
else if (mergedSecondaryCells[cellCode]) {
continue;
}
const datafield = datafields[j];
let value = currentRecord[datafield],
indent = '';
if (that.actualHierarchy && j === 0) {
let sign = '';
if (currentRecord._expanded) {
sign = that.collapseChar;
}
else if (currentRecord._expanded === false) {
sign = that.expandChar;
}
indent = `<div class="toggle-element" style="margin-left: ${25 * (currentRecord._level - 1) + 5}px;" expanded>${sign}</div>`;
}
value = that.getFormattedValue(value, datafield);
let css = '';
if (style && style.columns && style.columns[datafield] && style.columns[datafield][row]) {
const uniqueStyle = style.columns[datafield][row];
css += `border-color: ${uniqueStyle.border}; background-color: ${uniqueStyle.background}; color: ${uniqueStyle.color};"`;
}
if (j === 0 && outlineLevel > 1) {
css += `padding-left: ${(outlineLevel - 1) * 25}px;"`;
}
if (css) {
css = ` style="${css}"`;
}
currentContent += ` <td class="column column${datafield}"${css} colspan="${colspan}" rowspan="${rowspan}">${indent + value}</td>\n`;
}
htmlContent += currentContent + ' </tr>\n';
}
htmlContent += ` </tbody>
</table>
</body>
</html>`;
if (arguments[2]) {
return htmlContent;
}
return this.downloadFile(htmlContent, 'text/html', fileName);
}
/**
* Exports to an image (PNG/JPEG).
*/
exportToImage(data, fileName, fileExtension, callback) {
const that = this;
try {
html2canvas;
}
catch (error) {
throw new Error('jqx-grid: Missing reference to \'html2canvas.min.js\'.');
}
let imageData = null;
const htmlContent = that.exportToHTML(data, fileName, true),
iframe = document.createElement('iframe');
iframe.style.position = 'absolute';
iframe.style.top = 0;
iframe.style.left = 0;
iframe.style.border = 'none';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.opacity = 0;
document.body.appendChild(iframe);
iframe.contentDocument.write(htmlContent);
function checkIframePopulated() {
if (!iframe.contentDocument.body || !iframe.contentDocument.body.firstElementChild) {
requestAnimationFrame(checkIframePopulated);
}
else {
iframe.contentWindow.html2canvas(iframe.contentDocument.body.firstElementChild).then(canvas => {
const draw = $.jqxDraw(document.createElement('div'));
imageData = canvas.toDataURL('image/png');
if (callback) {
callback(imageData);
}
else {
document.body.appendChild(canvas);
draw.exportImage(undefined, canvas, fileExtension, fileName);
}
iframe.remove();
canvas.remove();
});
}
}
checkIframePopulated();
return imageData;
}
/**
* Gets merged cells information (for use in HTML and PDF export).
*/
getMergedCellsInfo(mergedMainCells, mergedSecondaryCells, mapping) {
const that = this;
if (!that.mergedCells) {
return;
}
const multipleTables = mapping && mapping[that.datafields.length - 1] !== 0;
that.mergedCellsPDF = that.mergedCells.slice(0);
for (let i = 0; i < that.mergedCellsPDF.length; i++) {
const cellDefinition = that.mergedCellsPDF[i];
let colspan = cellDefinition.colspan,
rowspan = cellDefinition.rowspan;
if (rowspan < 2 && colspan < 2) {
continue;
}
const row = cellDefinition.cell[1];
let col = cellDefinition.cell[0];
if (multipleTables && colspan > 1) {
const startTable = mapping[col],
endTable = mapping[col + colspan - 1],
splitCells = [];
if (endTable > startTable) {
let currentTable = startTable,
currentColumn = col,
overal = 0;
mainLoop:
for (let i = startTable; i <= endTable; i++) {
let start = currentColumn,
span = 0;
while (mapping[currentColumn] === currentTable) {
currentColumn++;
overal++;
span++;
if (overal === colspan) {
splitCells.push({ start: start, span: span });
break mainLoop;
}
}
splitCells.push({ start: start, span: span });
currentTable = mapping[currentColumn];
}
colspan = splitCells[0].span;
for (let i = 1; i < splitCells.length; i++) {
that.mergedCellsPDF.push({ cell: [splitCells[i].start, row], colspan: splitCells[i].span, rowspan: rowspan, originalCell: col });
}
}
}
for (let j = col; j < col + colspan; j++) {
for (let k = row; k < row + rowspan; k++) {
const code = j + ',' + k;
if (j === col && k === row) {
mergedMainCells[code] = { colspan: colspan, rowspan: rowspan, originalCell: cellDefinition.originalCell };
continue;
}
mergedSecondaryCells[code] = true;
}
}
}
}
/**
* Gets alternation index.
*/
getAlternationIndex(row, prefix) {
const that = this;
if (!that.style) {
return '';
}
const rowsDefinition = that.style.rows,
alternationCount = rowsDefinition && rowsDefinition.alternationCount;
if (alternationCount &&
(((rowsDefinition.alternationStart === undefined || row >= rowsDefinition.alternationStart) &&
(rowsDefinition.alternationEnd === undefined || row <= rowsDefinition.alternationEnd)) ||
rowsDefinition.alternationStart === rowsDefinition.alternationEnd)) {
return prefix + (row % rowsDefinition.alternationCount);
}
return '';
}
/**
* Gets formatted numeric or date value (for use in HTML and PDF export).
*/
getFormattedValue(value, datafield) {
const that = this,
style = that.style;
if (datafield && style && style.columns &&
style.columns[datafield] && style.columns[datafield].format) {
if (typeof value === 'number') {
return that.formatNumber(value, style.columns[datafield].format);
}
else if (value instanceof Date) {
return that.formatDate(value, style.columns[datafield].format);
}
}
else if (value instanceof Date) {
return that.formatDate(value, 'd');
}
return value;
}
/**
* Exports to JSON.
*/
exportToJSON(data, fileName) {
return this.downloadFile(JSON.stringify(data, this.datafields.concat('rows')), 'application/json', fileName);
}
/**
* Exports to PDF.
*/
exportToPDF(data, fileName) {
const that = this,
datafields = that.datafields,
startIndex = +that.exportHeader,
groupsHandled = [],
mergedMainCells = {},
mergedSecondaryCells = {},
mapping = {},
headerRows = startIndex ? that.complexHeader ? that.complexHeader.length : 1 : 0,
docDefinition = {
pageOrientation: that.pageOrientation || 'portrait'
};
let header = [], content = [], tables;
function createTableRow() {
let tableRow = [];
for (let i = 0; i < tables.length; i++) {
tableRow.push([]);
}
return tableRow;
}
data = that.processGroupingInformation(data);
that.data = data;
that.headerRows = headerRows;
that.getPDFStyle();
const styleInfo = that.styleInfo;
tables = styleInfo ? that.wrapPDFColumns(docDefinition, mapping) : [{ body: header, datafields: datafields }];
if (startIndex) {
header = that.getPDFHeader(datafields, tables, mapping);
}
that.getMergedCellsInfo(mergedMainCells, mergedSecondaryCells, mapping);
mainLoop:
for (let i = startIndex; i < data.length; i++) {
const currentRecord = data[i];
let groupId = '',
outlineLevel = 0;
if (that.groupBy) {
for (let k = 0; k < that.groupBy.length; k++) {
const datafield = that.groupBy[k],
currentGroup = currentRecord[datafield],
currentGroupLabel = that.groups[datafield][currentGroup];
groupId += currentGroup;
if (groupsHandled.indexOf(groupId) === -1) {
that.createGroupHeaderRow(tables, { text: currentGroupLabel, style: ['row', 'cell', 'group'], marginLeft: outlineLevel * 7.5 });
groupsHandled.push(groupId);
i--;
continue mainLoop;
}
outlineLevel++;
}
}
const tableRow = createTableRow(),
row = i - startIndex;
let n = that.getAlternationIndex(row, '');
for (let j = 0; j < datafields.length; j++) {
const datafield = datafields[j],
entry = { style: ['row', 'row' + row, 'cell', 'cell' + datafield] },
tableIndex = mapping[j] || 0;
if (n !== undefined) {
entry.style.splice(1, 0, 'rowN' + n);
}
if (that.mergedCellsPDF) {
const cellCode = j + ',' + row,
mergeInfo = mergedMainCells[cellCode];
if (mergeInfo) {
entry.colSpan = mergeInfo.colspan;
entry.rowSpan = mergeInfo.rowspan;
if (mergeInfo.originalCell !== undefined) {
entry.text = '';
entry.style[entry.style.length - 1] = 'cell' + datafields[mergeInfo.originalCell];
tableRow[tableIndex].push(entry);
continue;
}
}
else if (mergedSecondaryCells[cellCode]) {
tableRow[tableIndex].push({});
continue;
}
}
const value = that.getFormattedValue(currentRecord[datafield], datafield);
entry.text = value.toString();
that.getUniqueStylePDF(entry, datafield, row);
that.setIndentation(entry, { j: j, currentRecord: currentRecord, value: value, outlineLevel: outlineLevel });
tableRow[tableIndex].push(entry);
}
for (let k = 0; k < tables.length; k++) {
tables[k].body.push(tableRow[k]);
}
}
if (styleInfo) {
for (let i = 0; i < tables.length; i++) {
const body = tables[i].body;
for (let j = headerRows - 1; j >= 0; j--) {
body.unshift(header[i][j]);
}
content.push({
table: {
headerRows: headerRows,
widths: tables[i].widths,
heights: function (row) {
if (styleInfo.heights[row]) {
return styleInfo.heights[row];
}
if (styleInfo.defaultHeight) {
return styleInfo.defaultHeight;
}
},
body: body
},
pageBreak: 'after'
});
}
delete content[tables.length - 1].pageBreak;
docDefinition.styles = styleInfo.styles;
}
else {
const body = tables[0].body;
for (let j = headerRows - 1; j >= 0; j--) {
body.unshift(header[0][j]);
}
content = [{ table: { headerRows: headerRows, body: body } }];
docDefinition.styles = { header: { bold: true }, group: { bold: true } };
}
docDefinition.content = content;
pdfMake.createPdf(docDefinition).download(fileName);
delete that.mergedCellsPDF;
delete that.styleInfo;
}
/**
* Gets the header content when exporting to PDF.
*/
getPDFStyle() {
const that = this,
style = that.style;
if (!style) {
return '';
}
const sampleRecord = that.data[0],
headerDefinition = style.header,
columnsDefinition = style.columns,
rowsDefinition = style.rows,
styleInfo = {
heights: [],
widths: Array(that.datafields.length).fill('*'),
styles: {
header: {},
row: {},
cell: {},
group: { fillColor: '#FFFFFF', color: '#000000', bold: true }
}
};
that.styleInfo = styleInfo;
function processStyleDefinition(definition, type) {
if (!definition) {
return;
}
for (let prop in definition) {
if (!definition.hasOwnProperty(prop)) {
continue;
}
if (sampleRecord[prop] === undefined) {
if (prop === 'height' && type === 'header') {
for (let i = 0; i < that.headerRows; i++) {
styleInfo.heights[i] = (parseInt(definition[prop], 10) / that.headerRows) / 1.57;
}
}
else {
that.storePDFStyle({ prop: prop, value: definition[prop], toUpdate: type });
}
}
else {
for (let columnProp in definition[prop]) {
if (!isNaN(columnProp) || !definition[prop].hasOwnProperty(columnProp)) {
continue;
}
const value = definition[prop][columnProp],
index = that.datafields.indexOf(prop);
if (columnProp === 'width' && styleInfo.widths[index] === '*') {
styleInfo.widths[index] = parseFloat(value);
}
else {
that.storePDFStyle({ prop: columnProp, value: value, toUpdate: type + prop });
}
}
}
}
}
processStyleDefinition(headerDefinition, 'header');
processStyleDefinition(columnsDefinition, 'cell');
if (!rowsDefinition) {
return;
}
for (let prop in rowsDefinition) {
if (!rowsDefinition.hasOwnProperty(prop) || prop.indexOf('alt') !== -1) {
continue;
}
const value = rowsDefinition[prop];
if (!isNaN(prop)) {
for (let rowProp in value) {
if (value.hasOwnProperty(rowProp)) {
if (rowProp === 'height') {
styleInfo.heights[parseFloat(prop) + that.headerRows] = parseFloat(value[rowProp]) / 1.57;
}
else {
that.storePDFStyle({ prop: rowProp, value: value[rowProp], toUpdate: 'row' + prop });
}
}
}
continue;
}
if (prop === 'height') {
styleInfo.defaultHeight = parseFloat(value) / 1.57;
}
else {
that.storePDFStyle({ prop: prop, value: value, toUpdate: 'row' });
}
}
if (!rowsDefinition.alternationCount) {
return;
}
for (let i = 0; i < rowsDefinition.alternationCount; i++) {
const styleN = {};
if (rowsDefinition[`alternationIndex${i}Color`]) {
styleN.color = rowsDefinition[`alternationIndex${i}Color`];
}
if (rowsDefinition[`alternationIndex${i}BackgroundColor`]) {
styleN.fillColor = rowsDefinition[`alternationIndex${i}BackgroundColor`];
}
styleInfo.styles['rowN' + i] = styleN;
}
}
/**
* Stores style in object to be applied to generated PDF.
*/
storePDFStyle(details) {
const that = this;
let objectToUpdate = that.styleInfo.styles[details.toUpdate];
if (!objectToUpdate) {
objectToUpdate = {};
that.styleInfo.styles[details.toUpdate] = objectToUpdate;
}
let value = details.value;
switch (details.prop) {
case 'backgroundColor':
objectToUpdate.fillColor = value;
break;
case 'color':
objectToUpdate.color = value;
break;
case 'fontSize':
objectToUpdate.fontSize = parseFloat(value);
break;
case 'fontStyle':
if (value === 'italic') {
objectToUpdate.italics = true;
}
break;
case 'fontWeight':
if (value === 'bold') {
objectToUpdate.bold = true;
}
break;
case 'textAlign':
objectToUpdate.alignment = value;
break;
}
}
/**
* Enables column wrapping when exporting to PDF.
*/
wrapPDFColumns(docDefinition, mapping) {
const that = this,
styleInfo = this.styleInfo,
maxPerPage = docDefinition.pageOrientation === 'portrait' ? 775 : 1155, // maximum of 775px (portrait) or 1155px (landscape) per A4 page
tables = [];
let currentPage = 0;
for (let i = 0; i < styleInfo.widths.length; i++) {
let currentWidth = styleInfo.widths[i],
numericWidth = currentWidth;
if (currentWidth === '*') {
numericWidth = 150;
}
else if (currentWidth >= maxPerPage) {
numericWidth = maxPerPage
currentWidth = '*';
}
else {
currentWidth /= 1.57;
}
if (tables[currentPage] === undefined) {
const body = [];
tables[currentPage] = {
body: body,
width: numericWidth,
widths: [currentWidth],
datafields: [that.datafields[i]]
};
mapping[i] = currentPage;
continue;
}
const table = tables[currentPage];
if (table.width + numericWidth > maxPerPage) {
currentPage++;
i--;
continue;
}
mapping[i] = currentPage;
table.width += numericWidth;
table.widths.push(currentWidth);
table.datafields.push(that.datafields[i]);
}
return tables;
}
/**
* Gets the header content when exporting to PDF.
*/
getPDFHeader(datafields, tables, mapping) {
const that = this,
headerArray = [],
headerRows = that.headerRows,
headerStructure = that.complexHeader ? that.complexHeader : [Object.values(that.data[0])],
headers = [];
let result = [];
for (let i = 0; i < headerRows; i++) {
const row = headerStructure[i];
for (let k = 0; k < row.length; k++) {
let tableIndex = mapping[k] || 0;
if (!headers[tableIndex]) {
headers[tableIndex] = [];
}
if (!headers[tableIndex][i]) {
headers[tableIndex][i] = [];
}
headers[tableIndex][i].push(row[k]);
}
}
function processHeader(header, result, table) {
for (let j = 0; j < headerRows; j++) {
const row = header[j];
const tableRow = [];
for (let k = 0; k < row.length; k++) {
const currentLabel = row[k];
let colspan = 1, rowspan = 1;
if ((row[k - 1] && row[k - 1] === currentLabel) ||
(header[j - 1] && (header[j - 1][k] === currentLabel))) {
tableRow.push({});
continue;
}
let iterator = k + 1;
while (row[iterator] && row[iterator] === row[iterator - 1]) {
colspan++;
iterator++;
}
iterator = j + 1;
while (header[iterator] && header[iterator][k] === currentLabel) {
rowspan++;
iterator++;
}
const datafield = j === headerRows - 1 || rowspan + j === headerRows ?
table.datafields[k] : null,
entry = {
text: currentLabel, colSpan: colspan, rowSpan: rowspan
};
if (!datafield) {
entry.alignment = 'center';
entry.style = 'header';
}
else {
entry.style = ['header', 'header' + datafield];
}
tableRow.push(entry);
}
result.push(tableRow);
}
}
for (let i = 0; i < tables.length; i++) {
result = [];
processHeader(headers[i], result, tables[i]);
headerArray.push(result);
}
return headerArray;
}
/**
* Creates group header rows when exporting to PDF.
*/
createGroupHeaderRow(tables, entryTemplate) {
for (let i = 0; i < tables.length; i++) {
const entry = Object.assign({}, entryTemplate),
colspan = tables[i].datafields.length,
tableRow = [entry];
entry.colSpan = colspan;
tableRow.length = colspan;
tableRow.fill({}, 1, colspan - 1);
tables[i].body.push(tableRow);
}
}
/**
* Gets unique cell style when exporting to PDF.
*/
getUniqueStylePDF(entry, datafield, row) {
const style = this.style;
function toHex(background) {
const parts = /rgba\((\d+),(\d+),(\d+)\,(\d*.\d+|\d+)\)/gi.exec(background.replace(/\s/g, '')),
r = parseFloat(parts[1]).toString(16).toUpperCase(),
g = parseFloat(parts[2]).toString(16).toUpperCase(),
b = parseFloat(parts[3]).toString(16).toUpperCase();
return '#' + ('0').repeat(2 - r.length) + r +
('0').repeat(2 - g.length) + g +
('0').repeat(2 - b.length) + b;
}
if (!style || !style.columns || !style.columns[datafield]) {
return;
}
const uniqueStyle = style.columns[datafield][row];
if (!uniqueStyle) {
return;
}
entry.fillColor = toHex(uniqueStyle.background);
entry.color = uniqueStyle.color.toLowerCase();
}
/**
* Sets the indentation of a PDF cell.
*/
setIndentation(entry, details) {
if (details.j !== 0) {
return;
}
const that = this;
if (that.actualHierarchy) {
const currentRecord = details.currentRecord;
if (currentRecord._expanded !== undefined) {
entry.marginLeft = 25 * (currentRecord._level - 1);
entry.text = that.collapseChar + ' ' + details.value;
}
else {
entry.marginLeft = 25 * (currentRecord._level - 1) + 6;
}
}
else if (details.outlineLevel > 1) {
entry.marginLeft = (details.outlineLevel - 1) * 7.5;
}
}
/**
* Exports to XLSX.
*/
exportToXLSX(data, fileName) {
const that = this;
let style = that.style;
data = that.processGroupingInformation(data, true);
that.data = data;
that.getColumnsArray();
that.complexHeaderMergedCells = [];
if (that.complexHeaderMergeInfo) {
for (let cell in that.complexHeaderMergeInfo) {
if (that.complexHeaderMergeInfo.hasOwnProperty(cell)) {
const currentEntry = that.complexHeaderMergeInfo[cell];
if (currentEntry.from[0] === currentEntry.to[0] &&
currentEntry.from[1] === currentEntry.to[1]) {
continue;
}
that.complexHeaderMergedCells.push({
from: that.columnsArray[currentEntry.from[1]] + (currentEntry.from[0] + 1),
to: that.columnsArray[currentEntry.to[1]] + (currentEntry.to[0] + 1)
});
}
}
}
that.getConditionalFormatting();
if (!style) {
style = that.generateDefaultStyle(data);
}
const sharedStrings = that.generateSharedStrings(data),
sharedStringsCollection = sharedStrings.collection,
sharedStringsXML = sharedStrings.xml,
stylesXML = that.generateStyles(style),
sheet1XML = that.groupBy ? that.generateSheet1WithGrouping(data, sharedStringsCollection) :
that.generateSheet1(data, sharedStringsCollection),
auxiliaryFiles = that.generateAuxiliaryFiles(),
// eslint-disable-next-line
zip = new JSZip(),
_rels = zip.folder('_rels'),
docProps = zip.folder('docProps'),
xl = zip.folder('xl'),
xl_rels = xl.folder('_rels'),
theme = xl.folder('theme'),
worksheets = xl.folder('worksheets');
_rels.file('.rels', auxiliaryFiles._relsRels);
docProps.file('app.xml', auxiliaryFiles.docPropsAppXml);
docProps.file('core.xml', auxiliaryFiles.docPropsCoreXml);
xl_rels.file('workbook.xml.rels', auxiliaryFiles.xl_relsWorkbookXmlRels);
theme.file('theme1.xml', auxiliaryFiles.xlThemeTheme1Xml);
worksheets.file('sheet1.xml', sheet1XML);
xl.file('sharedStrings.xml', sharedStringsXML);
xl.file('styles.xml', stylesXML);
xl.file('workbook.xml', auxiliaryFiles.xlWorkbookXml);
zip.file('[Content_Types].xml', auxiliaryFiles.Content_TypesXml);
zip.generateAsync({
type: 'blob',
mimeType:
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
.then(function (content) {
return that.downloadFile(content, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', fileName);
});
delete that.conditionalFormattingXLSX;
delete that.complexHeaderMergeInfo;
delete that.defaultRowHeight;
delete that.rowHeight;
}
/**
* Processes grouping information.
*/
processGroupingInformation(data, xlsx) {
const that = this;
if (!that.groupBy) {
return data;
}
let header;
data = data.slice(0);
if (that.exportHeader) {
if (xlsx && that.complexHeader) {
header = data.slice(0, that.complexHeader.length);
data.splice(0, that.complexHeader.length);
}
else {
header = [data[0]];
data.splice(0, 1);
}
}
if (data.length > 1) {
const getCompareFunction = function (a, knownDataType) {
// gets data type of column (not necessary if the Grid provides this information)
const dataType = knownDataType || typeof a;
let compareFunction;
switch (dataType) {
case 'string':
compareFunction = new Intl.Collator().compare;
break;
case 'number':
compareFunction = function (a, b) {
return a - b;
};
break;
case 'boolean':
case 'bool':
compareFunction = function (a, b) {
if (a === b) {
return 0;
}
else if (a === false) {
return -1;
}
else {
return 1;
}
};
break;
case 'date':
case 'time':
case 'dateTime':
if (a instanceof Date) {
compareFunction = function (a, b) {
return a.compare(b);
};
}
break;
case 'object':
if (a instanceof Date) {
compareFunction = function (a, b) {
return a.getTime() - b.getTime();
};
}
break;
}
return compareFunction;
}
const sortByMultipleColumns = function (dataSource, sortColumns, directions, customSortingCallback) {
if (!dataSource || !(Array.isArray(dataSource)) || dataSource.length === 0 ||
!sortColumns || Array.isArray(sortColumns) && sortColumns.length === 0) {
return;
}
if (typeof sortColumns === 'string') {
sortColumns = [sortColumns];
}
const directionCoefficients = [],
compareFunctions = [];
if (directions === undefined) {
directions = [];
}
for (let i = 0; i < sortColumns.length; i++) {
if (directions[i] === undefined || directions[i] === 'asc' || directions[i] === 'ascending') {
directionCoefficients[i] = 1;
}
else {
directionCoefficients[i] = -1;
}
compareFunctions[i] = getCompareFunction(dataSource[0][sortColumns[i]]);
}
if (customSortingCallback) {
customSortingCallback(dataSource, sortColumns, directions, compareFunctions);
return;
}
dataSource.sort(function (a, b) {
for (let i = 0; i < sortColumns.length; i++) {
const result = compareFunctions[i](a[sortColumns[i]], b[sortColumns[i]]);
if (result === 0) {
if (sortColumns[i + 1]) {
continue;
}
else if (a._index !== undefined) {
// makes sorting stable
return (a._index - b._index) * directionCoefficients[i];
}
return 0;
}
return result * directionCoefficients[i];
}
});
}
sortByMultipleColumns(data, that.groupBy);
}
if (header) {
data = header.concat(data);
}
that.getGroupLabels(data);
return data;
}
/**
* Exports to XML.
*/
exportToXML(data, fileName) {
const datafields = this.datafields.slice(0);
let xmlContent = '<?xml version="1.0" encoding="UTF-8" ?>\n<table>\n';
if (datafields.indexOf('rows') === -1) {
datafields.push('rows');
}
function recursion(records, indent) {
let content = '';
for (let i = 0; i < records.length; i++) {
const currentRecord = records[i];
content += indent + '<row>\n';
for (let j = 0; j < datafields.length; j++) {
const datafield = datafields[j];
if (datafield === 'rows') {
if (!currentRecord.rows) {
continue;
}
content += `${indent} <rows>\n${recursion(currentRecord.rows, indent + ' ')}${indent} </rows>\n`;
continue;
}
content += indent + ` <${datafield}>${currentRecord[datafield]}</${datafield}>\n`;
}
content += indent + '</row>\n';
}
return content;
}
xmlContent += recursion(data, ' ') + '</table>';
return this.downloadFile(xmlContent, 'application/xml', fileName);
}
/**
* Formats a date.
*/
formatDate(value, format) {
var date = $.jqx.formatDate(value, format);
return date;
}
/**
* Formats a number.
*/
formatNumber(value, format) {
var number = $.jqx.formatNumber(value, format);
return number;
}
/**
* Generates auxiliary files necessary for XLSX.
*/
generateAuxiliaryFiles() {
// _rels\.rels
const _relsRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>`;
// docProps\app.xml
const docPropsAppXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><Application>Microsoft Excel</Application><DocSecurity>0</DocSecurity><ScaleCrop>false</ScaleCrop><HeadingPairs><vt:vector size="2" baseType="variant"><vt:variant><vt:lpstr>Worksheets</vt:lpstr></vt:variant><vt:variant><vt:i4>1</vt:i4></vt:variant></vt:vector></HeadingPairs><TitlesOfParts><vt:vector size="1" baseType="lpstr"><vt:lpstr>Sheet1</vt:lpstr></vt:vector></TitlesOfParts><Company></Company><LinksUpToDate>false</LinksUpToDate><SharedDoc>false</SharedDoc><HyperlinksChanged>false</HyperlinksChanged><AppVersion>16.0300</AppVersion></Properties>`;
// docProps\core.xml
const now = new Date().toISOString(),
docPr