summaryrefslogtreecommitdiff
path: root/priv/static/js/metricsgraphics/charts/table.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--priv/static/js/metricsgraphics/charts/table.js220
1 files changed, 220 insertions, 0 deletions
diff --git a/priv/static/js/metricsgraphics/charts/table.js b/priv/static/js/metricsgraphics/charts/table.js
new file mode 100644
index 0000000..3081d8c
--- /dev/null
+++ b/priv/static/js/metricsgraphics/charts/table.js
@@ -0,0 +1,220 @@
+/*
+Data Tables
+
+Along with histograms, bars, lines, and scatters, a simple data table can take you far.
+We often just want to look at numbers, organized as a table, where columns are variables,
+and rows are data points. Sometimes we want a cell to have a small graphic as the main
+column element, in which case we want small multiples. sometimes we want to
+
+var table = New data_table(data)
+ .target('div#data-table')
+ .title({accessor: 'point_name', align: 'left'})
+ .description({accessor: 'description'})
+ .number({accessor: ''})
+
+*/
+
+MG.data_table = function(args) {
+ 'use strict';
+ this.args = args;
+ this.args.standard_col = { width: 150, font_size: 12, font_weight: 'normal' };
+ this.args.columns = [];
+ this.formatting_options = [
+ ['color', 'color'],
+ ['font-weight', 'font_weight'],
+ ['font-style', 'font_style'],
+ ['font-size', 'font_size']
+ ];
+
+ this._strip_punctuation = function(s) {
+ var punctuationless = s.replace(/[^a-zA-Z0-9 _]+/g, '');
+ var finalString = punctuationless.replace(/ +?/g, '');
+ return finalString;
+ };
+
+ this._format_element = function(element, value, args) {
+ this.formatting_options.forEach(function(fo) {
+ var attr = fo[0];
+ var key = fo[1];
+ if (args[key]) element.style(attr,
+ typeof args[key] === 'string' ||
+ typeof args[key] === 'number' ?
+ args[key] : args[key](value));
+ });
+ };
+
+ this._add_column = function(_args, arg_type) {
+ var standard_column = this.args.standard_col;
+ var args = merge_with_defaults(MG.clone(_args), MG.clone(standard_column));
+ args.type = arg_type;
+ this.args.columns.push(args);
+ };
+
+ this.target = function() {
+ var target = arguments[0];
+ this.args.target = target;
+ return this;
+ };
+
+ this.title = function() {
+ this._add_column(arguments[0], 'title');
+ return this;
+ };
+
+ this.text = function() {
+ this._add_column(arguments[0], 'text');
+ return this;
+ };
+
+ this.bullet = function() {
+ /*
+ text label
+ main value
+ comparative measure
+ any number of ranges
+
+ additional args:
+ no title
+ xmin, xmax
+ format: percentage
+ xax_formatter
+ */
+ return this;
+ };
+
+ this.sparkline = function() {
+ return this;
+ };
+
+ this.number = function() {
+ this._add_column(arguments[0], 'number');
+ return this;
+ };
+
+ this.display = function() {
+ var args = this.args;
+
+ chart_title(args);
+
+ var target = args.target;
+ var table = d3.select(target).append('table').classed('mg-data-table', true);
+ var colgroup = table.append('colgroup');
+ var thead = table.append('thead');
+ var tbody = table.append('tbody');
+ var this_column;
+ var this_title;
+
+ var tr, th, td_accessor, td_type, td_value, th_text, td_text, td;
+ var col;
+ var h;
+
+ tr = thead.append('tr');
+
+ for (h = 0; h < args.columns.length; h++) {
+ var this_col = args.columns[h];
+ td_type = this_col.type;
+ th_text = this_col.label;
+ th_text = th_text === undefined ? '' : th_text;
+ th = tr.append('th')
+ .style('width', this_col.width)
+ .style('text-align', td_type === 'title' ? 'left' : 'right')
+ .text(th_text);
+
+ if (args.show_tooltips && this_col.description && mg_jquery_exists()) {
+ th.append('i')
+ .classed('fa', true)
+ .classed('fa-question-circle', true)
+ .classed('fa-inverse', true);
+
+ $(th.node()).popover({
+ html: true,
+ animation: false,
+ content: this_col.description,
+ trigger: 'hover',
+ placement: 'top',
+ container: $(th.node())
+ });
+ }
+ }
+
+ for (h = 0; h < args.columns.length; h++) {
+ col = colgroup.append('col');
+ if (args.columns[h].type === 'number') {
+ col.attr('align', 'char').attr('char', '.');
+ }
+ }
+
+ for (var i = 0; i < args.data.length; i++) {
+ tr = tbody.append('tr');
+ for (var j = 0; j < args.columns.length; j++) {
+ this_column = args.columns[j];
+ td_accessor = this_column.accessor;
+ td_value = td_text = args.data[i][td_accessor];
+ td_type = this_column.type;
+
+ if (td_type === 'number') {
+ //td_text may need to be rounded
+ if (this_column.hasOwnProperty('round') && !this_column.hasOwnProperty('format')) {
+ // round according to the number value in this_column.round
+ td_text = d3.format('0,.' + this_column.round + 'f')(td_text);
+ }
+
+ if (this_column.hasOwnProperty('value_formatter')) {
+ // provide a function that formats the text according to the function this_column.format.
+ td_text = this_column.value_formatter(td_text);
+ }
+
+ if (this_column.hasOwnProperty('format')) {
+ // this is a shorthand for percentage formatting, and others if need be.
+ // supported: 'percentage', 'count', 'temperature'
+
+ if (this_column.round) {
+ td_text = Math.round(td_text, this_column.round);
+ }
+
+ var this_format = this_column.format;
+ var formatter;
+
+ if (this_format === 'percentage') formatter = d3.format('.0%');
+ if (this_format === 'count') formatter = d3.format(',.0f');
+ if (this_format === 'temperature') formatter = function(t) {
+ return t + '°'; };
+
+ td_text = formatter(td_text);
+ }
+
+ if (this_column.hasOwnProperty('currency')) {
+ // this is another shorthand for formatting according to a currency amount, which gets appended to front of number
+ td_text = this_column.currency + td_text;
+ }
+ }
+
+ td = tr.append('td')
+ .classed('table-' + td_type, true)
+ .classed('table-' + td_type + '-' + this._strip_punctuation(td_accessor), true)
+ .attr('data-value', td_value)
+ .style('width', this_column.width)
+ .style('text-align', td_type === 'title' || td_type === 'text' ? 'left' : 'right');
+
+ this._format_element(td, td_value, this_column);
+
+ if (td_type === 'title') {
+ this_title = td.append('div').text(td_text);
+ this._format_element(this_title, td_text, this_column);
+
+ if (args.columns[j].hasOwnProperty('secondary_accessor')) {
+ td.append('div')
+ .text(args.data[i][args.columns[j].secondary_accessor])
+ .classed("secondary-title", true);
+ }
+ } else {
+ td.text(td_text);
+ }
+ }
+ }
+
+ return this;
+ };
+
+ return this;
+};