git_stats 1.0.14 → 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +9 -0
- data/README.md +8 -1
- data/config/locales/bg +63 -0
- data/config/locales/en.yml +3 -1
- data/config/locales/es.yml +63 -0
- data/config/locales/tr.yml +63 -0
- data/config/locales/zh.yml +66 -0
- data/config/locales/zh_tw.yml +65 -0
- data/config/locales/zh_tw_default.yml +76 -0
- data/lib/git_stats/git_data/commit.rb +1 -1
- data/lib/git_stats/git_data/repo.rb +50 -3
- data/lib/git_stats/git_data/short_stat.rb +1 -1
- data/lib/git_stats/stats_view/charts/charts.rb +1 -1
- data/lib/git_stats/stats_view/charts/repo_charts.rb +20 -0
- data/lib/git_stats/version.rb +1 -1
- data/spec/git_data/short_stat_spec.rb +1 -1
- data/templates/assets/export-csv.js +392 -0
- data/templates/assets/exporting.js +27 -0
- data/templates/assets/highstock.js +507 -300
- data/templates/files/_files.haml +4 -0
- data/templates/files/by_extension_by_date.haml +1 -0
- data/templates/layout.haml +2 -0
- data/templates/lines/_lines.haml +4 -0
- data/templates/lines/by_extension_by_date.haml +1 -0
- metadata +15 -3
@@ -41,7 +41,7 @@ module GitStats
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def lines_count
|
44
|
-
@lines_count ||= repo.run("git diff --shortstat `git hash-object -t tree /dev/null` #{self.sha} -- #{repo.tree_path}").lines.map do |line|
|
44
|
+
@lines_count ||= repo.run("git diff --shortstat --no-renames `git hash-object -t tree /dev/null` #{self.sha} -- #{repo.tree_path}").lines.map do |line|
|
45
45
|
line[/(\d+) insertions?/, 1].to_i
|
46
46
|
end.sum
|
47
47
|
end
|
@@ -39,6 +39,10 @@ module GitStats
|
|
39
39
|
@tree ||= Tree.new(repo: self, relative_path: @tree_path)
|
40
40
|
end
|
41
41
|
|
42
|
+
def command_memoization
|
43
|
+
@command_memoization_map ||= {}
|
44
|
+
end
|
45
|
+
|
42
46
|
def authors
|
43
47
|
@authors ||= run_and_parse("git shortlog -se #{commit_range} #{tree_path}").map do |author|
|
44
48
|
Author.new(repo: self, name: author[:name], email: author[:email])
|
@@ -95,6 +99,44 @@ module GitStats
|
|
95
99
|
}].fill_empty_days!(aggregated: true)
|
96
100
|
end
|
97
101
|
|
102
|
+
def files_by_extension_by_date
|
103
|
+
file_counts_by_date_by_extension = {}
|
104
|
+
extensions_sums = {}
|
105
|
+
commits.map do |commit|
|
106
|
+
commit.files_by_extension_count.map do |ext, count|
|
107
|
+
extensions_sums[ext] ||= 0;
|
108
|
+
extensions_sums[ext] = count;
|
109
|
+
file_counts_by_date_by_extension[ext] ||= {};
|
110
|
+
file_counts_by_date_by_extension[ext][commit.date.to_date] = extensions_sums[ext]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
@multi_data_file_counts_by_date ||= file_counts_by_date_by_extension.map { |ext, data|
|
114
|
+
{
|
115
|
+
name: ext || "NO EXTENSION",
|
116
|
+
data: data.fill_empty_days!(aggregated:true)
|
117
|
+
}
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
def lines_by_extension_by_date
|
122
|
+
lines_by_date_by_extension = {}
|
123
|
+
extensions_sums = {}
|
124
|
+
commits.map do |commit|
|
125
|
+
commit.lines_by_extension.map do |ext, count|
|
126
|
+
extensions_sums[ext] ||= 0;
|
127
|
+
extensions_sums[ext] = count;
|
128
|
+
lines_by_date_by_extension[ext] ||= {};
|
129
|
+
lines_by_date_by_extension[ext][commit.date.to_date] = extensions_sums[ext]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
@multi_data_lines_by_date ||= lines_by_date_by_extension.map { |ext, data|
|
133
|
+
{
|
134
|
+
name: ext || "NO EXTENSION",
|
135
|
+
data: data.fill_empty_days!(aggregated:true)
|
136
|
+
}
|
137
|
+
}
|
138
|
+
end
|
139
|
+
|
98
140
|
def last_commit
|
99
141
|
commits.last
|
100
142
|
end
|
@@ -124,9 +166,14 @@ module GitStats
|
|
124
166
|
end
|
125
167
|
|
126
168
|
def run(command)
|
127
|
-
|
128
|
-
|
129
|
-
|
169
|
+
if (command_memoization[command])
|
170
|
+
command_memoization[command]
|
171
|
+
else
|
172
|
+
result = command_runner.run(path, command)
|
173
|
+
invoke_command_observers(command, result)
|
174
|
+
command_memoization[command] = result
|
175
|
+
result
|
176
|
+
end
|
130
177
|
end
|
131
178
|
|
132
179
|
def run_and_parse(command)
|
@@ -19,7 +19,7 @@ module GitStats
|
|
19
19
|
|
20
20
|
private
|
21
21
|
def calculate_stat
|
22
|
-
stat_line = commit.repo.run("git show --shortstat --oneline #{commit.sha} -- #{commit.repo.tree_path}").lines.to_a[1]
|
22
|
+
stat_line = commit.repo.run("git show --shortstat --oneline --no-renames #{commit.sha} -- #{commit.repo.tree_path}").lines.to_a[1]
|
23
23
|
if stat_line.blank?
|
24
24
|
@files_changed = @insertions = @deletions = 0
|
25
25
|
else
|
@@ -3,7 +3,7 @@ module GitStats
|
|
3
3
|
module StatsView
|
4
4
|
module Charts
|
5
5
|
class All
|
6
|
-
delegate :files_by_extension, :lines_by_extension, :files_by_date, :lines_by_date, :comments_by_date, to: :repo_charts
|
6
|
+
delegate :files_by_extension, :files_by_extension_by_date, :lines_by_extension, :lines_by_extension_by_date, :files_by_date, :lines_by_date, :comments_by_date, to: :repo_charts
|
7
7
|
|
8
8
|
delegate :commits_sum_by_author_by_date, :changed_lines_by_author_by_date,
|
9
9
|
:insertions_by_author_by_date, :deletions_by_author_by_date, to: :authors_charts
|
@@ -27,6 +27,26 @@ module GitStats
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def files_by_extension_by_date
|
31
|
+
Chart.new do |f|
|
32
|
+
f.multi_date_chart(
|
33
|
+
data: @repo.files_by_extension_by_date,
|
34
|
+
title: :files_by_extension_by_date.t,
|
35
|
+
y_text: :files.t
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def lines_by_extension_by_date
|
41
|
+
Chart.new do |f|
|
42
|
+
f.multi_date_chart(
|
43
|
+
data: @repo.lines_by_extension_by_date,
|
44
|
+
title: :lines_by_extension_by_date.t,
|
45
|
+
y_text: :files.t
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
30
50
|
def files_by_date
|
31
51
|
Chart.new do |f|
|
32
52
|
f.date_chart(
|
data/lib/git_stats/version.rb
CHANGED
@@ -14,7 +14,7 @@ describe GitStats::GitData::ShortStat do
|
|
14
14
|
{content: '', expect: [0, 0, 0]},
|
15
15
|
].each do |test|
|
16
16
|
it "#{test[:content]} parsing" do
|
17
|
-
commit.repo.should_receive(:run).with("git show --shortstat --oneline abc -- .").and_return("abc some commit\n#{test[:content]}")
|
17
|
+
commit.repo.should_receive(:run).with("git show --shortstat --oneline --no-renames abc -- .").and_return("abc some commit\n#{test[:content]}")
|
18
18
|
|
19
19
|
|
20
20
|
commit.short_stat.should be_a(GitStats::GitData::ShortStat)
|
@@ -0,0 +1,392 @@
|
|
1
|
+
/**
|
2
|
+
* A Highcharts plugin for exporting data from a rendered chart as CSV, XLS or HTML table
|
3
|
+
*
|
4
|
+
* Author: Torstein Honsi
|
5
|
+
* Licence: MIT
|
6
|
+
* Version: 1.4.7
|
7
|
+
*/
|
8
|
+
/*global Highcharts, window, document, Blob */
|
9
|
+
(function (factory) {
|
10
|
+
if (typeof module === 'object' && module.exports) {
|
11
|
+
module.exports = factory;
|
12
|
+
} else {
|
13
|
+
factory(Highcharts);
|
14
|
+
}
|
15
|
+
})(function (Highcharts) {
|
16
|
+
|
17
|
+
'use strict';
|
18
|
+
|
19
|
+
var each = Highcharts.each,
|
20
|
+
pick = Highcharts.pick,
|
21
|
+
seriesTypes = Highcharts.seriesTypes,
|
22
|
+
downloadAttrSupported = document.createElement('a').download !== undefined;
|
23
|
+
|
24
|
+
Highcharts.setOptions({
|
25
|
+
lang: {
|
26
|
+
downloadCSV: 'Download CSV',
|
27
|
+
downloadXLS: 'Download XLS',
|
28
|
+
viewData: 'View data table'
|
29
|
+
}
|
30
|
+
});
|
31
|
+
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Get the data rows as a two dimensional array
|
35
|
+
*/
|
36
|
+
Highcharts.Chart.prototype.getDataRows = function () {
|
37
|
+
var options = (this.options.exporting || {}).csv || {},
|
38
|
+
xAxis,
|
39
|
+
xAxes = this.xAxis,
|
40
|
+
rows = {},
|
41
|
+
rowArr = [],
|
42
|
+
dataRows,
|
43
|
+
names = [],
|
44
|
+
i,
|
45
|
+
x,
|
46
|
+
xTitle,
|
47
|
+
// Options
|
48
|
+
dateFormat = options.dateFormat || '%Y-%m-%d %H:%M:%S',
|
49
|
+
columnHeaderFormatter = options.columnHeaderFormatter || function (item, key, keyLength) {
|
50
|
+
if (item instanceof Highcharts.Axis) {
|
51
|
+
return (item.options.title && item.options.title.text) ||
|
52
|
+
(item.isDatetimeAxis ? 'DateTime' : 'Category');
|
53
|
+
}
|
54
|
+
return item ?
|
55
|
+
item.name + (keyLength > 1 ? ' ('+ key + ')' : '') :
|
56
|
+
'Category';
|
57
|
+
},
|
58
|
+
xAxisIndices = [];
|
59
|
+
|
60
|
+
// Loop the series and index values
|
61
|
+
i = 0;
|
62
|
+
each(this.series, function (series) {
|
63
|
+
var keys = series.options.keys,
|
64
|
+
pointArrayMap = keys || series.pointArrayMap || ['y'],
|
65
|
+
valueCount = pointArrayMap.length,
|
66
|
+
requireSorting = series.requireSorting,
|
67
|
+
categoryMap = {},
|
68
|
+
xAxisIndex = Highcharts.inArray(series.xAxis, xAxes),
|
69
|
+
j;
|
70
|
+
|
71
|
+
// Map the categories for value axes
|
72
|
+
each(pointArrayMap, function (prop) {
|
73
|
+
categoryMap[prop] = (series[prop + 'Axis'] && series[prop + 'Axis'].categories) || [];
|
74
|
+
});
|
75
|
+
|
76
|
+
if (series.options.includeInCSVExport !== false && series.visible !== false) { // #55
|
77
|
+
|
78
|
+
// Build a lookup for X axis index and the position of the first
|
79
|
+
// series that belongs to that X axis. Includes -1 for non-axis
|
80
|
+
// series types like pies.
|
81
|
+
if (!Highcharts.find(xAxisIndices, function (index) {
|
82
|
+
return index[0] === xAxisIndex;
|
83
|
+
})) {
|
84
|
+
xAxisIndices.push([xAxisIndex, i]);
|
85
|
+
}
|
86
|
+
|
87
|
+
// Add the column headers, usually the same as series names
|
88
|
+
j = 0;
|
89
|
+
while (j < valueCount) {
|
90
|
+
names.push(columnHeaderFormatter(series, pointArrayMap[j], pointArrayMap.length));
|
91
|
+
j = j + 1;
|
92
|
+
}
|
93
|
+
|
94
|
+
each(series.points, function (point, pIdx) {
|
95
|
+
var key = requireSorting ? point.x : pIdx,
|
96
|
+
prop,
|
97
|
+
val;
|
98
|
+
|
99
|
+
j = 0;
|
100
|
+
|
101
|
+
if (!rows[key]) {
|
102
|
+
// Generate the row
|
103
|
+
rows[key] = [];
|
104
|
+
// Contain the X values from one or more X axes
|
105
|
+
rows[key].xValues = [];
|
106
|
+
}
|
107
|
+
rows[key].x = point.x;
|
108
|
+
rows[key].xValues[xAxisIndex] = point.x;
|
109
|
+
|
110
|
+
// Pies, funnels, geo maps etc. use point name in X row
|
111
|
+
if (!series.xAxis || series.exportKey === 'name') {
|
112
|
+
rows[key].name = point.name;
|
113
|
+
}
|
114
|
+
|
115
|
+
while (j < valueCount) {
|
116
|
+
prop = pointArrayMap[j]; // y, z etc
|
117
|
+
val = point[prop];
|
118
|
+
rows[key][i + j] = pick(categoryMap[prop][val], val); // Pick a Y axis category if present
|
119
|
+
j = j + 1;
|
120
|
+
}
|
121
|
+
|
122
|
+
});
|
123
|
+
i = i + j;
|
124
|
+
}
|
125
|
+
});
|
126
|
+
|
127
|
+
// Make a sortable array
|
128
|
+
for (x in rows) {
|
129
|
+
if (rows.hasOwnProperty(x)) {
|
130
|
+
rowArr.push(rows[x]);
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
var binding, xAxisIndex, column;
|
135
|
+
dataRows = [names];
|
136
|
+
|
137
|
+
i = xAxisIndices.length;
|
138
|
+
while (i--) { // Start from end to splice in
|
139
|
+
xAxisIndex = xAxisIndices[i][0];
|
140
|
+
column = xAxisIndices[i][1];
|
141
|
+
xAxis = xAxes[xAxisIndex];
|
142
|
+
|
143
|
+
// Sort it by X values
|
144
|
+
rowArr.sort(function (a, b) {
|
145
|
+
return a.xValues[xAxisIndex] - b.xValues[xAxisIndex];
|
146
|
+
});
|
147
|
+
|
148
|
+
// Add header row
|
149
|
+
xTitle = columnHeaderFormatter(xAxis);
|
150
|
+
//dataRows = [[xTitle].concat(names)];
|
151
|
+
dataRows[0].splice(column, 0, xTitle);
|
152
|
+
|
153
|
+
// Add the category column
|
154
|
+
each(rowArr, function (row) {
|
155
|
+
|
156
|
+
var category = row.name;
|
157
|
+
if (!category) {
|
158
|
+
if (xAxis.isDatetimeAxis) {
|
159
|
+
if (row.x instanceof Date) {
|
160
|
+
row.x = row.x.getTime();
|
161
|
+
}
|
162
|
+
category = Highcharts.dateFormat(dateFormat, row.x);
|
163
|
+
} else if (xAxis.categories) {
|
164
|
+
category = pick(
|
165
|
+
xAxis.names[row.x],
|
166
|
+
xAxis.categories[row.x],
|
167
|
+
row.x
|
168
|
+
)
|
169
|
+
} else {
|
170
|
+
category = row.x;
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
// Add the X/date/category
|
175
|
+
row.splice(column, 0, category);
|
176
|
+
});
|
177
|
+
}
|
178
|
+
dataRows = dataRows.concat(rowArr);
|
179
|
+
|
180
|
+
return dataRows;
|
181
|
+
};
|
182
|
+
|
183
|
+
/**
|
184
|
+
* Get a CSV string
|
185
|
+
*/
|
186
|
+
Highcharts.Chart.prototype.getCSV = function (useLocalDecimalPoint) {
|
187
|
+
var csv = '',
|
188
|
+
rows = this.getDataRows(),
|
189
|
+
options = (this.options.exporting || {}).csv || {},
|
190
|
+
itemDelimiter = options.itemDelimiter || ',', // use ';' for direct import to Excel
|
191
|
+
lineDelimiter = options.lineDelimiter || '\n'; // '\n' isn't working with the js csv data extraction
|
192
|
+
|
193
|
+
// Transform the rows to CSV
|
194
|
+
each(rows, function (row, i) {
|
195
|
+
var val = '',
|
196
|
+
j = row.length,
|
197
|
+
n = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.';
|
198
|
+
while (j--) {
|
199
|
+
val = row[j];
|
200
|
+
if (typeof val === "string") {
|
201
|
+
val = '"' + val + '"';
|
202
|
+
}
|
203
|
+
if (typeof val === 'number') {
|
204
|
+
if (n === ',') {
|
205
|
+
val = val.toString().replace(".", ",");
|
206
|
+
}
|
207
|
+
}
|
208
|
+
row[j] = val;
|
209
|
+
}
|
210
|
+
// Add the values
|
211
|
+
csv += row.join(itemDelimiter);
|
212
|
+
|
213
|
+
// Add the line delimiter
|
214
|
+
if (i < rows.length - 1) {
|
215
|
+
csv += lineDelimiter;
|
216
|
+
}
|
217
|
+
});
|
218
|
+
return csv;
|
219
|
+
};
|
220
|
+
|
221
|
+
/**
|
222
|
+
* Build a HTML table with the data
|
223
|
+
*/
|
224
|
+
Highcharts.Chart.prototype.getTable = function (useLocalDecimalPoint) {
|
225
|
+
var html = '<table><thead>',
|
226
|
+
rows = this.getDataRows();
|
227
|
+
|
228
|
+
// Transform the rows to HTML
|
229
|
+
each(rows, function (row, i) {
|
230
|
+
var tag = i ? 'td' : 'th',
|
231
|
+
val,
|
232
|
+
j,
|
233
|
+
n = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.';
|
234
|
+
|
235
|
+
html += '<tr>';
|
236
|
+
for (j = 0; j < row.length; j = j + 1) {
|
237
|
+
val = row[j];
|
238
|
+
// Add the cell
|
239
|
+
if (typeof val === 'number') {
|
240
|
+
val = val.toString();
|
241
|
+
if (n === ',') {
|
242
|
+
val = val.replace('.', n);
|
243
|
+
}
|
244
|
+
html += '<' + tag + ' class="number">' + val + '</' + tag + '>';
|
245
|
+
|
246
|
+
} else {
|
247
|
+
html += '<' + tag + '>' + (val === undefined ? '' : val) + '</' + tag + '>';
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
251
|
+
html += '</tr>';
|
252
|
+
|
253
|
+
// After the first row, end head and start body
|
254
|
+
if (!i) {
|
255
|
+
html += '</thead><tbody>';
|
256
|
+
}
|
257
|
+
|
258
|
+
});
|
259
|
+
html += '</tbody></table>';
|
260
|
+
|
261
|
+
return html;
|
262
|
+
};
|
263
|
+
|
264
|
+
function getContent(chart, href, extension, content, MIME) {
|
265
|
+
var a,
|
266
|
+
blobObject,
|
267
|
+
name,
|
268
|
+
options = (chart.options.exporting || {}).csv || {},
|
269
|
+
url = options.url || 'http://www.highcharts.com/studies/csv-export/download.php';
|
270
|
+
|
271
|
+
if (chart.options.exporting.filename) {
|
272
|
+
name = chart.options.exporting.filename;
|
273
|
+
} else if (chart.title) {
|
274
|
+
name = chart.title.textStr.replace(/ /g, '-').toLowerCase();
|
275
|
+
} else {
|
276
|
+
name = 'chart';
|
277
|
+
}
|
278
|
+
|
279
|
+
// MS specific. Check this first because of bug with Edge (#76)
|
280
|
+
if (window.Blob && window.navigator.msSaveOrOpenBlob) {
|
281
|
+
// Falls to msSaveOrOpenBlob if download attribute is not supported
|
282
|
+
blobObject = new Blob([content]);
|
283
|
+
window.navigator.msSaveOrOpenBlob(blobObject, name + '.' + extension);
|
284
|
+
|
285
|
+
// Download attribute supported
|
286
|
+
} else if (downloadAttrSupported) {
|
287
|
+
a = document.createElement('a');
|
288
|
+
a.href = href;
|
289
|
+
a.target = '_blank';
|
290
|
+
a.download = name + '.' + extension;
|
291
|
+
chart.container.append(a); // #111
|
292
|
+
a.click();
|
293
|
+
a.remove();
|
294
|
+
|
295
|
+
} else {
|
296
|
+
// Fall back to server side handling
|
297
|
+
Highcharts.post(url, {
|
298
|
+
data: content,
|
299
|
+
type: MIME,
|
300
|
+
extension: extension
|
301
|
+
});
|
302
|
+
}
|
303
|
+
}
|
304
|
+
|
305
|
+
/**
|
306
|
+
* Call this on click of 'Download CSV' button
|
307
|
+
*/
|
308
|
+
Highcharts.Chart.prototype.downloadCSV = function () {
|
309
|
+
var csv = this.getCSV(true);
|
310
|
+
getContent(
|
311
|
+
this,
|
312
|
+
'data:text/csv,\uFEFF' + encodeURIComponent(csv),
|
313
|
+
'csv',
|
314
|
+
csv,
|
315
|
+
'text/csv'
|
316
|
+
);
|
317
|
+
};
|
318
|
+
|
319
|
+
/**
|
320
|
+
* Call this on click of 'Download XLS' button
|
321
|
+
*/
|
322
|
+
Highcharts.Chart.prototype.downloadXLS = function () {
|
323
|
+
var uri = 'data:application/vnd.ms-excel;base64,',
|
324
|
+
template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">' +
|
325
|
+
'<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>' +
|
326
|
+
'<x:Name>Ark1</x:Name>' +
|
327
|
+
'<x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->' +
|
328
|
+
'<style>td{border:none;font-family: Calibri, sans-serif;} .number{mso-number-format:"0.00";}</style>' +
|
329
|
+
'<meta name=ProgId content=Excel.Sheet>' +
|
330
|
+
'<meta charset=UTF-8>' +
|
331
|
+
'</head><body>' +
|
332
|
+
this.getTable(true) +
|
333
|
+
'</body></html>',
|
334
|
+
base64 = function (s) {
|
335
|
+
return window.btoa(unescape(encodeURIComponent(s))); // #50
|
336
|
+
};
|
337
|
+
getContent(
|
338
|
+
this,
|
339
|
+
uri + base64(template),
|
340
|
+
'xls',
|
341
|
+
template,
|
342
|
+
'application/vnd.ms-excel'
|
343
|
+
);
|
344
|
+
};
|
345
|
+
|
346
|
+
/**
|
347
|
+
* View the data in a table below the chart
|
348
|
+
*/
|
349
|
+
Highcharts.Chart.prototype.viewData = function () {
|
350
|
+
if (!this.dataTableDiv) {
|
351
|
+
this.dataTableDiv = document.createElement('div');
|
352
|
+
this.dataTableDiv.className = 'highcharts-data-table';
|
353
|
+
|
354
|
+
// Insert after the chart container
|
355
|
+
this.renderTo.parentNode.insertBefore(
|
356
|
+
this.dataTableDiv,
|
357
|
+
this.renderTo.nextSibling
|
358
|
+
);
|
359
|
+
}
|
360
|
+
|
361
|
+
this.dataTableDiv.innerHTML = this.getTable();
|
362
|
+
};
|
363
|
+
|
364
|
+
|
365
|
+
// Add "Download CSV" to the exporting menu. Use download attribute if supported, else
|
366
|
+
// run a simple PHP script that returns a file. The source code for the PHP script can be viewed at
|
367
|
+
// https://raw.github.com/highslide-software/highcharts.com/master/studies/csv-export/csv.php
|
368
|
+
if (Highcharts.getOptions().exporting) {
|
369
|
+
Highcharts.getOptions().exporting.buttons.contextButton.menuItems.push({
|
370
|
+
textKey: 'downloadCSV',
|
371
|
+
onclick: function () { this.downloadCSV(); }
|
372
|
+
}, {
|
373
|
+
textKey: 'downloadXLS',
|
374
|
+
onclick: function () { this.downloadXLS(); }
|
375
|
+
}, {
|
376
|
+
textKey: 'viewData',
|
377
|
+
onclick: function () { this.viewData(); }
|
378
|
+
});
|
379
|
+
}
|
380
|
+
|
381
|
+
// Series specific
|
382
|
+
if (seriesTypes.map) {
|
383
|
+
seriesTypes.map.prototype.exportKey = 'name';
|
384
|
+
}
|
385
|
+
if (seriesTypes.mapbubble) {
|
386
|
+
seriesTypes.mapbubble.prototype.exportKey = 'name';
|
387
|
+
}
|
388
|
+
if (seriesTypes.treemap) {
|
389
|
+
seriesTypes.treemap.prototype.exportKey = 'name';
|
390
|
+
}
|
391
|
+
|
392
|
+
});
|