forked from esvit/ng-table-export
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathng-table-export.src.js
137 lines (123 loc) · 5.12 KB
/
ng-table-export.src.js
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
angular.module('ngTableExport', [])
.config(['$compileProvider', function($compileProvider) {
// allow data links
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|data):/);
}])
.directive('exportCsv', ['$parse', '$timeout', 'ngTableEventsChannel', function ($parse, $timeout, ngTableEventsChannel) {
var delimiter = ',';
var header = 'data:text/csv;charset=UTF-8,';
return {
restrict: 'A',
scope: false,
/**
* scope is table scope, element is <table>
*/
link: function(scope, element, attrs) {
var data = '';
// allow pass in of delimiter via directive attrs
if (attrs.delimiter) { delimiter = attrs.delimiter; }
function stringify(str) {
return '"' +
str.replace(/^\s\s*/, '').replace(/\s*\s$/, '') // trim spaces
.replace(/"/g,'""') + // replace quotes with double quotes
'"';
}
/**
* Parse the table and build up data uri
*/
function parseTable() {
data = '';
var rows = element.find('tr');
angular.forEach(rows, function(row, i) {
var tr = angular.element(row),
tds = tr.find('th'),
rowData = '';
if (tr.hasClass('ng-table-filters')) {
return;
}
if (tds.length === 0) {
tds = tr.find('td');
}
if (i !== 1) {
angular.forEach(tds, function(td) {
// respect colspan in row data
rowData += stringify(angular.element(td).text()) + Array.apply(null, Array(td.colSpan)).map(function () { return delimiter; }).join('');
});
rowData = rowData.slice(0, rowData.length - 1); //remove last semicolon
}
data += rowData + '\n';
});
// add delimiter hint for excel so it opens without having to import
data = 'sep=' + delimiter + '\n' + data;
}
/**
* Dynamically generate a link and click it; works in chrome + firefox; unfortunately, safari
* does not support the `download` attribute, so it ends up opening the file in a new tab https://bugs.webkit.org/show_bug.cgi?id=102914
*/
function download(dataUri, filename, scope) {
// tested in chrome / firefox / safari
var link = document.createElement('a');
// chrome + firefox
link.style.display = 'none';
link.href = dataUri;
link.download = filename;
link.target = '_blank';
// needs to get wrapped to play nicely with angular $digest
// else may cause '$digest already in progress' errors with other angular controls (e.g. angular-ui dropdown)
$timeout(function () {
try {
// must append to body for firefox; chrome & safari don't mind
document.body.appendChild(link);
link.click();
// destroy
document.body.removeChild(link);
}
catch(err) {
if (scope.logError) {
scope.logError('NG Table Export Error saving file on client.');
}
throw(err);
}
}, 0, false);
}
var csv = {
/**
* Generate data URI from table data
*/
generate: function(event, filename, table) {
var isNgTable = attrs.ngTable,
table = table || scope.$parent.tableParams,
settings = table ? table.settings() : {},
cnt = table ? table.count() : {},
total = table ? settings.total : {};
// is pager on? if so, we have to disable it temporarily
if (isNgTable && cnt < total) {
var $off = ngTableEventsChannel.onAfterReloadData(function () {
// de-register callback so it won't continue firing
$off();
// give browser some time to re-render; FIXME - no good way to know when rendering is done?
$timeout(function () {
// generate data from table
parseTable();
// finally, restore original table cnt
table.count(cnt);
table.reload();
// dynamically trigger download
download(header + encodeURIComponent(data), filename, scope);
}, 1000, false);
});
// disable the pager and reload the table so we get all the data
table.count(Infinity);
table.reload();
} else {
// pager isn't on, just parse the table
parseTable();
download(header + encodeURIComponent(data), filename);
}
}
};
// attach csv to table scope
$parse(attrs.exportCsv).assign(scope.$parent, csv);
}
};
}]);